diff --git a/Makefile b/Makefile index c4d29b18e..5f81aa9ba 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # Makefile. Bump this number every time a significant change is made to # this Makefile. # -# AdGuard-Project-Version: 5 +# AdGuard-Project-Version: 6 # Don't name these macros "GO" etc., because GNU Make apparently makes # them exported environment variables with the literal value of @@ -24,7 +24,8 @@ BRANCH = $$( git rev-parse --abbrev-ref HEAD ) DIST_DIR = build GOAMD64 = v1 GOPROXY = https://proxy.golang.org|direct -GOTOOLCHAIN = go1.22.5 +GOTOOLCHAIN = go1.22.6 +GOTELEMETRY = off OUT = dnsproxy RACE = 0 REVISION = $$( git rev-parse --short HEAD ) @@ -32,11 +33,11 @@ VERSION = 0 ENV = env\ BRANCH="$(BRANCH)"\ - COMMIT='$(COMMIT)'\ DIST_DIR='$(DIST_DIR)'\ GO="$(GO.MACRO)"\ GOAMD64='$(GOAMD64)'\ GOPROXY='$(GOPROXY)'\ + GOTELEMETRY='$(GOTELEMETRY)'\ GOTOOLCHAIN='$(GOTOOLCHAIN)'\ OUT='$(OUT)'\ PATH="$${PWD}/bin:$$( "$(GO.MACRO)" env GOPATH )/bin:$${PATH}"\ @@ -47,6 +48,11 @@ ENV = env\ # Keep the line above blank. +ENV_MISC = env\ + VERBOSE="$(VERBOSE.MACRO)"\ + +# Keep the line above blank. + # Keep this target first, so that a naked make invocation triggers a # full build. build: go-deps go-build @@ -55,13 +61,13 @@ init: ; git config core.hooksPath ./scripts/hooks test: go-test -go-build: ; $(ENV) "$(SHELL)" ./scripts/make/go-build.sh -go-deps: ; $(ENV) "$(SHELL)" ./scripts/make/go-deps.sh -go-lint: ; $(ENV) "$(SHELL)" ./scripts/make/go-lint.sh -go-test: ; $(ENV) RACE='1' "$(SHELL)" ./scripts/make/go-test.sh -go-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-tools.sh - -go-upd-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-upd-tools.sh +go-build: ; $(ENV) "$(SHELL)" ./scripts/make/go-build.sh +go-deps: ; $(ENV) "$(SHELL)" ./scripts/make/go-deps.sh +go-env: ; $(ENV) "$(GO.MACRO)" env +go-lint: ; $(ENV) "$(SHELL)" ./scripts/make/go-lint.sh +go-test: ; $(ENV) RACE='1' "$(SHELL)" ./scripts/make/go-test.sh +go-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-tools.sh +go-upd-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-upd-tools.sh go-check: go-tools go-lint go-test @@ -76,6 +82,9 @@ go-os-check: txt-lint: ; $(ENV) "$(SHELL)" ./scripts/make/txt-lint.sh +md-lint: ; $(ENV_MISC) "$(SHELL)" ./scripts/make/md-lint.sh +sh-lint: ; $(ENV_MISC) "$(SHELL)" ./scripts/make/sh-lint.sh + clean: ; $(ENV) $(GO.MACRO) clean && rm -f -r '$(DIST_DIR)' release: clean diff --git a/README.md b/README.md index 15cc62a21..c29624d07 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ Usage: dnsproxy [OPTIONS] Application Options: - --config-path= yaml configuration file. Minimal working configuration in config.yaml.dist. Options passed through command line will override the ones from this file. + --config-path= yaml configuration file. Minimal working configuration in config.yaml.dist. Options passed through command + line will override the ones from this file. -o, --output= Path to the log file. If not set, write to stdout. -c, --tls-crt= Path to a file with the certificate chain -k, --tls-key= Path to a file with the private key @@ -56,22 +57,29 @@ Application Options: --https-userinfo= If set, all DoH queries are required to have this basic authentication information. -g, --dnscrypt-config= Path to a file with DNSCrypt configuration. You can generate one using https://github.com/ameshkov/dnscrypt --edns-addr= Send EDNS Client Address - --upstream-mode= Defines the upstreams logic mode, possible values: load_balance, parallel, fastest_addr (default: load_balance) + --upstream-mode= Defines the upstreams logic mode, possible values: load_balance, parallel, fastest_addr (default: + load_balance) -l, --listen= Listening addresses -p, --port= Listening ports. Zero value disables TCP and UDP listeners -s, --https-port= Listening ports for DNS-over-HTTPS -t, --tls-port= Listening ports for DNS-over-TLS -q, --quic-port= Listening ports for DNS-over-QUIC -y, --dnscrypt-port= Listening ports for DNSCrypt - -u, --upstream= An upstream to be used (can be specified multiple times). You can also specify path to a file with the list of servers + -u, --upstream= An upstream to be used (can be specified multiple times). You can also specify path to a file with the + list of servers -b, --bootstrap= Bootstrap DNS for DoH and DoT, can be specified multiple times (default: use system-provided) - -f, --fallback= Fallback resolvers to use when regular ones are unavailable, can be specified multiple times. You can also specify path to a file with the list of servers + -f, --fallback= Fallback resolvers to use when regular ones are unavailable, can be specified multiple times. You can also + specify path to a file with the list of servers --private-rdns-upstream= Private DNS upstreams to use for reverse DNS lookups of private addresses, can be specified multiple times - --dns64-prefix= Prefix used to handle DNS64. If not specified, dnsproxy uses the 'Well-Known Prefix' 64:ff9b::. Can be specified multiple times + --dns64-prefix= Prefix used to handle DNS64. If not specified, dnsproxy uses the 'Well-Known Prefix' 64:ff9b::. Can be + specified multiple times --private-subnets= Private subnets to use for reverse DNS lookups of private addresses - --bogus-nxdomain= Transform the responses containing at least a single IP that matches specified addresses and CIDRs into NXDOMAIN. Can be specified multiple times. + --bogus-nxdomain= Transform the responses containing at least a single IP that matches specified addresses and CIDRs into + NXDOMAIN. Can be specified multiple times. + --hosts-files= List of paths to the hosts files relative to the root, can be specified multiple times --timeout= Timeout for outbound DNS queries to remote upstream servers in a human-readable form (default: 10s) - --cache-min-ttl= Minimum TTL value for DNS entries, in seconds. Capped at 3600. Artificially extending TTLs should only be done with careful consideration. + --cache-min-ttl= Minimum TTL value for DNS entries, in seconds. Capped at 3600. Artificially extending TTLs should only be + done with careful consideration. --cache-max-ttl= Maximum TTL value for DNS entries, in seconds. --cache-size= Cache size (in bytes). Default: 64k -r, --ratelimit= Ratelimit (requests per second) @@ -93,6 +101,7 @@ Application Options: --edns Use EDNS Client Subnet extension --dns64 If specified, dnsproxy will act as a DNS64 server --use-private-rdns If specified, use private upstreams for reverse DNS lookups of private addresses + --hosts-file-enabled= If specified, use hosts files for resolving (default: true) Help Options: -h, --help Show this help message diff --git a/bamboo-specs/bamboo.yaml b/bamboo-specs/bamboo.yaml index aee5b62ba..b77bdfdfc 100644 --- a/bamboo-specs/bamboo.yaml +++ b/bamboo-specs/bamboo.yaml @@ -10,11 +10,12 @@ # exact patch version as opposed to a minor one to make sure that this exact # version is actually used and not whatever the docker daemon on the CI has # cached a few months ago. - 'dockerGo': 'golang:1.22.5' + 'dockerGo': 'golang:1.22.6' 'maintainer': 'Adguard Go Team' 'name': 'dnsproxy' 'stages': +# TODO(e.burkov): Add separate lint stage for texts. - 'Lint': 'manual': false 'final': false diff --git a/go.mod b/go.mod index a09c4c2ef..b71655e23 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,21 @@ module github.com/AdguardTeam/dnsproxy -go 1.22.5 +go 1.22.6 require ( - github.com/AdguardTeam/golibs v0.25.2 + github.com/AdguardTeam/golibs v0.26.0 github.com/ameshkov/dnscrypt/v2 v2.2.7 github.com/ameshkov/dnsstamps v1.0.3 github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 github.com/bluele/gcache v0.0.2 - github.com/jessevdk/go-flags v1.5.0 + github.com/jessevdk/go-flags v1.6.1 github.com/miekg/dns v1.1.58 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/quic-go/quic-go v0.44.0 github.com/stretchr/testify v1.9.0 - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 - golang.org/x/net v0.27.0 - golang.org/x/sys v0.22.0 + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa + golang.org/x/net v0.28.0 + golang.org/x/sys v0.24.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -31,11 +31,11 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect gonum.org/v1/gonum v0.14.0 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 293afa948..dce68d906 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/AdguardTeam/golibs v0.25.2 h1:4+c9LjAIdd9trRk71hXghJ5OL/VRosBm+/0dKH+H39U= -github.com/AdguardTeam/golibs v0.25.2/go.mod h1:HaTyS2wCbxFudjht9N/+/Qf1b5cMad2BAYSwe7DPCXI= +github.com/AdguardTeam/golibs v0.26.0 h1:uLL0XggEjB+87lL1tPpEAQNoKAlHDq5AyBUVWEgf63E= +github.com/AdguardTeam/golibs v0.26.0/go.mod h1:iWdjXPCwmK2g2FKIb/OwEPnovSXeMqRhI8FWLxF5oxE= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw= @@ -26,8 +26,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20240130152714-0ed6a68c8d9e h1:E+3PBMCXn0ma79O7iCrne0iUpKtZ7rIcZvoz+jNtNtw= github.com/google/pprof v0.0.0-20240130152714-0ed6a68c8d9e/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -54,25 +54,24 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 9cbfce8b1..cefdb2a7f 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -49,12 +49,23 @@ func createProxyConfig( l *slog.Logger, options *Options, ) (conf *proxy.Config, err error) { - reqHdlr := handler.NewDefault(&handler.DefaultConfig{ + hostsFiles, err := options.hostsFiles(ctx, l) + if err != nil { + // Don't wrap the error since it's informative enough as is. + return nil, err + } + + reqHdlr, err := handler.NewDefault(&handler.DefaultConfig{ Logger: l.With(slogutil.KeyPrefix, "default_handler"), // TODO(e.burkov): Use the configured message constructor. MessageConstructor: dnsmsg.DefaultMessageConstructor{}, HaltIPv6: options.IPv6Disabled, + HostsFiles: hostsFiles, + FileSystem: osutil.RootDirFS(), }) + if err != nil { + return nil, fmt.Errorf("creating default handler: %w", err) + } conf = &proxy.Config{ Logger: l.With(slogutil.KeyPrefix, proxy.LogPrefix), @@ -141,7 +152,7 @@ func (opts *Options) initUpstreams( Logger: l, HTTPVersions: httpVersions, InsecureSkipVerify: opts.Insecure, - Timeout: timeout, + Timeout: timeout.Duration, } boot, err := initBootstrap(ctx, l, opts.BootstrapDNS, bootOpts) if err != nil { @@ -153,7 +164,7 @@ func (opts *Options) initUpstreams( HTTPVersions: httpVersions, InsecureSkipVerify: opts.Insecure, Bootstrap: boot, - Timeout: timeout, + Timeout: timeout.Duration, } upstreams := loadServersList(opts.Upstreams) @@ -166,7 +177,7 @@ func (opts *Options) initUpstreams( Logger: l, HTTPVersions: httpVersions, Bootstrap: boot, - Timeout: min(defaultLocalTimeout, timeout), + Timeout: min(defaultLocalTimeout, timeout.Duration), } privateUpstreams := loadServersList(opts.PrivateRDNSUpstreams) diff --git a/internal/cmd/options.go b/internal/cmd/options.go index 056c27bf7..194fa9866 100644 --- a/internal/cmd/options.go +++ b/internal/cmd/options.go @@ -1,12 +1,16 @@ package cmd import ( + "context" "fmt" + "log/slog" "os" + "strconv" "strings" "time" "github.com/AdguardTeam/dnsproxy/internal/version" + "github.com/AdguardTeam/golibs/hostsfile" "github.com/AdguardTeam/golibs/osutil" "github.com/AdguardTeam/golibs/timeutil" goFlags "github.com/jessevdk/go-flags" @@ -19,6 +23,42 @@ const ( argVersion = "--version" ) +// decodableBool is a boolean that can be unmarshaled from a flags. +// +// TODO(e.burkov): This is a workaround for go-flags, see +// https://github.com/AdguardTeam/dnsproxy/issues/182. +type decodableBool struct { + value bool +} + +// type check +var _ goFlags.Unmarshaler = (*decodableBool)(nil) + +// UnmarshalFlag implements the [goFlags.Unmarshaler] interface for +// *decodableBool. +func (b *decodableBool) UnmarshalFlag(text string) (err error) { + b.value, err = strconv.ParseBool(text) + + return err +} + +// decodableDuration is a duration that can be unmarshaled from a flags. +// +// TODO(e.burkov): This is a workaround for go-flags, see +// https://github.com/AdguardTeam/dnsproxy/issues/182. +type decodableDuration struct { + timeutil.Duration +} + +// type check +var _ goFlags.Unmarshaler = (*decodableDuration)(nil) + +// UnmarshalFlag implements the [goFlags.Unmarshaler] interface for +// *decodableDuration. +func (d *decodableDuration) UnmarshalFlag(text string) (err error) { + return d.UnmarshalText([]byte(text)) +} + // Options represents console arguments. For further additions, please do not // use the default option since it will cause some problems when config files // are used. @@ -105,9 +145,12 @@ type Options struct { // go-flags doesn't support text unmarshalers. BogusNXDomain []string `yaml:"bogus-nxdomain" long:"bogus-nxdomain" description:"Transform the responses containing at least a single IP that matches specified addresses and CIDRs into NXDOMAIN. Can be specified multiple times."` + // HostsFiles is the list of paths to the hosts files to resolve from. + HostsFiles []string `yaml:"hosts-files" long:"hosts-files" description:"List of paths to the hosts files relative to the root, can be specified multiple times"` + // Timeout for outbound DNS queries to remote upstream servers in a // human-readable form. Default is 10s. - Timeout timeutil.Duration `yaml:"timeout" long:"timeout" description:"Timeout for outbound DNS queries to remote upstream servers in a human-readable form" default:"10s"` + Timeout decodableDuration `yaml:"timeout" long:"timeout" description:"Timeout for outbound DNS queries to remote upstream servers in a human-readable form" default:"10s"` // CacheMinTTL is the minimum TTL value for caching DNS entries, in seconds. // It overrides the TTL value from the upstream server, if the one is less. @@ -186,6 +229,10 @@ type Options struct { // lookups of private addresses, including the requests for authority // records, such as SOA and NS. UsePrivateRDNS bool `yaml:"use-private-rdns" long:"use-private-rdns" description:"If specified, use private upstreams for reverse DNS lookups of private addresses" optional:"yes" optional-value:"true"` + + // HostsFileEnabled controls whether hosts files are used for resolving or + // not. + HostsFileEnabled decodableBool `yaml:"hosts-file-enabled" long:"hosts-file-enabled" description:"If specified, use hosts files for resolving" default:"true"` } // parseOptions returns options parsed from the command args or config file. @@ -229,3 +276,28 @@ func parseOptions() (opts *Options, exitCode int, err error) { return opts, osutil.ExitCodeSuccess, nil } + +// hostsFiles returns the list of hosts files to resolve from. It's empty if +// resolving from hosts files is disabled. +func (opts *Options) hostsFiles(ctx context.Context, l *slog.Logger) (paths []string, err error) { + if !opts.HostsFileEnabled.value { + l.DebugContext(ctx, "hosts files are disabled") + + return nil, nil + } + + l.DebugContext(ctx, "hosts files are enabled") + + if len(opts.HostsFiles) > 0 { + return opts.HostsFiles, nil + } + + paths, err = hostsfile.DefaultHostsPaths() + if err != nil { + return nil, fmt.Errorf("getting default hosts files: %w", err) + } + + l.DebugContext(ctx, "hosts files are not specified, using default", "paths", paths) + + return paths, nil +} diff --git a/internal/dnsmsg/constructor.go b/internal/dnsmsg/constructor.go index 1bbbe0c08..d533224cc 100644 --- a/internal/dnsmsg/constructor.go +++ b/internal/dnsmsg/constructor.go @@ -37,19 +37,19 @@ type DefaultMessageConstructor struct{} var _ MessageConstructor = DefaultMessageConstructor{} // NewMsgNXDOMAIN implements the [MessageConstructor] interface for -// defaultMessageConstructor. +// DefaultMessageConstructor. func (DefaultMessageConstructor) NewMsgNXDOMAIN(req *dns.Msg) (resp *dns.Msg) { return reply(req, dns.RcodeNameError) } // NewMsgSERVFAIL implements the [MessageConstructor] interface for -// defaultMessageConstructor. +// DefaultMessageConstructor. func (DefaultMessageConstructor) NewMsgSERVFAIL(req *dns.Msg) (resp *dns.Msg) { return reply(req, dns.RcodeServerFailure) } // NewMsgNOTIMPLEMENTED implements the [MessageConstructor] interface for -// defaultMessageConstructor. +// DefaultMessageConstructor. func (DefaultMessageConstructor) NewMsgNOTIMPLEMENTED(req *dns.Msg) (resp *dns.Msg) { resp = reply(req, dns.RcodeNotImplemented) @@ -68,7 +68,7 @@ func (DefaultMessageConstructor) NewMsgNOTIMPLEMENTED(req *dns.Msg) (resp *dns.M } // NewMsgNODATA implements the [MessageConstructor] interface for -// defaultMessageConstructor. +// DefaultMessageConstructor. func (DefaultMessageConstructor) NewMsgNODATA(req *dns.Msg) (resp *dns.Msg) { resp = reply(req, dns.RcodeSuccess) diff --git a/internal/handler/constructor.go b/internal/handler/constructor.go new file mode 100644 index 000000000..3e9d86180 --- /dev/null +++ b/internal/handler/constructor.go @@ -0,0 +1,131 @@ +package handler + +import ( + "net/netip" + + "github.com/AdguardTeam/dnsproxy/proxy" + "github.com/miekg/dns" +) + +// messageConstructor is an extension of the [proxy.MessageConstructor] +// interface that also provides methods for creating DNS responses. +type messageConstructor interface { + proxy.MessageConstructor + + // NewCompressedResponse creates a new compressed response message for req + // with the given response code. + NewCompressedResponse(req *dns.Msg, code int) (resp *dns.Msg) + + // NewPTRAnswer creates a new resource record for PTR response with the + // given FQDN and PTR domain. + NewPTRAnswer(fqdn, ptrDomain string) (ans *dns.PTR) + + // NewIPResponse creates a new A/AAAA response message for req with the + // given IP addresses. All IP addresses must be of the same family. + NewIPResponse(req *dns.Msg, ips []netip.Addr) (resp *dns.Msg) +} + +// defaultConstructor is a wrapper for [proxy.MessageConstructor] that also +// implements the [messageConstructor] interface. +// +// TODO(e.burkov): This implementation reflects the one from AdGuard Home, +// consider moving it to [golibs]. +type defaultConstructor struct { + proxy.MessageConstructor +} + +// type check +var _ messageConstructor = defaultConstructor{} + +// NewCompressedResponse implements the [messageConstructor] interface for +// defaultConstructor. +func (defaultConstructor) NewCompressedResponse(req *dns.Msg, code int) (resp *dns.Msg) { + resp = reply(req, code) + resp.Compress = true + + return resp +} + +// NewPTRAnswer implements the [messageConstructor] interface for +// [defaultConstructor]. +func (defaultConstructor) NewPTRAnswer(fqdn, ptrDomain string) (ans *dns.PTR) { + return &dns.PTR{ + Hdr: hdr(fqdn, dns.TypePTR), + Ptr: ptrDomain, + } +} + +// NewIPResponse implements the [messageConstructor] interface for +// [defaultConstructor] +func (c defaultConstructor) NewIPResponse(req *dns.Msg, ips []netip.Addr) (resp *dns.Msg) { + var ans []dns.RR + switch req.Question[0].Qtype { + case dns.TypeA: + ans = genAnswersWithIPv4s(req, ips) + case dns.TypeAAAA: + for _, ip := range ips { + if ip.Is6() { + ans = append(ans, newAnswerAAAA(req, ip)) + } + } + default: + // Go on and return an empty response. + } + + resp = c.NewCompressedResponse(req, dns.RcodeSuccess) + resp.Answer = ans + + return resp +} + +// defaultResponseTTL is the default TTL for the DNS responses in seconds. +const defaultResponseTTL = 10 + +// hdr creates a new DNS header with the given name and RR type. +func hdr(name string, rrType uint16) (h dns.RR_Header) { + return dns.RR_Header{ + Name: name, + Rrtype: rrType, + Ttl: defaultResponseTTL, + Class: dns.ClassINET, + } +} + +// reply creates a DNS response for req. +func reply(req *dns.Msg, code int) (resp *dns.Msg) { + resp = (&dns.Msg{}).SetRcode(req, code) + resp.RecursionAvailable = true + + return resp +} + +// newAnswerA creates a DNS A answer for req with the given IP address. +func newAnswerA(req *dns.Msg, ip netip.Addr) (ans *dns.A) { + return &dns.A{ + Hdr: hdr(req.Question[0].Name, dns.TypeA), + A: ip.AsSlice(), + } +} + +// newAnswerAAAA creates a DNS AAAA answer for req with the given IP address. +func newAnswerAAAA(req *dns.Msg, ip netip.Addr) (ans *dns.AAAA) { + return &dns.AAAA{ + Hdr: hdr(req.Question[0].Name, dns.TypeAAAA), + AAAA: ip.AsSlice(), + } +} + +// genAnswersWithIPv4s generates DNS A answers provided IPv4 addresses. If any +// of the IPs isn't an IPv4 address, genAnswersWithIPv4s logs a warning and +// returns nil, +func genAnswersWithIPv4s(req *dns.Msg, ips []netip.Addr) (ans []dns.RR) { + for _, ip := range ips { + if !ip.Is4() { + return nil + } + + ans = append(ans, newAnswerA(req, ip)) + } + + return ans +} diff --git a/internal/handler/default.go b/internal/handler/default.go index 545edcd17..b1883a8d2 100644 --- a/internal/handler/default.go +++ b/internal/handler/default.go @@ -4,19 +4,30 @@ package handler import ( "context" + "io/fs" "log/slog" "github.com/AdguardTeam/dnsproxy/proxy" - "github.com/miekg/dns" + "github.com/AdguardTeam/golibs/hostsfile" ) // DefaultConfig is the configuration for [Default]. type DefaultConfig struct { + // MessageConstructor constructs DNS messages. It must not be nil. + MessageConstructor proxy.MessageConstructor + + // FileSystem is the file system for reading files from. It must not be + // nil. + FileSystem fs.FS + // Logger is the logger. It must not be nil. Logger *slog.Logger - // MessageConstructor constructs DNS messages. It must not be nil. - MessageConstructor proxy.MessageConstructor + // HostsFiles is the list of paths to the hosts files. The hosts files + // aren't used if the list is empty. + // + // TODO(e.burkov): Consider passing just a [hostsfile.Storage]. + HostsFiles []string // HaltIPv6 halts the processing of AAAA requests and makes the handler // reply with NODATA to them. @@ -25,46 +36,51 @@ type DefaultConfig struct { // Default implements the default configurable [proxy.RequestHandler]. type Default struct { - logger *slog.Logger - messageConstructor proxy.MessageConstructor - isIPv6Halted bool + messages messageConstructor + hosts hostsfile.Storage + logger *slog.Logger + isIPv6Halted bool } // NewDefault creates a new [Default] handler. -func NewDefault(conf *DefaultConfig) (d *Default) { - return &Default{ - logger: conf.Logger, - isIPv6Halted: conf.HaltIPv6, - messageConstructor: conf.MessageConstructor, +func NewDefault(conf *DefaultConfig) (d *Default, err error) { + hosts, err := readHosts(conf.FileSystem, conf.HostsFiles) + if err != nil { + return nil, err + } + + mc, ok := conf.MessageConstructor.(messageConstructor) + if !ok { + mc = defaultConstructor{ + MessageConstructor: conf.MessageConstructor, + } } + + return &Default{ + logger: conf.Logger, + isIPv6Halted: conf.HaltIPv6, + messages: mc, + hosts: hosts, + }, nil } -// HandleRequest checks the IPv6 configuration for current session before -// resolving. -func (h Default) HandleRequest(p *proxy.Proxy, proxyCtx *proxy.DNSContext) (err error) { +// HandleRequest resolves the DNS request within proxyCtx. It only calls +// [proxy.Proxy.Resolve] if the request isn't handled by any of the internal +// handlers. +func (h *Default) HandleRequest(p *proxy.Proxy, proxyCtx *proxy.DNSContext) (err error) { // TODO(e.burkov): Use the [*context.Context] instead of // [*proxy.DNSContext] when the interface-based handler is implemented. ctx := context.TODO() + h.logger.DebugContext(ctx, "handling request", "req", &proxyCtx.Req.Question[0]) + if proxyCtx.Res = h.haltAAAA(ctx, proxyCtx.Req); proxyCtx.Res != nil { return nil } - return p.Resolve(proxyCtx) -} - -// haltAAAA halts the processing of AAAA requests if IPv6 is disabled. req must -// not be nil. -func (h *Default) haltAAAA(ctx context.Context, req *dns.Msg) (resp *dns.Msg) { - if h.isIPv6Halted && req.Question[0].Qtype == dns.TypeAAAA { - h.logger.DebugContext( - ctx, - "ipv6 is disabled; replying with empty response", - "req", req.Question[0].Name, - ) - - return h.messageConstructor.NewMsgNODATA(req) + if proxyCtx.Res = h.resolveFromHosts(ctx, proxyCtx.Req); proxyCtx.Res != nil { + return nil } - return nil + return p.Resolve(proxyCtx) } diff --git a/internal/handler/default_internal_test.go b/internal/handler/default_internal_test.go index 7f3b4789e..913e6b390 100644 --- a/internal/handler/default_internal_test.go +++ b/internal/handler/default_internal_test.go @@ -1,22 +1,41 @@ package handler import ( + "io/fs" + "net" + "net/netip" + "os" + "path" "testing" "time" + "github.com/AdguardTeam/dnsproxy/internal/dnsmsg" "github.com/AdguardTeam/dnsproxy/internal/dnsproxytest" + "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/logutil/slogutil" + "github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/testutil" "github.com/miekg/dns" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +// TODO(e.burkov): Remove when [hostsfile.DefaultStorage] stops using [log]. +func TestMain(m *testing.M) { + testutil.DiscardLogOutput(m) + + os.Exit(m.Run()) +} + // TODO(e.burkov): Add helpers to initialize [proxy.Proxy] to [dnsproxytest] // and rewrite the tests. // defaultTimeout is a default timeout for tests and contexts. const defaultTimeout = 1 * time.Second +// testdata is the file system for test data. +var testdata fs.FS = os.DirFS("testdata") + func TestDefault_haltAAAA(t *testing.T) { t.Parallel() @@ -33,11 +52,13 @@ func TestDefault_haltAAAA(t *testing.T) { t.Run("disabled", func(t *testing.T) { t.Parallel() - hdlr := NewDefault(&DefaultConfig{ + hdlr, err := NewDefault(&DefaultConfig{ Logger: slogutil.NewDiscardLogger(), MessageConstructor: messages, HaltIPv6: false, + FileSystem: testdata, }) + require.NoError(t, err) ctx := testutil.ContextWithTimeout(t, defaultTimeout) @@ -48,11 +69,13 @@ func TestDefault_haltAAAA(t *testing.T) { t.Run("enabled", func(t *testing.T) { t.Parallel() - hdlr := NewDefault(&DefaultConfig{ + hdlr, err := NewDefault(&DefaultConfig{ Logger: slogutil.NewDiscardLogger(), MessageConstructor: messages, HaltIPv6: true, + FileSystem: testdata, }) + require.NoError(t, err) ctx := testutil.ContextWithTimeout(t, defaultTimeout) @@ -60,3 +83,121 @@ func TestDefault_haltAAAA(t *testing.T) { assert.Equal(t, nodataResp, hdlr.haltAAAA(ctx, reqAAAA)) }) } + +func TestDefault_resolveFromHosts(t *testing.T) { + t.Parallel() + + // TODO(e.burkov): Use the one from [dnsproxytest]. + messages := dnsmsg.DefaultMessageConstructor{} + + hdlr, err := NewDefault(&DefaultConfig{ + MessageConstructor: messages, + FileSystem: testdata, + Logger: slogutil.NewDiscardLogger(), + HostsFiles: []string{path.Join(t.Name(), "hosts")}, + HaltIPv6: true, + }) + require.NoError(t, err) + + const ( + domainV4 = "ipv4.domain.example" + domainV6 = "ipv6.domain.example" + ) + + var ( + addrV4 = netip.MustParseAddr("1.2.3.4") + addrV6 = netip.MustParseAddr("2001:db8::1") + + reversedV4 = errors.Must(netutil.IPToReversedAddr(addrV4.AsSlice())) + reversedV6 = errors.Must(netutil.IPToReversedAddr(addrV6.AsSlice())) + unknownReversed = errors.Must(netutil.IPToReversedAddr(net.IP{4, 3, 2, 1})) + ) + + testCases := []struct { + wantAns dns.RR + req *dns.Msg + name string + }{{ + wantAns: &dns.A{ + Hdr: dns.RR_Header{ + Name: domainV4, + Rrtype: dns.TypeA, + Class: dns.ClassINET, + Ttl: 10, + }, + A: addrV4.AsSlice(), + }, + req: (&dns.Msg{}).SetQuestion(domainV4, dns.TypeA), + name: "success_a", + }, { + wantAns: &dns.AAAA{ + Hdr: dns.RR_Header{ + Name: domainV6, + Rrtype: dns.TypeAAAA, + Class: dns.ClassINET, + Ttl: 10, + }, + AAAA: addrV6.AsSlice(), + }, + req: (&dns.Msg{}).SetQuestion(domainV6, dns.TypeAAAA), + name: "success_aaaa", + }, { + wantAns: &dns.PTR{ + Hdr: dns.RR_Header{ + Name: reversedV4, + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: 10, + }, + Ptr: domainV4, + }, + req: (&dns.Msg{}).SetQuestion(reversedV4, dns.TypePTR), + name: "success_ptr_v4", + }, { + wantAns: &dns.PTR{ + Hdr: dns.RR_Header{ + Name: reversedV6, + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: 10, + }, + Ptr: domainV6, + }, + req: (&dns.Msg{}).SetQuestion(reversedV6, dns.TypePTR), + name: "success_ptr_v6", + }, { + wantAns: nil, + req: (&dns.Msg{}).SetQuestion("unknown.example", dns.TypeA), + name: "not_found_a", + }, { + wantAns: nil, + req: (&dns.Msg{}).SetQuestion("unknown.example", dns.TypeAAAA), + name: "not_found_aaaa", + }, { + wantAns: nil, + req: (&dns.Msg{}).SetQuestion(unknownReversed, dns.TypePTR), + name: "not_found_ptr", + }, { + wantAns: nil, + req: (&dns.Msg{}).SetQuestion("bad.ptr", dns.TypePTR), + name: "bad_ptr", + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ctx := testutil.ContextWithTimeout(t, defaultTimeout) + resp := hdlr.resolveFromHosts(ctx, tc.req) + if tc.wantAns == nil { + assert.Nil(t, resp) + + return + } + + require.NotNil(t, resp) + require.Len(t, resp.Answer, 1) + assert.Equal(t, tc.wantAns, resp.Answer[0]) + }) + } +} diff --git a/internal/handler/hosts.go b/internal/handler/hosts.go new file mode 100644 index 000000000..9eb840ab0 --- /dev/null +++ b/internal/handler/hosts.go @@ -0,0 +1,125 @@ +package handler + +import ( + "context" + "fmt" + "io/fs" + "net/netip" + "slices" + "strings" + + "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/hostsfile" + "github.com/AdguardTeam/golibs/logutil/slogutil" + "github.com/AdguardTeam/golibs/netutil" + "github.com/miekg/dns" +) + +// emptyStorage is a [hostsfile.Storage] that contains no records. +// +// TODO(e.burkov): Move to [hostsfile]. +type emptyStorage [0]hostsfile.Record + +// type check +var _ hostsfile.Storage = emptyStorage{} + +// ByAddr implements the [hostsfile.Storage] interface for [emptyStorage]. +func (emptyStorage) ByAddr(_ netip.Addr) (names []string) { + return nil +} + +// ByName implements the [hostsfile.Storage] interface for [emptyStorage]. +func (emptyStorage) ByName(_ string) (addrs []netip.Addr) { + return nil +} + +// readHosts reads the hosts files from the file system and returns a storage +// with parsed records. strg is always usable even if an error occurred. +func readHosts(fsys fs.FS, paths []string) (strg hostsfile.Storage, err error) { + // Don't check the error since it may only appear when any readers used. + defaultStrg, _ := hostsfile.NewDefaultStorage() + + var errs []error + for _, path := range paths { + err = readHostsFile(defaultStrg, fsys, path) + if err != nil { + // Don't wrap the error since it's informative enough as is. + errs = append(errs, err) + } + } + + // TODO(e.burkov): Add method for length. + isEmpty := true + defaultStrg.RangeAddrs(func(_ string, _ []netip.Addr) (cont bool) { + isEmpty = false + + return false + }) + + if isEmpty { + return emptyStorage{}, errors.Join(errs...) + } + + return defaultStrg, errors.Join(errs...) +} + +// readHostsFile reads the hosts file at path from fsys and parses it into strg. +func readHostsFile(strg *hostsfile.DefaultStorage, fsys fs.FS, path string) (err error) { + f, err := fsys.Open(path) + if err != nil { + // Don't wrap the error since it's informative enough as is. + return err + } + defer func() { err = errors.WithDeferred(err, f.Close()) }() + + err = hostsfile.Parse(strg, f, nil) + if err != nil { + return fmt.Errorf("parsing hosts file %q: %w", path, err) + } + + return nil +} + +// resolveFromHosts resolves the DNS query from the hosts file. It fills the +// response with the A, AAAA, and PTR records from the hosts file. +func (h *Default) resolveFromHosts(ctx context.Context, req *dns.Msg) (resp *dns.Msg) { + var addrs []netip.Addr + var ptrs []string + + q := req.Question[0] + name := strings.TrimSuffix(q.Name, ".") + switch q.Qtype { + case dns.TypeA: + addrs = slices.Clone(h.hosts.ByName(name)) + addrs = slices.DeleteFunc(addrs, netip.Addr.Is6) + case dns.TypeAAAA: + addrs = slices.Clone(h.hosts.ByName(name)) + addrs = slices.DeleteFunc(addrs, netip.Addr.Is4) + case dns.TypePTR: + addr, err := netutil.IPFromReversedAddr(name) + if err != nil { + h.logger.DebugContext(ctx, "failed parsing ptr", slogutil.KeyError, err) + + return nil + } + + ptrs = h.hosts.ByAddr(addr) + default: + return nil + } + + switch { + case len(addrs) > 0: + resp = h.messages.NewIPResponse(req, addrs) + case len(ptrs) > 0: + resp = h.messages.NewCompressedResponse(req, dns.RcodeSuccess) + name = req.Question[0].Name + for _, ptr := range ptrs { + resp.Answer = append(resp.Answer, h.messages.NewPTRAnswer(name, ptr)) + } + default: + h.logger.DebugContext(ctx, "no hosts records found", "name", name, "qtype", q.Qtype) + } + + return resp +} diff --git a/internal/handler/ipv6halt.go b/internal/handler/ipv6halt.go new file mode 100644 index 000000000..3d41ff675 --- /dev/null +++ b/internal/handler/ipv6halt.go @@ -0,0 +1,23 @@ +package handler + +import ( + "context" + + "github.com/miekg/dns" +) + +// haltAAAA halts the processing of AAAA requests if IPv6 is disabled. req must +// not be nil. +func (h *Default) haltAAAA(ctx context.Context, req *dns.Msg) (resp *dns.Msg) { + if h.isIPv6Halted && req.Question[0].Qtype == dns.TypeAAAA { + h.logger.DebugContext( + ctx, + "ipv6 is disabled; replying with empty response", + "req", req.Question[0].Name, + ) + + return h.messages.NewMsgNODATA(req) + } + + return nil +} diff --git a/internal/handler/testdata/TestDefault_resolveFromHosts/hosts b/internal/handler/testdata/TestDefault_resolveFromHosts/hosts new file mode 100644 index 000000000..9a081820b --- /dev/null +++ b/internal/handler/testdata/TestDefault_resolveFromHosts/hosts @@ -0,0 +1,3 @@ +1.2.3.4 ipv4.domain.example +2001:db8::1 ipv6.domain.example +# comment diff --git a/internal/tools/doc.go b/internal/tools/doc.go deleted file mode 100644 index 422b3fefe..000000000 --- a/internal/tools/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package tools and its main module are a nested internal module containing our -// development tool dependencies. -// -// See https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module. -package tools diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 728e9848d..58cea8c4f 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -1,6 +1,6 @@ module github.com/AdguardTeam/dnsproxy/internal/tools -go 1.22.5 +go 1.22.6 require ( github.com/fzipp/gocyclo v0.6.0 @@ -9,16 +9,16 @@ require ( github.com/kisielk/errcheck v1.7.0 github.com/kyoh86/looppointer v0.2.1 github.com/securego/gosec/v2 v2.20.0 - github.com/uudashr/gocognit v1.1.2 - golang.org/x/tools v0.22.0 - golang.org/x/vuln v1.1.2 - honnef.co/go/tools v0.4.7 - mvdan.cc/gofumpt v0.6.0 + github.com/uudashr/gocognit v1.1.3 + golang.org/x/tools v0.24.0 + golang.org/x/vuln v1.1.3 + honnef.co/go/tools v0.5.1 + mvdan.cc/gofumpt v0.7.0 mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f ) require ( - github.com/BurntSushi/toml v1.4.0 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect @@ -26,10 +26,10 @@ require ( github.com/kyoh86/nolint v0.0.1 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/telemetry v0.0.0-20240701175443-4e29c7872ac1 // indirect + golang.org/x/exp/typeparams v0.0.0-20240808152545-0cdaa3abc0fa // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/telemetry v0.0.0-20240815150606-0693e6240b9b // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 8f1876264..99eab8fc0 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -1,15 +1,15 @@ -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= @@ -50,69 +50,57 @@ github.com/securego/gosec/v2 v2.20.0 h1:z/d5qp1niWa2avgFyUIglYTYYuGq2LrJwNj1HRVX github.com/securego/gosec/v2 v2.20.0/go.mod h1:hkiArbBZLwK1cehBcg3oFWUlYPWTBffPwwJVWChu83o= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= -github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= +github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= +github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= -golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8 h1:+ZJmEdDFzH5H0CnzOrwgbH3elHctfTecW9X0k2tkn5M= -golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20240808152545-0cdaa3abc0fa h1:54T+HVkPu4D3lltpEHyI3Fs2pG/GqjGkXLgyKOmifXk= +golang.org/x/exp/typeparams v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240701175443-4e29c7872ac1 h1:jveUVYFLPlIma1aZBg9rrUN+Dqk4e6QbVSGiZGwA/2Y= -golang.org/x/telemetry v0.0.0-20240701175443-4e29c7872ac1/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240815150606-0693e6240b9b h1:bqoSGda4GdIdppjxRPd2mhhJDviKUBPMaBDIZeHi4Po= +golang.org/x/telemetry v0.0.0-20240815150606-0693e6240b9b/go.mod h1:m7R/r+o5h7UvF2JD9n2iLSGY4v8v+zNSyTJ6xynLrqs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/vuln v1.1.2 h1:UkLxe+kAMcrNBpGrFbU0Mc5l7cX97P2nhy21wx5+Qbk= -golang.org/x/vuln v1.1.2/go.mod h1:2o3fRKD8Uz9AraAL3lwd/grWBv+t+SeJnPcqBUJrY24= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= +golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= 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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -120,9 +108,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= -honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= -mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= -mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= +honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= +honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= +mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= +mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= diff --git a/internal/tools/tools.go b/internal/tools/tools.go index a1a473fff..ff1c2b137 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -1,5 +1,9 @@ //go:build tools +// Package tools and its main module are a nested internal module containing our +// development tool dependencies. +// +// See https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module. package tools import ( diff --git a/scripts/make/md-lint.sh b/scripts/make/md-lint.sh new file mode 100644 index 000000000..72e982081 --- /dev/null +++ b/scripts/make/md-lint.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# This comment is used to simplify checking local copies of the script. Bump +# this number every time a remarkable change is made to this script. +# +# AdGuard-Project-Version: 2 + +verbose="${VERBOSE:-0}" +readonly verbose + +set -e -f -u + +if [ "$verbose" -gt '0' ] +then + set -x +fi + +# NOTE: Adjust for your project. +# markdownlint\ +# ./README.md\ +# ; + +# TODO(e.burkov): Lint README.md. diff --git a/scripts/make/sh-lint.sh b/scripts/make/sh-lint.sh new file mode 100644 index 000000000..55d5afc0f --- /dev/null +++ b/scripts/make/sh-lint.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# This comment is used to simplify checking local copies of the script. Bump +# this number every time a remarkable change is made to this script. +# +# AdGuard-Project-Version: 2 + +verbose="${VERBOSE:-0}" +readonly verbose + +# Don't use -f, because we use globs in this script. +set -e -u + +if [ "$verbose" -gt '0' ] +then + set -x +fi + +# NOTE: Adjust for your project. +shellcheck -e 'SC2250' -f 'gcc' -o 'all' -x --\ + ./scripts/hooks/*\ + ./scripts/make/*\ + ;