From f893df7e642b1ee3dd29adddd028c123f8a0f73b Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 22 Dec 2020 13:39:50 +0100 Subject: [PATCH 01/35] Use a RWMutex instead of a Mutex for authosts --- internal/util/autohosts.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/util/autohosts.go b/internal/util/autohosts.go index ec2f3579e53..a9b4f7524b2 100644 --- a/internal/util/autohosts.go +++ b/internal/util/autohosts.go @@ -21,7 +21,7 @@ type onChangedT func() // AutoHosts - automatic DNS records type AutoHosts struct { // lock protects table and tableReverse. - lock sync.Mutex + lock sync.RWMutex // table is the host-to-IPs map. table map[string][]net.IP // tableReverse is the IP-to-hosts map. @@ -119,14 +119,14 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP { } var ipsCopy []net.IP - a.lock.Lock() + a.lock.RLock() if ips, ok := a.table[host]; ok { ipsCopy = make([]net.IP, len(ips)) copy(ipsCopy, ips) } - a.lock.Unlock() + a.lock.RUnlock() log.Debug("AutoHosts: answer: %s -> %v", host, ipsCopy) return ipsCopy @@ -145,8 +145,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) { ipStr := ipReal.String() - a.lock.Lock() - defer a.lock.Unlock() + a.lock.RLock() + defer a.lock.RUnlock() hosts = a.tableReverse[ipStr] @@ -161,8 +161,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) { // List returns an IP-to-hostnames table. It is safe for concurrent use. func (a *AutoHosts) List() (ipToHosts map[string][]string) { - a.lock.Lock() - defer a.lock.Unlock() + a.lock.RLock() + defer a.lock.RUnlock() ipToHosts = make(map[string][]string, len(a.tableReverse)) for k, v := range a.tableReverse { From 44168292d5f466b9e7cda271987f03363ab6d6a8 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 13:46:59 +0300 Subject: [PATCH 02/35] Pull request: 2662 dnscrypt logs Merge in DNS/adguard-home from 2662-dnscrypt-logs to master Closes #2662. Squashed commit of the following: commit 05f6742b5c73e1d150834965ae3a54ca06ef8e24 Author: Ainar Garipov Date: Thu Feb 11 12:58:08 2021 +0300 all: imp docs commit ee0b8c574c1cb5302a5ffb62d2fec4126509b2e8 Merge: aaa8c6b8 e64df20e Author: Ainar Garipov Date: Thu Feb 11 12:56:44 2021 +0300 Merge branch 'master' into 2662-dnscrypt-logs commit aaa8c6b8085679f4acd234527bd03cb0b2520b4f Author: Ainar Garipov Date: Thu Feb 11 12:38:49 2021 +0300 all: document changes commit 57b6a4d8e95e87d928274d095dc2004f1591d940 Author: Ainar Garipov Date: Thu Feb 11 12:36:22 2021 +0300 all: fix dnscrypt in logs --- CHANGELOG.md | 4 ++++ client/src/__locales/en.json | 3 ++- client/src/helpers/constants.js | 1 + internal/querylog/qlog.go | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f16494d9d3d..1b17ff8bfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,13 @@ and this project adheres to ### Fixed - Incorrect version tag in the Docker release ([#2663]). +- DNSCrypt queries weren't marked as such in logs ([#2662]). +[#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 + + ## [v0.105.0] - 2021-02-10 ### Added diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 697a7307442..b558dd60713 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -248,6 +248,7 @@ "custom_ip": "Custom IP", "blocking_ipv4": "Blocking IPv4", "blocking_ipv6": "Blocking IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", @@ -593,4 +594,4 @@ "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.", "client_not_in_allowed_clients": "The client is not allowed because it is not in the \"Allowed clients\" list.", "experimental": "Experimental" -} \ No newline at end of file +} diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index bab8c925f2c..0c9919ac3c5 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -534,6 +534,7 @@ export const BLOCK_ACTIONS = { }; export const SCHEME_TO_PROTOCOL_MAP = { + dnscrypt: 'dnscrypt', doh: 'dns_over_https', dot: 'dns_over_tls', doq: 'dns_over_quic', diff --git a/internal/querylog/qlog.go b/internal/querylog/qlog.go index 41ce98231e2..4726f075744 100644 --- a/internal/querylog/qlog.go +++ b/internal/querylog/qlog.go @@ -53,6 +53,7 @@ func NewClientProto(s string) (cp ClientProto, err error) { ClientProtoDOH, ClientProtoDOQ, ClientProtoDOT, + ClientProtoDNSCrypt, ClientProtoPlain: return cp, nil From f016ae172c640b55691c6701f9590766dd005c96 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 14:10:42 +0300 Subject: [PATCH 03/35] Pull request: home: inc req size for some apis Merge in DNS/adguard-home from 2666-req-body-lim to master Updates #2666. Squashed commit of the following: commit a525974aee54831963e3f95c8186d44f1752e9c7 Merge: 947703f3 44168292 Author: Ainar Garipov Date: Thu Feb 11 13:48:06 2021 +0300 Merge branch 'master' into 2666-req-body-lim commit 947703f36e1ee0ab08f938850f76824b7899d7e1 Author: Ainar Garipov Date: Thu Feb 11 13:28:54 2021 +0300 home: inc req size for some apis --- CHANGELOG.md | 7 +++++++ internal/home/middlewares.go | 12 +++++++++++- internal/home/web.go | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b17ff8bfc5..7560957b1c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,13 +17,20 @@ and this project adheres to ## [v0.105.1] - 2021-02-24 --> +### Changed + +- Increase the HTTP API request body size limit for the `/control/access/set` + API ([#2666]). + ### Fixed +- Set the request body size limit for HTTPS reqeusts as well. - Incorrect version tag in the Docker release ([#2663]). - DNSCrypt queries weren't marked as such in logs ([#2662]). [#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 +[#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 diff --git a/internal/home/middlewares.go b/internal/home/middlewares.go index d530ace87c5..7d34f73e946 100644 --- a/internal/home/middlewares.go +++ b/internal/home/middlewares.go @@ -30,7 +30,17 @@ const RequestBodySizeLimit = 64 * 1024 func limitRequestBody(h http.Handler) (limited http.Handler) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var err error - r.Body, err = aghio.LimitReadCloser(r.Body, RequestBodySizeLimit) + + var bodySizeLimit int64 = RequestBodySizeLimit + if u := r.URL; u.Path == "/control/access/set" { + // An exception for a poorly designed API. Remove once + // the new, better API is up. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2666. + bodySizeLimit *= 4 + } + + r.Body, err = aghio.LimitReadCloser(r.Body, bodySizeLimit) if err != nil { log.Error("limitRequestBody: %s", err) diff --git a/internal/home/web.go b/internal/home/web.go index 0048f42755a..cdd19aba455 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -259,7 +259,7 @@ func (web *Web) tlsServerLoop() { RootCAs: Context.tlsRoots, CipherSuites: Context.tlsCiphers, }, - Handler: Context.mux, + Handler: withMiddlewares(Context.mux, limitRequestBody), ReadTimeout: web.conf.ReadTimeout, ReadHeaderTimeout: web.conf.ReadHeaderTimeout, WriteTimeout: web.conf.WriteTimeout, From 841bb9bc35786c710414706ef38c2830024fbfed Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 15:20:30 +0300 Subject: [PATCH 04/35] Pull request: dnsforward: do not check client srv name unless asked Merge in DNS/adguard-home from 2664-non-strict-sni to master Updates #2664. Squashed commit of the following: commit e8d625fe3b1f06f97328809a3330b37e5bd578d7 Author: Ainar Garipov Date: Thu Feb 11 14:46:52 2021 +0300 all: imp doc commit 10537b8bdf126eca9608353e57d92edba632232a Author: Ainar Garipov Date: Thu Feb 11 14:30:25 2021 +0300 dnsforward: do not check client srv name unless asked --- CHANGELOG.md | 9 +- internal/dnsforward/clientid.go | 165 ++++++++++++++++++ .../{dns_test.go => clientid_test.go} | 80 ++++++--- internal/dnsforward/dns.go | 152 ---------------- 4 files changed, 230 insertions(+), 176 deletions(-) create mode 100644 internal/dnsforward/clientid.go rename internal/dnsforward/{dns_test.go => clientid_test.go} (73%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7560957b1c7..bfae45f13b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,17 +19,20 @@ and this project adheres to ### Changed -- Increase the HTTP API request body size limit for the `/control/access/set` - API ([#2666]). +- The server name sent by clients of TLS APIs is not only checked when + `strict_sni_check` is enabled ([#2664]). +- HTTP API request body size limit for the `/control/access/set` API is + increased ([#2666]). ### Fixed -- Set the request body size limit for HTTPS reqeusts as well. +- The request body size limit is now set for HTTPS requests as well. - Incorrect version tag in the Docker release ([#2663]). - DNSCrypt queries weren't marked as such in logs ([#2662]). [#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 +[#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 [#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 diff --git a/internal/dnsforward/clientid.go b/internal/dnsforward/clientid.go new file mode 100644 index 00000000000..c497c7b7fb9 --- /dev/null +++ b/internal/dnsforward/clientid.go @@ -0,0 +1,165 @@ +package dnsforward + +import ( + "crypto/tls" + "fmt" + "path" + "strings" + + "github.com/AdguardTeam/dnsproxy/proxy" + "github.com/lucas-clemente/quic-go" +) + +const maxDomainPartLen = 64 + +// ValidateClientID returns an error if clientID is not a valid client ID. +func ValidateClientID(clientID string) (err error) { + if len(clientID) > maxDomainPartLen { + return fmt.Errorf("client id %q is too long, max: %d", clientID, maxDomainPartLen) + } + + for i, r := range clientID { + if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' { + continue + } + + return fmt.Errorf("invalid char %q at index %d in client id %q", r, i, clientID) + } + + return nil +} + +// clientIDFromClientServerName extracts and validates a client ID. hostSrvName +// is the server name of the host. cliSrvName is the server name as sent by the +// client. When strict is true, and client and host server name don't match, +// clientIDFromClientServerName will return an error. +func clientIDFromClientServerName(hostSrvName, cliSrvName string, strict bool) (clientID string, err error) { + if hostSrvName == cliSrvName { + return "", nil + } + + if !strings.HasSuffix(cliSrvName, hostSrvName) { + if !strict { + return "", nil + } + + return "", fmt.Errorf("client server name %q doesn't match host server name %q", cliSrvName, hostSrvName) + } + + clientID = cliSrvName[:len(cliSrvName)-len(hostSrvName)-1] + err = ValidateClientID(clientID) + if err != nil { + return "", fmt.Errorf("invalid client id: %w", err) + } + + return clientID, nil +} + +// processClientIDHTTPS extracts the client's ID from the path of the +// client's DNS-over-HTTPS request. +func processClientIDHTTPS(ctx *dnsContext) (rc resultCode) { + pctx := ctx.proxyCtx + r := pctx.HTTPRequest + if r == nil { + ctx.err = fmt.Errorf("proxy ctx http request of proto %s is nil", pctx.Proto) + + return resultCodeError + } + + origPath := r.URL.Path + parts := strings.Split(path.Clean(origPath), "/") + if parts[0] == "" { + parts = parts[1:] + } + + if len(parts) == 0 || parts[0] != "dns-query" { + ctx.err = fmt.Errorf("client id check: invalid path %q", origPath) + + return resultCodeError + } + + clientID := "" + switch len(parts) { + case 1: + // Just /dns-query, no client ID. + return resultCodeSuccess + case 2: + clientID = parts[1] + default: + ctx.err = fmt.Errorf("client id check: invalid path %q: extra parts", origPath) + + return resultCodeError + } + + err := ValidateClientID(clientID) + if err != nil { + ctx.err = fmt.Errorf("client id check: invalid client id: %w", err) + + return resultCodeError + } + + ctx.clientID = clientID + + return resultCodeSuccess +} + +// tlsConn is a narrow interface for *tls.Conn to simplify testing. +type tlsConn interface { + ConnectionState() (cs tls.ConnectionState) +} + +// quicSession is a narrow interface for quic.Session to simplify testing. +type quicSession interface { + ConnectionState() (cs quic.ConnectionState) +} + +// processClientID extracts the client's ID from the server name of the client's +// DOT or DOQ request or the path of the client's DOH. +func processClientID(dctx *dnsContext) (rc resultCode) { + pctx := dctx.proxyCtx + proto := pctx.Proto + if proto == proxy.ProtoHTTPS { + return processClientIDHTTPS(dctx) + } else if proto != proxy.ProtoTLS && proto != proxy.ProtoQUIC { + return resultCodeSuccess + } + + srvConf := dctx.srv.conf + hostSrvName := srvConf.TLSConfig.ServerName + if hostSrvName == "" { + return resultCodeSuccess + } + + cliSrvName := "" + if proto == proxy.ProtoTLS { + conn := pctx.Conn + tc, ok := conn.(tlsConn) + if !ok { + dctx.err = fmt.Errorf("proxy ctx conn of proto %s is %T, want *tls.Conn", proto, conn) + + return resultCodeError + } + + cliSrvName = tc.ConnectionState().ServerName + } else if proto == proxy.ProtoQUIC { + qs, ok := pctx.QUICSession.(quicSession) + if !ok { + dctx.err = fmt.Errorf("proxy ctx quic session of proto %s is %T, want quic.Session", proto, pctx.QUICSession) + + return resultCodeError + } + + cliSrvName = qs.ConnectionState().ServerName + } + + clientID, err := clientIDFromClientServerName(hostSrvName, cliSrvName, srvConf.StrictSNICheck) + if err != nil { + dctx.err = fmt.Errorf("client id check: %w", err) + + return resultCodeError + } + + dctx.clientID = clientID + + return resultCodeSuccess +} diff --git a/internal/dnsforward/dns_test.go b/internal/dnsforward/clientid_test.go similarity index 73% rename from internal/dnsforward/dns_test.go rename to internal/dnsforward/clientid_test.go index bd0ef4ab686..503203f9737 100644 --- a/internal/dnsforward/dns_test.go +++ b/internal/dnsforward/clientid_test.go @@ -10,6 +10,7 @@ import ( "github.com/AdguardTeam/dnsproxy/proxy" "github.com/lucas-clemente/quic-go" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // testTLSConn is a tlsConn for tests. @@ -53,6 +54,7 @@ func TestProcessClientID(t *testing.T) { wantClientID string wantErrMsg string wantRes resultCode + strictSNI bool }{{ name: "udp", proto: proxy.ProtoUDP, @@ -61,6 +63,7 @@ func TestProcessClientID(t *testing.T) { wantClientID: "", wantErrMsg: "", wantRes: resultCodeSuccess, + strictSNI: false, }, { name: "tls_no_client_id", proto: proxy.ProtoTLS, @@ -69,6 +72,26 @@ func TestProcessClientID(t *testing.T) { wantClientID: "", wantErrMsg: "", wantRes: resultCodeSuccess, + strictSNI: true, + }, { + name: "tls_no_client_server_name", + proto: proxy.ProtoTLS, + hostSrvName: "example.com", + cliSrvName: "", + wantClientID: "", + wantErrMsg: `client id check: client server name "" ` + + `doesn't match host server name "example.com"`, + wantRes: resultCodeError, + strictSNI: true, + }, { + name: "tls_no_client_server_name_no_strict", + proto: proxy.ProtoTLS, + hostSrvName: "example.com", + cliSrvName: "", + wantClientID: "", + wantErrMsg: "", + wantRes: resultCodeSuccess, + strictSNI: false, }, { name: "tls_client_id", proto: proxy.ProtoTLS, @@ -77,30 +100,39 @@ func TestProcessClientID(t *testing.T) { wantClientID: "cli", wantErrMsg: "", wantRes: resultCodeSuccess, + strictSNI: true, }, { name: "tls_client_id_hostname_error", proto: proxy.ProtoTLS, hostSrvName: "example.com", cliSrvName: "cli.example.net", wantClientID: "", - wantErrMsg: `client id check: client server name "cli.example.net" doesn't match host server name "example.com"`, - wantRes: resultCodeError, + wantErrMsg: `client id check: client server name "cli.example.net" ` + + `doesn't match host server name "example.com"`, + wantRes: resultCodeError, + strictSNI: true, }, { name: "tls_invalid_client_id", proto: proxy.ProtoTLS, hostSrvName: "example.com", cliSrvName: "!!!.example.com", wantClientID: "", - wantErrMsg: `client id check: invalid client id: invalid char '!' at index 0 in client id "!!!"`, - wantRes: resultCodeError, + wantErrMsg: `client id check: invalid client id: invalid char '!' ` + + `at index 0 in client id "!!!"`, + wantRes: resultCodeError, + strictSNI: true, }, { - name: "tls_client_id_too_long", - proto: proxy.ProtoTLS, - hostSrvName: "example.com", - cliSrvName: "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789.example.com", + name: "tls_client_id_too_long", + proto: proxy.ProtoTLS, + hostSrvName: "example.com", + cliSrvName: `abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmno` + + `pqrstuvwxyz0123456789.example.com`, wantClientID: "", - wantErrMsg: `client id check: invalid client id: client id "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" is too long, max: 64`, - wantRes: resultCodeError, + wantErrMsg: `client id check: invalid client id: client id "abcdefghijklmno` + + `pqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789" ` + + `is too long, max: 64`, + wantRes: resultCodeError, + strictSNI: true, }, { name: "quic_client_id", proto: proxy.ProtoQUIC, @@ -109,14 +141,17 @@ func TestProcessClientID(t *testing.T) { wantClientID: "cli", wantErrMsg: "", wantRes: resultCodeSuccess, + strictSNI: true, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + tlsConf := TLSConfig{ + ServerName: tc.hostSrvName, + StrictSNICheck: tc.strictSNI, + } srv := &Server{ - conf: ServerConfig{ - TLSConfig: TLSConfig{ServerName: tc.hostSrvName}, - }, + conf: ServerConfig{TLSConfig: tlsConf}, } var conn net.Conn @@ -146,10 +181,11 @@ func TestProcessClientID(t *testing.T) { assert.Equal(t, tc.wantRes, res) assert.Equal(t, tc.wantClientID, dctx.clientID) - if tc.wantErrMsg != "" && assert.NotNil(t, dctx.err) { - assert.Equal(t, tc.wantErrMsg, dctx.err.Error()) - } else { + if tc.wantErrMsg == "" { assert.Nil(t, dctx.err) + } else { + require.NotNil(t, dctx.err) + assert.Equal(t, tc.wantErrMsg, dctx.err.Error()) } }) } @@ -202,8 +238,9 @@ func TestProcessClientID_https(t *testing.T) { name: "invalid_client_id", path: "/dns-query/!!!", wantClientID: "", - wantErrMsg: `client id check: invalid client id: invalid char '!' at index 0 in client id "!!!"`, - wantRes: resultCodeError, + wantErrMsg: `client id check: invalid client id: invalid char '!'` + + ` at index 0 in client id "!!!"`, + wantRes: resultCodeError, }} for _, tc := range testCases { @@ -225,10 +262,11 @@ func TestProcessClientID_https(t *testing.T) { assert.Equal(t, tc.wantRes, res) assert.Equal(t, tc.wantClientID, dctx.clientID) - if tc.wantErrMsg != "" && assert.NotNil(t, dctx.err) { - assert.Equal(t, tc.wantErrMsg, dctx.err.Error()) - } else { + if tc.wantErrMsg == "" { assert.Nil(t, dctx.err) + } else { + require.NotNil(t, dctx.err) + assert.Equal(t, tc.wantErrMsg, dctx.err.Error()) } }) } diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index f8e7bff06e6..acc6aa8614c 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -1,10 +1,7 @@ package dnsforward import ( - "crypto/tls" - "fmt" "net" - "path" "strings" "time" @@ -13,7 +10,6 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/golibs/log" - "github.com/lucas-clemente/quic-go" "github.com/miekg/dns" ) @@ -234,154 +230,6 @@ func processInternalHosts(ctx *dnsContext) (rc resultCode) { return resultCodeSuccess } -const maxDomainPartLen = 64 - -// ValidateClientID returns an error if clientID is not a valid client ID. -func ValidateClientID(clientID string) (err error) { - if len(clientID) > maxDomainPartLen { - return fmt.Errorf("client id %q is too long, max: %d", clientID, maxDomainPartLen) - } - - for i, r := range clientID { - if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' { - continue - } - - return fmt.Errorf("invalid char %q at index %d in client id %q", r, i, clientID) - } - - return nil -} - -// clientIDFromClientServerName extracts and validates a client ID. hostSrvName -// is the server name of the host. cliSrvName is the server name as sent by the -// client. -func clientIDFromClientServerName(hostSrvName, cliSrvName string) (clientID string, err error) { - if hostSrvName == cliSrvName { - return "", nil - } - - if !strings.HasSuffix(cliSrvName, hostSrvName) { - return "", fmt.Errorf("client server name %q doesn't match host server name %q", cliSrvName, hostSrvName) - } - - clientID = cliSrvName[:len(cliSrvName)-len(hostSrvName)-1] - err = ValidateClientID(clientID) - if err != nil { - return "", fmt.Errorf("invalid client id: %w", err) - } - - return clientID, nil -} - -// processClientIDHTTPS extracts the client's ID from the path of the -// client's DNS-over-HTTPS request. -func processClientIDHTTPS(ctx *dnsContext) (rc resultCode) { - pctx := ctx.proxyCtx - r := pctx.HTTPRequest - if r == nil { - ctx.err = fmt.Errorf("proxy ctx http request of proto %s is nil", pctx.Proto) - - return resultCodeError - } - - origPath := r.URL.Path - parts := strings.Split(path.Clean(origPath), "/") - if parts[0] == "" { - parts = parts[1:] - } - - if len(parts) == 0 || parts[0] != "dns-query" { - ctx.err = fmt.Errorf("client id check: invalid path %q", origPath) - - return resultCodeError - } - - clientID := "" - switch len(parts) { - case 1: - // Just /dns-query, no client ID. - return resultCodeSuccess - case 2: - clientID = parts[1] - default: - ctx.err = fmt.Errorf("client id check: invalid path %q: extra parts", origPath) - - return resultCodeError - } - - err := ValidateClientID(clientID) - if err != nil { - ctx.err = fmt.Errorf("client id check: invalid client id: %w", err) - - return resultCodeError - } - - ctx.clientID = clientID - - return resultCodeSuccess -} - -// tlsConn is a narrow interface for *tls.Conn to simplify testing. -type tlsConn interface { - ConnectionState() (cs tls.ConnectionState) -} - -// quicSession is a narrow interface for quic.Session to simplify testing. -type quicSession interface { - ConnectionState() (cs quic.ConnectionState) -} - -// processClientID extracts the client's ID from the server name of the client's -// DOT or DOQ request or the path of the client's DOH. -func processClientID(ctx *dnsContext) (rc resultCode) { - pctx := ctx.proxyCtx - proto := pctx.Proto - if proto == proxy.ProtoHTTPS { - return processClientIDHTTPS(ctx) - } else if proto != proxy.ProtoTLS && proto != proxy.ProtoQUIC { - return resultCodeSuccess - } - - hostSrvName := ctx.srv.conf.TLSConfig.ServerName - if hostSrvName == "" { - return resultCodeSuccess - } - - cliSrvName := "" - if proto == proxy.ProtoTLS { - conn := pctx.Conn - tc, ok := conn.(tlsConn) - if !ok { - ctx.err = fmt.Errorf("proxy ctx conn of proto %s is %T, want *tls.Conn", proto, conn) - - return resultCodeError - } - - cliSrvName = tc.ConnectionState().ServerName - } else if proto == proxy.ProtoQUIC { - qs, ok := pctx.QUICSession.(quicSession) - if !ok { - ctx.err = fmt.Errorf("proxy ctx quic session of proto %s is %T, want quic.Session", proto, pctx.QUICSession) - - return resultCodeError - } - - cliSrvName = qs.ConnectionState().ServerName - } - - clientID, err := clientIDFromClientServerName(hostSrvName, cliSrvName) - if err != nil { - ctx.err = fmt.Errorf("client id check: %w", err) - - return resultCodeError - } - - ctx.clientID = clientID - - return resultCodeSuccess -} - // Respond to PTR requests if the target IP address is leased by our DHCP server func processInternalIPAddrs(ctx *dnsContext) (rc resultCode) { s := ctx.srv From 7e085652123eace8209bb3037874a98ef62c9331 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 15:41:03 +0300 Subject: [PATCH 05/35] Pull request: openapi: doc client id better Merge in DNS/adguard-home from doc-client-id to master Squashed commit of the following: commit ea03887d505296e5033964e8227ed906b102d990 Merge: 693453b5 841bb9bc Author: Ainar Garipov Date: Thu Feb 11 15:20:56 2021 +0300 Merge branch 'master' into doc-client-id commit 693453b5eab40e201501d6881418ee42191a1bc5 Author: Ainar Garipov Date: Thu Feb 11 12:55:01 2021 +0300 openapi: doc client id better --- openapi/CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openapi/CHANGELOG.md b/openapi/CHANGELOG.md index fab1099ebc1..7cbc626b351 100644 --- a/openapi/CHANGELOG.md +++ b/openapi/CHANGELOG.md @@ -4,6 +4,12 @@ ## v0.105: API changes +### New `"client_id"` field in `GET /querylog` response + +* The new field `"client_id"` of `QueryLogItem` objects is the ID sent by the + client for encrypted requests, if there was any. See the + "[Identifying clients]" section of our wiki. + ### New `"dnscrypt"` `"client_proto"` value in `GET /querylog` response * The field `"client_proto"` can now have the value `"dnscrypt"` when the @@ -69,6 +75,8 @@ As well as other documentation fixes. +[Identifying clients]: https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#idclient + ## v0.103: API changes ### API: replace settings in GET /control/dns_info & POST /control/dns_config From 7dd2d0af964fe820748ff935612187b50ea6ea6f Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 16:32:27 +0300 Subject: [PATCH 06/35] Pull request: all: doc make -j in readme Merge in DNS/adguard-home from 2668-doc-make-j to master Updates #2668. Squashed commit of the following: commit b52c2a18c46f8a6e5badf9db104c04a10765e96d Author: Ainar Garipov Date: Thu Feb 11 16:21:54 2021 +0300 all: doc make -j in readme --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 519119e91b1..f9ee5dae307 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ It depends. "DNS sinkholing" is capable of blocking a big percentage of ads, but it lacks flexibility and power of traditional ad blockers. You can get a good impression about the difference between these methods by reading [this article](https://adguard.com/en/blog/adguard-vs-adaway-dns66/). It compares AdGuard for Android (a traditional ad blocker) to hosts-level ad blockers (which are almost identical to DNS-based blockers in their capabilities). -However, this level of protection is enough for some users. Additionally, using a DNS-based blocker can help to block ads, tracking and analytics requests on other types of devices, such as SmartTVs, smart speakers or other kinds of IoT devices (on which you can't install tradtional ad blockers). +However, this level of protection is enough for some users. Additionally, using a DNS-based blocker can help to block ads, tracking and analytics requests on other types of devices, such as SmartTVs, smart speakers or other kinds of IoT devices (on which you can't install traditional ad blockers). **Known limitations** @@ -192,6 +192,12 @@ cd AdGuardHome make ``` +Please note, that the non-standard `-j` flag is currently not supported, so +building with `make -j 4` or setting your `MAKEFLAGS` to include, for example, +`-j 4` is likely to break the build. If you do have your `MAKEFLAGS` set to +that, and you don't want to change it, you can override it by running +`make -j 1`. + Check the [`Makefile`](https://github.com/AdguardTeam/AdGuardHome/blob/master/Makefile) to learn about other commands. **Building for a different platform.** You can build AdGuard for any OS/ARCH just like any other Go project. From a623ac694ba5d7acf45464941057bc79975142d8 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 17:55:37 +0300 Subject: [PATCH 07/35] Pull request: stats: imp err handling, logs Merge in DNS/adguard-home from 2661-imp-stats-logging to master Updates #2661. Squashed commit of the following: commit 474735a5c6ab650973343a1323ebf3c00edd71cf Author: Ainar Garipov Date: Thu Feb 11 17:44:34 2021 +0300 stats: imp err handling, logs --- internal/stats/unit.go | 66 +++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/internal/stats/unit.go b/internal/stats/unit.go index d955d04fa48..96775c72037 100644 --- a/internal/stats/unit.go +++ b/internal/stats/unit.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "encoding/gob" + "errors" "fmt" "net" "os" @@ -11,10 +12,14 @@ import ( "sync" "time" + "github.com/AdguardTeam/AdGuardHome/internal/agherr" "github.com/AdguardTeam/golibs/log" bolt "go.etcd.io/bbolt" ) +// TODO(a.garipov): Rewrite all of this. Add proper error handling and +// inspection. Improve logging. Decrease complexity. + const ( maxDomains = 100 // max number of top domains to store in file or return via Get() maxClients = 100 // max number of top clients to store in file or return via Get() @@ -61,11 +66,12 @@ type unitDB struct { TimeAvg uint32 // usec } -func createObject(conf Config) (*statsCtx, error) { - s := statsCtx{} +func createObject(conf Config) (s *statsCtx, err error) { + s = &statsCtx{} if !checkInterval(conf.LimitDays) { conf.LimitDays = 1 } + s.conf = &Config{} *s.conf = conf s.conf.limit = conf.LimitDays * 24 @@ -84,27 +90,43 @@ func createObject(conf Config) (*statsCtx, error) { log.Tracef("Deleting old units...") firstID := id - s.conf.limit - 1 unitDel := 0 - forEachBkt := func(name []byte, b *bolt.Bucket) error { - id := uint32(btoi(name)) - if id < firstID { - err := tx.DeleteBucket(name) - if err != nil { - log.Debug("tx.DeleteBucket: %s", err) + + // TODO(a.garipov): See if this is actually necessary. Looks + // like a rather bizarre solution. + errStop := agherr.Error("stop iteration") + forEachBkt := func(name []byte, _ *bolt.Bucket) (cberr error) { + nameID := uint32(btoi(name)) + if nameID < firstID { + cberr = tx.DeleteBucket(name) + if cberr != nil { + log.Debug("stats: tx.DeleteBucket: %s", cberr) + + return nil } - log.Debug("Stats: deleted unit %d", id) + + log.Debug("stats: deleted unit %d", nameID) unitDel++ + return nil } - return fmt.Errorf("") + + return errStop + } + + err = tx.ForEach(forEachBkt) + if err != nil && !errors.Is(err, errStop) { + log.Debug("stats: deleting units: %s", err) } - _ = tx.ForEach(forEachBkt) udb = s.loadUnitFromDB(tx, id) if unitDel != 0 { s.commitTxn(tx) } else { - _ = tx.Rollback() + err = tx.Rollback() + if err != nil { + log.Debug("rolling back: %s", err) + } } } @@ -115,8 +137,9 @@ func createObject(conf Config) (*statsCtx, error) { } s.unit = &u - log.Debug("Stats: initialized") - return &s, nil + log.Debug("stats: initialized") + + return s, nil } func (s *statsCtx) Start() { @@ -133,7 +156,7 @@ func (s *statsCtx) dbOpen() bool { log.Tracef("db.Open...") s.db, err = bolt.Open(s.conf.Filename, 0o644, nil) if err != nil { - log.Error("Stats: open DB: %s: %s", s.conf.Filename, err) + log.Error("stats: open DB: %s: %s", s.conf.Filename, err) if err.Error() == "invalid argument" { log.Error("AdGuard Home cannot be initialized due to an incompatible file system.\nPlease read the explanation here: https://github.com/AdguardTeam/AdGuardHome/internal/wiki/Getting-Started#limitations") } @@ -262,10 +285,13 @@ func (s *statsCtx) periodicFlush() { func (s *statsCtx) deleteUnit(tx *bolt.Tx, id uint32) bool { err := tx.DeleteBucket(unitName(id)) if err != nil { - log.Tracef("bolt DeleteBucket: %s", err) + log.Tracef("stats: bolt DeleteBucket: %s", err) + return false } - log.Debug("Stats: deleted unit %d", id) + + log.Debug("stats: deleted unit %d", id) + return true } @@ -390,7 +416,7 @@ func (s *statsCtx) setLimit(limitDays int) { conf := *s.conf conf.limit = uint32(limitDays) * 24 s.conf = &conf - log.Debug("Stats: set limit: %d", limitDays) + log.Debug("stats: set limit: %d", limitDays) } func (s *statsCtx) WriteDiskConfig(dc *DiskConfig) { @@ -415,7 +441,7 @@ func (s *statsCtx) Close() { log.Tracef("db.Close") } - log.Debug("Stats: closed") + log.Debug("stats: closed") } // Reset counters and clear database @@ -443,7 +469,7 @@ func (s *statsCtx) clear() { _ = s.dbOpen() - log.Debug("Stats: cleared") + log.Debug("stats: cleared") } // Get Client IP address From 6b8a46ef3bd39d32866b9938b1ba00fcf0228a8b Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Thu, 11 Feb 2021 18:08:44 +0300 Subject: [PATCH 08/35] Fix install script for darwin --- scripts/install.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/install.sh b/scripts/install.sh index 551f84fc1f3..7a410cee9aa 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -228,7 +228,13 @@ main() { download "${URL}" "${PKG_NAME}" || error_exit "Cannot download the package" - unpack "${PKG_NAME}" "${OUT_DIR}" "${PKG_EXT}" || error_exit "Cannot unpack the package" + if [ "${OS}" = "darwin" ]; then + # TODO: remove this after v0.106.0 release + mkdir "${AGH_DIR}" + unpack "${PKG_NAME}" "${AGH_DIR}" "${PKG_EXT}" || error_exit "Cannot unpack the package" + else + unpack "${PKG_NAME}" "${OUT_DIR}" "${PKG_EXT}" || error_exit "Cannot unpack the package" + fi # Install AdGuard Home service and run it. ( cd "${AGH_DIR}" && ./AdGuardHome -s install || error_exit "Cannot install AdGuardHome as a service" ) From 7b014082ab5772a588f50708d758500db10fbbb3 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 18:40:14 +0300 Subject: [PATCH 09/35] Pull request: home: set vary hdr to origin Merge in DNS/adguard-home from 2658-vary-origin to master Updates #2658. Squashed commit of the following: commit b4bf6c16e19f1c0b04cc2e526e2b0968956cf56c Author: Ainar Garipov Date: Thu Feb 11 18:18:32 2021 +0300 all: doc changes commit f2599c5b48759565e2f621c2fcf89440de56e4a4 Merge: 3eb08ac8 6b8a46ef Author: Ainar Garipov Date: Thu Feb 11 18:16:53 2021 +0300 Merge branch 'master' into 2658-vary-origin commit 3eb08ac889163d123b5ca638a83a9289b456d04e Author: Ainar Garipov Date: Thu Feb 11 18:04:04 2021 +0300 home: set vary hdr to origin --- CHANGELOG.md | 4 ++++ internal/home/control.go | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfae45f13b0..f1e8d9c8502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,10 +26,14 @@ and this project adheres to ### Fixed +- The `Vary` header is now added along with `Access-Control-Allow-Origin` to + prevent cache-related and other issues in browsers ([#2658]). + domain, but with an HTTP scheme as opposed to `*` ([#2484]). - The request body size limit is now set for HTTPS requests as well. - Incorrect version tag in the Docker release ([#2663]). - DNSCrypt queries weren't marked as such in logs ([#2662]). +[#2658]: https://github.com/AdguardTeam/AdGuardHome/issues/2658 [#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 [#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 diff --git a/internal/home/control.go b/internal/home/control.go index 71bf52e53f3..19876b12b81 100644 --- a/internal/home/control.go +++ b/internal/home/control.go @@ -251,12 +251,15 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) { // Allow the frontend from the HTTP origin to send requests to the HTTPS // server. This can happen when the user has just set up HTTPS with - // redirects. + // redirects. Prevent cache-related errors by setting the Vary header. + // + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin. originURL := &url.URL{ Scheme: "http", Host: r.Host, } w.Header().Set("Access-Control-Allow-Origin", originURL.String()) + w.Header().Set("Vary", "Origin") return true } From 2eb21ef40901e893069e9e4b6fa902d759d510b5 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 11 Feb 2021 20:49:03 +0300 Subject: [PATCH 10/35] Pull request: dhcpd: do not override ra-slaac settings Merge in DNS/adguard-home from 2653-ra-slaac to master Updates #2653. Squashed commit of the following: commit f261413a58dc813e37cc848606ed490b8c0ac9f3 Author: Ainar Garipov Date: Thu Feb 11 20:37:13 2021 +0300 all: doc changes, rm debug commit 4a8c6e4897579493c1ca242fb8f0f440c3b51a74 Author: Ainar Garipov Date: Thu Feb 11 20:11:46 2021 +0300 dhcpd: do not override ra-slaac settings --- CHANGELOG.md | 4 +- internal/dhcpd/dhcpd.go | 19 +++--- internal/dhcpd/dhcphttp.go | 104 +++++++++++++++++++------------- internal/dhcpd/nullbool.go | 58 ++++++++++++++++++ internal/dhcpd/nullbool_test.go | 69 +++++++++++++++++++++ internal/dhcpd/routeradv.go | 10 +-- internal/dhcpd/server.go | 4 +- internal/dhcpd/v6.go | 6 +- internal/sysutil/net_linux.go | 12 ++-- staticcheck.conf | 2 + 10 files changed, 222 insertions(+), 66 deletions(-) create mode 100644 internal/dhcpd/nullbool.go create mode 100644 internal/dhcpd/nullbool_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e8d9c8502..097f5c46424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,13 +26,15 @@ and this project adheres to ### Fixed +- DHCPv6 server's `ra_slaac_only` and `ra_allow_slaac` settings aren't reset to + `false` on update any more ([#2653]). - The `Vary` header is now added along with `Access-Control-Allow-Origin` to prevent cache-related and other issues in browsers ([#2658]). - domain, but with an HTTP scheme as opposed to `*` ([#2484]). - The request body size limit is now set for HTTPS requests as well. - Incorrect version tag in the Docker release ([#2663]). - DNSCrypt queries weren't marked as such in logs ([#2662]). +[#2653]: https://github.com/AdguardTeam/AdGuardHome/issues/2653 [#2658]: https://github.com/AdguardTeam/AdGuardHome/issues/2658 [#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 diff --git a/internal/dhcpd/dhcpd.go b/internal/dhcpd/dhcpd.go index 185099910e5..bcd35d1c87f 100644 --- a/internal/dhcpd/dhcpd.go +++ b/internal/dhcpd/dhcpd.go @@ -117,14 +117,14 @@ type ServerInterface interface { } // Create - create object -func Create(config ServerConfig) *Server { +func Create(conf ServerConfig) *Server { s := &Server{} - s.conf.Enabled = config.Enabled - s.conf.InterfaceName = config.InterfaceName - s.conf.HTTPRegister = config.HTTPRegister - s.conf.ConfigModified = config.ConfigModified - s.conf.DBFilePath = filepath.Join(config.WorkDir, dbFilename) + s.conf.Enabled = conf.Enabled + s.conf.InterfaceName = conf.InterfaceName + s.conf.HTTPRegister = conf.HTTPRegister + s.conf.ConfigModified = conf.ConfigModified + s.conf.DBFilePath = filepath.Join(conf.WorkDir, dbFilename) if !webHandlersRegistered && s.conf.HTTPRegister != nil { if runtime.GOOS == "windows" { @@ -145,7 +145,7 @@ func Create(config ServerConfig) *Server { } var err4, err6 error - v4conf := config.Conf4 + v4conf := conf.Conf4 v4conf.Enabled = s.conf.Enabled if len(v4conf.RangeStart) == 0 { v4conf.Enabled = false @@ -154,7 +154,7 @@ func Create(config ServerConfig) *Server { v4conf.notify = s.onNotify s.srv4, err4 = v4Create(v4conf) - v6conf := config.Conf6 + v6conf := conf.Conf6 v6conf.Enabled = s.conf.Enabled if len(v6conf.RangeStart) == 0 { v6conf.Enabled = false @@ -172,6 +172,9 @@ func Create(config ServerConfig) *Server { return nil } + s.conf.Conf4 = conf.Conf4 + s.conf.Conf6 = conf.Conf6 + if s.conf.Enabled && !v4conf.Enabled && !v6conf.Enabled { log.Error("Can't enable DHCP server because neither DHCPv4 nor DHCPv6 servers are configured") return nil diff --git a/internal/dhcpd/dhcphttp.go b/internal/dhcpd/dhcphttp.go index b6b5c729f1a..0a182cf08f0 100644 --- a/internal/dhcpd/dhcphttp.go +++ b/internal/dhcpd/dhcphttp.go @@ -11,7 +11,6 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/sysutil" "github.com/AdguardTeam/AdGuardHome/internal/util" - "github.com/AdguardTeam/golibs/jsonutil" "github.com/AdguardTeam/golibs/log" ) @@ -29,7 +28,11 @@ type v4ServerConfJSON struct { LeaseDuration uint32 `json:"lease_duration"` } -func v4JSONToServerConf(j v4ServerConfJSON) V4ServerConf { +func v4JSONToServerConf(j *v4ServerConfJSON) V4ServerConf { + if j == nil { + return V4ServerConf{} + } + return V4ServerConf{ GatewayIP: j.GatewayIP, SubnetMask: j.SubnetMask, @@ -44,7 +47,11 @@ type v6ServerConfJSON struct { LeaseDuration uint32 `json:"lease_duration"` } -func v6JSONToServerConf(j v6ServerConfJSON) V6ServerConf { +func v6JSONToServerConf(j *v6ServerConfJSON) V6ServerConf { + if j == nil { + return V6ServerConf{} + } + return V6ServerConf{ RangeStart: j.RangeStart, LeaseDuration: j.LeaseDuration, @@ -83,13 +90,6 @@ func (s *Server) handleDHCPStatus(w http.ResponseWriter, r *http.Request) { } } -type dhcpServerConfigJSON struct { - Enabled bool `json:"enabled"` - InterfaceName string `json:"interface_name"` - V4 v4ServerConfJSON `json:"v4"` - V6 v6ServerConfJSON `json:"v6"` -} - func (s *Server) enableDHCP(ifaceName string) (code int, err error) { var hasStaticIP bool hasStaticIP, err = sysutil.IfaceHasStaticIP(ifaceName) @@ -112,14 +112,22 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) { return 0, nil } +type dhcpServerConfigJSON struct { + V4 *v4ServerConfJSON `json:"v4"` + V6 *v6ServerConfJSON `json:"v6"` + InterfaceName string `json:"interface_name"` + Enabled nullBool `json:"enabled"` +} + func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { - newconfig := dhcpServerConfigJSON{} - newconfig.Enabled = s.conf.Enabled - newconfig.InterfaceName = s.conf.InterfaceName + conf := dhcpServerConfigJSON{} + conf.Enabled = boolToNullBool(s.conf.Enabled) + conf.InterfaceName = s.conf.InterfaceName - js, err := jsonutil.DecodeObject(&newconfig, r.Body) + err := json.NewDecoder(r.Body).Decode(&conf) if err != nil { - httpError(r, w, http.StatusBadRequest, "Failed to parse new DHCP config json: %s", err) + httpError(r, w, http.StatusBadRequest, + "failed to parse new dhcp config json: %s", err) return } @@ -129,62 +137,72 @@ func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { v4Enabled := false v6Enabled := false - if js.Exists("v4") { - v4conf := v4JSONToServerConf(newconfig.V4) - v4conf.Enabled = newconfig.Enabled - if len(v4conf.RangeStart) == 0 { - v4conf.Enabled = false + if conf.V4 != nil { + v4Conf := v4JSONToServerConf(conf.V4) + v4Conf.Enabled = conf.Enabled == nbTrue + if len(v4Conf.RangeStart) == 0 { + v4Conf.Enabled = false } - v4Enabled = v4conf.Enabled - v4conf.InterfaceName = newconfig.InterfaceName + v4Enabled = v4Conf.Enabled + v4Conf.InterfaceName = conf.InterfaceName c4 := V4ServerConf{} s.srv4.WriteDiskConfig4(&c4) - v4conf.notify = c4.notify - v4conf.ICMPTimeout = c4.ICMPTimeout + v4Conf.notify = c4.notify + v4Conf.ICMPTimeout = c4.ICMPTimeout - s4, err = v4Create(v4conf) + s4, err = v4Create(v4Conf) if err != nil { - httpError(r, w, http.StatusBadRequest, "invalid dhcpv4 configuration: %s", err) + httpError(r, w, http.StatusBadRequest, + "invalid dhcpv4 configuration: %s", err) return } } - if js.Exists("v6") { - v6conf := v6JSONToServerConf(newconfig.V6) - v6conf.Enabled = newconfig.Enabled - if len(v6conf.RangeStart) == 0 { - v6conf.Enabled = false + if conf.V6 != nil { + v6Conf := v6JSONToServerConf(conf.V6) + v6Conf.Enabled = conf.Enabled == nbTrue + if len(v6Conf.RangeStart) == 0 { + v6Conf.Enabled = false } - v6Enabled = v6conf.Enabled - v6conf.InterfaceName = newconfig.InterfaceName - v6conf.notify = s.onNotify + // Don't overwrite the RA/SLAAC settings from the config file. + // + // TODO(a.garipov): Perhaps include them into the request to + // allow changing them from the HTTP API? + v6Conf.RASLAACOnly = s.conf.Conf6.RASLAACOnly + v6Conf.RAAllowSLAAC = s.conf.Conf6.RAAllowSLAAC + + v6Enabled = v6Conf.Enabled + v6Conf.InterfaceName = conf.InterfaceName + v6Conf.notify = s.onNotify - s6, err = v6Create(v6conf) + s6, err = v6Create(v6Conf) if err != nil { - httpError(r, w, http.StatusBadRequest, "invalid dhcpv6 configuration: %s", err) + httpError(r, w, http.StatusBadRequest, + "invalid dhcpv6 configuration: %s", err) return } } - if newconfig.Enabled && !v4Enabled && !v6Enabled { - httpError(r, w, http.StatusBadRequest, "dhcpv4 or dhcpv6 configuration must be complete") + if conf.Enabled == nbTrue && !v4Enabled && !v6Enabled { + httpError(r, w, http.StatusBadRequest, + "dhcpv4 or dhcpv6 configuration must be complete") return } s.Stop() - if js.Exists("enabled") { - s.conf.Enabled = newconfig.Enabled + if conf.Enabled != nbNull { + s.conf.Enabled = conf.Enabled == nbTrue } - if js.Exists("interface_name") { - s.conf.InterfaceName = newconfig.InterfaceName + if conf.InterfaceName != "" { + s.conf.InterfaceName = conf.InterfaceName } if s4 != nil { @@ -200,7 +218,7 @@ func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { if s.conf.Enabled { var code int - code, err = s.enableDHCP(newconfig.InterfaceName) + code, err = s.enableDHCP(conf.InterfaceName) if err != nil { httpError(r, w, code, "enabling dhcp: %s", err) diff --git a/internal/dhcpd/nullbool.go b/internal/dhcpd/nullbool.go new file mode 100644 index 00000000000..b07f6768e07 --- /dev/null +++ b/internal/dhcpd/nullbool.go @@ -0,0 +1,58 @@ +package dhcpd + +import ( + "bytes" + "fmt" +) + +// nullBool is a nullable boolean. Use these in JSON requests and responses +// instead of pointers to bool. +// +// TODO(a.garipov): Inspect uses of *bool, move this type into some new package +// if we need it somewhere else. +type nullBool uint8 + +// nullBool values +const ( + nbNull nullBool = iota + nbTrue + nbFalse +) + +// String implements the fmt.Stringer interface for nullBool. +func (nb nullBool) String() (s string) { + switch nb { + case nbNull: + return "null" + case nbTrue: + return "true" + case nbFalse: + return "false" + } + + return fmt.Sprintf("!invalid nullBool %d", uint8(nb)) +} + +// boolToNullBool converts a bool into a nullBool. +func boolToNullBool(cond bool) (nb nullBool) { + if cond { + return nbTrue + } + + return nbFalse +} + +// UnmarshalJSON implements the json.Unmarshaler interface for *nullBool. +func (nb *nullBool) UnmarshalJSON(b []byte) (err error) { + if len(b) == 0 || bytes.Equal(b, []byte("null")) { + *nb = nbNull + } else if bytes.Equal(b, []byte("true")) { + *nb = nbTrue + } else if bytes.Equal(b, []byte("false")) { + *nb = nbFalse + } else { + return fmt.Errorf("invalid nullBool value %q", b) + } + + return nil +} diff --git a/internal/dhcpd/nullbool_test.go b/internal/dhcpd/nullbool_test.go new file mode 100644 index 00000000000..2570dd44ffb --- /dev/null +++ b/internal/dhcpd/nullbool_test.go @@ -0,0 +1,69 @@ +package dhcpd + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNullBool_UnmarshalText(t *testing.T) { + testCases := []struct { + name string + data []byte + wantErrMsg string + want nullBool + }{{ + name: "empty", + data: []byte{}, + wantErrMsg: "", + want: nbNull, + }, { + name: "null", + data: []byte("null"), + wantErrMsg: "", + want: nbNull, + }, { + name: "true", + data: []byte("true"), + wantErrMsg: "", + want: nbTrue, + }, { + name: "false", + data: []byte("false"), + wantErrMsg: "", + want: nbFalse, + }, { + name: "invalid", + data: []byte("flase"), + wantErrMsg: `invalid nullBool value "flase"`, + want: nbNull, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var got nullBool + err := got.UnmarshalJSON(tc.data) + if tc.wantErrMsg == "" { + assert.Nil(t, err) + } else { + require.NotNil(t, err) + assert.Equal(t, tc.wantErrMsg, err.Error()) + } + + assert.Equal(t, tc.want, got) + }) + } + + t.Run("json", func(t *testing.T) { + want := nbTrue + var got struct { + A nullBool + } + + err := json.Unmarshal([]byte(`{"A":true}`), &got) + require.Nil(t, err) + assert.Equal(t, want, got.A) + }) +} diff --git a/internal/dhcpd/routeradv.go b/internal/dhcpd/routeradv.go index f1d63c7d554..59aad9d1398 100644 --- a/internal/dhcpd/routeradv.go +++ b/internal/dhcpd/routeradv.go @@ -13,8 +13,8 @@ import ( ) type raCtx struct { - raAllowSlaac bool // send RA packets without MO flags - raSlaacOnly bool // send RA packets with MO flags + raAllowSLAAC bool // send RA packets without MO flags + raSLAACOnly bool // send RA packets with MO flags ipAddr net.IP // source IP address (link-local-unicast) dnsIPAddr net.IP // IP address for DNS Server option prefixIPAddr net.IP // IP address for Prefix option @@ -159,7 +159,7 @@ func createICMPv6RAPacket(params icmpv6RA) []byte { func (ra *raCtx) Init() error { ra.stop.Store(0) ra.conn = nil - if !(ra.raAllowSlaac || ra.raSlaacOnly) { + if !(ra.raAllowSLAAC || ra.raSLAACOnly) { return nil } @@ -167,8 +167,8 @@ func (ra *raCtx) Init() error { ra.ipAddr, ra.dnsIPAddr) params := icmpv6RA{ - managedAddressConfiguration: !ra.raSlaacOnly, - otherConfiguration: !ra.raSlaacOnly, + managedAddressConfiguration: !ra.raSLAACOnly, + otherConfiguration: !ra.raSLAACOnly, mtu: uint32(ra.iface.MTU), prefixLen: 64, recursiveDNSServer: ra.dnsIPAddr, diff --git a/internal/dhcpd/server.go b/internal/dhcpd/server.go index 4adbca5ac07..1d3ce4609f8 100644 --- a/internal/dhcpd/server.go +++ b/internal/dhcpd/server.go @@ -83,8 +83,8 @@ type V6ServerConf struct { LeaseDuration uint32 `yaml:"lease_duration" json:"lease_duration"` // in seconds - RaSlaacOnly bool `yaml:"ra_slaac_only" json:"-"` // send ICMPv6.RA packets without MO flags - RaAllowSlaac bool `yaml:"ra_allow_slaac" json:"-"` // send ICMPv6.RA packets with MO flags + RASLAACOnly bool `yaml:"ra_slaac_only" json:"-"` // send ICMPv6.RA packets without MO flags + RAAllowSLAAC bool `yaml:"ra_allow_slaac" json:"-"` // send ICMPv6.RA packets with MO flags ipStart net.IP // starting IP address for dynamic leases leaseTime time.Duration // the time during which a dynamic lease is considered valid diff --git a/internal/dhcpd/v6.go b/internal/dhcpd/v6.go index 517885513f8..0b43d6d1cfc 100644 --- a/internal/dhcpd/v6.go +++ b/internal/dhcpd/v6.go @@ -552,8 +552,8 @@ func (s *v6Server) initRA(iface *net.Interface) error { } } - s.ra.raAllowSlaac = s.conf.RaAllowSlaac - s.ra.raSlaacOnly = s.conf.RaSlaacOnly + s.ra.raAllowSLAAC = s.conf.RAAllowSLAAC + s.ra.raSLAACOnly = s.conf.RASLAACOnly s.ra.dnsIPAddr = s.ra.ipAddr s.ra.prefixIPAddr = s.conf.ipStart s.ra.ifaceName = s.conf.InterfaceName @@ -594,7 +594,7 @@ func (s *v6Server) Start() error { } // don't initialize DHCPv6 server if we must force the clients to use SLAAC - if s.conf.RaSlaacOnly { + if s.conf.RASLAACOnly { log.Debug("DHCPv6: not starting DHCPv6 server due to ra_slaac_only=true") return nil } diff --git a/internal/sysutil/net_linux.go b/internal/sysutil/net_linux.go index 8f47cf428fc..9205fd5c9f6 100644 --- a/internal/sysutil/net_linux.go +++ b/internal/sysutil/net_linux.go @@ -33,15 +33,19 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { filePath: "/etc/network/interfaces", }} { f, err = os.Open(check.filePath) - if errors.Is(err, os.ErrNotExist) { - continue - } if err != nil { + if errors.Is(err, os.ErrNotExist) { + err = nil + + continue + } + return false, err } defer f.Close() - fileReadCloser, err := aghio.LimitReadCloser(f, maxConfigFileSize) + var fileReadCloser io.ReadCloser + fileReadCloser, err = aghio.LimitReadCloser(f, maxConfigFileSize) if err != nil { return false, err } diff --git a/staticcheck.conf b/staticcheck.conf index 146f83cb13b..4dd931764d5 100644 --- a/staticcheck.conf +++ b/staticcheck.conf @@ -10,7 +10,9 @@ initialisms = [ , "MX" , "PTR" , "QUIC" +, "RA" , "SDNS" +, "SLAAC" , "SVCB" ] dot_import_whitelist = [] From e83b919dbda3ac7b1835e9b312962ae30dd13e04 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 12 Feb 2021 12:59:08 +0300 Subject: [PATCH 11/35] Pull request: all: imp issue template Merge in DNS/adguard-home from imp-issue-tmpl to master Squashed commit of the following: commit e6251d4e6db9498d26e555116dbb870625219ffa Author: Ainar Garipov Date: Fri Feb 12 12:46:09 2021 +0300 all: imp issue template more commit f896c6076027c373bc8b62c600a82938ae3a813d Author: Ainar Garipov Date: Fri Feb 12 12:42:25 2021 +0300 all: imp issue template --- .github/ISSUE_TEMPLATE/Bug_report.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 5603c7d794e..86615ef861e 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -1,11 +1,9 @@ --- name: Bug report about: Create a bug report to help us improve AdGuard Home - --- - + ### Prerequisites @@ -17,16 +15,18 @@ Please answer the following questions for yourself before submitting an issue. * ### Issue Details - + * **Version of AdGuard Home server:** - * + * * **How did you install AdGuard Home:** - * + * * **How did you setup DNS configuration:** * * **If it's a router or IoT, please write device model:** * +* **CPU architecture:** + * * **Operating system and version:** * From 0d44822c43e1a2fd327689796135acdabfe49ac3 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Fri, 12 Feb 2021 13:27:44 +0300 Subject: [PATCH 12/35] Pull request: 2639 use testify require vol.3 Merge in DNS/adguard-home from 2639-testify-require-3 to master Updates #2639. Squashed commit of the following: commit 83d7afcbb7e5393db5a0242f3eaca063710d36b7 Merge: ef154b6d e83b919d Author: Eugene Burkov Date: Fri Feb 12 13:07:58 2021 +0300 Merge branch 'master' into 2639-testify-require-3 commit ef154b6d3c89f975ce28369372757a1205baa655 Merge: 5b46073a 2eb21ef4 Author: Eugene Burkov Date: Fri Feb 12 12:40:43 2021 +0300 Merge branch 'master' into 2639-testify-require-3 commit 5b46073a09badef44c86a5f48c6bb874c8df2674 Merge: 7dd7b6e0 890f0322 Author: Eugene Burkov Date: Wed Feb 10 21:20:51 2021 +0300 Merge branch 'master' into 2639-testify-require-3 commit 7dd7b6e00ead2bf507af541c801a9ac770106440 Author: Eugene Burkov Date: Wed Feb 10 21:19:36 2021 +0300 dhcpd: fix comment commit 9e74adbcf21dad58409c3dfc8e08b6470bfedc22 Author: Eugene Burkov Date: Wed Feb 10 15:13:40 2021 +0300 all: imp tests drastically --- internal/aghio/limitedreadcloser_test.go | 7 +- internal/dhcpd/dhcpd_test.go | 193 +++++++----- internal/dhcpd/dhcphttp_test.go | 3 +- internal/dhcpd/routeradv_test.go | 8 +- internal/dhcpd/v4.go | 3 +- internal/dhcpd/v46_test.go | 21 +- internal/dhcpd/v4_test.go | 361 ++++++++++++--------- internal/dhcpd/v6_test.go | 385 +++++++++++++---------- internal/home/ipdetector_test.go | 9 +- internal/home/middlewares_test.go | 3 +- 10 files changed, 570 insertions(+), 423 deletions(-) diff --git a/internal/aghio/limitedreadcloser_test.go b/internal/aghio/limitedreadcloser_test.go index 1f10e32bf7e..9cccda17538 100644 --- a/internal/aghio/limitedreadcloser_test.go +++ b/internal/aghio/limitedreadcloser_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestLimitReadCloser(t *testing.T) { @@ -78,11 +79,11 @@ func TestLimitedReadCloser_Read(t *testing.T) { buf := make([]byte, tc.limit+1) lreader, err := LimitReadCloser(readCloser, tc.limit) - assert.Nil(t, err) + require.Nil(t, err) n, err := lreader.Read(buf) - assert.Equal(t, n, tc.want) - assert.Equal(t, tc.err, err) + require.Equal(t, tc.err, err) + assert.Equal(t, tc.want, n) }) } } diff --git a/internal/dhcpd/dhcpd_test.go b/internal/dhcpd/dhcpd_test.go index 1aa1b9a6ab5..e9b44518230 100644 --- a/internal/dhcpd/dhcpd_test.go +++ b/internal/dhcpd/dhcpd_test.go @@ -11,6 +11,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghtest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMain(m *testing.M) { @@ -20,116 +21,156 @@ func TestMain(m *testing.M) { func testNotify(flags uint32) { } -// Leases database store/load +// Leases database store/load. func TestDB(t *testing.T) { var err error - s := Server{} - s.conf.DBFilePath = dbFilename + s := Server{ + conf: ServerConfig{ + DBFilePath: dbFilename, + }, + } - conf := V4ServerConf{ + s.srv4, err = v4Create(V4ServerConf{ Enabled: true, RangeStart: net.IP{192, 168, 10, 100}, RangeEnd: net.IP{192, 168, 10, 200}, GatewayIP: net.IP{192, 168, 10, 1}, SubnetMask: net.IP{255, 255, 255, 0}, notify: testNotify, - } - s.srv4, err = v4Create(conf) - assert.Nil(t, err) + }) + require.Nil(t, err) s.srv6, err = v6Create(V6ServerConf{}) - assert.Nil(t, err) + require.Nil(t, err) - l := Lease{} - l.IP = net.IP{192, 168, 10, 100} - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - exp1 := time.Now().Add(time.Hour) - l.Expiry = exp1 + leases := []Lease{{ + IP: net.IP{192, 168, 10, 100}, + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + Expiry: time.Now().Add(time.Hour), + }, { + IP: net.IP{192, 168, 10, 101}, + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB}, + }} srv4, ok := s.srv4.(*v4Server) - assert.True(t, ok) + require.True(t, ok) - srv4.addLease(&l) + srv4.addLease(&leases[0]) + require.Nil(t, s.srv4.AddStaticLease(leases[1])) - l2 := Lease{} - l2.IP = net.IP{192, 168, 10, 101} - l2.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:bb") - err = s.srv4.AddStaticLease(l2) - assert.Nil(t, err) - - _ = os.Remove("leases.db") s.dbStore() + t.Cleanup(func() { + assert.Nil(t, os.Remove(dbFilename)) + }) s.srv4.ResetLeases(nil) - s.dbLoad() ll := s.srv4.GetLeases(LeasesAll) + require.Len(t, ll, len(leases)) - assert.Equal(t, "aa:aa:aa:aa:aa:bb", ll[0].HWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 101}.Equal(ll[0].IP)) + assert.Equal(t, leases[1].HWAddr, ll[0].HWAddr) + assert.Equal(t, leases[1].IP, ll[0].IP) assert.EqualValues(t, leaseExpireStatic, ll[0].Expiry.Unix()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ll[1].HWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 100}.Equal(ll[1].IP)) - assert.Equal(t, exp1.Unix(), ll[1].Expiry.Unix()) - - _ = os.Remove("leases.db") + assert.Equal(t, leases[0].HWAddr, ll[1].HWAddr) + assert.Equal(t, leases[0].IP, ll[1].IP) + assert.Equal(t, leases[0].Expiry.Unix(), ll[1].Expiry.Unix()) } func TestIsValidSubnetMask(t *testing.T) { - assert.True(t, isValidSubnetMask([]byte{255, 255, 255, 0})) - assert.True(t, isValidSubnetMask([]byte{255, 255, 254, 0})) - assert.True(t, isValidSubnetMask([]byte{255, 255, 252, 0})) - assert.False(t, isValidSubnetMask([]byte{255, 255, 253, 0})) - assert.False(t, isValidSubnetMask([]byte{255, 255, 255, 1})) + testCases := []struct { + mask net.IP + want bool + }{{ + mask: net.IP{255, 255, 255, 0}, + want: true, + }, { + mask: net.IP{255, 255, 254, 0}, + want: true, + }, { + mask: net.IP{255, 255, 252, 0}, + want: true, + }, { + mask: net.IP{255, 255, 253, 0}, + }, { + mask: net.IP{255, 255, 255, 1}, + }} + + for _, tc := range testCases { + t.Run(tc.mask.String(), func(t *testing.T) { + assert.Equal(t, tc.want, isValidSubnetMask(tc.mask)) + }) + } } func TestNormalizeLeases(t *testing.T) { - dynLeases := []*Lease{} - staticLeases := []*Lease{} - - lease := &Lease{} - lease.HWAddr = []byte{1, 2, 3, 4} - dynLeases = append(dynLeases, lease) - lease = new(Lease) - lease.HWAddr = []byte{1, 2, 3, 5} - dynLeases = append(dynLeases, lease) - - lease = new(Lease) - lease.HWAddr = []byte{1, 2, 3, 4} - lease.IP = []byte{0, 2, 3, 4} - staticLeases = append(staticLeases, lease) - lease = new(Lease) - lease.HWAddr = []byte{2, 2, 3, 4} - staticLeases = append(staticLeases, lease) + dynLeases := []*Lease{{ + HWAddr: net.HardwareAddr{1, 2, 3, 4}, + }, { + HWAddr: net.HardwareAddr{1, 2, 3, 5}, + }} + + staticLeases := []*Lease{{ + HWAddr: net.HardwareAddr{1, 2, 3, 4}, + IP: net.IP{0, 2, 3, 4}, + }, { + HWAddr: net.HardwareAddr{2, 2, 3, 4}, + }} leases := normalizeLeases(staticLeases, dynLeases) + require.Len(t, leases, 3) - assert.Len(t, leases, 3) - assert.True(t, bytes.Equal(leases[0].HWAddr, []byte{1, 2, 3, 4})) - assert.True(t, bytes.Equal(leases[0].IP, []byte{0, 2, 3, 4})) - assert.True(t, bytes.Equal(leases[1].HWAddr, []byte{2, 2, 3, 4})) - assert.True(t, bytes.Equal(leases[2].HWAddr, []byte{1, 2, 3, 5})) + assert.Equal(t, leases[0].HWAddr, dynLeases[0].HWAddr) + assert.Equal(t, leases[0].IP, staticLeases[0].IP) + assert.Equal(t, leases[1].HWAddr, staticLeases[1].HWAddr) + assert.Equal(t, leases[2].HWAddr, dynLeases[1].HWAddr) } func TestOptions(t *testing.T) { - code, val := parseOptionString(" 12 hex abcdef ") - assert.EqualValues(t, 12, code) - assert.True(t, bytes.Equal([]byte{0xab, 0xcd, 0xef}, val)) - - code, _ = parseOptionString(" 12 hex abcdef1 ") - assert.EqualValues(t, 0, code) - - code, val = parseOptionString("123 ip 1.2.3.4") - assert.EqualValues(t, 123, code) - assert.True(t, net.IP{1, 2, 3, 4}.Equal(net.IP(val))) - - code, _ = parseOptionString("256 ip 1.1.1.1") - assert.EqualValues(t, 0, code) - code, _ = parseOptionString("-1 ip 1.1.1.1") - assert.EqualValues(t, 0, code) - code, _ = parseOptionString("12 ip 1.1.1.1x") - assert.EqualValues(t, 0, code) - code, _ = parseOptionString("12 x 1.1.1.1") - assert.EqualValues(t, 0, code) + testCases := []struct { + name string + optStr string + wantCode uint8 + wantVal []byte + }{{ + name: "all_right_hex", + optStr: " 12 hex abcdef ", + wantCode: 12, + wantVal: []byte{0xab, 0xcd, 0xef}, + }, { + name: "bad_hex", + optStr: " 12 hex abcdef1 ", + wantCode: 0, + }, { + name: "all_right_ip", + optStr: "123 ip 1.2.3.4", + wantCode: 123, + wantVal: net.IPv4(1, 2, 3, 4), + }, { + name: "bad_code", + optStr: "256 ip 1.1.1.1", + wantCode: 0, + }, { + name: "negative_code", + optStr: "-1 ip 1.1.1.1", + wantCode: 0, + }, { + name: "bad_ip", + optStr: "12 ip 1.1.1.1x", + wantCode: 0, + }, { + name: "bad_mode", + optStr: "12 x 1.1.1.1", + wantCode: 0, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + code, val := parseOptionString(tc.optStr) + require.EqualValues(t, tc.wantCode, code) + if tc.wantVal != nil { + assert.True(t, bytes.Equal(tc.wantVal, val)) + } + }) + } } diff --git a/internal/dhcpd/dhcphttp_test.go b/internal/dhcpd/dhcphttp_test.go index 47b926dcc1a..36a89a6ef7a 100644 --- a/internal/dhcpd/dhcphttp_test.go +++ b/internal/dhcpd/dhcphttp_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestServer_notImplemented(t *testing.T) { @@ -14,7 +15,7 @@ func TestServer_notImplemented(t *testing.T) { w := httptest.NewRecorder() r, err := http.NewRequest(http.MethodGet, "/unsupported", nil) - assert.Nil(t, err) + require.Nil(t, err) h(w, r) assert.Equal(t, http.StatusNotImplemented, w.Code) diff --git a/internal/dhcpd/routeradv_test.go b/internal/dhcpd/routeradv_test.go index 95f3d4fa25d..4a0f4c5bd6e 100644 --- a/internal/dhcpd/routeradv_test.go +++ b/internal/dhcpd/routeradv_test.go @@ -1,7 +1,6 @@ package dhcpd import ( - "bytes" "net" "testing" @@ -9,7 +8,7 @@ import ( ) func TestRA(t *testing.T) { - ra := icmpv6RA{ + data := createICMPv6RAPacket(icmpv6RA{ managedAddressConfiguration: false, otherConfiguration: true, mtu: 1500, @@ -17,8 +16,7 @@ func TestRA(t *testing.T) { prefixLen: 64, recursiveDNSServer: net.ParseIP("fe80::800:27ff:fe00:0"), sourceLinkLayerAddress: []byte{0x0a, 0x00, 0x27, 0x00, 0x00, 0x00}, - } - data := createICMPv6RAPacket(ra) + }) dataCorrect := []byte{ 0x86, 0x00, 0x00, 0x00, 0x40, 0x40, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, @@ -27,5 +25,5 @@ func TestRA(t *testing.T) { 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x27, 0xff, 0xfe, 0x00, 0x00, 0x00, } - assert.True(t, bytes.Equal(data, dataCorrect)) + assert.Equal(t, dataCorrect, data) } diff --git a/internal/dhcpd/v4.go b/internal/dhcpd/v4.go index 2f5484a2446..7d24699e76e 100644 --- a/internal/dhcpd/v4.go +++ b/internal/dhcpd/v4.go @@ -23,7 +23,8 @@ type v4Server struct { srv *server4.Server leasesLock sync.Mutex leases []*Lease - ipAddrs [256]byte + // TODO(e.burkov): This field type should be a normal bitmap. + ipAddrs [256]byte conf V4ServerConf } diff --git a/internal/dhcpd/v46_test.go b/internal/dhcpd/v46_test.go index 6007205dfcb..6495eeeeda2 100644 --- a/internal/dhcpd/v46_test.go +++ b/internal/dhcpd/v46_test.go @@ -7,6 +7,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/agherr" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type fakeIface struct { @@ -79,8 +80,8 @@ func TestIfaceIPAddrs(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got, gotErr := ifaceIPAddrs(tc.iface, tc.ipv) + require.True(t, errors.Is(gotErr, tc.wantErr)) assert.Equal(t, tc.want, got) - assert.True(t, errors.Is(gotErr, tc.wantErr)) }) } } @@ -140,12 +141,8 @@ func TestIfaceDNSIPAddrs(t *testing.T) { want: nil, wantErr: errTest, }, { - name: "ipv4_wait", - iface: &waitingFakeIface{ - addrs: []net.Addr{addr4}, - err: nil, - n: 1, - }, + name: "ipv4_wait", + iface: &waitingFakeIface{addrs: []net.Addr{addr4}, err: nil, n: 1}, ipv: ipVersion4, want: []net.IP{ip4, ip4}, wantErr: nil, @@ -168,12 +165,8 @@ func TestIfaceDNSIPAddrs(t *testing.T) { want: nil, wantErr: errTest, }, { - name: "ipv6_wait", - iface: &waitingFakeIface{ - addrs: []net.Addr{addr6}, - err: nil, - n: 1, - }, + name: "ipv6_wait", + iface: &waitingFakeIface{addrs: []net.Addr{addr6}, err: nil, n: 1}, ipv: ipVersion6, want: []net.IP{ip6, ip6}, wantErr: nil, @@ -182,8 +175,8 @@ func TestIfaceDNSIPAddrs(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got, gotErr := ifaceDNSIPAddrs(tc.iface, tc.ipv, 2, 0) + require.True(t, errors.Is(gotErr, tc.wantErr)) assert.Equal(t, tc.want, got) - assert.True(t, errors.Is(gotErr, tc.wantErr)) }) } } diff --git a/internal/dhcpd/v4_test.go b/internal/dhcpd/v4_test.go index 8edb31137ee..d204a200617 100644 --- a/internal/dhcpd/v4_test.go +++ b/internal/dhcpd/v4_test.go @@ -8,172 +8,182 @@ import ( "github.com/insomniacslk/dhcp/dhcpv4" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func notify4(flags uint32) { } -func TestV4StaticLeaseAddRemove(t *testing.T) { - conf := V4ServerConf{ +func TestV4_AddRemove_static(t *testing.T) { + s, err := v4Create(V4ServerConf{ Enabled: true, RangeStart: net.IP{192, 168, 10, 100}, RangeEnd: net.IP{192, 168, 10, 200}, GatewayIP: net.IP{192, 168, 10, 1}, SubnetMask: net.IP{255, 255, 255, 0}, notify: notify4, - } - s, err := v4Create(conf) - assert.Nil(t, err) + }) + require.Nil(t, err) ls := s.GetLeases(LeasesStatic) assert.Empty(t, ls) - // add static lease - l := Lease{} - l.IP = net.IP{192, 168, 10, 150} - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) - - // try to add the same static lease - fail + // Add static lease. + l := Lease{ + IP: net.IP{192, 168, 10, 150}, + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + } + require.Nil(t, s.AddStaticLease(l)) assert.NotNil(t, s.AddStaticLease(l)) - // check ls = s.GetLeases(LeasesStatic) - assert.Len(t, ls, 1) - assert.True(t, net.IP{192, 168, 10, 150}.Equal(ls[0].IP)) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) + require.Len(t, ls, 1) + assert.True(t, l.IP.Equal(ls[0].IP)) + assert.Equal(t, l.HWAddr, ls[0].HWAddr) assert.EqualValues(t, leaseExpireStatic, ls[0].Expiry.Unix()) - // try to remove static lease - fail - l.IP = net.IP{192, 168, 10, 110} - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.NotNil(t, s.RemoveStaticLease(l)) + // Try to remove static lease. + assert.NotNil(t, s.RemoveStaticLease(Lease{ + IP: net.IP{192, 168, 10, 110}, + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + })) - // remove static lease - l.IP = net.IP{192, 168, 10, 150} - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.RemoveStaticLease(l)) - - // check + // Remove static lease. + require.Nil(t, s.RemoveStaticLease(l)) ls = s.GetLeases(LeasesStatic) assert.Empty(t, ls) } -func TestV4StaticLeaseAddReplaceDynamic(t *testing.T) { - conf := V4ServerConf{ +func TestV4_AddReplace(t *testing.T) { + sIface, err := v4Create(V4ServerConf{ Enabled: true, RangeStart: net.IP{192, 168, 10, 100}, RangeEnd: net.IP{192, 168, 10, 200}, GatewayIP: net.IP{192, 168, 10, 1}, SubnetMask: net.IP{255, 255, 255, 0}, notify: notify4, - } - sIface, err := v4Create(conf) + }) + require.Nil(t, err) + s, ok := sIface.(*v4Server) - assert.True(t, ok) - assert.Nil(t, err) - - // add dynamic lease - ld := Lease{} - ld.IP = net.IP{192, 168, 10, 150} - ld.HWAddr, _ = net.ParseMAC("11:aa:aa:aa:aa:aa") - s.addLease(&ld) - - // add dynamic lease - { - ld := Lease{} - ld.IP = net.IP{192, 168, 10, 151} - ld.HWAddr, _ = net.ParseMAC("22:aa:aa:aa:aa:aa") - s.addLease(&ld) + require.True(t, ok) + + dynLeases := []Lease{{ + IP: net.IP{192, 168, 10, 150}, + HWAddr: net.HardwareAddr{0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }, { + IP: net.IP{192, 168, 10, 151}, + HWAddr: net.HardwareAddr{0x22, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }} + + for i := range dynLeases { + s.addLease(&dynLeases[i]) } - // add static lease with the same IP - l := Lease{} - l.IP = net.IP{192, 168, 10, 150} - l.HWAddr, _ = net.ParseMAC("33:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) + stLeases := []Lease{{ + IP: net.IP{192, 168, 10, 150}, + HWAddr: net.HardwareAddr{0x33, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }, { + IP: net.IP{192, 168, 10, 152}, + HWAddr: net.HardwareAddr{0x22, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }} - // add static lease with the same MAC - l = Lease{} - l.IP = net.IP{192, 168, 10, 152} - l.HWAddr, _ = net.ParseMAC("22:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) + for _, l := range stLeases { + require.Nil(t, s.AddStaticLease(l)) + } - // check ls := s.GetLeases(LeasesStatic) - assert.Len(t, ls, 2) - - assert.True(t, net.IP{192, 168, 10, 150}.Equal(ls[0].IP)) - assert.Equal(t, "33:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) - assert.EqualValues(t, leaseExpireStatic, ls[0].Expiry.Unix()) + require.Len(t, ls, 2) - assert.True(t, net.IP{192, 168, 10, 152}.Equal(ls[1].IP)) - assert.Equal(t, "22:aa:aa:aa:aa:aa", ls[1].HWAddr.String()) - assert.EqualValues(t, leaseExpireStatic, ls[1].Expiry.Unix()) + for i, l := range ls { + assert.True(t, stLeases[i].IP.Equal(l.IP)) + assert.Equal(t, stLeases[i].HWAddr, l.HWAddr) + assert.EqualValues(t, leaseExpireStatic, l.Expiry.Unix()) + } } -func TestV4StaticLeaseGet(t *testing.T) { - conf := V4ServerConf{ +func TestV4StaticLease_Get(t *testing.T) { + var err error + sIface, err := v4Create(V4ServerConf{ Enabled: true, RangeStart: net.IP{192, 168, 10, 100}, RangeEnd: net.IP{192, 168, 10, 200}, GatewayIP: net.IP{192, 168, 10, 1}, SubnetMask: net.IP{255, 255, 255, 0}, notify: notify4, - } - sIface, err := v4Create(conf) + }) + require.Nil(t, err) + s, ok := sIface.(*v4Server) - assert.True(t, ok) - assert.Nil(t, err) + require.True(t, ok) s.conf.dnsIPAddrs = []net.IP{{192, 168, 10, 1}} - l := Lease{} - l.IP = net.IP{192, 168, 10, 150} - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) - - // "Discover" - mac, _ := net.ParseMAC("aa:aa:aa:aa:aa:aa") - req, _ := dhcpv4.NewDiscovery(mac) - resp, _ := dhcpv4.NewReplyFromRequest(req) - assert.Equal(t, 1, s.process(req, resp)) - - // check "Offer" - assert.Equal(t, dhcpv4.MessageTypeOffer, resp.MessageType()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", resp.ClientHWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 150}.Equal(resp.YourIPAddr)) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.Router()[0])) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.ServerIdentifier())) - assert.True(t, net.IP{255, 255, 255, 0}.Equal(net.IP(resp.SubnetMask()))) - assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) - - // "Request" - req, _ = dhcpv4.NewRequestFromOffer(resp) - resp, _ = dhcpv4.NewReplyFromRequest(req) - assert.Equal(t, 1, s.process(req, resp)) - - // check "Ack" - assert.Equal(t, dhcpv4.MessageTypeAck, resp.MessageType()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", resp.ClientHWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 150}.Equal(resp.YourIPAddr)) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.Router()[0])) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.ServerIdentifier())) - assert.True(t, net.IP{255, 255, 255, 0}.Equal(net.IP(resp.SubnetMask()))) - assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + l := Lease{ + IP: net.IP{192, 168, 10, 150}, + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + } + require.Nil(t, s.AddStaticLease(l)) + + var req, resp *dhcpv4.DHCPv4 + mac := net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA} + + t.Run("discover", func(t *testing.T) { + var err error + + req, err = dhcpv4.NewDiscovery(mac) + require.Nil(t, err) + + resp, err = dhcpv4.NewReplyFromRequest(req) + require.Nil(t, err) + assert.Equal(t, 1, s.process(req, resp)) + }) + require.Nil(t, err) + + t.Run("offer", func(t *testing.T) { + assert.Equal(t, dhcpv4.MessageTypeOffer, resp.MessageType()) + assert.Equal(t, mac, resp.ClientHWAddr) + assert.True(t, l.IP.Equal(resp.YourIPAddr)) + assert.True(t, s.conf.GatewayIP.Equal(resp.Router()[0])) + assert.True(t, s.conf.GatewayIP.Equal(resp.ServerIdentifier())) + assert.Equal(t, s.conf.subnetMask, resp.SubnetMask()) + assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + }) + + t.Run("request", func(t *testing.T) { + req, err = dhcpv4.NewRequestFromOffer(resp) + require.Nil(t, err) + + resp, err = dhcpv4.NewReplyFromRequest(req) + require.Nil(t, err) + assert.Equal(t, 1, s.process(req, resp)) + }) + require.Nil(t, err) + + t.Run("ack", func(t *testing.T) { + assert.Equal(t, dhcpv4.MessageTypeAck, resp.MessageType()) + assert.Equal(t, mac, resp.ClientHWAddr) + assert.True(t, l.IP.Equal(resp.YourIPAddr)) + assert.True(t, s.conf.GatewayIP.Equal(resp.Router()[0])) + assert.True(t, s.conf.GatewayIP.Equal(resp.ServerIdentifier())) + assert.Equal(t, s.conf.subnetMask, resp.SubnetMask()) + assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + }) dnsAddrs := resp.DNS() - assert.Len(t, dnsAddrs, 1) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(dnsAddrs[0])) - - // check lease - ls := s.GetLeases(LeasesStatic) - assert.Len(t, ls, 1) - assert.True(t, net.IP{192, 168, 10, 150}.Equal(ls[0].IP)) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) + require.Len(t, dnsAddrs, 1) + assert.True(t, s.conf.GatewayIP.Equal(dnsAddrs[0])) + + t.Run("check_lease", func(t *testing.T) { + ls := s.GetLeases(LeasesStatic) + require.Len(t, ls, 1) + assert.True(t, l.IP.Equal(ls[0].IP)) + assert.Equal(t, mac, ls[0].HWAddr) + }) } -func TestV4DynamicLeaseGet(t *testing.T) { - conf := V4ServerConf{ +func TestV4DynamicLease_Get(t *testing.T) { + var err error + sIface, err := v4Create(V4ServerConf{ Enabled: true, RangeStart: net.IP{192, 168, 10, 100}, RangeEnd: net.IP{192, 168, 10, 200}, @@ -184,58 +194,97 @@ func TestV4DynamicLeaseGet(t *testing.T) { "81 hex 303132", "82 ip 1.2.3.4", }, - } - sIface, err := v4Create(conf) + }) + require.Nil(t, err) + s, ok := sIface.(*v4Server) - assert.True(t, ok) - assert.Nil(t, err) + require.True(t, ok) s.conf.dnsIPAddrs = []net.IP{{192, 168, 10, 1}} - // "Discover" - mac, _ := net.ParseMAC("aa:aa:aa:aa:aa:aa") - req, _ := dhcpv4.NewDiscovery(mac) - resp, _ := dhcpv4.NewReplyFromRequest(req) - assert.Equal(t, 1, s.process(req, resp)) - - // check "Offer" - assert.Equal(t, dhcpv4.MessageTypeOffer, resp.MessageType()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", resp.ClientHWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 100}.Equal(resp.YourIPAddr)) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.Router()[0])) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.ServerIdentifier())) - assert.True(t, net.IP{255, 255, 255, 0}.Equal(net.IP(resp.SubnetMask()))) - assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) - assert.Equal(t, []byte("012"), resp.Options[uint8(dhcpv4.OptionFQDN)]) - assert.True(t, net.IP{1, 2, 3, 4}.Equal(net.IP(resp.Options[uint8(dhcpv4.OptionRelayAgentInformation)]))) - - // "Request" - req, _ = dhcpv4.NewRequestFromOffer(resp) - resp, _ = dhcpv4.NewReplyFromRequest(req) - assert.Equal(t, 1, s.process(req, resp)) - - // check "Ack" - assert.Equal(t, dhcpv4.MessageTypeAck, resp.MessageType()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", resp.ClientHWAddr.String()) - assert.True(t, net.IP{192, 168, 10, 100}.Equal(resp.YourIPAddr)) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.Router()[0])) - assert.True(t, net.IP{192, 168, 10, 1}.Equal(resp.ServerIdentifier())) - assert.True(t, net.IP{255, 255, 255, 0}.Equal(net.IP(resp.SubnetMask()))) - assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + var req, resp *dhcpv4.DHCPv4 + mac := net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA} + + t.Run("discover", func(t *testing.T) { + req, err = dhcpv4.NewDiscovery(mac) + require.Nil(t, err) + + resp, err = dhcpv4.NewReplyFromRequest(req) + require.Nil(t, err) + assert.Equal(t, 1, s.process(req, resp)) + }) + require.Nil(t, err) + + t.Run("offer", func(t *testing.T) { + assert.Equal(t, dhcpv4.MessageTypeOffer, resp.MessageType()) + assert.Equal(t, mac, resp.ClientHWAddr) + assert.True(t, s.conf.RangeStart.Equal(resp.YourIPAddr)) + assert.True(t, s.conf.GatewayIP.Equal(resp.Router()[0])) + assert.True(t, s.conf.GatewayIP.Equal(resp.ServerIdentifier())) + assert.Equal(t, s.conf.subnetMask, resp.SubnetMask()) + assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + assert.Equal(t, []byte("012"), resp.Options[uint8(dhcpv4.OptionFQDN)]) + assert.True(t, net.IP{1, 2, 3, 4}.Equal(net.IP(resp.Options[uint8(dhcpv4.OptionRelayAgentInformation)]))) + }) + + t.Run("request", func(t *testing.T) { + var err error + + req, err = dhcpv4.NewRequestFromOffer(resp) + require.Nil(t, err) + + resp, err = dhcpv4.NewReplyFromRequest(req) + require.Nil(t, err) + assert.Equal(t, 1, s.process(req, resp)) + }) + require.Nil(t, err) + + t.Run("ack", func(t *testing.T) { + assert.Equal(t, dhcpv4.MessageTypeAck, resp.MessageType()) + assert.Equal(t, mac, resp.ClientHWAddr) + assert.True(t, s.conf.RangeStart.Equal(resp.YourIPAddr)) + assert.True(t, s.conf.GatewayIP.Equal(resp.Router()[0])) + assert.True(t, s.conf.GatewayIP.Equal(resp.ServerIdentifier())) + assert.Equal(t, s.conf.subnetMask, resp.SubnetMask()) + assert.Equal(t, s.conf.leaseTime.Seconds(), resp.IPAddressLeaseTime(-1).Seconds()) + }) dnsAddrs := resp.DNS() - assert.Len(t, dnsAddrs, 1) + require.Len(t, dnsAddrs, 1) assert.True(t, net.IP{192, 168, 10, 1}.Equal(dnsAddrs[0])) // check lease - ls := s.GetLeases(LeasesDynamic) - assert.Len(t, ls, 1) - assert.True(t, net.IP{192, 168, 10, 100}.Equal(ls[0].IP)) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) + t.Run("check_lease", func(t *testing.T) { + ls := s.GetLeases(LeasesDynamic) + assert.Len(t, ls, 1) + assert.True(t, net.IP{192, 168, 10, 100}.Equal(ls[0].IP)) + assert.Equal(t, mac, ls[0].HWAddr) + }) +} +func TestIP4InRange(t *testing.T) { start := net.IP{192, 168, 10, 100} stop := net.IP{192, 168, 10, 200} - assert.False(t, ip4InRange(start, stop, net.IP{192, 168, 10, 99})) - assert.False(t, ip4InRange(start, stop, net.IP{192, 168, 11, 100})) - assert.False(t, ip4InRange(start, stop, net.IP{192, 168, 11, 201})) - assert.True(t, ip4InRange(start, stop, net.IP{192, 168, 10, 100})) + + testCases := []struct { + ip net.IP + want bool + }{{ + ip: net.IP{192, 168, 10, 99}, + want: false, + }, { + ip: net.IP{192, 168, 11, 100}, + want: false, + }, { + ip: net.IP{192, 168, 11, 201}, + want: false, + }, { + ip: start, + want: true, + }} + + for _, tc := range testCases { + t.Run(tc.ip.String(), func(t *testing.T) { + assert.Equal(t, tc.want, ip4InRange(start, stop, tc.ip)) + }) + } } diff --git a/internal/dhcpd/v6_test.go b/internal/dhcpd/v6_test.go index 9cdf3ee4465..3eb06a89895 100644 --- a/internal/dhcpd/v6_test.go +++ b/internal/dhcpd/v6_test.go @@ -9,220 +9,283 @@ import ( "github.com/insomniacslk/dhcp/dhcpv6" "github.com/insomniacslk/dhcp/iana" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func notify6(flags uint32) { } -func TestV6StaticLeaseAddRemove(t *testing.T) { - conf := V6ServerConf{ +func TestV6_AddRemove_static(t *testing.T) { + s, err := v6Create(V6ServerConf{ Enabled: true, RangeStart: net.ParseIP("2001::1"), notify: notify6, + }) + require.Nil(t, err) + + require.Empty(t, s.GetLeases(LeasesStatic)) + + // Add static lease. + l := Lease{ + IP: net.ParseIP("2001::1"), + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, } - s, err := v6Create(conf) - assert.Nil(t, err) + require.Nil(t, s.AddStaticLease(l)) + + // Try to add the same static lease. + require.NotNil(t, s.AddStaticLease(l)) ls := s.GetLeases(LeasesStatic) - assert.Empty(t, ls) - - // add static lease - l := Lease{} - l.IP = net.ParseIP("2001::1") - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) - - // try to add static lease - fail - assert.NotNil(t, s.AddStaticLease(l)) - - // check - ls = s.GetLeases(LeasesStatic) - assert.Len(t, ls, 1) - assert.Equal(t, "2001::1", ls[0].IP.String()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) + require.Len(t, ls, 1) + assert.Equal(t, l.IP, ls[0].IP) + assert.Equal(t, l.HWAddr, ls[0].HWAddr) assert.EqualValues(t, leaseExpireStatic, ls[0].Expiry.Unix()) - // try to remove static lease - fail - l.IP = net.ParseIP("2001::2") - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.NotNil(t, s.RemoveStaticLease(l)) + // Try to remove non-existent static lease. + require.NotNil(t, s.RemoveStaticLease(Lease{ + IP: net.ParseIP("2001::2"), + HWAddr: l.HWAddr, + })) - // remove static lease - l.IP = net.ParseIP("2001::1") - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.RemoveStaticLease(l)) + // Remove static lease. + require.Nil(t, s.RemoveStaticLease(l)) - // check - ls = s.GetLeases(LeasesStatic) - assert.Empty(t, ls) + assert.Empty(t, s.GetLeases(LeasesStatic)) } -func TestV6StaticLeaseAddReplaceDynamic(t *testing.T) { - conf := V6ServerConf{ +func TestV6_AddReplace(t *testing.T) { + sIface, err := v6Create(V6ServerConf{ Enabled: true, RangeStart: net.ParseIP("2001::1"), notify: notify6, - } - sIface, err := v6Create(conf) + }) + require.Nil(t, err) s, ok := sIface.(*v6Server) - assert.True(t, ok) - assert.Nil(t, err) - - // add dynamic lease - ld := Lease{} - ld.IP = net.ParseIP("2001::1") - ld.HWAddr, _ = net.ParseMAC("11:aa:aa:aa:aa:aa") - s.addLease(&ld) - - // add dynamic lease - { - ld := Lease{} - ld.IP = net.ParseIP("2001::2") - ld.HWAddr, _ = net.ParseMAC("22:aa:aa:aa:aa:aa") - s.addLease(&ld) + require.True(t, ok) + + // Add dynamic leases. + dynLeases := []*Lease{{ + IP: net.ParseIP("2001::1"), + HWAddr: net.HardwareAddr{0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }, { + IP: net.ParseIP("2001::2"), + HWAddr: net.HardwareAddr{0x22, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }} + + for _, l := range dynLeases { + s.addLease(l) } - // add static lease with the same IP - l := Lease{} - l.IP = net.ParseIP("2001::1") - l.HWAddr, _ = net.ParseMAC("33:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) + stLeases := []Lease{{ + IP: net.ParseIP("2001::1"), + HWAddr: net.HardwareAddr{0x33, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }, { + IP: net.ParseIP("2001::3"), + HWAddr: net.HardwareAddr{0x22, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + }} - // add static lease with the same MAC - l = Lease{} - l.IP = net.ParseIP("2001::3") - l.HWAddr, _ = net.ParseMAC("22:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) + for _, l := range stLeases { + require.Nil(t, s.AddStaticLease(l)) + } - // check ls := s.GetLeases(LeasesStatic) - assert.Len(t, ls, 2) + require.Len(t, ls, 2) - assert.Equal(t, "2001::1", ls[0].IP.String()) - assert.Equal(t, "33:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) - assert.EqualValues(t, leaseExpireStatic, ls[0].Expiry.Unix()) - - assert.Equal(t, "2001::3", ls[1].IP.String()) - assert.Equal(t, "22:aa:aa:aa:aa:aa", ls[1].HWAddr.String()) - assert.EqualValues(t, leaseExpireStatic, ls[1].Expiry.Unix()) + for i, l := range ls { + assert.True(t, stLeases[i].IP.Equal(l.IP)) + assert.Equal(t, stLeases[i].HWAddr, l.HWAddr) + assert.EqualValues(t, leaseExpireStatic, l.Expiry.Unix()) + } } func TestV6GetLease(t *testing.T) { - conf := V6ServerConf{ + var err error + sIface, err := v6Create(V6ServerConf{ Enabled: true, RangeStart: net.ParseIP("2001::1"), notify: notify6, - } - sIface, err := v6Create(conf) + }) + require.Nil(t, err) s, ok := sIface.(*v6Server) - assert.True(t, ok) - assert.Nil(t, err) - s.conf.dnsIPAddrs = []net.IP{net.ParseIP("2000::1")} + require.True(t, ok) + + dnsAddr := net.ParseIP("2000::1") + s.conf.dnsIPAddrs = []net.IP{dnsAddr} s.sid = dhcpv6.Duid{ - Type: dhcpv6.DUID_LLT, - HwType: iana.HWTypeEthernet, + Type: dhcpv6.DUID_LLT, + HwType: iana.HWTypeEthernet, + LinkLayerAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, } - s.sid.LinkLayerAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - - l := Lease{} - l.IP = net.ParseIP("2001::1") - l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - assert.Nil(t, s.AddStaticLease(l)) - - // "Solicit" - mac, _ := net.ParseMAC("aa:aa:aa:aa:aa:aa") - req, _ := dhcpv6.NewSolicit(mac) - msg, _ := req.GetInnerMessage() - resp, _ := dhcpv6.NewAdvertiseFromSolicit(msg) - assert.True(t, s.process(msg, req, resp)) + + l := Lease{ + IP: net.ParseIP("2001::1"), + HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, + } + require.Nil(t, s.AddStaticLease(l)) + + var req, resp, msg *dhcpv6.Message + mac := net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA} + t.Run("solicit", func(t *testing.T) { + req, err = dhcpv6.NewSolicit(mac) + require.Nil(t, err) + + msg, err = req.GetInnerMessage() + require.Nil(t, err) + + resp, err = dhcpv6.NewAdvertiseFromSolicit(msg) + require.Nil(t, err) + + assert.True(t, s.process(msg, req, resp)) + }) + require.Nil(t, err) resp.AddOption(dhcpv6.OptServerID(s.sid)) - // check "Advertise" - assert.Equal(t, dhcpv6.MessageTypeAdvertise, resp.Type()) - oia := resp.Options.OneIANA() - oiaAddr := oia.Options.OneAddress() - assert.Equal(t, "2001::1", oiaAddr.IPv6Addr.String()) - assert.Equal(t, s.conf.leaseTime.Seconds(), oiaAddr.ValidLifetime.Seconds()) - - // "Request" - req, _ = dhcpv6.NewRequestFromAdvertise(resp) - msg, _ = req.GetInnerMessage() - resp, _ = dhcpv6.NewReplyFromMessage(msg) - assert.True(t, s.process(msg, req, resp)) - - // check "Reply" - assert.Equal(t, dhcpv6.MessageTypeReply, resp.Type()) - oia = resp.Options.OneIANA() - oiaAddr = oia.Options.OneAddress() - assert.Equal(t, "2001::1", oiaAddr.IPv6Addr.String()) - assert.Equal(t, s.conf.leaseTime.Seconds(), oiaAddr.ValidLifetime.Seconds()) + var oia *dhcpv6.OptIANA + var oiaAddr *dhcpv6.OptIAAddress + t.Run("advertise", func(t *testing.T) { + require.Equal(t, dhcpv6.MessageTypeAdvertise, resp.Type()) + oia = resp.Options.OneIANA() + oiaAddr = oia.Options.OneAddress() - dnsAddrs := resp.Options.DNS() - assert.Len(t, dnsAddrs, 1) - assert.Equal(t, "2000::1", dnsAddrs[0].String()) + assert.Equal(t, l.IP, oiaAddr.IPv6Addr) + assert.Equal(t, s.conf.leaseTime.Seconds(), oiaAddr.ValidLifetime.Seconds()) + }) - // check lease - ls := s.GetLeases(LeasesStatic) - assert.Len(t, ls, 1) - assert.Equal(t, "2001::1", ls[0].IP.String()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) + t.Run("request", func(t *testing.T) { + req, err = dhcpv6.NewRequestFromAdvertise(resp) + require.Nil(t, err) + + msg, err = req.GetInnerMessage() + require.Nil(t, err) + + resp, err = dhcpv6.NewReplyFromMessage(msg) + require.Nil(t, err) + + assert.True(t, s.process(msg, req, resp)) + }) + require.Nil(t, err) + + t.Run("reply", func(t *testing.T) { + require.Equal(t, dhcpv6.MessageTypeReply, resp.Type()) + oia = resp.Options.OneIANA() + oiaAddr = oia.Options.OneAddress() + + assert.Equal(t, l.IP, oiaAddr.IPv6Addr) + assert.Equal(t, s.conf.leaseTime.Seconds(), oiaAddr.ValidLifetime.Seconds()) + }) + + dnsAddrs := resp.Options.DNS() + require.Len(t, dnsAddrs, 1) + assert.Equal(t, dnsAddr, dnsAddrs[0]) + + t.Run("lease", func(t *testing.T) { + ls := s.GetLeases(LeasesStatic) + require.Len(t, ls, 1) + assert.Equal(t, l.IP, ls[0].IP) + assert.Equal(t, l.HWAddr, ls[0].HWAddr) + }) } func TestV6GetDynamicLease(t *testing.T) { - conf := V6ServerConf{ + sIface, err := v6Create(V6ServerConf{ Enabled: true, RangeStart: net.ParseIP("2001::2"), notify: notify6, - } - sIface, err := v6Create(conf) + }) + require.Nil(t, err) s, ok := sIface.(*v6Server) - assert.True(t, ok) - assert.Nil(t, err) - s.conf.dnsIPAddrs = []net.IP{net.ParseIP("2000::1")} + require.True(t, ok) + + dnsAddr := net.ParseIP("2000::1") + s.conf.dnsIPAddrs = []net.IP{dnsAddr} s.sid = dhcpv6.Duid{ - Type: dhcpv6.DUID_LLT, - HwType: iana.HWTypeEthernet, + Type: dhcpv6.DUID_LLT, + HwType: iana.HWTypeEthernet, + LinkLayerAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, } - s.sid.LinkLayerAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") - - // "Solicit" - mac, _ := net.ParseMAC("aa:aa:aa:aa:aa:aa") - req, _ := dhcpv6.NewSolicit(mac) - msg, _ := req.GetInnerMessage() - resp, _ := dhcpv6.NewAdvertiseFromSolicit(msg) - assert.True(t, s.process(msg, req, resp)) + + var req, resp, msg *dhcpv6.Message + mac := net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA} + t.Run("solicit", func(t *testing.T) { + req, err = dhcpv6.NewSolicit(mac) + require.Nil(t, err) + + msg, err = req.GetInnerMessage() + require.Nil(t, err) + + resp, err = dhcpv6.NewAdvertiseFromSolicit(msg) + require.Nil(t, err) + + assert.True(t, s.process(msg, req, resp)) + }) + require.Nil(t, err) resp.AddOption(dhcpv6.OptServerID(s.sid)) - // check "Advertise" - assert.Equal(t, dhcpv6.MessageTypeAdvertise, resp.Type()) - oia := resp.Options.OneIANA() - oiaAddr := oia.Options.OneAddress() - assert.Equal(t, "2001::2", oiaAddr.IPv6Addr.String()) + var oia *dhcpv6.OptIANA + var oiaAddr *dhcpv6.OptIAAddress + t.Run("advertise", func(t *testing.T) { + require.Equal(t, dhcpv6.MessageTypeAdvertise, resp.Type()) + oia = resp.Options.OneIANA() + oiaAddr = oia.Options.OneAddress() + assert.Equal(t, "2001::2", oiaAddr.IPv6Addr.String()) + }) + + t.Run("request", func(t *testing.T) { + req, err = dhcpv6.NewRequestFromAdvertise(resp) + require.Nil(t, err) + + msg, err = req.GetInnerMessage() + require.Nil(t, err) - // "Request" - req, _ = dhcpv6.NewRequestFromAdvertise(resp) - msg, _ = req.GetInnerMessage() - resp, _ = dhcpv6.NewReplyFromMessage(msg) - assert.True(t, s.process(msg, req, resp)) + resp, err = dhcpv6.NewReplyFromMessage(msg) + require.Nil(t, err) - // check "Reply" - assert.Equal(t, dhcpv6.MessageTypeReply, resp.Type()) - oia = resp.Options.OneIANA() - oiaAddr = oia.Options.OneAddress() - assert.Equal(t, "2001::2", oiaAddr.IPv6Addr.String()) + assert.True(t, s.process(msg, req, resp)) + }) + require.Nil(t, err) + + t.Run("reply", func(t *testing.T) { + require.Equal(t, dhcpv6.MessageTypeReply, resp.Type()) + oia = resp.Options.OneIANA() + oiaAddr = oia.Options.OneAddress() + assert.Equal(t, "2001::2", oiaAddr.IPv6Addr.String()) + }) dnsAddrs := resp.Options.DNS() - assert.Len(t, dnsAddrs, 1) - assert.Equal(t, "2000::1", dnsAddrs[0].String()) - - // check lease - ls := s.GetLeases(LeasesDynamic) - assert.Len(t, ls, 1) - assert.Equal(t, "2001::2", ls[0].IP.String()) - assert.Equal(t, "aa:aa:aa:aa:aa:aa", ls[0].HWAddr.String()) - - assert.False(t, ip6InRange(net.ParseIP("2001::2"), net.ParseIP("2001::1"))) - assert.False(t, ip6InRange(net.ParseIP("2001::2"), net.ParseIP("2002::2"))) - assert.True(t, ip6InRange(net.ParseIP("2001::2"), net.ParseIP("2001::2"))) - assert.True(t, ip6InRange(net.ParseIP("2001::2"), net.ParseIP("2001::3"))) + require.Len(t, dnsAddrs, 1) + assert.Equal(t, dnsAddr, dnsAddrs[0]) + + t.Run("lease", func(t *testing.T) { + ls := s.GetLeases(LeasesDynamic) + require.Len(t, ls, 1) + assert.Equal(t, "2001::2", ls[0].IP.String()) + assert.Equal(t, mac, ls[0].HWAddr) + }) +} + +func TestIP6InRange(t *testing.T) { + start := net.ParseIP("2001::2") + + testCases := []struct { + ip net.IP + want bool + }{{ + ip: net.ParseIP("2001::1"), + want: false, + }, { + ip: net.ParseIP("2002::2"), + want: false, + }, { + ip: start, + want: true, + }, { + ip: net.ParseIP("2001::3"), + want: true, + }} + + for _, tc := range testCases { + t.Run(tc.ip.String(), func(t *testing.T) { + assert.Equal(t, tc.want, ip6InRange(start, tc.ip)) + }) + } } diff --git a/internal/home/ipdetector_test.go b/internal/home/ipdetector_test.go index ee20612f80e..6609ba08f28 100644 --- a/internal/home/ipdetector_test.go +++ b/internal/home/ipdetector_test.go @@ -5,16 +5,15 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIPDetector_detectSpecialNetwork(t *testing.T) { var ipd *ipDetector + var err error - t.Run("newIPDetector", func(t *testing.T) { - var err error - ipd, err = newIPDetector() - assert.Nil(t, err) - }) + ipd, err = newIPDetector() + require.Nil(t, err) testCases := []struct { name string diff --git a/internal/home/middlewares_test.go b/internal/home/middlewares_test.go index 53b7a933d1c..fbd7a214758 100644 --- a/internal/home/middlewares_test.go +++ b/internal/home/middlewares_test.go @@ -9,6 +9,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghio" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestLimitRequestBody(t *testing.T) { @@ -60,8 +61,8 @@ func TestLimitRequestBody(t *testing.T) { lim.ServeHTTP(res, req) + require.Equal(t, tc.wantErr, err) assert.Equal(t, tc.want, res.Body.Bytes()) - assert.Equal(t, tc.wantErr, err) }) } } From 10f03b7527e0974a085aba8aeb4192e24b8ea19b Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 12 Feb 2021 16:40:34 +0300 Subject: [PATCH 13/35] Pull request: dhcpd: assume static ip on eperm Merge in DNS/adguard-home from 2667-eperm-dhcp to master Updates #2667. Squashed commit of the following: commit 7fad607ae0ae75419005707ee58312bc64fe78c5 Author: Ainar Garipov Date: Fri Feb 12 16:27:59 2021 +0300 dhcpd: assume static ip on eperm --- CHANGELOG.md | 3 +++ internal/dhcpd/{dhcphttp.go => http.go} | 16 +++++++++++++++- .../dhcpd/{dhcphttp_test.go => http_test.go} | 0 3 files changed, 18 insertions(+), 1 deletion(-) rename internal/dhcpd/{dhcphttp.go => http.go} (95%) rename internal/dhcpd/{dhcphttp_test.go => http_test.go} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 097f5c46424..23edf80421b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to ### Changed +- "Permission denied" errors when checking if the machine has a static IP no + longer prevent the DHCP server from starting ([#2667]). - The server name sent by clients of TLS APIs is not only checked when `strict_sni_check` is enabled ([#2664]). - HTTP API request body size limit for the `/control/access/set` API is @@ -40,6 +42,7 @@ and this project adheres to [#2663]: https://github.com/AdguardTeam/AdGuardHome/issues/2663 [#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 [#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 +[#2667]: https://github.com/AdguardTeam/AdGuardHome/issues/2667 diff --git a/internal/dhcpd/dhcphttp.go b/internal/dhcpd/http.go similarity index 95% rename from internal/dhcpd/dhcphttp.go rename to internal/dhcpd/http.go index 0a182cf08f0..de155c5cb93 100644 --- a/internal/dhcpd/dhcphttp.go +++ b/internal/dhcpd/http.go @@ -2,6 +2,7 @@ package dhcpd import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net" @@ -94,7 +95,20 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) { var hasStaticIP bool hasStaticIP, err = sysutil.IfaceHasStaticIP(ifaceName) if err != nil { - return http.StatusInternalServerError, fmt.Errorf("checking static ip: %w", err) + // ErrPermission may happen here on Linux systems where AdGuard + // Home is installed using Snap. That doesn't necessarily mean + // that the machine doesn't have a static IP, so we can assume + // that it has and go on. If the machine doesn't, we'll get an + // error later. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2667. + if errors.Is(err, os.ErrPermission) { + log.Info("error while checking static ip: %s; "+ + "assuming machine has static ip and going on", err) + hasStaticIP = true + } else { + return http.StatusInternalServerError, fmt.Errorf("checking static ip: %w", err) + } } if !hasStaticIP { diff --git a/internal/dhcpd/dhcphttp_test.go b/internal/dhcpd/http_test.go similarity index 100% rename from internal/dhcpd/dhcphttp_test.go rename to internal/dhcpd/http_test.go From e272e19516bff782c27bda5e15c6efb115a72d99 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 12 Feb 2021 18:56:18 +0300 Subject: [PATCH 14/35] Pull request: home: beta http server errorss are not fatal Merge in DNS/adguard-home from http-beta-no-fatal to master Squashed commit of the following: commit 13dcf7bca6d156f387639906c778fd6b07f491f3 Author: Ainar Garipov Date: Fri Feb 12 17:58:01 2021 +0300 home: beta http server errorss are not fatal --- internal/home/web.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/home/web.go b/internal/home/web.go index cdd19aba455..9cea9c7dca5 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -191,7 +191,10 @@ func (web *Web) Start() { WriteTimeout: web.conf.WriteTimeout, } go func() { - errs <- web.httpServerBeta.ListenAndServe() + betaErr := web.httpServerBeta.ListenAndServe() + if betaErr != nil { + log.Error("starting beta http server: %s", betaErr) + } }() } From 8a0bc5468b5173b27ab856ec636fe299a00737ad Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 13:32:16 +0300 Subject: [PATCH 15/35] Pull request #1004: dhcpd: fix dhcpv6 status json Merge in DNS/adguard-home from 2678-json-tag to master Updates #2678. Squashed commit of the following: commit 7c272ae8830ac10b0e0154656cf472b003315349 Author: Ainar Garipov Date: Mon Feb 15 13:14:16 2021 +0300 all: doc changes commit 3c964f814f2bc92e807aad3f5bad342eb455fe28 Author: Ainar Garipov Date: Mon Feb 15 12:54:27 2021 +0300 dhcpd: fix dhcpv6 status json --- CHANGELOG.md | 7 +++++-- internal/dhcpd/server.go | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23edf80421b..4a7407c13ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,11 +23,13 @@ and this project adheres to longer prevent the DHCP server from starting ([#2667]). - The server name sent by clients of TLS APIs is not only checked when `strict_sni_check` is enabled ([#2664]). -- HTTP API request body size limit for the `/control/access/set` API is - increased ([#2666]). +- HTTP API request body size limit for the `POST /control/access/set` HTTP API + is increased ([#2666]). ### Fixed +- The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response + is now correctly named again ([#2678]). - DHCPv6 server's `ra_slaac_only` and `ra_allow_slaac` settings aren't reset to `false` on update any more ([#2653]). - The `Vary` header is now added along with `Access-Control-Allow-Origin` to @@ -43,6 +45,7 @@ and this project adheres to [#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 [#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 [#2667]: https://github.com/AdguardTeam/AdGuardHome/issues/2667 +[#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678 diff --git a/internal/dhcpd/server.go b/internal/dhcpd/server.go index 1d3ce4609f8..2fac533e85c 100644 --- a/internal/dhcpd/server.go +++ b/internal/dhcpd/server.go @@ -79,7 +79,7 @@ type V6ServerConf struct { // The first IP address for dynamic leases // The last allowed IP address ends with 0xff byte - RangeStart net.IP `yaml:"range_start"` + RangeStart net.IP `yaml:"range_start" json:"range_start"` LeaseDuration uint32 `yaml:"lease_duration" json:"lease_duration"` // in seconds From 7d1ca48ae49689766dd294e32ad6db3b2deaa52f Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 13:56:41 +0300 Subject: [PATCH 16/35] Pull request #1005: home: imp large req handling Merge in DNS/adguard-home from 2675-larger-requests to master Updates #2675. Squashed commit of the following: commit 2b45c9bfdc817980204b11de768b425fb72a6488 Author: Ainar Garipov Date: Mon Feb 15 13:38:44 2021 +0300 home: imp names commit dad39ae7ee35346ea91f15665acc93ba0b5653df Author: Ainar Garipov Date: Mon Feb 15 13:31:53 2021 +0300 home: imp large req handling --- CHANGELOG.md | 5 ++-- internal/home/middlewares.go | 38 +++++++++++++++++++++++-------- internal/home/middlewares_test.go | 6 ++--- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a7407c13ef..775ebcc87d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,8 @@ and this project adheres to longer prevent the DHCP server from starting ([#2667]). - The server name sent by clients of TLS APIs is not only checked when `strict_sni_check` is enabled ([#2664]). -- HTTP API request body size limit for the `POST /control/access/set` HTTP API - is increased ([#2666]). +- HTTP API request body size limit for the `POST /control/access/set` and `POST + /control/filtering/set_rules` HTTP APIs is increased ([#2666], [#2675]). ### Fixed @@ -45,6 +45,7 @@ and this project adheres to [#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 [#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 [#2667]: https://github.com/AdguardTeam/AdGuardHome/issues/2667 +[#2675]: https://github.com/AdguardTeam/AdGuardHome/issues/2675 [#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678 diff --git a/internal/home/middlewares.go b/internal/home/middlewares.go index 7d34f73e946..de38c3faa2c 100644 --- a/internal/home/middlewares.go +++ b/internal/home/middlewares.go @@ -22,8 +22,30 @@ func withMiddlewares(h http.Handler, middlewares ...middleware) (wrapped http.Ha return wrapped } -// RequestBodySizeLimit is maximum request body length in bytes. -const RequestBodySizeLimit = 64 * 1024 +// defaultReqBodySzLim is the default maximum request body size. +const defaultReqBodySzLim = 64 * 1024 + +// largerReqBodySzLim is the maximum request body size for APIs expecting larger +// requests. +const largerReqBodySzLim = 4 * 1024 * 1024 + +// expectsLargerRequests shows if this request should use a larger body size +// limit. These are exceptions for poorly designed current APIs as well as APIs +// that are designed to expect large files and requests. Remove once the new, +// better APIs are up. +// +// See https://github.com/AdguardTeam/AdGuardHome/issues/2666 and +// https://github.com/AdguardTeam/AdGuardHome/issues/2675. +func expectsLargerRequests(r *http.Request) (ok bool) { + m := r.Method + if m != http.MethodPost { + return false + } + + p := r.URL.Path + return p == "/control/access/set" || + p == "/control/filtering/set_rules" +} // limitRequestBody wraps underlying handler h, making it's request's body Read // method limited. @@ -31,16 +53,12 @@ func limitRequestBody(h http.Handler) (limited http.Handler) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var err error - var bodySizeLimit int64 = RequestBodySizeLimit - if u := r.URL; u.Path == "/control/access/set" { - // An exception for a poorly designed API. Remove once - // the new, better API is up. - // - // See https://github.com/AdguardTeam/AdGuardHome/issues/2666. - bodySizeLimit *= 4 + var szLim int64 = defaultReqBodySzLim + if expectsLargerRequests(r) { + szLim = largerReqBodySzLim } - r.Body, err = aghio.LimitReadCloser(r.Body, bodySizeLimit) + r.Body, err = aghio.LimitReadCloser(r.Body, szLim) if err != nil { log.Error("limitRequestBody: %s", err) diff --git a/internal/home/middlewares_test.go b/internal/home/middlewares_test.go index fbd7a214758..8397302bdb3 100644 --- a/internal/home/middlewares_test.go +++ b/internal/home/middlewares_test.go @@ -14,7 +14,7 @@ import ( func TestLimitRequestBody(t *testing.T) { errReqLimitReached := &aghio.LimitReachedError{ - Limit: RequestBodySizeLimit, + Limit: defaultReqBodySzLim, } testCases := []struct { @@ -29,8 +29,8 @@ func TestLimitRequestBody(t *testing.T) { wantErr: nil, }, { name: "so_big", - body: string(make([]byte, RequestBodySizeLimit+1)), - want: make([]byte, RequestBodySizeLimit), + body: string(make([]byte, defaultReqBodySzLim+1)), + want: make([]byte, defaultReqBodySzLim), wantErr: errReqLimitReached, }, { name: "empty", From aebcd74efe5fedfcf4db7229d171471c26dd8a69 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 14:20:23 +0300 Subject: [PATCH 17/35] Pull request: home: imp init Merge in DNS/adguard-home from fix-init to master Squashed commit of the following: commit 551c143f6c3846f061b3118a06e1c756bc3e2ba1 Author: Ainar Garipov Date: Mon Feb 15 13:45:06 2021 +0300 home: imp init --- CHANGELOG.md | 1 + internal/home/home.go | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 775ebcc87d0..f84a1b6acd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to ### Fixed +- Occasional crashes during startup. - The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response is now correctly named again ([#2678]). - DHCPv6 server's `ra_slaac_only` and `ra_allow_slaac` settings aren't reset to diff --git a/internal/home/home.go b/internal/home/home.go index 1b6312c8c60..8db077edab6 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -304,6 +304,11 @@ func run(args options) { log.Fatalf("Can't initialize Web module") } + Context.ipDetector, err = newIPDetector() + if err != nil { + log.Fatal(err) + } + if !Context.firstRun { err := initDNSServer() if err != nil { @@ -324,11 +329,6 @@ func run(args options) { } } - Context.ipDetector, err = newIPDetector() - if err != nil { - log.Fatal(err) - } - Context.web.Start() // wait indefinitely for other go-routines to complete their job From d295621352f7dde326529a5d58bc6c9ed7db39bf Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 15:36:38 +0300 Subject: [PATCH 18/35] Pull request: home: inc http timeouts Merge in DNS/adguard-home from 2671-timeout to master Updates #2671. Updates #2682. Squashed commit of the following: commit 79b1a36a79e3c7c26fc1a4b171feb050690f8c83 Author: Ainar Garipov Date: Mon Feb 15 15:25:26 2021 +0300 all: doc changes commit 84229b782bde433faa4ed8b71dd092965787d30e Author: Ainar Garipov Date: Mon Feb 15 15:12:33 2021 +0300 home: imp names commit b18d7b08473c99ddd37ecfa14be8d48838c2afab Author: Ainar Garipov Date: Mon Feb 15 15:04:27 2021 +0300 home: inc http timeouts --- CHANGELOG.md | 3 +++ internal/home/home.go | 6 +++--- internal/home/web.go | 15 ++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f84a1b6acd3..bb24fb1fe01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to ### Changed +- Increased HTTP API timeouts ([#2671], [#2682]). - "Permission denied" errors when checking if the machine has a static IP no longer prevent the DHCP server from starting ([#2667]). - The server name sent by clients of TLS APIs is not only checked when @@ -46,8 +47,10 @@ and this project adheres to [#2664]: https://github.com/AdguardTeam/AdGuardHome/issues/2664 [#2666]: https://github.com/AdguardTeam/AdGuardHome/issues/2666 [#2667]: https://github.com/AdguardTeam/AdGuardHome/issues/2667 +[#2671]: https://github.com/AdguardTeam/AdGuardHome/issues/2671 [#2675]: https://github.com/AdguardTeam/AdGuardHome/issues/2675 [#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678 +[#2682]: https://github.com/AdguardTeam/AdGuardHome/issues/2682 diff --git a/internal/home/home.go b/internal/home/home.go index 8db077edab6..422312a6783 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -295,9 +295,9 @@ func run(args options) { BindPort: config.BindPort, BetaBindPort: config.BetaBindPort, - ReadTimeout: ReadTimeout, - ReadHeaderTimeout: ReadHeaderTimeout, - WriteTimeout: WriteTimeout, + ReadTimeout: readTimeout, + ReadHeaderTimeout: readHdrTimeout, + WriteTimeout: writeTimeout, } Context.web = CreateWeb(&webConf) if Context.web == nil { diff --git a/internal/home/web.go b/internal/home/web.go index 9cea9c7dca5..fff2aa07ece 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -16,17 +16,14 @@ import ( ) const ( - // ReadTimeout is the maximum duration for reading the entire request, + // readTimeout is the maximum duration for reading the entire request, // including the body. - ReadTimeout = 10 * time.Second - - // ReadHeaderTimeout is the amount of time allowed to read request - // headers. - ReadHeaderTimeout = 10 * time.Second - - // WriteTimeout is the maximum duration before timing out writes of the + readTimeout = 30 * time.Second + // readHdrTimeout is the amount of time allowed to read request headers. + readHdrTimeout = 30 * time.Second + // writeTimeout is the maximum duration before timing out writes of the // response. - WriteTimeout = 10 * time.Second + writeTimeout = 30 * time.Second ) type webConfig struct { From ab81ff03f6b1f624f5b70e2f750c502daa4efefb Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 15:53:24 +0300 Subject: [PATCH 19/35] Pull request: all: upd translations Merge in DNS/adguard-home from upd-locales to master Updates #2643. Squashed commit of the following: commit d7f26aaa63bfc9307887301abfff4779be7eba41 Author: Ainar Garipov Date: Thu Feb 11 16:18:54 2021 +0300 all: upd translations --- client/src/__locales/be.json | 11 + client/src/__locales/cs.json | 1 + client/src/__locales/da.json | 1 + client/src/__locales/de.json | 1 + client/src/__locales/en.json | 2 +- client/src/__locales/es.json | 17 +- client/src/__locales/fr.json | 1 + client/src/__locales/hr.json | 11 + client/src/__locales/it.json | 1 + client/src/__locales/ja.json | 1 + client/src/__locales/ko.json | 1 + client/src/__locales/nl.json | 1 + client/src/__locales/no.json | 4 + client/src/__locales/pl.json | 1 + client/src/__locales/pt-br.json | 1 + client/src/__locales/pt-pt.json | 1 + client/src/__locales/ro.json | 1 + client/src/__locales/ru.json | 1 + client/src/__locales/si-lk.json | 12 +- client/src/__locales/sk.json | 1 + client/src/__locales/sl.json | 1 + client/src/__locales/tr.json | 1 + client/src/__locales/vi.json | 1 + client/src/__locales/zh-cn.json | 1 + client/src/__locales/zh-tw.json | 11 +- scripts/translations/package-lock.json | 468 ++++++++++++++++++++++++- 26 files changed, 533 insertions(+), 21 deletions(-) diff --git a/client/src/__locales/be.json b/client/src/__locales/be.json index e2d35a79e63..b89af602584 100644 --- a/client/src/__locales/be.json +++ b/client/src/__locales/be.json @@ -32,6 +32,7 @@ "form_error_ip_format": "Няслушны фармат IP-адраса", "form_error_mac_format": "Некарэктны фармат MAC", "form_error_client_id_format": "Няслушны фармат ID кліента", + "form_error_server_name": "Няслушнае імя сервера", "form_error_positive": "Павінна быць больш 0", "form_error_negative": "Павінна быць не менш 0", "range_end_error": "Павінен перавышаць пачатак дыяпазону", @@ -247,10 +248,16 @@ "custom_ip": "Свой IP", "blocking_ipv4": "Блакаванне IPv4", "blocking_ipv6": "Блакаванне IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "dns_over_quic": "DNS-over-QUIC", + "client_id": "Ідэнтыфікатар кліента", + "client_id_placeholder": "Увядзіце ідэнтыфікатар кліента", + "client_id_desc": "Розныя кліенты могуць ідэнтыфікавацца па адмысловым ідэнтыфікатары кліента. Тут вы можаце даведацца больш пра ідэнтыфікацыю кліентаў.", "download_mobileconfig_doh": "Спампаваць .mobileconfig для DNS-over-HTTPS", "download_mobileconfig_dot": "Спампаваць .mobileconfig для DNS-over-TLS", + "download_mobileconfig": "Загрузіць файл канфігурацыі", "plain_dns": "Нешыфраваны DNS", "form_enter_rate_limit": "Увядзіце rate limit", "rate_limit": "Ограничение скорости", @@ -269,6 +276,7 @@ "source_label": "Крыніца", "found_in_known_domain_db": "Знойдзены ў базе вядомых даменаў.", "category_label": "Катэгорыя", + "rule_label": "Правіла(ы)", "list_label": "Спіс", "unknown_filter": "Невядомы фільтр {{filterId}}", "known_tracker": "Вядомы трэкер", @@ -329,6 +337,7 @@ "encryption_config_saved": "Налады шыфравання захаваны", "encryption_server": "Імя сервера", "encryption_server_enter": "Увядзіце ваша даменавае імя", + "encryption_server_desc": "Для выкарыстання HTTPS вам трэба ўвесці імя сервера, якое падыходзіць вашаму SSL-сертыфікату.", "encryption_redirect": "Аўтаматычна перанакіроўваць на HTTPS", "encryption_redirect_desc": "Калі ўлучана, AdGuard Home будзе аўтаматычна перанакіроўваць вас з HTTP на HTTPS адрас.", "encryption_https": "Порт HTTPS", @@ -384,6 +393,7 @@ "client_edit": "Рэдагаваць кліента", "client_identifier": "Ідэнтыфікатар", "ip_address": "IP-адрас", + "client_identifier_desc": "Кліенты могуць быць ідэнтыфікаваны па IP-адрасе, CIDR ці MAC-адрасу. Звярніце ўвагу, што выкарыстанне MAC як ідэнтыфікатара магчыма, толькі калі AdGuard Home таксама з'яўляецца і <0>DHCP-серверам", "form_enter_ip": "Увядзіце IP", "form_enter_mac": "Увядзіце MAC", "form_enter_id": "Увядзіце ідэнтыфікатар", @@ -427,6 +437,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy падтрымвае <1>DNS-over-HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox падтрымвае <1>DNS-over-HTTPS.", "setup_dns_privacy_other_5": "Вы можаце знайсці яшчэ варыянты <0>тут і <1>тут.", + "setup_dns_privacy_ioc_mac": "Канфігурацыя для iOS і macOS", "setup_dns_notice": "Каб выкарыстоўваць <1>DNS-over-HTTPS ці <1>DNS-over-TLS, вам патрэбна <0>наладзіць шыфраванне у наладах AdGuard Home.", "rewrite_added": "Правіла перанакіравання DNS для \"{{key}}\" паспяхова дададзена", "rewrite_deleted": "Правіла перанакіравання DNS для \"{{key}}\" паспяхова выдалена", diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index ca5d8a5c82b..84cf3e32e52 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -248,6 +248,7 @@ "custom_ip": "Vlastní IP", "blocking_ipv4": "Blokování IPv4", "blocking_ipv6": "Blokování IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS přes HTTPS", "dns_over_tls": "DNS přes TLS", "dns_over_quic": "DNS skrze QUIC", diff --git a/client/src/__locales/da.json b/client/src/__locales/da.json index 97105ad365c..3ba7f9b4a26 100644 --- a/client/src/__locales/da.json +++ b/client/src/__locales/da.json @@ -248,6 +248,7 @@ "custom_ip": "Tilpasset IP", "blocking_ipv4": "IPv4-blokering", "blocking_ipv6": "IPv6-blokering", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-Quic", diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index 7e35661e1a8..17d5832ee8a 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -248,6 +248,7 @@ "custom_ip": "Benutzerdefinierte IP", "blocking_ipv4": "IPv4-Sperren", "blocking_ipv6": "IPv6-Sperren", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS (DNS-Abrage über HTTPS)", "dns_over_tls": "DNS-over-TLS (DNS-Abrage über TLS)", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index b558dd60713..3b0aa663425 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -594,4 +594,4 @@ "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.", "client_not_in_allowed_clients": "The client is not allowed because it is not in the \"Allowed clients\" list.", "experimental": "Experimental" -} +} \ No newline at end of file diff --git a/client/src/__locales/es.json b/client/src/__locales/es.json index 3be25fac3bf..cf0d7d024e8 100644 --- a/client/src/__locales/es.json +++ b/client/src/__locales/es.json @@ -248,15 +248,16 @@ "custom_ip": "IP personalizada", "blocking_ipv4": "Bloqueo de IPv4", "blocking_ipv6": "Bloqueo de IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS mediante HTTPS", "dns_over_tls": "DNS mediante TLS", - "dns_over_quic": "DNS-over-QUIC", + "dns_over_quic": "DNS mediante QUIC", "client_id": "ID de cliente", - "client_id_placeholder": "Ingresa tu ID de cliente", - "client_id_desc": "Varios clientes se pueden identificar mediante un ID de cliente especial. Aquí puede aprender más sobre cómo identificar clientes.", + "client_id_placeholder": "Ingresa el ID del cliente", + "client_id_desc": "Diferentes clientes pueden ser identificados por un ID de cliente especial. Aquí puedes obtener más información sobre cómo identificar clientes.", "download_mobileconfig_doh": "Descargar .mobileconfig para DNS mediante HTTPS", "download_mobileconfig_dot": "Descargar .mobileconfig para DNS mediante TLS", - "download_mobileconfig": "Descargar el archivo de configuración", + "download_mobileconfig": "Descargar archivo de configuración", "plain_dns": "DNS simple", "form_enter_rate_limit": "Ingresa el límite de cantidad", "rate_limit": "Límite de cantidad", @@ -275,7 +276,7 @@ "source_label": "Fuente", "found_in_known_domain_db": "Encontrado en la base de datos de dominios conocidos.", "category_label": "Categoría", - "rule_label": "Regla(s)", + "rule_label": "Regla", "list_label": "Lista", "unknown_filter": "Filtro desconocido {{filterId}}", "known_tracker": "Rastreador conocido", @@ -336,7 +337,7 @@ "encryption_config_saved": "Configuración de cifrado guardado", "encryption_server": "Nombre del servidor", "encryption_server_enter": "Ingresa el nombre del dominio", - "encryption_server_desc": "Para utilizar HTTPS, debes ingresar el nombre del servidor que coincida con tu certificado SSL o certificado Wildcard. Si el campo no está establecido, el servidor aceptará conexiones TLS para cualquier dominio.", + "encryption_server_desc": "Para utilizar HTTPS, debes ingresar el nombre del servidor que coincida con tu certificado SSL o certificado comodín. Si el campo no está establecido, el servidor aceptará conexiones TLS para cualquier dominio.", "encryption_redirect": "Redireccionar a HTTPS automáticamente", "encryption_redirect_desc": "Si está marcado, AdGuard Home redireccionará automáticamente de HTTP a las direcciones HTTPS.", "encryption_https": "Puerto HTTPS", @@ -392,7 +393,7 @@ "client_edit": "Editar cliente", "client_identifier": "Identificador", "ip_address": "Dirección IP", - "client_identifier_desc": "Los clientes pueden ser identificados por la dirección IP, MAC, CIDR o un especial ID de cliente (puede ser utilizado para DoT/DoH/DoQ). <0>Aquí puede obtener más información sobre cómo identificar clientes.", + "client_identifier_desc": "Los clientes pueden ser identificados por la dirección IP, MAC, CIDR o un ID de cliente especial (puede ser utilizado para DoT/DoH/DoQ). <0>Aquí puedes obtener más información sobre cómo identificar clientes.", "form_enter_ip": "Ingresa la IP", "form_enter_mac": "Ingresa la MAC", "form_enter_id": "Ingresa el identificador", @@ -436,7 +437,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy soporta <1>DNS mediante HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox soporta <1>DNS mediante HTTPS.", "setup_dns_privacy_other_5": "Encontrarás más implementaciones <0>aquí y <1>aquí.", - "setup_dns_privacy_ioc_mac": "La configuración de iOS y macOS ", + "setup_dns_privacy_ioc_mac": "Configuración de iOS y macOS", "setup_dns_notice": "Para utilizar <1>DNS mediante HTTPS o <1>DNS mediante TLS, debes <0>configurar el cifrado en la configuración de AdGuard Home.", "rewrite_added": "Reescritura DNS para \"{{key}}\" añadido correctamente", "rewrite_deleted": "Reescritura DNS para \"{{key}}\" eliminado correctamente", diff --git a/client/src/__locales/fr.json b/client/src/__locales/fr.json index 36ec94e7d22..064f4ccc628 100644 --- a/client/src/__locales/fr.json +++ b/client/src/__locales/fr.json @@ -248,6 +248,7 @@ "custom_ip": "IP personnalisée", "blocking_ipv4": "Blocage IPv4", "blocking_ipv6": "Blocage IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/hr.json b/client/src/__locales/hr.json index 7b02b4d01f3..ab5567f0fbe 100644 --- a/client/src/__locales/hr.json +++ b/client/src/__locales/hr.json @@ -32,6 +32,7 @@ "form_error_ip_format": "Nevažeći format IP adrese", "form_error_mac_format": "Nevažeći MAC format", "form_error_client_id_format": "Nevažeći format ID-a klijenta", + "form_error_server_name": "Nevažeće ime poslužitelja", "form_error_positive": "Mora biti veće od 0", "form_error_negative": "Mora biti jednako ili veće od 0", "range_end_error": "Mora biti veće od početne vrijednosti raspona", @@ -247,10 +248,16 @@ "custom_ip": "Prilagođen IP", "blocking_ipv4": "Blokiranje IPv4", "blocking_ipv6": "Blokiranje IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "dns_over_quic": "DNS-over-Quic", + "client_id": "ID klijenta", + "client_id_placeholder": "Unesite ID klijenta", + "client_id_desc": "Razni klijenti mogu biti prepoznati po specijalnom identifikatoru. Ovdje možete saznati više kako možete identificirati klijente.", "download_mobileconfig_doh": "Preuzmi .mobileconfig za DNS-over-HTTPS", "download_mobileconfig_dot": "Preuzmi .mobileconfig za DNS-over-TLS", + "download_mobileconfig": "Preuzmite konfiguracijsku datoteku", "plain_dns": "Obični DNS", "form_enter_rate_limit": "Unesite ograničenje", "rate_limit": "Ograničenje", @@ -269,6 +276,7 @@ "source_label": "Izvor", "found_in_known_domain_db": "Pronađeno u bazi poznatih domena.", "category_label": "Kategorija", + "rule_label": "Pravilo", "list_label": "Popis", "unknown_filter": "Nepoznati filtar {{filterId}}", "known_tracker": "Poznati pratitelj", @@ -329,6 +337,7 @@ "encryption_config_saved": "Spremljene postavke šifriranja", "encryption_server": "Naziv poslužitelja", "encryption_server_enter": "Unesite naziv domene", + "encryption_server_desc": "Kako biste koristili HTTPS, morate unijeti naziv poslužitelja koji odgovara vašem SSL certifikatu.", "encryption_redirect": "Automatski preusmjeri na HTTPS", "encryption_redirect_desc": "Ako je omogućeno, AdGuard Home će vas automatski preusmjeravati s HTTP na HTTPS adrese.", "encryption_https": "HTTPS port", @@ -384,6 +393,7 @@ "client_edit": "Uredi klijenta", "client_identifier": "Identifikator", "ip_address": "IP adresa", + "client_identifier_desc": "Klijenti se mogu prepoznati po IP adresi, CIDR-u ili MAC adresi. Imajte na umu da je upotreba MAC-a kao identifikatora, moguća samo ako je AdGuard Home također i <0>DHCP poslužitelj", "form_enter_ip": "Unesite IP adresu", "form_enter_mac": "Unesite MAC adresu", "form_enter_id": "Unesi identifikator", @@ -427,6 +437,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy podržava <1>DNS-over-HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox podržava <1>DNS-over-HTTPS.", "setup_dns_privacy_other_5": "Možete pronaći više implementacija <0>ovdje i <1>ovdje.", + "setup_dns_privacy_ioc_mac": "konfiguracija za iOS i macOS", "setup_dns_notice": "Da biste koristili <1>DNS-over-HTTPS ili <1>DNS-over-TLS, morate <0>postaviti šifriranje u AdGuard Home postavkama.", "rewrite_added": "DNS prijepis za \"{{key}}\" je uspješno dodan", "rewrite_deleted": "DNS prijepis za \"{{key}}\" je uspješno uklonjen", diff --git a/client/src/__locales/it.json b/client/src/__locales/it.json index 5079165bd41..1f3a02078d4 100644 --- a/client/src/__locales/it.json +++ b/client/src/__locales/it.json @@ -248,6 +248,7 @@ "custom_ip": "IP personalizzato", "blocking_ipv4": "Blocca IPv4", "blocking_ipv6": "Blocca IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS su HTTPS", "dns_over_tls": "DNS su TLS", "dns_over_quic": "DNS su Quic", diff --git a/client/src/__locales/ja.json b/client/src/__locales/ja.json index 6c4ef890246..7eb453260f5 100644 --- a/client/src/__locales/ja.json +++ b/client/src/__locales/ja.json @@ -248,6 +248,7 @@ "custom_ip": "カスタムIP", "blocking_ipv4": "ブロック中のIPv4", "blocking_ipv6": "ブロック中のIPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/ko.json b/client/src/__locales/ko.json index c266c8c4d23..2f25cbc6ffa 100644 --- a/client/src/__locales/ko.json +++ b/client/src/__locales/ko.json @@ -248,6 +248,7 @@ "custom_ip": "사용자 지정 IP", "blocking_ipv4": "IPv4 차단", "blocking_ipv6": "IPv6 차단", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index d5be0f992c8..b903ced69ff 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -248,6 +248,7 @@ "custom_ip": "Aangepast IP", "blocking_ipv4": "Blokkeren IP4", "blocking_ipv6": "Blokkeren IP6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-via-HTTPS", "dns_over_tls": "DNS-via-TLS", "dns_over_quic": "DNS-via-QUIC", diff --git a/client/src/__locales/no.json b/client/src/__locales/no.json index 58637b4a3d6..dde12de0b0f 100644 --- a/client/src/__locales/no.json +++ b/client/src/__locales/no.json @@ -32,6 +32,7 @@ "form_error_ip_format": "Ugyldig IPv4-format", "form_error_mac_format": "Ugyldig MAC-format", "form_error_client_id_format": "Ugyldig ID-klientformat", + "form_error_server_name": "Ugyldig tjenernavn", "form_error_positive": "Må være høyere enn 0", "form_error_negative": "Må være ≥0", "range_end_error": "Må være høyere enn rekkeviddens start", @@ -247,8 +248,11 @@ "custom_ip": "Tilpasset IP", "blocking_ipv4": "IPv4-blokkering", "blocking_ipv6": "IPv6-blokkering", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "dns_over_quic": "DNS-over-QUIC", + "client_id": "Klient-ID", "download_mobileconfig_doh": "Last ned .mobileconfig for DNS-over-HTTPS", "download_mobileconfig_dot": "Last ned .mobileconfig for DNS-over-TLS", "plain_dns": "Ordinær DNS", diff --git a/client/src/__locales/pl.json b/client/src/__locales/pl.json index 55f172b3bbe..e44ef6d4e04 100644 --- a/client/src/__locales/pl.json +++ b/client/src/__locales/pl.json @@ -248,6 +248,7 @@ "custom_ip": "Niestandardowy adres IP", "blocking_ipv4": "Blokowanie IPv4", "blocking_ipv6": "Blokowanie IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/pt-br.json b/client/src/__locales/pt-br.json index 01a3a933dea..844aa1b6063 100644 --- a/client/src/__locales/pt-br.json +++ b/client/src/__locales/pt-br.json @@ -248,6 +248,7 @@ "custom_ip": "IP personalizado", "blocking_ipv4": "Bloqueando IPv4", "blocking_ipv6": "Bloqueando IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-sobre-HTTPS", "dns_over_tls": "DNS-sobre-TLS", "dns_over_quic": "DNS-sobre-QUIC", diff --git a/client/src/__locales/pt-pt.json b/client/src/__locales/pt-pt.json index e8c70cc941d..8e08db076df 100644 --- a/client/src/__locales/pt-pt.json +++ b/client/src/__locales/pt-pt.json @@ -248,6 +248,7 @@ "custom_ip": "IP Personalizado", "blocking_ipv4": "A bloquear IPv4", "blocking_ipv6": "A bloquear IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-sobre-HTTPS", "dns_over_tls": "DNS-sobre-TLS", "dns_over_quic": "DNS-sobre-QUIC", diff --git a/client/src/__locales/ro.json b/client/src/__locales/ro.json index 6523bd30dfc..80929301d3d 100644 --- a/client/src/__locales/ro.json +++ b/client/src/__locales/ro.json @@ -248,6 +248,7 @@ "custom_ip": "IP personalizat", "blocking_ipv4": "Blocarea IPv4", "blocking_ipv6": "Blocarea IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/ru.json b/client/src/__locales/ru.json index ea58c7f341d..1b9f0a39c8f 100644 --- a/client/src/__locales/ru.json +++ b/client/src/__locales/ru.json @@ -248,6 +248,7 @@ "custom_ip": "Свой IP", "blocking_ipv4": "Блокировка IPv4", "blocking_ipv6": "Блокировка IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/si-lk.json b/client/src/__locales/si-lk.json index 015c477c497..429093551d6 100644 --- a/client/src/__locales/si-lk.json +++ b/client/src/__locales/si-lk.json @@ -119,7 +119,7 @@ "enabled_save_search_toast": "ආරක්ෂිත සෙවීම සබල කර ඇත", "enabled_table_header": "සබල කර ඇත", "name_table_header": "නම", - "list_url_table_header": "URL ලැයිස්තුව", + "list_url_table_header": "ඒ.ස.නි.(URL) ලැයිස්තුව", "rules_count_table_header": "නීති ගණන", "last_time_updated_table_header": "අවසන් වරට යාවත්කාලීන කරන ලද", "actions_table_header": "ක්‍රියාමාර්ග", @@ -134,7 +134,7 @@ "add_allowlist": "අවසර දීමේ ලැයිස්තුවක් එකතු කරන්න", "cancel_btn": "අහෝසි කරන්න", "enter_name_hint": "නම ඇතුළත් කරන්න", - "enter_url_or_path_hint": "ලැයිස්තුවක URL හෝ ස්ථීර මාර්ගයක් ඇතුළත් කරන්න", + "enter_url_or_path_hint": "ලැයිස්තුවක ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයක් ඇතුළත් කරන්න", "check_updates_btn": "යාවත්කාල පරීක්ෂා කරන්න", "new_blocklist": "නව අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුව", "new_allowlist": "නව අවසර දීමේ ලැයිස්තුව", @@ -142,10 +142,10 @@ "edit_allowlist": "අවසර දීමේ ලැයිස්තුව සංස්කරණය කරන්න", "choose_blocklist": "අවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න", "choose_allowlist": "අනවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න", - "enter_valid_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුවට වලංගු URL ලිපිනයක් ඇතුළත් කරන්න.", - "enter_valid_allowlist": "අවසර දීමේ ලැයිස්තුවට වලංගු URL ලිපිනයක් ඇතුළත් කරන්න.", - "form_error_url_format": "වලංගු නොවන URL ආකෘතියකි", - "form_error_url_or_path_format": "ලැයිස්තුවක වලංගු නොවන URL හෝ ස්ථීර මාර්ගයකි", + "enter_valid_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුළත් කරන්න.", + "enter_valid_allowlist": "අවසර දීමේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුළත් කරන්න.", + "form_error_url_format": "වලංගු නොවන ඒ.ස.නි.(URL) ආකෘතියකි", + "form_error_url_or_path_format": "ලැයිස්තුවක වලංගු නොවන ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයකි", "custom_filter_rules": "අභිරුචි පෙරීමේ නීති", "custom_filter_rules_hint": "පේළියකට එක් නීතියක් බැගින් ඇතුළත් කරන්න. ඔබට දැන්වීම් අවහිර කිරීමේ නීති හෝ ධාරක ගොනු පද ගැලපුම් භාවිතා කළ හැකිය.", "examples_title": "උදාහරණ", diff --git a/client/src/__locales/sk.json b/client/src/__locales/sk.json index af88853a476..7c0d4fa9964 100644 --- a/client/src/__locales/sk.json +++ b/client/src/__locales/sk.json @@ -248,6 +248,7 @@ "custom_ip": "Vlastná IP adresa", "blocking_ipv4": "Blokovanie IPv4", "blocking_ipv6": "Blokovanie IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/sl.json b/client/src/__locales/sl.json index 4a35e53a957..007283bb616 100644 --- a/client/src/__locales/sl.json +++ b/client/src/__locales/sl.json @@ -248,6 +248,7 @@ "custom_ip": "IP po meri", "blocking_ipv4": "Onemogočanje IPv4", "blocking_ipv6": "Onemogočanje IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-prek-HTTPS", "dns_over_tls": "DNS-prek-TLS", "dns_over_quic": "DNS-prek-QIUC", diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index 0276740d1a9..04b067293ac 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -248,6 +248,7 @@ "custom_ip": "Özel IP", "blocking_ipv4": "IPv4 engelleme", "blocking_ipv6": "IPv6 engelleme", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/vi.json b/client/src/__locales/vi.json index 85a5df2f3a0..368b0f9aef4 100644 --- a/client/src/__locales/vi.json +++ b/client/src/__locales/vi.json @@ -248,6 +248,7 @@ "custom_ip": "IP tuỳ chỉnh", "blocking_ipv4": "Chặn IPv4", "blocking_ipv6": "Chặn IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 54b72644d12..edf26ede87b 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -248,6 +248,7 @@ "custom_ip": "自定义 IP", "blocking_ipv4": "拦截 IPv4", "blocking_ipv6": "拦截 IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", diff --git a/client/src/__locales/zh-tw.json b/client/src/__locales/zh-tw.json index 258c661cde4..84df5c3eeb8 100644 --- a/client/src/__locales/zh-tw.json +++ b/client/src/__locales/zh-tw.json @@ -1,6 +1,6 @@ { "client_settings": "用戶端設定", - "example_upstream_reserved": "您可以<0>為特定網域指定上游 DNS", + "example_upstream_reserved": "您可<0>對於特定的網域明確指定 DNS 上游", "example_upstream_comment": "您可明確指定註解", "upstream_parallel": "透過同時地查詢所有上游的伺服器,使用並行的查詢以加速解析網域", "parallel_requests": "並行的請求", @@ -32,6 +32,7 @@ "form_error_ip_format": "無效的 IP 格式", "form_error_mac_format": "無效的媒體存取控制(MAC)格式", "form_error_client_id_format": "無效的用戶端 ID 格式", + "form_error_server_name": "無效的伺服器名稱", "form_error_positive": "必須大於 0", "form_error_negative": "必須等於或大於 0", "range_end_error": "必須大於起始範圍", @@ -247,10 +248,16 @@ "custom_ip": "自訂的 IP", "blocking_ipv4": "封鎖 IPv4", "blocking_ipv6": "封鎖 IPv6", + "dnscrypt": "DNSCrypt", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "dns_over_quic": "DNS-over-QUIC", + "client_id": "用戶端 ID", + "client_id_placeholder": "輸入用戶端 ID", + "client_id_desc": "不同的用戶端可根據特殊的用戶端 ID 被識別。<0>於此,您可了解更多關於如何識別用戶端。", "download_mobileconfig_doh": "下載用於 DNS-over-HTTPS 的 .mobileconfig", "download_mobileconfig_dot": "下載用於 DNS-over-TLS 的 .mobileconfig", + "download_mobileconfig": "下載配置檔案", "plain_dns": "一般的 DNS", "form_enter_rate_limit": "輸入速率限制", "rate_limit": "速率限制", @@ -386,6 +393,7 @@ "client_edit": "編輯用戶端", "client_identifier": "識別碼", "ip_address": "IP 位址", + "client_identifier_desc": "用戶端可根據 IP 位址、無類別網域間路由(CIDR)、媒體存取控制(MAC)位址或特殊的用戶端 ID(可被用於 DoT/DoH/DoQ)被識別。<0>於此,您可了解更多關於如何識別用戶端。", "form_enter_ip": "輸入 IP", "form_enter_mac": "輸入媒體存取控制(MAC)", "form_enter_id": "輸入識別碼", @@ -429,6 +437,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy 支援 <1>DNS-over-HTTPS。", "setup_dns_privacy_other_4": "<0>Mozilla Firefox 支援 <1>DNS-over-HTTPS。", "setup_dns_privacy_other_5": "在<0>這裡和<1>這裡,您將發現更多的執行。", + "setup_dns_privacy_ioc_mac": "iOS 和 macOS 配置", "setup_dns_notice": "為了使用 <1>DNS-over-HTTPS 或 <1>DNS-over-TLS,您需要在 AdGuard Home 設定裡<0>配置加密。", "rewrite_added": "對於 \"{{key}}\" 之 DNS 改寫被成功地加入", "rewrite_deleted": "對於 \"{{key}}\" 之 DNS 改寫被成功地刪除", diff --git a/scripts/translations/package-lock.json b/scripts/translations/package-lock.json index 5361d8597db..42f5d23a230 100644 --- a/scripts/translations/package-lock.json +++ b/scripts/translations/package-lock.json @@ -1,8 +1,466 @@ { "name": "translations", - "version": "0.1.0", - "lockfileVersion": 1, + "version": "0.2.0", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "version": "0.2.0", + "dependencies": { + "request": "^2.88.0", + "request-promise": "^4.2.2" + } + }, + "node_modules/ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "dependencies": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "node_modules/mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dependencies": { + "mime-db": "~1.37.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/request-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", + "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", + "dependencies": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dependencies": { + "lodash": "^4.13.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sshpk": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dependencies": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + } + }, "dependencies": { "ajv": { "version": "6.5.5", @@ -205,9 +663,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "mime-db": { "version": "1.37.0", From a1c9e9d36b62a5ac05f2976ddb10127c0e01e8d6 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 16:25:44 +0300 Subject: [PATCH 20/35] Pull request: all: prep release Merge in DNS/adguard-home from prep-release to master Squashed commit of the following: commit 32d83fe663dfd7a585ed9d89d09d47fd7b4cb653 Author: Ainar Garipov Date: Mon Feb 15 16:02:56 2021 +0300 all: prep release --- CHANGELOG.md | 10 +++++++--- internal/home/web.go | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb24fb1fe01..4f00990e016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,9 +14,11 @@ and this project adheres to --> +## [v0.105.1] - 2021-02-15 + ### Changed - Increased HTTP API timeouts ([#2671], [#2682]). @@ -192,10 +194,12 @@ and this project adheres to + [Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...HEAD [v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.0...v0.105.1 ---> -[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.0...HEAD [v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.3...v0.105.0 [v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.2...v0.104.3 [v0.104.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.1...v0.104.2 diff --git a/internal/home/web.go b/internal/home/web.go index fff2aa07ece..e016e341e79 100644 --- a/internal/home/web.go +++ b/internal/home/web.go @@ -18,12 +18,12 @@ import ( const ( // readTimeout is the maximum duration for reading the entire request, // including the body. - readTimeout = 30 * time.Second + readTimeout = 60 * time.Second // readHdrTimeout is the amount of time allowed to read request headers. - readHdrTimeout = 30 * time.Second + readHdrTimeout = 60 * time.Second // writeTimeout is the maximum duration before timing out writes of the // response. - writeTimeout = 30 * time.Second + writeTimeout = 60 * time.Second ) type webConfig struct { From 66b549a565aba86d52d5e137a280954050521de9 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 16:52:16 +0300 Subject: [PATCH 21/35] Pull request: scripts: fix shameful error Merge in DNS/adguard-home from fix-edge to master Squashed commit of the following: commit fdb7bc5ff772aabf86063f18f3b7c4ec83e63028 Author: Ainar Garipov Date: Mon Feb 15 16:26:39 2021 +0300 scripts: fix shameful error --- scripts/make/build-docker.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/make/build-docker.sh b/scripts/make/build-docker.sh index 29b86ba62d2..92adb4fb0c1 100644 --- a/scripts/make/build-docker.sh +++ b/scripts/make/build-docker.sh @@ -26,7 +26,6 @@ else fi echo $version -exit 0 # Allow users to use sudo. readonly sudo_cmd="${SUDO:-}" From dbcc55f528d59b962fa1fb608e80ab373ec30cbf Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Mon, 15 Feb 2021 18:50:58 +0300 Subject: [PATCH 22/35] 2641: Fix optical issue on custom rules Close #2641 Squashed commit of the following: commit 3d7280418e42c1607dd644fdbf5faab870470c93 Author: Artem Baskal Date: Mon Feb 15 18:37:11 2021 +0300 Update changelog order commit 98e46fe3285b294de5f0b5525611cfb18afb63f3 Author: Artem Baskal Date: Mon Feb 15 18:30:53 2021 +0300 Update changelog commit 5342d7c7bc5ca40888a4daeef1526464b861ef29 Author: Artem Baskal Date: Mon Feb 15 18:03:14 2021 +0300 2641: Fix optical issue on custom rules --- CHANGELOG.md | 2 ++ client/src/components/App/index.css | 4 +++- client/src/components/ui/texareaCommentsHighlight.css | 2 +- client/src/install/Setup/Setup.css | 3 ++- client/src/login/Login/Login.css | 3 ++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f00990e016..127971a16d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to ### Fixed +- Optical issue on custom rules ([#2641]). - Occasional crashes during startup. - The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response is now correctly named again ([#2678]). @@ -42,6 +43,7 @@ and this project adheres to - Incorrect version tag in the Docker release ([#2663]). - DNSCrypt queries weren't marked as such in logs ([#2662]). +[#2641]: https://github.com/AdguardTeam/AdGuardHome/issues/2641 [#2653]: https://github.com/AdguardTeam/AdGuardHome/issues/2653 [#2658]: https://github.com/AdguardTeam/AdGuardHome/issues/2658 [#2662]: https://github.com/AdguardTeam/AdGuardHome/issues/2662 diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css index 2b1ee76dbff..990f13e438d 100644 --- a/client/src/components/App/index.css +++ b/client/src/components/App/index.css @@ -5,6 +5,7 @@ --gray-d8: #d8d8d8; --gray-f3: #f3f3f3; --font-family-monospace: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace; + --font-size-disable-autozoom: 1rem; } body { @@ -13,9 +14,10 @@ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif; } +/* Disable Auto Zoom in Input - Safari on iPhone https://stackoverflow.com/a/6394497 */ @media screen and (max-width: 767px) { input, select, textarea { - font-size: 16px !important; + font-size: var(--font-size-disable-autozoom); } } diff --git a/client/src/components/ui/texareaCommentsHighlight.css b/client/src/components/ui/texareaCommentsHighlight.css index 8551966da8c..19c84faca97 100644 --- a/client/src/components/ui/texareaCommentsHighlight.css +++ b/client/src/components/ui/texareaCommentsHighlight.css @@ -15,7 +15,7 @@ white-space: pre-wrap; line-height: 1.5rem; word-wrap: break-word; - font-size: 0.9375rem; + font-size: var(--font-size-disable-autozoom); margin: 0; } diff --git a/client/src/install/Setup/Setup.css b/client/src/install/Setup/Setup.css index 522d57c1698..b08f4cb8e92 100644 --- a/client/src/install/Setup/Setup.css +++ b/client/src/install/Setup/Setup.css @@ -1,6 +1,7 @@ +/* Disable Auto Zoom in Input - Safari on iPhone https://stackoverflow.com/a/6394497 */ @media screen and (max-width: 767px) { input, select, textarea { - font-size: 16px !important; + font-size: 1rem; } } diff --git a/client/src/login/Login/Login.css b/client/src/login/Login/Login.css index a6b84e96a98..0d3dbfc19b9 100644 --- a/client/src/login/Login/Login.css +++ b/client/src/login/Login/Login.css @@ -1,6 +1,7 @@ +/* Disable Auto Zoom in Input - Safari on iPhone https://stackoverflow.com/a/6394497 */ @media screen and (max-width: 767px) { input, select, textarea { - font-size: 16px !important; + font-size: 1rem; } } From f68f6c9b37cea1f33cb6fa791e6678b9df3a237b Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 15 Feb 2021 19:07:08 +0300 Subject: [PATCH 23/35] Pull request: all: fix statip ip ck Merge in DNS/adguard-home from fix-static-ip-check to master Squashed commit of the following: commit af365c106f3d620afc77492a06f5368611328f5f Author: Ainar Garipov Date: Mon Feb 15 18:55:35 2021 +0300 all: doc changes commit 922afb262458fc488e03cad232430d90c504f2f3 Merge: 43fec5fb dbcc55f5 Author: Ainar Garipov Date: Mon Feb 15 18:53:31 2021 +0300 Merge branch 'master' into fix-static-ip-check commit 43fec5fb79f5c67b375da00aa73d11b3ed9ba3a4 Author: Ainar Garipov Date: Mon Feb 15 18:37:16 2021 +0300 all: fix statip ip ck --- CHANGELOG.md | 2 ++ internal/dhcpd/http.go | 32 +++++++++++++++++++++++--------- internal/sysutil/net.go | 7 +++++++ internal/sysutil/net_linux.go | 17 +++++++++++++---- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 127971a16d9..39217416fb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ and this project adheres to ### Fixed +- Error when enabling the DHCP server when AdGuard Home couldn't determine if + the machine has a static IP. - Optical issue on custom rules ([#2641]). - Occasional crashes during startup. - The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response diff --git a/internal/dhcpd/http.go b/internal/dhcpd/http.go index de155c5cb93..2dab11321d3 100644 --- a/internal/dhcpd/http.go +++ b/internal/dhcpd/http.go @@ -95,26 +95,40 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) { var hasStaticIP bool hasStaticIP, err = sysutil.IfaceHasStaticIP(ifaceName) if err != nil { - // ErrPermission may happen here on Linux systems where AdGuard - // Home is installed using Snap. That doesn't necessarily mean - // that the machine doesn't have a static IP, so we can assume - // that it has and go on. If the machine doesn't, we'll get an - // error later. - // - // See https://github.com/AdguardTeam/AdGuardHome/issues/2667. if errors.Is(err, os.ErrPermission) { + // ErrPermission may happen here on Linux systems where + // AdGuard Home is installed using Snap. That doesn't + // necessarily mean that the machine doesn't have + // a static IP, so we can assume that it has and go on. + // If the machine doesn't, we'll get an error later. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2667. + // + // TODO(a.garipov): I was thinking about moving this + // into IfaceHasStaticIP, but then we wouldn't be able + // to log it. Think about it more. log.Info("error while checking static ip: %s; "+ "assuming machine has static ip and going on", err) hasStaticIP = true + } else if errors.Is(err, sysutil.ErrNoStaticIPInfo) { + // Couldn't obtain a definitive answer. Assume static + // IP an go on. + log.Info("can't check for static ip; " + + "assuming machine has static ip and going on") + hasStaticIP = true } else { - return http.StatusInternalServerError, fmt.Errorf("checking static ip: %w", err) + err = fmt.Errorf("checking static ip: %w", err) + + return http.StatusInternalServerError, err } } if !hasStaticIP { err = sysutil.IfaceSetStaticIP(ifaceName) if err != nil { - return http.StatusInternalServerError, fmt.Errorf("setting static ip: %w", err) + err = fmt.Errorf("setting static ip: %w", err) + + return http.StatusInternalServerError, err } } diff --git a/internal/sysutil/net.go b/internal/sysutil/net.go index 0e3b448ebcb..9ba41704c1f 100644 --- a/internal/sysutil/net.go +++ b/internal/sysutil/net.go @@ -5,10 +5,17 @@ import ( "os/exec" "strings" + "github.com/AdguardTeam/AdGuardHome/internal/agherr" "github.com/AdguardTeam/golibs/log" ) +// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about +// the IP being static is available. +const ErrNoStaticIPInfo agherr.Error = "no information about static ip" + // IfaceHasStaticIP checks if interface is configured to have static IP address. +// If it can't give a definitive answer, it returns false and an error for which +// errors.Is(err, ErrNoStaticIPInfo) is true. func IfaceHasStaticIP(ifaceName string) (has bool, err error) { return ifaceHasStaticIP(ifaceName) } diff --git a/internal/sysutil/net_linux.go b/internal/sysutil/net_linux.go index 9205fd5c9f6..1964f9dda96 100644 --- a/internal/sysutil/net_linux.go +++ b/internal/sysutil/net_linux.go @@ -21,7 +21,11 @@ import ( const maxConfigFileSize = 1024 * 1024 func ifaceHasStaticIP(ifaceName string) (has bool, err error) { - var f *os.File + // TODO(a.garipov): Currently, this function returns the first + // definitive result. So if /etc/dhcpcd.conf has a static IP while + // /etc/network/interfaces doesn't, it will return true. Perhaps this + // is not the most desirable behavior. + for _, check := range []struct { checker func(io.Reader, string) (bool, error) filePath string @@ -32,8 +36,11 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { checker: ifacesStaticConfig, filePath: "/etc/network/interfaces", }} { + var f *os.File f, err = os.Open(check.filePath) if err != nil { + // ErrNotExist can happen here if there is no such file. + // This is normal, as not every system uses those files. if errors.Is(err, os.ErrNotExist) { err = nil @@ -52,12 +59,14 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { defer fileReadCloser.Close() has, err = check.checker(fileReadCloser, ifaceName) - if has || err != nil { - break + if err != nil { + return false, err } + + return has, nil } - return has, err + return false, ErrNoStaticIPInfo } // dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to From e32c18faab81fb08cafe88324c7049cad5b47cf7 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Tue, 16 Feb 2021 17:58:42 +0300 Subject: [PATCH 24/35] Pull request: dhcpd: fix ip option parsing Merge in DNS/adguard-home from 2688-dhcp-opt-ip to master Updates #2688. Squashed commit of the following: commit e17e003a3a61c1f4ed55617bb61df721cbca12c1 Author: Ainar Garipov Date: Tue Feb 16 17:10:32 2021 +0300 dhcpd: fix ip option parsing --- CHANGELOG.md | 8 ++++++++ internal/dhcpd/dhcpd.go | 12 ++++++++++-- internal/dhcpd/dhcpd_test.go | 34 ++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39217416fb9..6d11db20d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,14 @@ and this project adheres to ## [v0.105.2] - 2021-02-24 --> +### Fixed + +- Wrong parsing of DHCP options of the `ip` type ([#2688]). + +[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 + + + ## [v0.105.1] - 2021-02-15 ### Changed diff --git a/internal/dhcpd/dhcpd.go b/internal/dhcpd/dhcpd.go index bcd35d1c87f..e1d5ab1b2fb 100644 --- a/internal/dhcpd/dhcpd.go +++ b/internal/dhcpd/dhcpd.go @@ -293,14 +293,22 @@ func parseOptionString(s string) (uint8, []byte) { if err != nil { return 0, nil } - case "ip": ip := net.ParseIP(sval) if ip == nil { return 0, nil } - val = ip + // Most DHCP options require IPv4, so do not put the 16-byte + // version if we can. Otherwise, the clients will receive weird + // data that looks like four IPv4 addresses. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2688. + if ip4 := ip.To4(); ip4 != nil { + val = ip4 + } else { + val = ip + } default: return 0, nil } diff --git a/internal/dhcpd/dhcpd_test.go b/internal/dhcpd/dhcpd_test.go index e9b44518230..cca733d9310 100644 --- a/internal/dhcpd/dhcpd_test.go +++ b/internal/dhcpd/dhcpd_test.go @@ -3,7 +3,6 @@ package dhcpd import ( - "bytes" "net" "os" "testing" @@ -130,36 +129,51 @@ func TestOptions(t *testing.T) { testCases := []struct { name string optStr string - wantCode uint8 wantVal []byte + wantCode uint8 }{{ - name: "all_right_hex", - optStr: " 12 hex abcdef ", - wantCode: 12, + name: "success_hex", + optStr: "12 hex abcdef", wantVal: []byte{0xab, 0xcd, 0xef}, + wantCode: 12, }, { name: "bad_hex", - optStr: " 12 hex abcdef1 ", + optStr: "12 hex abcdefx", + wantVal: nil, wantCode: 0, }, { - name: "all_right_ip", + name: "success_ip", optStr: "123 ip 1.2.3.4", + wantVal: net.IP{1, 2, 3, 4}, + wantCode: 123, + }, { + name: "success_ipv6", + optStr: "123 ip ::1234", + wantVal: net.IP{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0x12, 0x34, + }, wantCode: 123, - wantVal: net.IPv4(1, 2, 3, 4), }, { name: "bad_code", optStr: "256 ip 1.1.1.1", + wantVal: nil, wantCode: 0, }, { name: "negative_code", optStr: "-1 ip 1.1.1.1", + wantVal: nil, wantCode: 0, }, { name: "bad_ip", optStr: "12 ip 1.1.1.1x", + wantVal: nil, wantCode: 0, }, { name: "bad_mode", + wantVal: nil, optStr: "12 x 1.1.1.1", wantCode: 0, }} @@ -167,9 +181,9 @@ func TestOptions(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { code, val := parseOptionString(tc.optStr) - require.EqualValues(t, tc.wantCode, code) + require.Equal(t, tc.wantCode, code) if tc.wantVal != nil { - assert.True(t, bytes.Equal(tc.wantVal, val)) + assert.Equal(t, tc.wantVal, val) } }) } From 1122e71cf34a14cfd3c4e98ea43f80050ca6eebb Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Tue, 16 Feb 2021 18:46:49 +0300 Subject: [PATCH 25/35] Pull request: 2674 fix upstreams validation Merge in DNS/adguard-home from 2674-quic-upstream to master Updates #2674. Squashed commit of the following: commit ce7643580cc9e19881689e7fd4933bc953f2884e Author: Eugene Burkov Date: Tue Feb 16 18:23:39 2021 +0300 all: fix log commit b53e4368dd9ca61965e73b1f1274388422142830 Author: Eugene Burkov Date: Tue Feb 16 18:21:59 2021 +0300 all: log changes commit 1cdca48e31c272ccfbde955c2a3e560ca6ca6bcf Merge: bc441dac e32c18fa Author: Eugene Burkov Date: Tue Feb 16 18:15:47 2021 +0300 Merge branch 'master' into 2674-quic-upstream commit bc441dac3cbe8070c8c1d672925b14d309f05b9f Author: Eugene Burkov Date: Tue Feb 16 17:06:47 2021 +0300 dnsforward: fix error wrapping commit 281c1b43233c2bb51e3a933588087a207b7eef3d Author: Eugene Burkov Date: Tue Feb 16 17:00:35 2021 +0300 all: fix validation, imp shutdown commit 31a5ea7a081de4bcc3913bd04d62334fec1b59e1 Author: Eugene Burkov Date: Tue Feb 16 14:53:10 2021 +0300 dnsforward: fix upstreams validation --- CHANGELOG.md | 2 ++ internal/dnsforward/config.go | 2 +- internal/dnsforward/http.go | 6 ++++++ internal/home/home.go | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d11db20d5a..33a36ee49ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,10 @@ and this project adheres to ### Fixed +- Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). +[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 [#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index a80e7ad5ee7..818648996f6 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -282,7 +282,7 @@ func (s *Server) prepareUpstreamSettings() error { } if len(upstreamConfig.Upstreams) == 0 { - log.Info("Warning: no default upstream servers specified, using %v", defaultDNS) + log.Info("warning: no default upstream servers specified, using %v", defaultDNS) uc, err := proxy.ParseUpstreamsConfig(defaultDNS, s.conf.BootstrapDNS, DefaultTimeout) if err != nil { return fmt.Errorf("dns: failed to parse default upstreams: %v", err) diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go index e7508bc8a49..527d3b3879b 100644 --- a/internal/dnsforward/http.go +++ b/internal/dnsforward/http.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" + "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/upstream" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/utils" @@ -314,6 +315,11 @@ func ValidateUpstreams(upstreams []string) error { return nil } + _, err := proxy.ParseUpstreamsConfig(upstreams, []string{}, DefaultTimeout) + if err != nil { + return err + } + var defaultUpstreamFound bool for _, u := range upstreams { d, err := validateUpstream(u) diff --git a/internal/home/home.go b/internal/home/home.go index 422312a6783..bfc17750ad5 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -320,6 +320,7 @@ func run(args options) { go func() { err := startDNSServer() if err != nil { + closeDNSServer() log.Fatal(err) } }() From a0abad6644d1cbe80d9293b6742e38c4c6ddc282 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 18 Feb 2021 14:11:54 +0300 Subject: [PATCH 26/35] Pull request: 2692 time format Merge in DNS/adguard-home from 2692-time-format to master Closes #2692. Squashed commit of the following: commit a77e3ffc1e2ca7ad1eb4b56641eee787595268e9 Merge: 5262c0b9 1122e71c Author: Eugene Burkov Date: Thu Feb 18 13:58:29 2021 +0300 Merge branch 'master' into 2692-time-format commit 5262c0b95979a6c7a01bdd56e9476c4cdf217119 Author: Eugene Burkov Date: Thu Feb 18 13:50:38 2021 +0300 dhcpd: imp docs commit 3744338d51dd003a0052672ceffa260c70f5738d Author: Eugene Burkov Date: Wed Feb 17 21:10:37 2021 +0300 dhcpd: fix lease time format --- CHANGELOG.md | 2 ++ internal/dhcpd/dhcpd.go | 31 ++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33a36ee49ca..0d47edd7a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,11 +19,13 @@ and this project adheres to ### Fixed +- DHCP lease's `expired` field incorrect time format ([#2692]). - Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). [#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 [#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 +[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692 diff --git a/internal/dhcpd/dhcpd.go b/internal/dhcpd/dhcpd.go index e1d5ab1b2fb..7a48d239f93 100644 --- a/internal/dhcpd/dhcpd.go +++ b/internal/dhcpd/dhcpd.go @@ -19,7 +19,12 @@ import ( const ( defaultDiscoverTime = time.Second * 3 - leaseExpireStatic = 1 + // leaseExpireStatic is used to define the Expiry field for static + // leases. + // + // TODO(e.burkov): Remove it when static leases determining mechanism + // will be improved. + leaseExpireStatic = 1 ) var webHandlersRegistered = false @@ -37,12 +42,24 @@ type Lease struct { // MarshalJSON implements the json.Marshaler interface for *Lease. func (l *Lease) MarshalJSON() ([]byte, error) { + var expiryStr string + if expiry := l.Expiry; expiry.Unix() != leaseExpireStatic { + // The front-end is waiting for RFC 3999 format of the time + // value. It also shouldn't got an Expiry field for static + // leases. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2692. + expiryStr = expiry.Format(time.RFC3339) + } + type lease Lease return json.Marshal(&struct { HWAddr string `json:"mac"` + Expiry string `json:"expires,omitempty"` *lease }{ HWAddr: l.HWAddr.String(), + Expiry: expiryStr, lease: (*lease)(l), }) } @@ -248,14 +265,10 @@ const ( LeasesAll = LeasesDynamic | LeasesStatic ) -// Leases returns the list of current DHCP leases (thread-safe) -func (s *Server) Leases(flags int) []Lease { - result := s.srv4.GetLeases(flags) - - v6leases := s.srv6.GetLeases(flags) - result = append(result, v6leases...) - - return result +// Leases returns the list of active IPv4 and IPv6 DHCP leases. It's safe for +// concurrent use. +func (s *Server) Leases(flags int) (leases []Lease) { + return append(s.srv4.GetLeases(flags), s.srv6.GetLeases(flags)...) } // FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases From 836d0db563cd83b5c1d686caced2e164a5886f5e Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Tue, 23 Feb 2021 14:21:08 +0300 Subject: [PATCH 27/35] Add links to discussions --- .github/ISSUE_TEMPLATE/Bug_report.md | 2 +- .github/ISSUE_TEMPLATE/Feature_request.md | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 86615ef861e..9aaebca40ec 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -3,7 +3,7 @@ name: Bug report about: Create a bug report to help us improve AdGuard Home --- - +Have a question or an idea? Please search it [on our forum](https://github.com/AdguardTeam/AdGuardHome/discussions) to make sure it was not yet asked. If you cannot find what you had in mind, please [submit it here](https://github.com/AdguardTeam/AdGuardHome/discussions/new). ### Prerequisites diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 4937f5b6c03..094531b3b2e 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -1,11 +1,9 @@ --- name: Feature request -about: Suggest an idea for AdGuard Home - +about: Suggest a feature request for AdGuard Home --- - +Have a question or an idea? Please search it [on our forum](https://github.com/AdguardTeam/AdGuardHome/discussions) to make sure it was not yet asked. If you cannot find what you had in mind, please [submit it here](https://github.com/AdguardTeam/AdGuardHome/discussions/new). ### Prerequisites From e31c0c456a7b32f75d13065dfad9e6167986b0c8 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 24 Feb 2021 14:13:29 +0300 Subject: [PATCH 28/35] Pull request: all: imp stalebot Merge in DNS/adguard-home from imp-stalebot to master Squashed commit of the following: commit 8b72c1328030e2299e296a7ab6adb0148dcb03ad Author: Ainar Garipov Date: Wed Feb 24 13:43:41 2021 +0300 all: imp stalebot --- .github/stale.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index 5c7c4caa03c..518db8b932c 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,20 +1,22 @@ # Number of days of inactivity before an issue becomes stale. -'daysUntilStale': 60 +'daysUntilStale': 90 # Number of days of inactivity before a stale issue is closed. -'daysUntilClose': 7 +'daysUntilClose': 15 # Issues with these labels will never be considered stale. 'exemptLabels': - 'bug' - 'enhancement' - 'feature request' - 'localization' +- 'needs investigation' - 'recurrent' +- 'research' # Label to use when marking an issue as stale. 'staleLabel': 'wontfix' # Comment to post when marking an issue as stale. Set to `false` to disable. 'markComment': > This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you + recent activity. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable. 'closeComment': false From d6a059e395a3998421649014c7b1175a4075ef61 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 26 Feb 2021 15:52:52 +0300 Subject: [PATCH 29/35] Pull request: openapi: add missing property Merge in DNS/adguard-home from fix-openapi to master Squashed commit of the following: commit 24efa5732b327d179f07cbf67fbe8df6ee1b9477 Author: Ainar Garipov Date: Fri Feb 26 15:42:56 2021 +0300 openapi: add missing property --- openapi/openapi.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 5de5a607df2..5892d704fdb 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1279,6 +1279,8 @@ 'type': 'string' 'edns_cs_enabled': 'type': 'boolean' + 'disable_ipv6': + 'type': 'boolean' 'dnssec_enabled': 'type': 'boolean' 'cache_size': From 91403d0b95e30e071bdf425a95e0f3746c76d359 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Mon, 1 Mar 2021 17:20:16 +0300 Subject: [PATCH 30/35] Pull request: 2757 fix OpenWRT detection Merge in DNS/adguard-home from 2757-openwrt to master Updates #2757. Squashed commit of the following: commit 8e94e6a67ae702bd1b281b306555a4ce9ecc6391 Author: Eugene Burkov Date: Mon Mar 1 17:02:24 2021 +0300 util: convert only once commit f1c74f4d18898f286d70c58f93b2fa21de6b5780 Author: Eugene Burkov Date: Mon Mar 1 16:22:51 2021 +0300 util: log changes, imp docs commit 0a4558d044602058255db71f825a730642cc9b07 Author: Eugene Burkov Date: Mon Mar 1 15:53:26 2021 +0300 util: imp os detection --- CHANGELOG.md | 4 +++- internal/util/helpers.go | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d47edd7a0a..7d078d4e786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,12 @@ and this project adheres to --> ### Fixed +- Incomplete OpenWRT detection ([#2757]). - DHCP lease's `expired` field incorrect time format ([#2692]). - Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). @@ -26,6 +27,7 @@ and this project adheres to [#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 [#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 [#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692 +[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757 diff --git a/internal/util/helpers.go b/internal/util/helpers.go index b575b269dd3..1b759f45165 100644 --- a/internal/util/helpers.go +++ b/internal/util/helpers.go @@ -5,10 +5,12 @@ package util import ( + "bytes" "fmt" "io/ioutil" "os" "os/exec" + "path/filepath" "runtime" "strings" ) @@ -64,16 +66,43 @@ func SplitNext(str *string, splitBy byte) string { return strings.TrimSpace(s) } -// IsOpenWRT checks if OS is OpenWRT. +// IsOpenWRT returns true if host OS is OpenWRT. func IsOpenWRT() bool { if runtime.GOOS != "linux" { return false } - body, err := ioutil.ReadFile("/etc/os-release") + const etcDir = "/etc" + + // TODO(e.burkov): Take care of dealing with fs package after updating + // Go version to 1.16. + fileInfos, err := ioutil.ReadDir(etcDir) if err != nil { return false } - return strings.Contains(string(body), "OpenWrt") + // fNameSubstr is a part of a name of the desired file. + const fNameSubstr = "release" + osNameData := []byte("OpenWrt") + + for _, fileInfo := range fileInfos { + if fileInfo.IsDir() { + continue + } + + if !strings.Contains(fileInfo.Name(), fNameSubstr) { + continue + } + + body, err := ioutil.ReadFile(filepath.Join(etcDir, fileInfo.Name())) + if err != nil { + continue + } + + if bytes.Contains(body, osNameData) { + return true + } + } + + return false } From 94e783d5725163d8163a106a1a1bb30cbdcadbf9 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Mon, 1 Mar 2021 20:37:28 +0300 Subject: [PATCH 31/35] Pull request: 2470 session token Merge in DNS/adguard-home from 2470-session-token to master Updates #2470. Squashed commit of the following: commit 02e874404808ee23000c49b4b2980b049dc4d0e6 Author: Eugene Burkov Date: Mon Mar 1 20:11:35 2021 +0300 home: imp time formating commit 6f4a6c9b190b2672cecd3e3e31413b03d19f8771 Author: Eugene Burkov Date: Mon Mar 1 18:48:15 2021 +0300 home: rm user's data from session token --- CHANGELOG.md | 6 ++++ internal/home/auth.go | 59 +++++++++++++++++++++++--------------- internal/home/auth_test.go | 33 +++++++++++++++++---- 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d078d4e786..cd5293c1fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,12 @@ and this project adheres to [#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692 [#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757 +### Security + +- Session token doesn't contain user's information anymore ([#2470]). + +[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470 + ## [v0.105.1] - 2021-02-15 diff --git a/internal/home/auth.go b/internal/home/auth.go index 26b577870d4..76e7e7b6cfe 100644 --- a/internal/home/auth.go +++ b/internal/home/auth.go @@ -2,13 +2,10 @@ package home import ( "crypto/rand" - "crypto/sha256" "encoding/binary" "encoding/hex" "encoding/json" "fmt" - "math" - "math/big" "net/http" "strings" "sync" @@ -20,8 +17,12 @@ import ( ) const ( - cookieTTL = 365 * 24 // in hours + // cookieTTL is given in hours. + cookieTTL = 365 * 24 sessionCookieName = "agh_session" + + // sessionTokenSize is the length of session token in bytes. + sessionTokenSize = 16 ) type session struct { @@ -285,16 +286,29 @@ type loginJSON struct { Password string `json:"password"` } -func getSession(u *User) ([]byte, error) { - maxSalt := big.NewInt(math.MaxUint32) - salt, err := rand.Int(rand.Reader, maxSalt) +// newSessionToken returns cryptographically secure randomly generated slice of +// bytes of sessionTokenSize length. +// +// TODO(e.burkov): Think about using byte array instead of byte slice. +func newSessionToken() (data []byte, err error) { + randData := make([]byte, sessionTokenSize) + + _, err = rand.Read(randData) if err != nil { return nil, err } - d := []byte(fmt.Sprintf("%s%s%s", salt, u.Name, u.PasswordHash)) - hash := sha256.Sum256(d) - return hash[:], nil + return randData, nil +} + +// cookieTimeFormat is the format to be used in (time.Time).Format for cookie's +// expiry field. +const cookieTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT" + +// cookieExpiryFormat returns the formatted exp to be used in cookie string. +// It's quite simple for now, but probably will be expanded in the future. +func cookieExpiryFormat(exp time.Time) (formatted string) { + return exp.Format(cookieTimeFormat) } func (a *Auth) httpCookie(req loginJSON) (string, error) { @@ -303,24 +317,23 @@ func (a *Auth) httpCookie(req loginJSON) (string, error) { return "", nil } - sess, err := getSession(&u) + sess, err := newSessionToken() if err != nil { return "", err } now := time.Now().UTC() - expire := now.Add(cookieTTL * time.Hour) - expstr := expire.Format(time.RFC1123) - expstr = expstr[:len(expstr)-len("UTC")] // "UTC" -> "GMT" - expstr += "GMT" - - s := session{} - s.userName = u.Name - s.expire = uint32(now.Unix()) + a.sessionTTL - a.addSession(sess, &s) - - return fmt.Sprintf("%s=%s; Path=/; HttpOnly; Expires=%s", - sessionCookieName, hex.EncodeToString(sess), expstr), nil + + a.addSession(sess, &session{ + userName: u.Name, + expire: uint32(now.Unix()) + a.sessionTTL, + }) + + return fmt.Sprintf( + "%s=%s; Path=/; HttpOnly; Expires=%s", + sessionCookieName, hex.EncodeToString(sess), + cookieExpiryFormat(now.Add(cookieTTL*time.Hour)), + ), nil } func handleLogin(w http.ResponseWriter, r *http.Request) { diff --git a/internal/home/auth_test.go b/internal/home/auth_test.go index 4dbd07b6938..7dbbf3c62f7 100644 --- a/internal/home/auth_test.go +++ b/internal/home/auth_test.go @@ -1,6 +1,8 @@ package home import ( + "bytes" + "crypto/rand" "encoding/hex" "net/http" "net/url" @@ -11,6 +13,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghtest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMain(m *testing.M) { @@ -24,14 +27,34 @@ func prepareTestDir() string { return dir } +func TestNewSessionToken(t *testing.T) { + // Successful case. + token, err := newSessionToken() + require.Nil(t, err) + assert.Len(t, token, sessionTokenSize) + + // Break the rand.Reader. + prevReader := rand.Reader + t.Cleanup(func() { + rand.Reader = prevReader + }) + rand.Reader = &bytes.Buffer{} + + // Unsuccessful case. + token, err = newSessionToken() + require.NotNil(t, err) + assert.Empty(t, token) +} + func TestAuth(t *testing.T) { dir := prepareTestDir() - defer func() { _ = os.RemoveAll(dir) }() + t.Cleanup(func() { _ = os.RemoveAll(dir) }) fn := filepath.Join(dir, "sessions.db") - users := []User{ - {Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"}, - } + users := []User{{ + Name: "name", + PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2", + }} a := InitAuth(fn, nil, 60) s := session{} @@ -41,7 +64,7 @@ func TestAuth(t *testing.T) { assert.Equal(t, checkSessionNotFound, a.checkSession("notfound")) a.RemoveSession("notfound") - sess, err := getSession(&users[0]) + sess, err := newSessionToken() assert.Nil(t, err) sessStr := hex.EncodeToString(sess) From a234b63da10eaae84e2854b3874dc8bc97bd3042 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 3 Mar 2021 15:27:25 +0300 Subject: [PATCH 32/35] Pull request: 2600 inconsistent response Merge in DNS/adguard-home from 2600-upd-dnsproxy to master Closes #2600. Squashed commit of the following: commit 4b1515395841f14d86bc85b5c516d14919b5dc25 Author: Eugene Burkov Date: Tue Mar 2 18:39:19 2021 +0300 all: upd dnsproxy again, log changes commit 8a866201f140655b0d2f58552a7ad9bcae91a173 Author: Eugene Burkov Date: Tue Mar 2 14:53:48 2021 +0300 all: cleanup commit ae81234c79a6dbc61cccbae9c1b9d0144bb7f506 Author: Eugene Burkov Date: Tue Mar 2 14:49:28 2021 +0300 all: fix deps commit 662384c366feaf553d9eba2b5e3be93774631ec5 Author: Eugene Burkov Date: Tue Mar 2 13:58:26 2021 +0300 all: upd dnsproxy version, fix functions' signatures --- CHANGELOG.md | 3 +++ go.mod | 2 +- go.sum | 4 ++-- internal/dnsforward/config.go | 14 ++++++++++++-- internal/dnsforward/http.go | 9 +++++++-- internal/home/clients.go | 8 +++++++- internal/home/home_test.go | 2 +- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5293c1fcb..1fc350b68b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,11 +19,14 @@ and this project adheres to ### Fixed +- Inconsistent responses for messages with EDNS0 and AD when DNS caching is + enabled ([#2600]). - Incomplete OpenWRT detection ([#2757]). - DHCP lease's `expired` field incorrect time format ([#2692]). - Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). +[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600 [#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 [#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 [#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692 diff --git a/go.mod b/go.mod index b8d18f43d1e..e0224884179 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.14 require ( - github.com/AdguardTeam/dnsproxy v0.33.9 + github.com/AdguardTeam/dnsproxy v0.35.3 github.com/AdguardTeam/golibs v0.4.4 github.com/AdguardTeam/urlfilter v0.14.3 github.com/NYTimes/gziphandler v1.1.1 diff --git a/go.sum b/go.sum index 4afc5ca7150..584609cf4a7 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AdguardTeam/dnsproxy v0.33.9 h1:HUwywkhUV/M73E7qWcBAF+SdsNq742s82Lvox4pr/tM= -github.com/AdguardTeam/dnsproxy v0.33.9/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs= +github.com/AdguardTeam/dnsproxy v0.35.3 h1:mvXWoIZRRATJQyGTnq0O1ofbvuVMKRZMyycU/2tFiyE= +github.com/AdguardTeam/dnsproxy v0.35.3/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 818648996f6..fdc8e5e2052 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -276,14 +276,24 @@ func (s *Server) prepareUpstreamSettings() error { upstreams = s.conf.UpstreamDNS } upstreams = filterOutComments(upstreams) - upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams, s.conf.BootstrapDNS, DefaultTimeout) + upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams, + upstream.Options{ + Bootstrap: s.conf.BootstrapDNS, + Timeout: DefaultTimeout, + }, + ) if err != nil { return fmt.Errorf("dns: proxy.ParseUpstreamsConfig: %w", err) } if len(upstreamConfig.Upstreams) == 0 { log.Info("warning: no default upstream servers specified, using %v", defaultDNS) - uc, err := proxy.ParseUpstreamsConfig(defaultDNS, s.conf.BootstrapDNS, DefaultTimeout) + uc, err := proxy.ParseUpstreamsConfig(defaultDNS, + upstream.Options{ + Bootstrap: s.conf.BootstrapDNS, + Timeout: DefaultTimeout, + }, + ) if err != nil { return fmt.Errorf("dns: failed to parse default upstreams: %v", err) } diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go index 527d3b3879b..0a2269dcfb7 100644 --- a/internal/dnsforward/http.go +++ b/internal/dnsforward/http.go @@ -150,7 +150,7 @@ func (req *dnsConfig) checkBootstrap() (string, error) { return boot, fmt.Errorf("invalid bootstrap server address: empty") } - if _, err := upstream.NewResolver(boot, 0); err != nil { + if _, err := upstream.NewResolver(boot, upstream.Options{Timeout: 0}); err != nil { return boot, fmt.Errorf("invalid bootstrap server address: %w", err) } } @@ -315,7 +315,12 @@ func ValidateUpstreams(upstreams []string) error { return nil } - _, err := proxy.ParseUpstreamsConfig(upstreams, []string{}, DefaultTimeout) + _, err := proxy.ParseUpstreamsConfig(upstreams, + upstream.Options{ + Bootstrap: []string{}, + Timeout: DefaultTimeout, + }, + ) if err != nil { return err } diff --git a/internal/home/clients.go b/internal/home/clients.go index c3eb366f13f..5a9e9eac49d 100644 --- a/internal/home/clients.go +++ b/internal/home/clients.go @@ -17,6 +17,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/dnsproxy/proxy" + "github.com/AdguardTeam/dnsproxy/upstream" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/utils" ) @@ -295,7 +296,12 @@ func (clients *clientsContainer) FindUpstreams(ip string) *proxy.UpstreamConfig } if c.upstreamConfig == nil { - config, err := proxy.ParseUpstreamsConfig(c.Upstreams, config.DNS.BootstrapDNS, dnsforward.DefaultTimeout) + config, err := proxy.ParseUpstreamsConfig(c.Upstreams, + upstream.Options{ + Bootstrap: config.DNS.BootstrapDNS, + Timeout: dnsforward.DefaultTimeout, + }, + ) if err == nil { c.upstreamConfig = &config } diff --git a/internal/home/home_test.go b/internal/home/home_test.go index 02613b7c44e..033b8e26fe1 100644 --- a/internal/home/home_test.go +++ b/internal/home/home_test.go @@ -146,7 +146,7 @@ func TestHome(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) // test DNS over UDP - r, err := upstream.NewResolver("127.0.0.1:5354", 3*time.Second) + r, err := upstream.NewResolver("127.0.0.1:5354", upstream.Options{Timeout: 3 * time.Second}) assert.Nil(t, err) addrs, err := r.LookupIPAddr(context.TODO(), "static.adguard.com") assert.Nil(t, err) From 52575d0247d5411d26083d4c186d39d8098b916e Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 3 Mar 2021 16:14:23 +0300 Subject: [PATCH 33/35] util: imp autohosts --- internal/util/autohosts.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/util/autohosts.go b/internal/util/autohosts.go index ad7825d5104..e4cea58c65c 100644 --- a/internal/util/autohosts.go +++ b/internal/util/autohosts.go @@ -120,14 +120,13 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP { var ipsCopy []net.IP a.lock.RLock() + defer a.lock.RUnlock() if ips, ok := a.table[host]; ok { ipsCopy = make([]net.IP, len(ips)) copy(ipsCopy, ips) } - a.lock.RUnlock() - log.Debug("AutoHosts: answer: %s -> %v", host, ipsCopy) return ipsCopy } @@ -339,10 +338,13 @@ func (a *AutoHosts) updateHosts() { } } - a.lock.Lock() - a.table = table - a.tableReverse = tableRev - a.lock.Unlock() + func() { + a.lock.Lock() + defer a.lock.Unlock() + + a.table = table + a.tableReverse = tableRev + }() a.notify() } From 400b76d47b777fa3da3b34f48e2ff28df587bad2 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 3 Mar 2021 19:55:37 +0300 Subject: [PATCH 34/35] Pull request: 2681 fix DNS-over-TLS bug Merge in DNS/adguard-home from 2681-fix-dot-bug to master Updates #2681 Squashed commit of the following: commit 8de0f4c9767218cd6956a2ab97eda6c5028d1d07 Author: Eugene Burkov Date: Wed Mar 3 19:25:34 2021 +0300 all: upd dnsproxy --- CHANGELOG.md | 2 ++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fc350b68b8..12b8d1a7f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to ### Fixed +- Wrong DNS-over-TLS ALPN configuration ([#2681]). - Inconsistent responses for messages with EDNS0 and AD when DNS caching is enabled ([#2600]). - Incomplete OpenWRT detection ([#2757]). @@ -28,6 +29,7 @@ and this project adheres to [#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600 [#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 +[#2681]: https://github.com/AdguardTeam/AdGuardHome/issues/2681 [#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688 [#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692 [#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757 diff --git a/go.mod b/go.mod index e0224884179..03afd7baba7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.14 require ( - github.com/AdguardTeam/dnsproxy v0.35.3 + github.com/AdguardTeam/dnsproxy v0.35.4 github.com/AdguardTeam/golibs v0.4.4 github.com/AdguardTeam/urlfilter v0.14.3 github.com/NYTimes/gziphandler v1.1.1 diff --git a/go.sum b/go.sum index 584609cf4a7..8a91875fe66 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AdguardTeam/dnsproxy v0.35.3 h1:mvXWoIZRRATJQyGTnq0O1ofbvuVMKRZMyycU/2tFiyE= -github.com/AdguardTeam/dnsproxy v0.35.3/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs= +github.com/AdguardTeam/dnsproxy v0.35.4 h1:zuVVtDouhYXXWHb8Zp0oCcVMop6PDCQ9PosQ5fJApsg= +github.com/AdguardTeam/dnsproxy v0.35.4/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= From 90ebc4d8c9f9657c826fd0d39e708aa6cbdc12ad Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 4 Mar 2021 17:49:34 +0300 Subject: [PATCH 35/35] Pull request: 2582 invalid hostname Merge in DNS/adguard-home from 2582-invalid-hostname to master Updates #2582. Squashed commit of the following: commit 909598dae00588792b092f89c272c4487ba55dd1 Author: Eugene Burkov Date: Thu Mar 4 17:32:58 2021 +0300 all: imp code quality, log changes commit b3b970803709030c48cfe343b88d73524a043de3 Author: Eugene Burkov Date: Thu Mar 4 16:56:28 2021 +0300 home: add host processing logic --- CHANGELOG.md | 2 ++ internal/home/clients.go | 13 +++++++++++++ internal/home/clients_test.go | 26 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b8d1a7f56..a409cd8a2ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to ### Fixed +- Incomplete hostnames with trailing zero-bytes handling ([#2582]). - Wrong DNS-over-TLS ALPN configuration ([#2681]). - Inconsistent responses for messages with EDNS0 and AD when DNS caching is enabled ([#2600]). @@ -27,6 +28,7 @@ and this project adheres to - Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). +[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582 [#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600 [#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674 [#2681]: https://github.com/AdguardTeam/AdGuardHome/issues/2681 diff --git a/internal/home/clients.go b/internal/home/clients.go index 5a9e9eac49d..6c314874bf6 100644 --- a/internal/home/clients.go +++ b/internal/home/clients.go @@ -586,9 +586,22 @@ func (clients *clientsContainer) SetWhoisInfo(ip string, info [][]string) { log.Debug("clients: set whois info for auto-client with IP %s: %q", ip, info) } +// sanitizeHost proccesses a host to remove some special symbols causing errors. +// Logic may be expanded in the future. +func sanitizeHost(host string) (processed string) { + // cutset brings together all the deprecated sets. + // + // See https://github.com/AdguardTeam/AdGuardHome/issues/2582. + const cutset = "\x00" + + return strings.TrimRight(host, cutset) +} + // AddHost adds a new IP-hostname pairing. The priorities of the sources is // taken into account. ok is true if the pairing was added. func (clients *clientsContainer) AddHost(ip, host string, src clientSource) (ok bool, err error) { + host = sanitizeHost(host) + clients.lock.Lock() ok = clients.addHostLocked(ip, host, src) clients.lock.Unlock() diff --git a/internal/home/clients_test.go b/internal/home/clients_test.go index a098bf4c352..e6200ddd2ad 100644 --- a/internal/home/clients_test.go +++ b/internal/home/clients_test.go @@ -290,3 +290,29 @@ func TestClientsCustomUpstream(t *testing.T) { assert.Equal(t, 1, len(config.Upstreams)) assert.Equal(t, 1, len(config.DomainReservedUpstreams)) } + +func TestProcessHost(t *testing.T) { + const ( + name int = iota + host + want + + fieldsNum + ) + + testCases := [][fieldsNum]string{{ + name: "valid", + host: "abc", + want: "abc", + }, { + name: "with_trailing_zero_byte", + host: "abc\x00", + want: "abc", + }} + + for _, tc := range testCases { + t.Run(tc[name], func(t *testing.T) { + assert.Equal(t, tc[want], sanitizeHost(tc[host])) + }) + } +}