Pull request 2021: upd golibs

Merge in DNS/adguard-home from upd-golibs to master

Squashed commit of the following:

commit 266b002c5450329761dee21d918c80d08e5d8ab9
Merge: 99eb7745d e305bd8e4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Oct 5 14:21:51 2023 +0300

    Merge branch 'master' into upd-golibs

commit 99eb7745d0bee190399f9b16cb7151f34a591b54
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Oct 5 14:14:28 2023 +0300

    home: imp alignment

commit 556cde56720ce449aec17b500825681fc8c084bf
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Oct 5 13:35:35 2023 +0300

    dnsforward: imp naming, docs

commit 1ee99655a3318263db1edbcb9e4eeb33bfe441c8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Oct 5 13:28:39 2023 +0300

    home: make ports uint16

commit b228032ea1f5902ab9bac7b5d55d84aaf6354616
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Oct 4 18:56:59 2023 +0300

    all: rm system resolvers

commit 4b5becbed5890db80612e53861f000aaf4c869ff
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Oct 4 17:30:16 2023 +0300

    all: upd golibs
This commit is contained in:
Eugene Burkov 2023-10-05 15:26:19 +03:00
parent e305bd8e40
commit 5f61b550fa
23 changed files with 146 additions and 640 deletions

14
go.mod
View File

@ -3,8 +3,8 @@ module github.com/AdguardTeam/AdGuardHome
go 1.20 go 1.20
require ( require (
github.com/AdguardTeam/dnsproxy v0.54.0 github.com/AdguardTeam/dnsproxy v0.56.0
github.com/AdguardTeam/golibs v0.15.0 github.com/AdguardTeam/golibs v0.17.0
github.com/AdguardTeam/urlfilter v0.17.0 github.com/AdguardTeam/urlfilter v0.17.0
github.com/NYTimes/gziphandler v1.1.1 github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.2.7 github.com/ameshkov/dnscrypt/v2 v2.2.7
@ -26,8 +26,8 @@ require (
// TODO(a.garipov): This package is deprecated; find a new one or use our // TODO(a.garipov): This package is deprecated; find a new one or use our
// own code for that. Perhaps, use gopacket. // own code for that. Perhaps, use gopacket.
github.com/mdlayher/raw v0.1.0 github.com/mdlayher/raw v0.1.0
github.com/miekg/dns v1.1.55 github.com/miekg/dns v1.1.56
github.com/quic-go/quic-go v0.38.1 github.com/quic-go/quic-go v0.39.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/ti-mo/netfilter v0.5.0 github.com/ti-mo/netfilter v0.5.0
go.etcd.io/bbolt v1.3.7 go.etcd.io/bbolt v1.3.7
@ -47,10 +47,9 @@ require (
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // indirect
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb // indirect
github.com/mdlayher/socket v0.5.0 // indirect github.com/mdlayher/socket v0.5.0 // indirect
github.com/onsi/ginkgo/v2 v2.12.0 // indirect github.com/onsi/ginkgo/v2 v2.12.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
@ -58,6 +57,7 @@ require (
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/mod v0.12.0 // indirect golang.org/x/mod v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect

37
go.sum
View File

@ -1,7 +1,7 @@
github.com/AdguardTeam/dnsproxy v0.54.0 h1:OgSitM/EKrMMOi+guWZNwaU1cqRqJKWgR3l3fPWWayI= github.com/AdguardTeam/dnsproxy v0.56.0 h1:kAg88woRTWTgqVEB2i2Uhze8Lv0JF1zTIAGhe0prjKM=
github.com/AdguardTeam/dnsproxy v0.54.0/go.mod h1:tG/treaQekcKnugYoKOfm8vt3JGi6CliWta0MkQr15U= github.com/AdguardTeam/dnsproxy v0.56.0/go.mod h1:fqmehcE3cHFNqKbWQpIjGk7GqBy7ur1v5At499lFjRc=
github.com/AdguardTeam/golibs v0.15.0 h1:yOv/fdVkJIOWKr0NlUXAE9RA0DK9GKiBbiGzq47vY7o= github.com/AdguardTeam/golibs v0.17.0 h1:oPp2+2kV41qH45AIFbAlHFTPQOQ6JbF+JemjeECFn1g=
github.com/AdguardTeam/golibs v0.15.0/go.mod h1:66ZLs8P7nk/3IfKroQ1rqtieLk+5eXYXMBKXlVL7KeI= github.com/AdguardTeam/golibs v0.17.0/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
github.com/AdguardTeam/urlfilter v0.17.0 h1:tUzhtR9wMx704GIP3cibsDQJrixlMHfwoQbYJfPdFow= github.com/AdguardTeam/urlfilter v0.17.0 h1:tUzhtR9wMx704GIP3cibsDQJrixlMHfwoQbYJfPdFow=
github.com/AdguardTeam/urlfilter v0.17.0/go.mod h1:bbuZjPUzm/Ip+nz5qPPbwIP+9rZyQbQad8Lt/0fCulU= github.com/AdguardTeam/urlfilter v0.17.0/go.mod h1:bbuZjPUzm/Ip+nz5qPPbwIP+9rZyQbQad8Lt/0fCulU=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
@ -33,8 +33,6 @@ github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -43,8 +41,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb h1:LCMfzVg3sflxTs4UvuP4D8CkoZnfHLe2qzqgDn/4OHs= github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ=
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -75,11 +73,11 @@ github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI= github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI=
github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI= github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA=
github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
@ -96,8 +94,8 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So=
github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4= github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -113,10 +111,11 @@ github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+Kd
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
@ -125,7 +124,6 @@ golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjs
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -134,7 +132,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -148,8 +145,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -163,15 +158,11 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=

View File

@ -12,12 +12,12 @@ import (
// listenPacketReusable announces on the local network address additionally // listenPacketReusable announces on the local network address additionally
// configuring the socket to have a reusable binding. // configuring the socket to have a reusable binding.
func listenPacketReusable(ifaceName, network, address string) (c net.PacketConn, err error) { func listenPacketReusable(ifaceName, network, address string) (c net.PacketConn, err error) {
var port int var port uint16
_, port, err = netutil.SplitHostPort(address) _, port, err = netutil.SplitHostPort(address)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO(e.burkov): Inspect nclient4.NewRawUDPConn and implement here. // TODO(e.burkov): Inspect nclient4.NewRawUDPConn and implement here.
return nclient4.NewRawUDPConn(ifaceName, port) return nclient4.NewRawUDPConn(ifaceName, int(port))
} }

View File

@ -2,6 +2,7 @@ package aghnet_test
import ( import (
"io/fs" "io/fs"
"net"
"net/netip" "net/netip"
"net/url" "net/url"
"os" "os"
@ -64,7 +65,7 @@ ParseAddr("256.256.256.256"): IPv4 field has value >255`,
want: netip.AddrPort{}, want: netip.AddrPort{},
}, { }, {
name: "error_invalid_port", name: "error_invalid_port",
input: netutil.JoinHostPort(v4addr.String(), -5), input: net.JoinHostPort(v4addr.String(), "-5"),
wantErrMsg: `invalid port "-5" parsing "1.2.3.4:-5" wantErrMsg: `invalid port "-5" parsing "1.2.3.4:-5"
ParseAddr("1.2.3.4:-5"): unexpected character (at ":-5")`, ParseAddr("1.2.3.4:-5"): unexpected character (at ":-5")`,
want: netip.AddrPort{}, want: netip.AddrPort{},

View File

@ -1,36 +0,0 @@
package aghnet
// DefaultRefreshIvl is the default period of time between refreshing cached
// addresses.
// const DefaultRefreshIvl = 5 * time.Minute
// HostGenFunc is the signature for functions generating fake hostnames. The
// implementation must be safe for concurrent use.
type HostGenFunc func() (host string)
// SystemResolvers helps to work with local resolvers' addresses provided by OS.
type SystemResolvers interface {
// Get returns the slice of local resolvers' addresses. It must be safe for
// concurrent use.
Get() (rs []string)
// refresh refreshes the local resolvers' addresses cache. It must be safe
// for concurrent use.
refresh() (err error)
}
// NewSystemResolvers returns a SystemResolvers with the cache refresh rate
// defined by refreshIvl. It disables auto-refreshing if refreshIvl is 0. If
// nil is passed for hostGenFunc, the default generator will be used.
func NewSystemResolvers(
hostGenFunc HostGenFunc,
) (sr SystemResolvers, err error) {
sr = newSystemResolvers(hostGenFunc)
// Fill cache.
err = sr.refresh()
if err != nil {
return nil, err
}
return sr, nil
}

View File

@ -1,146 +0,0 @@
//go:build !windows
package aghnet
import (
"context"
"fmt"
"net"
"strings"
"sync"
"time"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil"
)
// defaultHostGen is the default method of generating host for Refresh.
func defaultHostGen() (host string) {
// TODO(e.burkov): Use strings.Builder.
return fmt.Sprintf("test%d.org", time.Now().UnixNano())
}
// systemResolvers is a default implementation of SystemResolvers interface.
type systemResolvers struct {
// addrsLock protects addrs.
addrsLock sync.RWMutex
// addrs is the set that contains cached local resolvers' addresses.
addrs *stringutil.Set
// resolver is used to fetch the resolvers' addresses.
resolver *net.Resolver
// hostGenFunc generates hosts to resolve.
hostGenFunc HostGenFunc
}
const (
// errBadAddrPassed is returned when dialFunc can't parse an IP address.
errBadAddrPassed errors.Error = "the passed string is not a valid IP address"
// errFakeDial is an error which dialFunc is expected to return.
errFakeDial errors.Error = "this error signals the successful dialFunc work"
// errUnexpectedHostFormat is returned by validateDialedHost when the host has
// more than one percent sign.
errUnexpectedHostFormat errors.Error = "unexpected host format"
)
// refresh implements the SystemResolvers interface for *systemResolvers.
func (sr *systemResolvers) refresh() (err error) {
defer func() { err = errors.Annotate(err, "systemResolvers: %w") }()
_, err = sr.resolver.LookupHost(context.Background(), sr.hostGenFunc())
dnserr := &net.DNSError{}
if errors.As(err, &dnserr) && dnserr.Err == errFakeDial.Error() {
return nil
}
return err
}
func newSystemResolvers(hostGenFunc HostGenFunc) (sr SystemResolvers) {
if hostGenFunc == nil {
hostGenFunc = defaultHostGen
}
s := &systemResolvers{
resolver: &net.Resolver{
PreferGo: true,
},
hostGenFunc: hostGenFunc,
addrs: stringutil.NewSet(),
}
s.resolver.Dial = s.dialFunc
return s
}
// validateDialedHost validated the host used by resolvers in dialFunc.
func validateDialedHost(host string) (err error) {
defer func() { err = errors.Annotate(err, "parsing %q: %w", host) }()
parts := strings.Split(host, "%")
switch len(parts) {
case 1:
// host
case 2:
// Remove the zone and check the IP address part.
host = parts[0]
default:
return errUnexpectedHostFormat
}
if _, err = netutil.ParseIP(host); err != nil {
return errBadAddrPassed
}
return nil
}
// dockerEmbeddedDNS is the address of Docker's embedded DNS server.
//
// See
// https://github.com/moby/moby/blob/v1.12.0/docs/userguide/networking/dockernetworks.md.
const dockerEmbeddedDNS = "127.0.0.11"
// dialFunc gets the resolver's address and puts it into internal cache.
func (sr *systemResolvers) dialFunc(_ context.Context, _, address string) (_ net.Conn, err error) {
// Just validate the passed address is a valid IP.
var host string
host, err = netutil.SplitHost(address)
if err != nil {
// TODO(e.burkov): Maybe use a structured errBadAddrPassed to
// allow unwrapping of the real error.
return nil, fmt.Errorf("%s: %w", err, errBadAddrPassed)
}
// Exclude Docker's embedded DNS server, as it may cause recursion if
// the container is set as the host system's default DNS server.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/3064.
//
// TODO(a.garipov): Perhaps only do this when we are in the container?
// Maybe use an environment variable?
if host == dockerEmbeddedDNS {
return nil, errFakeDial
}
err = validateDialedHost(host)
if err != nil {
return nil, fmt.Errorf("validating dialed host: %w", err)
}
sr.addrsLock.Lock()
defer sr.addrsLock.Unlock()
sr.addrs.Add(host)
return nil, errFakeDial
}
func (sr *systemResolvers) Get() (rs []string) {
sr.addrsLock.RLock()
defer sr.addrsLock.RUnlock()
return sr.addrs.Values()
}

View File

@ -1,81 +0,0 @@
//go:build !windows
package aghnet
import (
"context"
"testing"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func createTestSystemResolversImpl(
t *testing.T,
hostGenFunc HostGenFunc,
) (imp *systemResolvers) {
t.Helper()
sr := createTestSystemResolvers(t, hostGenFunc)
return testutil.RequireTypeAssert[*systemResolvers](t, sr)
}
func TestSystemResolvers_Refresh(t *testing.T) {
t.Run("expected_error", func(t *testing.T) {
sr := createTestSystemResolvers(t, nil)
assert.NoError(t, sr.refresh())
})
t.Run("unexpected_error", func(t *testing.T) {
_, err := NewSystemResolvers(func() string {
return "127.0.0.1::123"
})
assert.Error(t, err)
})
}
func TestSystemResolvers_DialFunc(t *testing.T) {
imp := createTestSystemResolversImpl(t, nil)
testCases := []struct {
want error
name string
address string
}{{
want: errFakeDial,
name: "valid_ipv4",
address: "127.0.0.1",
}, {
want: errFakeDial,
name: "valid_ipv6_port",
address: "[::1]:53",
}, {
want: errFakeDial,
name: "valid_ipv6_zone_port",
address: "[::1%lo0]:53",
}, {
want: errBadAddrPassed,
name: "invalid_split_host",
address: "127.0.0.1::123",
}, {
want: errUnexpectedHostFormat,
name: "invalid_ipv6_zone_port",
address: "[::1%%lo0]:53",
}, {
want: errBadAddrPassed,
name: "invalid_parse_ip",
address: "not-ip",
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
conn, err := imp.dialFunc(context.Background(), "", tc.address)
require.Nil(t, conn)
assert.ErrorIs(t, err, tc.want)
})
}
}

View File

@ -1,37 +0,0 @@
package aghnet
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func createTestSystemResolvers(
t *testing.T,
hostGenFunc HostGenFunc,
) (sr SystemResolvers) {
t.Helper()
var err error
sr, err = NewSystemResolvers(hostGenFunc)
require.NoError(t, err)
require.NotNil(t, sr)
return sr
}
func TestSystemResolvers_Get(t *testing.T) {
sr := createTestSystemResolvers(t, nil)
var rs []string
require.NotPanics(t, func() {
rs = sr.Get()
})
assert.NotEmpty(t, rs)
}
// TODO(e.burkov): Write tests for refreshWithTicker.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/2846.

View File

@ -1,163 +0,0 @@
//go:build windows
package aghnet
import (
"bufio"
"fmt"
"io"
"net"
"os/exec"
"strings"
"sync"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
)
// systemResolvers implementation differs for Windows since Go's resolver
// doesn't work there.
//
// See https://github.com/golang/go/issues/33097.
type systemResolvers struct {
// addrs is the slice of cached local resolvers' addresses.
addrs []string
addrsLock sync.RWMutex
}
func newSystemResolvers(_ HostGenFunc) (sr SystemResolvers) {
return &systemResolvers{}
}
func (sr *systemResolvers) Get() (rs []string) {
sr.addrsLock.RLock()
defer sr.addrsLock.RUnlock()
addrs := sr.addrs
rs = make([]string, len(addrs))
copy(rs, addrs)
return rs
}
// writeExit writes "exit" to w and closes it. It is supposed to be run in
// a goroutine.
func writeExit(w io.WriteCloser) {
defer log.OnPanic("systemResolvers: writeExit")
defer func() {
derr := w.Close()
if derr != nil {
log.Error("systemResolvers: writeExit: closing: %s", derr)
}
}()
_, err := io.WriteString(w, "exit")
if err != nil {
log.Error("systemResolvers: writeExit: writing: %s", err)
}
}
// scanAddrs scans the DNS addresses from nslookup's output. The expected
// output of nslookup looks like this:
//
// Default Server: 192-168-1-1.qualified.domain.ru
// Address: 192.168.1.1
func scanAddrs(s *bufio.Scanner) (addrs []string) {
for s.Scan() {
line := strings.TrimSpace(s.Text())
fields := strings.Fields(line)
if len(fields) != 2 || fields[0] != "Address:" {
continue
}
// If the address contains port then it is separated with '#'.
ipPort := strings.Split(fields[1], "#")
if len(ipPort) == 0 {
continue
}
addr := ipPort[0]
if net.ParseIP(addr) == nil {
log.Debug("systemResolvers: %q is not a valid ip", addr)
continue
}
addrs = append(addrs, addr)
}
return addrs
}
// getAddrs gets local resolvers' addresses from OS in a special Windows way.
//
// TODO(e.burkov): This whole function needs more detailed research on getting
// local resolvers addresses on Windows. We execute the external command for
// now that is not the most accurate way.
func (sr *systemResolvers) getAddrs() (addrs []string, err error) {
var cmdPath string
cmdPath, err = exec.LookPath("nslookup.exe")
if err != nil {
return nil, fmt.Errorf("looking up cmd path: %w", err)
}
cmd := exec.Command(cmdPath)
var stdin io.WriteCloser
stdin, err = cmd.StdinPipe()
if err != nil {
return nil, fmt.Errorf("getting the command's stdin pipe: %w", err)
}
var stdout io.ReadCloser
stdout, err = cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("getting the command's stdout pipe: %w", err)
}
go writeExit(stdin)
err = cmd.Start()
if err != nil {
return nil, fmt.Errorf("start command executing: %w", err)
}
s := bufio.NewScanner(stdout)
addrs = scanAddrs(s)
err = cmd.Wait()
if err != nil {
return nil, fmt.Errorf("executing the command: %w", err)
}
err = s.Err()
if err != nil {
return nil, fmt.Errorf("scanning output: %w", err)
}
// Don't close StdoutPipe since Wait do it for us in ¿most? cases.
//
// See [exec.Cmd.StdoutPipe].
return addrs, nil
}
func (sr *systemResolvers) refresh() (err error) {
defer func() { err = errors.Annotate(err, "systemResolvers: %w") }()
got, err := sr.getAddrs()
if err != nil {
return fmt.Errorf("can't get addresses: %w", err)
}
if len(got) == 0 {
return nil
}
sr.addrsLock.Lock()
defer sr.addrsLock.Unlock()
sr.addrs = got
return nil
}

View File

@ -1,7 +0,0 @@
//go:build windows
package aghnet
// TODO(e.burkov): Write tests for Windows implementation.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/2846.

View File

@ -436,18 +436,18 @@ func (conf *ServerConfig) collectDNSAddrs() (
// defaultPlainDNSPort is the default port for plain DNS. // defaultPlainDNSPort is the default port for plain DNS.
const defaultPlainDNSPort uint16 = 53 const defaultPlainDNSPort uint16 = 53
// upstreamMatcher is a function that matches address of an upstream. // addrPortMatcher is a function that matches an IP address with port.
type upstreamMatcher func(addr netip.AddrPort) (ok bool) type addrPortMatcher func(addr netip.AddrPort) (ok bool)
// filterOut filters out all the upstreams that match um. It returns all the // filterOut filters out all the upstreams that match um. It returns all the
// closing errors joined. // closing errors joined.
func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) { func (m addrPortMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) {
var errs []error var errs []error
delFunc := func(u upstream.Upstream) (ok bool) { delFunc := func(u upstream.Upstream) (ok bool) {
// TODO(e.burkov): We should probably consider the protocol of u to // TODO(e.burkov): We should probably consider the protocol of u to
// only filter out the listening addresses of the same protocol. // only filter out the listening addresses of the same protocol.
addr, parseErr := aghnet.ParseAddrPort(u.Address(), defaultPlainDNSPort) addr, parseErr := aghnet.ParseAddrPort(u.Address(), defaultPlainDNSPort)
if parseErr != nil || !um(addr) { if parseErr != nil || !m(addr) {
// Don't filter out the upstream if it either cannot be parsed, or // Don't filter out the upstream if it either cannot be parsed, or
// does not match um. // does not match um.
return false return false
@ -469,23 +469,21 @@ func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) {
return errors.Join(errs...) return errors.Join(errs...)
} }
// filterOurAddrs filters out all the upstreams that pointing to the local // ourAddrsMatcher returns a matcher that matches all the configured listening
// listening addresses to avoid recursive queries. upsConf may appear empty // addresses.
// after the filtering. All the filtered upstreams are closed and these func (conf *ServerConfig) ourAddrsMatcher() (m addrPortMatcher, err error) {
// closings errors are joined.
func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err error) {
addrs, unspecPorts := conf.collectDNSAddrs() addrs, unspecPorts := conf.collectDNSAddrs()
if len(addrs) == 0 { if len(addrs) == 0 {
log.Debug("dnsforward: no listen addresses") log.Debug("dnsforward: no listen addresses")
return nil // Match no addresses.
return func(_ netip.AddrPort) (ok bool) { return false }, nil
} }
var matcher upstreamMatcher
if len(unspecPorts) == 0 { if len(unspecPorts) == 0 {
log.Debug("dnsforward: filtering out addresses %s", addrs) log.Debug("dnsforward: filtering out addresses %s", addrs)
matcher = func(a netip.AddrPort) (ok bool) { m = func(a netip.AddrPort) (ok bool) {
_, ok = addrs[a] _, ok = addrs[a]
return ok return ok
@ -495,12 +493,12 @@ func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err err
ifaceAddrs, err = aghnet.CollectAllIfacesAddrs() ifaceAddrs, err = aghnet.CollectAllIfacesAddrs()
if err != nil { if err != nil {
// Don't wrap the error since it's informative enough as is. // Don't wrap the error since it's informative enough as is.
return err return nil, err
} }
log.Debug("dnsforward: filtering out addresses %s on ports %d", ifaceAddrs, unspecPorts) log.Debug("dnsforward: filtering out addresses %s on ports %d", ifaceAddrs, unspecPorts)
matcher = func(a netip.AddrPort) (ok bool) { m = func(a netip.AddrPort) (ok bool) {
if _, ok = unspecPorts[a.Port()]; ok { if _, ok = unspecPorts[a.Port()]; ok {
return slices.Contains(ifaceAddrs, a.Addr()) return slices.Contains(ifaceAddrs, a.Addr())
} }
@ -509,7 +507,7 @@ func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err err
} }
} }
return matcher.filterOut(upsConf) return m, nil
} }
// prepareTLS - prepares TLS configuration for the DNS proxy // prepareTLS - prepares TLS configuration for the DNS proxy

View File

@ -25,8 +25,10 @@ import (
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/netutil/sysresolv"
"github.com/AdguardTeam/golibs/stringutil" "github.com/AdguardTeam/golibs/stringutil"
"github.com/miekg/dns" "github.com/miekg/dns"
"golang.org/x/exp/slices"
) )
// DefaultTimeout is the default upstream timeout // DefaultTimeout is the default upstream timeout
@ -72,6 +74,11 @@ type DHCP interface {
Enabled() (ok bool) Enabled() (ok bool)
} }
type SystemResolvers interface {
// Addrs returns the list of system resolvers' addresses.
Addrs() (addrs []netip.AddrPort)
}
// Server is the main way to start a DNS server. // Server is the main way to start a DNS server.
// //
// Example: // Example:
@ -126,7 +133,7 @@ type Server struct {
// sysResolvers used to fetch system resolvers to use by default for private // sysResolvers used to fetch system resolvers to use by default for private
// PTR resolving. // PTR resolving.
sysResolvers aghnet.SystemResolvers sysResolvers SystemResolvers
// recDetector is a cache for recursive requests. It is used to detect // recDetector is a cache for recursive requests. It is used to detect
// and prevent recursive requests only for private upstreams. // and prevent recursive requests only for private upstreams.
@ -225,9 +232,7 @@ func NewServer(p DNSCreateParams) (s *Server, err error) {
anonymizer: p.Anonymizer, anonymizer: p.Anonymizer,
} }
// TODO(e.burkov): Enable the refresher after the actual implementation s.sysResolvers, err = sysresolv.NewSystemResolvers(nil, defaultPlainDNSPort)
// passes the public testing.
s.sysResolvers, err = aghnet.NewSystemResolvers(nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("initializing system resolvers: %w", err) return nil, fmt.Errorf("initializing system resolvers: %w", err)
} }
@ -442,19 +447,30 @@ const defaultLocalTimeout = 1 * time.Second
// setupLocalResolvers initializes the resolvers for local addresses. For // setupLocalResolvers initializes the resolvers for local addresses. For
// internal use only. // internal use only.
func (s *Server) setupLocalResolvers() (err error) { func (s *Server) setupLocalResolvers() (err error) {
matcher, err := s.conf.ourAddrsMatcher()
if err != nil {
// Don't wrap the error because it's informative enough as is.
return err
}
bootstraps := s.conf.BootstrapDNS bootstraps := s.conf.BootstrapDNS
resolvers := s.conf.LocalPTRResolvers resolvers := s.conf.LocalPTRResolvers
filterConfig := false
if len(resolvers) == 0 { if len(resolvers) == 0 {
resolvers = s.sysResolvers.Get() sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher)
bootstraps = nil resolvers = make([]string, 0, len(sysResolvers))
for _, r := range sysResolvers {
resolvers = append(resolvers, r.String())
}
} else { } else {
resolvers = stringutil.FilterOut(resolvers, IsCommentOrEmpty) resolvers = stringutil.FilterOut(resolvers, IsCommentOrEmpty)
filterConfig = true
} }
log.Debug("dnsforward: upstreams to resolve ptr for local addresses: %v", resolvers) log.Debug("dnsforward: upstreams to resolve ptr for local addresses: %v", resolvers)
uc, err := s.prepareLocalUpstreamConfig(resolvers, nil, &upstream.Options{ uc, err := s.prepareUpstreamConfig(resolvers, nil, &upstream.Options{
Bootstrap: bootstraps, Bootstrap: bootstraps,
Timeout: defaultLocalTimeout, Timeout: defaultLocalTimeout,
// TODO(e.burkov): Should we verify server's certificates? // TODO(e.burkov): Should we verify server's certificates?
@ -464,6 +480,12 @@ func (s *Server) setupLocalResolvers() (err error) {
return fmt.Errorf("preparing private upstreams: %w", err) return fmt.Errorf("preparing private upstreams: %w", err)
} }
if filterConfig {
if err = matcher.filterOut(uc); err != nil {
return fmt.Errorf("filtering private upstreams: %w", err)
}
}
s.localResolvers = &proxy.Proxy{ s.localResolvers = &proxy.Proxy{
Config: proxy.Config{ Config: proxy.Config{
UpstreamConfig: uc, UpstreamConfig: uc,

View File

@ -179,17 +179,16 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) {
// defaultLocalPTRUpstreams returns the list of default local PTR resolvers // defaultLocalPTRUpstreams returns the list of default local PTR resolvers
// filtered of AdGuard Home's own DNS server addresses. It may appear empty. // filtered of AdGuard Home's own DNS server addresses. It may appear empty.
func (s *Server) defaultLocalPTRUpstreams() (ups []string, err error) { func (s *Server) defaultLocalPTRUpstreams() (ups []string, err error) {
s.serverLock.RLock() matcher, err := s.conf.ourAddrsMatcher()
defer s.serverLock.RUnlock()
uc, err := s.prepareLocalUpstreamConfig(s.sysResolvers.Get(), nil, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting system upstream config: %w", err) // Don't wrap the error because it's informative enough as is.
return nil, err
} }
defer func() { err = errors.Join(err, uc.Close()) }()
for _, u := range uc.Upstreams { sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher)
ups = append(ups, u.Address()) ups = make([]string, 0, len(sysResolvers))
for _, r := range sysResolvers {
ups = append(ups, r.String())
} }
return ups, nil return ups, nil
@ -228,7 +227,7 @@ func (req *jsonDNSConfig) checkBootstrap() (err error) {
return errors.Error("empty") return errors.Error("empty")
} }
if _, err = upstream.NewResolver(b, nil); err != nil { if _, err = upstream.NewUpstreamResolver(b, nil); err != nil {
return err return err
} }
} }

View File

@ -28,17 +28,12 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// fakeSystemResolvers is a mock aghnet.SystemResolvers implementation for // emptySysResolvers is an empty [SystemResolvers] implementation that always
// tests. // returns nil.
type fakeSystemResolvers struct { type emptySysResolvers struct{}
// SystemResolvers is embedded here simply to make *fakeSystemResolvers
// an aghnet.SystemResolvers without actually implementing all methods.
aghnet.SystemResolvers
}
// Get implements the aghnet.SystemResolvers interface for *fakeSystemResolvers. // Addrs implements the aghnet.SystemResolvers interface for emptySysResolvers.
// It always returns nil. func (emptySysResolvers) Addrs() (addrs []netip.AddrPort) {
func (fsr *fakeSystemResolvers) Get() (rs []string) {
return nil return nil
} }
@ -79,7 +74,7 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
ConfigModified: func() {}, ConfigModified: func() {},
} }
s := createTestServer(t, filterConf, forwardConf, nil) s := createTestServer(t, filterConf, forwardConf, nil)
s.sysResolvers = &fakeSystemResolvers{} s.sysResolvers = &emptySysResolvers{}
require.NoError(t, s.Start()) require.NoError(t, s.Start())
testutil.CleanupAndRequireSuccess(t, s.Stop) testutil.CleanupAndRequireSuccess(t, s.Stop)
@ -156,7 +151,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
ConfigModified: func() {}, ConfigModified: func() {},
} }
s := createTestServer(t, filterConf, forwardConf, nil) s := createTestServer(t, filterConf, forwardConf, nil)
s.sysResolvers = &fakeSystemResolvers{} s.sysResolvers = &emptySysResolvers{}
defaultConf := s.conf defaultConf := s.conf
@ -485,7 +480,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) {
hostsListener := newLocalUpstreamListener(t, 0, goodHandler) hostsListener := newLocalUpstreamListener(t, 0, goodHandler)
hostsUps := (&url.URL{ hostsUps := (&url.URL{
Scheme: "tcp", Scheme: "tcp",
Host: netutil.JoinHostPort(upstreamHost, int(hostsListener.Port())), Host: netutil.JoinHostPort(upstreamHost, hostsListener.Port()),
}).String() }).String()
hc, err := aghnet.NewHostsContainer( hc, err := aghnet.NewHostsContainer(

View File

@ -103,27 +103,6 @@ func (s *Server) prepareUpstreamConfig(
return uc, nil return uc, nil
} }
// prepareLocalUpstreamConfig returns the upstream configuration for private
// upstreams based on upstreams and configuration of s. It also filters out
// the own listening addresses from the upstreams, so it may appear empty.
func (s *Server) prepareLocalUpstreamConfig(
upstreams []string,
defaultUpstreams []string,
opts *upstream.Options,
) (uc *proxy.UpstreamConfig, err error) {
uc, err = s.prepareUpstreamConfig(upstreams, defaultUpstreams, opts)
if err != nil {
return nil, fmt.Errorf("preparing private upstreams: %w", err)
}
err = s.conf.filterOurAddrs(uc)
if err != nil {
return nil, fmt.Errorf("filtering private upstreams: %w", err)
}
return uc, nil
}
// replaceUpstreamsWithHosts replaces unique upstreams with their resolved // replaceUpstreamsWithHosts replaces unique upstreams with their resolved
// versions based on the system hosts file. // versions based on the system hosts file.
// //

View File

@ -182,7 +182,7 @@ type httpPprofConfig struct {
// not absolutely necessary. // not absolutely necessary.
type dnsConfig struct { type dnsConfig struct {
BindHosts []netip.Addr `yaml:"bind_hosts"` BindHosts []netip.Addr `yaml:"bind_hosts"`
Port int `yaml:"port"` Port uint16 `yaml:"port"`
// AnonymizeClientIP defines if clients' IP addresses should be anonymized // AnonymizeClientIP defines if clients' IP addresses should be anonymized
// in query log and statistics. // in query log and statistics.
@ -232,13 +232,13 @@ type tlsConfigSettings struct {
Enabled bool `yaml:"enabled" json:"enabled"` // Enabled is the encryption (DoT/DoH/HTTPS) status Enabled bool `yaml:"enabled" json:"enabled"` // Enabled is the encryption (DoT/DoH/HTTPS) status
ServerName string `yaml:"server_name" json:"server_name,omitempty"` // ServerName is the hostname of your HTTPS/TLS server ServerName string `yaml:"server_name" json:"server_name,omitempty"` // ServerName is the hostname of your HTTPS/TLS server
ForceHTTPS bool `yaml:"force_https" json:"force_https"` // ForceHTTPS: if true, forces HTTP->HTTPS redirect ForceHTTPS bool `yaml:"force_https" json:"force_https"` // ForceHTTPS: if true, forces HTTP->HTTPS redirect
PortHTTPS int `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS will be disabled PortHTTPS uint16 `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS will be disabled
PortDNSOverTLS int `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"` // DNS-over-TLS port. If 0, DoT will be disabled PortDNSOverTLS uint16 `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"` // DNS-over-TLS port. If 0, DoT will be disabled
PortDNSOverQUIC int `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"` // DNS-over-QUIC port. If 0, DoQ will be disabled PortDNSOverQUIC uint16 `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"` // DNS-over-QUIC port. If 0, DoQ will be disabled
// PortDNSCrypt is the port for DNSCrypt requests. If it's zero, // PortDNSCrypt is the port for DNSCrypt requests. If it's zero,
// DNSCrypt is disabled. // DNSCrypt is disabled.
PortDNSCrypt int `yaml:"port_dnscrypt" json:"port_dnscrypt"` PortDNSCrypt uint16 `yaml:"port_dnscrypt" json:"port_dnscrypt"`
// DNSCryptConfigFile is the path to the DNSCrypt config file. Must be // DNSCryptConfigFile is the path to the DNSCrypt config file. Must be
// set if PortDNSCrypt is not zero. // set if PortDNSCrypt is not zero.
// //
@ -554,10 +554,10 @@ func validateConfig() (err error) {
} }
// udpPort is the port number for UDP protocol. // udpPort is the port number for UDP protocol.
type udpPort int type udpPort uint16
// tcpPort is the port number for TCP protocol. // tcpPort is the port number for TCP protocol.
type tcpPort int type tcpPort uint16
// addPorts is a helper for ports validation that skips zero ports. // addPorts is a helper for ports validation that skips zero ports.
func addPorts[T tcpPort | udpPort](uc aghalg.UniqChecker[T], ports ...T) { func addPorts[T tcpPort | udpPort](uc aghalg.UniqChecker[T], ports ...T) {

View File

@ -24,11 +24,9 @@ import (
// addresses to a slice of strings. // addresses to a slice of strings.
func appendDNSAddrs(dst []string, addrs ...netip.Addr) (res []string) { func appendDNSAddrs(dst []string, addrs ...netip.Addr) (res []string) {
for _, addr := range addrs { for _, addr := range addrs {
var hostport string hostport := addr.String()
if config.DNS.Port != defaultPortDNS { if p := config.DNS.Port; p != defaultPortDNS {
hostport = netip.AddrPortFrom(addr, uint16(config.DNS.Port)).String() hostport = netutil.JoinHostPort(hostport, p)
} else {
hostport = addr.String()
} }
dst = append(dst, hostport) dst = append(dst, hostport)
@ -102,7 +100,7 @@ type statusResponse struct {
Version string `json:"version"` Version string `json:"version"`
Language string `json:"language"` Language string `json:"language"`
DNSAddrs []string `json:"dns_addresses"` DNSAddrs []string `json:"dns_addresses"`
DNSPort int `json:"dns_port"` DNSPort uint16 `json:"dns_port"`
HTTPPort uint16 `json:"http_port"` HTTPPort uint16 `json:"http_port"`
// ProtectionDisabledDuration is the duration of the protection pause in // ProtectionDisabledDuration is the duration of the protection pause in
@ -340,7 +338,7 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (proceed bool)
var ( var (
forceHTTPS bool forceHTTPS bool
serveHTTP3 bool serveHTTP3 bool
portHTTPS int portHTTPS uint16
) )
func() { func() {
config.RLock() config.RLock()
@ -394,7 +392,7 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (proceed bool)
// httpsURL returns a copy of u for redirection to the HTTPS version, taking the // httpsURL returns a copy of u for redirection to the HTTPS version, taking the
// hostname and the HTTPS port into account. // hostname and the HTTPS port into account.
func httpsURL(u *url.URL, host string, portHTTPS int) (redirectURL *url.URL) { func httpsURL(u *url.URL, host string, portHTTPS uint16) (redirectURL *url.URL) {
hostPort := host hostPort := host
if portHTTPS != defaultPortHTTPS { if portHTTPS != defaultPortHTTPS {
hostPort = netutil.JoinHostPort(host, portHTTPS) hostPort = netutil.JoinHostPort(host, portHTTPS)

View File

@ -43,8 +43,8 @@ func (web *webAPI) handleInstallGetAddresses(w http.ResponseWriter, r *http.Requ
data := getAddrsResponse{ data := getAddrsResponse{
Version: version.Version(), Version: version.Version(),
WebPort: defaultPortHTTP, WebPort: int(defaultPortHTTP),
DNSPort: defaultPortDNS, DNSPort: int(defaultPortDNS),
} }
ifaces, err := aghnet.GetValidNetInterfacesForWeb() ifaces, err := aghnet.GetValidNetInterfacesForWeb()
@ -64,7 +64,7 @@ func (web *webAPI) handleInstallGetAddresses(w http.ResponseWriter, r *http.Requ
type checkConfReqEnt struct { type checkConfReqEnt struct {
IP netip.Addr `json:"ip"` IP netip.Addr `json:"ip"`
Port int `json:"port"` Port uint16 `json:"port"`
Autofix bool `json:"autofix"` Autofix bool `json:"autofix"`
} }
@ -97,7 +97,7 @@ func (req *checkConfReq) validateWeb(tcpPorts aghalg.UniqChecker[tcpPort]) (err
defer func() { err = errors.Annotate(err, "validating ports: %w") }() defer func() { err = errors.Annotate(err, "validating ports: %w") }()
// TODO(a.garipov): Declare all port variables anywhere as uint16. // TODO(a.garipov): Declare all port variables anywhere as uint16.
reqPort := uint16(req.Web.Port) reqPort := req.Web.Port
port := tcpPort(reqPort) port := tcpPort(reqPort)
addPorts(tcpPorts, port) addPorts(tcpPorts, port)
if err = tcpPorts.Validate(); err != nil { if err = tcpPorts.Validate(); err != nil {
@ -128,7 +128,7 @@ func (req *checkConfReq) validateDNS(
) (canAutofix bool, err error) { ) (canAutofix bool, err error) {
defer func() { err = errors.Annotate(err, "validating ports: %w") }() defer func() { err = errors.Annotate(err, "validating ports: %w") }()
port := uint16(req.DNS.Port) port := req.DNS.Port
switch port { switch port {
case 0: case 0:
return false, nil return false, nil
@ -142,13 +142,13 @@ func (req *checkConfReq) validateDNS(
return false, err return false, err
} }
err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.DNS.IP, uint16(port))) err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.DNS.IP, port))
if err != nil { if err != nil {
return false, err return false, err
} }
} }
err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, uint16(port))) err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, port))
if !aghnet.IsAddrInUse(err) { if !aghnet.IsAddrInUse(err) {
return false, err return false, err
} }
@ -160,7 +160,7 @@ func (req *checkConfReq) validateDNS(
log.Error("disabling DNSStubListener: %s", err) log.Error("disabling DNSStubListener: %s", err)
} }
err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, uint16(port))) err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, port))
canAutofix = false canAutofix = false
} }
@ -305,7 +305,7 @@ func disableDNSStubListener() error {
type applyConfigReqEnt struct { type applyConfigReqEnt struct {
IP netip.Addr `json:"ip"` IP netip.Addr `json:"ip"`
Port int `json:"port"` Port uint16 `json:"port"`
} }
type applyConfigReq struct { type applyConfigReq struct {
@ -395,14 +395,14 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request
return return
} }
err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, uint16(req.DNS.Port))) err = aghnet.CheckPort("udp", netip.AddrPortFrom(req.DNS.IP, req.DNS.Port))
if err != nil { if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err) aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
return return
} }
err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.DNS.IP, uint16(req.DNS.Port))) err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.DNS.IP, req.DNS.Port))
if err != nil { if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err) aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
@ -413,7 +413,7 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request
copyInstallSettings(curConfig, config) copyInstallSettings(curConfig, config)
Context.firstRun = false Context.firstRun = false
config.HTTPConfig.Address = netip.AddrPortFrom(req.Web.IP, uint16(req.Web.Port)) config.HTTPConfig.Address = netip.AddrPortFrom(req.Web.IP, req.Web.Port)
config.DNS.BindHosts = []netip.Addr{req.DNS.IP} config.DNS.BindHosts = []netip.Addr{req.DNS.IP}
config.DNS.Port = req.DNS.Port config.DNS.Port = req.DNS.Port
@ -445,8 +445,7 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request
} }
web.conf.firstRun = false web.conf.firstRun = false
web.conf.BindHost = req.Web.IP web.conf.BindAddr = netip.AddrPortFrom(req.Web.IP, req.Web.Port)
web.conf.BindPort = req.Web.Port
registerControlHandlers(web) registerControlHandlers(web)
@ -487,9 +486,9 @@ func decodeApplyConfigReq(r io.Reader) (req *applyConfigReq, restartHTTP bool, e
} }
addrPort := config.HTTPConfig.Address addrPort := config.HTTPConfig.Address
restartHTTP = addrPort.Addr() != req.Web.IP || int(addrPort.Port()) != req.Web.Port restartHTTP = addrPort.Addr() != req.Web.IP || addrPort.Port() != req.Web.Port
if restartHTTP { if restartHTTP {
err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.Web.IP, uint16(req.Web.Port))) err = aghnet.CheckPort("tcp", netip.AddrPortFrom(req.Web.IP, req.Web.Port))
if err != nil { if err != nil {
return nil, false, fmt.Errorf( return nil, false, fmt.Errorf(
"checking address %s:%d: %w", "checking address %s:%d: %w",

View File

@ -27,11 +27,11 @@ import (
// Default listening ports. // Default listening ports.
const ( const (
defaultPortDNS = 53 defaultPortDNS uint16 = 53
defaultPortHTTP = 80 defaultPortHTTP uint16 = 80
defaultPortHTTPS = 443 defaultPortHTTPS uint16 = 443
defaultPortQUIC = 853 defaultPortQUIC uint16 = 853
defaultPortTLS = 853 defaultPortTLS uint16 = 853
) )
// Called by other modules when configuration is changed // Called by other modules when configuration is changed
@ -196,27 +196,27 @@ func isRunning() bool {
return Context.dnsServer != nil && Context.dnsServer.IsRunning() return Context.dnsServer != nil && Context.dnsServer.IsRunning()
} }
func ipsToTCPAddrs(ips []netip.Addr, port int) (tcpAddrs []*net.TCPAddr) { func ipsToTCPAddrs(ips []netip.Addr, port uint16) (tcpAddrs []*net.TCPAddr) {
if ips == nil { if ips == nil {
return nil return nil
} }
tcpAddrs = make([]*net.TCPAddr, 0, len(ips)) tcpAddrs = make([]*net.TCPAddr, 0, len(ips))
for _, ip := range ips { for _, ip := range ips {
tcpAddrs = append(tcpAddrs, net.TCPAddrFromAddrPort(netip.AddrPortFrom(ip, uint16(port)))) tcpAddrs = append(tcpAddrs, net.TCPAddrFromAddrPort(netip.AddrPortFrom(ip, port)))
} }
return tcpAddrs return tcpAddrs
} }
func ipsToUDPAddrs(ips []netip.Addr, port int) (udpAddrs []*net.UDPAddr) { func ipsToUDPAddrs(ips []netip.Addr, port uint16) (udpAddrs []*net.UDPAddr) {
if ips == nil { if ips == nil {
return nil return nil
} }
udpAddrs = make([]*net.UDPAddr, 0, len(ips)) udpAddrs = make([]*net.UDPAddr, 0, len(ips))
for _, ip := range ips { for _, ip := range ips {
udpAddrs = append(udpAddrs, net.UDPAddrFromAddrPort(netip.AddrPortFrom(ip, uint16(port)))) udpAddrs = append(udpAddrs, net.UDPAddrFromAddrPort(netip.AddrPortFrom(ip, port)))
} }
return udpAddrs return udpAddrs
@ -346,8 +346,8 @@ func getDNSEncryption() (de dnsEncryption) {
hostname := tlsConf.ServerName hostname := tlsConf.ServerName
if tlsConf.PortHTTPS != 0 { if tlsConf.PortHTTPS != 0 {
addr := hostname addr := hostname
if tlsConf.PortHTTPS != defaultPortHTTPS { if p := tlsConf.PortHTTPS; p != defaultPortHTTPS {
addr = netutil.JoinHostPort(addr, tlsConf.PortHTTPS) addr = netutil.JoinHostPort(addr, p)
} }
de.https = (&url.URL{ de.https = (&url.URL{
@ -357,17 +357,17 @@ func getDNSEncryption() (de dnsEncryption) {
}).String() }).String()
} }
if tlsConf.PortDNSOverTLS != 0 { if p := tlsConf.PortDNSOverTLS; p != 0 {
de.tls = (&url.URL{ de.tls = (&url.URL{
Scheme: "tls", Scheme: "tls",
Host: netutil.JoinHostPort(hostname, tlsConf.PortDNSOverTLS), Host: netutil.JoinHostPort(hostname, p),
}).String() }).String()
} }
if tlsConf.PortDNSOverQUIC != 0 { if p := tlsConf.PortDNSOverQUIC; p != 0 {
de.quic = (&url.URL{ de.quic = (&url.URL{
Scheme: "quic", Scheme: "quic",
Host: netutil.JoinHostPort(hostname, tlsConf.PortDNSOverQUIC), Host: netutil.JoinHostPort(hostname, p),
}).String() }).String()
} }
} }

View File

@ -329,7 +329,7 @@ func setupBindOpts(opts options) (err error) {
if opts.bindPort != 0 { if opts.bindPort != 0 {
config.HTTPConfig.Address = netip.AddrPortFrom( config.HTTPConfig.Address = netip.AddrPortFrom(
config.HTTPConfig.Address.Addr(), config.HTTPConfig.Address.Addr(),
uint16(opts.bindPort), opts.bindPort,
) )
err = checkPorts() err = checkPorts()
@ -497,8 +497,7 @@ func initWeb(opts options, clientBuildFS fs.FS, upd *updater.Updater) (web *webA
clientFS: clientFS, clientFS: clientFS,
BindHost: config.HTTPConfig.Address.Addr(), BindAddr: config.HTTPConfig.Address,
BindPort: int(config.HTTPConfig.Address.Port()),
ReadTimeout: readTimeout, ReadTimeout: readTimeout,
ReadHeaderTimeout: readHdrTimeout, ReadHeaderTimeout: readHdrTimeout,
@ -853,7 +852,7 @@ func loadCmdLineOpts() (opts options) {
// example: // example:
// //
// go to http://127.0.0.1:80 // go to http://127.0.0.1:80
func printWebAddrs(proto, addr string, port int) { func printWebAddrs(proto, addr string, port uint16) {
log.Printf("go to %s://%s", proto, netutil.JoinHostPort(addr, port)) log.Printf("go to %s://%s", proto, netutil.JoinHostPort(addr, port))
} }
@ -865,7 +864,7 @@ func printHTTPAddresses(proto string) {
Context.tls.WriteDiskConfig(&tlsConf) Context.tls.WriteDiskConfig(&tlsConf)
} }
port := int(config.HTTPConfig.Address.Port()) port := config.HTTPConfig.Address.Port()
if proto == aghhttp.SchemeHTTPS { if proto == aghhttp.SchemeHTTPS {
port = tlsConf.PortHTTPS port = tlsConf.PortHTTPS
} }

View File

@ -42,7 +42,7 @@ type options struct {
// bindPort is the port on which to serve the HTTP UI. // bindPort is the port on which to serve the HTTP UI.
// //
// Deprecated: Use bindAddr. // Deprecated: Use bindAddr.
bindPort int bindPort uint16
// bindAddr is the address to serve the web UI on. // bindAddr is the address to serve the web UI on.
bindAddr netip.AddrPort bindAddr netip.AddrPort
@ -160,15 +160,11 @@ var cmdLineOpts = []cmdLineOpt{{
shortName: "h", shortName: "h",
}, { }, {
updateWithValue: func(o options, v string) (options, error) { updateWithValue: func(o options, v string) (options, error) {
var err error p, err := strconv.ParseUint(v, 10, 16)
var p int if err != nil {
minPort, maxPort := 0, 1<<16-1 err = fmt.Errorf("parsing port: %w", err)
if p, err = strconv.Atoi(v); err != nil {
err = fmt.Errorf("port %q is not a number", v)
} else if p < minPort || p > maxPort {
err = fmt.Errorf("port %d not in range %d - %d", p, minPort, maxPort)
} else { } else {
o.bindPort = p o.bindPort = uint16(p)
} }
return o, err return o, err
@ -180,7 +176,7 @@ var cmdLineOpts = []cmdLineOpt{{
return "", false return "", false
} }
return strconv.Itoa(o.bindPort), true return strconv.Itoa(int(o.bindPort)), true
}, },
description: "Deprecated. Port to serve HTTP pages on. Use --web-addr.", description: "Deprecated. Port to serve HTTP pages on. Use --web-addr.",
longName: "port", longName: "port",

View File

@ -67,11 +67,11 @@ func TestParseBindHost(t *testing.T) {
} }
func TestParseBindPort(t *testing.T) { func TestParseBindPort(t *testing.T) {
assert.Equal(t, 0, testParseOK(t).bindPort, "empty is port 0") assert.Equal(t, uint16(0), testParseOK(t).bindPort, "empty is port 0")
assert.Equal(t, 65535, testParseOK(t, "-p", "65535").bindPort, "-p is port") assert.Equal(t, uint16(65535), testParseOK(t, "-p", "65535").bindPort, "-p is port")
testParseParamMissing(t, "-p") testParseParamMissing(t, "-p")
assert.Equal(t, 65535, testParseOK(t, "--port", "65535").bindPort, "--port is port") assert.Equal(t, uint16(65535), testParseOK(t, "--port", "65535").bindPort, "--port is port")
testParseParamMissing(t, "--port") testParseParamMissing(t, "--port")
testParseErr(t, "not an int", "-p", "x") testParseErr(t, "not an int", "-p", "x")

View File

@ -39,8 +39,8 @@ type webConfig struct {
clientFS fs.FS clientFS fs.FS
BindHost netip.Addr // BindAddr is the binding address with port for plain HTTP web interface.
BindPort int BindAddr netip.AddrPort
// ReadTimeout is an option to pass to http.Server for setting an // ReadTimeout is an option to pass to http.Server for setting an
// appropriate field. // appropriate field.
@ -125,12 +125,12 @@ func newWebAPI(conf *webConfig) (w *webAPI) {
// available, unless the HTTPS server isn't active. // available, unless the HTTPS server isn't active.
// //
// TODO(a.garipov): Adapt for HTTP/3. // TODO(a.garipov): Adapt for HTTP/3.
func webCheckPortAvailable(port int) (ok bool) { func webCheckPortAvailable(port uint16) (ok bool) {
if Context.web.httpsServer.server != nil { if Context.web.httpsServer.server != nil {
return true return true
} }
addrPort := netip.AddrPortFrom(config.HTTPConfig.Address.Addr(), uint16(port)) addrPort := netip.AddrPortFrom(config.HTTPConfig.Address.Addr(), port)
return aghnet.CheckPort("tcp", addrPort) == nil return aghnet.CheckPort("tcp", addrPort) == nil
} }
@ -185,10 +185,9 @@ func (web *webAPI) start() {
hdlr := h2c.NewHandler(withMiddlewares(Context.mux, limitRequestBody), &http2.Server{}) hdlr := h2c.NewHandler(withMiddlewares(Context.mux, limitRequestBody), &http2.Server{})
// Create a new instance, because the Web is not usable after Shutdown. // Create a new instance, because the Web is not usable after Shutdown.
hostStr := web.conf.BindHost.String()
web.httpServer = &http.Server{ web.httpServer = &http.Server{
ErrorLog: log.StdLog("web: plain", log.DEBUG), ErrorLog: log.StdLog("web: plain", log.DEBUG),
Addr: netutil.JoinHostPort(hostStr, web.conf.BindPort), Addr: web.conf.BindAddr.String(),
Handler: hdlr, Handler: hdlr,
ReadTimeout: web.conf.ReadTimeout, ReadTimeout: web.conf.ReadTimeout,
ReadHeaderTimeout: web.conf.ReadHeaderTimeout, ReadHeaderTimeout: web.conf.ReadHeaderTimeout,
@ -249,7 +248,7 @@ func (web *webAPI) tlsServerLoop() {
web.httpsServer.cond.L.Unlock() web.httpsServer.cond.L.Unlock()
var portHTTPS int var portHTTPS uint16
func() { func() {
config.RLock() config.RLock()
defer config.RUnlock() defer config.RUnlock()
@ -257,7 +256,7 @@ func (web *webAPI) tlsServerLoop() {
portHTTPS = config.TLS.PortHTTPS portHTTPS = config.TLS.PortHTTPS
}() }()
addr := netutil.JoinHostPort(web.conf.BindHost.String(), portHTTPS) addr := netip.AddrPortFrom(web.conf.BindAddr.Addr(), portHTTPS).String()
web.httpsServer.server = &http.Server{ web.httpsServer.server = &http.Server{
ErrorLog: log.StdLog("web: https", log.DEBUG), ErrorLog: log.StdLog("web: https", log.DEBUG),
Addr: addr, Addr: addr,