From 5f61b550fa8837290c6df6b268d2746c3307b10c Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 5 Oct 2023 15:26:19 +0300 Subject: [PATCH] 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 Date: Thu Oct 5 14:21:51 2023 +0300 Merge branch 'master' into upd-golibs commit 99eb7745d0bee190399f9b16cb7151f34a591b54 Author: Eugene Burkov Date: Thu Oct 5 14:14:28 2023 +0300 home: imp alignment commit 556cde56720ce449aec17b500825681fc8c084bf Author: Eugene Burkov Date: Thu Oct 5 13:35:35 2023 +0300 dnsforward: imp naming, docs commit 1ee99655a3318263db1edbcb9e4eeb33bfe441c8 Author: Eugene Burkov Date: Thu Oct 5 13:28:39 2023 +0300 home: make ports uint16 commit b228032ea1f5902ab9bac7b5d55d84aaf6354616 Author: Eugene Burkov Date: Wed Oct 4 18:56:59 2023 +0300 all: rm system resolvers commit 4b5becbed5890db80612e53861f000aaf4c869ff Author: Eugene Burkov Date: Wed Oct 4 17:30:16 2023 +0300 all: upd golibs --- go.mod | 14 +- go.sum | 37 ++-- internal/aghnet/interfaces_linux.go | 4 +- internal/aghnet/net_test.go | 3 +- internal/aghnet/systemresolvers.go | 36 ---- internal/aghnet/systemresolvers_others.go | 146 ---------------- .../aghnet/systemresolvers_others_test.go | 81 --------- internal/aghnet/systemresolvers_test.go | 37 ---- internal/aghnet/systemresolvers_windows.go | 163 ------------------ .../aghnet/systemresolvers_windows_test.go | 7 - internal/dnsforward/config.go | 28 ++- internal/dnsforward/dnsforward.go | 36 +++- internal/dnsforward/http.go | 17 +- internal/dnsforward/http_test.go | 21 +-- internal/dnsforward/upstreams.go | 21 --- internal/home/config.go | 14 +- internal/home/control.go | 14 +- internal/home/controlinstall.go | 31 ++-- internal/home/dns.go | 30 ++-- internal/home/home.go | 9 +- internal/home/options.go | 16 +- internal/home/options_test.go | 6 +- internal/home/web.go | 15 +- 23 files changed, 146 insertions(+), 640 deletions(-) delete mode 100644 internal/aghnet/systemresolvers.go delete mode 100644 internal/aghnet/systemresolvers_others.go delete mode 100644 internal/aghnet/systemresolvers_others_test.go delete mode 100644 internal/aghnet/systemresolvers_test.go delete mode 100644 internal/aghnet/systemresolvers_windows.go delete mode 100644 internal/aghnet/systemresolvers_windows_test.go diff --git a/go.mod b/go.mod index 21759345..395c7606 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/AdguardTeam/AdGuardHome go 1.20 require ( - github.com/AdguardTeam/dnsproxy v0.54.0 - github.com/AdguardTeam/golibs v0.15.0 + github.com/AdguardTeam/dnsproxy v0.56.0 + github.com/AdguardTeam/golibs v0.17.0 github.com/AdguardTeam/urlfilter v0.17.0 github.com/NYTimes/gziphandler v1.1.1 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 // own code for that. Perhaps, use gopacket. github.com/mdlayher/raw v0.1.0 - github.com/miekg/dns v1.1.55 - github.com/quic-go/quic-go v0.38.1 + github.com/miekg/dns v1.1.56 + github.com/quic-go/quic-go v0.39.0 github.com/stretchr/testify v1.8.4 github.com/ti-mo/netfilter v0.5.0 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/davecgh/go-spew v1.1.1 // 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-20230907193218-d3ddc7976beb // indirect + github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // 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/pierrec/lz4/v4 v4.1.18 // 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/qtls-go1-20 v0.3.4 // 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/sync v0.3.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index 6974d179..32869da1 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/AdguardTeam/dnsproxy v0.54.0 h1:OgSitM/EKrMMOi+guWZNwaU1cqRqJKWgR3l3fPWWayI= -github.com/AdguardTeam/dnsproxy v0.54.0/go.mod h1:tG/treaQekcKnugYoKOfm8vt3JGi6CliWta0MkQr15U= -github.com/AdguardTeam/golibs v0.15.0 h1:yOv/fdVkJIOWKr0NlUXAE9RA0DK9GKiBbiGzq47vY7o= -github.com/AdguardTeam/golibs v0.15.0/go.mod h1:66ZLs8P7nk/3IfKroQ1rqtieLk+5eXYXMBKXlVL7KeI= +github.com/AdguardTeam/dnsproxy v0.56.0 h1:kAg88woRTWTgqVEB2i2Uhze8Lv0JF1zTIAGhe0prjKM= +github.com/AdguardTeam/dnsproxy v0.56.0/go.mod h1:fqmehcE3cHFNqKbWQpIjGk7GqBy7ur1v5At499lFjRc= +github.com/AdguardTeam/golibs v0.17.0 h1:oPp2+2kV41qH45AIFbAlHFTPQOQ6JbF+JemjeECFn1g= +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/go.mod h1:bbuZjPUzm/Ip+nz5qPPbwIP+9rZyQbQad8Lt/0fCulU= 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-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/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/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= @@ -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/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 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-20230907193218-d3ddc7976beb/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= +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/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= 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.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI= 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.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= +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/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +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/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= @@ -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/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/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= -github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= +github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So= +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/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= 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/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/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 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/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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/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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= 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= @@ -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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= 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= @@ -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-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-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-20220209214540-3681064d5158/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/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-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.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= 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-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= 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= diff --git a/internal/aghnet/interfaces_linux.go b/internal/aghnet/interfaces_linux.go index 435084fb..c27e4244 100644 --- a/internal/aghnet/interfaces_linux.go +++ b/internal/aghnet/interfaces_linux.go @@ -12,12 +12,12 @@ import ( // listenPacketReusable announces on the local network address additionally // configuring the socket to have a reusable binding. func listenPacketReusable(ifaceName, network, address string) (c net.PacketConn, err error) { - var port int + var port uint16 _, port, err = netutil.SplitHostPort(address) if err != nil { return nil, err } // TODO(e.burkov): Inspect nclient4.NewRawUDPConn and implement here. - return nclient4.NewRawUDPConn(ifaceName, port) + return nclient4.NewRawUDPConn(ifaceName, int(port)) } diff --git a/internal/aghnet/net_test.go b/internal/aghnet/net_test.go index 70c38b04..2a77803b 100644 --- a/internal/aghnet/net_test.go +++ b/internal/aghnet/net_test.go @@ -2,6 +2,7 @@ package aghnet_test import ( "io/fs" + "net" "net/netip" "net/url" "os" @@ -64,7 +65,7 @@ ParseAddr("256.256.256.256"): IPv4 field has value >255`, want: netip.AddrPort{}, }, { 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" ParseAddr("1.2.3.4:-5"): unexpected character (at ":-5")`, want: netip.AddrPort{}, diff --git a/internal/aghnet/systemresolvers.go b/internal/aghnet/systemresolvers.go deleted file mode 100644 index 5ca8e9be..00000000 --- a/internal/aghnet/systemresolvers.go +++ /dev/null @@ -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 -} diff --git a/internal/aghnet/systemresolvers_others.go b/internal/aghnet/systemresolvers_others.go deleted file mode 100644 index a0bdf953..00000000 --- a/internal/aghnet/systemresolvers_others.go +++ /dev/null @@ -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() -} diff --git a/internal/aghnet/systemresolvers_others_test.go b/internal/aghnet/systemresolvers_others_test.go deleted file mode 100644 index 8bc506a8..00000000 --- a/internal/aghnet/systemresolvers_others_test.go +++ /dev/null @@ -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) - }) - } -} diff --git a/internal/aghnet/systemresolvers_test.go b/internal/aghnet/systemresolvers_test.go deleted file mode 100644 index 0a19490d..00000000 --- a/internal/aghnet/systemresolvers_test.go +++ /dev/null @@ -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. diff --git a/internal/aghnet/systemresolvers_windows.go b/internal/aghnet/systemresolvers_windows.go deleted file mode 100644 index 6fad70e4..00000000 --- a/internal/aghnet/systemresolvers_windows.go +++ /dev/null @@ -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 -} diff --git a/internal/aghnet/systemresolvers_windows_test.go b/internal/aghnet/systemresolvers_windows_test.go deleted file mode 100644 index 5b60bda7..00000000 --- a/internal/aghnet/systemresolvers_windows_test.go +++ /dev/null @@ -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. diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 31a7f271..c49698b6 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -436,18 +436,18 @@ func (conf *ServerConfig) collectDNSAddrs() ( // defaultPlainDNSPort is the default port for plain DNS. const defaultPlainDNSPort uint16 = 53 -// upstreamMatcher is a function that matches address of an upstream. -type upstreamMatcher func(addr netip.AddrPort) (ok bool) +// addrPortMatcher is a function that matches an IP address with port. +type addrPortMatcher func(addr netip.AddrPort) (ok bool) // filterOut filters out all the upstreams that match um. It returns all the // closing errors joined. -func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) { +func (m addrPortMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) { var errs []error delFunc := func(u upstream.Upstream) (ok bool) { // TODO(e.burkov): We should probably consider the protocol of u to // only filter out the listening addresses of the same protocol. 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 // does not match um. return false @@ -469,23 +469,21 @@ func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) { return errors.Join(errs...) } -// filterOurAddrs filters out all the upstreams that pointing to the local -// listening addresses to avoid recursive queries. upsConf may appear empty -// after the filtering. All the filtered upstreams are closed and these -// closings errors are joined. -func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err error) { +// ourAddrsMatcher returns a matcher that matches all the configured listening +// addresses. +func (conf *ServerConfig) ourAddrsMatcher() (m addrPortMatcher, err error) { addrs, unspecPorts := conf.collectDNSAddrs() if len(addrs) == 0 { 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 { 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] return ok @@ -495,12 +493,12 @@ func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err err ifaceAddrs, err = aghnet.CollectAllIfacesAddrs() if err != nil { // 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) - matcher = func(a netip.AddrPort) (ok bool) { + m = func(a netip.AddrPort) (ok bool) { if _, ok = unspecPorts[a.Port()]; ok { 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 diff --git a/internal/dnsforward/dnsforward.go b/internal/dnsforward/dnsforward.go index 098db5c4..6f0a9bbe 100644 --- a/internal/dnsforward/dnsforward.go +++ b/internal/dnsforward/dnsforward.go @@ -25,8 +25,10 @@ import ( "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/netutil" + "github.com/AdguardTeam/golibs/netutil/sysresolv" "github.com/AdguardTeam/golibs/stringutil" "github.com/miekg/dns" + "golang.org/x/exp/slices" ) // DefaultTimeout is the default upstream timeout @@ -72,6 +74,11 @@ type DHCP interface { 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. // // Example: @@ -126,7 +133,7 @@ type Server struct { // sysResolvers used to fetch system resolvers to use by default for private // PTR resolving. - sysResolvers aghnet.SystemResolvers + sysResolvers SystemResolvers // recDetector is a cache for recursive requests. It is used to detect // and prevent recursive requests only for private upstreams. @@ -225,9 +232,7 @@ func NewServer(p DNSCreateParams) (s *Server, err error) { anonymizer: p.Anonymizer, } - // TODO(e.burkov): Enable the refresher after the actual implementation - // passes the public testing. - s.sysResolvers, err = aghnet.NewSystemResolvers(nil) + s.sysResolvers, err = sysresolv.NewSystemResolvers(nil, defaultPlainDNSPort) if err != nil { 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 // internal use only. 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 resolvers := s.conf.LocalPTRResolvers + filterConfig := false if len(resolvers) == 0 { - resolvers = s.sysResolvers.Get() - bootstraps = nil + sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher) + resolvers = make([]string, 0, len(sysResolvers)) + for _, r := range sysResolvers { + resolvers = append(resolvers, r.String()) + } } else { resolvers = stringutil.FilterOut(resolvers, IsCommentOrEmpty) + filterConfig = true } 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, Timeout: defaultLocalTimeout, // 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) } + if filterConfig { + if err = matcher.filterOut(uc); err != nil { + return fmt.Errorf("filtering private upstreams: %w", err) + } + } + s.localResolvers = &proxy.Proxy{ Config: proxy.Config{ UpstreamConfig: uc, diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go index 70eaaca0..02432ce2 100644 --- a/internal/dnsforward/http.go +++ b/internal/dnsforward/http.go @@ -179,17 +179,16 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) { // defaultLocalPTRUpstreams returns the list of default local PTR resolvers // filtered of AdGuard Home's own DNS server addresses. It may appear empty. func (s *Server) defaultLocalPTRUpstreams() (ups []string, err error) { - s.serverLock.RLock() - defer s.serverLock.RUnlock() - - uc, err := s.prepareLocalUpstreamConfig(s.sysResolvers.Get(), nil, nil) + matcher, err := s.conf.ourAddrsMatcher() 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 { - ups = append(ups, u.Address()) + sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher) + ups = make([]string, 0, len(sysResolvers)) + for _, r := range sysResolvers { + ups = append(ups, r.String()) } return ups, nil @@ -228,7 +227,7 @@ func (req *jsonDNSConfig) checkBootstrap() (err error) { return errors.Error("empty") } - if _, err = upstream.NewResolver(b, nil); err != nil { + if _, err = upstream.NewUpstreamResolver(b, nil); err != nil { return err } } diff --git a/internal/dnsforward/http_test.go b/internal/dnsforward/http_test.go index 9f7faa8d..8524acc4 100644 --- a/internal/dnsforward/http_test.go +++ b/internal/dnsforward/http_test.go @@ -28,17 +28,12 @@ import ( "github.com/stretchr/testify/require" ) -// fakeSystemResolvers is a mock aghnet.SystemResolvers implementation for -// tests. -type fakeSystemResolvers struct { - // SystemResolvers is embedded here simply to make *fakeSystemResolvers - // an aghnet.SystemResolvers without actually implementing all methods. - aghnet.SystemResolvers -} +// emptySysResolvers is an empty [SystemResolvers] implementation that always +// returns nil. +type emptySysResolvers struct{} -// Get implements the aghnet.SystemResolvers interface for *fakeSystemResolvers. -// It always returns nil. -func (fsr *fakeSystemResolvers) Get() (rs []string) { +// Addrs implements the aghnet.SystemResolvers interface for emptySysResolvers. +func (emptySysResolvers) Addrs() (addrs []netip.AddrPort) { return nil } @@ -79,7 +74,7 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) { ConfigModified: func() {}, } s := createTestServer(t, filterConf, forwardConf, nil) - s.sysResolvers = &fakeSystemResolvers{} + s.sysResolvers = &emptySysResolvers{} require.NoError(t, s.Start()) testutil.CleanupAndRequireSuccess(t, s.Stop) @@ -156,7 +151,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) { ConfigModified: func() {}, } s := createTestServer(t, filterConf, forwardConf, nil) - s.sysResolvers = &fakeSystemResolvers{} + s.sysResolvers = &emptySysResolvers{} defaultConf := s.conf @@ -485,7 +480,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) { hostsListener := newLocalUpstreamListener(t, 0, goodHandler) hostsUps := (&url.URL{ Scheme: "tcp", - Host: netutil.JoinHostPort(upstreamHost, int(hostsListener.Port())), + Host: netutil.JoinHostPort(upstreamHost, hostsListener.Port()), }).String() hc, err := aghnet.NewHostsContainer( diff --git a/internal/dnsforward/upstreams.go b/internal/dnsforward/upstreams.go index dd1634b7..f30dce69 100644 --- a/internal/dnsforward/upstreams.go +++ b/internal/dnsforward/upstreams.go @@ -103,27 +103,6 @@ func (s *Server) prepareUpstreamConfig( 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 // versions based on the system hosts file. // diff --git a/internal/home/config.go b/internal/home/config.go index 96472168..e9514367 100644 --- a/internal/home/config.go +++ b/internal/home/config.go @@ -182,7 +182,7 @@ type httpPprofConfig struct { // not absolutely necessary. type dnsConfig struct { BindHosts []netip.Addr `yaml:"bind_hosts"` - Port int `yaml:"port"` + Port uint16 `yaml:"port"` // AnonymizeClientIP defines if clients' IP addresses should be anonymized // 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 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 - PortHTTPS int `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 - PortDNSOverQUIC int `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"` // DNS-over-QUIC port. If 0, DoQ will be disabled + PortHTTPS uint16 `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS 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 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, // 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 // set if PortDNSCrypt is not zero. // @@ -554,10 +554,10 @@ func validateConfig() (err error) { } // udpPort is the port number for UDP protocol. -type udpPort int +type udpPort uint16 // 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. func addPorts[T tcpPort | udpPort](uc aghalg.UniqChecker[T], ports ...T) { diff --git a/internal/home/control.go b/internal/home/control.go index 4a675e93..db0c2c5e 100644 --- a/internal/home/control.go +++ b/internal/home/control.go @@ -24,11 +24,9 @@ import ( // addresses to a slice of strings. func appendDNSAddrs(dst []string, addrs ...netip.Addr) (res []string) { for _, addr := range addrs { - var hostport string - if config.DNS.Port != defaultPortDNS { - hostport = netip.AddrPortFrom(addr, uint16(config.DNS.Port)).String() - } else { - hostport = addr.String() + hostport := addr.String() + if p := config.DNS.Port; p != defaultPortDNS { + hostport = netutil.JoinHostPort(hostport, p) } dst = append(dst, hostport) @@ -102,7 +100,7 @@ type statusResponse struct { Version string `json:"version"` Language string `json:"language"` DNSAddrs []string `json:"dns_addresses"` - DNSPort int `json:"dns_port"` + DNSPort uint16 `json:"dns_port"` HTTPPort uint16 `json:"http_port"` // ProtectionDisabledDuration is the duration of the protection pause in @@ -340,7 +338,7 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (proceed bool) var ( forceHTTPS bool serveHTTP3 bool - portHTTPS int + portHTTPS uint16 ) func() { 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 // 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 if portHTTPS != defaultPortHTTPS { hostPort = netutil.JoinHostPort(host, portHTTPS) diff --git a/internal/home/controlinstall.go b/internal/home/controlinstall.go index d6985eab..c36cc512 100644 --- a/internal/home/controlinstall.go +++ b/internal/home/controlinstall.go @@ -43,8 +43,8 @@ func (web *webAPI) handleInstallGetAddresses(w http.ResponseWriter, r *http.Requ data := getAddrsResponse{ Version: version.Version(), - WebPort: defaultPortHTTP, - DNSPort: defaultPortDNS, + WebPort: int(defaultPortHTTP), + DNSPort: int(defaultPortDNS), } ifaces, err := aghnet.GetValidNetInterfacesForWeb() @@ -64,7 +64,7 @@ func (web *webAPI) handleInstallGetAddresses(w http.ResponseWriter, r *http.Requ type checkConfReqEnt struct { IP netip.Addr `json:"ip"` - Port int `json:"port"` + Port uint16 `json:"port"` 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") }() // TODO(a.garipov): Declare all port variables anywhere as uint16. - reqPort := uint16(req.Web.Port) + reqPort := req.Web.Port port := tcpPort(reqPort) addPorts(tcpPorts, port) if err = tcpPorts.Validate(); err != nil { @@ -128,7 +128,7 @@ func (req *checkConfReq) validateDNS( ) (canAutofix bool, err error) { defer func() { err = errors.Annotate(err, "validating ports: %w") }() - port := uint16(req.DNS.Port) + port := req.DNS.Port switch port { case 0: return false, nil @@ -142,13 +142,13 @@ func (req *checkConfReq) validateDNS( 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 { 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) { return false, err } @@ -160,7 +160,7 @@ func (req *checkConfReq) validateDNS( 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 } @@ -305,7 +305,7 @@ func disableDNSStubListener() error { type applyConfigReqEnt struct { IP netip.Addr `json:"ip"` - Port int `json:"port"` + Port uint16 `json:"port"` } type applyConfigReq struct { @@ -395,14 +395,14 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request 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 { aghhttp.Error(r, w, http.StatusBadRequest, "%s", err) 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 { 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) 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.Port = req.DNS.Port @@ -445,8 +445,7 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request } web.conf.firstRun = false - web.conf.BindHost = req.Web.IP - web.conf.BindPort = req.Web.Port + web.conf.BindAddr = netip.AddrPortFrom(req.Web.IP, req.Web.Port) registerControlHandlers(web) @@ -487,9 +486,9 @@ func decodeApplyConfigReq(r io.Reader) (req *applyConfigReq, restartHTTP bool, e } 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 { - 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 { return nil, false, fmt.Errorf( "checking address %s:%d: %w", diff --git a/internal/home/dns.go b/internal/home/dns.go index 6ae34944..d26dd0d8 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -27,11 +27,11 @@ import ( // Default listening ports. const ( - defaultPortDNS = 53 - defaultPortHTTP = 80 - defaultPortHTTPS = 443 - defaultPortQUIC = 853 - defaultPortTLS = 853 + defaultPortDNS uint16 = 53 + defaultPortHTTP uint16 = 80 + defaultPortHTTPS uint16 = 443 + defaultPortQUIC uint16 = 853 + defaultPortTLS uint16 = 853 ) // Called by other modules when configuration is changed @@ -196,27 +196,27 @@ func isRunning() bool { 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 { return nil } tcpAddrs = make([]*net.TCPAddr, 0, len(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 } -func ipsToUDPAddrs(ips []netip.Addr, port int) (udpAddrs []*net.UDPAddr) { +func ipsToUDPAddrs(ips []netip.Addr, port uint16) (udpAddrs []*net.UDPAddr) { if ips == nil { return nil } udpAddrs = make([]*net.UDPAddr, 0, len(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 @@ -346,8 +346,8 @@ func getDNSEncryption() (de dnsEncryption) { hostname := tlsConf.ServerName if tlsConf.PortHTTPS != 0 { addr := hostname - if tlsConf.PortHTTPS != defaultPortHTTPS { - addr = netutil.JoinHostPort(addr, tlsConf.PortHTTPS) + if p := tlsConf.PortHTTPS; p != defaultPortHTTPS { + addr = netutil.JoinHostPort(addr, p) } de.https = (&url.URL{ @@ -357,17 +357,17 @@ func getDNSEncryption() (de dnsEncryption) { }).String() } - if tlsConf.PortDNSOverTLS != 0 { + if p := tlsConf.PortDNSOverTLS; p != 0 { de.tls = (&url.URL{ Scheme: "tls", - Host: netutil.JoinHostPort(hostname, tlsConf.PortDNSOverTLS), + Host: netutil.JoinHostPort(hostname, p), }).String() } - if tlsConf.PortDNSOverQUIC != 0 { + if p := tlsConf.PortDNSOverQUIC; p != 0 { de.quic = (&url.URL{ Scheme: "quic", - Host: netutil.JoinHostPort(hostname, tlsConf.PortDNSOverQUIC), + Host: netutil.JoinHostPort(hostname, p), }).String() } } diff --git a/internal/home/home.go b/internal/home/home.go index f166e3a3..7e57652e 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -329,7 +329,7 @@ func setupBindOpts(opts options) (err error) { if opts.bindPort != 0 { config.HTTPConfig.Address = netip.AddrPortFrom( config.HTTPConfig.Address.Addr(), - uint16(opts.bindPort), + opts.bindPort, ) err = checkPorts() @@ -497,8 +497,7 @@ func initWeb(opts options, clientBuildFS fs.FS, upd *updater.Updater) (web *webA clientFS: clientFS, - BindHost: config.HTTPConfig.Address.Addr(), - BindPort: int(config.HTTPConfig.Address.Port()), + BindAddr: config.HTTPConfig.Address, ReadTimeout: readTimeout, ReadHeaderTimeout: readHdrTimeout, @@ -853,7 +852,7 @@ func loadCmdLineOpts() (opts options) { // example: // // 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)) } @@ -865,7 +864,7 @@ func printHTTPAddresses(proto string) { Context.tls.WriteDiskConfig(&tlsConf) } - port := int(config.HTTPConfig.Address.Port()) + port := config.HTTPConfig.Address.Port() if proto == aghhttp.SchemeHTTPS { port = tlsConf.PortHTTPS } diff --git a/internal/home/options.go b/internal/home/options.go index e6e21c84..1bbf2752 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -42,7 +42,7 @@ type options struct { // bindPort is the port on which to serve the HTTP UI. // // Deprecated: Use bindAddr. - bindPort int + bindPort uint16 // bindAddr is the address to serve the web UI on. bindAddr netip.AddrPort @@ -160,15 +160,11 @@ var cmdLineOpts = []cmdLineOpt{{ shortName: "h", }, { updateWithValue: func(o options, v string) (options, error) { - var err error - var p int - minPort, maxPort := 0, 1<<16-1 - 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) + p, err := strconv.ParseUint(v, 10, 16) + if err != nil { + err = fmt.Errorf("parsing port: %w", err) } else { - o.bindPort = p + o.bindPort = uint16(p) } return o, err @@ -180,7 +176,7 @@ var cmdLineOpts = []cmdLineOpt{{ 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.", longName: "port", diff --git a/internal/home/options_test.go b/internal/home/options_test.go index f5dc1c75..dbcf02cc 100644 --- a/internal/home/options_test.go +++ b/internal/home/options_test.go @@ -67,11 +67,11 @@ func TestParseBindHost(t *testing.T) { } func TestParseBindPort(t *testing.T) { - assert.Equal(t, 0, testParseOK(t).bindPort, "empty is port 0") - assert.Equal(t, 65535, testParseOK(t, "-p", "65535").bindPort, "-p is port") + assert.Equal(t, uint16(0), testParseOK(t).bindPort, "empty is port 0") + assert.Equal(t, uint16(65535), testParseOK(t, "-p", "65535").bindPort, "-p is port") 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") testParseErr(t, "not an int", "-p", "x") diff --git a/internal/home/web.go b/internal/home/web.go index ac659a3f..da327c70 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -39,8 +39,8 @@ type webConfig struct { clientFS fs.FS - BindHost netip.Addr - BindPort int + // BindAddr is the binding address with port for plain HTTP web interface. + BindAddr netip.AddrPort // ReadTimeout is an option to pass to http.Server for setting an // appropriate field. @@ -125,12 +125,12 @@ func newWebAPI(conf *webConfig) (w *webAPI) { // available, unless the HTTPS server isn't active. // // 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 { 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 } @@ -185,10 +185,9 @@ func (web *webAPI) start() { hdlr := h2c.NewHandler(withMiddlewares(Context.mux, limitRequestBody), &http2.Server{}) // Create a new instance, because the Web is not usable after Shutdown. - hostStr := web.conf.BindHost.String() web.httpServer = &http.Server{ ErrorLog: log.StdLog("web: plain", log.DEBUG), - Addr: netutil.JoinHostPort(hostStr, web.conf.BindPort), + Addr: web.conf.BindAddr.String(), Handler: hdlr, ReadTimeout: web.conf.ReadTimeout, ReadHeaderTimeout: web.conf.ReadHeaderTimeout, @@ -249,7 +248,7 @@ func (web *webAPI) tlsServerLoop() { web.httpsServer.cond.L.Unlock() - var portHTTPS int + var portHTTPS uint16 func() { config.RLock() defer config.RUnlock() @@ -257,7 +256,7 @@ func (web *webAPI) tlsServerLoop() { 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{ ErrorLog: log.StdLog("web: https", log.DEBUG), Addr: addr,