From b29f320fd466715d02041a4753223ad4f2105f76 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 23 Feb 2022 22:42:03 +0800 Subject: [PATCH 01/99] Simplify Dockerfile Alpine Linux apk usage Remove additional `--update` and manual clean up for apk in Dockerfile --- scripts/make/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/make/Dockerfile b/scripts/make/Dockerfile index f5a543a2..a731e3a6 100644 --- a/scripts/make/Dockerfile +++ b/scripts/make/Dockerfile @@ -21,8 +21,7 @@ LABEL\ org.opencontainers.image.version=$VERSION # Update certificates. -RUN apk --no-cache --update add ca-certificates libcap tzdata && \ - rm -rf /var/cache/apk/* && \ +RUN apk --no-cache add ca-certificates libcap tzdata && \ mkdir -p /opt/adguardhome/conf /opt/adguardhome/work && \ chown -R nobody: /opt/adguardhome From c346216424d6571f96d80f47a9224da4c47dbbf9 Mon Sep 17 00:00:00 2001 From: bakito Date: Sat, 12 Mar 2022 12:46:15 +0100 Subject: [PATCH 02/99] correct openapi schema --- internal/home/controlfiltering.go | 2 +- openapi/openapi.yaml | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/internal/home/controlfiltering.go b/internal/home/controlfiltering.go index 639403d8..51d86146 100644 --- a/internal/home/controlfiltering.go +++ b/internal/home/controlfiltering.go @@ -316,7 +316,7 @@ type filterJSON struct { URL string `json:"url"` Name string `json:"name"` RulesCount uint32 `json:"rules_count"` - LastUpdated string `json:"last_updated"` + LastUpdated string `json:"last_updated,omitempty"` } type filteringConfig struct { diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 8b21a01f..bb3bfe09 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1396,7 +1396,6 @@ 'required': - 'enabled' - 'id' - - 'last_updated' - 'name' - 'rules_count' - 'url' @@ -1434,6 +1433,10 @@ 'type': 'array' 'items': '$ref': '#/components/schemas/Filter' + 'whitelist_filters': + 'type': 'array' + 'items': + '$ref': '#/components/schemas/Filter' 'user_rules': 'type': 'array' 'items': @@ -1451,14 +1454,7 @@ 'description': 'Filtering URL settings' 'properties': 'data': - 'properties': - 'enabled': - 'type': 'boolean' - 'name': - 'type': 'string' - 'url': - 'type': 'string' - 'type': 'object' + '$ref': '#/components/schemas/Filter' 'url': 'type': 'string' 'whitelist': @@ -1860,6 +1856,8 @@ 'description': 'Previously added URL containing filtering rules' 'type': 'string' 'example': 'https://filters.adtidy.org/windows/filters/15.txt' + 'whitelist': + 'type': 'boolean' 'QueryLogItem': 'type': 'object' 'description': 'Query log item' From 5e71f5df6a8cd12a65fecd2f1e28b2aa69609193 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 30 Mar 2022 15:11:57 +0300 Subject: [PATCH 03/99] Pull request: 2846 cover aghnet vol.3 Merge in DNS/adguard-home from 2846-cover-aghnet-vol.3 to master Updates #2846. Squashed commit of the following: commit cb22987c43c17bbc8d098e65639cc84e2284bc7b Merge: cf995e9d f31ffcc5 Author: Eugene Burkov Date: Wed Mar 30 15:01:10 2022 +0300 Merge branch 'master' into 2846-cover-aghnet-vol.3 commit cf995e9dce635f16e10406a61e2ab12f06407f1f Author: Eugene Burkov Date: Mon Mar 28 18:29:50 2022 +0300 aghnet: imp tests commit bc225fe8800633b29216840bc7d5b82d7c2d2bfb Author: Eugene Burkov Date: Mon Mar 28 18:03:06 2022 +0300 aghnet: imp tests commit a82eb6045495b94a2e81ced9a3ef5bfe65788e56 Merge: f8081249 0d562a7b Author: Eugene Burkov Date: Mon Mar 28 17:39:13 2022 +0300 Merge branch 'master' into 2846-cover-aghnet-vol.3 commit f80812490c49f69655d409c6f015b069affa2f19 Merge: edccaa79 3603b1fc Author: Eugene Burkov Date: Mon Mar 28 17:29:20 2022 +0300 Merge branch 'master' into 2846-cover-aghnet-vol.3 commit edccaa79fca061ffeea1985c293eed123b16a09c Author: Eugene Burkov Date: Mon Mar 28 13:53:40 2022 +0300 aghnet: imp tests commit 7c5028c92f0a6680516bda67c73e794182c9b825 Author: Eugene Burkov Date: Fri Mar 25 18:01:28 2022 +0300 aghnet: imp code & docs commit 7897c6b13e9be340ae8a71947a8a0bab82c682eb Author: Eugene Burkov Date: Fri Mar 25 17:11:46 2022 +0300 aghnet: imp coverage commit 1eef110af3bf721a0275c695bf27c31815abff04 Author: Eugene Burkov Date: Wed Mar 23 21:10:29 2022 +0300 all: return byte slice --- internal/aghnet/arpdb.go | 75 +++---- internal/aghnet/arpdb_bsd.go | 5 +- internal/aghnet/arpdb_linux.go | 30 +-- internal/aghnet/arpdb_linux_test.go | 67 ++++--- internal/aghnet/arpdb_openbsd.go | 5 +- internal/aghnet/arpdb_test.go | 41 ++-- internal/aghnet/arpdb_unix.go | 13 -- internal/aghnet/arpdb_windows.go | 11 +- internal/aghnet/hostscontainer_test.go | 4 + internal/aghnet/net.go | 43 ++-- internal/aghnet/net_darwin.go | 134 +++++++------ internal/aghnet/net_darwin_test.go | 261 +++++++++++++++++++++++++ internal/aghnet/net_freebsd.go | 2 +- internal/aghnet/net_freebsd_test.go | 72 ++++--- internal/aghnet/net_linux.go | 29 ++- internal/aghnet/net_linux_test.go | 202 ++++++++++--------- internal/aghnet/net_openbsd.go | 2 +- internal/aghnet/net_openbsd_test.go | 66 ++++--- internal/aghnet/net_test.go | 99 +++++++++- internal/aghos/os.go | 14 +- internal/home/service_openbsd.go | 5 +- 21 files changed, 789 insertions(+), 391 deletions(-) delete mode 100644 internal/aghnet/arpdb_unix.go create mode 100644 internal/aghnet/net_darwin_test.go diff --git a/internal/aghnet/arpdb.go b/internal/aghnet/arpdb.go index afb880c3..4909af5f 100644 --- a/internal/aghnet/arpdb.go +++ b/internal/aghnet/arpdb.go @@ -2,13 +2,11 @@ package aghnet import ( "bufio" + "bytes" "fmt" - "io" "net" - "strings" "sync" - "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/netutil" ) @@ -116,50 +114,33 @@ func (ns *neighs) reset(with []Neighbor) { // of Neighbors. type parseNeighsFunc func(sc *bufio.Scanner, lenHint int) (ns []Neighbor) -// runCmdFunc is the function that runs some command and returns its output -// wrapped to be a io.Reader. -type runCmdFunc func() (r io.Reader, err error) - // cmdARPDB is the implementation of the ARPDB that uses command line to // retrieve data. type cmdARPDB struct { - parse parseNeighsFunc - runcmd runCmdFunc - ns *neighs + parse parseNeighsFunc + ns *neighs + cmd string + args []string } // type check var _ ARPDB = (*cmdARPDB)(nil) -// runCmd runs the cmd with it's args and returns the result wrapped to be an -// io.Reader. The error is returned either if the exit code retured by command -// not equals 0 or the execution itself failed. -func runCmd(cmd string, args ...string) (r io.Reader, err error) { - var code int - var out string - code, out, err = aghos.RunCommand(cmd, args...) - if err != nil { - return nil, err - } else if code != 0 { - return nil, fmt.Errorf("unexpected exit code %d", code) - } - - return strings.NewReader(out), nil -} - // Refresh implements the ARPDB interface for *cmdARPDB. func (arp *cmdARPDB) Refresh() (err error) { defer func() { err = errors.Annotate(err, "cmd arpdb: %w") }() - var r io.Reader - r, err = arp.runcmd() + code, out, err := aghosRunCommand(arp.cmd, arp.args...) if err != nil { return fmt.Errorf("running command: %w", err) + } else if code != 0 { + return fmt.Errorf("running command: unexpected exit code %d", code) } - sc := bufio.NewScanner(r) + sc := bufio.NewScanner(bytes.NewReader(out)) ns := arp.parse(sc, arp.ns.len()) if err = sc.Err(); err != nil { + // TODO(e.burkov): This error seems unreachable. Investigate. return fmt.Errorf("scanning the output: %w", err) } @@ -180,8 +161,7 @@ func (arp *cmdARPDB) Neighbors() (ns []Neighbor) { type arpdbs struct { // arps is the set of ARPDB implementations to range through. arps []ARPDB - // last is the last succeeded ARPDB index. - last int + neighs } // newARPDBs returns a properly initialized *arpdbs. It begins refreshing from @@ -189,7 +169,10 @@ type arpdbs struct { func newARPDBs(arps ...ARPDB) (arp *arpdbs) { return &arpdbs{ arps: arps, - last: 0, + neighs: neighs{ + mu: &sync.RWMutex{}, + ns: make([]Neighbor, 0), + }, } } @@ -199,20 +182,18 @@ var _ ARPDB = (*arpdbs)(nil) // Refresh implements the ARPDB interface for *arpdbs. func (arp *arpdbs) Refresh() (err error) { var errs []error - l := len(arp.arps) - // Start from the last succeeded implementation. - for i := 0; i < l; i++ { - cur := (arp.last + i) % l - err = arp.arps[cur].Refresh() - if err == nil { - // The succeeded implementation found so update the last succeeded - // index. - arp.last = cur - return nil + for _, a := range arp.arps { + err = a.Refresh() + if err != nil { + errs = append(errs, err) + + continue } - errs = append(errs, err) + arp.reset(a.Neighbors()) + + return nil } if len(errs) > 0 { @@ -223,10 +204,8 @@ func (arp *arpdbs) Refresh() (err error) { } // Neighbors implements the ARPDB interface for *arpdbs. +// +// TODO(e.burkov): Think of a way to avoid cloning the slice twice. func (arp *arpdbs) Neighbors() (ns []Neighbor) { - if l := len(arp.arps); l > 0 && arp.last < l { - return arp.arps[arp.last].Neighbors() - } - - return nil + return arp.clone() } diff --git a/internal/aghnet/arpdb_bsd.go b/internal/aghnet/arpdb_bsd.go index fe00418a..a82da76c 100644 --- a/internal/aghnet/arpdb_bsd.go +++ b/internal/aghnet/arpdb_bsd.go @@ -15,12 +15,13 @@ import ( func newARPDB() *cmdARPDB { return &cmdARPDB{ - parse: parseArpA, - runcmd: rcArpA, + parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, ns: make([]Neighbor, 0), }, + cmd: "arp", + args: []string{"-a"}, } } diff --git a/internal/aghnet/arpdb_linux.go b/internal/aghnet/arpdb_linux.go index 976d8b7a..3d391f29 100644 --- a/internal/aghnet/arpdb_linux.go +++ b/internal/aghnet/arpdb_linux.go @@ -6,7 +6,6 @@ package aghnet import ( "bufio" "fmt" - "io" "io/fs" "net" "strings" @@ -34,11 +33,25 @@ func newARPDB() (arp *arpdbs) { return newARPDBs( // Try /proc/net/arp first. - &fsysARPDB{ns: ns, fsys: aghos.RootDirFS(), filename: "proc/net/arp"}, - // Try "arp -a" then. - &cmdARPDB{parse: parseF, runcmd: rcArpA, ns: ns}, - // Try "ip neigh" finally. - &cmdARPDB{parse: parseIPNeigh, runcmd: rcIPNeigh, ns: ns}, + &fsysARPDB{ + ns: ns, + fsys: rootDirFS, + filename: "proc/net/arp", + }, + // Then, try "arp -a". + &cmdARPDB{ + parse: parseF, + ns: ns, + cmd: "arp", + args: []string{"-a"}, + }, + // Finally, try "ip neigh". + &cmdARPDB{ + parse: parseIPNeigh, + ns: ns, + cmd: "ip", + args: []string{"neigh"}, + }, ) } @@ -187,11 +200,6 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) { return ns } -// rcIPNeigh runs "ip neigh". -func rcIPNeigh() (r io.Reader, err error) { - return runCmd("ip", "neigh") -} - // parseIPNeigh parses the output of the "ip neigh" command on Linux. The // expected input format: // diff --git a/internal/aghnet/arpdb_linux_test.go b/internal/aghnet/arpdb_linux_test.go index b9ed859f..46d87150 100644 --- a/internal/aghnet/arpdb_linux_test.go +++ b/internal/aghnet/arpdb_linux_test.go @@ -4,11 +4,10 @@ package aghnet import ( - "io" "net" - "strings" "sync" "testing" + "testing/fstest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -43,6 +42,8 @@ var wantNeighs = []Neighbor{{ }} func TestFSysARPDB(t *testing.T) { + require.NoError(t, fstest.TestFS(testdata, "proc_net_arp")) + a := &fsysARPDB{ ns: &neighs{ mu: &sync.RWMutex{}, @@ -59,33 +60,43 @@ func TestFSysARPDB(t *testing.T) { assert.Equal(t, wantNeighs, ns) } -func TestCmdARPDB_arpawrt(t *testing.T) { - a := &cmdARPDB{ - parse: parseArpAWrt, - runcmd: func() (r io.Reader, err error) { return strings.NewReader(arpAOutputWrt), nil }, - ns: &neighs{ - mu: &sync.RWMutex{}, - ns: make([]Neighbor, 0), - }, +func TestCmdARPDB_linux(t *testing.T) { + sh := mapShell{ + "arp -a": {err: nil, out: arpAOutputWrt, code: 0}, + "ip neigh": {err: nil, out: ipNeighOutput, code: 0}, } + substShell(t, sh.RunCmd) - err := a.Refresh() - require.NoError(t, err) + t.Run("wrt", func(t *testing.T) { + a := &cmdARPDB{ + parse: parseArpAWrt, + cmd: "arp", + args: []string{"-a"}, + ns: &neighs{ + mu: &sync.RWMutex{}, + ns: make([]Neighbor, 0), + }, + } - assert.Equal(t, wantNeighs, a.Neighbors()) -} - -func TestCmdARPDB_ipneigh(t *testing.T) { - a := &cmdARPDB{ - parse: parseIPNeigh, - runcmd: func() (r io.Reader, err error) { return strings.NewReader(ipNeighOutput), nil }, - ns: &neighs{ - mu: &sync.RWMutex{}, - ns: make([]Neighbor, 0), - }, - } - err := a.Refresh() - require.NoError(t, err) - - assert.Equal(t, wantNeighs, a.Neighbors()) + err := a.Refresh() + require.NoError(t, err) + + assert.Equal(t, wantNeighs, a.Neighbors()) + }) + + t.Run("ip_neigh", func(t *testing.T) { + a := &cmdARPDB{ + parse: parseIPNeigh, + cmd: "ip", + args: []string{"neigh"}, + ns: &neighs{ + mu: &sync.RWMutex{}, + ns: make([]Neighbor, 0), + }, + } + err := a.Refresh() + require.NoError(t, err) + + assert.Equal(t, wantNeighs, a.Neighbors()) + }) } diff --git a/internal/aghnet/arpdb_openbsd.go b/internal/aghnet/arpdb_openbsd.go index 805cb459..a00ffa85 100644 --- a/internal/aghnet/arpdb_openbsd.go +++ b/internal/aghnet/arpdb_openbsd.go @@ -14,12 +14,13 @@ import ( func newARPDB() *cmdARPDB { return &cmdARPDB{ - runcmd: rcArpA, - parse: parseArpA, + parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, ns: make([]Neighbor, 0), }, + cmd: "arp", + args: []string{"-a"}, } } diff --git a/internal/aghnet/arpdb_test.go b/internal/aghnet/arpdb_test.go index aa5c821a..75778b74 100644 --- a/internal/aghnet/arpdb_test.go +++ b/internal/aghnet/arpdb_test.go @@ -1,12 +1,9 @@ package aghnet import ( - "io" "net" - "strings" "sync" "testing" - "testing/iotest" "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/testutil" @@ -16,9 +13,7 @@ import ( func TestNewARPDB(t *testing.T) { var a ARPDB - require.NotPanics(t, func() { - a = NewARPDB() - }) + require.NotPanics(t, func() { a = NewARPDB() }) assert.NotNil(t, a) } @@ -135,11 +130,11 @@ func TestARPDBS(t *testing.T) { assert.Equal(t, 1, succRefrCount) assert.NotEmpty(t, a.Neighbors()) - // Only the last succeeded ARPDB should be used. + // Unstable ARPDB should refresh successfully again. err = a.Refresh() require.NoError(t, err) - assert.Equal(t, 2, succRefrCount) + assert.Equal(t, 1, succRefrCount) assert.NotEmpty(t, a.Neighbors()) }) @@ -153,6 +148,7 @@ func TestARPDBS(t *testing.T) { func TestCmdARPDB_arpa(t *testing.T) { a := &cmdARPDB{ + cmd: "cmd", parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, @@ -161,7 +157,8 @@ func TestCmdARPDB_arpa(t *testing.T) { } t.Run("arp_a", func(t *testing.T) { - a.runcmd = func() (r io.Reader, err error) { return strings.NewReader(arpAOutput), nil } + sh := theOnlyCmd("cmd", 0, arpAOutput, nil) + substShell(t, sh.RunCmd) err := a.Refresh() require.NoError(t, err) @@ -170,32 +167,20 @@ func TestCmdARPDB_arpa(t *testing.T) { }) t.Run("runcmd_error", func(t *testing.T) { - a.runcmd = func() (r io.Reader, err error) { return nil, errors.Error("can't run") } + sh := theOnlyCmd("cmd", 0, "", errors.Error("can't run")) + substShell(t, sh.RunCmd) err := a.Refresh() testutil.AssertErrorMsg(t, "cmd arpdb: running command: can't run", err) }) -} -func TestCmdARPDB_errors(t *testing.T) { - const errRead errors.Error = "can't read" + t.Run("bad_code", func(t *testing.T) { + sh := theOnlyCmd("cmd", 1, "", nil) + substShell(t, sh.RunCmd) - badReaderRunCmd := runCmdFunc(func() (r io.Reader, err error) { - return iotest.ErrReader(errRead), nil + err := a.Refresh() + testutil.AssertErrorMsg(t, "cmd arpdb: running command: unexpected exit code 1", err) }) - - a := &cmdARPDB{ - runcmd: badReaderRunCmd, - parse: parseArpA, - ns: &neighs{ - mu: &sync.RWMutex{}, - ns: make([]Neighbor, 0), - }, - } - - const wantErrMsg string = "cmd arpdb: scanning the output: " + string(errRead) - - testutil.AssertErrorMsg(t, wantErrMsg, a.Refresh()) } func TestEmptyARPDB(t *testing.T) { diff --git a/internal/aghnet/arpdb_unix.go b/internal/aghnet/arpdb_unix.go deleted file mode 100644 index 50346f92..00000000 --- a/internal/aghnet/arpdb_unix.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows -// +build !windows - -package aghnet - -import ( - "io" -) - -// rcArpA runs "arp -a". -func rcArpA() (r io.Reader, err error) { - return runCmd("arp", "-a") -} diff --git a/internal/aghnet/arpdb_windows.go b/internal/aghnet/arpdb_windows.go index 5156330b..2a70125f 100644 --- a/internal/aghnet/arpdb_windows.go +++ b/internal/aghnet/arpdb_windows.go @@ -5,7 +5,6 @@ package aghnet import ( "bufio" - "io" "net" "strings" "sync" @@ -13,20 +12,16 @@ import ( func newARPDB() *cmdARPDB { return &cmdARPDB{ - runcmd: rcArpA, + parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, ns: make([]Neighbor, 0), }, - parse: parseArpA, + cmd: "arp", + args: []string{"/a"}, } } -// rcArpA runs "arp /a". -func rcArpA() (r io.Reader, err error) { - return runCmd("arp", "/a") -} - // parseArpA parses the output of the "arp /a" command on Windows. The expected // input format (the first line is empty): // diff --git a/internal/aghnet/hostscontainer_test.go b/internal/aghnet/hostscontainer_test.go index 40bfb34c..807722a8 100644 --- a/internal/aghnet/hostscontainer_test.go +++ b/internal/aghnet/hostscontainer_test.go @@ -286,6 +286,8 @@ func TestHostsContainer_Translate(t *testing.T) { OnClose: func() (err error) { panic("not implemented") }, } + require.NoError(t, fstest.TestFS(testdata, "etc_hosts")) + hc, err := NewHostsContainer(0, testdata, &stubWatcher, "etc_hosts") require.NoError(t, err) testutil.CleanupAndRequireSuccess(t, hc.Close) @@ -358,6 +360,8 @@ func TestHostsContainer_Translate(t *testing.T) { func TestHostsContainer(t *testing.T) { const listID = 1234 + require.NoError(t, fstest.TestFS(testdata, "etc_hosts")) + testCases := []struct { want []*rules.DNSRewrite name string diff --git a/internal/aghnet/net.go b/internal/aghnet/net.go index 2d791c03..d17b9165 100644 --- a/internal/aghnet/net.go +++ b/internal/aghnet/net.go @@ -2,19 +2,27 @@ package aghnet import ( + "bytes" "encoding/json" "fmt" "io" "net" - "os/exec" - "strings" "syscall" + "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/netutil" ) +// aghosRunCommand is the function to run shell commands. It's an unexported +// variable instead of a direct call to make it substitutable in tests. +var aghosRunCommand = aghos.RunCommand + +// rootDirFS is the filesystem pointing to the root directory. It's an +// unexported variable instead to make it substitutable in tests. +var rootDirFS = aghos.RootDirFS() + // ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about // the IP being static is available. const ErrNoStaticIPInfo errors.Error = "no information about static ip" @@ -32,22 +40,29 @@ func IfaceSetStaticIP(ifaceName string) (err error) { } // GatewayIP returns IP address of interface's gateway. -func GatewayIP(ifaceName string) net.IP { - cmd := exec.Command("ip", "route", "show", "dev", ifaceName) - log.Tracef("executing %s %v", cmd.Path, cmd.Args) - d, err := cmd.Output() - if err != nil || cmd.ProcessState.ExitCode() != 0 { +// +// TODO(e.burkov): Investigate if the gateway address may be fetched in another +// way since not every machine has the software installed. +func GatewayIP(ifaceName string) (ip net.IP) { + code, out, err := aghosRunCommand("ip", "route", "show", "dev", ifaceName) + if err != nil { + log.Debug("%s", err) + + return nil + } else if code != 0 { + log.Debug("fetching gateway ip: unexpected exit code: %d", code) + return nil } - fields := strings.Fields(string(d)) + fields := bytes.Fields(out) // The meaningful "ip route" command output should contain the word // "default" at first field and default gateway IP address at third field. - if len(fields) < 3 || fields[0] != "default" { + if len(fields) < 3 || string(fields[0]) != "default" { return nil } - return net.ParseIP(fields[2]) + return net.ParseIP(string(fields[2])) } // CanBindPort checks if we can bind to the given port. @@ -101,7 +116,7 @@ func (iface NetInterface) MarshalJSON() ([]byte, error) { // GetValidNetInterfacesForWeb returns interfaces that are eligible for DNS and WEB only // we do not return link-local addresses here -func GetValidNetInterfacesForWeb() ([]*NetInterface, error) { +func GetValidNetInterfacesForWeb() (netInterfaces []*NetInterface, err error) { ifaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("couldn't get interfaces: %w", err) @@ -109,8 +124,6 @@ func GetValidNetInterfacesForWeb() ([]*NetInterface, error) { return nil, errors.Error("couldn't find any legible interface") } - var netInterfaces []*NetInterface - for _, iface := range ifaces { var addrs []net.Addr addrs, err = iface.Addrs() @@ -130,12 +143,14 @@ func GetValidNetInterfacesForWeb() ([]*NetInterface, error) { ipNet, ok := addr.(*net.IPNet) if !ok { // Should be net.IPNet, this is weird. - return nil, fmt.Errorf("got iface.Addrs() element %s that is not net.IPNet, it is %T", addr, addr) + return nil, fmt.Errorf("got %s that is not net.IPNet, it is %T", addr, addr) } + // Ignore link-local. if ipNet.IP.IsLinkLocalUnicast() { continue } + netIface.Addresses = append(netIface.Addresses, ipNet.IP) netIface.Subnets = append(netIface.Subnets, ipNet) } diff --git a/internal/aghnet/net_darwin.go b/internal/aghnet/net_darwin.go index 3c504988..63e57dc4 100644 --- a/internal/aghnet/net_darwin.go +++ b/internal/aghnet/net_darwin.go @@ -4,10 +4,11 @@ package aghnet import ( + "bufio" + "bytes" "fmt" - "os" + "io" "regexp" - "strings" "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/golibs/errors" @@ -27,7 +28,7 @@ func canBindPrivilegedPorts() (can bool, err error) { return aghos.HaveAdminRights() } -func ifaceHasStaticIP(ifaceName string) (bool, error) { +func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { portInfo, err := getCurrentHardwarePortInfo(ifaceName) if err != nil { return false, err @@ -36,9 +37,10 @@ func ifaceHasStaticIP(ifaceName string) (bool, error) { return portInfo.static, nil } -// getCurrentHardwarePortInfo gets information for the specified network interface. +// getCurrentHardwarePortInfo gets information for the specified network +// interface. func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) { - // First of all we should find hardware port name + // First of all we should find hardware port name. m := getNetworkSetupHardwareReports() hardwarePort, ok := m[ifaceName] if !ok { @@ -48,6 +50,10 @@ func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) { return getHardwarePortInfo(hardwarePort) } +// hardwareReportsReg is the regular expression matching the lines of +// networksetup command output lines containing the interface information. +var hardwareReportsReg = regexp.MustCompile("Hardware Port: (.*?)\nDevice: (.*?)\n") + // getNetworkSetupHardwareReports parses the output of the `networksetup // -listallhardwareports` command it returns a map where the key is the // interface name, and the value is the "hardware port" returns nil if it fails @@ -56,54 +62,44 @@ func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) { // TODO(e.burkov): There should be more proper approach than parsing the // command output. For example, see // https://developer.apple.com/documentation/systemconfiguration. -func getNetworkSetupHardwareReports() map[string]string { - _, out, err := aghos.RunCommand("networksetup", "-listallhardwareports") +func getNetworkSetupHardwareReports() (reports map[string]string) { + _, out, err := aghosRunCommand("networksetup", "-listallhardwareports") if err != nil { return nil } - re, err := regexp.Compile("Hardware Port: (.*?)\nDevice: (.*?)\n") - if err != nil { - return nil + reports = make(map[string]string) + + matches := hardwareReportsReg.FindAllSubmatch(out, -1) + for _, m := range matches { + reports[string(m[2])] = string(m[1]) } - m := make(map[string]string) - - matches := re.FindAllStringSubmatch(out, -1) - for i := range matches { - port := matches[i][1] - device := matches[i][2] - m[device] = port - } - - return m + return reports } -func getHardwarePortInfo(hardwarePort string) (hardwarePortInfo, error) { - h := hardwarePortInfo{} +// hardwarePortReg is the regular expression matching the lines of networksetup +// command output lines containing the port information. +var hardwarePortReg = regexp.MustCompile("IP address: (.*?)\nSubnet mask: (.*?)\nRouter: (.*?)\n") - _, out, err := aghos.RunCommand("networksetup", "-getinfo", hardwarePort) +func getHardwarePortInfo(hardwarePort string) (h hardwarePortInfo, err error) { + _, out, err := aghosRunCommand("networksetup", "-getinfo", hardwarePort) if err != nil { return h, err } - re := regexp.MustCompile("IP address: (.*?)\nSubnet mask: (.*?)\nRouter: (.*?)\n") - - match := re.FindStringSubmatch(out) - if len(match) == 0 { + match := hardwarePortReg.FindSubmatch(out) + if len(match) != 4 { return h, errors.Error("could not find hardware port info") } - h.name = hardwarePort - h.ip = match[1] - h.subnet = match[2] - h.gatewayIP = match[3] - - if strings.Index(out, "Manual Configuration") == 0 { - h.static = true - } - - return h, nil + return hardwarePortInfo{ + name: hardwarePort, + ip: string(match[1]), + subnet: string(match[2]), + gatewayIP: string(match[3]), + static: bytes.Index(out, []byte("Manual Configuration")) == 0, + }, nil } func ifaceSetStaticIP(ifaceName string) (err error) { @@ -113,7 +109,7 @@ func ifaceSetStaticIP(ifaceName string) (err error) { } if portInfo.static { - return errors.Error("IP address is already static") + return errors.Error("ip address is already static") } dnsAddrs, err := getEtcResolvConfServers() @@ -121,50 +117,62 @@ func ifaceSetStaticIP(ifaceName string) (err error) { return err } - args := make([]string, 0) - args = append(args, "-setdnsservers", portInfo.name) - args = append(args, dnsAddrs...) + args := append([]string{"-setdnsservers", portInfo.name}, dnsAddrs...) // Setting DNS servers is necessary when configuring a static IP - code, _, err := aghos.RunCommand("networksetup", args...) + code, _, err := aghosRunCommand("networksetup", args...) if err != nil { return err - } - if code != 0 { + } else if code != 0 { return fmt.Errorf("failed to set DNS servers, code=%d", code) } // Actually configures hardware port to have static IP - code, _, err = aghos.RunCommand("networksetup", "-setmanual", - portInfo.name, portInfo.ip, portInfo.subnet, portInfo.gatewayIP) + code, _, err = aghosRunCommand( + "networksetup", + "-setmanual", + portInfo.name, + portInfo.ip, + portInfo.subnet, + portInfo.gatewayIP, + ) if err != nil { return err - } - if code != 0 { + } else if code != 0 { return fmt.Errorf("failed to set DNS servers, code=%d", code) } return nil } +// etcResolvConfReg is the regular expression matching the lines of resolv.conf +// file containing a name server information. +var etcResolvConfReg = regexp.MustCompile("nameserver ([a-zA-Z0-9.:]+)") + // getEtcResolvConfServers returns a list of nameservers configured in // /etc/resolv.conf. -func getEtcResolvConfServers() ([]string, error) { - body, err := os.ReadFile("/etc/resolv.conf") +func getEtcResolvConfServers() (addrs []string, err error) { + const filename = "etc/resolv.conf" + + _, err = aghos.FileWalker(func(r io.Reader) (_ []string, _ bool, err error) { + sc := bufio.NewScanner(r) + for sc.Scan() { + matches := etcResolvConfReg.FindAllStringSubmatch(sc.Text(), -1) + if len(matches) == 0 { + continue + } + + for _, m := range matches { + addrs = append(addrs, m[1]) + } + } + + return nil, false, sc.Err() + }).Walk(rootDirFS, filename) if err != nil { - return nil, err - } - - re := regexp.MustCompile("nameserver ([a-zA-Z0-9.:]+)") - - matches := re.FindAllStringSubmatch(string(body), -1) - if len(matches) == 0 { - return nil, errors.Error("found no DNS servers in /etc/resolv.conf") - } - - addrs := make([]string, 0) - for i := range matches { - addrs = append(addrs, matches[i][1]) + return nil, fmt.Errorf("parsing etc/resolv.conf file: %w", err) + } else if len(addrs) == 0 { + return nil, fmt.Errorf("found no dns servers in %s", filename) } return addrs, nil diff --git a/internal/aghnet/net_darwin_test.go b/internal/aghnet/net_darwin_test.go new file mode 100644 index 00000000..905600d5 --- /dev/null +++ b/internal/aghnet/net_darwin_test.go @@ -0,0 +1,261 @@ +package aghnet + +import ( + "io/fs" + "testing" + "testing/fstest" + + "github.com/AdguardTeam/AdGuardHome/internal/aghtest" + "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/testutil" + "github.com/stretchr/testify/assert" +) + +func TestIfaceHasStaticIP(t *testing.T) { + testCases := []struct { + name string + shell mapShell + ifaceName string + wantHas assert.BoolAssertionFunc + wantErrMsg string + }{{ + name: "success", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "IP address: 1.2.3.4\nSubnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + }, + ifaceName: "en0", + wantHas: assert.False, + wantErrMsg: ``, + }, { + name: "success_static", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "Manual Configuration\nIP address: 1.2.3.4\n" + + "Subnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + }, + ifaceName: "en0", + wantHas: assert.True, + wantErrMsg: ``, + }, { + name: "reports_error", + shell: theOnlyCmd( + "networksetup -listallhardwareports", + 0, + "", + errors.Error("can't list"), + ), + ifaceName: "en0", + wantHas: assert.False, + wantErrMsg: `could not find hardware port for en0`, + }, { + name: "port_error", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: errors.Error("can't get"), + out: ``, + code: 0, + }, + }, + ifaceName: "en0", + wantHas: assert.False, + wantErrMsg: `can't get`, + }, { + name: "port_bad_output", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "nothing meaningful", + code: 0, + }, + }, + ifaceName: "en0", + wantHas: assert.False, + wantErrMsg: `could not find hardware port info`, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + substShell(t, tc.shell.RunCmd) + + has, err := IfaceHasStaticIP(tc.ifaceName) + testutil.AssertErrorMsg(t, tc.wantErrMsg, err) + + tc.wantHas(t, has) + }) + } +} + +func TestIfaceSetStaticIP(t *testing.T) { + succFsys := fstest.MapFS{ + "etc/resolv.conf": &fstest.MapFile{ + Data: []byte(`nameserver 1.1.1.1`), + }, + } + panicFsys := &aghtest.FS{ + OnOpen: func(name string) (fs.File, error) { panic("not implemented") }, + } + + testCases := []struct { + name string + shell mapShell + fsys fs.FS + wantErrMsg string + }{{ + name: "success", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "IP address: 1.2.3.4\nSubnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + "networksetup -setdnsservers hwport 1.1.1.1": { + err: nil, + out: "", + code: 0, + }, + "networksetup -setmanual hwport 1.2.3.4 255.255.255.0 1.2.3.1": { + err: nil, + out: "", + code: 0, + }, + }, + fsys: succFsys, + wantErrMsg: ``, + }, { + name: "static_already", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "Manual Configuration\nIP address: 1.2.3.4\n" + + "Subnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + }, + fsys: panicFsys, + wantErrMsg: `ip address is already static`, + }, { + name: "reports_error", + shell: theOnlyCmd( + "networksetup -listallhardwareports", + 0, + "", + errors.Error("can't list"), + ), + fsys: panicFsys, + wantErrMsg: `could not find hardware port for en0`, + }, { + name: "resolv_conf_error", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "IP address: 1.2.3.4\nSubnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + }, + fsys: fstest.MapFS{ + "etc/resolv.conf": &fstest.MapFile{ + Data: []byte("this resolv.conf is invalid"), + }, + }, + wantErrMsg: `found no dns servers in etc/resolv.conf`, + }, { + name: "set_dns_error", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "IP address: 1.2.3.4\nSubnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + "networksetup -setdnsservers hwport 1.1.1.1": { + err: errors.Error("can't set"), + out: "", + code: 0, + }, + }, + fsys: succFsys, + wantErrMsg: `can't set`, + }, { + name: "set_manual_error", + shell: mapShell{ + "networksetup -listallhardwareports": { + err: nil, + out: "Hardware Port: hwport\nDevice: en0\n", + code: 0, + }, + "networksetup -getinfo hwport": { + err: nil, + out: "IP address: 1.2.3.4\nSubnet mask: 255.255.255.0\nRouter: 1.2.3.1\n", + code: 0, + }, + "networksetup -setdnsservers hwport 1.1.1.1": { + err: nil, + out: "", + code: 0, + }, + "networksetup -setmanual hwport 1.2.3.4 255.255.255.0 1.2.3.1": { + err: errors.Error("can't set"), + out: "", + code: 0, + }, + }, + fsys: succFsys, + wantErrMsg: `can't set`, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + substShell(t, tc.shell.RunCmd) + substRootDirFS(t, tc.fsys) + + err := IfaceSetStaticIP("en0") + testutil.AssertErrorMsg(t, tc.wantErrMsg, err) + }) + } +} diff --git a/internal/aghnet/net_freebsd.go b/internal/aghnet/net_freebsd.go index a5200fb8..34d93303 100644 --- a/internal/aghnet/net_freebsd.go +++ b/internal/aghnet/net_freebsd.go @@ -22,7 +22,7 @@ func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { walker := aghos.FileWalker(interfaceName(ifaceName).rcConfStaticConfig) - return walker.Walk(aghos.RootDirFS(), rcConfFilename) + return walker.Walk(rootDirFS, rcConfFilename) } // rcConfStaticConfig checks if the interface is configured by /etc/rc.conf to diff --git a/internal/aghnet/net_freebsd_test.go b/internal/aghnet/net_freebsd_test.go index 3781b154..e00dafa7 100644 --- a/internal/aghnet/net_freebsd_test.go +++ b/internal/aghnet/net_freebsd_test.go @@ -4,56 +4,74 @@ package aghnet import ( - "strings" + "io/fs" "testing" + "testing/fstest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestRcConfStaticConfig(t *testing.T) { - const iface interfaceName = `em0` - const nl = "\n" + const ( + ifaceName = `em0` + rcConf = "etc/rc.conf" + ) testCases := []struct { - name string - rcconfData string - wantCont bool + name string + rootFsys fs.FS + wantHas assert.BoolAssertionFunc }{{ - name: "simple", - rcconfData: `ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl, - wantCont: false, + name: "simple", + rootFsys: fstest.MapFS{rcConf: &fstest.MapFile{ + Data: []byte(`ifconfig_` + ifaceName + `="inet 127.0.0.253 netmask 0xffffffff"` + nl), + }}, + wantHas: assert.True, }, { - name: "case_insensitiveness", - rcconfData: `ifconfig_em0="InEt 127.0.0.253 NeTmAsK 0xffffffff"` + nl, - wantCont: false, + name: "case_insensitiveness", + rootFsys: fstest.MapFS{rcConf: &fstest.MapFile{ + Data: []byte(`ifconfig_` + ifaceName + `="InEt 127.0.0.253 NeTmAsK 0xffffffff"` + nl), + }}, + wantHas: assert.True, }, { name: "comments_and_trash", - rcconfData: `# comment 1` + nl + - `` + nl + - `# comment 2` + nl + - `ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl, - wantCont: false, + rootFsys: fstest.MapFS{rcConf: &fstest.MapFile{ + Data: []byte(`# comment 1` + nl + + `` + nl + + `# comment 2` + nl + + `ifconfig_` + ifaceName + `="inet 127.0.0.253 netmask 0xffffffff"` + nl, + ), + }}, + wantHas: assert.True, }, { name: "aliases", - rcconfData: `ifconfig_em0_alias="inet 127.0.0.1/24"` + nl + - `ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl, - wantCont: false, + rootFsys: fstest.MapFS{rcConf: &fstest.MapFile{ + Data: []byte(`ifconfig_` + ifaceName + `_alias="inet 127.0.0.1/24"` + nl + + `ifconfig_` + ifaceName + `="inet 127.0.0.253 netmask 0xffffffff"` + nl, + ), + }}, + wantHas: assert.True, }, { name: "incorrect_config", - rcconfData: `ifconfig_em0="inet6 127.0.0.253 netmask 0xffffffff"` + nl + - `ifconfig_em0="inet 256.256.256.256 netmask 0xffffffff"` + nl + - `ifconfig_em0=""` + nl, - wantCont: true, + rootFsys: fstest.MapFS{rcConf: &fstest.MapFile{ + Data: []byte( + `ifconfig_` + ifaceName + `="inet6 127.0.0.253 netmask 0xffffffff"` + nl + + `ifconfig_` + ifaceName + `="inet 256.256.256.256 netmask 0xffffffff"` + nl + + `ifconfig_` + ifaceName + `=""` + nl, + ), + }}, + wantHas: assert.False, }} for _, tc := range testCases { - r := strings.NewReader(tc.rcconfData) t.Run(tc.name, func(t *testing.T) { - _, cont, err := iface.rcConfStaticConfig(r) + substRootDirFS(t, tc.rootFsys) + + has, err := IfaceHasStaticIP(ifaceName) require.NoError(t, err) - assert.Equal(t, tc.wantCont, cont) + tc.wantHas(t, has) }) } } diff --git a/internal/aghnet/net_linux.go b/internal/aghnet/net_linux.go index 93414165..c2526524 100644 --- a/internal/aghnet/net_linux.go +++ b/internal/aghnet/net_linux.go @@ -21,8 +21,7 @@ import ( // have a static IP. func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) { s := bufio.NewScanner(r) - ifaceFound := findIfaceLine(s, string(n)) - if !ifaceFound { + if !findIfaceLine(s, string(n)) { return nil, true, s.Err() } @@ -61,9 +60,9 @@ func (n interfaceName) ifacesStaticConfig(r io.Reader) (sub []string, cont bool, fields := strings.Fields(line) fieldsNum := len(fields) - // Man page interfaces(5) declares that interface definition - // should consist of the key word "iface" followed by interface - // name, and method at fourth field. + // Man page interfaces(5) declares that interface definition should + // consist of the key word "iface" followed by interface name, and + // method at fourth field. if fieldsNum >= 4 && fields[0] == "iface" && fields[1] == string(n) && fields[3] == "static" { return nil, false, nil @@ -78,10 +77,10 @@ func (n interfaceName) ifacesStaticConfig(r io.Reader) (sub []string, cont bool, } func ifaceHasStaticIP(ifaceName string) (has bool, err error) { - // 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. + // TODO(a.garipov): Currently, this function returns the first definitive + // result. So if /etc/dhcpcd.conf has and /etc/network/interfaces has no + // static IP configuration, it will return true. Perhaps this is not the + // most desirable behavior. iface := interfaceName(ifaceName) @@ -95,12 +94,10 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { FileWalker: iface.ifacesStaticConfig, filename: "etc/network/interfaces", }} { - has, err = pair.Walk(aghos.RootDirFS(), pair.filename) + has, err = pair.Walk(rootDirFS, pair.filename) if err != nil { return false, err - } - - if has { + } else if has { return true, nil } } @@ -141,13 +138,15 @@ func ifaceSetStaticIP(ifaceName string) (err error) { gatewayIP := GatewayIP(ifaceName) add := dhcpcdConfIface(ifaceName, ipNet, gatewayIP, ipNet.IP) - body, err := os.ReadFile("/etc/dhcpcd.conf") + const filename = "/etc/dhcpcd.conf" + + body, err := os.ReadFile(filename) if err != nil && !errors.Is(err, os.ErrNotExist) { return err } body = append(body, []byte(add)...) - err = maybe.WriteFile("/etc/dhcpcd.conf", body, 0o644) + err = maybe.WriteFile(filename, body, 0o644) if err != nil { return fmt.Errorf("writing conf: %w", err) } diff --git a/internal/aghnet/net_linux_test.go b/internal/aghnet/net_linux_test.go index bf2cecfe..e46da4df 100644 --- a/internal/aghnet/net_linux_test.go +++ b/internal/aghnet/net_linux_test.go @@ -4,122 +4,130 @@ package aghnet import ( - "bytes" + "io/fs" "net" "testing" + "testing/fstest" + "github.com/AdguardTeam/golibs/testutil" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestDHCPCDStaticConfig(t *testing.T) { - const iface interfaceName = `wlan0` +func TestHasStaticIP(t *testing.T) { + const ifaceName = "wlan0" + + const ( + dhcpcd = "etc/dhcpcd.conf" + netifaces = "etc/network/interfaces" + ) testCases := []struct { - name string - data []byte - wantCont bool + rootFsys fs.FS + name string + wantHas assert.BoolAssertionFunc + wantErrMsg string }{{ - name: "has_not", - data: []byte(`#comment` + nl + - `# comment` + nl + - `interface eth0` + nl + - `static ip_address=192.168.0.1/24` + nl + - `# interface ` + iface + nl + - `static ip_address=192.168.1.1/24` + nl + - `# comment` + nl, - ), - wantCont: true, + rootFsys: fstest.MapFS{ + dhcpcd: &fstest.MapFile{ + Data: []byte(`#comment` + nl + + `# comment` + nl + + `interface eth0` + nl + + `static ip_address=192.168.0.1/24` + nl + + `# interface ` + ifaceName + nl + + `static ip_address=192.168.1.1/24` + nl + + `# comment` + nl, + ), + }, + }, + name: "dhcpcd_has_not", + wantHas: assert.False, + wantErrMsg: `no information about static ip`, }, { - name: "has", - data: []byte(`#comment` + nl + - `# comment` + nl + - `interface eth0` + nl + - `static ip_address=192.168.0.1/24` + nl + - `# interface ` + iface + nl + - `static ip_address=192.168.1.1/24` + nl + - `# comment` + nl + - `interface ` + iface + nl + - `# comment` + nl + - `static ip_address=192.168.2.1/24` + nl, - ), - wantCont: false, + rootFsys: fstest.MapFS{ + dhcpcd: &fstest.MapFile{ + Data: []byte(`#comment` + nl + + `# comment` + nl + + `interface ` + ifaceName + nl + + `static ip_address=192.168.0.1/24` + nl + + `# interface ` + ifaceName + nl + + `static ip_address=192.168.1.1/24` + nl + + `# comment` + nl, + ), + }, + }, + name: "dhcpcd_has", + wantHas: assert.True, + wantErrMsg: ``, + }, { + rootFsys: fstest.MapFS{ + netifaces: &fstest.MapFile{ + Data: []byte(`allow-hotplug ` + ifaceName + nl + + `#iface enp0s3 inet static` + nl + + `# address 192.168.0.200` + nl + + `# netmask 255.255.255.0` + nl + + `# gateway 192.168.0.1` + nl + + `iface ` + ifaceName + ` inet dhcp` + nl, + ), + }, + }, + name: "netifaces_has_not", + wantHas: assert.False, + wantErrMsg: `no information about static ip`, + }, { + rootFsys: fstest.MapFS{ + netifaces: &fstest.MapFile{ + Data: []byte(`allow-hotplug ` + ifaceName + nl + + `iface ` + ifaceName + ` inet static` + nl + + ` address 192.168.0.200` + nl + + ` netmask 255.255.255.0` + nl + + ` gateway 192.168.0.1` + nl + + `#iface ` + ifaceName + ` inet dhcp` + nl, + ), + }, + }, + name: "netifaces_has", + wantHas: assert.True, + wantErrMsg: ``, + }, { + rootFsys: fstest.MapFS{ + netifaces: &fstest.MapFile{ + Data: []byte(`source hello` + nl + + `#iface ` + ifaceName + ` inet static` + nl, + ), + }, + "hello": &fstest.MapFile{ + Data: []byte(`iface ` + ifaceName + ` inet static` + nl), + }, + }, + name: "netifaces_another_file", + wantHas: assert.True, + wantErrMsg: ``, + }, { + rootFsys: fstest.MapFS{ + netifaces: &fstest.MapFile{ + Data: []byte(`source hello` + nl + + `iface ` + ifaceName + ` inet static` + nl, + ), + }, + }, + name: "netifaces_ignore_another", + wantHas: assert.True, + wantErrMsg: ``, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - r := bytes.NewReader(tc.data) - _, cont, err := iface.dhcpcdStaticConfig(r) - require.NoError(t, err) + substRootDirFS(t, tc.rootFsys) - assert.Equal(t, tc.wantCont, cont) + has, err := IfaceHasStaticIP(ifaceName) + testutil.AssertErrorMsg(t, tc.wantErrMsg, err) + + tc.wantHas(t, has) }) } } -func TestIfacesStaticConfig(t *testing.T) { - const iface interfaceName = `enp0s3` - - testCases := []struct { - name string - data []byte - wantCont bool - wantPatterns []string - }{{ - name: "has_not", - data: []byte(`allow-hotplug ` + iface + nl + - `#iface enp0s3 inet static` + nl + - `# address 192.168.0.200` + nl + - `# netmask 255.255.255.0` + nl + - `# gateway 192.168.0.1` + nl + - `iface ` + iface + ` inet dhcp` + nl, - ), - wantCont: true, - wantPatterns: []string{}, - }, { - name: "has", - data: []byte(`allow-hotplug ` + iface + nl + - `iface ` + iface + ` inet static` + nl + - ` address 192.168.0.200` + nl + - ` netmask 255.255.255.0` + nl + - ` gateway 192.168.0.1` + nl + - `#iface ` + iface + ` inet dhcp` + nl, - ), - wantCont: false, - wantPatterns: []string{}, - }, { - name: "return_patterns", - data: []byte(`source hello` + nl + - `source world` + nl + - `#iface ` + iface + ` inet static` + nl, - ), - wantCont: true, - wantPatterns: []string{"hello", "world"}, - }, { - // This one tests if the first found valid interface prevents - // checking files under the `source` directive. - name: "ignore_patterns", - data: []byte(`source hello` + nl + - `source world` + nl + - `iface ` + iface + ` inet static` + nl, - ), - wantCont: false, - wantPatterns: []string{}, - }} - - for _, tc := range testCases { - r := bytes.NewReader(tc.data) - t.Run(tc.name, func(t *testing.T) { - patterns, has, err := iface.ifacesStaticConfig(r) - require.NoError(t, err) - - assert.Equal(t, tc.wantCont, has) - assert.ElementsMatch(t, tc.wantPatterns, patterns) - }) - } -} - -func TestSetStaticIPdhcpcdConf(t *testing.T) { +func TestSetStaticIP_dhcpcdConfIface(t *testing.T) { testCases := []struct { name string dhcpcdConf string diff --git a/internal/aghnet/net_openbsd.go b/internal/aghnet/net_openbsd.go index 627db0ab..68ef90e0 100644 --- a/internal/aghnet/net_openbsd.go +++ b/internal/aghnet/net_openbsd.go @@ -20,7 +20,7 @@ func canBindPrivilegedPorts() (can bool, err error) { func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { filename := fmt.Sprintf("etc/hostname.%s", ifaceName) - return aghos.FileWalker(hostnameIfStaticConfig).Walk(aghos.RootDirFS(), filename) + return aghos.FileWalker(hostnameIfStaticConfig).Walk(rootDirFS, filename) } // hostnameIfStaticConfig checks if the interface is configured by diff --git a/internal/aghnet/net_openbsd_test.go b/internal/aghnet/net_openbsd_test.go index e157d93a..356799b7 100644 --- a/internal/aghnet/net_openbsd_test.go +++ b/internal/aghnet/net_openbsd_test.go @@ -4,49 +4,69 @@ package aghnet import ( - "strings" + "fmt" + "io/fs" "testing" + "testing/fstest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestHostnameIfStaticConfig(t *testing.T) { - const nl = "\n" +func TestIfaceHasStaticIP(t *testing.T) { + const ifaceName = "em0" + + confFile := fmt.Sprintf("etc/hostname.%s", ifaceName) testCases := []struct { - name string - rcconfData string - wantHas bool + name string + rootFsys fs.FS + wantHas assert.BoolAssertionFunc }{{ - name: "simple", - rcconfData: `inet 127.0.0.253` + nl, - wantHas: true, + name: "simple", + rootFsys: fstest.MapFS{ + confFile: &fstest.MapFile{ + Data: []byte(`inet 127.0.0.253` + nl), + }, + }, + wantHas: assert.True, }, { - name: "case_sensitiveness", - rcconfData: `InEt 127.0.0.253` + nl, - wantHas: false, + name: "case_sensitiveness", + rootFsys: fstest.MapFS{ + confFile: &fstest.MapFile{ + Data: []byte(`InEt 127.0.0.253` + nl), + }, + }, + wantHas: assert.False, }, { name: "comments_and_trash", - rcconfData: `# comment 1` + nl + - `` + nl + - `# inet 127.0.0.253` + nl + - `inet` + nl, - wantHas: false, + rootFsys: fstest.MapFS{ + confFile: &fstest.MapFile{ + Data: []byte(`# comment 1` + nl + nl + + `# inet 127.0.0.253` + nl + + `inet` + nl, + ), + }, + }, + wantHas: assert.False, }, { name: "incorrect_config", - rcconfData: `inet6 127.0.0.253` + nl + - `inet 256.256.256.256` + nl, - wantHas: false, + rootFsys: fstest.MapFS{ + confFile: &fstest.MapFile{ + Data: []byte(`inet6 127.0.0.253` + nl + `inet 256.256.256.256` + nl), + }, + }, + wantHas: assert.False, }} for _, tc := range testCases { - r := strings.NewReader(tc.rcconfData) t.Run(tc.name, func(t *testing.T) { - _, has, err := hostnameIfStaticConfig(r) + substRootDirFS(t, tc.rootFsys) + + has, err := IfaceHasStaticIP(ifaceName) require.NoError(t, err) - assert.Equal(t, tc.wantHas, has) + tc.wantHas(t, has) }) } } diff --git a/internal/aghnet/net_test.go b/internal/aghnet/net_test.go index b461cb44..29de869b 100644 --- a/internal/aghnet/net_test.go +++ b/internal/aghnet/net_test.go @@ -1,9 +1,11 @@ package aghnet import ( + "fmt" "io/fs" "net" "os" + "strings" "testing" "github.com/AdguardTeam/AdGuardHome/internal/aghtest" @@ -14,11 +16,102 @@ import ( "github.com/stretchr/testify/require" ) +func TestMain(m *testing.M) { + aghtest.DiscardLogOutput(m) +} + // testdata is the filesystem containing data for testing the package. var testdata fs.FS = os.DirFS("./testdata") -func TestMain(m *testing.M) { - aghtest.DiscardLogOutput(m) +// substRootDirFS replaces the aghos.RootDirFS function used throughout the +// package with fsys for tests ran under t. +func substRootDirFS(t testing.TB, fsys fs.FS) { + t.Helper() + + prev := rootDirFS + t.Cleanup(func() { rootDirFS = prev }) + rootDirFS = fsys +} + +// RunCmdFunc is the signature of aghos.RunCommand function. +type RunCmdFunc func(cmd string, args ...string) (code int, out []byte, err error) + +// substShell replaces the the aghos.RunCommand function used throughout the +// package with rc for tests ran under t. +func substShell(t testing.TB, rc RunCmdFunc) { + t.Helper() + + prev := aghosRunCommand + t.Cleanup(func() { aghosRunCommand = prev }) + aghosRunCommand = rc +} + +// mapShell is a substitution of aghos.RunCommand that maps the command to it's +// execution result. It's only needed to simplify testing. +// +// TODO(e.burkov): Perhaps put all the shell interactions behind an interface. +type mapShell map[string]struct { + err error + out string + code int +} + +// theOnlyCmd returns s that only handles a single command and arguments +// combination from cmd. +func theOnlyCmd(cmd string, code int, out string, err error) (s mapShell) { + return mapShell{cmd: {code: code, out: out, err: err}} +} + +// RunCmd is a RunCmdFunc handled by s. +func (s mapShell) RunCmd(cmd string, args ...string) (code int, out []byte, err error) { + key := strings.Join(append([]string{cmd}, args...), " ") + ret, ok := s[key] + if !ok { + return 0, nil, fmt.Errorf("unexpected shell command %q", key) + } + + return ret.code, []byte(ret.out), ret.err +} + +func TestGatewayIP(t *testing.T) { + testCases := []struct { + name string + shell mapShell + want net.IP + }{{ + name: "success_v4", + shell: theOnlyCmd("ip route show dev ifaceName", 0, `default via 1.2.3.4 onlink`, nil), + want: net.IP{1, 2, 3, 4}.To16(), + }, { + name: "success_v6", + shell: theOnlyCmd("ip route show dev ifaceName", 0, `default via ::ffff onlink`, nil), + want: net.IP{ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xFF, 0xFF, + }, + }, { + name: "bad_output", + shell: theOnlyCmd("ip route show dev ifaceName", 0, `non-default via 1.2.3.4 onlink`, nil), + want: nil, + }, { + name: "err_runcmd", + shell: theOnlyCmd("ip route show dev ifaceName", 0, "", errors.Error("can't run command")), + want: nil, + }, { + name: "bad_code", + shell: theOnlyCmd("ip route show dev ifaceName", 1, "", nil), + want: nil, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + substShell(t, tc.shell.RunCmd) + + assert.Equal(t, tc.want, GatewayIP("ifaceName")) + }) + } } func TestGetInterfaceByIP(t *testing.T) { @@ -133,6 +226,8 @@ func TestCheckPort(t *testing.T) { } func TestCollectAllIfacesAddrs(t *testing.T) { + t.Skip("TODO(e.burkov): Substitute the net.Interfaces.") + addrs, err := CollectAllIfacesAddrs() require.NoError(t, err) diff --git a/internal/aghos/os.go b/internal/aghos/os.go index 8ac189a1..018a3e89 100644 --- a/internal/aghos/os.go +++ b/internal/aghos/os.go @@ -57,20 +57,22 @@ func HaveAdminRights() (bool, error) { const MaxCmdOutputSize = 64 * 1024 // RunCommand runs shell command. -func RunCommand(command string, arguments ...string) (code int, output string, err error) { +func RunCommand(command string, arguments ...string) (code int, output []byte, err error) { cmd := exec.Command(command, arguments...) out, err := cmd.Output() if len(out) > MaxCmdOutputSize { out = out[:MaxCmdOutputSize] } - if errors.As(err, new(*exec.ExitError)) { - return cmd.ProcessState.ExitCode(), string(out), nil - } else if err != nil { - return 1, "", fmt.Errorf("command %q failed: %w: %s", command, err, out) + if err != nil { + if eerr := new(exec.ExitError); errors.As(err, &eerr) { + return eerr.ExitCode(), eerr.Stderr, nil + } + + return 1, nil, fmt.Errorf("command %q failed: %w: %s", command, err, out) } - return cmd.ProcessState.ExitCode(), string(out), nil + return cmd.ProcessState.ExitCode(), out, nil } // PIDByCommand searches for process named command and returns its PID ignoring diff --git a/internal/home/service_openbsd.go b/internal/home/service_openbsd.go index 679a7437..8ad0d212 100644 --- a/internal/home/service_openbsd.go +++ b/internal/home/service_openbsd.go @@ -314,12 +314,13 @@ func (s *openbsdRunComService) runCom(cmd string) (out string, err error) { // TODO(e.burkov): It's possible that os.ErrNotExist is caused by // something different than the service script's non-existence. Keep it // in mind, when replace the aghos.RunCommand. - _, out, err = aghos.RunCommand(scriptPath, cmd) + var outData []byte + _, outData, err = aghos.RunCommand(scriptPath, cmd) if errors.Is(err, os.ErrNotExist) { return "", service.ErrNotInstalled } - return out, err + return string(outData), err } // Status implements service.Service interface for *openbsdRunComService. From a79b61aac31db689a0d704bf356e67a6ea6f881e Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Thu, 31 Mar 2022 11:54:47 +0300 Subject: [PATCH 04/99] Pull request: fix down flag Squashed commit of the following: commit ea446e844a21e7e7e0271d4d133c581014facda1 Merge: bb8cabfa 5e71f5df Author: Ildar Kamalov Date: Thu Mar 31 10:49:20 2022 +0300 Merge branch 'master' into client-down-flag commit bb8cabfae8e2e3eaa09f48ffe7d2fb3b308d31fb Author: Ildar Kamalov Date: Wed Mar 30 19:27:30 2022 +0300 client: fix down flag --- client/src/install/Setup/Settings.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/install/Setup/Settings.js b/client/src/install/Setup/Settings.js index ce128fb8..234d345a 100644 --- a/client/src/install/Setup/Settings.js +++ b/client/src/install/Setup/Settings.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import { Field, reduxForm, formValueSelector } from 'redux-form'; import { Trans, withTranslation } from 'react-i18next'; import flow from 'lodash/flow'; +import i18n from 'i18next'; import Controls from './Controls'; import AddressList from './AddressList'; @@ -31,10 +32,10 @@ const renderInterfaces = (interfaces) => Object.values(interfaces) if (option && ip_addresses?.length > 0) { const ip = getInterfaceIp(option); - const isDown = flags?.includes('down'); + const isUp = flags?.includes('up'); - return ; } From c70f941bf87b92d819e6a7adf5255bc43404b026 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 31 Mar 2022 19:56:50 +0300 Subject: [PATCH 05/99] Pull request: 2846 cover aghnet vol.4 Merge in DNS/adguard-home from 2846-cover-aghnet-vol.4 to master Updates #2846. Squashed commit of the following: commit 576ef857628a403ce1478c10a4aad23985c09613 Author: Eugene Burkov Date: Thu Mar 31 19:38:57 2022 +0300 aghnet: imp code commit 5b4b17ff52867aaab2c9d30a0fc7fc2fe31ff4d5 Author: Eugene Burkov Date: Thu Mar 31 14:58:34 2022 +0300 aghnet: imp coverage --- internal/aghnet/arpdb_test.go | 10 +++ internal/aghnet/hostgen.go | 9 +-- internal/aghnet/hostgen_test.go | 88 +++++++++++++--------- internal/aghnet/net.go | 80 ++++++++------------ internal/aghnet/net_darwin.go | 4 - internal/aghnet/net_freebsd.go | 4 - internal/aghnet/net_freebsd_test.go | 2 +- internal/aghnet/net_linux.go | 70 +++++++++-------- internal/aghnet/net_linux_test.go | 36 --------- internal/aghnet/net_nolinux.go | 10 +++ internal/aghnet/net_openbsd.go | 4 - internal/aghnet/net_test.go | 112 +++++++++++++++++++++++++--- internal/aghnet/net_windows.go | 4 - internal/home/home.go | 37 ++++----- scripts/make/go-lint.sh | 3 +- 15 files changed, 266 insertions(+), 207 deletions(-) create mode 100644 internal/aghnet/net_nolinux.go diff --git a/internal/aghnet/arpdb_test.go b/internal/aghnet/arpdb_test.go index 75778b74..d6971448 100644 --- a/internal/aghnet/arpdb_test.go +++ b/internal/aghnet/arpdb_test.go @@ -181,6 +181,16 @@ func TestCmdARPDB_arpa(t *testing.T) { err := a.Refresh() testutil.AssertErrorMsg(t, "cmd arpdb: running command: unexpected exit code 1", err) }) + + t.Run("empty", func(t *testing.T) { + sh := theOnlyCmd("cmd", 0, "", nil) + substShell(t, sh.RunCmd) + + err := a.Refresh() + require.NoError(t, err) + + assert.Empty(t, a.Neighbors()) + }) } func TestEmptyARPDB(t *testing.T) { diff --git a/internal/aghnet/hostgen.go b/internal/aghnet/hostgen.go index d9278515..683c8d9f 100644 --- a/internal/aghnet/hostgen.go +++ b/internal/aghnet/hostgen.go @@ -11,7 +11,7 @@ const ( ipv6HostnameMaxLen = len("ff80-f076-0000-0000-0000-0000-0000-0010") ) -// generateIPv4Hostname generates the hostname for specific IP version. +// generateIPv4Hostname generates the hostname by IP address version 4. func generateIPv4Hostname(ipv4 net.IP) (hostname string) { hnData := make([]byte, 0, ipv4HostnameMaxLen) for i, part := range ipv4 { @@ -24,7 +24,7 @@ func generateIPv4Hostname(ipv4 net.IP) (hostname string) { return string(hnData) } -// generateIPv6Hostname generates the hostname for specific IP version. +// generateIPv6Hostname generates the hostname by IP address version 6. func generateIPv6Hostname(ipv6 net.IP) (hostname string) { hnData := make([]byte, 0, ipv6HostnameMaxLen) for i, partsNum := 0, net.IPv6len/2; i < partsNum; i++ { @@ -51,12 +51,11 @@ func generateIPv6Hostname(ipv6 net.IP) (hostname string) { // // ff80-f076-0000-0000-0000-0000-0000-0010 // +// ip must be either an IPv4 or an IPv6. func GenerateHostname(ip net.IP) (hostname string) { if ipv4 := ip.To4(); ipv4 != nil { return generateIPv4Hostname(ipv4) - } else if ipv6 := ip.To16(); ipv6 != nil { - return generateIPv6Hostname(ipv6) } - return "" + return generateIPv6Hostname(ip) } diff --git a/internal/aghnet/hostgen_test.go b/internal/aghnet/hostgen_test.go index 37121628..d37e556b 100644 --- a/internal/aghnet/hostgen_test.go +++ b/internal/aghnet/hostgen_test.go @@ -8,41 +8,57 @@ import ( ) func TestGenerateHostName(t *testing.T) { - testCases := []struct { - name string - want string - ip net.IP - }{{ - name: "good_ipv4", - want: "127-0-0-1", - ip: net.IP{127, 0, 0, 1}, - }, { - name: "bad_ipv4", - want: "", - ip: net.IP{127, 0, 0, 1, 0}, - }, { - name: "good_ipv6", - want: "fe00-0000-0000-0000-0000-0000-0000-0001", - ip: net.ParseIP("fe00::1"), - }, { - name: "bad_ipv6", - want: "", - ip: net.IP{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, - }, - }, { - name: "nil", - want: "", - ip: nil, - }} + t.Run("valid", func(t *testing.T) { + testCases := []struct { + name string + want string + ip net.IP + }{{ + name: "good_ipv4", + want: "127-0-0-1", + ip: net.IP{127, 0, 0, 1}, + }, { + name: "good_ipv6", + want: "fe00-0000-0000-0000-0000-0000-0000-0001", + ip: net.ParseIP("fe00::1"), + }, { + name: "4to6", + want: "1-2-3-4", + ip: net.ParseIP("::ffff:1.2.3.4"), + }} - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - hostname := GenerateHostname(tc.ip) - assert.Equal(t, tc.want, hostname) - }) - } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + hostname := GenerateHostname(tc.ip) + assert.Equal(t, tc.want, hostname) + }) + } + }) + + t.Run("invalid", func(t *testing.T) { + testCases := []struct { + name string + ip net.IP + }{{ + name: "bad_ipv4", + ip: net.IP{127, 0, 0, 1, 0}, + }, { + name: "bad_ipv6", + ip: net.IP{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, + }, + }, { + name: "nil", + ip: nil, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Panics(t, func() { GenerateHostname(tc.ip) }) + }) + } + }) } diff --git a/internal/aghnet/net.go b/internal/aghnet/net.go index d17b9165..cd2edc72 100644 --- a/internal/aghnet/net.go +++ b/internal/aghnet/net.go @@ -15,13 +15,17 @@ import ( "github.com/AdguardTeam/golibs/netutil" ) -// aghosRunCommand is the function to run shell commands. It's an unexported -// variable instead of a direct call to make it substitutable in tests. -var aghosRunCommand = aghos.RunCommand +// Variables and functions to substitute in tests. +var ( + // aghosRunCommand is the function to run shell commands. + aghosRunCommand = aghos.RunCommand -// rootDirFS is the filesystem pointing to the root directory. It's an -// unexported variable instead to make it substitutable in tests. -var rootDirFS = aghos.RootDirFS() + // netInterfaces is the function to get the available network interfaces. + netInterfaceAddrs = net.InterfaceAddrs + + // rootDirFS is the filesystem pointing to the root directory. + rootDirFS = aghos.RootDirFS() +) // ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about // the IP being static is available. @@ -65,23 +69,6 @@ func GatewayIP(ifaceName string) (ip net.IP) { return net.ParseIP(string(fields[2])) } -// CanBindPort checks if we can bind to the given port. -func CanBindPort(port int) (can bool, err error) { - var addr *net.TCPAddr - addr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port)) - if err != nil { - return false, err - } - - var listener *net.TCPListener - listener, err = net.ListenTCP("tcp", addr) - if err != nil { - return false, err - } - _ = listener.Close() - return true, nil -} - // CanBindPrivilegedPorts checks if current process can bind to privileged // ports. func CanBindPrivilegedPorts() (can bool, err error) { @@ -100,8 +87,8 @@ type NetInterface struct { MTU int `json:"mtu"` } -// MarshalJSON implements the json.Marshaler interface for NetInterface. -func (iface NetInterface) MarshalJSON() ([]byte, error) { +// MarshalText implements the json.Marshaler interface for NetInterface. +func (iface NetInterface) MarshalText() ([]byte, error) { type netInterface NetInterface return json.Marshal(&struct { HardwareAddr string `json:"hardware_address"` @@ -114,9 +101,12 @@ func (iface NetInterface) MarshalJSON() ([]byte, error) { }) } -// GetValidNetInterfacesForWeb returns interfaces that are eligible for DNS and WEB only -// we do not return link-local addresses here -func GetValidNetInterfacesForWeb() (netInterfaces []*NetInterface, err error) { +// GetValidNetInterfacesForWeb returns interfaces that are eligible for DNS and +// WEB only we do not return link-local addresses here. +// +// TODO(e.burkov): Can't properly test the function since it's nontrivial to +// substitute net.Interface.Addrs and the net.InterfaceAddrs can't be used. +func GetValidNetInterfacesForWeb() (netIfaces []*NetInterface, err error) { ifaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("couldn't get interfaces: %w", err) @@ -157,14 +147,16 @@ func GetValidNetInterfacesForWeb() (netInterfaces []*NetInterface, err error) { // Discard interfaces with no addresses. if len(netIface.Addresses) != 0 { - netInterfaces = append(netInterfaces, netIface) + netIfaces = append(netIfaces, netIface) } } - return netInterfaces, nil + return netIfaces, nil } // GetInterfaceByIP returns the name of interface containing provided ip. +// +// TODO(e.burkov): See TODO on GetValidInterfacesForWeb. func GetInterfaceByIP(ip net.IP) string { ifaces, err := GetValidNetInterfacesForWeb() if err != nil { @@ -184,6 +176,8 @@ func GetInterfaceByIP(ip net.IP) string { // GetSubnet returns pointer to net.IPNet for the specified interface or nil if // the search fails. +// +// TODO(e.burkov): See TODO on GetValidInterfacesForWeb. func GetSubnet(ifaceName string) *net.IPNet { netIfaces, err := GetValidNetInterfacesForWeb() if err != nil { @@ -234,29 +228,21 @@ func IsAddrInUse(err error) (ok bool) { // CollectAllIfacesAddrs returns the slice of all network interfaces IP // addresses without port number. func CollectAllIfacesAddrs() (addrs []string, err error) { - var ifaces []net.Interface - ifaces, err = net.Interfaces() + var ifaceAddrs []net.Addr + ifaceAddrs, err = netInterfaceAddrs() if err != nil { - return nil, fmt.Errorf("getting network interfaces: %w", err) + return nil, fmt.Errorf("getting interfaces addresses: %w", err) } - for _, iface := range ifaces { - var ifaceAddrs []net.Addr - ifaceAddrs, err = iface.Addrs() + for _, addr := range ifaceAddrs { + cidr := addr.String() + var ip net.IP + ip, _, err = net.ParseCIDR(cidr) if err != nil { - return nil, fmt.Errorf("getting addresses for %q: %w", iface.Name, err) + return nil, fmt.Errorf("parsing cidr: %w", err) } - for _, addr := range ifaceAddrs { - cidr := addr.String() - var ip net.IP - ip, _, err = net.ParseCIDR(cidr) - if err != nil { - return nil, fmt.Errorf("parsing cidr: %w", err) - } - - addrs = append(addrs, ip.String()) - } + addrs = append(addrs, ip.String()) } return addrs, nil diff --git a/internal/aghnet/net_darwin.go b/internal/aghnet/net_darwin.go index 63e57dc4..296a18b0 100644 --- a/internal/aghnet/net_darwin.go +++ b/internal/aghnet/net_darwin.go @@ -24,10 +24,6 @@ type hardwarePortInfo struct { static bool } -func canBindPrivilegedPorts() (can bool, err error) { - return aghos.HaveAdminRights() -} - func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { portInfo, err := getCurrentHardwarePortInfo(ifaceName) if err != nil { diff --git a/internal/aghnet/net_freebsd.go b/internal/aghnet/net_freebsd.go index 34d93303..85d40184 100644 --- a/internal/aghnet/net_freebsd.go +++ b/internal/aghnet/net_freebsd.go @@ -13,10 +13,6 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghos" ) -func canBindPrivilegedPorts() (can bool, err error) { - return aghos.HaveAdminRights() -} - func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { const rcConfFilename = "etc/rc.conf" diff --git a/internal/aghnet/net_freebsd_test.go b/internal/aghnet/net_freebsd_test.go index e00dafa7..2c758360 100644 --- a/internal/aghnet/net_freebsd_test.go +++ b/internal/aghnet/net_freebsd_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestRcConfStaticConfig(t *testing.T) { +func TestIfaceHasStaticIP(t *testing.T) { const ( ifaceName = `em0` rcConf = "etc/rc.conf" diff --git a/internal/aghnet/net_linux.go b/internal/aghnet/net_linux.go index c2526524..148abe1f 100644 --- a/internal/aghnet/net_linux.go +++ b/internal/aghnet/net_linux.go @@ -13,10 +13,28 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghos" "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/stringutil" "github.com/google/renameio/maybe" "golang.org/x/sys/unix" ) +// dhcpсdConf is the name of /etc/dhcpcd.conf file in the root filesystem. +const dhcpcdConf = "etc/dhcpcd.conf" + +func canBindPrivilegedPorts() (can bool, err error) { + cnbs, err := unix.PrctlRetInt( + unix.PR_CAP_AMBIENT, + unix.PR_CAP_AMBIENT_IS_SET, + unix.CAP_NET_BIND_SERVICE, + 0, + 0, + ) + // Don't check the error because it's always nil on Linux. + adm, _ := aghos.HaveAdminRights() + + return cnbs == 1 || adm, err +} + // dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to // have a static IP. func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) { @@ -89,7 +107,7 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { filename string }{{ FileWalker: iface.dhcpcdStaticConfig, - filename: "etc/dhcpcd.conf", + filename: dhcpcdConf, }, { FileWalker: iface.ifacesStaticConfig, filename: "etc/network/interfaces", @@ -105,14 +123,6 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) { return false, ErrNoStaticIPInfo } -func canBindPrivilegedPorts() (can bool, err error) { - cnbs, err := unix.PrctlRetInt(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, unix.CAP_NET_BIND_SERVICE, 0, 0) - // Don't check the error because it's always nil on Linux. - adm, _ := aghos.HaveAdminRights() - - return cnbs == 1 || adm, err -} - // findIfaceLine scans s until it finds the line that declares an interface with // the given name. If findIfaceLine can't find the line, it returns false. func findIfaceLine(s *bufio.Scanner, name string) (ok bool) { @@ -128,25 +138,23 @@ func findIfaceLine(s *bufio.Scanner, name string) (ok bool) { } // ifaceSetStaticIP configures the system to retain its current IP on the -// interface through dhcpdc.conf. +// interface through dhcpcd.conf. func ifaceSetStaticIP(ifaceName string) (err error) { ipNet := GetSubnet(ifaceName) if ipNet.IP == nil { return errors.Error("can't get IP address") } - gatewayIP := GatewayIP(ifaceName) - add := dhcpcdConfIface(ifaceName, ipNet, gatewayIP, ipNet.IP) - - const filename = "/etc/dhcpcd.conf" - - body, err := os.ReadFile(filename) + body, err := os.ReadFile(dhcpcdConf) if err != nil && !errors.Is(err, os.ErrNotExist) { return err } + gatewayIP := GatewayIP(ifaceName) + add := dhcpcdConfIface(ifaceName, ipNet, gatewayIP) + body = append(body, []byte(add)...) - err = maybe.WriteFile(filename, body, 0o644) + err = maybe.WriteFile(dhcpcdConf, body, 0o644) if err != nil { return fmt.Errorf("writing conf: %w", err) } @@ -156,22 +164,24 @@ func ifaceSetStaticIP(ifaceName string) (err error) { // dhcpcdConfIface returns configuration lines for the dhcpdc.conf files that // configure the interface to have a static IP. -func dhcpcdConfIface(ifaceName string, ipNet *net.IPNet, gatewayIP, dnsIP net.IP) (conf string) { - var body []byte - - add := fmt.Sprintf( - "\n# %[1]s added by AdGuard Home.\ninterface %[1]s\nstatic ip_address=%s\n", +func dhcpcdConfIface(ifaceName string, ipNet *net.IPNet, gwIP net.IP) (conf string) { + b := &strings.Builder{} + stringutil.WriteToBuilder( + b, + "\n# ", ifaceName, - ipNet) - body = append(body, []byte(add)...) + " added by AdGuard Home.\ninterface ", + ifaceName, + "\nstatic ip_address=", + ipNet.String(), + "\n", + ) - if gatewayIP != nil { - add = fmt.Sprintf("static routers=%s\n", gatewayIP) - body = append(body, []byte(add)...) + if gwIP != nil { + stringutil.WriteToBuilder(b, "static routers=", gwIP.String(), "\n") } - add = fmt.Sprintf("static domain_name_servers=%s\n\n", dnsIP) - body = append(body, []byte(add)...) + stringutil.WriteToBuilder(b, "static domain_name_servers=", ipNet.IP.String(), "\n\n") - return string(body) + return b.String() } diff --git a/internal/aghnet/net_linux_test.go b/internal/aghnet/net_linux_test.go index e46da4df..838802ff 100644 --- a/internal/aghnet/net_linux_test.go +++ b/internal/aghnet/net_linux_test.go @@ -5,7 +5,6 @@ package aghnet import ( "io/fs" - "net" "testing" "testing/fstest" @@ -126,38 +125,3 @@ func TestHasStaticIP(t *testing.T) { }) } } - -func TestSetStaticIP_dhcpcdConfIface(t *testing.T) { - testCases := []struct { - name string - dhcpcdConf string - routers net.IP - }{{ - name: "with_gateway", - dhcpcdConf: nl + `# wlan0 added by AdGuard Home.` + nl + - `interface wlan0` + nl + - `static ip_address=192.168.0.2/24` + nl + - `static routers=192.168.0.1` + nl + - `static domain_name_servers=192.168.0.2` + nl + nl, - routers: net.IP{192, 168, 0, 1}, - }, { - name: "without_gateway", - dhcpcdConf: nl + `# wlan0 added by AdGuard Home.` + nl + - `interface wlan0` + nl + - `static ip_address=192.168.0.2/24` + nl + - `static domain_name_servers=192.168.0.2` + nl + nl, - routers: nil, - }} - - ipNet := &net.IPNet{ - IP: net.IP{192, 168, 0, 2}, - Mask: net.IPMask{255, 255, 255, 0}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - s := dhcpcdConfIface("wlan0", ipNet, tc.routers, net.IP{192, 168, 0, 2}) - assert.Equal(t, tc.dhcpcdConf, s) - }) - } -} diff --git a/internal/aghnet/net_nolinux.go b/internal/aghnet/net_nolinux.go new file mode 100644 index 00000000..f429c6fa --- /dev/null +++ b/internal/aghnet/net_nolinux.go @@ -0,0 +1,10 @@ +//go:build !linux +// +build !linux + +package aghnet + +import "github.com/AdguardTeam/AdGuardHome/internal/aghos" + +func canBindPrivilegedPorts() (can bool, err error) { + return aghos.HaveAdminRights() +} diff --git a/internal/aghnet/net_openbsd.go b/internal/aghnet/net_openbsd.go index 68ef90e0..cf911105 100644 --- a/internal/aghnet/net_openbsd.go +++ b/internal/aghnet/net_openbsd.go @@ -13,10 +13,6 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/aghos" ) -func canBindPrivilegedPorts() (can bool, err error) { - return aghos.HaveAdminRights() -} - func ifaceHasStaticIP(ifaceName string) (ok bool, err error) { filename := fmt.Sprintf("etc/hostname.%s", ifaceName) diff --git a/internal/aghnet/net_test.go b/internal/aghnet/net_test.go index 29de869b..77eab3be 100644 --- a/internal/aghnet/net_test.go +++ b/internal/aghnet/net_test.go @@ -56,7 +56,7 @@ type mapShell map[string]struct { code int } -// theOnlyCmd returns s that only handles a single command and arguments +// theOnlyCmd returns mapShell that only handles a single command and arguments // combination from cmd. func theOnlyCmd(cmd string, code int, out string, err error) (s mapShell) { return mapShell{cmd: {code: code, out: out, err: err}} @@ -73,18 +73,34 @@ func (s mapShell) RunCmd(cmd string, args ...string) (code int, out []byte, err return ret.code, []byte(ret.out), ret.err } +// ifaceAddrsFunc is the signature of net.InterfaceAddrs function. +type ifaceAddrsFunc func() (ifaces []net.Addr, err error) + +// substNetInterfaceAddrs replaces the the net.InterfaceAddrs function used +// throughout the package with f for tests ran under t. +func substNetInterfaceAddrs(t *testing.T, f ifaceAddrsFunc) { + t.Helper() + + prev := netInterfaceAddrs + t.Cleanup(func() { netInterfaceAddrs = prev }) + netInterfaceAddrs = f +} + func TestGatewayIP(t *testing.T) { + const ifaceName = "ifaceName" + const cmd = "ip route show dev " + ifaceName + testCases := []struct { name string shell mapShell want net.IP }{{ name: "success_v4", - shell: theOnlyCmd("ip route show dev ifaceName", 0, `default via 1.2.3.4 onlink`, nil), + shell: theOnlyCmd(cmd, 0, `default via 1.2.3.4 onlink`, nil), want: net.IP{1, 2, 3, 4}.To16(), }, { name: "success_v6", - shell: theOnlyCmd("ip route show dev ifaceName", 0, `default via ::ffff onlink`, nil), + shell: theOnlyCmd(cmd, 0, `default via ::ffff onlink`, nil), want: net.IP{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -93,15 +109,15 @@ func TestGatewayIP(t *testing.T) { }, }, { name: "bad_output", - shell: theOnlyCmd("ip route show dev ifaceName", 0, `non-default via 1.2.3.4 onlink`, nil), + shell: theOnlyCmd(cmd, 0, `non-default via 1.2.3.4 onlink`, nil), want: nil, }, { name: "err_runcmd", - shell: theOnlyCmd("ip route show dev ifaceName", 0, "", errors.Error("can't run command")), + shell: theOnlyCmd(cmd, 0, "", errors.Error("can't run command")), want: nil, }, { name: "bad_code", - shell: theOnlyCmd("ip route show dev ifaceName", 1, "", nil), + shell: theOnlyCmd(cmd, 1, "", nil), want: nil, }} @@ -109,7 +125,7 @@ func TestGatewayIP(t *testing.T) { t.Run(tc.name, func(t *testing.T) { substShell(t, tc.shell.RunCmd) - assert.Equal(t, tc.want, GatewayIP("ifaceName")) + assert.Equal(t, tc.want, GatewayIP(ifaceName)) }) } } @@ -226,12 +242,56 @@ func TestCheckPort(t *testing.T) { } func TestCollectAllIfacesAddrs(t *testing.T) { - t.Skip("TODO(e.burkov): Substitute the net.Interfaces.") + testCases := []struct { + name string + wantErrMsg string + addrs []net.Addr + wantAddrs []string + }{{ + name: "success", + wantErrMsg: ``, + addrs: []net.Addr{&net.IPNet{ + IP: net.IP{1, 2, 3, 4}, + Mask: net.CIDRMask(24, netutil.IPv4BitLen), + }, &net.IPNet{ + IP: net.IP{4, 3, 2, 1}, + Mask: net.CIDRMask(16, netutil.IPv4BitLen), + }}, + wantAddrs: []string{"1.2.3.4", "4.3.2.1"}, + }, { + name: "not_cidr", + wantErrMsg: `parsing cidr: invalid CIDR address: 1.2.3.4`, + addrs: []net.Addr{&net.IPAddr{ + IP: net.IP{1, 2, 3, 4}, + }}, + wantAddrs: nil, + }, { + name: "empty", + wantErrMsg: ``, + addrs: []net.Addr{}, + wantAddrs: nil, + }} - addrs, err := CollectAllIfacesAddrs() - require.NoError(t, err) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + substNetInterfaceAddrs(t, func() ([]net.Addr, error) { return tc.addrs, nil }) - assert.NotEmpty(t, addrs) + addrs, err := CollectAllIfacesAddrs() + testutil.AssertErrorMsg(t, tc.wantErrMsg, err) + + assert.Equal(t, tc.wantAddrs, addrs) + }) + } + + t.Run("internal_error", func(t *testing.T) { + const errAddrs errors.Error = "can't get addresses" + const wantErrMsg string = `getting interfaces addresses: ` + string(errAddrs) + + substNetInterfaceAddrs(t, func() ([]net.Addr, error) { return nil, errAddrs }) + + _, err := CollectAllIfacesAddrs() + testutil.AssertErrorMsg(t, wantErrMsg, err) + }) } func TestIsAddrInUse(t *testing.T) { @@ -250,3 +310,33 @@ func TestIsAddrInUse(t *testing.T) { assert.False(t, IsAddrInUse(anotherErr)) }) } + +func TestNetInterface_MarshalText(t *testing.T) { + const want = `{` + + `"hardware_address":"aa:bb:cc:dd:ee:ff",` + + `"flags":"up|multicast",` + + `"ip_addresses":["1.2.3.4","aaaa::1"],` + + `"name":"iface0",` + + `"mtu":1500` + + `}` + + ip4, ip6 := net.IP{1, 2, 3, 4}, net.IP{0xAA, 0xAA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + mask4, mask6 := net.CIDRMask(24, netutil.IPv4BitLen), net.CIDRMask(8, netutil.IPv6BitLen) + + iface := &NetInterface{ + Addresses: []net.IP{ip4, ip6}, + Subnets: []*net.IPNet{{ + IP: ip4.Mask(mask4), + Mask: mask4, + }, { + IP: ip6.Mask(mask6), + Mask: mask6, + }}, + Name: "iface0", + HardwareAddr: net.HardwareAddr{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + Flags: net.FlagUp | net.FlagMulticast, + MTU: 1500, + } + + testutil.AssertMarshalText(t, want, iface) +} diff --git a/internal/aghnet/net_windows.go b/internal/aghnet/net_windows.go index 128f5716..0cea8fe7 100644 --- a/internal/aghnet/net_windows.go +++ b/internal/aghnet/net_windows.go @@ -13,10 +13,6 @@ import ( "golang.org/x/sys/windows" ) -func canBindPrivilegedPorts() (can bool, err error) { - return aghos.HaveAdminRights() -} - func ifaceHasStaticIP(string) (ok bool, err error) { return false, aghos.Unsupported("checking static ip") } diff --git a/internal/home/home.go b/internal/home/home.go index 5fae42c8..df1dc95b 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -517,27 +517,15 @@ func StartMods() error { func checkPermissions() { log.Info("Checking if AdGuard Home has necessary permissions") - if runtime.GOOS == "windows" { - // On Windows we need to have admin rights to run properly - - admin, _ := aghos.HaveAdminRights() - if admin { - return - } - + if ok, err := aghnet.CanBindPrivilegedPorts(); !ok || err != nil { log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.") } // We should check if AdGuard Home is able to bind to port 53 - ok, err := aghnet.CanBindPort(53) - - if ok { - log.Info("AdGuard Home can bind to port 53") - return - } - - if errors.Is(err, os.ErrPermission) { - msg := `Permission check failed. + err := aghnet.CheckPort("tcp", net.IP{127, 0, 0, 1}, defaultPortDNS) + if err != nil { + if errors.Is(err, os.ErrPermission) { + log.Fatal(`Permission check failed. AdGuard Home is not allowed to bind to privileged ports (for instance, port 53). Please note, that this is crucial for a server to be able to use privileged ports. @@ -545,16 +533,17 @@ Please note, that this is crucial for a server to be able to use privileged port You have two options: 1. Run AdGuard Home with root privileges 2. On Linux you can grant the CAP_NET_BIND_SERVICE capability: -https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#running-without-superuser` +https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#running-without-superuser`) + } - log.Fatal(msg) + log.Info( + "AdGuard failed to bind to port 53: %s\n\n"+ + "Please note, that this is crucial for a DNS server to be able to use that port.", + err, + ) } - msg := fmt.Sprintf(`AdGuard failed to bind to port 53 due to %v - -Please note, that this is crucial for a DNS server to be able to use that port.`, err) - - log.Info(msg) + log.Info("AdGuard Home can bind to port 53") } // Write PID to a file diff --git a/scripts/make/go-lint.sh b/scripts/make/go-lint.sh index 8e646f0c..32d99480 100644 --- a/scripts/make/go-lint.sh +++ b/scripts/make/go-lint.sh @@ -134,9 +134,10 @@ underscores() { -e '_bsd.go'\ -e '_darwin.go'\ -e '_freebsd.go'\ - -e '_openbsd.go'\ -e '_linux.go'\ -e '_little.go'\ + -e '_nolinux.go'\ + -e '_openbsd.go'\ -e '_others.go'\ -e '_test.go'\ -e '_unix.go'\ From e9e0b7c4f907dd37e35511639caca0a88779bd0f Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Wed, 6 Apr 2022 19:27:24 +0300 Subject: [PATCH 06/99] Pull request: 700 validate only enabled encryption form Merge in DNS/adguard-home from 700-validate to master Updates #700. Squashed commit of the following: commit 9cd9ff2d23352e00c7782cf68195809111c832e5 Author: Ildar Kamalov Date: Wed Apr 6 18:50:11 2022 +0300 client: validate only enabled encryption form --- client/src/components/Settings/Encryption/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/components/Settings/Encryption/index.js b/client/src/components/Settings/Encryption/index.js index 13f5c47c..bcd2d323 100644 --- a/client/src/components/Settings/Encryption/index.js +++ b/client/src/components/Settings/Encryption/index.js @@ -25,7 +25,9 @@ class Encryption extends Component { handleFormChange = debounce((values) => { const submitValues = this.getSubmitValues(values); - this.props.validateTlsConfig(submitValues); + if (submitValues.enabled) { + this.props.validateTlsConfig(submitValues); + } }, DEBOUNCE_TIMEOUT); getInitialValues = (data) => { From 8bb95469d92bac60811f3f76c59511e52d0ffadc Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 6 Apr 2022 19:36:13 +0300 Subject: [PATCH 07/99] Pull request: 4465 fix ifaces resp Merge in DNS/adguard-home from 4465-bad-ifaces-resp to master Closes #4465. Squashed commit of the following: commit cc44252b2f12ba4b15df315253417aba2a3f98a6 Author: Eugene Burkov Date: Wed Apr 6 19:21:40 2022 +0300 aghnet: fix get_addresses --- internal/aghnet/net.go | 4 ++-- internal/aghnet/net_test.go | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/internal/aghnet/net.go b/internal/aghnet/net.go index cd2edc72..268380bd 100644 --- a/internal/aghnet/net.go +++ b/internal/aghnet/net.go @@ -87,8 +87,8 @@ type NetInterface struct { MTU int `json:"mtu"` } -// MarshalText implements the json.Marshaler interface for NetInterface. -func (iface NetInterface) MarshalText() ([]byte, error) { +// MarshalJSON implements the json.Marshaler interface for NetInterface. +func (iface NetInterface) MarshalJSON() ([]byte, error) { type netInterface NetInterface return json.Marshal(&struct { HardwareAddr string `json:"hardware_address"` diff --git a/internal/aghnet/net_test.go b/internal/aghnet/net_test.go index 77eab3be..40d395ba 100644 --- a/internal/aghnet/net_test.go +++ b/internal/aghnet/net_test.go @@ -1,6 +1,8 @@ package aghnet import ( + "bytes" + "encoding/json" "fmt" "io/fs" "net" @@ -311,14 +313,14 @@ func TestIsAddrInUse(t *testing.T) { }) } -func TestNetInterface_MarshalText(t *testing.T) { +func TestNetInterface_MarshalJSON(t *testing.T) { const want = `{` + `"hardware_address":"aa:bb:cc:dd:ee:ff",` + `"flags":"up|multicast",` + `"ip_addresses":["1.2.3.4","aaaa::1"],` + `"name":"iface0",` + `"mtu":1500` + - `}` + `}` + "\n" ip4, ip6 := net.IP{1, 2, 3, 4}, net.IP{0xAA, 0xAA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} mask4, mask6 := net.CIDRMask(24, netutil.IPv4BitLen), net.CIDRMask(8, netutil.IPv6BitLen) @@ -338,5 +340,9 @@ func TestNetInterface_MarshalText(t *testing.T) { MTU: 1500, } - testutil.AssertMarshalText(t, want, iface) + b := &bytes.Buffer{} + err := json.NewEncoder(b).Encode(iface) + require.NoError(t, err) + + assert.Equal(t, want, b.String()) } From 0e608fda1367c33e8da1b8fc28029f45b3d69fab Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 6 Apr 2022 19:56:39 +0300 Subject: [PATCH 08/99] Pull request: 4437 depr memory opt Merge in DNS/adguard-home from 4437-rm-mem-opt to master Updates #4437. Updates #2044. Squashed commit of the following: commit d1e5520213f6b68570d18a8d831d4923112901ba Merge: 73a6b494 8bb95469 Author: Eugene Burkov Date: Wed Apr 6 19:37:09 2022 +0300 Merge branch 'master' into 4437-rm-mem-opt commit 73a6b4948cb32f1cb79a54b244018b29382fad76 Author: Eugene Burkov Date: Wed Apr 6 18:33:23 2022 +0300 all: imp log of changes commit a62efcdcd44de300726c906c7f6198c0a02d4ccf Author: Eugene Burkov Date: Wed Apr 6 18:27:42 2022 +0300 home: depr memory opt --- CHANGELOG.md | 3 +++ internal/home/home.go | 3 --- internal/home/memory.go | 40 ----------------------------------- internal/home/options.go | 13 ++++++------ internal/home/options_test.go | 32 +++++++++++----------------- 5 files changed, 22 insertions(+), 69 deletions(-) delete mode 100644 internal/home/memory.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d1e9260..9bc865a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,8 @@ In this release, the schema version has changed from 12 to 13. ### Deprecated +- Obsolete `--no-mem-optimization` option ([#4437]). v0.109.0 will remove the + flag completely. - Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. ### Fixed @@ -111,6 +113,7 @@ In this release, the schema version has changed from 12 to 13. [#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221 [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 +[#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437 [repr]: https://reproducible-builds.org/docs/source-date-epoch/ [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 diff --git a/internal/home/home.go b/internal/home/home.go index df1dc95b..420e67d8 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -389,9 +389,6 @@ func run(args options, clientBuildFS fs.FS) { // configure log level and output configureLogger(args) - // Go memory hacks - memoryUsage(args) - // Print the first message after logger is configured. log.Println(version.Full()) log.Debug("current working directory is %s", Context.workDir) diff --git a/internal/home/memory.go b/internal/home/memory.go deleted file mode 100644 index bcb6e70f..00000000 --- a/internal/home/memory.go +++ /dev/null @@ -1,40 +0,0 @@ -package home - -import ( - "os" - "runtime/debug" - "time" - - "github.com/AdguardTeam/golibs/log" -) - -// memoryUsage implements a couple of not really beautiful hacks which purpose is to -// make OS reclaim the memory freed by AdGuard Home as soon as possible. -// See this for the details on the performance hits & gains: -// https://github.com/AdguardTeam/AdGuardHome/internal/issues/2044#issuecomment-687042211 -func memoryUsage(args options) { - if args.disableMemoryOptimization { - log.Info("Memory optimization is disabled") - return - } - - // Makes Go allocate heap at a slower pace - // By default we keep it at 50% - debug.SetGCPercent(50) - - // madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED - // instead of MADV_FREE on Linux when returning memory to the - // kernel. This is less efficient, but causes RSS numbers to drop - // more quickly. - _ = os.Setenv("GODEBUG", "madvdontneed=1") - - // periodically call "debug.FreeOSMemory" so - // that the OS could reclaim the free memory - go func() { - ticker := time.NewTicker(5 * time.Minute) - for range ticker.C { - log.Debug("free os memory") - debug.FreeOSMemory() - } - }() -} diff --git a/internal/home/options.go b/internal/home/options.go index 6d9a1f99..731c8620 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/AdguardTeam/AdGuardHome/internal/version" + "github.com/AdguardTeam/golibs/log" ) // options passed from command-line arguments @@ -27,10 +28,6 @@ type options struct { // runningAsService flag is set to true when options are passed from the service runner runningAsService bool - // disableMemoryOptimization - disables memory optimization hacks - // see memoryUsage() function for the details - disableMemoryOptimization bool - glinetMode bool // Activate GL-Inet compatibility mode // noEtcHosts flag should be provided when /etc/hosts file shouldn't be @@ -180,8 +177,12 @@ var noCheckUpdateArg = arg{ var disableMemoryOptimizationArg = arg{ "Disable memory optimization.", "no-mem-optimization", "", - nil, func(o options) (options, error) { o.disableMemoryOptimization = true; return o, nil }, nil, - func(o options) []string { return boolSliceOrNil(o.disableMemoryOptimization) }, + nil, nil, func(_ options, _ string) (f effect, err error) { + log.Info("warning: using --no-mem-optimization flag has no effect and is deprecated") + + return nil, nil + }, + func(o options) []string { return nil }, } var verboseArg = arg{ diff --git a/internal/home/options_test.go b/internal/home/options_test.go index b189f045..21972b0a 100644 --- a/internal/home/options_test.go +++ b/internal/home/options_test.go @@ -101,9 +101,13 @@ func TestParseDisableUpdate(t *testing.T) { assert.True(t, testParseOK(t, "--no-check-update").disableUpdate, "--no-check-update is disable update") } +// TODO(e.burkov): Remove after v0.108.0. func TestParseDisableMemoryOptimization(t *testing.T) { - assert.False(t, testParseOK(t).disableMemoryOptimization, "empty is not disable update") - assert.True(t, testParseOK(t, "--no-mem-optimization").disableMemoryOptimization, "--no-mem-optimization is disable update") + o, eff, err := parse("", []string{"--no-mem-optimization"}) + require.NoError(t, err) + + assert.Nil(t, eff) + assert.Zero(t, o) } func TestParseService(t *testing.T) { @@ -127,8 +131,6 @@ func TestParseUnknown(t *testing.T) { } func TestSerialize(t *testing.T) { - const reportFmt = "expected %s but got %s" - testCases := []struct { name string opts options @@ -173,19 +175,14 @@ func TestSerialize(t *testing.T) { name: "glinet_mode", opts: options{glinetMode: true}, ss: []string{"--glinet"}, - }, { - name: "disable_mem_opt", - opts: options{disableMemoryOptimization: true}, - ss: []string{"--no-mem-optimization"}, }, { name: "multiple", opts: options{ - serviceControlAction: "run", - configFilename: "config", - workDir: "work", - pidFile: "pid", - disableUpdate: true, - disableMemoryOptimization: true, + serviceControlAction: "run", + configFilename: "config", + workDir: "work", + pidFile: "pid", + disableUpdate: true, }, ss: []string{ "-c", "config", @@ -193,18 +190,13 @@ func TestSerialize(t *testing.T) { "-s", "run", "--pidfile", "pid", "--no-check-update", - "--no-mem-optimization", }, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { result := serialize(tc.opts) - require.Lenf(t, result, len(tc.ss), reportFmt, tc.ss, result) - - for i, r := range result { - assert.Equalf(t, tc.ss[i], r, reportFmt, tc.ss, result) - } + assert.ElementsMatch(t, tc.ss, result) }) } } From 4c5b38a4474b573086b1afd97c4e24522829ebe6 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 7 Apr 2022 14:07:27 +0300 Subject: [PATCH 09/99] Pull request: 4437 imp help output Merge in DNS/adguard-home from imp-help to master Updates #4437. Squashed commit of the following: commit 941338b93e19021c5b211e9e644387e4326533ce Author: Eugene Burkov Date: Thu Apr 7 13:59:55 2022 +0300 home: imp help output --- internal/home/options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/home/options.go b/internal/home/options.go index 731c8620..dc11ca35 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -175,7 +175,7 @@ var noCheckUpdateArg = arg{ } var disableMemoryOptimizationArg = arg{ - "Disable memory optimization.", + "Deprecated. Disable memory optimization.", "no-mem-optimization", "", nil, nil, func(_ options, _ string) (f effect, err error) { log.Info("warning: using --no-mem-optimization flag has no effect and is deprecated") From 96594a34333a49a8ce3a818b3b7e48ceb547d7c2 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 7 Apr 2022 18:08:39 +0300 Subject: [PATCH 10/99] Pull request: dnsforward: upd svcp param ech name Merge in DNS/adguard-home from upd-ech-dnsrewrite to master Squashed commit of the following: commit b5d9e8643fcb0d7fe7bc44c6d8fc8a9d3f2c9595 Author: Ainar Garipov Date: Thu Apr 7 18:01:18 2022 +0300 all: imp chlog commit 447c5ea6bc2031d4af46578bdb8d724bff001ca0 Author: Ainar Garipov Date: Thu Apr 7 15:40:18 2022 +0300 dnsforward: upd svcp param ech name --- CHANGELOG.md | 41 ++++++++++++++++++----------- go.mod | 10 +++---- go.sum | 18 ++++++++----- internal/dnsforward/svcbmsg.go | 30 ++++++++++++++++++--- internal/dnsforward/svcbmsg_test.go | 8 ++++-- 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc865a3..ca7d27ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,8 +30,11 @@ and this project adheres to ### Changed +- Filtering rules with the `dnsrewrite` modifier that create SVCB or HTTPS + responses should use `ech` instead of `echconfig` to conform with the [latest + drafts][svcb-draft-08]. - The default DNS-over-QUIC port number is now `853` instead of `754` in - accoradance with the latest [RFC draft][doq-draft-10] ([#4276]). + accordance with the latest [RFC draft][doq-draft-10] ([#4276]). - Reverse DNS now has a greater priority as the source of runtime clients' information than ARP neighborhood. - Improved detection of runtime clients through more resilient ARP processing @@ -79,6 +82,9 @@ In this release, the schema version has changed from 12 to 13. ### Deprecated +- SVCB/HTTPS parameter name `echconfig` in filtering rules with the `dnsrewrite` + modifier. Use `ech` instead. v0.109.0 will remove support for the outdated + name `echconfig`. - Obsolete `--no-mem-optimization` option ([#4437]). v0.109.0 will remove the flag completely. - Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. @@ -115,8 +121,9 @@ In this release, the schema version has changed from 12 to 13. [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437 -[repr]: https://reproducible-builds.org/docs/source-date-epoch/ -[doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 +[repr]: https://reproducible-builds.org/docs/source-date-epoch/ +[doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 +[svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html @@ -176,7 +183,7 @@ See also the [v0.107.3 GitHub milestone][ms-v0.107.3]. ### Added -- Support for a `$dnsrewrite` modifier with an empty `NOERROR` response +- Support for a `dnsrewrite` modifier with an empty `NOERROR` response ([#4133]). ### Fixed @@ -292,7 +299,7 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0]. - Better error message for ED25519 private keys, which are not widely supported ([#3737]). - Cache now follows RFC more closely for negative answers ([#3707]). -- `$dnsrewrite` rules and other DNS rewrites will now be applied even when the +- `dnsrewrite` rules and other DNS rewrites will now be applied even when the protection is disabled ([#1558]). - DHCP gateway address, subnet mask, IP address range, and leases validations ([#3529]). @@ -365,7 +372,7 @@ In this release, the schema version has changed from 10 to 12. ### Fixed - EDNS0 TCP keepalive option handling ([#3778]). -- Rules with the `$denyallow` modifier applying to IP addresses when they +- Rules with the `denyallow` modifier applying to IP addresses when they shouldn't ([#3175]). - The length of the EDNS0 client subnet option appearing too long for some upstream servers ([#3887]). @@ -373,8 +380,8 @@ In this release, the schema version has changed from 10 to 12. settings ([#3558]). - Incomplete propagation of the client's IP anonymization setting to the statistics ([#3890]). -- Incorrect `$dnsrewrite` results for entries from the operating system's hosts - file ([#3815]). +- Incorrect results with the `dnsrewrite` modifier for entries from the + operating system's hosts file ([#3815]). - Matching against rules with `|` at the end of the domain name ([#3371]). - Incorrect assignment of explicitly configured DHCP options ([#3744]). - Occasional panic during shutdown ([#3655]). @@ -401,8 +408,8 @@ In this release, the schema version has changed from 10 to 12. - Letter case mismatches in `CNAME` filtering ([#3335]). - Occasional breakages on network errors with DNS-over-HTTP upstreams ([#3217]). - Errors when setting static IP on Linux ([#3257]). -- Treatment of domain names and FQDNs in custom rules with `$dnsrewrite` that - use the `PTR` type ([#3256]). +- Treatment of domain names and FQDNs in custom rules with the `dnsrewrite` + modifier that use the `PTR` type ([#3256]). - Redundant hostname generating while loading static leases with empty hostname ([#3166]). - Domain name case in responses ([#3194]). @@ -566,7 +573,7 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0]. - The ability to block user for login after configurable number of unsuccessful attempts for configurable time ([#2826]). -- `$denyallow` modifier for filters ([#2923]). +- `denyallow` modifier for filters ([#2923]). - Hostname uniqueness validation in the DHCP server ([#2952]). - Hostname generating for DHCP clients which don't provide their own ([#2723]). - New flag `--no-etc-hosts` to disable client domain name lookups in the @@ -581,7 +588,8 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0]. network ([#2393], [#2961]). - The ability to serve DNS queries on multiple hosts and interfaces ([#1401]). - `ips` and `text` DHCP server options ([#2385]). -- `SRV` records support in `$dnsrewrite` filters ([#2533]). +- `SRV` records support in filtering rules with the `dnsrewrite` modifier + ([#2533]). ### Changed @@ -595,7 +603,8 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0]. ([#2704]). - Stricter validation of the IP addresses of static leases in the DHCP server with regards to the netmask ([#2838]). -- Stricter validation of `$dnsrewrite` filter modifier parameters ([#2498]). +- Stricter validation of `dnsrewrite` filtering rule modifier parameters + ([#2498]). - New, more correct versioning scheme ([#2412]). ### Deprecated @@ -604,7 +613,7 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0]. ### Fixed -- Multiple answers for `$dnsrewrite` rule matching requests with repeating +- Multiple answers for a `dnsrewrite` rule matching requests with repeating patterns in it ([#2981]). - Root server resolving when custom upstreams for hosts are specified ([#2994]). - Inconsistent resolving of DHCP clients when the DHCP server is disabled @@ -743,7 +752,7 @@ See also the [v0.105.0 GitHub milestone][ms-v0.105.0]. - `ipset` subdomain matching, just like `dnsmasq` does ([#2179]). - ClientID support for DNS-over-HTTPS, DNS-over-QUIC, and DNS-over-TLS ([#1383]). -- `$dnsrewrite` modifier for filters ([#2102]). +- The new `dnsrewrite` modifier for filters ([#2102]). - The host checking API and the query logs API can now return multiple matched rules ([#2102]). - Detecting of network interface configured to have static IP address via @@ -751,7 +760,7 @@ See also the [v0.105.0 GitHub milestone][ms-v0.105.0]. - DNSCrypt protocol support ([#1361]). - A 5 second wait period until a DHCP server's network interface gets an IP address ([#2304]). -- `$dnstype` modifier for filters ([#2337]). +- `dnstype` modifier for filters ([#2337]). - HTTP API request body size limit ([#2305]). ### Changed diff --git a/go.mod b/go.mod index 8cfd5475..1886d519 100644 --- a/go.mod +++ b/go.mod @@ -20,14 +20,14 @@ require ( github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 github.com/mdlayher/netlink v1.5.0 github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b - github.com/miekg/dns v1.1.45 + github.com/miekg/dns v1.1.48 github.com/satori/go.uuid v1.2.0 github.com/stretchr/testify v1.7.0 github.com/ti-mo/netfilter v0.4.0 go.etcd.io/bbolt v1.3.6 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/net v0.0.0-20211216030914-fe4d6282115f - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e + golang.org/x/net v0.0.0-20220403103023-749bd193bc2b + golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 howett.net/plist v1.0.0 @@ -55,10 +55,10 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect - golang.org/x/mod v0.5.1 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.8 // indirect + golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index 5e5ef775..1e8c5022 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.44/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk= -github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.48 h1:Ucfr7IIVyMBz4lRE8qmGUuZ4Wt3/ZGu9hmcMT3Uu4tQ= +github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= @@ -301,6 +301,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -311,8 +312,9 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -353,8 +355,9 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0= +golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -424,9 +427,11 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -451,8 +456,9 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/dnsforward/svcbmsg.go b/internal/dnsforward/svcbmsg.go index 99413ed3..3d25f05b 100644 --- a/internal/dnsforward/svcbmsg.go +++ b/internal/dnsforward/svcbmsg.go @@ -32,12 +32,16 @@ func (s *Server) genAnswerHTTPS(req *dns.Msg, svcb *rules.DNSSVCB) (ans *dns.HTT // github.com/miekg/dns module. var strToSVCBKey = map[string]dns.SVCBKey{ "alpn": dns.SVCB_ALPN, - "echconfig": dns.SVCB_ECHCONFIG, + "ech": dns.SVCB_ECHCONFIG, "ipv4hint": dns.SVCB_IPV4HINT, "ipv6hint": dns.SVCB_IPV6HINT, "mandatory": dns.SVCB_MANDATORY, "no-default-alpn": dns.SVCB_NO_DEFAULT_ALPN, "port": dns.SVCB_PORT, + + // TODO(a.garipov): This is the previous name for the parameter that has + // since been changed. Remove this in v0.109.0. + "echconfig": dns.SVCB_ECHCONFIG, } // svcbKeyHandler is a handler for one SVCB parameter key. @@ -51,10 +55,10 @@ var svcbKeyHandlers = map[string]svcbKeyHandler{ } }, - "echconfig": func(valStr string) (val dns.SVCBKeyValue) { + "ech": func(valStr string) (val dns.SVCBKeyValue) { ech, err := base64.StdEncoding.DecodeString(valStr) if err != nil { - log.Debug("can't parse svcb/https echconfig: %s; ignoring", err) + log.Debug("can't parse svcb/https ech: %s; ignoring", err) return nil } @@ -119,6 +123,26 @@ var svcbKeyHandlers = map[string]svcbKeyHandler{ Port: uint16(port64), } }, + + // TODO(a.garipov): This is the previous name for the parameter that has + // since been changed. Remove this in v0.109.0. + "echconfig": func(valStr string) (val dns.SVCBKeyValue) { + log.Info( + `warning: svcb/https record parameter name "echconfig" is deprecated; ` + + `use "ech" instead`, + ) + + ech, err := base64.StdEncoding.DecodeString(valStr) + if err != nil { + log.Debug("can't parse svcb/https ech: %s; ignoring", err) + + return nil + } + + return &dns.SVCBECHConfig{ + ECH: ech, + } + }, } // genAnswerSVCB returns a properly initialized SVCB resource record. diff --git a/internal/dnsforward/svcbmsg_test.go b/internal/dnsforward/svcbmsg_test.go index db6994c3..28794531 100644 --- a/internal/dnsforward/svcbmsg_test.go +++ b/internal/dnsforward/svcbmsg_test.go @@ -87,14 +87,18 @@ func TestGenAnswerHTTPS_andSVCB(t *testing.T) { svcb: dnssvcb("alpn", "h3"), want: wantsvcb(&dns.SVCBAlpn{Alpn: []string{"h3"}}), name: "alpn", + }, { + svcb: dnssvcb("ech", "AAAA"), + want: wantsvcb(&dns.SVCBECHConfig{ECH: []byte{0, 0, 0}}), + name: "ech", }, { svcb: dnssvcb("echconfig", "AAAA"), want: wantsvcb(&dns.SVCBECHConfig{ECH: []byte{0, 0, 0}}), - name: "echconfig", + name: "ech_deprecated", }, { svcb: dnssvcb("echconfig", "%BAD%"), want: wantsvcb(nil), - name: "echconfig_invalid", + name: "ech_invalid", }, { svcb: dnssvcb("ipv4hint", "127.0.0.1"), want: wantsvcb(&dns.SVCBIPv4Hint{Hint: []net.IP{ip4}}), From 9f0fdc5e78331a9486c1be2de2d062abff63deb7 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Fri, 8 Apr 2022 16:43:49 +0300 Subject: [PATCH 11/99] Pull request: upd bamboo-specs snapcraft Merge in DNS/adguard-home from upd-bamboo-spec to master Squashed commit of the following: commit c26c70f97cbce98afd5c7d4241188d6949869c2a Author: Dimitry Kolyshev Date: Fri Apr 8 13:51:23 2022 +0200 upd bamboo-specs snapcraft commit afe40c03b70d2b2dff9c7c25044d7924bdd3c765 Author: Dimitry Kolyshev Date: Fri Apr 8 13:10:38 2022 +0200 upd bamboo-specs snapcraft --- bamboo-specs/release.yaml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/bamboo-specs/release.yaml b/bamboo-specs/release.yaml index 50bf1362..62abf5ce 100644 --- a/bamboo-specs/release.yaml +++ b/bamboo-specs/release.yaml @@ -183,8 +183,27 @@ cd ./dist/ + channel="${bamboo.channel}" + readonly channel + case "$channel" + in + ('release') + snapchannel='candidate' + ;; + ('beta') + snapchannel='beta' + ;; + ('edge') + snapchannel='edge' + ;; + (*) + echo "invalid channel '$channel'" + exit 1 + ;; + esac + env\ - SNAPCRAFT_CHANNEL=edge\ + SNAPCRAFT_CHANNEL="$snapchannel"\ SNAPCRAFT_EMAIL="${bamboo.snapcraftEmail}"\ SNAPCRAFT_MACAROON="${bamboo.snapcraftMacaroonPassword}"\ SNAPCRAFT_UBUNTU_DISCHARGE="${bamboo.snapcraftUbuntuDischargePassword}"\ From 2c2c0d445b338a1411208339816c75898f9fad5e Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Tue, 12 Apr 2022 15:45:18 +0300 Subject: [PATCH 12/99] Pull request #1473: svcb dohpath support Merge in DNS/adguard-home from 4463-ddr-support to master Squashed commit of the following: commit 99a149e9024354ad0341739c3c9b08cefbd74468 Author: Dimitry Kolyshev Date: Tue Apr 12 14:13:17 2022 +0200 imp docs commit 26150be8df8b35e47c108f6e3319c57b39fb8e38 Author: Dimitry Kolyshev Date: Mon Apr 11 20:36:18 2022 +0200 imp code docs commit 5a4607f71abba83a9ac8753abd74c9fb97e4a545 Merge: 00f0abf5 9f0fdc5e Author: Dimitry Kolyshev Date: Mon Apr 11 16:14:49 2022 +0200 Merge remote-tracking branch 'origin/master' into 4463-ddr-support # Conflicts: # internal/dnsforward/svcbmsg.go commit 00f0abf5eea07aeeebc2a856a958215021a51ab7 Author: Dimitry Kolyshev Date: Mon Apr 11 16:06:42 2022 +0200 svcb dohpath support commit ace81ce1ea2fb96c4434c6c1fded4a79427cf17e Author: Dimitry Kolyshev Date: Thu Apr 7 14:31:32 2022 +0200 svcb dohpath support commit a1b5df4fb2e87dab265d6ca55928610a6acc1c00 Author: Dimitry Kolyshev Date: Wed Apr 6 16:53:17 2022 +0200 svcb dohpath support --- CHANGELOG.md | 4 ++++ go.mod | 3 +++ go.sum | 2 ++ internal/dnsforward/dnsrewrite_test.go | 32 +++++++++++++++++++++----- internal/dnsforward/svcbmsg.go | 6 +++++ internal/dnsforward/svcbmsg_test.go | 4 ++++ 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca7d27ad..aa305b2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to ### Added +- Support for SVCB/HTTPS parameter `dohpath` in filtering rules with + `dnsrewrite` modifier according to the [RFC draft][dns-draft-02] ([#4463]). - The ability to customize the set of networks that are considered private through the new `dns.private_networks` property in the configuration file ([#3142]). @@ -120,10 +122,12 @@ In this release, the schema version has changed from 12 to 13. [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437 +[#4463]: https://github.com/AdguardTeam/AdGuardHome/issues/4463 [repr]: https://reproducible-builds.org/docs/source-date-epoch/ [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 [svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html +[dns-draft-02]: https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02#section-5.1 diff --git a/go.mod b/go.mod index 1886d519..110f2bbb 100644 --- a/go.mod +++ b/go.mod @@ -64,3 +64,6 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect honnef.co/go/tools v0.2.2 // indirect ) + +// TODO(a.garipov): Return to the main repo once miekg/dns#1359 is merged. +replace github.com/miekg/dns => github.com/ainar-g/dns v1.1.49-0.20220411125901-8a162bbc18d8 diff --git a/go.sum b/go.sum index 1e8c5022..e405e27c 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,8 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmH github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw= github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us= +github.com/ainar-g/dns v1.1.49-0.20220411125901-8a162bbc18d8 h1:Hp2waLwK989ui3bDkFpedlIHfyWdZ77gynvd+GPEqXY= +github.com/ainar-g/dns v1.1.49-0.20220411125901-8a162bbc18d8/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/ameshkov/dnscrypt/v2 v2.2.3 h1:X9UP5AHtwp46Ji+sGFfF/1Is6OPI/SjxLqhKpx0P5UI= github.com/ameshkov/dnscrypt/v2 v2.2.3/go.mod h1:xJB9cE1/GF+NB6EEQqRlkoa4bjcV2w7VYn1G+zVq7Bs= github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A= diff --git a/internal/dnsforward/dnsrewrite_test.go b/internal/dnsforward/dnsrewrite_test.go index 347b8f29..5ba10582 100644 --- a/internal/dnsforward/dnsrewrite_test.go +++ b/internal/dnsforward/dnsrewrite_test.go @@ -22,7 +22,7 @@ func TestServer_FilterDNSRewrite(t *testing.T) { Preference: 32, } svcbVal := &rules.DNSSVCB{ - Params: map[string]string{"alpn": "h3"}, + Params: map[string]string{"alpn": "h3", "dohpath": "/dns-query"}, Target: dns.Fqdn(domain), Priority: 32, } @@ -164,10 +164,20 @@ func TestServer_FilterDNSRewrite(t *testing.T) { require.Len(t, d.Res.Answer, 1) ans, ok := d.Res.Answer[0].(*dns.SVCB) - require.True(t, ok) - assert.Equal(t, dns.SVCB_ALPN, ans.Value[0].Key()) - assert.Equal(t, svcbVal.Params["alpn"], ans.Value[0].String()) + require.True(t, ok) + require.Len(t, ans.Value, 2) + + assert.ElementsMatch( + t, + []dns.SVCBKey{dns.SVCB_ALPN, dns.SVCB_DOHPATH}, + []dns.SVCBKey{ans.Value[0].Key(), ans.Value[1].Key()}, + ) + assert.ElementsMatch( + t, + []string{svcbVal.Params["alpn"], svcbVal.Params["dohpath"]}, + []string{ans.Value[0].String(), ans.Value[1].String()}, + ) assert.Equal(t, svcbVal.Target, ans.Target) assert.Equal(t, svcbVal.Priority, ans.Priority) }) @@ -186,8 +196,18 @@ func TestServer_FilterDNSRewrite(t *testing.T) { ans, ok := d.Res.Answer[0].(*dns.HTTPS) require.True(t, ok) - assert.Equal(t, dns.SVCB_ALPN, ans.Value[0].Key()) - assert.Equal(t, svcbVal.Params["alpn"], ans.Value[0].String()) + require.Len(t, ans.Value, 2) + + assert.ElementsMatch( + t, + []dns.SVCBKey{dns.SVCB_ALPN, dns.SVCB_DOHPATH}, + []dns.SVCBKey{ans.Value[0].Key(), ans.Value[1].Key()}, + ) + assert.ElementsMatch( + t, + []string{svcbVal.Params["alpn"], svcbVal.Params["dohpath"]}, + []string{ans.Value[0].String(), ans.Value[1].String()}, + ) assert.Equal(t, svcbVal.Target, ans.Target) assert.Equal(t, svcbVal.Priority, ans.Priority) }) diff --git a/internal/dnsforward/svcbmsg.go b/internal/dnsforward/svcbmsg.go index 3d25f05b..d1e3e3d8 100644 --- a/internal/dnsforward/svcbmsg.go +++ b/internal/dnsforward/svcbmsg.go @@ -143,6 +143,12 @@ var svcbKeyHandlers = map[string]svcbKeyHandler{ ECH: ech, } }, + + "dohpath": func(valStr string) (val dns.SVCBKeyValue) { + return &dns.SVCBDoHPath{ + Template: valStr, + } + }, } // genAnswerSVCB returns a properly initialized SVCB resource record. diff --git a/internal/dnsforward/svcbmsg_test.go b/internal/dnsforward/svcbmsg_test.go index 28794531..8de53988 100644 --- a/internal/dnsforward/svcbmsg_test.go +++ b/internal/dnsforward/svcbmsg_test.go @@ -127,6 +127,10 @@ func TestGenAnswerHTTPS_andSVCB(t *testing.T) { svcb: dnssvcb("no-default-alpn", ""), want: wantsvcb(&dns.SVCBNoDefaultAlpn{}), name: "no_default_alpn", + }, { + svcb: dnssvcb("dohpath", "/dns-query"), + want: wantsvcb(&dns.SVCBDoHPath{Template: "/dns-query"}), + name: "dohpath", }, { svcb: dnssvcb("port", "8080"), want: wantsvcb(&dns.SVCBPort{Port: 8080}), From 21a1187ed2d18e316d8af33c5d8bdd19034fea9f Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 13 Apr 2022 18:16:33 +0300 Subject: [PATCH 13/99] Pull request: all: upd go, tools Merge in DNS/adguard-home from upd-go to master Squashed commit of the following: commit 26cd13146df705ead5e1c39c27e73252c71fa64d Author: Ainar Garipov Date: Wed Apr 13 17:46:24 2022 +0300 all: upd go, tools --- CHANGELOG.md | 134 +++++++++++++--------- bamboo-specs/release.yaml | 6 +- bamboo-specs/test.yaml | 2 +- go.mod | 45 ++++---- go.sum | 149 +++++++++---------------- internal/aghnet/hostscontainer.go | 2 +- internal/aghnet/hostscontainer_test.go | 30 ++--- internal/filtering/filtering.go | 4 +- internal/tools/go.mod | 24 ++-- internal/tools/go.sum | 74 +++++++----- 10 files changed, 236 insertions(+), 234 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa305b2a..a80b4ea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,17 @@ and this project adheres to ## [Unreleased] +### Security + +- Enforced password strength policy ([#3503]). +- Weaker cipher suites that use the CBC (cipher block chaining) mode of + operation have been disabled ([#2993]). + ### Added -- Support for SVCB/HTTPS parameter `dohpath` in filtering rules with - `dnsrewrite` modifier according to the [RFC draft][dns-draft-02] ([#4463]). - The ability to customize the set of networks that are considered private through the new `dns.private_networks` property in the configuration file ([#3142]). @@ -32,9 +36,6 @@ and this project adheres to ### Changed -- Filtering rules with the `dnsrewrite` modifier that create SVCB or HTTPS - responses should use `ech` instead of `echconfig` to conform with the [latest - drafts][svcb-draft-08]. - The default DNS-over-QUIC port number is now `853` instead of `754` in accordance with the latest [RFC draft][doq-draft-10] ([#4276]). - Reverse DNS now has a greater priority as the source of runtime clients' @@ -84,28 +85,8 @@ In this release, the schema version has changed from 12 to 13. ### Deprecated -- SVCB/HTTPS parameter name `echconfig` in filtering rules with the `dnsrewrite` - modifier. Use `ech` instead. v0.109.0 will remove support for the outdated - name `echconfig`. -- Obsolete `--no-mem-optimization` option ([#4437]). v0.109.0 will remove the - flag completely. - Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. -### Fixed - -- I/O timeout errors on checking another DHCP server. - -### Removed - -- Go 1.16 support. - -### Security - -- `User-Agent` HTTP header removed from outgoing DNS-over-HTTPS requests. -- Enforced password strength policy ([#3503]). -- Weaker cipher suites that use the CBC (cipher block chaining) mode of - operation have been disabled ([#2993]). - [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 [#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993 [#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057 @@ -117,27 +98,76 @@ In this release, the schema version has changed from 12 to 13. [#3978]: https://github.com/AdguardTeam/AdGuardHome/issues/3978 [#4166]: https://github.com/AdguardTeam/AdGuardHome/issues/4166 [#4213]: https://github.com/AdguardTeam/AdGuardHome/issues/4213 -[#4216]: https://github.com/AdguardTeam/AdGuardHome/issues/4216 [#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221 [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 -[#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437 -[#4463]: https://github.com/AdguardTeam/AdGuardHome/issues/4463 -[repr]: https://reproducible-builds.org/docs/source-date-epoch/ -[doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 -[svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html -[dns-draft-02]: https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02#section-5.1 +[repr]: https://reproducible-builds.org/docs/source-date-epoch/ +[doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 + + + +## [v0.107.6] - 2022-04-13 See also the [v0.107.6 GitHub milestone][ms-v0.107.6]. -[ms-v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/milestone/42?closed=1 ---> +### Security + +- `User-Agent` HTTP header removed from outgoing DNS-over-HTTPS requests. +- Go version was updated to prevent the possibility of exploiting the + [CVE-2022-24675], [CVE-2022-27536], and [CVE-2022-28327] vulnerabilities. + +### Added + +- Support for SVCB/HTTPS parameter `dohpath` in filtering rules with + the `dnsrewrite` modifier according to the [RFC draft][dns-draft-02] + ([#4463]). + +### Changed + +- Filtering rules with the `dnsrewrite` modifier that create SVCB or HTTPS + responses should use `ech` instead of `echconfig` to conform with the [latest + drafts][svcb-draft-08]. + +### Deprecated + +- SVCB/HTTPS parameter name `echconfig` in filtering rules with the `dnsrewrite` + modifier. Use `ech` instead. v0.109.0 will remove support for the outdated + name `echconfig`. +- Obsolete `--no-mem-optimization` option ([#4437]). v0.109.0 will remove the + flag completely. + +### Fixed + +- I/O timeout errors when checking for the presence of another DHCP server. +- Network interfaces being incorrectly labeled as down during installation. +- Rules for blocking the QQ service ([#3717]). + +### Removed + +- Go 1.16 support, since that branch of the Go compiler has reached end of life + and doesn't receive security updates anymore. + +[#3717]: https://github.com/AdguardTeam/AdGuardHome/issues/3717 +[#4437]: https://github.com/AdguardTeam/AdGuardHome/issues/4437 +[#4463]: https://github.com/AdguardTeam/AdGuardHome/issues/4463 + +[CVE-2022-24675]: https://www.cvedetails.com/cve/CVE-2022-24675 +[CVE-2022-27536]: https://www.cvedetails.com/cve/CVE-2022-27536 +[CVE-2022-28327]: https://www.cvedetails.com/cve/CVE-2022-28327 +[dns-draft-02]: https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02#section-5.1 +[ms-v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/milestone/42?closed=1 +[svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html @@ -159,6 +189,11 @@ were resolved. See also the [v0.107.4 GitHub milestone][ms-v0.107.4]. +### Security + +- Go version was updated to prevent the possibility of exploiting the + [CVE-2022-23806], [CVE-2022-23772], and [CVE-2022-23773] vulnerabilities. + ### Fixed - Optimistic cache now responds with expired items even if those can't be @@ -166,11 +201,6 @@ See also the [v0.107.4 GitHub milestone][ms-v0.107.4]. - Unnecessarily complex hosts-related logic leading to infinite recursion in some cases ([#4216]). -### Security - -- Go version was updated to prevent the possibility of exploiting the - [CVE-2022-23806], [CVE-2022-23772], and [CVE-2022-23773] vulnerabilities. - [#4216]: https://github.com/AdguardTeam/AdGuardHome/issues/4216 [#4254]: https://github.com/AdguardTeam/AdGuardHome/issues/4254 @@ -276,7 +306,7 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0]. ([#2141]). - The ability to completely purge DHCP leases ([#1691]). - Settable timeouts for querying the upstream servers ([#2280]). -- Configuration file parameters to change group and user ID on startup on Unix +- Configuration file properties to change group and user ID on startup on Unix ([#2763]). - Experimental OpenBSD support for AMD64 and 64-bit ARM CPUs ([#2439], [#3225], [#3226]). @@ -325,8 +355,8 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0]. original encoded version shown in request details ([#3013]). - When /etc/hosts-type rules have several IPs for one host, all IPs are now returned instead of only the first one ([#1381]). -- Property `rlimit_nofile` is now in the `os` object of the configuration file, - together with the new `group` and `user` properties ([#2763]). +- Property `rlimit_nofile` is now in the `os` object of the configuration + file, together with the new `group` and `user` properties ([#2763]). - Permissions on filter files are now `0o644` instead of `0o600` ([#3198]). #### Configuration Changes @@ -669,6 +699,10 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0]. ## [v0.105.2] - 2021-03-10 +### Security + +- Session token doesn't contain user's information anymore ([#2470]). + See also the [v0.105.2 GitHub milestone][ms-v0.105.2]. ### Fixed @@ -682,10 +716,6 @@ See also the [v0.105.2 GitHub milestone][ms-v0.105.2]. - Incomplete DNS upstreams validation ([#2674]). - Wrong parsing of DHCP options of the `ip` type ([#2688]). -### Security - -- Session token doesn't contain user's information anymore ([#2470]). - [#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470 [#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582 [#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600 @@ -897,13 +927,13 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2]. - -[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.5...HEAD +[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.6...HEAD +[v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.5...v0.107.6 [v0.107.5]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.4...v0.107.5 [v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...v0.107.4 [v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.2...v0.107.3 diff --git a/bamboo-specs/release.yaml b/bamboo-specs/release.yaml index 62abf5ce..d0513f0f 100644 --- a/bamboo-specs/release.yaml +++ b/bamboo-specs/release.yaml @@ -7,7 +7,7 @@ # Make sure to sync any changes with the branch overrides below. 'variables': 'channel': 'edge' - 'dockerGo': 'adguard/golang-ubuntu:4.2' + 'dockerGo': 'adguard/golang-ubuntu:4.3' 'stages': - 'Make release': @@ -285,7 +285,7 @@ # need to build a few of these. 'variables': 'channel': 'beta' - 'dockerGo': 'adguard/golang-ubuntu:4.2' + 'dockerGo': 'adguard/golang-ubuntu:4.3' # release-vX.Y.Z branches are the branches from which the actual final release # is built. - '^release-v[0-9]+\.[0-9]+\.[0-9]+': @@ -300,4 +300,4 @@ # are the ones that actually get released. 'variables': 'channel': 'release' - 'dockerGo': 'adguard/golang-ubuntu:4.2' + 'dockerGo': 'adguard/golang-ubuntu:4.3' diff --git a/bamboo-specs/test.yaml b/bamboo-specs/test.yaml index fa410195..e973b77c 100644 --- a/bamboo-specs/test.yaml +++ b/bamboo-specs/test.yaml @@ -5,7 +5,7 @@ 'key': 'AHBRTSPECS' 'name': 'AdGuard Home - Build and run tests' 'variables': - 'dockerGo': 'adguard/golang-ubuntu:4.2' + 'dockerGo': 'adguard/golang-ubuntu:4.3' 'stages': - 'Tests': diff --git a/go.mod b/go.mod index 110f2bbb..30d8b377 100644 --- a/go.mod +++ b/go.mod @@ -3,66 +3,67 @@ module github.com/AdguardTeam/AdGuardHome go 1.17 require ( - github.com/AdguardTeam/dnsproxy v0.41.4 + github.com/AdguardTeam/dnsproxy v0.42.1 github.com/AdguardTeam/golibs v0.10.8 - github.com/AdguardTeam/urlfilter v0.15.2 + github.com/AdguardTeam/urlfilter v0.16.0 github.com/NYTimes/gziphandler v1.1.1 github.com/ameshkov/dnscrypt/v2 v2.2.3 github.com/digineo/go-ipset/v2 v2.2.1 github.com/fsnotify/fsnotify v1.5.1 github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 - github.com/google/go-cmp v0.5.6 + github.com/google/go-cmp v0.5.7 github.com/google/gopacket v1.1.19 github.com/google/renameio v1.0.1 - github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 - github.com/kardianos/service v1.2.0 - github.com/lucas-clemente/quic-go v0.25.0 - github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 - github.com/mdlayher/netlink v1.5.0 + github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 + github.com/kardianos/service v1.2.1 + github.com/lucas-clemente/quic-go v0.26.0 + github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 + github.com/mdlayher/netlink v1.6.0 + // TODO(a.garipov): This package is deprecated; find a new one or use + // our own code for that. github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b github.com/miekg/dns v1.1.48 github.com/satori/go.uuid v1.2.0 github.com/stretchr/testify v1.7.0 github.com/ti-mo/netfilter v0.4.0 go.etcd.io/bbolt v1.3.6 - golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/net v0.0.0-20220403103023-749bd193bc2b - golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 + golang.org/x/net v0.0.0-20220412020605-290c469a71a5 + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 howett.net/plist v1.0.0 ) require ( - github.com/BurntSushi/toml v0.4.1 // indirect + github.com/BurntSushi/toml v1.1.0 // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect github.com/ameshkov/dnsstamps v1.0.3 // indirect - github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47 // indirect + github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect - github.com/mdlayher/socket v0.1.1 // indirect + github.com/josharian/native v1.0.0 // indirect + github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect + github.com/mdlayher/socket v0.2.3 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.1.1 // indirect - github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect + github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - honnef.co/go/tools v0.2.2 // indirect ) // TODO(a.garipov): Return to the main repo once miekg/dns#1359 is merged. diff --git a/go.sum b/go.sum index e405e27c..e75df993 100644 --- a/go.sum +++ b/go.sum @@ -7,20 +7,19 @@ 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.41.4 h1:zA8BJmWBkSL5kp4b8CblQRgIrLGzJ4IUGQ7tA1255Cw= -github.com/AdguardTeam/dnsproxy v0.41.4/go.mod h1:GCdEbTw683vBqksJIccPSYzBg2yIFbRiDnXltyIinug= +github.com/AdguardTeam/dnsproxy v0.42.1 h1:RZAtW75cvMX1d9Mibg0CA343V7VWV5PLrXsLhBZfdYc= +github.com/AdguardTeam/dnsproxy v0.42.1/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= -github.com/AdguardTeam/golibs v0.10.6/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= github.com/AdguardTeam/golibs v0.10.8 h1:diU9gP9qG1qeLbAkzIwfUerpHSqzR6zaBgzvRMR/m6Q= github.com/AdguardTeam/golibs v0.10.8/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU= -github.com/AdguardTeam/urlfilter v0.15.2 h1:LZGgrm4l4Ys9eAqB+UUmZfiC6vHlDlYFhx0WXqo6LtQ= -github.com/AdguardTeam/urlfilter v0.15.2/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI= +github.com/AdguardTeam/urlfilter v0.16.0 h1:IO29m+ZyQuuOnPLTzHuXj35V1DZOp1Dcryl576P2syg= +github.com/AdguardTeam/urlfilter v0.16.0/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= @@ -37,15 +36,14 @@ github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaE github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo= github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47 h1:M57m0xQqZIhx7CEJgeLSvRFKEK1RjzRuIXiA3HfYU7g= github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA= +github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 h1:0b2vaepXIfMsG++IsjHiI2p4bxALD1Y2nQKGMR5zDQM= +github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -58,7 +56,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= @@ -97,10 +94,10 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= @@ -120,87 +117,68 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= -github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 h1:jhdHqd7DxBrzfuFSoPxjD6nUVaV/1RIn9aHA0WCf/as= -github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 h1:Yg3n3AI7GoHnWt7dyjsLPU+TEuZfPAg0OdiA3MJUV6I= +github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA= -github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= +github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= -github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw= -github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs= -github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA= -github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U= -github.com/jsimonetti/rtnetlink v0.0.0-20210525051524-4cc836578190/go.mod h1:NmKSdU4VGSiv1bMsdqNALI4RSvvjtz65tTMCnD05qLo= -github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786 h1:N527AHMa793TP5z5GNAn/VLPzlc0ewzWdeP/25gDfgQ= -github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786/go.mod h1:v4hqbTdfQngbVSZJVWUhGE/lbTFf9jb+ygmNUDQMuOs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g= -github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= +github.com/kardianos/service v1.2.1 h1:AYndMsehS+ywIS6RB9KOlcXzteWUzxgMgBymJD7+BYk= +github.com/kardianos/service v1.2.1/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= -github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/lucas-clemente/quic-go v0.26.0 h1:ALBQXr9UJ8A1LyzvceX4jd9QFsHvlI0RR6BkV16o00A= +github.com/lucas-clemente/quic-go v0.26.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= +github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc= +github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/qtls-go1-18 v0.1.0/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y= +github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= -github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= -github.com/mdlayher/ethtool v0.0.0-20211028163843-288d040e9d60 h1:tHdB+hQRHU10CfcK0furo6rSNgZ38JT8uPh70c/pFD8= -github.com/mdlayher/ethtool v0.0.0-20211028163843-288d040e9d60/go.mod h1:aYbhishWc4Ai3I2U4Gaa2n3kHWSwzme6EsG/46HRQbE= -github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= -github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= +github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE= +github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118/go.mod h1:ZFUnHIVchZ9lJoWoEGUg8Q3M4U8aNNWA3CVSUTkW4og= github.com/mdlayher/netlink v0.0.0-20190313131330-258ea9dff42c/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= github.com/mdlayher/netlink v1.1.2-0.20201013204415-ded538f7f4be/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= -github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8= -github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= -github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= -github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys= -github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= -github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q= -github.com/mdlayher/netlink v1.5.0 h1:r4fa439+SsMarM0rMONU3iSshSV3ArVqJl6H/zjrhh4= -github.com/mdlayher/netlink v1.5.0/go.mod h1:1Kr8BBFxGyUyNmztC9WLOayqYVAd2wsgOZm18nqGuzQ= +github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= +github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= +github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU= github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A= github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= -github.com/mdlayher/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc= -github.com/mdlayher/socket v0.0.0-20211007213009-516dcbdf0267/go.mod h1:nFZ1EtZYK8Gi/k6QNu7z7CgO20i/4ExeQswwWuPmG/g= -github.com/mdlayher/socket v0.1.0/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= -github.com/mdlayher/socket v0.1.1 h1:q3uOGirUPfAV2MUoaC7BavjQ154J7+JOkTWyiV+intI= github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= +github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= +github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM= +github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.44/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/dns v1.1.48 h1:Ucfr7IIVyMBz4lRE8qmGUuZ4Wt3/ZGu9hmcMT3Uu4tQ= -github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= @@ -283,13 +261,12 @@ github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 h1:XMAtQHwKjWHIRwg+8Nj/rzUomQY1q6cM3ncA0wP8GU4= -github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= +github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= +github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -304,8 +281,9 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -314,7 +292,6 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -328,10 +305,10 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -341,25 +318,19 @@ golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0= -golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -387,7 +358,6 @@ golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -402,17 +372,8 @@ golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -421,17 +382,16 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM= -golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -451,21 +411,19 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a h1:ofrrl6c6NG5/IOSx/R1cyiQxxjqlur0h/TvbUhkH0II= +golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -516,9 +474,6 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk= -honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= diff --git a/internal/aghnet/hostscontainer.go b/internal/aghnet/hostscontainer.go index 290dc1c0..65c9d3c4 100644 --- a/internal/aghnet/hostscontainer.go +++ b/internal/aghnet/hostscontainer.go @@ -51,7 +51,7 @@ type requestMatcher struct { // // It's safe for concurrent use. func (rm *requestMatcher) MatchRequest( - req urlfilter.DNSRequest, + req *urlfilter.DNSRequest, ) (res *urlfilter.DNSResult, ok bool) { switch req.DNSType { case dns.TypeA, dns.TypeAAAA, dns.TypePTR: diff --git a/internal/aghnet/hostscontainer_test.go b/internal/aghnet/hostscontainer_test.go index 807722a8..42202f43 100644 --- a/internal/aghnet/hostscontainer_test.go +++ b/internal/aghnet/hostscontainer_test.go @@ -193,7 +193,7 @@ func TestHostsContainer_refresh(t *testing.T) { // Require the changes are written. require.Eventually(t, func() bool { - res, ok := hc.MatchRequest(urlfilter.DNSRequest{ + res, ok := hc.MatchRequest(&urlfilter.DNSRequest{ Hostname: "hostname", DNSType: dns.TypeA, }) @@ -207,7 +207,7 @@ func TestHostsContainer_refresh(t *testing.T) { // Require the changes are written. require.Eventually(t, func() bool { - res, ok := hc.MatchRequest(urlfilter.DNSRequest{ + res, ok := hc.MatchRequest(&urlfilter.DNSRequest{ Hostname: "hostname", DNSType: dns.TypeA, }) @@ -365,7 +365,7 @@ func TestHostsContainer(t *testing.T) { testCases := []struct { want []*rules.DNSRewrite name string - req urlfilter.DNSRequest + req *urlfilter.DNSRequest }{{ want: []*rules.DNSRewrite{{ RCode: dns.RcodeSuccess, @@ -377,7 +377,7 @@ func TestHostsContainer(t *testing.T) { RRType: dns.TypeAAAA, }}, name: "simple", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "simplehost", DNSType: dns.TypeA, }, @@ -392,7 +392,7 @@ func TestHostsContainer(t *testing.T) { RRType: dns.TypeAAAA, }}, name: "hello_alias", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "hello.world", DNSType: dns.TypeA, }, @@ -407,21 +407,21 @@ func TestHostsContainer(t *testing.T) { RRType: dns.TypeAAAA, }}, name: "other_line_alias", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "hello.world.again", DNSType: dns.TypeA, }, }, { want: []*rules.DNSRewrite{}, name: "hello_subdomain", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "say.hello", DNSType: dns.TypeA, }, }, { want: []*rules.DNSRewrite{}, name: "hello_alias_subdomain", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "say.hello.world", DNSType: dns.TypeA, }, @@ -436,7 +436,7 @@ func TestHostsContainer(t *testing.T) { Value: net.ParseIP("::2"), }}, name: "lots_of_aliases", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "for.testing", DNSType: dns.TypeA, }, @@ -447,21 +447,21 @@ func TestHostsContainer(t *testing.T) { Value: "simplehost.", }}, name: "reverse", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "1.0.0.1.in-addr.arpa", DNSType: dns.TypePTR, }, }, { want: []*rules.DNSRewrite{}, name: "non-existing", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "nonexisting", DNSType: dns.TypeA, }, }, { want: nil, name: "bad_type", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "1.0.0.1.in-addr.arpa", DNSType: dns.TypeSRV, }, @@ -476,7 +476,7 @@ func TestHostsContainer(t *testing.T) { Value: net.ParseIP("::42"), }}, name: "issue_4216_4_6", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "domain", DNSType: dns.TypeA, }, @@ -491,7 +491,7 @@ func TestHostsContainer(t *testing.T) { Value: net.IPv4(1, 3, 5, 7), }}, name: "issue_4216_4", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "domain4", DNSType: dns.TypeA, }, @@ -506,7 +506,7 @@ func TestHostsContainer(t *testing.T) { Value: net.ParseIP("::31"), }}, name: "issue_4216_6", - req: urlfilter.DNSRequest{ + req: &urlfilter.DNSRequest{ Hostname: "domain6", DNSType: dns.TypeAAAA, }, diff --git a/internal/filtering/filtering.go b/internal/filtering/filtering.go index 9bedeef7..8af49b0c 100644 --- a/internal/filtering/filtering.go +++ b/internal/filtering/filtering.go @@ -471,7 +471,7 @@ func (d *DNSFilter) matchSysHosts( return res, nil } - dnsres, _ := d.EtcHosts.MatchRequest(urlfilter.DNSRequest{ + dnsres, _ := d.EtcHosts.MatchRequest(&urlfilter.DNSRequest{ Hostname: host, SortedClientTags: setts.ClientTags, // TODO(e.burkov): Wait for urlfilter update to pass net.IP. @@ -802,7 +802,7 @@ func (d *DNSFilter) matchHost( return Result{}, nil } - ureq := urlfilter.DNSRequest{ + ureq := &urlfilter.DNSRequest{ Hostname: host, SortedClientTags: setts.ClientTags, // TODO(e.burkov): Wait for urlfilter update to pass net.IP. diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 98ef459a..2ad6ce16 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -3,30 +3,32 @@ module github.com/AdguardTeam/AdGuardHome/internal/tools go 1.17 require ( - github.com/fzipp/gocyclo v0.4.0 + github.com/fzipp/gocyclo v0.5.1 github.com/golangci/misspell v0.3.5 github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 github.com/kisielk/errcheck v1.6.0 github.com/kyoh86/looppointer v0.1.7 - github.com/securego/gosec/v2 v2.9.5 + github.com/securego/gosec/v2 v2.11.0 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 - golang.org/x/tools v0.1.8 - honnef.co/go/tools v0.2.2 - mvdan.cc/gofumpt v0.2.1 - mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 + golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a + honnef.co/go/tools v0.3.0 + mvdan.cc/gofumpt v0.3.1 + mvdan.cc/unparam v0.0.0-20220316160445-06cc5682983b ) require ( - github.com/BurntSushi/toml v0.4.1 // indirect + github.com/BurntSushi/toml v1.1.0 // indirect github.com/client9/misspell v0.3.4 // indirect - github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-cmp v0.5.7 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.0 // indirect github.com/kyoh86/nolint v0.0.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - golang.org/x/mod v0.5.1 // indirect - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/internal/tools/go.sum b/internal/tools/go.sum index e1b2e226..7dbf5491 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -34,8 +34,9 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -92,14 +93,13 @@ github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= -github.com/fzipp/gocyclo v0.4.0 h1:IykTnjwh2YLyYkGa0y92iTTEQcnyAz0r9zOo15EbJ7k= -github.com/fzipp/gocyclo v0.4.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/fzipp/gocyclo v0.5.1 h1:L66amyuYogbxl0j2U+vGqJXusPF2IkduvXLnYD5TFgw= +github.com/fzipp/gocyclo v0.5.1/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -157,8 +157,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -168,6 +168,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -200,6 +201,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -276,7 +278,6 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6Fx github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -284,13 +285,16 @@ github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2f github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -325,8 +329,8 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/securego/gosec/v2 v2.9.5 h1:Wiyf78NNedu8RClwW0vPRgPKCY7LJX4WujjJcPV2Nwg= -github.com/securego/gosec/v2 v2.9.5/go.mod h1:lG831xFHrZofatyJb9Y5yMUE8Ws6z5U5CMHe9vYn1kM= +github.com/securego/gosec/v2 v2.11.0 h1:+PDkpzR41OI2jrw1q6AdXZCbsNGNGT7pQjal0H0cArI= +github.com/securego/gosec/v2 v2.11.0/go.mod h1:SX8bptShuG8reGC0XS09+a4H2BoWSJi+fscA+Pulbpo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -401,7 +405,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -412,7 +417,11 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4 h1:P5yukcpQfG1ZDKR0pGdaZCVwaNPntMxLFKYg81li58M= +golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -436,8 +445,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -473,6 +483,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -493,6 +504,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -539,15 +551,16 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -613,15 +626,17 @@ golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200710042808-f1c4188a97a1/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a h1:ofrrl6c6NG5/IOSx/R1cyiQxxjqlur0h/TvbUhkH0II= +golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -714,7 +729,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -737,12 +751,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk= -honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -mvdan.cc/gofumpt v0.2.1 h1:7jakRGkQcLAJdT+C8Bwc9d0BANkVPSkHZkzNv07pJAs= -mvdan.cc/gofumpt v0.2.1/go.mod h1:a/rvZPhsNaedOJBzqRD9omnwVwHZsBdJirXHa9Gh9Ig= -mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 h1:Jh3LAeMt1eGpxomyu3jVkmVZWW2MxZ1qIIV2TZ/nRio= -mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5/go.mod h1:b8RRCBm0eeiWR8cfN88xeq2G5SG3VKGO+5UPWi5FSOY= +honnef.co/go/tools v0.3.0 h1:2LdYUZ7CIxnYgskbUZfY7FPggmqnh6shBqfWa8Tn3XU= +honnef.co/go/tools v0.3.0/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= +mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= +mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= +mvdan.cc/unparam v0.0.0-20220316160445-06cc5682983b h1:C8Pi6noat8BcrL9WnSRYeQ63fpkJk3hKVHtF5731kIw= +mvdan.cc/unparam v0.0.0-20220316160445-06cc5682983b/go.mod h1:WqFWCt8MGPoFSYGsQSiIORRlYVhkJsIk+n2MY6rhNbA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 57171f0a61574bf9cc4819e2f8444638c4b5693c Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 13 Apr 2022 20:30:36 +0300 Subject: [PATCH 14/99] Pull request: client: upd i18n Merge in DNS/adguard-home from upd-i18n to master Squashed commit of the following: commit 181c13667eb79e5f0c8ec6502e8bd79f7403bf8d Author: Ainar Garipov Date: Wed Apr 13 20:24:32 2022 +0300 client: upd i18n --- client/src/__locales/bg.json | 38 ++++++++++++++- client/src/__locales/de.json | 4 +- client/src/__locales/fa.json | 84 +++++++++++++++++++++++++++++++-- client/src/__locales/nl.json | 20 ++++---- client/src/__locales/no.json | 45 ++++++++++++++++-- client/src/__locales/ru.json | 4 +- client/src/__locales/sv.json | 10 ++-- client/src/__locales/tr.json | 6 +-- client/src/__locales/zh-tw.json | 4 +- 9 files changed, 183 insertions(+), 32 deletions(-) diff --git a/client/src/__locales/bg.json b/client/src/__locales/bg.json index 1b6a1db5..a64b7620 100644 --- a/client/src/__locales/bg.json +++ b/client/src/__locales/bg.json @@ -1,16 +1,22 @@ { + "client_settings": "Kлиентски настройки", + "example_upstream_comment": "Можете да поставите коментар", + "load_balancing": "Балансиране на натоварването", "check_dhcp_servers": "Проверка за активен DHCP сървър", + "save_config": "Запиши настройките", "enabled_dhcp": "DHCP е разрешен", "disabled_dhcp": "DHCP е забранен", "dhcp_title": "DHCP сървър (тестови!)", "dhcp_description": "Ако рутера ви не раздава DHCP адреси, може да използвате вградения в AdGuard DHCP сървър.", "dhcp_enable": "Рзреши DHCP сървъра", "dhcp_disable": "Забрани DHCP сървъра", + "dhcp_not_found": "Вашата мрежа няма активен DHCP сървър. Безопасно е ползването на вградения DHCP сървър.", "dhcp_found": "Вашата мрежа вече има активен DHCP сървър. Не е безопасно ползването на втори!", "dhcp_leases": "DHCP раздадени адреси", "dhcp_leases_not_found": "Няма намерени активни DHCP адреси", + "dhcp_config_saved": "Запиши конфигурацията на DHCP сървъра", "form_error_required": "Задължително поле", - "form_error_ip_format": "Невалиден IP адрес", + "form_error_ip_format": "Невалиден IPv4 адрес", "form_error_positive": "Проверете дали е положително число", "dhcp_form_gateway_input": "IP шлюз", "dhcp_form_subnet_input": "Мрежова маска", @@ -24,15 +30,21 @@ "dhcp_ip_addresses": "IP адреси", "dhcp_table_hostname": "Име на устройство", "dhcp_table_expires": "История", + "dhcp_warning": "Ако искате да използвате вградения DHCP сървър, трябва да няма друг активен DHCP в мрежата Ви!", + "country": "Държава", "city": "Град", + "delete_confirm": "Наистина ли искате да изтриете \"{{key}}\"?", + "error_details": "Подробности за грешка", "response_details": "Подробности за отговора", "request_details": "Поискайте подробности", + "details": "Детайли", "back": "Назад", "dashboard": "Табло", "settings": "Настройки", "filters": "Филтри", "filter": "Филтър", "query_log": "История на заявките", + "compact": "Compact", "faq": "ЧЗВ", "version": "версия", "address": "Адрес", @@ -60,7 +72,12 @@ "top_clients": "Най-активни IP адреси", "no_clients_found": "Нямa намерени адреси", "general_statistics": "Обща статисика", + "number_of_dns_query_24_hours": "Сума на DNS заявки за последните 24 часа", + "number_of_dns_query_blocked_24_hours": "Сума на блокирани DNS заявки от филтрите за реклама и местни", + "number_of_dns_query_blocked_24_hours_by_sec": "Сума на блокирани DNS заявки от AdGuard свързани със сигурността", + "number_of_dns_query_blocked_24_hours_adult": "Сума на блокирани сайтове за възрастни", "enforced_save_search": "Активирано Безопасно Търсене", + "number_of_dns_query_to_safe_search": "Сума на DNS заявки при който е приложено Безопасно Търсене", "average_processing_time": "Средно време за обработка", "average_processing_time_hint": "Средно време за обработка на DNS заявки в милисекунди", "block_domain_use_filters_and_hosts": "Блокирани домейни - общи и местни филтри", @@ -70,6 +87,7 @@ "use_adguard_parental": "Включи AdGuard Родителски Надзор", "use_adguard_parental_hint": "Модул XXX в AdGuard Home ще провери дали страницата има материали за възвъстни. Използва се същия API за анонимност като при модула за Сигурност.", "enforce_safe_search": "Включи Безопасно Търсене", + "enforce_save_search_hint": "AdGuard Home прилага Безопасно Търсене в следните търсачки и сайтове: Google, Youtube, Bing, и Yandex.", "no_servers_specified": "Няма избрани услуги", "general_settings": "Общи настройки", "custom_filtering_rules": "Местни правила за филтриране", @@ -106,10 +124,13 @@ "example_comment_hash": "# Това е също коментар", "example_regex_meaning": "блокирай достъп до домейни който съвпадат със следното", "example_upstream_regular": "класически DNS (UDP протокол)", + "example_upstream_udp": "обикновен DNS (върху UDP, име на хост);", "example_upstream_dot": "криптиран DNS-върху-TLS", "example_upstream_doh": "криптиран DNS-върху-HTTPS", "example_upstream_sdns": "може да ползвате DNS Подписване за DNSCrypt или DNS-върху-HTTPS сървъри", "example_upstream_tcp": "класически DNS (TCP протокол)", + "example_upstream_tcp_hostname": "обикновен DNS (върху TCP, име на хост);", + "updated_upstream_dns_toast": "Глобалните DNS сървъри са обновени", "dns_test_ok_toast": "Въведените DNS сървъри работят коректно", "dns_test_not_ok_toast": "Сървър \"{{key}}\": не работи, моля проверете дали е въведен коректно", "unblock": "Отблокирай", @@ -135,11 +156,13 @@ "rule_added_to_custom_filtering_toast": "Добавено до местни правила за филтриране: {{rule}}", "default": "По подразбиране", "custom_ip": "Персонализиран IP", + "dns_over_https": "DNS-пред-HTTPS", "dns_over_quic": "DNS-over-QUIC", "plain_dns": "Обикновен DNS", "source_label": "Източник", "found_in_known_domain_db": "Намерен в списъците с домейни.", "category_label": "Категория", + "rule_label": "Правило", "unknown_filter": "Непознат филтър {{filterId}}", "install_welcome_title": "Добре дошли в AdGuard Home!", "install_welcome_desc": "AdGuard Home e мрежово решение за блокиране на реклами и тракери на DNS ниво. Създадено е за да ви даде пълен контрол над мрежата и всичките ви устройства, без да е необходимо допълнително инсталиране на друг софтуер.", @@ -147,6 +170,7 @@ "install_settings_listen": "Активни интерфейси", "install_settings_port": "Порт", "install_settings_interface_link": "Вашата AdGuard Home страница за администрация ще е достъпна на този адрес:", + "form_error_port": "Моля въведете валиден порт", "install_settings_dns": "DNS сървър", "install_settings_dns_desc": "За да работи, ще трябва да настроите вашият рутер или устройства да ползват DNS сървър с адрес:", "install_settings_all_interfaces": "Всички интерфейси", @@ -165,6 +189,7 @@ "install_devices_router": "Рутер", "install_devices_router_desc": "Ако настроите вашият рутер няма нужда ръчно да настройвате всяко едно от устрйствата в мрежата.", "install_devices_address": "AdGuard Home DNS сървърът е на следния адрес", + "install_devices_router_list_1": "Отворете страницата за настройки на вашия рутер. Обикновено тя се намира на URL (тук http://192.168.0.1/ или тук http://192.168.1.1/). За достъп може да ви трябва парола. Ако сте забравили паролата може да я ресетнете като натиснета скрития ресет бутон - внимание това ще ресетне всички настройки на рутера до фабрични! Някой рутери могат да бъдате администрирани от софтуер или приложение, който би трябвало да е вече инсталиран на компютъра/телефона ви.", "install_devices_router_list_2": "Намерета DHCP/DNS настройки. В под раздел DHCP рзгледайте и намерете къде е полето за DNS настройка в което може да въведете персонализирани настройки за DNS сървъри.", "install_devices_router_list_3": "Въведете адресът на AdGuard Home сървъра.", "install_devices_windows_list_1": "Отворете Контролния Панел през Старт меню или чрез функция търсене на Windows.", @@ -192,8 +217,10 @@ "install_saved": "Успешно записано", "encryption_title": "Криптиране", "encryption_desc": "Подържа се сигурна връзка (HTTPS/TLS) включително за DNS и страницата за администрация", + "encryption_config_saved": "Конфигурацията е успешно записана", "encryption_server": "Име на сървъра", "encryption_server_enter": "Въведете име на домейна", + "encryption_server_desc": "За да използвате HTTPS, трябва името на сървъра да съвпада с това на SSL сертификата.", "encryption_redirect": "Автоматично пренасочване към HTTPS", "encryption_redirect_desc": "Служи за автоматично пренасочване от HTTP към HTTPS на страницата за Администрация в AdGuard Home.", "encryption_https": "HTTPS порт", @@ -219,7 +246,9 @@ "encryption_reset": "Сигурни ли сте че искате да изтриете настройките за криптиране?", "topline_expiring_certificate": "Вашият SSL сертификат изтича. Обнови <0>Настройки за криптиране.", "topline_expired_certificate": "Вашият SSL сертификат е изтекъл. Обнови <0>Настройки за криптиране.", + "form_error_port_range": "Въведете порт в диапазона 80-65535", "form_error_port_unsafe": "Не е безопасно да използвате този порт", + "form_error_equal": "Не трябва да съвпада", "form_error_password": "Паролата не съвпада", "reset_settings": "Изтрий всички настройки", "update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук за повече информация.", @@ -230,7 +259,11 @@ "name": "Име", "clients_not_found": "Нямa намерени адреси", "check_updates_now": "Провери за актуализации", + "interval_6_hour": "6 часа", + "interval_24_hour": "24 часа", "domain": "Домейн", + "ecs": "ECS", + "statistics_clear": "Нулирай статистиката", "disabled": "Деактивиран", "username_label": "Потребител", "username_placeholder": "Въведете потребител", @@ -238,11 +271,14 @@ "password_placeholder": "Въведете парола", "network": "Мрежа", "descr": "Описание", + "try_again": "Опитай пак", + "disable_ipv6": "Изключете IPv6 протокола", "show_blocked_responses": "Блокирано", "show_whitelisted_responses": "В белия списък", "show_processed_responses": "Обработен", "allowed": "В белия списък", "safe_search": "Безопасно търсене", + "blocklist": "Черен списък", "filter_category_general": "General", "filter_category_security": "Сигурност", "port_53_faq_link": "Порт 53 често е зает от \"DNSStubListener\" или \"systemd-resolved\" услуги. Моля, прочетете <0>тази инструкция как да решите това.", diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index 6f8ff803..be5666a8 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -274,8 +274,8 @@ "blocking_ipv4": "IPv4-Sperren", "blocking_ipv6": "IPv6-Sperren", "dnscrypt": "DNSCrypt", - "dns_over_https": "DNS-over-HTTPS (DNS-Abfrage über HTTPS)", - "dns_over_tls": "DNS-over-TLS (DNS-Abfrage über TLS)", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "dns_over_quic": "DNS-over-QUIC", "client_id": "Client-ID", "client_id_placeholder": "Client-ID eingeben", diff --git a/client/src/__locales/fa.json b/client/src/__locales/fa.json index d465b2bf..20cc372d 100644 --- a/client/src/__locales/fa.json +++ b/client/src/__locales/fa.json @@ -1,26 +1,50 @@ { "client_settings": "تنظیمات کلاینت", + "example_upstream_reserved": "میتوانید جریان ارسالی DNS <0> را برای یک دامنه مشخص تعیین کنید ", + "upstream_parallel": "استفاده از جستار موازی برای سرعت دادن به تفکیک با جستار همزمان همه جریان های ارسالی", "parallel_requests": "درخواست های موازی", "bootstrap_dns": "خودراه انداز سرورهای DNS", "bootstrap_dns_desc": "خودراه انداز سرورهای DNS برای تفکیک آدرس آی پی تفکیک کننده های DoH/DoT که شما بعنوان جریان ارسالی تعیین کردید استفاده میشود.", + "local_ptr_title": "سرورهای خصوصی DNS", + "local_ptr_desc": "سرور یا سرور های DNS ای که AdGuard Home برای درخواست های منابع محلی ارائه شده مورد استفاده قرار خواهد داد. برای مثال، این سرور برای تعیین نام های سرویس دهنده برای سرویس گیرنده با آدرس های آی پی خصوصی مورد استفاده قرار خواهد گرفت. اگر تعیین نشود،AdGuard Home به طور خودکار از تعیین کننده ی DNS پیش فرض شما استفاده خواهد کرد.", + "local_ptr_default_resolver": "به طور پیش فرض، AdGuard Home از تعیین کننده های DNS معکوس زیر استفاده می کند: {{ip}}.", + "local_ptr_no_default_resolver": "AdGuard Home نتوانست برای این دستگاه تعیین کننده های DNS معکوس محرمانه مناسب را معین کند.", + "local_ptr_placeholder": "در هر خط یک آدرس سرور را وارد کنید", + "resolve_clients_title": "فعال سازی تعیین نام های سرویس دهنده ی سرویس گیرندگان", + "resolve_clients_desc": "در صورت فعال بودن،AdGuard Home به طور خودکار اقدام به تعیین نام های سرویس دهنده ی سرویس گیرندگان از آدرس های آی پی با ارسال یک درخواست PTR به یک تعیین کننده ی همتا خواهد کرد (سرور خصوصی DNS برای سرویس گیرندگان محلی،سرور مادر برای سرویس گیرندگان با آی پی عمومی).", + "use_private_ptr_resolvers_title": "از تعیین کننده های rDNS محرمانه استفاده کنید", + "use_private_ptr_resolvers_desc": "داده گیری های دی ان اس معکوس را برای آدرس های اینترنتی خدمات منظقه ای با استفاده از سرور های مادر اجرا کنید. چنانچه غیر فعال باشد،AdGuard Home با NXDOMAIN به همه چنین درخواست های PTR پاسخ می دهد به استثناء خدمات گیرنده های شناخته شده از طرف DHCP،/و غیره/هوست ها، و سایر.", "check_dhcp_servers": "بررسی برای سرورهای DHCP", + "save_config": "ذخیره پیکربندی", "enabled_dhcp": "سرور DHCP فعال شده است", "disabled_dhcp": "سرور DHCP غیرفعال شده است", "dhcp_title": "سرور DHCP", "dhcp_description": "اگر روتر شما تنظیمات DHCP ارائه نمی کند،میتوانید از سرور DHCP تو-کار خود AdGuard استفاده کنید.", "dhcp_enable": "فعالسازی سرور DHCP", "dhcp_disable": "غیرفعالسازی سرور DHCP", + "dhcp_not_found": "سرورهای فعال DHCP در شبکه یافت نشد.فعالسازی سرور DHCP تو-کار اَمن است.", "dhcp_found": "تعدادی سرور DHCP فعال در شبکه یافت شد.فعالسازی سرور DHCP توکار اَمن نیست.", "dhcp_leases": "اجاره DHCP", "dhcp_static_leases": "اجاره DHCP ایستا", "dhcp_leases_not_found": "اجاره DHCP یافت نشد", + "dhcp_config_saved": "پیکربندی سرور DHCP ذخیره شده است", "form_error_required": "فیلد مورد نیاز", "form_error_ip4_format": "فرمت نامعتبر IPv4", + "form_error_ip4_range_start_format": "قالب IPv4 شروع دامنه نامعتبر است", + "form_error_ip4_range_end_format": "قالب IPv4 پایان دامنه نامعتبر است", + "form_error_ip4_gateway_format": "قالب IPv4 درگاه نامعتبر است", "form_error_ip6_format": "فرمت نامعتبر IPv6", - "form_error_ip_format": "آدرس آی پی نامعتبر است", + "form_error_ip_format": "فرمت IPv4 نامعتبر است", "form_error_mac_format": "فرمت مَک نامعتبر است", "form_error_client_id_format": "فرمت شناسه کلاینت نامعتبر است", + "form_error_subnet": "زیرشبکه\"{{cidr}}\"آدرس آی پی {{ip}} را در بر ندارد", "form_error_positive": "باید بزرگتر از 0 باشد", + "out_of_range_error": "باید خارج از دامنه باشد\"{{start}}\"-\"{{end}}\"", + "lower_range_start_error": "باید کمتر از شروع دامنه باشد", + "greater_range_start_error": "باید بیشتر از شروع دامنه باشد", + "greater_range_end_error": "باید بیشتر از پایان دامنه باشد", + "subnet_error": "آدرس ها باید در یک زیرشبکه باشند", + "gateway_or_subnet_invalid": "پوشش زیرشبکه نامعتبر است", "dhcp_form_gateway_input": "آی پی دروازه", "dhcp_form_subnet_input": "ماسک زیر شبکه", "dhcp_form_range_title": "دامنه آدرس های آی پی", @@ -34,11 +58,19 @@ "ip": "IP", "dhcp_table_hostname": "نام میزبان", "dhcp_table_expires": "انقضاء", + "dhcp_warning": "اگر میخواهید DHCP سرور توکار را فعال کنید،مطمئن شوید DHCP سرور دیگری فعال نباشد.در غیر اینصورت،آن دسترسی به اینترنت را برای دستگاه های وصل شده قطع می کند!", + "dhcp_error": "ما نمیتوانیم تشخیص دهیم آیا یک سرور DHCP دیگر در شبکه موجود است یا نه.", + "dhcp_static_ip_error": "به منظور استفاده از سرور DHCP یک آدرس آی پی ثابت باید تنظیم شود.ما موفق به تشخیص اینکه آیا رابط این شبکه برای استفاده از آی پی ثابت تنظیم شده است یا نه موفق نشدیم.لطفا آدرس آی پی ثابت را دستی تنظیم کنید.", + "dhcp_dynamic_ip_found": "سیستم شما آدرس آی پی متغییر برای این رابط استفاده می کند <0>{{interfaceName}}. به منظور استفاده از سرور DHCP آدرس ثابت باید تعیین شود. آدرس آی پی فعلی شما هست <0>{{ipAddress}}. اگر شما دکمه DHCP را فشار دهید ما این آدرس آی پی را بعنوان ثابت تنظیم می کنیم.", "dhcp_lease_added": "اجاره ایستا \"{{key}}\" با موفقیت اضافه شد", "dhcp_lease_deleted": "اجاره ایستا \"{{key}}\" با موفقیت حذف شد", "dhcp_new_static_lease": "اجاره ایستا جدید", "dhcp_static_leases_not_found": "هیچ اجاره DHCP ایستا یافت نشد", "dhcp_add_static_lease": "افزودن اجاره ایستا", + "dhcp_reset_leases": "بازگردانی همه مجوزهای منابع", + "dhcp_reset_leases_confirm": "آیا می خواهید تمام مجوزهای منابع را بازگردانی کنید؟", + "dhcp_reset_leases_success": "مجوزهای منابع DHCP با موفقیت بازگردانی شد", + "dhcp_reset": "آیا میخواهید پیکربندی DHCP را ریست کنید؟", "country": "کشور", "city": "شهر", "delete_confirm": "آیا میخواهید \"{{key}}\" را حذف کنید؟", @@ -54,6 +86,7 @@ "filters": "فيلترها", "filter": "فیلتر", "query_log": "جستار وقایع", + "compact": "فشرده", "nothing_found": "هیچ چیز یافت نشد", "faq": "پرسش و پاسخ", "version": "نسخه", @@ -78,13 +111,22 @@ "for_last_24_hours": "برای 24 ساعت گذشته", "for_last_days": "برای {{count}} روز آخر", "for_last_days_plural": "برای {{count}} روز گذشته", + "stats_disabled": "آمار غیرفعال شده است. شما می توانید از قسمت <0>صفحه تنظیمات آن را روشن نمایید.", + "stats_disabled_short": "آمار غیرفعال شده است", "no_domains_found": "دامنه یافت نشد", "requests_count": "تعداد درخواست ها", "top_blocked_domains": "دامنه های بیشتر مسدود شده", "top_clients": "بالاترین کلاینت ها", "no_clients_found": "کلاینتی یافت نشد", "general_statistics": "آمار عمومی", + "number_of_dns_query_days": "تعداد جستار DNS پردازش شده در {{count}} روز آخر", + "number_of_dns_query_days_plural": "تعداد جستار DNS پردازش شده در {{count}} روز گذشته", + "number_of_dns_query_24_hours": "تعداد جستار DNS پردازش شده در 24 ساعت گذشته", + "number_of_dns_query_blocked_24_hours": "تعداد درخواست DNS مسدود شده با فیلترهای مسدودساز تبلیغ و لیست سیاه میزبان", + "number_of_dns_query_blocked_24_hours_by_sec": "تعداد درخواست DNS مسدود شده با مدل امنیت وب گردی AdGuard", + "number_of_dns_query_blocked_24_hours_adult": "تعداد وبسایت های غیر اخلاقی مسدود شده", "enforced_save_search": "جستجوی اَمن اجبار شده", + "number_of_dns_query_to_safe_search": "تعداد درخواست های DNS برای موتور جستجو که جستجوی اَمن اجبار شده", "average_processing_time": "میانگین زمان پردازش", "average_processing_time_hint": "زمان میانگین بر هزارم ثانیه در پردازش درخواست DNS", "block_domain_use_filters_and_hosts": "مسدودسازی دامنه ها توسط فیلترها و فایل های میزبان", @@ -94,6 +136,7 @@ "use_adguard_parental": "از سرویس وب نظارت والدین AdGuard استفاده کن", "use_adguard_parental_hint": "AdGuard Home بررسی می کند اگر دامنه حاوی موارد غیر اخلاقی است.آن از همان اِی پی آی دارای حریم خصوصی سرویس وب امنیت وب گردی استفاده می کند.", "enforce_safe_search": "اجبار جستجوی اَمن", + "enforce_save_search_hint": "AdGuard Home میتواند جستجوی اَمن را در موتور جستجوهای زیر اعمال کند:گوگل،یوتوب،بینگ و یاندکس", "no_servers_specified": "سروری تعیین نشده است", "general_settings": "تنظیمات عمومی", "dns_settings": "تنظیمات DNS", @@ -145,6 +188,7 @@ "form_error_url_or_path_format": "آدرس نامعتبر یا یک مسیر کامل لیست", "custom_filter_rules": "دستورات فیلترینگ دستی", "custom_filter_rules_hint": "یک دستور در خط وارد کنید.میتوانید از دستورات مسدودساز تبلیغ یا نحو فایل های میزبان استفاده کنید.", + "system_host_files": "فایل های هوست سیستم", "examples_title": "مثال ها", "example_meaning_filter_block": "مسدودسازی دسترسی به دامنه example.org و همه زیر دامنه ها آن", "example_meaning_filter_whitelist": "بازکردن دسترسی به دامنه example.org و همه زیر دامنه ها آن", @@ -159,6 +203,7 @@ "example_upstream_sdns": "شما میتوانید از DNS Stamps برای DNSCrypt یا DNS-over-HTTPS resolvers استفاده کنید", "example_upstream_tcp": "DNS عادی (بر TCP)", "all_lists_up_to_date_toast": "همه لیست ها از قبل بروز اند", + "updated_upstream_dns_toast": "سرورهای DNS جریان ارسالی بروز رسانی شده است", "dns_test_ok_toast": "سرورهای DNS تعیین شده بدرستی کار می کنند", "dns_test_not_ok_toast": "سرور \"{{key}}\": نمیتواند مورد استفاده قرار گیرد،لطفا بررسی کنید آن را بدرستی نوشته اید", "unblock": "رفع انسداد", @@ -169,6 +214,7 @@ "domain_or_client": "دامنه یا کلاینت", "type_table_header": "نوع", "response_table_header": "پاسخ", + "response_code": "کد پاسخ", "client_table_header": "کلاینت", "empty_response_status": "خالی", "show_all_filter_type": "نمایش همه", @@ -187,6 +233,7 @@ "query_log_filtered": "فیلتر شده با {{filter}}", "query_log_confirm_clear": "آیا واقعا میخواهید کل وقایع جستار را پاک کنید؟", "query_log_cleared": "وقایع جستار با موفقیت پاک شد", + "query_log_updated": "فیلتر با موفقیت بروز رسانی شد", "query_log_clear": "پاکسازی وقایع جستار", "query_log_retention": "حفظ وقایع جستار برای", "query_log_enable": "فعالسازی وقایع", @@ -212,15 +259,19 @@ "rate_limit": "میزان محدودیت", "edns_enable": "فعالسازی زیرشبکه کلاینت EDNS", "edns_cs_desc": "اگر فعال باشد،AdGuard Home زیرشبکه های کلاینت ها را به سرورهای DNS می فرستد.", + "rate_limit_desc": "تعداد درخواست های بر ثانیه مجازی که یک کلاینت میتواند بسازد (0: نامحدود)", "blocking_ipv4_desc": "آدرس آی پی برگشت داده شده برای درخواست مسدود شده A", "blocking_ipv6_desc": "آدرس آی پی برگشت داده شده برای درخواست مسدود شده AAAA", + "blocking_mode_default": "پیش فرض: وقتی مسدود شود با دستور سبک-مسدودساز تبلیغ REFUSED پاسخ میدهد،پاسخ با آدرس آی پی تعیین شده در دستور وقتی با دستور /etc/hosts-style rule مسدود شود", "blocking_mode_nxdomain": "NXDOMAIN: پاسخ با کُد NXDOMAIN", "blocking_mode_null_ip": "Null IP: پاسخ با آدرس آی پی صفر(0.0.0.0 برای A; :: برای AAAA)", "blocking_mode_custom_ip": "آی پی دستی: پاسخ با آدرس آی پی دستی تنظیم شده", "upstream_dns_client_desc": "اگر این فیلد را خالی نگه دارید، AdGuard Home از سرور پیکربندی شده در <0> تنظیماتDNS استفاده می کند.", + "tracker_source": "منبع ردیاب", "source_label": "منبع", "found_in_known_domain_db": "در پایگاه داده دامنه های شناخته شده پیدا شد", "category_label": "دسته بندی", + "rule_label": "دستور", "list_label": "لیست", "unknown_filter": "فیلتر ناشناخته {{filterId}}", "known_tracker": "ردیاب های شناخته شده", @@ -230,6 +281,7 @@ "install_settings_listen": "رابط گوش دادن", "install_settings_port": "پورت", "install_settings_interface_link": "رابط صفحه وب آدمین AdGuard Home شما در این آدرس قابل دسترسی خواهد بود:", + "form_error_port": "مقدار پورت معتبر وارد کنید", "install_settings_dns": "سرور DNS", "install_settings_dns_desc": "نیاز است شما دستگاه یا روتر خود را برای استفاده از سرور DNS روی آدرس های زیر پیکربندی کنید:", "install_settings_all_interfaces": "همه رابط ها", @@ -248,8 +300,10 @@ "install_devices_router": "روتر", "install_devices_router_desc": "این راه انداز خودکار همه دستگاه های متصل شده به روتر خانه را پوشش میدهد و نیازی نیست شما هر یک از آنها را دستی پیکربندی کنید.", "install_devices_address": "DNS سرور AdGuard Home به آدرس های زیر گوش میدهد", + "install_devices_router_list_1": "اولویت ها را برای روتر خود باز کنید.معمولا میتوانید آن را ز طریق مرورگر از طریق آدرسی مانند ( http://192.168.0.1/ یا http://192.168.1.1/) دسترسی داشته باشید.ممکن است رمزعبور پرسیده شود،اگر آن را بخاطر ندارید،غالبا میتوان رمزعبور را با فشردن دکمه پشت روتر ریست کرد.برخی روترها برنامه خاصی نیاز دارد که باید در رایانه/گوشی نصب شده باشد.", "install_devices_router_list_2": "تنظیمات DHCP/DNS را بیابید.دنبال حروف DNS بگردید در فیلدی که اجازه دو یا سه گروه عدد را میدهد و هر کدام در چهار گروه سه عددی شکسته شده است", "install_devices_router_list_3": "آدرس سرور AdGuard Home خود را آنجا وارد کنید", + "install_devices_router_list_4": "شما نمیتوانید DNS سرور سفارشی در برخی از روترها تنظیم کنید. در این مورد اگر شما AdGuard Home را بعنوان DHCP سرور راه اندازی کنید میتواند کمک کند. در غیر اینصورت باید راهنمای سفارشی سازی DNS سرورها برای مدل خاص روتر خود را انتخاب کنید.", "install_devices_windows_list_1": "کنترل پنل را از طریق استارت منو یا جستجوی ویندوز باز کنید.", "install_devices_windows_list_2": "بروید به شبکه و دسته اینترنت و سپس به شبکه و مرکز اشتراک گذاری", "install_devices_windows_list_3": "در سمت چپ صفحه تنظیمات آداپتور را تغییر داده و روی آن کلیک کنید", @@ -275,8 +329,10 @@ "install_saved": "با موفقیت ذخیره نشد", "encryption_title": "رمزگُذاری", "encryption_desc": "پشتیبانی رمزگُذاری (HTTPS/TLS) برای DNS و رابط آدمین وب", + "encryption_config_saved": "پیکربندی رمزگذاری ذخیره شد", "encryption_server": "نام سرور", "encryption_server_enter": "نام دامنه خود را وارد کنید", + "encryption_server_desc": "به منظور استفاده از HTTPS،شما باید نام سرور مطابق با گواهینامه اِس اِس اِل را وارد کنید.", "encryption_redirect": "تغییر مسیر خودکار به HTTPS", "encryption_redirect_desc": "اگر انتخاب شده باشد،AdGuard Home خودکار شما را از آدرس HTTP به HTTPS منتقل می کند", "encryption_https": "پورت HTTPS", @@ -302,10 +358,13 @@ "encryption_reset": "آیا میخواهید تنظیمات رمزگُذاری به پیش فرض بازگردد؟", "topline_expiring_certificate": "گواهینامه اِس اِس اِل شما در صدد انقضاء است. <0>تنظیمات رمزگُذاری را بروز رسانی کنید.", "topline_expired_certificate": "گواهینامه اِس اِس اِل شما منقضی شده است. <0>تنظیمات رمزگُذاری را بروز رسانی کنید.", + "form_error_port_range": "مقدار پورت را در محدوده 80-65535 وارد کنید", "form_error_port_unsafe": "این پورت غیر ایمن است", + "form_error_equal": "نباید برابر باشد", "form_error_password": "رمزعبور تطبیق ندارد", "reset_settings": "ریست تنظیمات", "update_announcement": "AdGuard Home {{version}} در دسترس است! <0>اینجا کلیک کنید برای اطلاعات بیشتر.", + "setup_guide": "راهنمای راه اندازی", "dns_addresses": "آدرس های DNS", "dns_start": "سرور DNS در حال شروع است", "dns_status_error": "خطا در دریافت وضعیت DNS", @@ -314,6 +373,7 @@ "dns_providers": "در اینجا یک <0>لیست از سرویس های ارائه دهنده DNS برای انتخاب هست.", "update_now": "حالا بروز رسانی", "update_failed": "بروز رسانی خودکار موفق نشد. لطفا مراحل را دنبال کرده تا بطور دستی بروز رسانی کنید.", + "manual_update": "لطفااین مراحل را دنبال کنیدتا به طور دستی بروزرسانی نمایید.", "processing_update": "منتظر بمانید،AdGuard Home در حال بروز رسانی است", "clients_title": "کلاینت ها", "clients_desc": "پیکربندی دستگاه های متصل شده به AdGuard Home", @@ -327,7 +387,9 @@ "client_edit": "ویرایش کلاینت", "client_identifier": "احراز با", "ip_address": "آدرس آی پی", + "client_identifier_desc": "کلاینت میتواند با آدرس آی پی یا آدرس مَک احراز شود. لطفا توجه کنید،که استفاده از مَک بعنوان عامل احراز زمانی امکان دارد که AdGuard Home نیز <0>سرور DHCP باشد", "form_enter_ip": "آی پی را وارد کنید", + "form_enter_subnet_ip": "یک آدرس آی پی در زیر شبکه \"{{cidr}}\" وارد کنید", "form_enter_mac": "مَک را وارد کنید", "form_enter_id": "خطای احرازکننده", "form_add_id": "افزودن احرازکننده", @@ -349,6 +411,7 @@ "access_disallowed_title": "کلاینت های غیرمجاز", "access_disallowed_desc": "یک لیست از CIDR یا آدرس های IP.اگر پیکربندی شود،AdGuard Home درخواست ها را از این آدرس های IP نمی پذیرد.", "access_blocked_title": "دامنه های مسدود شده", + "access_blocked_desc": "این را با فیلتر ها به اشتباه نگیرید.AdGuard Home جستار DNS را با این دامنه ها در جستار سوال ها نمی پذیرد.", "access_settings_saved": "تنظیمات دسترسی با موفقیت ذخیره شد", "updates_checked": "بروز رسانی با موفقیت بررسی شد", "updates_version_equal": "AdGuard Home بروز است", @@ -356,6 +419,7 @@ "dns_privacy": "حریم خصوصی DNS", "setup_dns_privacy_1": "<0>DNS-over-TLS: استفاده از<1>{{address}} .", "setup_dns_privacy_2": "<0>DNS-over-HTTPS: استفاده از <1>{{address}} .", + "setup_dns_privacy_3": "<0>لطفا توجه کنید که پروتکل های رمزگذاری شده DNS فقط در آندروئید 9 پشتیبانی می شود. پس برای سیستم عامل های دیگر نیاز است که برنامه دیگری نصب کنید.<0>در اینجا میتوانید لیست نرم افزارهای قابل استفاده را ببینید.", "setup_dns_privacy_android_1": "آندروئید 9 بطور پیش فرض از DNS-over-TLS پشتیبانی می کند. برای پیکربندی آن، بروید به تنظیمات → شبکه & اینترنت → پیشرفته → DNS خصوصی و نام دامنه را آنجا وارد کنید.", "setup_dns_privacy_android_2": "<0>AdGuard for Android پشتیبانی از <1>DNS-over-HTTPS و <1>DNS-over-TLS.", "setup_dns_privacy_android_3": "<0>Intra قابلیت <1>DNS-over-HTTPS را به آندروئید اضافه می کند.", @@ -410,10 +474,11 @@ "statistics_configuration": "پیکربندی آمارها", "statistics_retention": "مدت حفظ آمارها", "statistics_retention_desc": "اگر مقدار فاصله را کاهش دهید،برخی داده ها از بین خواهد رفت", - "statistics_clear": "بازنشانی آمار", + "statistics_clear": " پاکسازی آمار", "statistics_clear_confirm": "آیا واقعا میخواهید آمار را پاک کنید؟", "statistics_retention_confirm": "آیا واقعا میخواهید مدت حفظ آمار را تغییر دهید؟ اگر فاصله را کاهش دهید، برخی داده ها حذف میشود", "statistics_cleared": "آمارها با موفقیت حذف شد", + "statistics_enable": "فعالسازی داده های آماری", "interval_hours": "{{count}} ساعت", "interval_hours_plural": "{{count}} ساعت", "filters_configuration": "پیکربندی فیلترها", @@ -440,7 +505,10 @@ "domain_desc": "نامه دامنه یا علامت تطبیقی را برای بازنویسی وارد کنید.", "example_rewrite_domain": "فقط بازنویسی پاسخ برای این دامنه.", "example_rewrite_wildcard": "بازنویسی پاسخ ها برای همه زیردامنه های <0>example.org.", + "disable_ipv6": "غیرفعالسازی IPv6", + "disable_ipv6_desc": "اگر این ویژگی فعال شده، همه جستارهای DNS برای آدرس های IPv6 (نوع AAAA) رها میشود.", "fastest_addr": "سریعترین آدرس آی پی", + "fastest_addr_desc": "جستار همه سرورهای DNS و بازگرداندن سریعترین آدرس IP از میان همه پاسخ ها", "autofix_warning_text": "اگر روی \"تعمیر\" کلیک کنید، AdGuardHome سیستم شما را برای استفاده از DNS سرور AdGuardHome پیکربندی می کند.", "autofix_warning_list": "این وظایف را اجرا میکند: <0>غیرفعالسازی DNSStubListener سیستم <0>تنظیم آدرس DNS 127.0.0.1 سرور به <0>جایگزینی لینک نمادی هدف /etc/resolv.conf به/run/systemd/resolve/resolv.conf <0>توقف DNSStubListener (بارگیری مجدد سرویس systemd-resolved)", "autofix_warning_result": "در نتیجه همه درخواست های DNS از سیستم شما بطور پیش فرض با AdGuardHome پردازش خواهد شد.", @@ -467,6 +535,7 @@ "set_static_ip": "تنظیم یک آدرس آی پی ثابت", "install_static_ok": "خبر خوب! آدرس آی پی ثابت از قبل پیکربندی شده است", "install_static_error": "AdGuard Home نمیتواند رابط این شبکه را خودکار پیکربندی کند. لطفا دستورالعمل چگونگی انجام دستی آن را مطالعه کنید.", + "install_static_configure": "ما تشخیص دادیم از آدرس آی پی پویا استفاده شده است — <0>{{ip}}. آیا میخواهید از آن بعنوان آدرس ثابت استفاده کنید؟", "confirm_static_ip": "AdGuard Home {{ip}} بعنوان آدرس آی پی ثابت شما پیکربندی می کند. ادامه میدهید؟", "list_updated": "{{count}} لیست بروز رسانی شد", "list_updated_plural": "{{count}} لیست بروز رسانی شد", @@ -477,16 +546,21 @@ "show_whitelisted_responses": "لیست سفید", "show_processed_responses": "پردازش شده", "blocked_safebrowsing": "بستن وب گردی اَمن", - "blocked_adult_websites": "مسدود شده با نظارت والدین", + "blocked_adult_websites": "وبسایت غیراخلاقی مسدود شده", "blocked_threats": "تهدیدات مسدود شده", "allowed": "اجازه داده شده", "filtered": "فیلتر شده", "rewritten": "بازنویسی شده", - "safe_search": "فعالسازی جستجوی اَمن", + "safe_search": "جستجوی اَمن", "blocklist": "لیست سیاه", "milliseconds_abbreviation": "هـ ثـ", + "cache_optimistic": "حالت ویژه پردازش", + "cache_optimistic_desc": "AdGuard Home را وادار می کند که از سمت حافظه پنهان پاسخ دهد حتی وقتی که موارد وارد شده منقضی شده باشد و همچنین سعی بر تازه کردن آنها می کند.", "filter_category_general": "General", "filter_category_security": "مسدودسازی بدافزار و فیشینگ", "filter_category_other": "ساير", - "parental_control": "نظارت والدین" + "use_saved_key": "از کلید ذخیره شده قبلی استفاده کنید", + "parental_control": "نظارت والدین", + "safe_browsing": "وب گردی اَمن", + "form_error_password_length": "رمزعبور باید حداقل {{value}} کاراکتر باشد." } diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index 990f4b09..7fc19d73 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -126,7 +126,7 @@ "top_blocked_domains": "Top geblokkeerde domeinen", "top_clients": "Top gebruikers", "no_clients_found": "Geen gebruikers gevonden", - "general_statistics": "Generieke statistieken", + "general_statistics": "Algemene statistieken", "number_of_dns_query_days": "Aantal verwerkte DNS aanvragen van de laatste {{count}} dag", "number_of_dns_query_days_plural": "Aantal verwerkte DNS aanvragen van de laatste {{count}} dagen", "number_of_dns_query_24_hours": "Aantal verwerkte DNS aanvragen van de laatste 24 uur", @@ -137,7 +137,7 @@ "number_of_dns_query_to_safe_search": "Aantal DNS aanvragen in zoekmachines dmv geforceerd veilig zoeken", "average_processing_time": "Gemiddelde procestijd", "average_processing_time_hint": "Gemiddelde verwerkingstijd in milliseconden van een DNS aanvraag", - "block_domain_use_filters_and_hosts": "Blokkeerd domeinen dmv filters en host bestanden", + "block_domain_use_filters_and_hosts": "Domeinen blokkeren d.m.v. filters en host-bestanden", "filters_block_toggle_hint": "Je kan blokkeringsregels toevoegen in de Filters instellingen.", "use_adguard_browsing_sec": "Gebruik AdGuardBrowsing Security web service", "use_adguard_browsing_sec_hint": "AdGuard Home controleert of het domein in de blokkeerlijst voorkomt dmv Browsing Security web service. Dit gebeurt dmv een privacy vriendelijk API verzoek:een korte prefix van de domein naam met SHA256 hash wordt verzonden naar de server.", @@ -146,15 +146,15 @@ "enforce_safe_search": "Veilig zoeken gebruiken", "enforce_save_search_hint": "AdGuard Home kan veilig zoeken forceren voor de volgende zoekmachines: Google, Youtube, Bing, en DuckDuckGo, Yandex, Pixabay.", "no_servers_specified": "Geen servers gespecificeerd", - "general_settings": "Generieke instellingen", - "dns_settings": "DNS Instellingen", + "general_settings": "Algemene instellingen", + "dns_settings": "DNS instellingen", "dns_blocklists": "DNS blokkeerlijsten", "dns_allowlists": "DNS toestemmingslijsten", "dns_blocklists_desc": "AdGuard Home zal domeinen blokkeren die voorkomen in de blokkeerlijsten.", "dns_allowlists_desc": "Domeinen in de DNS toestemmingslijsten worden toegestaan zelfs al komen ze voor in de blokkeerlijsten.", "custom_filtering_rules": "Aangepaste filter regels", - "encryption_settings": "Encryptie Instellingen", - "dhcp_settings": "DHCP Instellingen", + "encryption_settings": "Encryptie instellingen", + "dhcp_settings": "DHCP instellingen", "upstream_dns": "Upstream DNS-servers", "upstream_dns_help": "Een server-adres per regel invoeren. Meer weten over het configureren van upstream DNS-servers.", "upstream_dns_configured_in_file": "Geconfigureerd in {{path}}", @@ -225,8 +225,8 @@ "block": "Blokkeren", "disallow_this_client": "Toepassing/systeem niet toelaten", "allow_this_client": "Toepassing/systeem toelaten", - "block_for_this_client_only": "Alleen voor deze toepassing/dit systeem blokkeren", - "unblock_for_this_client_only": "Alleen voor deze toepassing/dit systeem deblokkeren", + "block_for_this_client_only": "Alleen voor deze cliënt blokkeren", + "unblock_for_this_client_only": "Alleen voor deze cliënt deblokkeren", "time_table_header": "Tijd", "date": "Datum", "domain_name_table_header": "Domein naam", @@ -403,7 +403,7 @@ "down": "Uitgeschakeld", "fix": "Los op", "dns_providers": "hier is een <0>lijst of gekende DNS providers waarvan je kan kiezen.", - "update_now": "Update nu", + "update_now": "Nu bijwerken", "update_failed": "Automatisch bijwerken is mislukt. Volg deze stappen om handmatig bij te werken.", "manual_update": "Volg deze stappen om handmatig bij te werken.", "processing_update": "Even geduld, AdGuard Home wordt bijgewerkt", @@ -624,7 +624,7 @@ "original_response": "Oorspronkelijke reactie", "click_to_view_queries": "Klik om queries te bekijken", "port_53_faq_link": "Poort 53 wordt vaak gebruikt door services als DNSStubListener- of de systeem DNS-resolver. Lees a.u.b. <0>deze instructie hoe dit is op te lossen.", - "adg_will_drop_dns_queries": "AdGuard Home zal alle DNS verzoeken van deze toepassing/dit systeem negeren.", + "adg_will_drop_dns_queries": "AdGuard Home zal alle DNS-verzoeken van deze cliënt laten vervallen.", "filter_allowlist": "WAARSCHUWING: Deze actie zal ook de regel \"{{disallowed_rule}}\" uitsluiten van de lijst met toegestane clients.", "last_rule_in_allowlist": "Kan deze client niet weigeren omdat het uitsluiten van de regel \"{{disallowed_rule}}\" de lijst \"Toegestane clients\" zal UITSCHAKELEN.", "use_saved_key": "De eerder opgeslagen sleutel gebruiken", diff --git a/client/src/__locales/no.json b/client/src/__locales/no.json index b8f8bc63..0259d267 100644 --- a/client/src/__locales/no.json +++ b/client/src/__locales/no.json @@ -10,6 +10,10 @@ "bootstrap_dns_desc": "Bootstrap-DNS-tjenere brukes til å oppklare IP-adressene til DoH/DoT-oppklarerene som du har valgt som oppstrømstjenere.", "local_ptr_title": "Private DNS-tjenere", "local_ptr_desc": "DNS-tjenerne som AdGuard Home bruker for lokale PTR-spørringer. Disse tjenerne brukes til å løse vertsnavnene til klienter med private IP-adresser, for eksempel \"192.168.12.34\", ved bruk av omvendt DNS. Hvis det ikke er angitt, bruker AdGuard Home adressene til standard-DNS-løserne til operativsystemet ditt, bortsett fra adressene til selve AdGuard Home.", + "local_ptr_default_resolver": "Som standard, bruker AdGuard Home følgende revers-DNS-oppletere: {{ip}}.", + "local_ptr_no_default_resolver": "AdGuard Home klarte ikke å finne egnede private revers-DNS-oppletere for dette systemet.", + "local_ptr_placeholder": "Skriv inn én tjeneradresse per linje", + "resolve_clients_title": "Skru på revers-oppleting av klienters IP-adresser", "use_private_ptr_resolvers_title": "Bruk private omvendte DNS-løsere", "check_dhcp_servers": "Se etter DHCP-tjenere", "save_config": "Lagre oppsettet", @@ -21,20 +25,24 @@ "dhcp_description": "Dersom ruteren din ikke har DHCP-innstillinger, kan du bruke AdGuard Home sin egen innebygde DHCP-tjener.", "dhcp_enable": "Skru på DHCP-tjeneren", "dhcp_disable": "Skru av DHCP-tjeneren", + "dhcp_not_found": "Det er trygt å skru på den innebygde DHCP-tjeneren - vi kunne ikke finne noen aktive DHCP-tjenere i nettverket. Men vi oppfordrer deg til å dobbeltsjekke manuelt, siden vår automatiske test ikke gir 100% sikre svar ennå.", "dhcp_found": "En aktiv DHCP-tjener ble oppdaget i nettverket. Det er ikke trygt å bruke den innebygde DHCP-tjeneren.", "dhcp_leases": "DHCP-leieavtaler", "dhcp_static_leases": "Statiske DHCP-leieavtaler", "dhcp_leases_not_found": "Ingen DHCP-leieavtaler ble funnet", + "dhcp_config_saved": "Lagret DHCP-tjeneroppsettet", "dhcp_ipv4_settings": "DHCP IPv4-innstillinger", "dhcp_ipv6_settings": "DHCP IPv6-innstillinger", "form_error_required": "Påkrevd felt", "form_error_ip4_format": "Ugyldig IPv4-format", "form_error_ip6_format": "Ugyldig IPv6-format", - "form_error_ip_format": "Ugyldig IP-adresse", + "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_subnet": "Undernettet «{{cidr}}» inneholder ikke IP-adressen «{{ip}}»", "form_error_positive": "Må være høyere enn 0", + "greater_range_start_error": "Må være høyere enn rekkeviddens start", "dhcp_form_gateway_input": "Gateway-IP", "dhcp_form_subnet_input": "Nettverksmaske", "dhcp_form_range_title": "Spennvidden til IP-adressene", @@ -48,11 +56,16 @@ "ip": "IP-adresse", "dhcp_table_hostname": "Vertsnavn", "dhcp_table_expires": "Utløper", + "dhcp_warning": "Hvis du vil aktivere DHCP-tjeneren likevel, så sørg for at det ikke er noen andre aktive DHCP-tjenere i nettverket ditt. Ellers kan det knekke internettilgangen til tilkoblede enheter!", + "dhcp_error": "Vi klarte ikke å fastslå om det er en annen DHCP-tjener i nettverket ditt eller ikke.", + "dhcp_static_ip_error": "For å kunne bruke DHCP-tjeneren, må det være satt en statisk IP-adresse. Vi klarte ikke å finne ut om dette nettverksgrensesnittet har blitt satt opp med en statisk IP-adresse. Vennligst sett opp en statisk IP-adresse manuelt.", + "dhcp_dynamic_ip_found": "Systemet ditt bruker et oppsett med dynamisk IP-adresse for grensesnittet <0>{{interfaceName}}. For å kunne bruke DHCP-tjeneren, må en statisk IP-adresse ha blitt satt opp. Din nåværende IP-adresse er <0>{{ipAddress}}. Vi vil automatisk gjøre denne IP-adressen statisk hvis du trykker på «Skru på DHCP»-knappen.", "dhcp_lease_added": "Den statiske leieavtalen «{{key}}» ble vellykket lagt til", "dhcp_lease_deleted": "Den statiske leieavtalen «{{key}}» ble vellykket lagt slettet", "dhcp_new_static_lease": "Ny statisk leieavtale", "dhcp_static_leases_not_found": "Ingen statiske DHCP-leieavtaler ble funnet", "dhcp_add_static_lease": "Legg til statisk leieavtale", + "dhcp_reset": "Er du sikker på at du vil tilbakestille DHCP-oppsettet?", "country": "Land", "city": "By", "delete_confirm": "Er du sikker på at du vil slette «{{key}}»?", @@ -93,13 +106,22 @@ "for_last_24_hours": "de siste 24 timene", "for_last_days": "det siste døgnet", "for_last_days_plural": "de siste {{count}} dagene", + "stats_disabled": "Statistikkene har blitt skrudd av. Du kan skru den på fra <0>innstillingssiden.", + "stats_disabled_short": "Statistikkene har blitt skrudd av", "no_domains_found": "Ingen domener ble funnet", "requests_count": "Antall forespørsler", "top_blocked_domains": "Mest blokkerte domener", "top_clients": "Vanligste klienter", "no_clients_found": "Ingen klienter ble funnet", "general_statistics": "Generelle statistikker", + "number_of_dns_query_days": "Antall DNS-forespørsler som ble behandlet det siste døgnet", + "number_of_dns_query_days_plural": "Antall DNS-forespørsler som ble behandlet de siste {{count}} dagene", + "number_of_dns_query_24_hours": "Antall DNS-forespørsler som ble behandlet de siste 24 timene", + "number_of_dns_query_blocked_24_hours": "Antall DNS-forespørsler som ble blokkert av adblock-filtre, hosts-lister, og domene-lister", + "number_of_dns_query_blocked_24_hours_by_sec": "Antall DNS-forespørsler som ble blokkert av AdGuard sin nettlesersikkerhetsmodul", + "number_of_dns_query_blocked_24_hours_adult": "Antall voksennettsteder som ble blokkert", "enforced_save_search": "Påtvungede barnevennlige søk", + "number_of_dns_query_to_safe_search": "Antall DNS-forespørsler til søkemotorer der \"Safe Search\" ble fremtvunget", "average_processing_time": "Gjennomsnittlig behandlingstid", "average_processing_time_hint": "Gjennomsnittstid for behandling av DNS-forespørsler i millisekunder", "block_domain_use_filters_and_hosts": "Blokker domener ved hjelp av filtre, «hosts»-filer, og rå domener", @@ -181,6 +203,7 @@ "example_upstream_sdns": "du kan bruke <0>DNS-stempler med <1>DNSCrypt eller <2>DNS-over-HTTPS-behandlere", "example_upstream_tcp": "vanlig DNS (over TCP)", "all_lists_up_to_date_toast": "Alle listene er allerede oppdatert", + "updated_upstream_dns_toast": "Oppdaterte oppstrøms-DNS-tjenerne", "dns_test_ok_toast": "De spesifiserte DNS-tjenerne fungerer riktig", "dns_test_not_ok_toast": "Tjeneren «{{key}}» kunne ikke brukes, vennligst dobbeltsjekk at du har skrevet den riktig", "unblock": "Tillat", @@ -241,13 +264,16 @@ "dns_over_quic": "DNS-over-QUIC", "client_id": "Klient-ID", "client_id_placeholder": "Skriv inn klient-ID", + "client_id_desc": "Forskjellige klienter kan identifiserer med en spesiell klient-ID. Her kan du lære mer om hvordan man identifiserer klienter.", "download_mobileconfig_doh": "Last ned .mobileconfig for DNS-over-HTTPS", "download_mobileconfig_dot": "Last ned .mobileconfig for DNS-over-TLS", + "download_mobileconfig": "Last ned oppsettsfil", "plain_dns": "Ordinær DNS", "form_enter_rate_limit": "Skriv inn forespørselsfrekvensgrense", "rate_limit": "Forespørselsfrekvensgrense", "edns_enable": "Aktiver EDNS-klientundernett", "edns_cs_desc": "Hvis det er skrudd på, vil AdGuard Home sende klientenes undernett til DNS-tjenerne.", + "rate_limit_desc": "Antallet forespørsler per sekund som én enkelt klient har lov til å be om (0: ubegrenset)", "blocking_ipv4_desc": "IP-adressen som det skal svares med for blokkerte A-forespørsler", "blocking_ipv6_desc": "IP-adressen som det skal svares med for blokkerte AAAA-forespørsler", "blocking_mode_default": "Standard: Svar med null-IP-adresse (0.0.0.0 for A; :: for AAAA) når den blokkeres av adblock-aktige oppføringer; svar med IP-adressen som er spesifisert i oppføringen når den blokkeres av /etc/hosts-typeoppføringer", @@ -289,8 +315,10 @@ "install_devices_router": "Ruter", "install_devices_router_desc": "Dette oppsettet vil automatisk dekke alle enhetene som er koblet til hjemmeruteren din, og du vil ikke måtte sette opp hver av dem manuelt.", "install_devices_address": "AdGuard Home-DNS-tjeneren lytter til de følgende adressene", + "install_devices_router_list_1": "Åpne innstillingene til ruteren din. Vanligvis kan du få tilgang til den på nettleseren din gjennom en URL (f.eks. http://192.168.0.1/ eller http://192.168.1.1/). Du kan bli spurt om å skrive inn passordet ditt. Hvis du ikke husker det, kan du som oftest tilbakestille passordet ditt ved å trykke på knapp på selve ruteren. Noen rutere krever et spesifikt program, som i så fall er ment å allerede ha blitt installert på din PC/mobil.", "install_devices_router_list_2": "Finn DHCP-/DNS-innstillingene. Se etter DNS-bokstavene ved siden av et felt som tillater to eller tre sett med sifre, som hver er delt opp i fire grupper på 1-3 sifre.", "install_devices_router_list_3": "Skriv inn din AdGuard Home-tjeners adresser her.", + "install_devices_router_list_4": "På noen rutertyper, f.eks. Altibox sine hjemmesentraler, kan man ikke velge en selvvalgt DNS-tjener. I så fall kan det hjelpe på saken om du setter opp AdGuard Home som en <0>DHCP-tjener. Alternativt, burde du se i bruksanvisningen til din spesifikke rutermodell om hvordan man tilpasser DNS-tjenerne.", "install_devices_windows_list_1": "Åpne «Kontrollpanel» gjennom Start-menyen eller et Windows-søk.", "install_devices_windows_list_2": "Gå til «Nettverk og internett»-kategorien, og så til «Nettverks- og delingssenter».", "install_devices_windows_list_3": "På den venstre siden av skjermen, finn «Endre innstillinger for nettverkskort» og klikk på den.", @@ -316,6 +344,7 @@ "install_saved": "Lagringen var vellykket", "encryption_title": "Kryptering", "encryption_desc": "Krypteringsstøtte (HTTPS/TLS) for både DNS og admin-nettgrensesnittet", + "encryption_config_saved": "Krypteringsoppsettet ble lagret", "encryption_server": "Tjenerens navn", "encryption_server_enter": "Skriv inn domenenavnet ditt", "encryption_server_desc": "For å kunne bruke HTTPS, må du skrive inn tjenernavnet som samsvarer med ditt SSL-sertifikat eller jokertegnsertifikat. Hvis feltet er tomt, vil den akseptere TLS-tilkoblinger til ethvert domene.", @@ -346,7 +375,9 @@ "encryption_reset": "Er du sikker på at du vil tilbakestille krypteringsinnstillingene?", "topline_expiring_certificate": "Ditt SSL-sertifikat er i ferd med å utløpe. Oppdater <0>Krypteringsinnstillinger.", "topline_expired_certificate": "SSL-sertifikatet har utløpt. Oppdater <0>Krypteringsinnstillinger.", + "form_error_port_range": "Skriv inn et portnummer i området 80-65535", "form_error_port_unsafe": "Denne porten er ikke trygg", + "form_error_equal": "Burde ikke være de samme", "form_error_password": "Passordet samsvarer ikke", "reset_settings": "Tilbakestill innstillinger", "update_announcement": "AdGuard Home {{version}} er nå tilgjengelig! <0>Klikk her for mere informasjon.", @@ -374,6 +405,7 @@ "ip_address": "IP-adresse", "client_identifier_desc": "Klienter kan bli identifisert gjennom IP-adressen, CIDR, MAC-adressen, eller en spesiell klient-ID (kan også brukes for DoT/DoH/DoQ). <0>Her kan du lære mer om å identifisere klienter.", "form_enter_ip": "Skriv inn IP", + "form_enter_subnet_ip": "Skriv inn en IP-adresse i undernettet «{{cidr}}»", "form_enter_mac": "Skriv inn MAC", "form_enter_id": "Skriv inn identifikator", "form_add_id": "Legg til identifikator", @@ -416,6 +448,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy støtter <1>DNS-over-HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox støtter <1>DNS-over-HTTPS.", "setup_dns_privacy_other_5": "Du finner flere implementeringer <0>her og <1>her.", + "setup_dns_privacy_ioc_mac": "iOS- og macOS-oppsett", "setup_dns_notice": "For å benytte <1>DNS-over-HTTPS eller <1>DNS-over-TLS, må du <0>sette opp Kryptering i AdGuard Home-innstillingene.", "rewrite_added": "DNS-omdirigeringen for «{{key}}» ble vellykket lagt til", "rewrite_deleted": "DNS-omdirigeringen for «{{key}}» ble vellykket slettet", @@ -453,6 +486,7 @@ "interval_days": "{{count}} dag", "interval_days_plural": "{{count}} dager", "domain": "Domene", + "punycode": "Punycode", "answer": "Svar", "filter_added_successfully": "Filteret har blitt vellykket lagt til", "filter_removed_successfully": "Listen ble vellykket fjernet", @@ -499,6 +533,7 @@ "disable_ipv6": "Skru av IPv6", "disable_ipv6_desc": "Hvis dette er skrudd på, vil alle DNS-forespørslene til IPv6-adresser (AAAA-type) bli droppet.", "fastest_addr": "Raskeste IP-adresse", + "fastest_addr_desc": "Forespør alle DNS-tjenerne og hent den raskeste IP-adressen blant alle svarene. Dette vil gjøre DNS-forespørslene tregere, siden vi må vente på svar fra alle DNS-tjenerne, men det vil forbedre tilkoblingen generelt.", "autofix_warning_text": "Hvis du klikker på «Fiks», vil AdGuard Home sette opp systemet ditt til å bruke 'AdGuard Home'-DNS-tjeneren.", "autofix_warning_list": "Den vil utføre disse handlingene: <0>Skru av systemets DNSStubListener <0>Sette DNS-tjeneradressen til 127.0.0.1 <0>Bytte ut det symbolske lenkemålet til /etc/resolv.conf med /run/systemd/resolve/resolv.conf <0>Stoppe DNSStubListener (gjeninnlast 'systemd-resolved'-tjenesten)", "autofix_warning_result": "Som følge av det vil alle DNS-forespørsler fra systemet ditt bli behandlet av AdGuard Home som standard.", @@ -528,6 +563,7 @@ "set_static_ip": "Velg en statisk IP-adresse", "install_static_ok": "Gode nyheter! Den statiske IP-adressen er allerede satt opp", "install_static_error": "AdGuard Home kan ikke sette opp automatisk i dette nettverksgrensesnitt. Vennligst let opp anvisningen for hvordan man gjør det manuellt.", + "install_static_configure": "Vi har oppdaget at det brukes en dynamisk IP-adresse — <0>{{ip}}. Vil du bruke det som din statiske adresse?", "confirm_static_ip": "AdGuard Home vil sette opp {{ip}} til å bli din statiske IP-adresse. Vil du fortsette?", "list_updated": "{{count}} liste oppdatert", "list_updated_plural": "{{count}} lister oppdatert", @@ -539,12 +575,12 @@ "show_whitelisted_responses": "Hvitelistet", "show_processed_responses": "Bearbeidet", "blocked_safebrowsing": "Blokkert av barnevennlig nettlesing", - "blocked_adult_websites": "Blokkert av foreldrekontroll", + "blocked_adult_websites": "Blokkerte voksennettsteder", "blocked_threats": "Blokkerte trusler", "allowed": "Unntak", "filtered": "Filtrert", "rewritten": "Omskrevet", - "safe_search": "Aktivert sikkert søk", + "safe_search": "Trygge søk", "blocklist": "Blokkeringsliste", "milliseconds_abbreviation": "ms", "cache_size": "Mellomlagerstørrelse", @@ -564,13 +600,16 @@ "filter_category_regional": "Regional", "filter_category_other": "Andre", "filter_category_general_desc": "Lister som blokkerer sporing og reklamer på de fleste enheter", + "filter_category_security_desc": "Lister som spesialiserer seg på å blokkere skadevare-, phishing- eller svindeldomener", "filter_category_regional_desc": "Lister som fokuserer på regionale reklamer og sporingstjenere", "filter_category_other_desc": "Andre blokkeringslister", + "setup_config_to_enable_dhcp_server": "Oppsett for å skru på DHCP-tjeneren", "original_response": "Opprinnelig svar", "click_to_view_queries": "Klikk for å vise forespørsler", "port_53_faq_link": "Port 53 er ofte opptatt av «DNSStubListener»- eller «systemd-resolved»-tjenestene. Vennligst les <0>denne instruksjonen om hvordan man løser dette.", "adg_will_drop_dns_queries": "AdGuard Home vil droppe alle DNS-forespørsler fra denne klienten.", "use_saved_key": "Bruk den tidligere lagrede nøkkelen", "parental_control": "Foreldrekontroll", + "safe_browsing": "Sikker surfing", "served_from_cache": "{{value}} (formidlet fra mellomlageret)" } diff --git a/client/src/__locales/ru.json b/client/src/__locales/ru.json index 214169fd..d439d0ff 100644 --- a/client/src/__locales/ru.json +++ b/client/src/__locales/ru.json @@ -198,7 +198,7 @@ "enter_valid_allowlist": "Добавьте действующий URL-адрес в белый список.", "form_error_url_format": "Неверный формат URL", "form_error_url_or_path_format": "Неверный URL или абсолютный путь к списку", - "custom_filter_rules": "Пользовательское правило фильтрации", + "custom_filter_rules": "Пользовательские правила фильтрации", "custom_filter_rules_hint": "Вводите по одному правилу на строчку. Вы можете использовать правила блокировки или синтаксис файлов hosts.", "system_host_files": "Системные hosts-файлы", "examples_title": "Примеры", @@ -475,7 +475,7 @@ "rewrite_applied": "Применено правило перезаписи", "rewrite_hosts_applied": "Переписано по правилу файла hosts", "dns_rewrites": "Перезапись DNS-запросов", - "form_domain": "Введите домен", + "form_domain": "Введите имя или маску домена", "form_answer": "Введите IP адрес или домен", "form_error_domain_format": "Некорректный домен", "form_error_answer_format": "Некорректный ответ", diff --git a/client/src/__locales/sv.json b/client/src/__locales/sv.json index 90ddd608..a107e8c7 100644 --- a/client/src/__locales/sv.json +++ b/client/src/__locales/sv.json @@ -1,7 +1,7 @@ { "client_settings": "Klientinställningar", - "example_upstream_reserved": "Du kan specificera DNS-uppström <0>för en specifik domän", - "example_upstream_comment": "Du kan ange en kommentar", + "example_upstream_reserved": "uppström <0>för en specifik domän;", + "example_upstream_comment": "du kan ange en kommentar.", "upstream_parallel": "Använd parallella förfrågningar för att snabba upp dessa genom att fråga alla uppströmsservrar samtidigt.", "parallel_requests": "Parallella förfrågningar", "load_balancing": "Lastbalansering", @@ -196,7 +196,7 @@ "choose_allowlist": "Välj frilistor", "enter_valid_blocklist": "Ange en giltig URL till blockeringslistan.", "enter_valid_allowlist": "Ange en giltig URL till frilistan.", - "form_error_url_format": "Ogiltigt URL format", + "form_error_url_format": "Ogiltigt URL-format", "form_error_url_or_path_format": "Ogiltig URL eller absolut sökväg till listan", "custom_filter_rules": "Egna filterregler", "custom_filter_rules_hint": "Skriv en regel per rad. Du kan använda antingen annonsblockeringsregler eller värdfilssyntax.", @@ -210,11 +210,13 @@ "example_comment_hash": "# Också en kommentar", "example_regex_meaning": "blockera åtkomst till domäner som matchar det angivna uttrycket", "example_upstream_regular": "vanlig DNS (över UDP)", + "example_upstream_udp": "vanlig DNS (över UDP, värdnamn);", "example_upstream_dot": "krypterat <0>DNS-over-TLS", "example_upstream_doh": "krypterat <0>DNS-over-HTTPS", - "example_upstream_doq": "krypterat <0>DNS-over-QUIC", + "example_upstream_doq": "krypterat <0>DNS-over-QUIC (experimentell);", "example_upstream_sdns": "Du kan använda <0>DNS-stamps för <1>DNSCrypt eller <2>DNS-over-HTTPS-resolvers", "example_upstream_tcp": "vanlig DNS (över UDP)", + "example_upstream_tcp_hostname": "vanlig DNS (över TCP, värdnamn);", "all_lists_up_to_date_toast": "Alla listor är redan uppdaterade", "updated_upstream_dns_toast": "Sparade uppströms dns-servrar", "dns_test_ok_toast": "Angivna DNS servrar fungerar korrekt", diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index 5aa53ec1..74dedd8b 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -388,7 +388,7 @@ "encryption_issuer": "Sağlayan", "encryption_hostnames": "Ana makine adları", "encryption_reset": "Şifreleme ayarlarını sıfırlamak istediğinizden emin misiniz?", - "topline_expiring_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını güncelleyin.", + "topline_expiring_certificate": "SSL sertifikanızın süresi sona üzere. <0>Şifreleme ayarlarını güncelleyin.", "topline_expired_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını güncelleyin.", "form_error_port_range": "80-65535 aralığında geçerli bir bağlantı noktası değeri girin", "form_error_port_unsafe": "Güvenli olmayan bağlantı noktası", @@ -489,9 +489,9 @@ "blocked_service": "Engellenen hizmet", "block_all": "Tümünü engelle", "unblock_all": "Tüm engellemeyi kaldır", - "encryption_certificate_path": "Sertifika yolu", + "encryption_certificate_path": "Sertifika dosya yolu", "encryption_private_key_path": "Özel anahtar yolu", - "encryption_certificates_source_path": "Sertifika dosyalarının yolunu belirleyin", + "encryption_certificates_source_path": "Bir sertifika dosyası yolu ayarlayın", "encryption_certificates_source_content": "Sertifika içeriğini yapıştır", "encryption_key_source_path": "Özel bir anahtar dosyası belirleyin", "encryption_key_source_content": "Özel anahtar içeriğini yapıştır", diff --git a/client/src/__locales/zh-tw.json b/client/src/__locales/zh-tw.json index 8b1fab72..666ddcc3 100644 --- a/client/src/__locales/zh-tw.json +++ b/client/src/__locales/zh-tw.json @@ -625,8 +625,8 @@ "click_to_view_queries": "點擊以檢視查詢", "port_53_faq_link": "連接埠 53 常被 \"DNSStubListener\" 或 \"systemd-resolved\" 服務佔用。請閱讀有關如何解決這個的<0>用法說明。", "adg_will_drop_dns_queries": "AdGuard Home 將持續排除來自此用戶端之所有的 DNS 查詢。", - "filter_allowlist": "警告:此操作將把 \"{{disallowed_rule}}\" 規則排除在已允許用戶端的清單之外。", - "last_rule_in_allowlist": "無法禁止此用戶端,因為排除 “{{disallowed_rule}}” 規則將禁用“已允許用戶端”的清單。", + "filter_allowlist": "警告:此動作也將把 \"{{disallowed_rule}}\" 規則排除在已允許的用戶端的清單之外。", + "last_rule_in_allowlist": "因為排除 \"{{disallowed_rule}}\" 規則將禁用\"已允許的用戶端\"清單,無法不允許此用戶端。", "use_saved_key": "使用該先前已儲存的金鑰", "parental_control": "家長控制", "safe_browsing": "安全瀏覽", From 12ee287d0b25cc1fb498e54c4484c995613e9bcb Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Tue, 19 Apr 2022 15:01:49 +0300 Subject: [PATCH 15/99] Pull request: 3157 excessive ptrs Merge in DNS/adguard-home from 3157-excessive-ptrs to master Updates #3157. Squashed commit of the following: commit 6803988240dca2f147bb80a5b3f78d7749d2fa14 Author: Eugene Burkov Date: Tue Apr 19 14:50:01 2022 +0300 aghnet: and again commit 1a7f4d1dbc8fd4d3ae620349917526a75fa71b47 Author: Eugene Burkov Date: Tue Apr 19 14:49:20 2022 +0300 aghnet: docs again commit d88da1fc7135f3cd03aff10b02d9957c8ffdfd30 Author: Eugene Burkov Date: Tue Apr 19 14:47:36 2022 +0300 aghnet: imp docs commit c45dbc7800e882c6c4110aab640c32b03046f89a Author: Eugene Burkov Date: Tue Apr 19 14:41:19 2022 +0300 aghnet: keep alphabetical order commit b61781785d096ef43f60fb4f1905a4ed3cdf7c68 Author: Eugene Burkov Date: Tue Apr 19 13:50:56 2022 +0300 aghnet: imp code quality commit 578dbd71ed2f2089c69343d7d4bf8bbc29150ace Author: Eugene Burkov Date: Tue Apr 12 17:02:38 2022 +0300 aghnet: imp arp container --- CHANGELOG.md | 5 +++++ internal/aghnet/arpdb_bsd.go | 13 +++++++++---- internal/aghnet/arpdb_linux.go | 19 ++++++++++++------- internal/aghnet/arpdb_openbsd.go | 15 ++++++++++----- internal/aghnet/arpdb_windows.go | 2 +- internal/dnsforward/dns.go | 1 - internal/dnsforward/recursiondetector_test.go | 14 ++++---------- internal/home/rdns.go | 11 +++++------ 8 files changed, 46 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a80b4ea1..9d82fb57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,10 +87,15 @@ In this release, the schema version has changed from 12 to 13. - Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. +### Fixed + +- ARP tables refreshing process causing excessive PTR requests ([#3157]). + [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 [#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993 [#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057 [#3142]: https://github.com/AdguardTeam/AdGuardHome/issues/3142 +[#3157]: https://github.com/AdguardTeam/AdGuardHome/issues/3157 [#3367]: https://github.com/AdguardTeam/AdGuardHome/issues/3367 [#3381]: https://github.com/AdguardTeam/AdGuardHome/issues/3381 [#3503]: https://github.com/AdguardTeam/AdGuardHome/issues/3503 diff --git a/internal/aghnet/arpdb_bsd.go b/internal/aghnet/arpdb_bsd.go index a82da76c..26ac7758 100644 --- a/internal/aghnet/arpdb_bsd.go +++ b/internal/aghnet/arpdb_bsd.go @@ -13,19 +13,24 @@ import ( "github.com/AdguardTeam/golibs/netutil" ) -func newARPDB() *cmdARPDB { +func newARPDB() (arp *cmdARPDB) { return &cmdARPDB{ parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, ns: make([]Neighbor, 0), }, - cmd: "arp", - args: []string{"-a"}, + cmd: "arp", + // Use -n flag to avoid resolving the hostnames of the neighbors. By + // default ARP attempts to resolve the hostnames via DNS. See man 8 + // arp. + // + // See also https://github.com/AdguardTeam/AdGuardHome/issues/3157. + args: []string{"-a", "-n"}, } } -// parseArpA parses the output of the "arp -a" command on macOS and FreeBSD. +// parseArpA parses the output of the "arp -a -n" command on macOS and FreeBSD. // The expected input format: // // host.name (192.168.0.1) at ff:ff:ff:ff:ff:ff on en0 ifscope [ethernet] diff --git a/internal/aghnet/arpdb_linux.go b/internal/aghnet/arpdb_linux.go index 3d391f29..9cc38906 100644 --- a/internal/aghnet/arpdb_linux.go +++ b/internal/aghnet/arpdb_linux.go @@ -38,12 +38,17 @@ func newARPDB() (arp *arpdbs) { fsys: rootDirFS, filename: "proc/net/arp", }, - // Then, try "arp -a". + // Then, try "arp -a -n". &cmdARPDB{ parse: parseF, ns: ns, cmd: "arp", - args: []string{"-a"}, + // Use -n flag to avoid resolving the hostnames of the neighbors. + // By default ARP attempts to resolve the hostnames via DNS. See + // man 8 arp. + // + // See also https://github.com/AdguardTeam/AdGuardHome/issues/3157. + args: []string{"-a", "-n"}, }, // Finally, try "ip neigh". &cmdARPDB{ @@ -109,11 +114,11 @@ func (arp *fsysARPDB) Neighbors() (ns []Neighbor) { return arp.ns.clone() } -// parseArpAWrt parses the output of the "arp -a" command on OpenWrt. The +// parseArpAWrt parses the output of the "arp -a -n" command on OpenWrt. The // expected input format: // -// IP address HW type Flags HW address Mask Device -// 192.168.11.98 0x1 0x2 5a:92:df:a9:7e:28 * wan +// IP address HW type Flags HW address Mask Device +// 192.168.11.98 0x1 0x2 5a:92:df:a9:7e:28 * wan // func parseArpAWrt(sc *bufio.Scanner, lenHint int) (ns []Neighbor) { if !sc.Scan() { @@ -153,8 +158,8 @@ func parseArpAWrt(sc *bufio.Scanner, lenHint int) (ns []Neighbor) { return ns } -// parseArpA parses the output of the "arp -a" command on Linux. The expected -// input format: +// parseArpA parses the output of the "arp -a -n" command on Linux. The +// expected input format: // // hostname (192.168.1.1) at ab:cd:ef:ab:cd:ef [ether] on enp0s3 // diff --git a/internal/aghnet/arpdb_openbsd.go b/internal/aghnet/arpdb_openbsd.go index a00ffa85..d5ec5fea 100644 --- a/internal/aghnet/arpdb_openbsd.go +++ b/internal/aghnet/arpdb_openbsd.go @@ -12,20 +12,25 @@ import ( "github.com/AdguardTeam/golibs/log" ) -func newARPDB() *cmdARPDB { +func newARPDB() (arp *cmdARPDB) { return &cmdARPDB{ parse: parseArpA, ns: &neighs{ mu: &sync.RWMutex{}, ns: make([]Neighbor, 0), }, - cmd: "arp", - args: []string{"-a"}, + cmd: "arp", + // Use -n flag to avoid resolving the hostnames of the neighbors. By + // default ARP attempts to resolve the hostnames via DNS. See man 8 + // arp. + // + // See also https://github.com/AdguardTeam/AdGuardHome/issues/3157. + args: []string{"-a", "-n"}, } } -// parseArpA parses the output of the "arp -a" command on OpenBSD. The expected -// input format: +// parseArpA parses the output of the "arp -a -n" command on OpenBSD. The +// expected input format: // // Host Ethernet Address Netif Expire Flags // 192.168.1.1 ab:cd:ef:ab:cd:ef em0 19m59s diff --git a/internal/aghnet/arpdb_windows.go b/internal/aghnet/arpdb_windows.go index 2a70125f..8d5431eb 100644 --- a/internal/aghnet/arpdb_windows.go +++ b/internal/aghnet/arpdb_windows.go @@ -10,7 +10,7 @@ import ( "sync" ) -func newARPDB() *cmdARPDB { +func newARPDB() (arp *cmdARPDB) { return &cmdARPDB{ parse: parseArpA, ns: &neighs{ diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index 63f694bd..d423482a 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -135,7 +135,6 @@ func (s *Server) processRecursion(dctx *dnsContext) (rc resultCode) { pctx.Res = s.genNXDomain(pctx.Req) return resultCodeFinish - } return resultCodeSuccess diff --git a/internal/dnsforward/recursiondetector_test.go b/internal/dnsforward/recursiondetector_test.go index 7573b668..4edb3a37 100644 --- a/internal/dnsforward/recursiondetector_test.go +++ b/internal/dnsforward/recursiondetector_test.go @@ -83,7 +83,7 @@ func TestRecursionDetector_Suspect(t *testing.T) { testCases := []struct { name string msg dns.Msg - want bool + want int }{{ name: "simple", msg: dns.Msg{ @@ -95,24 +95,18 @@ func TestRecursionDetector_Suspect(t *testing.T) { Qtype: dns.TypeA, }}, }, - want: true, + want: 1, }, { name: "unencumbered", msg: dns.Msg{}, - want: false, + want: 0, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { t.Cleanup(rd.clear) - rd.add(tc.msg) - - if tc.want { - assert.Equal(t, 1, rd.recentRequests.Stats().Count) - } else { - assert.Zero(t, rd.recentRequests.Stats().Count) - } + assert.Equal(t, tc.want, rd.recentRequests.Stats().Count) }) } } diff --git a/internal/home/rdns.go b/internal/home/rdns.go index 7a2d1bcd..924aff37 100644 --- a/internal/home/rdns.go +++ b/internal/home/rdns.go @@ -16,18 +16,17 @@ type RDNS struct { exchanger dnsforward.RDNSExchanger clients *clientsContainer - // usePrivate is used to store the state of current private RDNS - // resolving settings and to react to it's changes. + // usePrivate is used to store the state of current private RDNS resolving + // settings and to react to it's changes. usePrivate uint32 // ipCh used to pass client's IP to rDNS workerLoop. ipCh chan net.IP // ipCache caches the IP addresses to be resolved by rDNS. The resolved - // address stays here while it's inside clients. After leaving clients - // the address will be resolved once again. If the address couldn't be - // resolved, cache prevents further attempts to resolve it for some - // time. + // address stays here while it's inside clients. After leaving clients the + // address will be resolved once again. If the address couldn't be + // resolved, cache prevents further attempts to resolve it for some time. ipCache cache.Cache } From 82af43039c78b49908151c09175a5161dd911601 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Tue, 19 Apr 2022 16:07:57 +0300 Subject: [PATCH 16/99] Pull request: whotracksme tracker links Merge in DNS/adguard-home from 4416-ui-tracker-href to master Squashed commit of the following: commit 979ea82a3b4d2c2a895b81aacd613fb7e5bec586 Merge: 4fe6328b 12ee287d Author: Dimitry Kolyshev Date: Tue Apr 19 15:03:13 2022 +0200 Merge remote-tracking branch 'origin/master' into 4416-ui-tracker-href commit 4fe6328b276e697a2aa351c6543d2efe6d2dc2e1 Author: Dimitry Kolyshev Date: Tue Apr 19 14:08:10 2022 +0200 whotracksme tracker links --- client/src/helpers/trackers/trackers.js | 19 ++++++++++++++++++- .../src/helpers/trackers/whotracksme_web.json | 6 ++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 client/src/helpers/trackers/whotracksme_web.json diff --git a/client/src/helpers/trackers/trackers.js b/client/src/helpers/trackers/trackers.js index 7af6dcb4..5327d18e 100644 --- a/client/src/helpers/trackers/trackers.js +++ b/client/src/helpers/trackers/trackers.js @@ -1,4 +1,5 @@ import whotracksmeDb from './whotracksme.json'; +import whotracksmeWebsites from './whotracksme_web.json'; import adguardDb from './adguard.json'; import { REPOSITORY } from '../constants'; @@ -20,6 +21,22 @@ export const sources = { ADGUARD: 2, }; +/** + * Gets link to tracker page on whotracks.me. + * + * @param trackerId + * @return {string} + */ +const getWhotracksmeUrl = (trackerId) => { + const websiteId = whotracksmeWebsites.websites[trackerId]; + if (websiteId) { + // Overrides links to websites. + return `https://whotracks.me/websites/${websiteId}.html`; + } + + return `https://whotracks.me/trackers/${trackerId}.html`; +}; + /** * Gets the source metadata for the specified tracker * @param {TrackerData} trackerData tracker data @@ -33,7 +50,7 @@ export const getSourceData = (trackerData) => { if (trackerData.source === sources.WHOTRACKSME) { return { name: 'Whotracks.me', - url: `https://whotracks.me/trackers/${trackerData.id}.html`, + url: getWhotracksmeUrl(trackerData.id), }; } if (trackerData.source === sources.ADGUARD) { diff --git a/client/src/helpers/trackers/whotracksme_web.json b/client/src/helpers/trackers/whotracksme_web.json new file mode 100644 index 00000000..8123fe1b --- /dev/null +++ b/client/src/helpers/trackers/whotracksme_web.json @@ -0,0 +1,6 @@ +{ + "timeUpdated": "2021-12-19T13:50:00.512Z", + "websites": { + "netflix": "netflix.com" + } +} From 9b7fe740862c590f3311ad427672a0b06c6b4ff6 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 25 Apr 2022 13:59:34 +0300 Subject: [PATCH 17/99] Pull request: all: do not mark help-wanted issues as stale Merge in DNS/adguard-home from help-wanted-stale to master Squashed commit of the following: commit 1c5ffcdd0153dd7d9d9bcc1e35dee4a0b3113f59 Author: Ainar Garipov Date: Fri Apr 22 20:04:01 2022 +0300 all: do not mark help-wanted issues as stale --- .github/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/stale.yml b/.github/stale.yml index d242832f..6ed9a7df 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,6 +8,7 @@ - 'documentation' - 'enhancement' - 'feature request' +- 'help wanted' - 'localization' - 'needs investigation' - 'recurrent' From 9d144ecb0a4433e594365ea89c73881da561938d Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Mon, 25 Apr 2022 17:09:49 +0300 Subject: [PATCH 18/99] Pull request: client: imp rdns desc Squashed commit of the following: commit 5631f5f7155d7e5ad58dc5088cc3c93cb40a94a4 Author: Eugene Burkov Date: Mon Apr 25 17:03:13 2022 +0300 client: imp rdns desc --- client/src/__locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 706ddf55..f39d2f51 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Bootstrap DNS servers", "bootstrap_dns_desc": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", "local_ptr_title": "Private reverse DNS servers", - "local_ptr_desc": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve the hostnames of clients with private IP addresses, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", + "local_ptr_desc": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve PTR requests for addresses in private IP ranges, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", "local_ptr_default_resolver": "By default, AdGuard Home uses the following reverse DNS resolvers: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home could not determine suitable private reverse DNS resolvers for this system.", "local_ptr_placeholder": "Enter one server address per line", From 2a1ad532f454ed2ab25d19eaf168ba9f6d534f2f Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Mon, 25 Apr 2022 18:41:39 +0300 Subject: [PATCH 19/99] Pull request: home: rm unnecessary locking in update; refactor Merge in DNS/adguard-home from 4499-rm-unnecessary-locking to master Squashed commit of the following: commit 6d70472506dd0fd69225454c73d9f7f6a208b76b Author: Ainar Garipov Date: Mon Apr 25 17:26:54 2022 +0300 home: rm unnecessary locking in update; refactor --- CHANGELOG.md | 2 + .../aghnet/{net_nolinux.go => net_bsd.go} | 4 +- internal/aghnet/net_windows.go | 8 +- internal/home/controlupdate.go | 122 ++++++++++-------- internal/updater/check.go | 2 +- scripts/make/go-lint.sh | 1 - 6 files changed, 79 insertions(+), 60 deletions(-) rename internal/aghnet/{net_nolinux.go => net_bsd.go} (69%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d82fb57..b43f0524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,7 @@ In this release, the schema version has changed from 12 to 13. ### Fixed +- Slow version update queries making other HTTP APIs unresponsible ([#4499]). - ARP tables refreshing process causing excessive PTR requests ([#3157]). [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 @@ -106,6 +107,7 @@ In this release, the schema version has changed from 12 to 13. [#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221 [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 +[#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 [repr]: https://reproducible-builds.org/docs/source-date-epoch/ [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 diff --git a/internal/aghnet/net_nolinux.go b/internal/aghnet/net_bsd.go similarity index 69% rename from internal/aghnet/net_nolinux.go rename to internal/aghnet/net_bsd.go index f429c6fa..bd705e92 100644 --- a/internal/aghnet/net_nolinux.go +++ b/internal/aghnet/net_bsd.go @@ -1,5 +1,5 @@ -//go:build !linux -// +build !linux +//go:build darwin || freebsd || openbsd +// +build darwin freebsd openbsd package aghnet diff --git a/internal/aghnet/net_windows.go b/internal/aghnet/net_windows.go index 0cea8fe7..17499cce 100644 --- a/internal/aghnet/net_windows.go +++ b/internal/aghnet/net_windows.go @@ -1,5 +1,5 @@ -//go:build !(linux || darwin || freebsd || openbsd) -// +build !linux,!darwin,!freebsd,!openbsd +//go:build windows +// +build windows package aghnet @@ -13,6 +13,10 @@ import ( "golang.org/x/sys/windows" ) +func canBindPrivilegedPorts() (can bool, err error) { + return true, nil +} + func ifaceHasStaticIP(string) (ok bool, err error) { return false, aghos.Unsupported("checking static ip") } diff --git a/internal/home/controlupdate.go b/internal/home/controlupdate.go index 79b9f37e..ae469598 100644 --- a/internal/home/controlupdate.go +++ b/internal/home/controlupdate.go @@ -3,6 +3,7 @@ package home import ( "context" "encoding/json" + "fmt" "net/http" "os" "os/exec" @@ -27,12 +28,16 @@ type temporaryError interface { // Get the latest available version from the Internet func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + resp := &versionResponse{} if Context.disableUpdate { - // w.Header().Set("Content-Type", "application/json") resp.Disabled = true - _ = json.NewEncoder(w).Encode(resp) - // TODO(e.burkov): Add error handling and deal with headers. + err := json.NewEncoder(w).Encode(resp) + if err != nil { + aghhttp.Error(r, w, http.StatusInternalServerError, "writing body: %s", err) + } + return } @@ -44,30 +49,48 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { if r.ContentLength != 0 { err = json.NewDecoder(r.Body).Decode(req) if err != nil { - aghhttp.Error(r, w, http.StatusBadRequest, "JSON parse: %s", err) + aghhttp.Error(r, w, http.StatusBadRequest, "parsing request: %s", err) return } } + err = requestVersionInfo(resp, req.Recheck) + if err != nil { + // Don't wrap the error, because it's informative enough as is. + aghhttp.Error(r, w, http.StatusBadGateway, "%s", err) + + return + } + + err = resp.setAllowedToAutoUpdate() + if err != nil { + // Don't wrap the error, because it's informative enough as is. + aghhttp.Error(r, w, http.StatusInternalServerError, "%s", err) + + return + } + + err = json.NewEncoder(w).Encode(resp) + if err != nil { + aghhttp.Error(r, w, http.StatusInternalServerError, "writing body: %s", err) + } +} + +// requestVersionInfo sets the VersionInfo field of resp if it can reach the +// update server. +func requestVersionInfo(resp *versionResponse, recheck bool) (err error) { for i := 0; i != 3; i++ { - func() { - Context.controlLock.Lock() - defer Context.controlLock.Unlock() - - resp.VersionInfo, err = Context.updater.VersionInfo(req.Recheck) - }() - + resp.VersionInfo, err = Context.updater.VersionInfo(recheck) if err != nil { var terr temporaryError if errors.As(err, &terr) && terr.Temporary() { - // Temporary network error. This case may happen while - // we're restarting our DNS server. Log and sleep for - // some time. + // Temporary network error. This case may happen while we're + // restarting our DNS server. Log and sleep for some time. // // See https://github.com/AdguardTeam/AdGuardHome/issues/934. d := time.Duration(i) * time.Second - log.Info("temp net error: %q; sleeping for %s and retrying", err, d) + log.Info("update: temp net error: %q; sleeping for %s and retrying", err, d) time.Sleep(d) continue @@ -76,29 +99,14 @@ func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { break } + if err != nil { vcu := Context.updater.VersionCheckURL() - // TODO(a.garipov): Figure out the purpose of %T verb. - aghhttp.Error( - r, - w, - http.StatusBadGateway, - "Couldn't get version check json from %s: %T %s\n", - vcu, - err, - err, - ) - return + return fmt.Errorf("getting version info from %s: %s", vcu, err) } - resp.confirmAutoUpdate() - - w.Header().Set("Content-Type", "application/json") - err = json.NewEncoder(w).Encode(resp) - if err != nil { - aghhttp.Error(r, w, http.StatusInternalServerError, "Couldn't write body: %s", err) - } + return nil } // handleUpdate performs an update to the latest available version procedure. @@ -132,31 +140,37 @@ func handleUpdate(w http.ResponseWriter, r *http.Request) { // versionResponse is the response for /control/version.json endpoint. type versionResponse struct { - Disabled bool `json:"disabled"` updater.VersionInfo + Disabled bool `json:"disabled"` } -// confirmAutoUpdate checks the real possibility of auto update. -func (vr *versionResponse) confirmAutoUpdate() { - if vr.CanAutoUpdate != nil && *vr.CanAutoUpdate { - canUpdate := true - - var tlsConf *tlsConfigSettings - if runtime.GOOS != "windows" { - tlsConf = &tlsConfigSettings{} - Context.tls.WriteDiskConfig(tlsConf) - } - - if tlsConf != nil && - ((tlsConf.Enabled && (tlsConf.PortHTTPS < 1024 || - tlsConf.PortDNSOverTLS < 1024 || - tlsConf.PortDNSOverQUIC < 1024)) || - config.BindPort < 1024 || - config.DNS.Port < 1024) { - canUpdate, _ = aghnet.CanBindPrivilegedPorts() - } - vr.CanAutoUpdate = &canUpdate +// setAllowedToAutoUpdate sets CanAutoUpdate to true if AdGuard Home is actually +// allowed to perform an automatic update by the OS. +func (vr *versionResponse) setAllowedToAutoUpdate() (err error) { + if vr.CanAutoUpdate == nil || !*vr.CanAutoUpdate { + return } + + tlsConf := &tlsConfigSettings{} + Context.tls.WriteDiskConfig(tlsConf) + + canUpdate := true + if tlsConfUsesPrivilegedPorts(tlsConf) || config.BindPort < 1024 || config.DNS.Port < 1024 { + canUpdate, err = aghnet.CanBindPrivilegedPorts() + if err != nil { + return fmt.Errorf("checking ability to bind privileged ports: %w", err) + } + } + + vr.CanAutoUpdate = &canUpdate + + return nil +} + +// tlsConfUsesPrivilegedPorts returns true if the provided TLS configuration +// indicates that privileged ports are used. +func tlsConfUsesPrivilegedPorts(c *tlsConfigSettings) (ok bool) { + return c.Enabled && (c.PortHTTPS < 1024 || c.PortDNSOverTLS < 1024 || c.PortDNSOverQUIC < 1024) } // finishUpdate completes an update procedure. diff --git a/internal/updater/check.go b/internal/updater/check.go index edf046af..ec7176b2 100644 --- a/internal/updater/check.go +++ b/internal/updater/check.go @@ -17,11 +17,11 @@ const versionCheckPeriod = 8 * time.Hour // VersionInfo contains information about a new version. type VersionInfo struct { + CanAutoUpdate *bool `json:"can_autoupdate,omitempty"` NewVersion string `json:"new_version,omitempty"` Announcement string `json:"announcement,omitempty"` AnnouncementURL string `json:"announcement_url,omitempty"` SelfUpdateMinVersion string `json:"-"` - CanAutoUpdate *bool `json:"can_autoupdate,omitempty"` } // MaxResponseSize is responses on server's requests maximum length in bytes. diff --git a/scripts/make/go-lint.sh b/scripts/make/go-lint.sh index 32d99480..c363e513 100644 --- a/scripts/make/go-lint.sh +++ b/scripts/make/go-lint.sh @@ -136,7 +136,6 @@ underscores() { -e '_freebsd.go'\ -e '_linux.go'\ -e '_little.go'\ - -e '_nolinux.go'\ -e '_openbsd.go'\ -e '_others.go'\ -e '_test.go'\ From 0a1ff65b4a3155ce65661d051fb6e8600c265702 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Mon, 25 Apr 2022 19:10:52 +0300 Subject: [PATCH 20/99] Pull request: client: fix constant loading for blocked requests Updates #4420 Squashed commit of the following: commit 461a59e1541626020bf0bcfaf34ba7d2f4509dc7 Merge: 5c5e7b5d 2a1ad532 Author: Ainar Garipov Date: Mon Apr 25 18:46:02 2022 +0300 Merge branch 'master' into 4420-loading-log commit 5c5e7b5d1a69d30e40e71f49f46dea89fa8c40a2 Author: Ildar Kamalov Date: Sun Apr 24 22:18:22 2022 +0300 client: fix constant loading for blocked requests --- client/src/components/Logs/InfiniteTable.js | 29 ++++++++++++++------- client/src/helpers/helpers.js | 4 +-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/client/src/components/Logs/InfiniteTable.js b/client/src/components/Logs/InfiniteTable.js index d419ac3d..36f411c8 100644 --- a/client/src/components/Logs/InfiniteTable.js +++ b/client/src/components/Logs/InfiniteTable.js @@ -43,7 +43,7 @@ const InfiniteTable = ({ useEffect(() => { listener(); - }, [items.length < QUERY_LOGS_PAGE_LIMIT]); + }, [items.length < QUERY_LOGS_PAGE_LIMIT, isEntireLog]); useEffect(() => { const THROTTLE_TIME = 100; @@ -66,15 +66,24 @@ const InfiniteTable = ({ const isNothingFound = items.length === 0 && !processingGetLogs; - return
- {loading && } -
- {isNothingFound - ? - : <>{items.map(renderRow)} - {!isEntireLog &&
{t('loading_table_status')}
} - } -
; + return ( +
+ {loading && } +
+ {isNothingFound ? ( + + ) : ( + <> + {items.map(renderRow)} + {!isEntireLog && ( +
+ {t('loading_table_status')} +
+ )} + + )} +
+ ); }; InfiniteTable.propTypes = { diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js index 5fb42c05..a7bf9485 100644 --- a/client/src/helpers/helpers.js +++ b/client/src/helpers/helpers.js @@ -693,8 +693,8 @@ export const replaceZeroWithEmptyString = (value) => (parseInt(value, 10) === 0 * @returns {string} */ export const getLogsUrlParams = (search, response_status) => `?${queryString.stringify({ - search, - response_status, + search: search || undefined, + response_status: response_status || undefined, })}`; export const processContent = ( From 235316e0508ee015bf4ce663d2b7929079541c59 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Tue, 26 Apr 2022 13:04:16 +0300 Subject: [PATCH 21/99] Pull request: 3020 runtime clients sources control Merge in DNS/adguard-home from 3020-client-sources to master Closes #3020. Squashed commit of the following: commit f8e6b6d63373f99b52f7b8c32f4242c453daf1a4 Merge: 41fb071d 0a1ff65b Author: Ainar Garipov Date: Mon Apr 25 19:19:15 2022 +0300 Merge branch 'master' into 3020-client-sources commit 41fb071deb2a87e0a69d09c8f418a016b4dd7e93 Author: Eugene Burkov Date: Mon Apr 25 13:38:28 2022 +0300 home: fix nil, imp docs commit aaa7765914a8a4645eba357cd088a9470611ffdc Author: Eugene Burkov Date: Mon Apr 25 12:25:47 2022 +0300 home: imp code commit 3f71b999564c604583b46313d29f5b70cf51ee14 Author: Eugene Burkov Date: Fri Apr 22 19:12:27 2022 +0300 home: runtime clients sources control --- CHANGELOG.md | 36 ++++++++- internal/home/clients.go | 26 ++++-- internal/home/config.go | 28 ++++--- internal/home/dns.go | 17 ++-- internal/home/home.go | 15 ++-- internal/home/options.go | 12 ++- internal/home/upgrade.go | 69 +++++++++++++++- internal/home/upgrade_test.go | 145 ++++++++++++++++++++++++++-------- 8 files changed, 283 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b43f0524..047726ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ and this project adheres to ### Added +- The ability to control each source of runtime clients separately via + `clients.runtime_sources` configuration object ([#3020]). - The ability to customize the set of networks that are considered private through the new `dns.private_networks` property in the configuration file ([#3142]). @@ -63,8 +65,36 @@ and this project adheres to #### Configuration Changes -In this release, the schema version has changed from 12 to 13. +In this release, the schema version has changed from 12 to 14. +- Object `clients`, which in schema versions 13 and earlier was an array of + actual persistent clients, is now consist of `persistent` and + `runtime_sources` properties: + + ```yaml + # BEFORE: + 'clients': + - name: client-name + # … + + # AFTER: + 'clients': + 'persistent': + - name: client-name + # … + 'runtime_sources': + whois: true + arp: true + rdns: true + dhcp: true + hosts: true + ``` + + The value for `clients.runtime_sources.rdns` field is taken from + `dns.resolve_clients` property. To rollback this change, remove the + `runtime_sources` property, move the contents of `persistent` into the + `clients` itself, the value of `clients.runtime_sources.rdns` into the + `dns.resolve_clietns`, and change the `schema_version` back to `13`. - Property `local_domain_name`, which in schema versions 12 and earlier used to be a part of the `dns` object, is now a part of the `dhcp` object: @@ -85,6 +115,9 @@ In this release, the schema version has changed from 12 to 13. ### Deprecated +- The `--no-etc-hosts` option. Its' functionality is now controlled by + `clients.runtime_sources.hosts` configuration property. v0.109.0 will remove + the flag completely. - Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. ### Fixed @@ -94,6 +127,7 @@ In this release, the schema version has changed from 12 to 13. [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 [#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993 +[#3020]: https://github.com/AdguardTeam/AdGuardHome/issues/3020 [#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057 [#3142]: https://github.com/AdguardTeam/AdGuardHome/issues/3142 [#3157]: https://github.com/AdguardTeam/AdGuardHome/issues/3157 diff --git a/internal/home/clients.go b/internal/home/clients.go index fe15e514..d4d6b959 100644 --- a/internal/home/clients.go +++ b/internal/home/clients.go @@ -59,6 +59,16 @@ const ( ClientSourceHostsFile ) +// clientSourceConf is used to configure where the runtime clients will be +// obtained from. +type clientSourcesConf struct { + WHOIS bool `yaml:"whois"` + ARP bool `yaml:"arp"` + RDNS bool `yaml:"rdns"` + DHCP bool `yaml:"dhcp"` + HostsFile bool `yaml:"hosts"` +} + // RuntimeClient information type RuntimeClient struct { WHOISInfo *RuntimeClientWHOISInfo @@ -134,14 +144,14 @@ func (clients *clientsContainer) Init( clients.dhcpServer.SetOnLeaseChanged(clients.onDHCPLeaseChanged) } - go clients.handleHostsUpdates() + if clients.etcHosts != nil { + go clients.handleHostsUpdates() + } } func (clients *clientsContainer) handleHostsUpdates() { - if clients.etcHosts != nil { - for upd := range clients.etcHosts.Upd() { - clients.addFromHostsFile(upd) - } + for upd := range clients.etcHosts.Upd() { + clients.addFromHostsFile(upd) } } @@ -158,7 +168,9 @@ func (clients *clientsContainer) Start() { // Reload reloads runtime clients. func (clients *clientsContainer) Reload() { - clients.addFromSystemARP() + if clients.arpdb != nil { + clients.addFromSystemARP() + } } type clientObject struct { @@ -843,7 +855,7 @@ func (clients *clientsContainer) addFromSystemARP() { // updateFromDHCP adds the clients that have a non-empty hostname from the DHCP // server. func (clients *clientsContainer) updateFromDHCP(add bool) { - if clients.dhcpServer == nil { + if clients.dhcpServer == nil || !config.Clients.Sources.DHCP { return } diff --git a/internal/home/config.go b/internal/home/config.go index aa8450be..720683a1 100644 --- a/internal/home/config.go +++ b/internal/home/config.go @@ -51,6 +51,13 @@ type osConfig struct { RlimitNoFile uint64 `yaml:"rlimit_nofile"` } +type clientsConfig struct { + // Sources defines the set of sources to fetch the runtime clients from. + Sources *clientSourcesConf `yaml:"runtime_sources"` + // Persistent are the configured clients. + Persistent []*clientObject `yaml:"persistent"` +} + // configuration is loaded from YAML // field ordering is important -- yaml fields will mirror ordering from here type configuration struct { @@ -88,7 +95,7 @@ type configuration struct { // Clients contains the YAML representations of the persistent clients. // This field is only used for reading and writing persistent client data. // Keep this field sorted to ensure consistent ordering. - Clients []*clientObject `yaml:"clients"` + Clients *clientsConfig `yaml:"clients"` logSettings `yaml:",inline"` @@ -123,9 +130,6 @@ type dnsConfig struct { // UpstreamTimeout is the timeout for querying upstream servers. UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"` - // ResolveClients enables and disables resolving clients with RDNS. - ResolveClients bool `yaml:"resolve_clients"` - // PrivateNets is the set of IP networks for which the private reverse DNS // resolver should be used. PrivateNets []string `yaml:"private_networks"` @@ -198,7 +202,6 @@ var config = &configuration{ FilteringEnabled: true, // whether or not use filter lists FiltersUpdateIntervalHours: 24, UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout}, - ResolveClients: true, UsePrivateRDNS: true, }, TLS: tlsConfigSettings{ @@ -209,6 +212,15 @@ var config = &configuration{ DHCP: &dhcpd.ServerConfig{ LocalDomainName: "lan", }, + Clients: &clientsConfig{ + Sources: &clientSourcesConf{ + WHOIS: true, + ARP: true, + RDNS: true, + DHCP: true, + HostsFile: true, + }, + }, logSettings: logSettings{ LogCompress: false, LogLocalTime: false, @@ -404,9 +416,7 @@ func (c *configuration) write() error { s.WriteDiskConfig(&c) dns := &config.DNS dns.FilteringConfig = c - dns.LocalPTRResolvers, - dns.ResolveClients, - dns.UsePrivateRDNS = s.RDNSSettings() + dns.LocalPTRResolvers, config.Clients.Sources.RDNS, dns.UsePrivateRDNS = s.RDNSSettings() } if Context.dhcpServer != nil { @@ -415,7 +425,7 @@ func (c *configuration) write() error { config.DHCP = c } - config.Clients = Context.clients.forConfig() + config.Clients.Persistent = Context.clients.forConfig() configFile := config.getConfigFilename() log.Debug("Writing YAML file: %s", configFile) diff --git a/internal/home/dns.go b/internal/home/dns.go index c30e12ec..e0fc1aab 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -136,7 +136,10 @@ func initDNSServer() (err error) { } Context.rdns = NewRDNS(Context.dnsServer, &Context.clients, config.DNS.UsePrivateRDNS) - Context.whois = initWHOIS(&Context.clients) + + if !config.Clients.Sources.WHOIS { + Context.whois = initWHOIS(&Context.clients) + } Context.filters.Init() return nil @@ -153,10 +156,11 @@ func onDNSRequest(pctx *proxy.DNSContext) { return } - if config.DNS.ResolveClients && !ip.IsLoopback() { + srcs := config.Clients.Sources + if srcs.RDNS && !ip.IsLoopback() { Context.rdns.Begin(ip) } - if !netutil.IsSpecialPurpose(ip) { + if srcs.WHOIS && !netutil.IsSpecialPurpose(ip) { Context.whois.Begin(ip) } } @@ -239,7 +243,7 @@ func generateServerConfig() (newConf dnsforward.ServerConfig, err error) { newConf.FilterHandler = applyAdditionalFiltering newConf.GetCustomUpstreamByClient = Context.clients.findUpstreams - newConf.ResolveClients = dnsConf.ResolveClients + newConf.ResolveClients = config.Clients.Sources.RDNS newConf.UsePrivateRDNS = dnsConf.UsePrivateRDNS newConf.LocalPTRResolvers = dnsConf.LocalPTRResolvers newConf.UpstreamTimeout = dnsConf.UpstreamTimeout.Duration @@ -387,10 +391,11 @@ func startDNSServer() error { continue } - if config.DNS.ResolveClients && !ip.IsLoopback() { + srcs := config.Clients.Sources + if srcs.RDNS && !ip.IsLoopback() { Context.rdns.Begin(ip) } - if !netutil.IsSpecialPurpose(ip) { + if srcs.WHOIS && !netutil.IsSpecialPurpose(ip) { Context.whois.Begin(ip) } } diff --git a/internal/home/home.go b/internal/home/home.go index 420e67d8..539552d1 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -173,6 +173,11 @@ func setupContext(args options) { os.Exit(0) } + + if !args.noEtcHosts && config.Clients.Sources.HostsFile { + err = setupHostsContainer() + fatalOnError(err) + } } Context.mux = http.NewServeMux() @@ -285,14 +290,12 @@ func setupConfig(args options) (err error) { ConfName: config.getConfigFilename(), }) - if !args.noEtcHosts { - if err = setupHostsContainer(); err != nil { - return err - } + var arpdb aghnet.ARPDB + if config.Clients.Sources.ARP { + arpdb = aghnet.NewARPDB() } - arpdb := aghnet.NewARPDB() - Context.clients.Init(config.Clients, Context.dhcpServer, Context.etcHosts, arpdb) + Context.clients.Init(config.Clients.Persistent, Context.dhcpServer, Context.etcHosts, arpdb) if args.bindPort != 0 { uc := aghalg.UniqChecker{} diff --git a/internal/home/options.go b/internal/home/options.go index dc11ca35..6f5a4d8d 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -230,13 +230,19 @@ var helpArg = arg{ } var noEtcHostsArg = arg{ - description: "Do not use the OS-provided hosts.", + description: "Deprecated. Do not use the OS-provided hosts.", longName: "no-etc-hosts", shortName: "", updateWithValue: nil, updateNoValue: func(o options) (options, error) { o.noEtcHosts = true; return o, nil }, - effect: nil, - serialize: func(o options) []string { return boolSliceOrNil(o.noEtcHosts) }, + effect: func(_ options, _ string) (f effect, err error) { + log.Info( + "warning: --no-etc-hosts flag is deprecated and will be removed in the future versions", + ) + + return nil, nil + }, + serialize: func(o options) []string { return boolSliceOrNil(o.noEtcHosts) }, } var localFrontendArg = arg{ diff --git a/internal/home/upgrade.go b/internal/home/upgrade.go index 34297470..d9611dc9 100644 --- a/internal/home/upgrade.go +++ b/internal/home/upgrade.go @@ -21,9 +21,11 @@ import ( ) // currentSchemaVersion is the current schema version. -const currentSchemaVersion = 13 +const currentSchemaVersion = 14 // These aliases are provided for convenience. +// +// TODO(e.burkov): Remove any after updating to Go 1.18. type ( any = interface{} yarr = []any @@ -86,6 +88,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) { upgradeSchema10to11, upgradeSchema11to12, upgradeSchema12to13, + upgradeSchema13to14, } n := 0 @@ -726,7 +729,7 @@ func upgradeSchema12to13(diskConf yobj) (err error) { var dhcp yobj dhcp, ok = dhcpVal.(yobj) if !ok { - return fmt.Errorf("unexpected type of dhcp: %T", dnsVal) + return fmt.Errorf("unexpected type of dhcp: %T", dhcpVal) } const field = "local_domain_name" @@ -737,6 +740,68 @@ func upgradeSchema12to13(diskConf yobj) (err error) { return nil } +// upgradeSchema13to14 performs the following changes: +// +// # BEFORE: +// 'clients': +// - 'name': 'client-name' +// # … +// +// # AFTER: +// 'clients': +// 'persistent': +// - 'name': 'client-name' +// # … +// 'runtime_sources': +// 'whois': true +// 'arp': true +// 'rdns': true +// 'dhcp': true +// 'hosts': true +// +func upgradeSchema13to14(diskConf yobj) (err error) { + log.Printf("Upgrade yaml: 13 to 14") + diskConf["schema_version"] = 14 + + clientsVal, ok := diskConf["clients"] + if !ok { + clientsVal = yarr{} + } + + var rdnsSrc bool + if dnsVal, dok := diskConf["dns"]; dok { + var dnsSettings yobj + dnsSettings, ok = dnsVal.(yobj) + if !ok { + return fmt.Errorf("unexpected type of dns: %T", dnsVal) + } + + var rdnsSrcVal any + rdnsSrcVal, ok = dnsSettings["resolve_clients"] + if ok { + rdnsSrc, ok = rdnsSrcVal.(bool) + if !ok { + return fmt.Errorf("unexpected type of resolve_clients: %T", rdnsSrcVal) + } + + delete(dnsSettings, "resolve_clients") + } + } + + diskConf["clients"] = yobj{ + "persistent": clientsVal, + "runtime_sources": &clientSourcesConf{ + WHOIS: true, + ARP: true, + RDNS: rdnsSrc, + DHCP: true, + HostsFile: true, + }, + } + + return nil +} + // TODO(a.garipov): Replace with log.Output when we port it to our logging // package. func funcName() string { diff --git a/internal/home/upgrade_test.go b/internal/home/upgrade_test.go index c63bc443..4c25cba3 100644 --- a/internal/home/upgrade_test.go +++ b/internal/home/upgrade_test.go @@ -513,46 +513,129 @@ func TestUpgradeSchema11to12(t *testing.T) { } func TestUpgradeSchema12to13(t *testing.T) { - t.Run("no_dns", func(t *testing.T) { - conf := yobj{} + const newSchemaVer = 13 - err := upgradeSchema12to13(conf) - require.NoError(t, err) - - assert.Equal(t, conf["schema_version"], 13) - }) - - t.Run("no_dhcp", func(t *testing.T) { - conf := yobj{ - "dns": yobj{}, - } - - err := upgradeSchema12to13(conf) - require.NoError(t, err) - - assert.Equal(t, conf["schema_version"], 13) - }) - - t.Run("good", func(t *testing.T) { - conf := yobj{ + testCases := []struct { + in yobj + want yobj + name string + }{{ + in: yobj{}, + want: yobj{"schema_version": newSchemaVer}, + name: "no_dns", + }, { + in: yobj{"dns": yobj{}}, + want: yobj{ + "dns": yobj{}, + "schema_version": newSchemaVer, + }, + name: "no_dhcp", + }, { + in: yobj{ "dns": yobj{ "local_domain_name": "lan", }, "dhcp": yobj{}, - "schema_version": 12, - } - - wantConf := yobj{ + "schema_version": newSchemaVer - 1, + }, + want: yobj{ "dns": yobj{}, "dhcp": yobj{ "local_domain_name": "lan", }, - "schema_version": 13, - } + "schema_version": newSchemaVer, + }, + name: "good", + }} - err := upgradeSchema12to13(conf) - require.NoError(t, err) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := upgradeSchema12to13(tc.in) + require.NoError(t, err) - assert.Equal(t, wantConf, conf) - }) + assert.Equal(t, tc.want, tc.in) + }) + } +} + +func TestUpgradeSchema13to14(t *testing.T) { + const newSchemaVer = 14 + + testClient := &clientObject{ + Name: "agh-client", + IDs: []string{"id1"}, + UseGlobalSettings: true, + } + + testCases := []struct { + in yobj + want yobj + name string + }{{ + in: yobj{}, + want: yobj{ + "schema_version": newSchemaVer, + // The clients field will be added anyway. + "clients": yobj{ + "persistent": yarr{}, + "runtime_sources": &clientSourcesConf{ + WHOIS: true, + ARP: true, + RDNS: false, + DHCP: true, + HostsFile: true, + }, + }, + }, + name: "no_clients", + }, { + in: yobj{ + "clients": []*clientObject{testClient}, + }, + want: yobj{ + "schema_version": newSchemaVer, + "clients": yobj{ + "persistent": []*clientObject{testClient}, + "runtime_sources": &clientSourcesConf{ + WHOIS: true, + ARP: true, + RDNS: false, + DHCP: true, + HostsFile: true, + }, + }, + }, + name: "no_dns", + }, { + in: yobj{ + "clients": []*clientObject{testClient}, + "dns": yobj{ + "resolve_clients": true, + }, + }, + want: yobj{ + "schema_version": newSchemaVer, + "clients": yobj{ + "persistent": []*clientObject{testClient}, + "runtime_sources": &clientSourcesConf{ + WHOIS: true, + ARP: true, + RDNS: true, + DHCP: true, + HostsFile: true, + }, + }, + "dns": yobj{}, + }, + name: "good", + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := upgradeSchema13to14(tc.in) + require.NoError(t, err) + + assert.Equal(t, tc.want, tc.in) + }) + } } From 1c89394aef6abb1e4810c84db01d44cec770dee7 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Tue, 26 Apr 2022 15:21:45 +0300 Subject: [PATCH 22/99] Pull request: 4525 fix panic Merge in DNS/adguard-home from 3020-fix-panic to master Closes #4525. Squashed commit of the following: commit f8d9e25eccb485269aa2f0275d4e08da767f9d05 Author: Eugene Burkov Date: Tue Apr 26 15:09:11 2022 +0300 home: imp code commit 8fe02c8f057c05b9e8ce1de056a92e7cd69ae4c6 Author: Eugene Burkov Date: Tue Apr 26 14:44:33 2022 +0300 home: fix panic --- internal/home/dns.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/home/dns.go b/internal/home/dns.go index e0fc1aab..e28193ee 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -135,9 +135,11 @@ func initDNSServer() (err error) { return fmt.Errorf("dnsServer.Prepare: %w", err) } - Context.rdns = NewRDNS(Context.dnsServer, &Context.clients, config.DNS.UsePrivateRDNS) + if config.Clients.Sources.RDNS { + Context.rdns = NewRDNS(Context.dnsServer, &Context.clients, config.DNS.UsePrivateRDNS) + } - if !config.Clients.Sources.WHOIS { + if config.Clients.Sources.WHOIS { Context.whois = initWHOIS(&Context.clients) } From ed449c618628c5e3ee76072cb010ece32eea565e Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Tue, 26 Apr 2022 20:50:09 +0300 Subject: [PATCH 23/99] Pull request: all: add stub binary for new api Merge in DNS/adguard-home from new-api to master Squashed commit of the following: commit 83f4418c253b9abc5131d9e2acc2a4a96e4122c4 Author: Ainar Garipov Date: Tue Apr 26 19:09:34 2022 +0300 all: fix build commit 1fbb53fdf779bde79fab72f9c8eb929e08bb044c Merge: 73a55197 1c89394a Author: Ainar Garipov Date: Tue Apr 26 18:37:27 2022 +0300 Merge branch 'master' into new-api commit 73a5519723f662979bdeb5192bc15835e7f03512 Author: Ainar Garipov Date: Tue Apr 26 18:36:50 2022 +0300 v1: imp names, docs commit d3fbc2f2082612b8ba438c8216c6c74421cc2df5 Author: Ainar Garipov Date: Fri Apr 22 17:55:42 2022 +0300 cmd: imp docs commit c2a73aa364a848e8066d1132d4b53bbc3e22db2d Author: Ainar Garipov Date: Fri Apr 22 16:19:14 2022 +0300 all: add stub binary for new api --- Makefile | 3 + internal/aghos/os.go | 10 + internal/aghos/os_unix.go | 27 + internal/aghos/os_windows.go | 21 + internal/v1/agh/agh.go | 33 + internal/v1/cmd/cmd.go | 69 + internal/v1/cmd/signal.go | 70 + internal/v1/websvc/websvc.go | 185 ++ internal/v1/websvc/websvc_test.go | 69 + main.go | 3 + main_v1.go | 21 + openapi/v1.yaml | 4913 +++++++++++++++++++++++++++++ scripts/make/go-build.sh | 12 +- scripts/make/go-lint.sh | 3 +- 14 files changed, 5437 insertions(+), 2 deletions(-) create mode 100644 internal/aghos/os_unix.go create mode 100644 internal/v1/agh/agh.go create mode 100644 internal/v1/cmd/cmd.go create mode 100644 internal/v1/cmd/signal.go create mode 100644 internal/v1/websvc/websvc.go create mode 100644 internal/v1/websvc/websvc_test.go create mode 100644 main_v1.go create mode 100644 openapi/v1.yaml diff --git a/Makefile b/Makefile index 5d9e7a7c..7c8f205f 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,8 @@ YARN_INSTALL_FLAGS = $(YARN_FLAGS) --network-timeout 120000 --silent\ --ignore-engines --ignore-optional --ignore-platform\ --ignore-scripts +V1API = 0 + # Macros for the build-release target. If FRONTEND_PREBUILT is 0, the # default, the macro $(BUILD_RELEASE_DEPS_$(FRONTEND_PREBUILT)) expands # into BUILD_RELEASE_DEPS_0, and so both frontend and backend @@ -61,6 +63,7 @@ ENV = env\ PATH="$${PWD}/bin:$$( "$(GO.MACRO)" env GOPATH )/bin:$${PATH}"\ RACE='$(RACE)'\ SIGN='$(SIGN)'\ + V1API='$(V1API)'\ VERBOSE='$(VERBOSE)'\ VERSION='$(VERSION)'\ diff --git a/internal/aghos/os.go b/internal/aghos/os.go index 018a3e89..3b688749 100644 --- a/internal/aghos/os.go +++ b/internal/aghos/os.go @@ -175,3 +175,13 @@ func RootDirFS() (fsys fs.FS) { // behavior is undocumented but it currently works. return os.DirFS("") } + +// NotifyShutdownSignal notifies c on receiving shutdown signals. +func NotifyShutdownSignal(c chan<- os.Signal) { + notifyShutdownSignal(c) +} + +// IsShutdownSignal returns true if sig is a shutdown signal. +func IsShutdownSignal(sig os.Signal) (ok bool) { + return isShutdownSignal(sig) +} diff --git a/internal/aghos/os_unix.go b/internal/aghos/os_unix.go new file mode 100644 index 00000000..9a3cc308 --- /dev/null +++ b/internal/aghos/os_unix.go @@ -0,0 +1,27 @@ +//go:build darwin || freebsd || linux || openbsd +// +build darwin freebsd linux openbsd + +package aghos + +import ( + "os" + "os/signal" + + "golang.org/x/sys/unix" +) + +func notifyShutdownSignal(c chan<- os.Signal) { + signal.Notify(c, unix.SIGINT, unix.SIGQUIT, unix.SIGTERM) +} + +func isShutdownSignal(sig os.Signal) (ok bool) { + switch sig { + case + unix.SIGINT, + unix.SIGQUIT, + unix.SIGTERM: + return true + default: + return false + } +} diff --git a/internal/aghos/os_windows.go b/internal/aghos/os_windows.go index bff5a3f0..31fca3ef 100644 --- a/internal/aghos/os_windows.go +++ b/internal/aghos/os_windows.go @@ -4,6 +4,10 @@ package aghos import ( + "os" + "os/signal" + "syscall" + "golang.org/x/sys/windows" ) @@ -35,3 +39,20 @@ func haveAdminRights() (bool, error) { func isOpenWrt() (ok bool) { return false } + +func notifyShutdownSignal(c chan<- os.Signal) { + // syscall.SIGTERM is processed automatically. See go doc os/signal, + // section Windows. + signal.Notify(c, os.Interrupt) +} + +func isShutdownSignal(sig os.Signal) (ok bool) { + switch sig { + case + os.Interrupt, + syscall.SIGTERM: + return true + default: + return false + } +} diff --git a/internal/v1/agh/agh.go b/internal/v1/agh/agh.go new file mode 100644 index 00000000..212da4d6 --- /dev/null +++ b/internal/v1/agh/agh.go @@ -0,0 +1,33 @@ +// Package agh contains common entities and interfaces of AdGuard Home. +// +// TODO(a.garipov): Move to the upper-level internal/. +package agh + +import "context" + +// Service is the interface for API servers. +// +// TODO(a.garipov): Consider adding a context to Start. +// +// TODO(a.garipov): Consider adding a Wait method or making an extension +// interface for that. +type Service interface { + // Start starts the service. It does not block. + Start() (err error) + + // Shutdown gracefully stops the service. ctx is used to determine + // a timeout before trying to stop the service less gracefully. + Shutdown(ctx context.Context) (err error) +} + +// type check +var _ Service = EmptyService{} + +// EmptyService is a Service that does nothing. +type EmptyService struct{} + +// Start implements the Service interface for EmptyService. +func (EmptyService) Start() (err error) { return nil } + +// Shutdown implements the Service interface for EmptyService. +func (EmptyService) Shutdown(_ context.Context) (err error) { return nil } diff --git a/internal/v1/cmd/cmd.go b/internal/v1/cmd/cmd.go new file mode 100644 index 00000000..4c4e252f --- /dev/null +++ b/internal/v1/cmd/cmd.go @@ -0,0 +1,69 @@ +// Package cmd is the AdGuard Home entry point. It contains the on-disk +// configuration file utilities, signal processing logic, and so on. +// +// TODO(a.garipov): Move to the upper-level internal/. +package cmd + +import ( + "context" + "io/fs" + "math/rand" + "net" + "time" + + "github.com/AdguardTeam/AdGuardHome/internal/v1/websvc" + "github.com/AdguardTeam/golibs/log" + "github.com/AdguardTeam/golibs/netutil" +) + +// Main is the entry point of application. +func Main(clientBuildFS fs.FS) { + // # Initial Configuration + + rand.Seed(time.Now().UnixNano()) + + // TODO(a.garipov): Set up logging. + + // # Web Service + + // TODO(a.garipov): Use in the Web service. + _ = clientBuildFS + + // TODO(a.garipov): Make configurable. + web := websvc.New(&websvc.Config{ + Addresses: []*netutil.IPPort{{ + IP: net.IP{127, 0, 0, 1}, + Port: 3001, + }}, + Timeout: 60 * time.Second, + }) + + err := web.Start() + fatalOnError(err) + + sigHdlr := newSignalHandler( + web, + ) + + go sigHdlr.handle() + + select {} +} + +// defaultTimeout is the timeout used for some operations where another timeout +// hasn't been defined yet. +const defaultTimeout = 15 * time.Second + +// ctxWithDefaultTimeout is a helper function that returns a context with +// timeout set to defaultTimeout. +func ctxWithDefaultTimeout() (ctx context.Context, cancel context.CancelFunc) { + return context.WithTimeout(context.Background(), defaultTimeout) +} + +// fatalOnError is a helper that exits the program with an error code if err is +// not nil. It must only be used within Main. +func fatalOnError(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/internal/v1/cmd/signal.go b/internal/v1/cmd/signal.go new file mode 100644 index 00000000..b9f09673 --- /dev/null +++ b/internal/v1/cmd/signal.go @@ -0,0 +1,70 @@ +package cmd + +import ( + "os" + + "github.com/AdguardTeam/AdGuardHome/internal/aghos" + "github.com/AdguardTeam/AdGuardHome/internal/v1/agh" + "github.com/AdguardTeam/golibs/log" +) + +// signalHandler processes incoming signals and shuts services down. +type signalHandler struct { + signal chan os.Signal + + // services are the services that are shut down before application + // exiting. + services []agh.Service +} + +// handle processes OS signals. +func (h *signalHandler) handle() { + defer log.OnPanic("signalProcessor.handle") + + for sig := range h.signal { + log.Info("sigproc: received signal %q", sig) + + if aghos.IsShutdownSignal(sig) { + h.shutdown() + } + } +} + +// Exit status constants. +const ( + statusSuccess = 0 + statusError = 1 +) + +// shutdown gracefully shuts down all services. +func (h *signalHandler) shutdown() { + ctx, cancel := ctxWithDefaultTimeout() + defer cancel() + + status := statusSuccess + + log.Info("sigproc: shutting down services") + for i, service := range h.services { + err := service.Shutdown(ctx) + if err != nil { + log.Error("sigproc: shutting down service at index %d: %s", i, err) + status = statusError + } + } + + log.Info("sigproc: shutting down adguard home") + + os.Exit(status) +} + +// newSignalHandler returns a new signalHandler that shuts down svcs. +func newSignalHandler(svcs ...agh.Service) (h *signalHandler) { + h = &signalHandler{ + signal: make(chan os.Signal, 1), + services: svcs, + } + + aghos.NotifyShutdownSignal(h.signal) + + return h +} diff --git a/internal/v1/websvc/websvc.go b/internal/v1/websvc/websvc.go new file mode 100644 index 00000000..e741ff3d --- /dev/null +++ b/internal/v1/websvc/websvc.go @@ -0,0 +1,185 @@ +// Package websvc contains the AdGuard Home web service. +// +// TODO(a.garipov): Add tests. +package websvc + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "net" + "net/http" + "sync" + "time" + + "github.com/AdguardTeam/AdGuardHome/internal/v1/agh" + "github.com/AdguardTeam/golibs/errors" + "github.com/AdguardTeam/golibs/log" + "github.com/AdguardTeam/golibs/netutil" +) + +// Config is the AdGuard Home web service configuration structure. +type Config struct { + // TLS is the optional TLS configuration. If TLS is not nil, + // SecureAddresses must not be empty. + TLS *tls.Config + + // Addresses are the addresses on which to serve the plain HTTP API. + Addresses []*netutil.IPPort + + // SecureAddresses are the addresses on which to serve the HTTPS API. If + // SecureAddresses is not empty, TLS must not be nil. + SecureAddresses []*netutil.IPPort + + // Timeout is the timeout for all server operations. + Timeout time.Duration +} + +// Service is the AdGuard Home web service. A nil *Service is a valid service +// that does nothing. +type Service struct { + tls *tls.Config + servers []*http.Server + timeout time.Duration +} + +// New returns a new properly initialized *Service. If c is nil, svc is a nil +// *Service that does nothing. +func New(c *Config) (svc *Service) { + if c == nil { + return nil + } + + svc = &Service{ + tls: c.TLS, + timeout: c.Timeout, + } + + mux := http.NewServeMux() + mux.HandleFunc("/health-check", svc.handleGetHealthCheck) + + for _, a := range c.Addresses { + addr := a.String() + errLog := log.StdLog("websvc: http: "+addr, log.ERROR) + svc.servers = append(svc.servers, &http.Server{ + Addr: addr, + Handler: mux, + ErrorLog: errLog, + ReadTimeout: c.Timeout, + WriteTimeout: c.Timeout, + IdleTimeout: c.Timeout, + ReadHeaderTimeout: c.Timeout, + }) + } + + for _, a := range c.SecureAddresses { + addr := a.String() + errLog := log.StdLog("websvc: https: "+addr, log.ERROR) + svc.servers = append(svc.servers, &http.Server{ + Addr: addr, + Handler: mux, + TLSConfig: c.TLS, + ErrorLog: errLog, + ReadTimeout: c.Timeout, + WriteTimeout: c.Timeout, + IdleTimeout: c.Timeout, + ReadHeaderTimeout: c.Timeout, + }) + } + + return svc +} + +// Addrs returns all addresses on which this server serves the HTTP API. Addrs +// must not be called until Start returns. +func (svc *Service) Addrs() (addrs []string) { + addrs = make([]string, 0, len(svc.servers)) + for _, srv := range svc.servers { + addrs = append(addrs, srv.Addr) + } + + return addrs +} + +// handleGetHealthCheck is the handler for the GET /health-check HTTP API. +func (svc *Service) handleGetHealthCheck(w http.ResponseWriter, _ *http.Request) { + _, _ = io.WriteString(w, "OK") +} + +// unit is a convenient alias for struct{}. +type unit = struct{} + +// type check +var _ agh.Service = (*Service)(nil) + +// Start implements the agh.Service interface for *Service. svc may be nil. +// After Start exits, all HTTP servers have tried to start, possibly failing and +// writing error messages to the log. +func (svc *Service) Start() (err error) { + if svc == nil { + return nil + } + + srvs := svc.servers + + wg := &sync.WaitGroup{} + wg.Add(len(srvs)) + for _, srv := range srvs { + go serve(srv, wg) + } + + wg.Wait() + + return nil +} + +// serve starts and runs srv and writes all errors into its log. +func serve(srv *http.Server, wg *sync.WaitGroup) { + addr := srv.Addr + defer log.OnPanic(addr) + + var l net.Listener + var err error + if srv.TLSConfig == nil { + l, err = net.Listen("tcp", addr) + } else { + l, err = tls.Listen("tcp", addr, srv.TLSConfig) + } + if err != nil { + srv.ErrorLog.Printf("starting srv %s: binding: %s", addr, err) + } + + // Update the server's address in case the address had the port zero, which + // would mean that a random available port was automatically chosen. + srv.Addr = l.Addr().String() + + log.Info("websvc: starting srv http://%s", srv.Addr) + wg.Done() + + err = srv.Serve(l) + if err != nil && !errors.Is(err, http.ErrServerClosed) { + srv.ErrorLog.Printf("starting srv %s: %s", addr, err) + } +} + +// Shutdown implements the agh.Service interface for *Service. svc may be nil. +func (svc *Service) Shutdown(ctx context.Context) (err error) { + if svc == nil { + return nil + } + + var errs []error + for _, srv := range svc.servers { + serr := srv.Shutdown(ctx) + if serr != nil { + errs = append(errs, fmt.Errorf("shutting down srv %s: %w", srv.Addr, serr)) + } + } + + if len(errs) > 0 { + return errors.List("shutting down") + } + + return nil +} diff --git a/internal/v1/websvc/websvc_test.go b/internal/v1/websvc/websvc_test.go new file mode 100644 index 00000000..01b892cd --- /dev/null +++ b/internal/v1/websvc/websvc_test.go @@ -0,0 +1,69 @@ +package websvc_test + +import ( + "context" + "io" + "net" + "net/http" + "net/url" + "testing" + "time" + + "github.com/AdguardTeam/AdGuardHome/internal/v1/websvc" + "github.com/AdguardTeam/golibs/netutil" + "github.com/AdguardTeam/golibs/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const testTimeout = 1 * time.Second + +func TestService_Start_getHealthCheck(t *testing.T) { + c := &websvc.Config{ + TLS: nil, + Addresses: []*netutil.IPPort{{ + IP: net.IP{127, 0, 0, 1}, + Port: 0, + }}, + SecureAddresses: nil, + Timeout: testTimeout, + } + + svc := websvc.New(c) + + err := svc.Start() + require.NoError(t, err) + t.Cleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), testTimeout) + t.Cleanup(cancel) + + err = svc.Shutdown(ctx) + require.NoError(t, err) + }) + + addrs := svc.Addrs() + require.Len(t, addrs, 1) + + u := &url.URL{ + Scheme: "http", + Host: addrs[0], + Path: "/health-check", + } + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + require.NoError(t, err) + + httpCli := &http.Client{ + Timeout: testTimeout, + } + resp, err := httpCli.Do(req) + require.NoError(t, err) + + testutil.CleanupAndRequireSuccess(t, resp.Body.Close) + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + assert.Equal(t, []byte("OK"), body) +} diff --git a/main.go b/main.go index 505eb3e5..03ad2f03 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,6 @@ +//go:build !v1 +// +build !v1 + package main import ( diff --git a/main_v1.go b/main_v1.go new file mode 100644 index 00000000..6b5f3dea --- /dev/null +++ b/main_v1.go @@ -0,0 +1,21 @@ +//go:build v1 +// +build v1 + +package main + +import ( + "embed" + + "github.com/AdguardTeam/AdGuardHome/internal/v1/cmd" +) + +// Embed the prebuilt client here since we strive to keep .go files inside the +// internal directory and the embed package is unable to embed files located +// outside of the same or underlying directory. + +//go:embed build2 +var clientBuildFS embed.FS + +func main() { + cmd.Main(clientBuildFS) +} diff --git a/openapi/v1.yaml b/openapi/v1.yaml new file mode 100644 index 00000000..30c318bc --- /dev/null +++ b/openapi/v1.yaml @@ -0,0 +1,4913 @@ +'openapi': '3.0.3' +'info': + 'contact': + 'email': 'devteam@adguard.com' + 'name': 'AdGuard Home' + 'url': 'https://github.com/AdguardTeam/AdGuardHome' + 'description': | + **!! WARNING! API IS AT THE DRAFT STAGE! THINGS WILL BREAK! !!** + + AdGuard Home REST API, V1 **DRAFT**. Our administration web interface is + built on top of this REST API. + + This API is currently a **DRAFT** and is not covered by any stability + guarantees. Once this API reaches maturity, the old `/control/` API will + mostly be removed. + + ## Information For API Users + + * Empty arrays are always sent by the backend, unless documented + otherwise. If the backend doesn't, it's a backend error. + + * `PATCH` requests with JSON bodies use RFC 7396 JSON Merge Patch unless + documented otherwise. + + * The property `x-error-class` on plain text error responses suggests, + which class of error should be used if the API user wants to wrap it + into an object. The property `x-error-code` suggest the error code for + the error object. The code usually goes into the `code` property, and + the content, into `msg`. + + * The property `x-skip-web-api` on operations suggests API clients for + web, like our frontend, to skip this operation in their generated code. + + * The header `Server` will be set to `AdGuardHome/<>`. For + example: `AdGuardHome/v0.107.0-a.42+abcd1234`. + + ## Conventions For API Authors + + ### Naming + + * `CapitalCamelCase` for entities. + + * Initialisms are spelled like `DhcpSettings` and not `DHCPSettings`. + + * `lower_snake_case` for path and query parameters. + + * No unit suffices. + + * Path parameters's names start with `Path`; query, with `Query`. + + * Requests end with `Req`; responses, with `Resp`. + + ### Structure + + * Add `400` and `422` responses to requests that accept data. + + * Add `401` responses, unless the method can work without authorization. + + * Add `500` responses. + + * Descriptions are always on their own lines. + + * Don't add a description if there is already one a level above. + + * Five levels of indentation max, except for descriptions and array + items. + + * Keep things in alphabetical order. + + * Mark required things as such. Document possibly-absent fields **both** + in `required` **and** in `description`, if there is one. + + * Prefer flat objects. Example: `resp.top_user`, not `resp.top.user.val`. + + * Prefer to make it easier for the frontend where possible. + + * Provide examples for requests and responses. If examples are provided + elsewhere, document that. + + * Summaries and descriptions with dots. + + * Top-level value in a JSON request or response must be an object. + + ### Types + + * Add `'maximum': 65535` for 16-bit unsigned integers (for example, port + numbers). + + * Add `'minimum': 0` for unsigned integers. + + * Duration in milliseconds. Time in milliseconds in the Unix epoch. Both + of type `double`, because that is easier for the JS frontend. + + * Integers are always `int64`, numbers are always `double. + + 'license': + 'name': 'GNU General Public License v3.0' + 'url': 'https://www.gnu.org/licenses/gpl-3.0.txt' + 'title': 'AdGuard Home V1 DRAFT API' + 'version': '0.108' + +'servers': +- 'description': > + The V1 HTTP API namespace. + 'url': '/api/v1' + +'security': +- 'basicAuth': [] + +'tags': +- 'description': > + Authorization and account management. + 'name': 'accounts' +- 'description': > + Configuration and settings for Apple products. + 'name': 'apple' +- 'description': > + Runtime and persistent client information. + 'name': 'clients' +- 'description': > + DHCP server methods. + 'name': 'dhcp' +- 'description': > + First-time install configuration handlers. Will not be available once the + installation is done. + 'name': 'install' +- 'description': > + Query logs. + 'name': 'log' +- 'description': > + Filter lists, blocked services, and custom filtering rules. + 'name': 'protection' +- 'description': > + Settings management. + 'name': 'settings' +- 'description': > + Query, filtering, system, and other statistics. + 'name': 'stats' +- 'description': > + Information about the AdGuard Home server and the host system. + 'name': 'system' + +'paths': + '/health-check': + 'get': + 'operationId': 'HealthCheck' + 'servers': + - 'url': '/' + 'summary': 'Check if the server is up.' + 'tags': + - 'system' + + '/accounts/profile': + 'get': + 'operationId': 'GetV1AccountsProfile' + 'responses': + '200': + '$ref': '#/components/responses/GetV1AccountsProfileResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get the profile of the current user.' + 'tags': + - 'accounts' + 'patch': + 'operationId': 'PatchV1AccountsProfile' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1AccountsProfileReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1AccountsProfileResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update the profile of the current user.' + 'tags': + - 'accounts' + + '/accounts/session': + 'delete': + 'operationId': 'DeleteV1AccountsSession' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Log out of the system.' + 'tags': + - 'accounts' + 'post': + 'operationId': 'PostV1AccountsSession' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1AccountsSessionReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Log into the system.' + 'tags': + - 'accounts' + + '/apple/doh.mobileconfig': + 'get': + 'operationId': 'GetV1AppleDohMobileconfig' + 'parameters': + - '$ref': '#/components/parameters/QueryClientId' + - '$ref': '#/components/parameters/QueryHost' + 'responses': + '200': + '$ref': '#/components/responses/GetV1AppleDohMobileconfigResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get a DNS-over-HTTPS .mobileconfig.' + 'tags': + - 'apple' + 'x-skip-web-api': true + + '/apple/dot.mobileconfig': + 'get': + 'operationId': 'GetV1AppleDotMobileconfig' + 'parameters': + - '$ref': '#/components/parameters/QueryHost' + - '$ref': '#/components/parameters/QueryClientId' + 'responses': + '200': + '$ref': '#/components/responses/GetV1AppleDotMobileconfigResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get a DNS-over-HTTPS .mobileconfig.' + 'tags': + - 'apple' + 'x-skip-web-api': true + + '/clients/persistent': + 'get': + 'operationId': 'GetV1ClientsPersistent' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ClientsPersistentResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all persistent clients.' + 'tags': + - 'clients' + 'post': + 'operationId': 'PostV1ClientsPersistent' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ClientsPersistentReq' + 'responses': + '201': + '$ref': '#/components/responses/PostV1ClientsPersistentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Create a new persistent client.' + 'tags': + - 'clients' + + '/clients/persistent/{client_uid}': + 'delete': + 'operationId': 'DeleteV1ClientPersistent' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Delete a persistent client.' + 'tags': + - 'clients' + 'parameters': + - '$ref': '#/components/parameters/PathClientUid' + 'patch': + 'operationId': 'PatchV1ClientPersistent' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1ClientPersistentReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1ClientPersistentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update a persistent client.' + 'tags': + - 'clients' + + '/clients/runtime': + 'get': + 'operationId': 'GetV1ClientsRuntime' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ClientsRuntimeResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all runtime clients.' + 'tags': + - 'clients' + + '/dhcp/leases': + 'get': + 'operationId': 'GetV1DhcpLeases' + 'responses': + '200': + '$ref': '#/components/responses/GetV1DhcpLeasesResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all dynamic and static DHCP leases.' + 'tags': + - 'dhcp' + 'post': + 'operationId': 'PostV1DhcpLeases' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1DhcpLeasesReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1DhcpLeasesResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Create a new static DHCP lease.' + 'tags': + - 'dhcp' + + '/dhcp/leases/{lease_uid}': + 'delete': + 'operationId': 'DeleteV1DhcpLease' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Delete a static DHCP lease.' + 'tags': + - 'dhcp' + 'parameters': + - '$ref': '#/components/parameters/PathLeaseUid' + 'patch': + 'operationId': 'PatchV1DhcpLease' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1DhcpLeaseReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1DhcpLeaseResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update a static DHCP lease.' + 'tags': + - 'dhcp' + + '/dhcp/status': + 'get': + 'operationId': 'GetV1DhcpStatus' + 'responses': + '200': + '$ref': '#/components/responses/GetV1DhcpStatusResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get DHCP server status.' + 'tags': + - 'dhcp' + + '/install/check': + 'post': + 'operationId': 'PostV1InstallCheck' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1InstallCheckReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1InstallCheckResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Check initial configuration.' + 'tags': + - 'install' + + '/install/configure': + 'post': + 'operationId': 'PostV1InstallConfigure' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1InstallConfigureReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Apply initial configuration.' + 'tags': + - 'install' + + '/install/info': + 'get': + 'operationId': 'GetV1InstallInfo' + 'responses': + '200': + '$ref': '#/components/responses/GetV1InstallInfoResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get initial configuration information.' + 'tags': + - 'install' + + '/log/clear': + 'post': + 'operationId': 'PostV1LogClear' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1LogClearReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Clear the whole query log.' + 'tags': + - 'log' + + '/log/search': + 'get': + 'operationId': 'GetV1LogSearch' + 'parameters': + - '$ref': '#/components/parameters/QueryBefore' + - '$ref': '#/components/parameters/QueryLimit' + - '$ref': '#/components/parameters/QueryReason' + - '$ref': '#/components/parameters/QueryTerm' + 'responses': + '200': + '$ref': '#/components/responses/GetV1LogSearchResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Search query logs.' + 'tags': + - 'log' + + '/protection/blocked_services': + 'get': + 'operationId': 'GetV1ProtectionBlockedServices' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ProtectionBlockedServicesResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get blocked services.' + 'tags': + - 'protection' + 'put': + 'operationId': 'PutV1ProtectionBlockedServices' + 'requestBody': + '$ref': '#/components/requestBodies/PutV1ProtectionBlockedServicesReq' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ProtectionBlockedServicesResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Replace blocked services.' + 'tags': + - 'protection' + + '/protection/check_custom_rules': + 'post': + 'operationId': 'PostV1ProtectionCheckCustomRules' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ProtectionCheckCustomRulesReq' + 'responses': + '201': + '$ref': '#/components/responses/PostV1ProtectionCheckCustomRulesResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Check custom filtering rules.' + 'tags': + - 'protection' + + '/protection/custom_rules': + 'get': + 'operationId': 'GetV1ProtectionCustomRules' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ProtectionCustomRulesResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get custom rules.' + 'tags': + - 'protection' + 'put': + 'operationId': 'PutV1ProtectionCustomRules' + 'requestBody': + '$ref': '#/components/requestBodies/PutV1ProtectionCustomRulesReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Replace custom rules.' + 'tags': + - 'protection' + + '/protection/dns_rewrites': + 'get': + 'operationId': 'GetV1ProtectionDnsRewrites' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ProtectionDnsRewritesResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all classic DNS rewrites.' + 'tags': + - 'protection' + 'post': + 'operationId': 'PostV1ProtectionDnsRewrites' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ProtectionDnsRewritesReq' + 'responses': + '201': + '$ref': '#/components/responses/PostV1ProtectionDnsRewritesResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Add a new classic DNS rewrite.' + 'tags': + - 'protection' + + '/protection/dns_rewrites/{dns_rewrite_uid}': + 'delete': + 'operationId': 'DeleteV1ProtectionDnsRewrite' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Delete a classic DNS rewrite.' + 'tags': + - 'protection' + 'parameters': + - '$ref': '#/components/parameters/PathDnsRewriteUid' + + '/protection/filters': + 'get': + 'operationId': 'GetV1ProtectionFilters' + 'responses': + '200': + '$ref': '#/components/responses/GetV1ProtectionFiltersResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all filters.' + 'tags': + - 'protection' + 'post': + 'operationId': 'PostV1ProtectionFilters' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ProtectionFiltersReq' + 'responses': + '201': + '$ref': '#/components/responses/PostV1ProtectionFiltersResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Add a new filter.' + 'tags': + - 'protection' + + '/protection/filters/{filter_uid}': + 'delete': + 'operationId': 'DeleteV1ProtectionFilter' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Delete a filter.' + 'tags': + - 'protection' + 'parameters': + - '$ref': '#/components/parameters/PathFilterUid' + 'patch': + 'operationId': 'PatchV1ProtectionFilter' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1ProtectionFilterReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1ProtectionFilterResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '404': + '$ref': '#/components/responses/NotFoundResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': > + Update a filter's settings. + 'tags': + - 'protection' + + '/protection/refresh_filters': + 'post': + 'operationId': 'PostV1ProtectionRefreshFilters' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ProtectionRefreshFiltersReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1ProtectionRefreshFiltersResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': > + Refresh all filters. + 'tags': + - 'protection' + + '/protection/refresh_filters/{filter_uid}': + 'parameters': + - '$ref': '#/components/parameters/PathFilterUid' + 'post': + 'operationId': 'PostV1ProtectionRefreshFilter' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1ProtectionRefreshFilterReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1ProtectionRefreshFilterResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': > + Refresh a filter. + 'tags': + - 'protection' + + '/settings/all': + 'get': + 'operationId': 'GetV1SettingsAll' + 'responses': + '200': + '$ref': '#/components/responses/GetV1SettingsAllResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all settings.' + 'tags': + - 'settings' + + '/settings/dhcp': + 'patch': + 'operationId': 'PatchV1SettingsDhcp' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsDhcpReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsDhcpResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update DHCP server settings.' + 'tags': + - 'settings' + + '/settings/dns': + 'patch': + 'operationId': 'PatchV1SettingsDns' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsDnsReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsDnsResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update DNS server settings.' + 'tags': + - 'settings' + + '/settings/dns/access': + 'get': + 'description': > + Get DNS access settings. This is a separate API, because these lists + can become quite big. + 'operationId': 'GetV1SettingsDnsAccess' + 'responses': + '200': + '$ref': '#/components/responses/GetV1SettingsDnsAccessResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get DNS access settings.' + 'tags': + - 'settings' + 'put': + 'description': > + Update DNS access settings. This is a separate API, because these lists + can become quite big. + 'operationId': 'PutV1SettingsDnsAccess' + 'requestBody': + '$ref': '#/components/requestBodies/PutV1SettingsDnsAccessReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update DNS access settings.' + 'tags': + - 'settings' + + '/settings/dns/check': + 'post': + 'operationId': 'PostV1SettingsDnsCheck' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1SettingsDnsCheckReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1SettingsDnsCheckResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Check DNS upstream settings.' + 'tags': + - 'settings' + + '/settings/log': + 'patch': + 'operationId': 'PatchV1SettingsLog' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsLogReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsLogResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update query logging settings.' + 'tags': + - 'settings' + + '/settings/protection': + 'patch': + 'operationId': 'PatchV1SettingsProtection' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsProtectionReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsProtectionResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update protection settings.' + 'tags': + - 'settings' + + '/settings/stats': + 'patch': + 'operationId': 'PatchV1SettingsStats' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsStatsReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsStatsResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update statistics settings.' + 'tags': + - 'settings' + + '/settings/tls': + 'patch': + 'operationId': 'PatchV1SettingsTls' + 'requestBody': + '$ref': '#/components/requestBodies/PatchV1SettingsTlsReq' + 'responses': + '200': + '$ref': '#/components/responses/PatchV1SettingsTlsResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update TLS and encryption settings.' + 'tags': + - 'settings' + + '/settings/tls/check': + 'post': + 'operationId': 'PostV1SettingsTlsCheck' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1SettingsTlsCheckReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1SettingsTlsCheckResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Check TLS and encryption settings.' + 'tags': + - 'settings' + + '/stats/all': + 'get': + 'operationId': 'GetV1StatsAll' + 'responses': + '200': + '$ref': '#/components/responses/GetV1StatsAllResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get all statistics.' + 'tags': + - 'stats' + + '/stats/clear': + 'post': + 'operationId': 'PostV1StatsClear' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1StatsClearReq' + 'responses': + '204': + '$ref': '#/components/responses/NoContentResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Clear all statistics.' + 'tags': + - 'stats' + + '/system/info': + 'get': + 'operationId': 'GetV1SystemInfo' + 'responses': + '200': + '$ref': '#/components/responses/GetV1SystemInfoResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Get server information.' + 'tags': + - 'system' + + '/system/reset': + 'post': + 'operationId': 'PostV1SystemReset' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1SystemResetReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1SystemResetResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Reset all settings to defaults.' + 'tags': + - 'system' + + '/system/update': + 'post': + 'operationId': 'PostV1SystemUpdate' + 'requestBody': + '$ref': '#/components/requestBodies/PostV1SystemUpdateReq' + 'responses': + '200': + '$ref': '#/components/responses/PostV1SystemUpdateResp' + '400': + '$ref': '#/components/responses/BadRequestResp' + '401': + '$ref': '#/components/responses/UnauthorizedResp' + '422': + '$ref': '#/components/responses/UnprocessableEntityResp' + '500': + '$ref': '#/components/responses/InternalServerErrorResp' + 'summary': 'Update AdGuard Home.' + 'tags': + - 'system' + +'components': + 'parameters': + 'PathDnsRewriteUid': + 'description': > + DNS rewrite ID. + 'example': 'abcd1234' + 'in': 'path' + 'name': 'dns_rewrite_uid' + 'required': true + 'schema': + '$ref': '#/components/schemas/Uid' + + 'PathClientUid': + 'description': > + The unique ID of a client. + 'example': 'abcd1234' + 'in': 'path' + 'name': 'client_uid' + 'required': true + 'schema': + '$ref': '#/components/schemas/Uid' + + 'PathFilterUid': + 'description': > + The ID of a filter. + 'example': 'abcd1234' + 'in': 'path' + 'name': 'filter_uid' + 'required': true + 'schema': + '$ref': '#/components/schemas/Uid' + + 'PathLeaseUid': + 'description': > + The ID of a static lease. + 'example': 'abcd1234' + 'in': 'path' + 'name': 'lease_uid' + 'required': true + 'schema': + '$ref': '#/components/schemas/Uid' + + 'QueryBefore': + 'description': > + Unix time, before which to show the search results, in milliseconds. + 'example': 1614345496000 + 'in': 'query' + 'name': 'before' + 'required': false + 'schema': + 'format': 'double' + 'type': 'number' + + 'QueryClientId': + 'description': > + ClientID, **not** its UID. + 'example': 'client-1' + 'in': 'query' + 'name': 'client_id' + 'required': false + 'schema': + '$ref': '#/components/schemas/ClientId' + + 'QueryHost': + 'description': > + The host for which the Configuration is generated. + 'example': 'example.org' + 'in': 'query' + 'name': 'host' + 'required': true + 'schema': + 'type': 'string' + + 'QueryLimit': + 'description': > + Maximum amount of records to return. + 'example': 100 + 'in': 'query' + 'name': 'limit' + 'required': false + 'schema': + 'format': 'int64' + 'type': 'integer' + + 'QueryReason': + 'description': > + Filter query log results by filtering reason. + 'example': 'not_filtered_notfound' + 'in': 'query' + 'name': 'reason' + 'required': false + 'schema': + '$ref': '#/components/schemas/FilteringReason' + + 'QueryTerm': + 'description': > + Search term. + 'example': '127.0.0.1' + 'in': 'query' + 'name': 'term' + 'required': false + 'schema': + 'type': 'string' + + 'requestBodies': + 'PatchV1AccountsProfileReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1AccountsProfileReq' + 'required': true + + 'PatchV1ClientPersistentReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1ClientPersistentReq' + 'required': true + + 'PatchV1DhcpLeaseReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1DhcpLeaseReq' + 'required': true + + 'PatchV1ProtectionFilterReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1ProtectionFilterReq' + 'required': true + + 'PatchV1SettingsDhcpReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsDhcpReq' + 'required': true + + 'PatchV1SettingsDnsReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsDnsReq' + 'required': true + + 'PatchV1SettingsLogReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsLogReq' + 'required': true + + 'PatchV1SettingsProtectionReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsProtectionReq' + 'required': true + + 'PatchV1SettingsStatsReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsStatsReq' + 'required': true + + 'PatchV1SettingsTlsReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsTlsReq' + 'required': true + + 'PostV1AccountsSessionReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1AccountsSessionReq' + 'required': true + + 'PostV1ClientsPersistentReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ClientsPersistentReq' + 'required': true + + 'PostV1DhcpLeasesReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1DhcpLeasesReq' + 'required': true + + 'PostV1InstallCheckReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1InstallCheckReq' + 'required': true + + 'PostV1InstallConfigureReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1InstallConfigureReq' + 'required': true + + 'PostV1LogClearReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1LogClearReq' + 'required': true + + 'PostV1ProtectionCheckCustomRulesReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionCheckCustomRulesReq' + 'required': true + + 'PostV1ProtectionDnsRewritesReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionDnsRewritesReq' + 'required': true + + 'PostV1ProtectionFiltersReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionFiltersReq' + 'required': true + + 'PostV1ProtectionRefreshFilterReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionRefreshFilterReq' + 'required': true + + 'PostV1ProtectionRefreshFiltersReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionRefreshFiltersReq' + 'required': true + + 'PostV1SettingsDnsCheckReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SettingsDnsCheckReq' + 'required': true + + 'PostV1SettingsTlsCheckReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SettingsTlsCheckReq' + 'required': true + + 'PostV1StatsClearReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1StatsClearReq' + 'required': true + + 'PostV1SystemResetReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SystemResetReq' + 'required': true + + 'PostV1SystemUpdateReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SystemUpdateReq' + 'required': true + + 'PutV1ProtectionBlockedServicesReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PutV1ProtectionBlockedServicesReq' + 'required': true + + 'PutV1ProtectionCustomRulesReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PutV1ProtectionCustomRulesReq' + 'required': true + + 'PutV1SettingsDnsAccessReq': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PutV1SettingsDnsAccessReq' + 'required': true + + 'responses': + 'BadRequestResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/BadRequestResp' + 'text/plain': + 'example': >- + invalid character '{' looking for beginning of object key string + 'x-error-class': '#/components/schemas/BadRequestResp' + 'x-error-code': 'TXT400' + 'description': > + Generic bad request response. Sent when the request data is malformed + (for example, invalid JSON). + + 'GetV1AccountsProfileResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1AccountsProfileResp' + 'description': > + A successful response to a `GET /api/v1/accounts/profile` request. + + 'GetV1AppleDohMobileconfigResp': + 'content': + 'application/xml': + 'schema': + '$ref': '#/components/schemas/GetV1AppleDohMobileconfigResp' + 'description': > + A successful response to a `GET /api/v1/apple/doh.mobileconfig` request. + + 'GetV1AppleDotMobileconfigResp': + 'content': + 'application/xml': + 'schema': + '$ref': '#/components/schemas/GetV1AppleDotMobileconfigResp' + 'description': > + A successful response to a `GET /api/v1/apple/dot.mobileconfig` request. + + 'GetV1ClientsPersistentResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ClientsPersistentResp' + 'description': > + A successful response to a `GET /api/v1/clients/persistent` request. + + 'GetV1ClientsRuntimeResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ClientsRuntimeResp' + 'description': > + A successful response to a `GET /api/v1/clients/runtime` request. + + 'GetV1DhcpLeasesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1DhcpLeasesResp' + 'description': > + A successful response to a `GET /api/v1/dhcp/leases` request. + + 'GetV1DhcpStatusResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1DhcpStatusResp' + 'description': > + A successful response to a `GET /api/v1/dhcp/status` request. + + 'GetV1InstallInfoResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1InstallInfoResp' + 'description': > + A successful response to a `GET /api/v1/install/info` request. + + 'GetV1LogSearchResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1LogSearchResp' + 'description': > + A successful response to a `GET /api/v1/log/search` request. + + 'GetV1ProtectionBlockedServicesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ProtectionBlockedServicesResp' + 'description': > + A successful response to a `GET /api/v1/protection/blocked_services` + or a `PUT /api/v1/protection/blocked_services` request. + + 'GetV1ProtectionCustomRulesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ProtectionCustomRulesResp' + 'description': > + A successful response to a `GET /api/v1/protection/custom_rules` + request. + + 'GetV1ProtectionDnsRewritesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ProtectionDnsRewritesResp' + 'description': > + A successful response to a `GET /api/v1/protection/dns_rewrites` + request. + + 'GetV1ProtectionFiltersResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1ProtectionFiltersResp' + 'description': > + A successful response to a `GET /api/v1/protection/filters` request. + + 'GetV1SettingsAllResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1SettingsAllResp' + 'description': > + A successful response to a `GET /api/v1/settings/all` request. + + 'GetV1SettingsDnsAccessResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1SettingsDnsAccessResp' + 'description': > + A successful response to a `GET /api/v1/settings/dns/access` request. + + 'GetV1StatsAllResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1StatsAllResp' + 'description': > + A successful response to a `GET /api/v1/stats/all` request. + + 'GetV1SystemInfoResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/GetV1SystemInfoResp' + 'description': > + A successful response to a `GET /api/v1/server/info` request. + + 'InternalServerErrorResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/InternalServerErrorResp' + 'text/plain': + 'example': >- + runtime error: invalid memory address or nil pointer dereference + 'x-error-class': '#/components/schemas/InternalServerErrorResp' + 'x-error-code': 'TXT500' + 'description': > + Generic internal server error. + + 'NoContentResp': + 'description': > + Generic no-error no-content response. + + 'NotFoundResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/NotFoundResp' + 'text/plain': + 'example': >- + Not found. + 'x-error-class': '#/components/schemas/NotFoundResp' + 'x-error-code': 'TXT404' + 'description': > + Generic not found response. + + 'PatchV1AccountsProfileResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1AccountsProfileResp' + 'description': > + A successful response to a `PATCH /api/v1/accounts/profile` request. + + 'PatchV1ClientPersistentResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1ClientPersistentResp' + 'description': > + A successful response to + a `PATCH /api/v1/clients/persistent/{client_uid}` request. + + 'PatchV1DhcpLeaseResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1DhcpLeaseResp' + 'description': > + A successful response to a `PATCH /api/v1/dhcp/leases/{lease_uid}` + request. + + 'PatchV1ProtectionFilterResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1ProtectionFilterResp' + 'description': > + A successful response to a `PATCH /api/v1/filters/{filter_uid}` request. + + 'PatchV1SettingsDhcpResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsDhcpResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/dhcp` request. + + 'PatchV1SettingsDnsResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsDnsResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/dns` request. + + 'PatchV1SettingsLogResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsLogResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/log` request. + + 'PatchV1SettingsProtectionResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsProtectionResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/protection` request. + + 'PatchV1SettingsStatsResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsStatsResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/stats` request. + + 'PatchV1SettingsTlsResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PatchV1SettingsTlsResp' + 'description': > + A successful response to a `PATCH /api/v1/settings/tls` request. + + 'PostV1ClientsPersistentResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ClientsPersistentResp' + 'description': > + A successful response to a `POST /api/v1/clients/persistent` request. + + 'PostV1DhcpLeasesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1DhcpLeasesResp' + 'description': > + A successful response to a `POST /api/v1/dhcp/leases` request. + + 'PostV1InstallCheckResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1InstallCheckResp' + 'description': > + A successful response to a `POST /api/v1/install/check` request. + + 'PostV1ProtectionCheckCustomRulesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionCheckCustomRulesResp' + 'description': > + A successful response to a `POST /api/v1/protection/check_custom_rules` + request. + + 'PostV1ProtectionDnsRewritesResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionDnsRewritesResp' + 'description': > + A successful response to a `POST /api/v1/protection/dns_rewrites` + request. + + 'PostV1ProtectionFiltersResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionFiltersResp' + 'description': > + A successful response to a `POST /api/v1/protection/filters` request. + + 'PostV1ProtectionRefreshFilterResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionRefreshFilterResp' + 'description': > + A successful response to + a `POST /api/v1/protection/refresh_filters/{filter_uid}` request. + + 'PostV1ProtectionRefreshFiltersResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1ProtectionRefreshFiltersResp' + 'description': > + A successful response to a `POST /api/v1/protection/refresh_filters` + request. + + 'PostV1SettingsDnsCheckResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SettingsDnsCheckResp' + 'description': > + A successful response to a `POST /api/v1/settings/dns/check` request. + + 'PostV1SettingsTlsCheckResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SettingsTlsCheckResp' + 'description': > + A successful response to a `POST /api/v1/settings/tls/check` request. + + 'PostV1SystemResetResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SystemResetResp' + 'description': > + A successful response to a `POST /api/v1/system/reset` request. + + 'PostV1SystemUpdateResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/PostV1SystemUpdateResp' + 'description': > + A successful response to a `POST /api/v1/system/update` request. + + 'UnauthorizedResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/UnauthorizedResp' + 'text/plain': + 'example': 'no or bad authorization provided' + 'x-error-class': '#/components/schemas/UnauthorizedResp' + 'x-error-code': 'TXT401' + 'description': > + This API requires authorization. + 'headers': + 'WWW-Authenticate': + 'description': > + The required WWW-Authenticate header. + 'example': 'Basic realm="AdGuard Home", charset="UTF-8"' + 'required': true + 'schema': + 'type': 'string' + + 'UnprocessableEntityResp': + 'content': + 'application/json': + 'schema': + '$ref': '#/components/schemas/UnprocessableEntityResp' + 'description': > + Generic bad request data response. Sent when the request data is + well-formed but is invalid for this request. + + 'schemas': + 'BadRequestResp': + 'example': + 'code': 'JSN000' + 'msg': >- + invalid character '{' looking for beginning of object key string + 'properties': + 'code': + '$ref': '#/components/schemas/ErrorCode' + 'msg': + 'description': > + Error message string. + 'type': 'string' + 'required': + - 'code' + - 'msg' + 'type': 'object' + + 'BlockedServiceId': + 'description': > + ID of a blocked service. + 'enum': + - '9gag' + - 'amazon' + - 'cloudflare' + - 'dailymotion' + - 'discord' + - 'disneyplus' + - 'ebay' + - 'epic_games' + - 'facebook' + - 'hulu' + - 'imgur' + - 'instagram' + - 'mail_ru' + - 'netflix' + - 'ok' + - 'origin' + - 'pinterest' + - 'qq' + - 'reddit' + - 'skype' + - 'snapchat' + - 'spotify' + - 'steam' + - 'telegram' + - 'tiktok' + - 'tinder' + - 'twitch' + - 'twitter' + - 'viber' + - 'vimeo' + - 'vk' + - 'wechat' + - 'weibo' + - 'whatsapp' + - 'youtube' + 'type': 'string' + + 'BlockedServices': + 'description': > + Blocked services. + 'example': + 'services': + - '9gag' + - 'dailymotion' + 'properties': + 'services': + 'description': > + All blocked services. + 'items': + '$ref': '#/components/schemas/BlockedServiceId' + 'type': 'array' + 'required': + - 'services' + 'type': 'object' + + 'Channel': + 'description': > + AdGuard Home release channel. + 'enum': + - 'beta' + - 'development' + - 'edge' + - 'release' + 'type': 'string' + + 'ClientId': + 'pattern': '[0-9a-z-]{1,64}' + 'type': 'string' + + 'ClientInfo': + 'description': > + A shorter information about a client. If the `uid` field is present, + this is a persistent client. Otherwise, this is a runtime client. + 'properties': + 'blocked': + 'description': > + If `true`, client is blocked. + 'type': 'boolean' + 'ids': + 'description': | + Client identifiers. That includes ClientIDs set by users as well as + IP addresses. There must be at least one identifier. + + Not to be confused with the `uid` field. + 'example': + - '1.2.3.4' + - 'user-1' + 'items': + 'type': 'string' + 'minItems': 1 + 'type': 'array' + 'name': + 'description': > + The name of the client, if any. If there are none, this field is + absent. + 'example': 'User 1' + 'type': 'string' + 'num': + 'description': > + Total number of requests for this client. + 'example': 1000 + 'format': 'int64' + 'type': 'integer' + 'num_blocked': + 'description': > + Total number of blocked requests for this client. + 'example': 1000 + 'format': 'int64' + 'type': 'integer' + 'uid': + '$ref': '#/components/schemas/Uid' + 'whois': + '$ref': '#/components/schemas/Whois' + 'required': + - 'blocked' + - 'ids' + - 'num' + - 'num_blocked' + 'type': 'object' + + 'CustomRules': + 'description': > + Custom filtering rules. + 'example': + 'rules': + - '||example.com' + - '# Some comment' + 'properties': + 'rules': + 'description': > + All custom filtering rules + 'items': + 'type': 'string' + 'type': 'array' + 'required': + - 'rules' + 'type': 'object' + + 'DhcpLease': + 'allOf': + - '$ref': '#/components/schemas/DhcpLeasePost' + - 'description': > + A dynamic or static DHCP lease. If the `uid` field is present, this is + a static lease. Otherwise, this is a dynamic lease. + 'example': + 'expires': 1614345496000 + 'hostname': 'my-mobile' + 'ip': '192.168.1.2' + 'mac': '01:23:45:67:89:ab' + 'uid': 'abcd1234' + 'properties': + 'uid': + '$ref': '#/components/schemas/Uid' + + 'DhcpLeasePatch': + 'description': > + A static DHCP lease update object. + 'example': + 'expires': 1614345496000 + 'properties': + 'expires': + 'description': > + The Unix time of the lease's expiry time, in milliseconds. + 'format': 'double' + 'type': 'number' + 'hostname': + 'description': > + Client's hostname. + 'type': 'string' + 'ip': + 'description': > + IP address leased to the client. + 'type': 'string' + 'mac': + 'description': > + Hardware address of the lease client. + 'type': 'string' + 'type': 'object' + + 'DhcpLeasePost': + 'allOf': + - '$ref': '#/components/schemas/DhcpLeasePatch' + - 'description': > + A static DHCP lease create object. + 'example': + 'expires': 1614345496000 + 'hostname': 'my-mobile' + 'ip': '192.168.1.2' + 'mac': '01:23:45:67:89:ab' + 'required': + - 'expires' + - 'hostname' + - 'ip' + - 'mac' + + 'DhcpSettings': + 'allOf': + - '$ref': '#/components/schemas/DhcpSettingsPatch' + - 'description': > + DHCP server settings. + 'example': + 'enabled': true + 'interface_name': 'wlan0' + 'ipv4_gateway_ip': '192.168.1.1' + 'ipv4_lease_duration': 86400000 + 'ipv4_range_end': '192.168.1.101' + 'ipv4_range_start': '192.168.1.2' + 'ipv4_subnet_mask': '255.255.255.0' + 'ipv6_range_start': '2001:db8::1' + 'ipv6_lease_duration': 86400000 + 'required': + - 'enabled' + + 'DhcpSettingsPatch': + 'description': > + DHCP server settings update object. + 'example': + 'enabled': true + 'interface_name': 'wlan0' + 'ipv4_gateway_ip': '192.168.1.1' + 'ipv4_lease_duration': 86400000 + 'ipv4_range_end': '192.168.1.101' + 'ipv4_range_start': '192.168.1.2' + 'ipv4_subnet_mask': '255.255.255.0' + 'properties': + 'enabled': + 'description': > + If `true`, the DHCP server is enabled. + 'type': 'boolean' + 'interface_name': + 'description': > + The name of network interface to serve on. + 'type': 'string' + 'ipv4_gateway_ip': + 'description': > + The IP address of the gateway. + 'type': 'string' + 'ipv4_lease_duration': + 'description': > + The duration of the IPv4 lease, in milliseconds. + 'type': 'number' + 'ipv4_range_end': + 'description': > + The end of the IPv4 addresses to serve to clients. + 'type': 'string' + 'ipv4_range_start': + 'description': > + The start of the IPv4 addresses to serve to clients. + 'type': 'string' + 'ipv4_subnet_mask': + 'description': > + The IP subnet mask. + 'type': 'string' + 'ipv6_lease_duration': + 'description': > + The duration of the IPv6 lease, in milliseconds. + 'type': 'number' + 'ipv6_range_start': + 'description': > + The start of the IPv6 addresses to serve to clients. + 'type': 'string' + 'type': 'object' + + 'DnsAccessSettings': + 'description': > + DNS server access settings. + 'example': + 'allowed_clients': [] + 'blocked_clients': + - '1.2.3.4' + - '5.6.7.8/16' + 'blocked_domain_rules': + - 'id.server' + - '*.example.org' + - '||example.com^' + 'properties': + 'allowed_clients': + 'description': > + CIDR or IP addresses of clients in the allowlist. If non-empty, + AdGuard Home will accept requests from these IP addresses only. + 'items': + 'type': 'string' + 'type': 'array' + 'blocked_clients': + 'description': > + CIDR or IP addresses of clients in the blocklist. If non-empty, + AdGuard Home will drop requests from these IP addresses. + 'items': + 'type': 'string' + 'type': 'array' + 'blocked_domain_rules': + 'description': > + AdGuard Home will drop DNS queries, if the domains in their queries + match these rules. Here you can specify the exact domain + names, wildcards, and `urlfilter` rules. Examples: + + * `example.org` + + * `*.example.org` + + * `||example.org^` + 'items': + 'type': 'string' + 'type': 'array' + 'required': + - 'allowed_clients' + - 'blocked_clients' + - 'blocked_domain_rules' + 'type': 'object' + + 'DnsBlockingMode': + 'description': | + DNS blocking mode. + + * `custom_ip`: Respond with a custom IP address. If this mode is + selected, both `blocking_ipv4` and `blocking_ipv6` parameters must + be set. + + * `default`: Same as `null_ip` for Adblock-style rules, but respond + with the IP address specified in the rule when blocked by an + `/etc/hosts`-style rule. + + * `null_ip`: Respond with a zero IP address: `0.0.0.0` for `A` + requests and `::` for `AAAA` ones. + + * `nxdomain`: Respond with the `NXDOMAIN` code. + + * `refused`: Respond with the `REFUSET` code. + + 'enum': + - 'custom_ip' + - 'default' + - 'null_ip' + - 'nxdomain' + - 'refused' + 'type': 'string' + + 'DnsClass': + 'description': > + DNS resource record class, aka `CLASS`. + 'enum': + - 'any' + - 'ch' + - 'cs' + - 'hs' + - 'in' + 'type': 'string' + + 'DnsProto': + 'description': > + DNS protocol. + 'enum': + - 'dot' + - 'doh' + - 'doq' + - 'dnscrypt' + - 'udp' + 'type': 'string' + + 'DnsResponseCode': + 'description': > + DNS response code, aka `RCODE`. + 'enum': + - 'badalg' + - 'badcookie' + - 'badkey' + - 'badmode' + - 'badname' + - 'badsig' + - 'badtime' + - 'badtrunc' + - 'badvers' + - 'formerr' + - 'noerror' + - 'notauth' + - 'notimp' + - 'notzone' + - 'nxdomain' + - 'nxrrset' + - 'refused' + - 'servfail' + - 'yxdomain' + - 'yxrrset' + 'type': 'string' + + 'DnsRewrite': + 'allOf': + - '$ref': '#/components/schemas/DnsRewritePost' + - 'description': > + A classic DNS rewrite. + 'example': + 'answer': 'A' + 'domain': 'example.com' + 'id': 'abcd1234' + 'properties': + 'id': + '$ref': '#/components/schemas/Uid' + 'required': + - 'answer' + - 'domain' + - 'id' + 'type': 'object' + + 'DnsRewritePost': + 'description': > + A classic DNS rewrite create object. + 'example': + 'answer': 'A' + 'domain': 'example.com' + 'properties': + 'answer': + 'description': > + The value of an `A`, `AAAA`, or `CNAME` DNS record in the response. + Acceptable formats: + + * Domain name: add a `CNAME` record with this domain name. + + * IPv4 address: use this IP in an `A` response. + + * IPv6 address: use this IP in an `AAAA` response. + + * The literal `A`: keep only `A` records from the upstream + response. + + * The literal `AAAA`: keep only `AAAA` records from the upstream + response. + 'type': 'string' + 'domain': + 'description': > + Domain name or wildcard. + 'type': 'string' + 'required': + - 'answer' + - 'domain' + 'type': 'object' + + 'DnsSettings': + 'allOf': + - '$ref': '#/components/schemas/DnsSettingsPatch' + - 'description': > + DNS server settings. + 'example': + 'blocking_mode': 'default' + 'bootstrap_servers': + - '9.9.9.10' + - '149.112.112.10' + 'cache_size': 4194304 + 'cache_ttl_max': 0 + 'cache_ttl_min': 0 + 'dnssec': false + 'edns_client_subnet': false + 'ipv6': true + 'rate_limit': 20 + 'upstream_mode': 'load_balancing' + 'upstream_servers': + - '1.1.1.1' + - '8.8.8.8' + 'required': + - 'blocking_mode' + - 'bootstrap_servers' + - 'cache_size' + - 'cache_ttl_max' + - 'cache_ttl_min' + - 'dnssec' + - 'edns_client_subnet' + - 'ipv6' + - 'rate_limit' + - 'upstream_mode' + - 'upstream_servers' + + 'DnsSettingsPatch': + 'description': > + DNS server settings update object. + 'example': + 'cache_size': 4194304 + 'upstream_servers': + - '1.1.1.1' + 'properties': + 'blocking_ipv4': + 'description': > + IPv4 address to respond with when `blocking_mode` is `custom_ip`. + See the documentation for the `DnsBlockingMode` schema. If + `blocking_mode` is different from `custom_ip`, this property is not + included. + 'type': 'string' + 'blocking_ipv6': + 'description': > + IPv6 address to respond with when `blocking_mode` is `custom_ip`. + See the documentation for the `DnsBlockingMode` schema. If + `blocking_mode` is different from `custom_ip`, this property is not + included. + 'type': 'string' + 'blocking_mode': + '$ref': '#/components/schemas/DnsBlockingMode' + 'bootstrap_servers': + 'description': | + Bootstrap DNS servers' IP addresses to resolve the hostnames of the + encrypted DNS server providers. + 'items': + 'type': 'string' + 'type': 'array' + 'cache_size': + 'description': > + DNS cache size in bytes. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'cache_ttl_max': + 'description': > + Set a maximum time-to-live value for entries in the DNS cache. `0` + means no override. The value is in **seconds**, like in DNS record + headers. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'cache_ttl_min': + 'description': > + Extend short time-to-live values received from the upstream server + when caching DNS responses. `0` means no override. TThe value is + in **seconds**, like in DNS record headers. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'dnssec': + 'description': > + If `true`, set DNSSEC flag in outcoming DNS queries and check the + result. A DNSSEC-enabled resolver is required. + 'type': 'boolean' + 'edns_client_subnet': + 'description': > + If `true`, enable EDNS Client Subnet support and send clients' + subnets to DNS servers. + 'type': 'boolean' + 'ipv6': + 'description': > + If `true`, accept `AAAA` DNS queries. If `false`, respond to them + with an empty answer. + 'type': 'boolean' + 'rate_limit': + 'description': > + The number of requests per second that a single client is allowed to + make. `0` means no limit. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'upstream_mode': + '$ref': '#/components/schemas/DnsUpstreamMode' + 'upstream_servers': + 'description': > + Upstream DNS servers. + 'items': + '$ref': '#/components/schemas/UpstreamServerAddr' + 'type': 'array' + 'type': 'object' + + 'DnsType': + 'description': > + DNS resource record type, aka `TYPE`. + 'enum': + - 'a' + - 'aaaa' + - 'afsdb' + - 'any' + - 'apl' + - 'atma' + - 'avc' + - 'axfr' + - 'caa' + - 'cdnskey' + - 'cds' + - 'cert' + - 'cname' + - 'csync' + - 'dhcid' + - 'dlv' + - 'dname' + - 'dnskey' + - 'ds' + - 'eid' + - 'eui48' + - 'eui64' + - 'gid' + - 'gpos' + - 'hinfo' + - 'hip' + - 'https' + - 'isdn' + - 'ixfr' + - 'key' + - 'kx' + - 'l32' + - 'l64' + - 'loc' + - 'lp' + - 'maila' + - 'mailb' + - 'mb' + - 'md' + - 'mf' + - 'mg' + - 'minfo' + - 'mr' + - 'mx' + - 'naptr' + - 'nid' + - 'nimloc' + - 'ninfo' + - 'ns' + - 'nsap-ptr' + - 'nsec' + - 'nsec3' + - 'nsec3param' + - 'null' + - 'nxt' + - 'openpgpkey' + - 'opt' + - 'ptr' + - 'px' + - 'rkey' + - 'rp' + - 'rrsig' + - 'rt' + - 'sig' + - 'smimea' + - 'soa' + - 'spf' + - 'srv' + - 'sshfp' + - 'svcb' + - 'ta' + - 'talink' + - 'tkey' + - 'tlsa' + - 'tsig' + - 'txt' + - 'uid' + - 'uinfo' + - 'unspec' + - 'uri' + - 'x25' + 'type': 'string' + + 'DnsUpstreamMode': + 'description': | + Upstream request mode. + + * `fastest`: Query all DNS servers and return the IP address that was + returned by the fastest response. Slows down DNS responses, since + it waits for responses from all upstreams, but improves the overall + connectivity. + + * `load_balancing`: Query one server at a time using a weighted random + algorithm picking the server so that the fastest server is used + more often. + + * `parallel`: Use parallel requests to speed up resolving by + simultaneously querying all upstream servers. + 'enum': + - 'fastest' + - 'load_balancing' + - 'parallel' + 'type': 'string' + + 'ErrorCode': + 'description': | + An error code. + + * `AUT000`: No or bad authorization credentials provided. + + * `ENT404`: Entity not found; as opposed to path not found. + + * `JSN000`: A JSON syntax error. + + * `JSN001`: A JSON type error. + + * `OSS000`: The server's operating system doesn't support the + requested functionality. + + * `PTH404`: Path not found; as opposed to entity not found. + + * `RNT000`: A server runtime error. + + * `TXT400`: A plaintext bad request error. Used when a plaintext + error is wrapped. + + * `TXT401`: A plaintext unauthorized error. Used when a plaintext + error is wrapped. + + * `TXT404`: A plaintext not found error. Used when a plaintext error + is wrapped. + + * `TXT500`: A plaintext internal server error. Used when a plaintext + error is wrapped. + + TODO(a.garipov): Expand with TLS validation errors, DHCP errors, filter + URL reaching errors, OS and I/O errors, and so on. + 'enum': + - 'AUT000' + - 'ENT404' + - 'JSN000' + - 'JSN001' + - 'OSS000' + - 'PTH404' + - 'RNT000' + - 'TXT400' + - 'TXT401' + - 'TXT404' + - 'TXT500' + 'type': 'string' + + 'Filter': + 'allOf': + - '$ref': '#/components/schemas/FilterPatch' + - 'description': > + A single filter list of rules. + 'example': + 'allowlist': false + 'enabled': true + 'name': 'AdMaster 5000 Super List v2.0 Final' + 'num_rules': 36766 + 'refreshed': 1614345496000 + 'uid': 'abcd1234' + 'url': 'https://admaster.example.com/list.txt' + 'properties': + 'num_rules': + 'description': > + Number of rules in this filter. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'refreshed': + 'description': > + Unix time of last refresh for this filter, in milliseconds. + 'format': 'double' + 'type': 'number' + 'uid': + '$ref': '#/components/schemas/Uid' + 'required': + - 'allowlist' + - 'enabled' + - 'name' + - 'num_rules' + - 'refreshed' + - 'uid' + - 'url' + + 'FilterPatch': + 'description': > + A filter update object. + 'example': + 'enabled': true + 'properties': + 'allowlist': + 'description': > + If `true`, this filter works as an allowlist filters. + 'type': 'boolean' + 'enabled': + 'description': > + If `true`, this filter is applied. + 'type': 'boolean' + 'name': + 'description': > + The name of this filter. + 'type': 'string' + 'url': + 'description': | + A URL of the file containing filtering rules. + + Examples of allowed schemes: + + * `file:///home/user/ads/rules.txt`: A local file. + + * `http://example.com/ads/rules.txt`: Remote list, fetched over + plain HTTP. + + * `https://example.com/ads/rules.txt`: Remote list, fetched over + HTTPS. + 'type': 'string' + 'type': 'object' + + 'FilterPost': + 'allOf': + - '$ref': '#/components/schemas/FilterPatch' + - 'description': > + A filter create object. + 'example': + 'allowlist': false + 'enabled': true + 'name': 'AdMaster 5000 Super List v2.0 Final' + 'url': 'https://admaster.example.com/list.txt' + 'required': + - 'allowlist' + - 'enabled' + - 'name' + - 'url' + + 'FilteringReason': + 'description': > + Request filtering status. + 'enum': + - 'filtered_blocked_service' + - 'filtered_blocklist' + - 'filtered_invalid' + - 'filtered_parental' + - 'filtered_safe_browsing' + - 'filtered_safe_search' + - 'not_filtered_allowlist' + - 'not_filtered_error' + - 'not_filtered_notfound' + - 'rewrite' + - 'rewrite_etc_hosts' + - 'rewrite_rule' + 'type': 'string' + + 'FilteringResultRule': + 'description': > + Applied filtering rule. + 'properties': + 'filter_list_uid': + '$ref': '#/components/schemas/Uid' + 'text': + 'description': > + The text of the filtering rule applied to the request, if any. + 'type': 'string' + 'required': + - 'filter_list_uid' + - 'text' + 'type': 'object' + + 'GetV1AccountsProfileResp': + '$ref': '#/components/schemas/Profile' + + # TODO(a.garipov): Find a way to describe such XML documents using OpenAPI. + # If that is even possible. + 'GetV1AppleDohMobileconfigResp': + 'example': | + + + + + PayloadContent + + + DNSSettings + + DNSProtocol + HTTPS + ServerName + example.com + ServerURL + https://example.com/dns-query/123 + + Name + myexample.local DoH + PayloadDescription + Configures device to use AdGuard Home + PayloadDisplayName + myexample.local DoH + PayloadIdentifier + com.apple.dnsSettings.managed.b6928468-ae3a-4368-a70d-cb7122275013 + PayloadType + com.apple.dnsSettings.managed + PayloadUUID + 18526b8c-6065-4b96-b635-9cde769ac0f2 + PayloadVersion + 1 + + + PayloadDescription + Adds AdGuard Home to Big Sur and iOS 14 or newer systems + PayloadDisplayName + myexample.local DoH + PayloadIdentifier + 9a37b659-7541-4f9e-8b4d-6e2a59a123c8 + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + 255dbaf7-0c52-4855-9b22-ad8209690197 + PayloadVersion + 1 + + + 'type': 'object' + + # TODO(a.garipov): See the comment on GetV1AppleDohMobileconfigResp. + 'GetV1AppleDotMobileconfigResp': + 'example': | + + + + + PayloadContent + + + DNSSettings + + DNSProtocol + TLS + ServerName + 123.example.com + + Name + example.com DoT + PayloadDescription + Configures device to use AdGuard Home + PayloadDisplayName + example.com DoT + PayloadIdentifier + com.apple.dnsSettings.managed.7807cb66-c6ec-4c78-be29-d8ffcb3321ee + PayloadType + com.apple.dnsSettings.managed + PayloadUUID + b0fb9137-e27a-4f95-abc3-556103ad9ac1 + PayloadVersion + 1 + + + PayloadDescription + Adds AdGuard Home to Big Sur and iOS 14 or newer systems + PayloadDisplayName + myexample.local DoT + PayloadIdentifier + f1095036-406e-4243-8210-cf0ffa52b3f6 + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + 21cd3597-0769-486a-86d0-7b5e32d24305 + PayloadVersion + 1 + + + 'type': 'object' + + 'GetV1ClientsPersistentResp': + 'description': > + Persistent clients. + 'example': + 'clients': + - 'blocked': false + 'blocked_services': [] + 'filtering': false + 'ids': ['client-1'] + 'name': 'Client 1' + 'parental': false + 'safe_browsing': false + 'safe_search': false + 'tags': ['user_admin'] + 'use_global_blocked_services': true + 'use_global_settings': true + 'uid': 'abcd1234' + 'upstream_servers': [] + - 'blocked': false + 'blocked_services': [] + 'filtering': true + 'ids': ['client-2'] + 'name': 'Client 2' + 'parental': true + 'safe_browsing': true + 'safe_search': true + 'tags': ['user_child'] + 'use_global_blocked_services': false + 'use_global_settings': false + 'uid': 'efgh5678' + 'upstream_servers': [] + 'properties': + 'clients': + 'description': > + All persistent clients. + 'items': + '$ref': '#/components/schemas/PersistentClient' + 'type': 'array' + 'required': + - 'clients' + 'type': 'object' + + 'GetV1ClientsRuntimeResp': + 'description': > + Runtime clients. + 'example': + 'clients': + - 'host': 'my-box' + 'ip': '1.2.3.4' + 'num_blocked_requests': 0 + 'num_requests': 100 + 'sources': + - 'arp' + - 'ip': '5.6.7.8' + 'num_blocked_requests': 100 + 'num_requests': 100 + 'sources': + - 'whois' + 'whois': + 'city': 'Minsk' + 'country': 'BY' + 'properties': + 'clients': + 'description': > + All runtime clients. + 'items': + '$ref': '#/components/schemas/RuntimeClient' + 'type': 'array' + 'required': + - 'clients' + 'type': 'object' + + 'GetV1DhcpLeasesResp': + 'description': > + All dynamic and static DHCP leases. + 'example': + 'leases': + - 'expires': 1614345496000 + 'hostname': 'my-mobile' + 'ip': '192.168.1.2' + 'mac': '01:23:45:67:89:ab' + 'uid': 'abcd1234' + - 'expires': 1614345497000 + 'hostname': '' + 'ip': '192.168.1.3' + 'mac': '01:23:45:67:89:cd' + 'properties': + 'leases': + 'description': > + Dynamic and static DHCP leases. + 'items': + '$ref': '#/components/schemas/DhcpLease' + 'type': 'array' + 'required': + - 'leases' + 'type': 'object' + + 'GetV1DhcpStatusResp': + 'description': > + Current DHCP server status and data for enabling it. + 'example': + 'interfaces': + - 'ips': + - '192.168.1.1' + 'mac': '01:23:45:67:89:ab' + 'mtu': 1500 + 'name': 'lan0' + 'up': true + 'ipv4_other_servers': + 'ips': + - '192.169.1.1' + 'ipv4_static_ip': + 'ip': '192.168.1.1' + 'static': true + 'supported': true + 'ipv6_other_servers': + 'ips': [] + 'error': 'permission denied' + 'ipv6_static_ip': + 'ip': '200f::1' + 'static': true + 'supported': true + 'properties': + 'interfaces': + 'description': > + Available network interfaces. + 'items': + '$ref': '#/components/schemas/NetworkInterface' + 'type': 'array' + 'ipv4_other_servers': + '$ref': '#/components/schemas/GetV1DhcpStatusRespOtherServer' + 'ipv4_static_ip': + '$ref': '#/components/schemas/StaticIpCheckResult' + 'ipv6_other_servers': + '$ref': '#/components/schemas/GetV1DhcpStatusRespOtherServer' + 'ipv6_static_ip': + '$ref': '#/components/schemas/StaticIpCheckResult' + 'required': + - 'interfaces' + - 'ipv4_other_servers' + - 'ipv4_static_ip' + - 'ipv6_other_servers' + - 'ipv6_static_ip' + 'type': 'object' + + 'GetV1DhcpStatusRespOtherServer': + 'properties': + 'error': + 'description': > + Error, if any. If there is no error, this field is absent. + 'type': 'string' + 'ips': + 'description': > + IP addresses of other DHCP servers, if found. + 'required': + - 'ips' + 'type': 'object' + + 'GetV1InstallInfoResp': + 'description': > + AdGuard Home addresses configuration. + 'example': + 'dns_port': 53 + 'interfaces': + - 'ips': + - '192.168.1.1' + 'mac': '01:23:45:67:89:ab' + 'mtu': 1500 + 'name': 'lan0' + 'up': true + 'web_port': 80 + 'properties': + 'dns_port': + 'description': > + Recommended DNS port. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'interfaces': + 'description': > + Available network interfaces. + 'items': + '$ref': '#/components/schemas/NetworkInterface' + 'type': 'array' + 'web_port': + 'description': > + Recommended web interface port. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'required': + - 'dns_port' + - 'interfaces' + - 'web_port' + 'type': 'object' + + 'GetV1LogSearchResp': + 'description': > + Query log search results. + 'example': + 'results': + - 'answer': + - 'ttl': 60 + 'type': 'a' + 'value': '5.6.7.8' + 'answer_dnssec': false + 'client': + 'blocked': false + 'ids': + - '1.2.3.4' + - 'user-1' + 'name': 'User 1' + 'num': 100 + 'num_blocked': 50 + 'uid': 'abcd1234' + 'whois': + 'city': 'Minsk' + 'country': 'BY' + 'elapsed': 3.2 + 'proto': 'udp' + 'question': + 'class': 'in' + 'host': 'example.com' + 'type': 'a' + 'rcode': 'noerror' + 'reason': 'not_filtered_notfound' + 'rules': [] + 'start': 1614345496000 + 'upstream': '8.8.8.8' + 'properties': + 'results': + 'description': > + The query log. + 'items': + '$ref': '#/components/schemas/LogRecord' + 'type': 'array' + 'required': + - 'results' + 'type': 'object' + + 'GetV1ProtectionBlockedServicesResp': + '$ref': '#/components/schemas/BlockedServices' + + 'GetV1ProtectionCustomRulesResp': + '$ref': '#/components/schemas/CustomRules' + + 'GetV1ProtectionDnsRewritesResp': + 'description': > + Classic DNS rewrites. + 'example': + 'rules': + - 'answer': 'A' + 'domain': 'example.com' + 'id': 'abcd1234' + - 'answer': '0.0.0.0' + 'domain': '*.example.org' + 'id': 'efgh5678' + - 'answer': 'my.example.net' + 'domain': 'example.net' + 'id': 'ijkl9012' + 'properties': + 'rules': + 'description': > + All classic DNS rewrites. + 'items': + '$ref': '#/components/schemas/DnsRewrite' + 'type': 'array' + 'required': + - 'rules' + 'type': 'object' + + 'GetV1ProtectionFiltersResp': + 'description': > + Filters. + 'example': + 'filters': + - 'allowlist': false + 'enabled': true + 'name': 'AdMaster 5000 Super List v2.0 Final' + 'num_rules': 36766 + 'refreshed': 1614345496000 + 'uid': 'abcd1234' + 'url': 'https://admaster.example.com/list.txt' + - 'allowlist': false + 'enabled': true + 'name': 'My personal list' + 'num_rules': 0 + 'refreshed': 1614345497000 + 'uid': 'efgh5678' + 'url': 'file:///home/user/Documents/ad_list.txt' + 'properties': + 'filters': + 'description': > + All current filters. + 'items': + '$ref': '#/components/schemas/Filter' + 'type': 'array' + 'required': + - 'filters' + 'type': 'object' + + # Perhaps a lot of these belong in separate APIs, but our colleagues asked + # to pack as much data into every request as reasonably possible. + 'GetV1SettingsAllResp': + 'description': > + Most settings. + # Don't add examples, as are provided by the subclasses. + 'properties': + 'dhcp': + '$ref': '#/components/schemas/DhcpSettings' + 'dns': + '$ref': '#/components/schemas/DnsSettings' + 'log': + '$ref': '#/components/schemas/LogSettings' + 'protection': + '$ref': '#/components/schemas/ProtectionSettings' + 'stats': + '$ref': '#/components/schemas/StatsSettings' + 'tls': + '$ref': '#/components/schemas/TlsSettings' + 'required': + - 'dhcp' + - 'dns' + - 'log' + - 'protection' + - 'stats' + - 'tls' + 'type': 'object' + + 'GetV1SettingsDnsAccessResp': + '$ref': '#/components/schemas/DnsAccessSettings' + + # See the comment on the GetV1SettingsAllResp schema. + 'GetV1StatsAllResp': + 'description': > + All statistics. + 'example': + 'dns_cache_hit_rate': 56.7 + 'dns_cache_records': 123 + 'graph_avg_processing': + - 3.0 + - 0.4 + 'graph_blocked_ad_queries': + - 10 + - 20 + 'graph_blocked_custom_rule_queries': + - 10 + - 20 + 'graph_blocked_domains': + - 10 + - 20 + 'graph_blocked_parental_control_queries': + - 10 + - 20 + 'graph_blocked_safe_browsing_queries': + - 10 + - 20 + 'graph_blocked_safe_search_queries': + - 10 + - 20 + 'graph_blocked_service_queries': + - 10 + - 20 + 'graph_blocked_tracker_queries': + - 10 + - 20 + 'graph_cpu_percent': + - 50 + - 75 + 'graph_domains': + - 20 + - 30 + 'graph_queries': + - 1000 + - 2002 + 'graph_ram_resident': + - 1048576 + - 2097152 + 'time_unit': 'hour' + 'top_blocked_domains': + - 'name': 'example.net' + 'num': 100 + 'top_clients': + - 'blocked': false + 'ids': + - '1.2.3.4' + - 'user-1' + 'name': 'User 1' + 'num': 100 + 'num_blocked': 50 + 'uid': 'abcd1234' + 'whois': + 'city': 'Minsk' + 'country': 'BY' + - 'blocked': true + 'ids': + - '5.6.7.8' + 'num': 100 + 'num_blocked': 100 + 'top_domains': + - 'name': 'example.com' + 'num': 1000 + - 'name': 'example.net' + 'num': 100 + 'total_blocked_ad_queries': 100 + 'total_blocked_custom_rule_queries': 10 + 'total_blocked_domains': 500 + 'total_blocked_parental_control_queries': 10 + 'total_blocked_safe_browsing_queries': 10 + 'total_blocked_safe_search_queries': 10 + 'total_blocked_service_queries': 10 + 'total_blocked_tracker_queries': 10 + 'total_domains': 1000 + 'total_queries': 10000 + 'properties': + 'dns_cache_hit_rate': + 'description': > + DNS cache hit rate, in percent. + 'maximum': 100.0 + 'minimum': 0.0 + 'format': 'double' + 'type': 'number' + 'dns_cache_records': + 'description': > + Number of DNS responses currently in cache. + 'minimum': 0 + 'format': 'int64' + 'type': 'integer' + 'graph_avg_processing': + 'description': > + Average DNS query processing duration graph information. Each item + is one `time_unit` long. The duration is in milliseconds. Sorted + by time in descending order. + 'items': + 'format': 'double' + 'type': 'number' + 'type': 'array' + 'graph_blocked_ad_queries': + 'description': > + Number of queries blocked by advertising filters graph information. + Each item is one `time_unit` long. Sorted by time in descending + order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_custom_rule_queries': + 'description': > + Number of queries blocked by custom filtering rules graph + information. Each item is one `time_unit` long. Sorted by time in + descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_domains': + 'description': > + Blocked queried domains graph information. Each item is one + `time_unit` long. Sorted by time in descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_parental_control_queries': + 'description': > + Number of queries blocked by parental control services graph + information. Each item is one `time_unit` long. Sorted by time in + descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_safe_browsing_queries': + 'description': > + Number of queries blocked by safe browsing services graph + information. Each item is one `time_unit` long. Sorted by time in + descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_safe_search_queries': + 'description': > + Number of queries blocked by safe search services graph information. + Each item is one `time_unit` long. Sorted by time in descending + order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_service_queries': + 'description': > + Number of queries blocked by blocked service settings graph + information. Each item is one `time_unit` long. Sorted by time in + descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_blocked_tracker_queries': + 'description': > + Number of queries blocked by tracker filters graph information. + Each item is one `time_unit` long. Sorted by time in descending + order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_cpu_percent': + 'description': > + CPU usage percentage graph information. Each item is one + `time_unit` long. Sorted by time in descending order. + 'items': + 'format': 'double' + 'type': 'number' + 'type': 'array' + 'graph_domains': + 'description': > + Queried domains graph information. Each item is one `time_unit` + long. Sorted by time in descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_queries': + 'description': > + Number of served DNS queries graph information. Each item is one + `time_unit` long. Sorted by time in descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'graph_ram_resident': + 'description': > + AdGuard Home's resident memory usage graph information. The size is + in bytes. Each item is one `time_unit` long. Sorted by time in + descending order. + 'items': + 'format': 'int64' + 'type': 'integer' + 'type': 'array' + 'time_unit': + '$ref': '#/components/schemas/TimeUnit' + 'top_blocked_domains': + 'description': > + Top blocked queried domains. Sorted by number in descending order. + 'items': + '$ref': '#/components/schemas/GetV1StatsAllRespTopsItem' + 'type': 'array' + 'top_clients': + 'description': > + Top clients. Sorted by number in descending order. + 'items': + '$ref': '#/components/schemas/ClientInfo' + 'type': 'array' + 'top_domains': + 'description': > + Top queried domains. Sorted by number in descending order. + 'items': + '$ref': '#/components/schemas/GetV1StatsAllRespTopsItem' + 'type': 'array' + 'total_blocked_ad_queries': + 'description': > + Total number of queries blocked by advertising filters. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_custom_rule_queries': + 'description': > + Total number of queries blocked by custom filtering rules. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_domains': + 'description': > + Total number of blocked queried domains. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_parental_control_queries': + 'description': > + Total number of queries blocked by parental control services. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_safe_browsing_queries': + 'description': > + Total number of queries blocked by safe browsing services. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_safe_search_queries': + 'description': > + Total number of queries blocked by safe search services. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_service_queries': + 'description': > + Total number of queries blocked by blocked service settings. + 'format': 'int64' + 'type': 'integer' + 'total_blocked_tracker_queries': + 'description': > + Total number of queries blocked by tracker filters. + 'format': 'int64' + 'type': 'integer' + 'total_domains': + 'description': > + Total number of queried domains. + 'format': 'int64' + 'type': 'integer' + 'total_queries': + 'description': > + Total number of served DNS queries. + 'format': 'int64' + 'type': 'integer' + 'required': + - 'dns_cache_hit_rate' + - 'dns_cache_records' + - 'graph_avg_processing' + - 'graph_blocked_ad_queries' + - 'graph_blocked_custom_rule_queries' + - 'graph_blocked_domains' + - 'graph_blocked_parental_control_queries' + - 'graph_blocked_safe_browsing_queries' + - 'graph_blocked_safe_search_queries' + - 'graph_blocked_service_queries' + - 'graph_blocked_tracker_queries' + - 'graph_cpu_percent' + - 'graph_domains' + - 'graph_queries' + - 'graph_ram_resident' + - 'time_unit' + - 'top_blocked_domains' + - 'top_clients' + - 'top_domains' + - 'total_blocked_ad_queries' + - 'total_blocked_custom_rule_queries' + - 'total_blocked_domains' + - 'total_blocked_parental_control_queries' + - 'total_blocked_safe_browsing_queries' + - 'total_blocked_safe_search_queries' + - 'total_blocked_service_queries' + - 'total_blocked_tracker_queries' + - 'total_domains' + - 'total_queries' + 'type': 'object' + + 'GetV1StatsAllRespTopsItem': + 'description': > + A top array item. + 'properties': + 'name': + 'description': > + The name of the entity. Mostly domain names. + 'example': 'example.com' + 'type': 'string' + 'num': + 'description': > + The value of the statistic. + 'example': 1000 + 'format': 'int64' + 'type': 'integer' + 'required': + - 'name' + - 'num' + 'type': 'object' + + 'GetV1SystemInfoResp': + 'description': > + Information about the AdGuard Home server. + 'example': + 'channel': 'release' + 'new_version': 'v0.106.1' + 'start': 1614345496000 + 'version': 'v0.106.0' + 'properties': + 'channel': + '$ref': '#/components/schemas/Channel' + 'new_version': + 'description': > + New available version of AdGuard Home to which the server can be + updated, if any. If there are none, this field is absent. + 'type': 'string' + 'start': + 'description': > + Unix time at which AdGuard Home started working, in milliseconds. + 'format': 'double' + 'type': 'number' + 'version': + 'description': > + Current AdGuard Home version. + 'type': 'string' + 'required': + - 'channel' + - 'start' + - 'version' + 'type': 'object' + + 'InternalServerErrorResp': + 'example': + 'code': 'RNT000' + 'msg': >- + runtime error: invalid memory address or nil pointer dereference + 'properties': + 'code': + '$ref': '#/components/schemas/ErrorCode' + 'msg': + 'description': > + Error message string. + 'type': 'string' + 'required': + - 'code' + - 'msg' + 'type': 'object' + + 'Lang': + 'description': > + Language code. + # Hold the enum in sync with .twosky.json. + 'enum': + - 'be' + - 'bg' + - 'cs' + - 'da' + - 'de' + - 'en' + - 'es' + - 'fa' + - 'fr' + - 'hr' + - 'hu' + - 'id' + - 'it' + - 'ja' + - 'ko' + - 'nl' + - 'no' + - 'pl' + - 'pt-br' + - 'pt-pt' + - 'ro' + - 'ru' + - 'si-lk' + - 'sk' + - 'sl' + - 'sr-cs' + - 'sv' + - 'th' + - 'tr' + - 'vi' + - 'zh-cn' + - 'zh-hk' + - 'zh-tw' + 'type': 'string' + + 'LogRecord': + 'description': > + Query log record. + 'properties': + 'answer': + 'description': > + The answer given to the user. + 'items': + '$ref': '#/components/schemas/LogRecordDnsAnswer' + 'type': 'array' + 'answer_dnssec': + 'description': > + If `true`, DNSSEC was used. + 'type': 'boolean' + 'blocked_service': + 'description': > + Set if `reason` is `filtered_blocked_service`. Otherwise, this + field is absent. + 'type': 'string' + 'client': + '$ref': '#/components/schemas/ClientInfo' + 'elapsed': + 'description': > + Time it took to process the request, in milliseconds. + 'format': 'double' + 'type': 'number' + 'original_answer': + 'description': > + Original answer from the upstream server, if the answer was + rewritten. + 'items': + '$ref': '#/components/schemas/LogRecordDnsAnswer' + 'type': 'array' + 'proto': + '$ref': '#/components/schemas/DnsProto' + 'question': + '$ref': '#/components/schemas/LogRecordDnsQuestion' + 'rcode': + '$ref': '#/components/schemas/DnsResponseCode' + 'reason': + '$ref': '#/components/schemas/FilteringReason' + 'rules': + 'description': > + Applied rules. + 'items': + '$ref': '#/components/schemas/FilteringResultRule' + 'type': 'array' + 'start': + 'description': > + Request processing start Unix time, in milliseconds. + 'format': 'double' + 'type': 'number' + 'upstream': + '$ref': '#/components/schemas/UpstreamServerAddr' + 'required': + - 'answer' + - 'answer_dnssec' + - 'client' + - 'elapsed' + - 'proto' + - 'question' + - 'rcode' + - 'reason' + - 'rules' + - 'start' + - 'upstream' + 'type': 'object' + + 'LogRecordDnsAnswer': + 'description': > + DNS answer section. + 'properties': + 'ttl': + 'description': > + TTL of a record. This value is in **seconds**, like in DNS record + headers. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'type': + '$ref': '#/components/schemas/DnsType' + 'value': + 'description': > + An opaque string describing the result value. + 'type': 'string' + 'required': + - 'ttl' + - 'type' + - 'value' + 'type': 'object' + + 'LogRecordDnsQuestion': + 'description': > + DNS question section. + 'properties': + 'class': + '$ref': '#/components/schemas/DnsClass' + 'host': + 'description': > + Host from the query. + 'type': 'string' + 'type': + '$ref': '#/components/schemas/DnsType' + 'required': + - 'class' + - 'host' + - 'type' + 'type': 'object' + + 'LogSettings': + 'allOf': + - '$ref': '#/components/schemas/LogSettingsPatch' + - 'description': > + Query logging settings. + 'example': + 'anonymize': true + 'enabled': true + 'rotation': 604800000 + 'required': + - 'anonymize' + - 'enabled' + - 'rotation' + + 'LogSettingsPatch': + 'description': > + Query logging settings update object. + 'properties': + 'anonymize': + 'description': > + If `true`, client IP address anonymization is enabled. + 'type': 'boolean' + 'enabled': + 'description': > + If `true`, query logging is enabled. + 'type': 'boolean' + 'rotation': + 'description': > + Log rotation interval, in milliseconds. After that time, the log + file will be replaced by a new one, while the old one gets renamed. + 'format': 'double' + 'minimum': 86400000 + 'maximum': 7776000000 + 'type': 'number' + 'type': 'object' + + 'NetworkInterface': + 'properties': + 'ips': + 'description': > + The IP addresses of the interface, if any. + 'items': + 'type': 'string' + 'type': 'array' + 'mac': + 'description': > + The MAC address of the interface. + 'type': 'string' + 'mtu': + 'description': > + The interface's MTU, the maximum transmission unit. + 'format': 'int64' + 'type': 'integer' + 'name': + 'description': > + The name of the interface. + 'type': 'string' + 'up': + 'description': > + If `true`, the interface is up. + 'type': 'boolean' + 'required': + - 'ips' + - 'mac' + - 'mtu' + - 'name' + - 'up' + 'type': 'object' + + 'NotFoundResp': + 'example': + 'code': 'ENT404' + 'msg': >- + entity not found + 'properties': + 'code': + '$ref': '#/components/schemas/ErrorCode' + 'msg': + 'description': > + Error message string. + 'type': 'string' + 'required': + - 'code' + - 'msg' + 'type': 'object' + + 'PatchV1AccountsProfileReq': + 'example': + 'lang': 'ru' + 'properties': + 'lang': + '$ref': '#/components/schemas/Lang' + 'type': 'object' + + 'PatchV1AccountsProfileResp': + '$ref': '#/components/schemas/Profile' + + 'PatchV1ClientPersistentReq': + '$ref': '#/components/schemas/PersistentClientPatch' + + 'PatchV1ClientPersistentResp': + '$ref': '#/components/schemas/PersistentClient' + + 'PatchV1DhcpLeaseReq': + '$ref': '#/components/schemas/DhcpLeasePatch' + + 'PatchV1DhcpLeaseResp': + '$ref': '#/components/schemas/DhcpLease' + + 'PatchV1ProtectionFilterReq': + '$ref': '#/components/schemas/FilterPatch' + + 'PatchV1ProtectionFilterResp': + '$ref': '#/components/schemas/Filter' + + 'PatchV1SettingsDhcpReq': + '$ref': '#/components/schemas/DhcpSettingsPatch' + + 'PatchV1SettingsDhcpResp': + '$ref': '#/components/schemas/DhcpSettings' + + 'PatchV1SettingsDnsReq': + '$ref': '#/components/schemas/DnsSettingsPatch' + + 'PatchV1SettingsDnsResp': + '$ref': '#/components/schemas/DnsSettings' + + 'PatchV1SettingsLogReq': + '$ref': '#/components/schemas/LogSettingsPatch' + + 'PatchV1SettingsLogResp': + '$ref': '#/components/schemas/LogSettings' + + 'PatchV1SettingsProtectionReq': + '$ref': '#/components/schemas/ProtectionSettingsPatch' + + 'PatchV1SettingsProtectionResp': + '$ref': '#/components/schemas/ProtectionSettings' + + 'PatchV1SettingsStatsReq': + '$ref': '#/components/schemas/StatsSettingsPatch' + + 'PatchV1SettingsStatsResp': + '$ref': '#/components/schemas/StatsSettings' + + 'PatchV1SettingsTlsReq': + '$ref': '#/components/schemas/TlsSettingsPatch' + + 'PatchV1SettingsTlsResp': + '$ref': '#/components/schemas/TlsSettings' + + 'PersistentClient': + 'allOf': + - '$ref': '#/components/schemas/PersistentClientPatch' + - 'description': > + Persistent client. + 'example': + 'blocked': false + 'blocked_services': [] + 'filtering': false + 'ids': ['client-1'] + 'name': 'Client 1' + 'num_blocked_requests': 50 + 'num_requests': 100 + 'parental': false + 'safe_browsing': false + 'safe_search': false + 'tags': ['user_admin'] + 'use_global_blocked_services': true + 'use_global_settings': true + 'uid': 'abcd1234' + 'upstream_servers': [] + 'properties': + 'num_blocked_requests': + 'description': > + Total number of blocked requests for this runtime client. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'num_requests': + 'description': > + Total number of requests for this runtime client. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'uid': + '$ref': '#/components/schemas/Uid' + 'required': + - 'blocked' + - 'blocked_services' + - 'filtering' + - 'ids' + - 'name' + - 'parental' + - 'safe_browsing' + - 'safe_search' + - 'tags' + - 'uid' + - 'upstream_servers' + - 'use_global_blocked_services' + - 'use_global_settings' + + 'PersistentClientPatch': + 'description': > + Persistent client update object. + 'example': + 'filtering': false + 'parental': false + 'safe_browsing': false + 'safe_search': false + 'tags': ['user_admin'] + 'properties': + 'blocked': + 'description': > + If `true`, the client is blocked. + 'type': 'boolean' + 'blocked_services': + 'description': > + Custom blocked services for this client. + 'items': + '$ref': '#/components/schemas/BlockedServiceId' + 'type': 'array' + 'filtering': + 'description': > + If `true`, filtering based on filter rule lists is enabled for this + client. + 'type': 'boolean' + 'ids': + 'description': > + IP, CIDR, MAC, or ClientID (not to be confused with the `uid` field) + for client identification. + 'items': + 'type': 'string' + 'type': 'array' + 'name': + 'description': > + The name of this client. + 'type': 'string' + 'parental': + 'description': > + If `true`, parental protection is enabled for this client. + 'type': 'boolean' + 'safe_browsing': + 'description': > + If `true`, safe browsing protection is enabled for this client. + 'type': 'boolean' + 'safe_search': + 'description': > + If `true`, safe search protection is enabled for this client. + 'type': 'boolean' + 'tags': + 'description': > + Client tags. + 'items': + '$ref': '#/components/schemas/PersistentClientTag' + 'type': 'array' + 'use_global_blocked_services': + 'description': > + If `true`, use global blocked services for this client instead of + the custom ones. + 'type': 'boolean' + 'use_global_settings': + 'description': > + If `true`, use global protection settings for this client instead of + the custom ones. + 'type': 'boolean' + 'upstream_servers': + 'description': > + Custom upstream DNS servers for this client. + 'items': + '$ref': '#/components/schemas/UpstreamServerAddr' + 'type': 'array' + 'type': 'object' + + 'PersistentClientPost': + 'allOf': + - '$ref': '#/components/schemas/PersistentClientPatch' + - 'description': > + Persistent client create object. + 'example': + 'blocked': false + 'blocked_services': [] + 'filtering': false + 'ids': ['client-1'] + 'name': 'Client 1' + 'parental': false + 'safe_browsing': false + 'safe_search': false + 'tags': ['user_admin'] + 'use_global_blocked_services': true + 'use_global_settings': true + 'upstream_servers': [] + 'required': + - 'blocked' + - 'blocked_services' + - 'filtering' + - 'ids' + - 'name' + - 'parental' + - 'safe_browsing' + - 'safe_search' + - 'tags' + - 'upstream_servers' + - 'use_global_blocked_services' + - 'use_global_settings' + + 'PersistentClientTag': + 'description': > + Tags can be included in filtering rules to allow you to apply them more + accurately. + 'enum': + - 'device_audio' + - 'device_camera' + - 'device_gameconsole' + - 'device_laptop' + - 'device_nas' + - 'device_other' + - 'device_pc' + - 'device_phone' + - 'device_printer' + - 'device_securityalarm' + - 'device_tablet' + - 'device_tv' + - 'os_android' + - 'os_ios' + - 'os_linux' + - 'os_macos' + - 'os_other' + - 'os_windows' + - 'user_admin' + - 'user_child' + - 'user_regular' + 'type': 'string' + + 'PostV1AccountsSessionReq': + 'example': + 'password': 'G00dp455word!' + 'username': 'admin' + 'properties': + 'password': + 'description': > + Password. + 'format': 'password' + 'type': 'string' + 'username': + 'description': > + Username. + 'type': 'string' + 'required': + - 'password' + - 'username' + 'type': 'object' + + 'PostV1ClientsPersistentReq': + '$ref': '#/components/schemas/PersistentClientPost' + + 'PostV1ClientsPersistentResp': + '$ref': '#/components/schemas/PersistentClient' + + 'PostV1DhcpLeasesReq': + '$ref': '#/components/schemas/DhcpLeasePost' + + 'PostV1DhcpLeasesResp': + '$ref': '#/components/schemas/DhcpLease' + + 'PostV1InstallCheckReq': + 'description': > + Configuration for checking. + 'example': + 'dns': + 'ip': + - '0.0.0.0' + 'port': 53 + 'static_ip': false + 'web': + 'ip': + - '0.0.0.0' + 'port': 80 + 'properties': + 'dns': + '$ref': '#/components/schemas/PostV1InstallCheckReqServer' + 'static_ip': + 'description': > + If `true`, check if a static IP is set or can be set. + 'type': 'boolean' + 'web': + '$ref': '#/components/schemas/PostV1InstallCheckReqServer' + 'required': + - 'dns' + - 'static_ip' + - 'web' + 'type': 'object' + + 'PostV1InstallCheckReqServer': + 'description': > + A configuration for a server check. + 'properties': + 'ip': + 'description': > + IP addresses to check for availability. + 'items': + 'type': 'string' + 'minItems': 1 + 'type': 'array' + 'port': + 'description': > + Port to check for availability. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'required': + - 'ip' + - 'port' + 'type': 'object' + + 'PostV1InstallCheckResp': + 'description': > + Configuration checking response. + 'example': + 'dns': + 'error': 'permission denied' + 'static_ip': + 'ip': '192.168.1.1' + 'static': true + 'supported': true + 'web': {} + 'properties': + 'dns': + '$ref': '#/components/schemas/PostV1InstallCheckRespNetwork' + 'static_ip': + '$ref': '#/components/schemas/StaticIpCheckResult' + 'web': + '$ref': '#/components/schemas/PostV1InstallCheckRespNetwork' + 'required': + - 'dns' + - 'static_ip' + - 'web' + 'type': 'object' + + 'PostV1InstallCheckRespNetwork': + 'properties': + 'error': + 'description': > + Error, if any. If there is no error, this field is absent. + 'type': 'string' + 'type': 'object' + + 'PostV1InstallConfigureReq': + 'description': > + AdGuard Home initial configuration. + 'example': + 'dns_ip': '0.0.0.0' + 'dns_port': 53 + 'password': 'G00dp455word!' + 'username': 'admin' + 'set_static_ip': true + 'web_ip': '0.0.0.0' + 'web_port': 80 + 'properties': + 'dns_ip': + 'description': > + The IP address to serve DNS queries on. + 'type': 'string' + 'dns_port': + 'description': > + The port to serve DNS queries on. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'password': + 'description': > + Password. + 'type': 'string' + 'username': + 'description': > + Username. + 'type': 'string' + 'set_static_ip': + 'description': > + If `true`, set the server's IP address to static. + 'type': 'boolean' + 'web_ip': + 'description': > + The IP address to serve the web interface on. + 'type': 'string' + 'web_port': + 'description': > + The port to serve the web interface on. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'required': + - 'dns_ip' + - 'dns_port' + - 'password' + - 'username' + - 'set_static_ip' + - 'web_ip' + - 'web_port' + 'type': 'object' + + 'PostV1LogClearReq': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1ProtectionCheckCustomRulesReq': + 'description': > + Data to check using custom filtering rules. + 'example': + 'host': 'example.com' + 'properties': + 'host': + 'description': > + The hostname to check. + 'type': 'string' + 'required': + - 'host' + 'type': 'object' + + 'PostV1ProtectionCheckCustomRulesResp': + 'description': > + Custom filtering rules check results. + 'example': + 'reason': 'filtered_blocklist' + 'rules': + - 'filter_list_uid': 'abcd1234' + 'text': '||example.com^' + 'properties': + 'cname': + 'description': > + Set if `reason` is `Rewrite`. Otherwise, this field is absent. + 'type': 'string' + 'ip_addrs': + 'description': > + Set if `reason` is `Rewrite`. Otherwise, this field is absent. + 'items': + 'type': 'string' + 'type': 'array' + 'reason': + '$ref': '#/components/schemas/FilteringReason' + 'rules': + 'description': > + Applied rules. + 'items': + '$ref': '#/components/schemas/FilteringResultRule' + 'type': 'array' + 'service_name': + 'description': > + Set if `reason` is `FilteredBlockedService`. Otherwise, this field + is absent. + 'type': 'string' + 'required': + - 'reason' + - 'rules' + 'type': 'object' + + 'PostV1ProtectionDnsRewritesReq': + '$ref': '#/components/schemas/DnsRewritePost' + + 'PostV1ProtectionDnsRewritesResp': + '$ref': '#/components/schemas/DnsRewrite' + + 'PostV1ProtectionFiltersReq': + '$ref': '#/components/schemas/FilterPost' + + 'PostV1ProtectionFiltersResp': + '$ref': '#/components/schemas/Filter' + + 'PostV1ProtectionRefreshFilterReq': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1ProtectionRefreshFilterResp': + '$ref': '#/components/schemas/Filter' + + 'PostV1ProtectionRefreshFiltersReq': + 'description': > + Filters refresh parameters. + 'example': + 'allowlist': false + 'blocklist': true + 'properties': + 'allowlist': + 'description': > + If `true`, refresh all allowlist filters. + 'type': 'boolean' + 'blocklist': + 'description': > + If `true`, refresh all blocklist filters. + 'type': 'boolean' + 'required': + - 'allowlist' + - 'blocklist' + 'type': 'object' + + 'PostV1ProtectionRefreshFiltersResp': + 'description': > + Refresh results. + 'example': + 'errors': + - 'msg': 'context deadline exceeded' + 'uid': 'efgh5678' + 'refreshed': + - 'allowlist': false + 'enabled': true + 'name': 'AdMaster 5000 Super List v2.0 Final' + 'num_rules': 36766 + 'refreshed': 1614345496000 + 'uid': 'abcd1234' + 'url': 'https://admaster.example.com/list.txt' + 'properties': + 'errors': + 'description': > + All encountered errors. + 'items': + '$ref': '#/components/schemas/RefreshFilterError' + 'type': 'array' + 'refreshed': + 'description': > + Refreshed filters. + 'items': + '$ref': '#/components/schemas/Filter' + 'type': 'array' + 'required': + - 'errors' + - 'refreshed' + 'type': 'object' + + 'PostV1SettingsDnsCheckReq': + 'description': > + Validatable DNS settings. + 'example': + 'bootstrap_servers': + - '9.9.9.10' + - '149.112.112.10' + 'upstream_servers': + - '1.1.1.1' + - '8.8.8.8' + 'properties': + 'bootstrap_servers': + 'description': | + Bootstrap DNS servers' IP addresses to check. + 'items': + 'type': 'string' + 'type': 'array' + 'upstream_servers': + 'description': > + Upstream DNS servers to check. + 'items': + '$ref': '#/components/schemas/UpstreamServerAddr' + 'type': 'array' + 'required': + - 'bootstrap_servers' + - 'upstream_servers' + 'type': 'object' + + 'PostV1SettingsDnsCheckResp': + 'description': > + DNS settings validation results. + 'example': + 'bootstrap_servers': + '9.9.9.10': 'network is unreachable' + 'upstream_servers': + '8.8.8.8': 'network is unreachable' + 'properties': + 'bootstrap_servers': + 'additionalProperties': + 'minLength': 1 + 'type': 'string' + 'description': > + An IP-address-to-error mapping. If an address is not in this + object, the check for that address is successful. If there were no + errors, this field is absent. + 'upstream_servers': + 'additionalProperties': + 'type': 'string' + 'description': > + An upstream-address-to-error mapping. If an address is not in this + object, the check for that address is successful. If there were no + errors, this field is absent. + 'type': 'object' + + 'PostV1SettingsTlsCheckReq': + 'description': > + Validatable TLS settings. + 'example': + 'certificate_path': '/etc/ssl/example.com.cert' + 'port_dns_over_quic': 784 + 'port_dns_over_tls': 853 + 'port_https': 443 + 'private_key_path': '/etc/ssl/example.com.key' + 'server_name': 'dns.example.com' + 'properties': + 'certificate': + 'description': | + Base64-encoded string with PEM-encoded certificate chain. + + Should not be sent if `certificate_path` is sent. Otherwise, must + be sent. + 'format': 'byte' + 'type': 'string' + 'certificate_path': + 'description': | + Path to the certificate file. + + Should not be sent if `certificate` is sent. Otherwise, must be + sent. + 'type': 'string' + 'port_dns_over_quic': + 'default': 784 + 'description': > + The DNS-over-QUIC port. If `0`, DNS-over-QUIC is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'port_dns_over_tls': + 'default': 853 + 'description': > + The DNS-over-TLS port. If `0`, DNS-over-TLS is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'port_https': + 'default': 443 + 'description': > + The HTTPS port. If `0`, HTTPS is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'private_key': + 'description': | + Base64-encoded string with PEM-encoded private key. + + Should not be sent if `private_key_path` is sent. Otherwise, must + be sent. + 'format': 'byte' + 'type': 'string' + 'private_key_path': + 'description': | + Path to the private key file. + + Should not be sent if `private_key` is sent. Otherwise, must be + sent. + 'type': 'string' + 'server_name': + 'description': > + The name of the server. Used to validate the certificates as well + as to check ClientIDs in DNS-over-HTTP and DNS-over-TLS. + 'type': 'string' + 'required': + - 'port_dns_over_quic' + - 'port_dns_over_tls' + - 'port_https' + - 'server_name' + 'type': 'object' + + 'PostV1SettingsTlsCheckResp': + 'description': > + TLS settings validation results. + 'example': + 'dns_names': + - '*.example.com' + - 'example.com' + 'issuer': 'CN=Example CA,OU=Development,O=Example CA,L=Canberra,ST=Canberra,C=AU' + 'key_type': 'RSA' + 'not_after': 1614345497000 + 'not_before': 1614345496000 + 'port_https_error': 'address already in use' + 'subject': 'CN=Example CA,OU=Development,O=Example CA,L=Canberra,ST=Canberra,C=AU' + 'warnings': [] + 'properties': + 'cert_error': + 'description': > + Certificate validation error, if any. If the certificate is valid, + this field is absent. + 'type': 'string' + 'chain_error': + 'description': > + Certificate chain validation error, if any. If the certificate + chain is valid, this field is absent. + 'type': 'string' + 'dns_names': + 'description': > + The value of the `SubjectAltNames` field of the first certificate in + the chain. + 'items': + 'type': 'string' + 'type': 'array' + 'issuer': + 'description': > + The issuer of the first certificate in the chain. + 'type': 'string' + 'key_error': + 'description': > + Private key pair error, if any. If the key is valid, this field is + absent. + 'type': 'string' + 'key_type': + '$ref': '#/components/schemas/TlsKeyType' + 'not_after': + 'description': > + The value of the `NotAfter` field of the first certificate in the + chain, as a Unix time, in milliseconds. + 'format': 'double' + 'type': 'number' + 'not_before': + 'description': > + The value of the `NotBefore` field of the first certificate in the + chain, as a Unix time, in milliseconds. + 'format': 'double' + 'type': 'number' + 'port_dns_over_quic_error': + 'description': > + DNS-over-QUIC port checking error, if any. If the port is + available, this field is absent. + 'type': 'string' + 'port_dns_over_tls_error': + 'description': > + DNS-over-TLS port checking error, if any. If the port is available, + this field is absent. + 'type': 'string' + 'port_https_error': + 'description': > + DNS-over-HTTPS port checking error, if any. If the port is + available, this field is absent. + 'type': 'string' + 'pair_error': + 'description': > + Certificate and key pair error, if any. If the pair is valid, this + field is absent. + 'type': 'string' + 'subject': + 'description': > + The subject of the first certificate in the chain. + 'type': 'string' + 'warnings': + 'description': > + Validation warnings, if any. + 'items': + 'type': 'string' + 'type': 'array' + 'required': + - 'dns_names' + - 'issuer' + - 'key_type' + - 'not_after' + - 'not_before' + - 'subject' + - 'warnings' + 'type': 'object' + + 'PostV1StatsClearReq': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1SystemResetReq': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1SystemResetResp': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1SystemUpdateReq': + 'description': > + Currently empty, may get more fields in the future. + 'type': 'object' + + 'PostV1SystemUpdateResp': + 'example': + 'reload': 10000 + 'properties': + 'reload': + 'description': > + Time, after which the frontend must reload the page, in + milliseconds. + 'format': 'double' + 'type': 'number' + 'type': 'object' + + 'Profile': + 'description': > + Current user's profile. + 'example': + 'lang': 'en' + 'username': 'admin' + 'properties': + 'lang': + '$ref': '#/components/schemas/Lang' + 'username': + 'description': > + Current user's name. + 'type': 'string' + 'required': + - 'lang' + - 'username' + 'type': 'object' + + 'ProtectionSettings': + 'allOf': + - '$ref': '#/components/schemas/ProtectionSettingsPatch' + - 'description': > + Protection settings. + 'example': + 'autoupdate': 86400000 + 'filtering': true + 'parental': true + 'safe_browsing': false + 'safe_search': false + 'required': + - 'autoupdate' + - 'filtering' + - 'parental' + - 'safe_browsing' + - 'safe_search' + + 'ProtectionSettingsPatch': + 'description': > + Protection settings update object. + 'example': + 'autoupdate': 0 + 'properties': + 'autoupdate': + 'description': > + Filter automatic update interval, in milliseconds. Set to `0` to + disable automatic updates. + 'format': 'double' + 'minimum': 0 + 'maximum': 604800000 + 'type': 'number' + 'filtering': + 'description': > + If `true`, filtering based on filter rule lists is enabled. + 'type': 'boolean' + 'parental': + 'description': > + If `true`, parental protection is enabled. + 'type': 'boolean' + 'pause_end': + 'description': | + If `state` is `paused`, `pause_end` will show the Unix time until + which the protection is disabled in milliseconds. Otherwise, the + property won't be set. + + When updating, if `state` is set to `paused`, `pause_end` must be + set to a timestamp in the future. + 'format': 'double' + 'type': 'number' + 'safe_browsing': + 'description': > + If `true`, safe browsing protection is enabled. + 'type': 'boolean' + 'safe_search': + 'description': > + If `true`, safe search protection is enabled. + 'type': 'boolean' + 'state': + '$ref': '#/components/schemas/ProtectionSettingsState' + 'type': 'object' + + 'ProtectionSettingsState': + 'description': | + State of protection. + + * `off`: Protection is disabled. + + * `on`: Protection is enabled. + + * `paused`: Protection is paused. See the `pause_end` property to get + or set the end of the pause. + 'enum': + - 'off' + - 'on' + - 'paused' + 'type': 'string' + + 'PutV1ProtectionBlockedServicesReq': + '$ref': '#/components/schemas/BlockedServices' + + 'PutV1ProtectionCustomRulesReq': + '$ref': '#/components/schemas/CustomRules' + + 'PutV1SettingsDnsAccessReq': + '$ref': '#/components/schemas/DnsAccessSettings' + + 'RefreshFilterError': + 'description': > + Filter refresh error. + 'properties': + 'msg': + 'description': > + Error message. + 'type': 'string' + 'uid': + '$ref': '#/components/schemas/Uid' + 'required': + - 'msg' + - 'uid' + 'type': 'object' + + 'RuntimeClient': + 'description': > + A runtime client's information. + 'properties': + 'host': + 'description': > + The RDNS host of the runtime, if any. If there is none, this field + is absent. + 'type': 'string' + 'ip': + 'description': > + The IP-address of the runtime client. + 'type': 'string' + 'sources': + 'description': > + The sources from which the information about this runtime client was + collected. + 'items': + '$ref': '#/components/schemas/RuntimeClientSource' + 'minItems': 1 + 'type': 'array' + 'num_blocked_requests': + 'description': > + Total number of blocked requests for this runtime client. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'num_requests': + 'description': > + Total number of requests for this runtime client. + 'format': 'int64' + 'minimum': 0 + 'type': 'integer' + 'whois': + '$ref': '#/components/schemas/Whois' + 'required': + - 'ip' + - 'num_blocked_requests' + - 'num_requests' + - 'sources' + 'type': 'object' + + 'RuntimeClientSource': + 'description': > + The source from which the information about this runtime client was + collected. + + * `arp`: The information was collected from the `arp -a` output. + + * `dhcp`: The information was collected from our DHCP server. + + * `hosts_file`: The information was collected from the `/etc/hosts` + file. + + * `rdns`: The information was collected by performing a reverse DNS + lookup. + + * `whois`: The information was collected by performing a WHOIS lookup. + 'enum': + - 'arp' + - 'dhcp' + - 'hosts_file' + - 'rdns' + - 'whois' + 'type': 'string' + + 'StaticIpCheckResult': + 'properties': + 'error': + 'description': > + Error, if any. If there is no error, this field is absent. + 'type': 'string' + 'ip': + 'description': > + The IP address. + 'type': 'string' + 'static': + 'description': > + If `true`, the interface has a static IP address. + 'type': 'boolean' + 'supported': + 'description': > + If `true`, setting a static IP on this system is supported. + 'type': 'boolean' + 'required': + - 'ip' + - 'static' + - 'supported' + 'type': 'object' + + 'StatsSettings': + 'allOf': + - '$ref': '#/components/schemas/StatsSettingsPatch' + - 'description': > + Statistics settings. + 'required': + - 'autorefresh' + - 'retention' + + 'StatsSettingsPatch': + 'description': > + Statistics settings update object. + 'properties': + 'autorefresh': + 'description': > + Statistics UI autorefresh time in milliseconds. `0` means + autorefresh is disabled. + 'format': 'double' + 'type': 'number' + 'retention': + 'description': > + Statistics retention interval, in milliseconds. + 'format': 'double' + 'type': 'number' + 'type': 'object' + + 'TimeUnit': + 'description': > + Time units used for statistics. See the documentation for the + `GET /api/v1/stats/all` request. + 'enum': + - 'hour' + - 'day' + 'type': 'string' + + 'TlsKeyType': + 'description': > + TLS key type. + 'enum': + - 'ECDSA' + - 'RSA' + 'type': 'string' + + 'TlsSettings': + 'allOf': + - '$ref': '#/components/schemas/TlsSettingsPatch' + - 'description': > + TLS and encryption settings. + 'example': + 'certificate_path': '/etc/ssl/example.com.cert' + 'enabled': true + 'force_https': true + 'port_dns_over_quic': 784 + 'port_dns_over_tls': 853 + 'port_https': 443 + 'private_key_path': '/etc/ssl/example.com.key' + 'server_name': 'dns.example.com' + 'required': + - 'enabled' + - 'force_https' + - 'port_dns_over_quic' + - 'port_dns_over_tls' + - 'port_https' + - 'server_name' + + 'TlsSettingsPatch': + 'description': > + TLS and encryption settings update object. + 'example': + 'certificate': 'Base64KeyDatAA==' + 'enabled': true + 'private_key': 'Base64CertDatA==' + 'properties': + 'certificate': + 'description': | + Base64-encoded string with PEM-encoded certificate chain. + + Should not be sent if `certificate_path` is sent. Otherwise, must + be sent. + 'format': 'byte' + 'type': 'string' + 'certificate_path': + 'description': | + Path to the certificate file. + + Should not be sent if `certificate` is sent. Otherwise, must be + sent. + 'type': 'string' + 'enabled': + 'description': > + If `true`, AdGuard Home the administration interface will be served + over HTTPS, and the DNS server will listen requests over + DNS-over-TLS and other protocols. + 'type': 'boolean' + 'force_https': + 'description': > + If `true`, enabled the HTTP-to-HTTPS redirect. + 'type': 'boolean' + 'port_dns_over_quic': + 'default': 784 + 'description': > + The DNS-over-QUIC port. If `0`, DNS-over-QUIC is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'port_dns_over_tls': + 'default': 853 + 'description': > + The DNS-over-TLS port. If `0`, DNS-over-TLS is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'port_https': + 'default': 443 + 'description': > + The HTTPS port. If `0`, HTTPS is disabled. + 'format': 'int64' + 'maximum': 65535 + 'minimum': 0 + 'type': 'integer' + 'private_key': + 'description': | + Base64-encoded string with PEM-encoded private key. + + Should not be sent if `private_key_path` is sent. Otherwise, must + be sent. + 'format': 'byte' + 'type': 'string' + 'private_key_path': + 'description': | + Path to the private key file. + + Should not be sent if `private_key` is sent. Otherwise, must be + sent. + 'type': 'string' + 'server_name': + 'description': > + The name of the server. Used to validate the certificates as well + as to check ClientIDs in DNS-over-HTTP and DNS-over-TLS. + 'type': 'string' + 'type': 'object' + + 'Uid': + 'description': > + A unique ID of an entity, an opaque string. + 'pattern': '[0-9a-zA-Z_-]{1,64}' + 'type': 'string' + + 'UnauthorizedResp': + 'example': + 'code': 'AUT000' + 'msg': 'no or bad authorization provided' + 'properties': + 'code': + '$ref': '#/components/schemas/ErrorCode' + 'msg': + 'description': > + Error message string. + 'type': 'string' + 'required': + - 'code' + - 'msg' + 'type': 'object' + + 'UnprocessableEntityResp': + 'example': + 'code': 'JSN001' + 'msg': >- + json: cannot unmarshal string into Go struct field T.A of type int + 'properties': + 'code': + '$ref': '#/components/schemas/ErrorCode' + 'msg': + 'description': > + Error message string. + 'type': 'string' + 'required': + - 'code' + - 'msg' + 'type': 'object' + + 'UpstreamServerAddr': + 'description': | + Upstream DNS server address. Supported item formats: + + * `94.140.14.140`: plain DNS-over-UDP. + + * `tls://dns-unfiltered.adguard.com`: encrypted DNS-over-TLS. + + * `https://dns-unfiltered.adguard.com/dns-query`: encrypted + DNS-over-HTTPS. + + * `quic://dns-unfiltered.adguard.com:784`: encrypted DNS-over-QUIC + (experimental). + + * `tcp://94.140.14.140`: plain DNS-over-TCP. + + * `sdns://...`: DNS Stamps for DNSCrypt or DNS-over-HTTPS + resolvers. + + * `[/example.local/]94.140.14.140`: DNS upstream for specific + domain(s). + + * `# comment`: A comment. + 'type': 'string' + + 'Whois': + 'additionalProperties': + 'type': 'string' + 'description': > + WHOIS information, if any. If there are none, this field is usually + absent. + 'minProperties': 1 + 'type': 'object' + + # TODO(a.garipov): Find a way to specify a cookie authorization. + 'securitySchemes': + 'basicAuth': + 'description': > + Basic HTTP authorization. + 'scheme': 'basic' + 'type': 'http' diff --git a/scripts/make/go-build.sh b/scripts/make/go-build.sh index 7854166c..c998a611 100644 --- a/scripts/make/go-build.sh +++ b/scripts/make/go-build.sh @@ -123,4 +123,14 @@ CGO_ENABLED="$cgo_enabled" GO111MODULE='on' export CGO_ENABLED GO111MODULE -"$go" build --ldflags "$ldflags" "$race_flags" --trimpath "$o_flags" "$v_flags" "$x_flags" +# Build the new binary if requested. +if [ "${V1API:-0}" -eq '0' ] +then + tags_flags='--tags=' +else + tags_flags='--tags=v1' +fi +readonly tags_flags + +"$go" build --ldflags "$ldflags" "$race_flags" "$tags_flags" --trimpath "$o_flags" "$v_flags"\ + "$x_flags" diff --git a/scripts/make/go-lint.sh b/scripts/make/go-lint.sh index c363e513..df2f297a 100644 --- a/scripts/make/go-lint.sh +++ b/scripts/make/go-lint.sh @@ -140,6 +140,7 @@ underscores() { -e '_others.go'\ -e '_test.go'\ -e '_unix.go'\ + -e '_v1.go'\ -e '_windows.go' \ -v\ | sed -e 's/./\t\0/' @@ -222,7 +223,7 @@ gocyclo --over 17 ./internal/dhcpd/ ./internal/dnsforward/\ # Apply stricter standards to new or somewhat refactored code. gocyclo --over 10 ./internal/aghio/ ./internal/aghnet/ ./internal/aghos/\ ./internal/aghtest/ ./internal/stats/ ./internal/tools/\ - ./internal/updater/ ./internal/version/ ./main.go + ./internal/updater/ ./internal/v1/ ./internal/version/ ./main.go\ ineffassign ./... From c4ff80fd3aa070b75bcfc02b0aaf6b5670fddefe Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Wed, 27 Apr 2022 11:39:48 +0300 Subject: [PATCH 24/99] Pull request: dnsforward: ddr support Merge in DNS/adguard-home from 4463-ddr-support-1 to master Squashed commit of the following: commit 74d8337a9d78e00a0b01301bbf92054fc58aff0d Merge: 7882c56e ed449c61 Author: Dimitry Kolyshev Date: Wed Apr 27 10:32:48 2022 +0200 Merge remote-tracking branch 'origin/master' into 4463-ddr-support-1 commit 7882c56eced204b99a0189c839f5b5ef56fcbfd8 Author: Dimitry Kolyshev Date: Tue Apr 26 13:29:16 2022 +0200 all: docs commit 59593cf47f8db2131fb8a4a44ec3721de8f73567 Author: Dimitry Kolyshev Date: Tue Apr 26 13:06:49 2022 +0200 all: docs commit 13bfe00d91b190a2538eeee642ce40abe031ecf2 Author: Dimitry Kolyshev Date: Tue Apr 26 12:58:48 2022 +0200 all: docs commit a663b53d211483a717a480e24e120a201dc3d9da Merge: 53122f6a 235316e0 Author: Dimitry Kolyshev Date: Tue Apr 26 12:33:07 2022 +0200 Merge remote-tracking branch 'origin/master' into 4463-ddr-support-1 commit 53122f6aac8e9ede69de833e367e006f4c5c75c0 Author: Dimitry Kolyshev Date: Tue Apr 26 12:30:56 2022 +0200 dnsforward: ddr support commit 87083ded02c120e1fb3e54b885a1992efd8f780d Author: Dimitry Kolyshev Date: Tue Apr 26 11:51:06 2022 +0200 dnsforward: ddr support commit 3dc711e0a9ba1a024e7d24527b2a690aa36413ce Author: Dimitry Kolyshev Date: Tue Apr 26 11:39:59 2022 +0200 dnsforward: imp code commit f63f6a9d65a96960ae2c06aeca2b32aef70d8f63 Author: Dimitry Kolyshev Date: Tue Apr 26 11:34:23 2022 +0200 dnsforward: ddr support commit e64ffcdac8f9428e4c93a6dc99cc3f1bb090af35 Author: Dimitry Kolyshev Date: Tue Apr 26 11:22:20 2022 +0200 dnsforward: ddr support commit 297460946bb1765137c7c3fe3e298cd574635287 Author: Dimitry Kolyshev Date: Tue Apr 26 11:08:59 2022 +0200 dnsforward: imp code commit 61b4e2e0e06e212c31b7a9d1b09fab392ae6dbc4 Author: Dimitry Kolyshev Date: Mon Apr 25 14:39:34 2022 +0200 dnsforward: ddr support commit 7c2787e12eb67a02b41cbb4fe36a12671259f9c9 Author: Dimitry Kolyshev Date: Mon Apr 25 11:41:42 2022 +0200 all: docs commit 29c2c872843f6d006e6a98144a52e23a4cbe7be9 Author: Dimitry Kolyshev Date: Mon Apr 25 11:26:07 2022 +0200 dnsforward: ddr support commit 2d4ba0c4ce4fbbf3d99da8dd92349da2ec9cff13 Author: Dimitry Kolyshev Date: Mon Apr 25 11:03:34 2022 +0200 dnsforward: ddr support commit 0efb5b5cd55bcba3dfae35e80209277f0643a87e Author: Dimitry Kolyshev Date: Sun Apr 24 13:07:25 2022 +0200 dnsforward: imp code commit 884381ef04029d5d743834555cb6601d891c2d25 Author: Dimitry Kolyshev Date: Sun Apr 24 12:56:41 2022 +0200 dnsforward: imp code commit 41231f24e83a9690d36546e83fd61ddd709050ed Author: Dimitry Kolyshev Date: Fri Apr 22 16:05:47 2022 +0200 dnsforward: ddr support commit 9d9da3f479efa5d5609f9b1e6b0d1a93fc253b9f Author: Dimitry Kolyshev Date: Fri Apr 22 13:46:29 2022 +0200 all: ddr support commit b225363df143d599e9acbf1a6b0bf6d00044dd47 Author: Dimitry Kolyshev Date: Fri Apr 22 13:38:27 2022 +0200 dnsforward: imp code ... and 10 more commits --- CHANGELOG.md | 5 +- internal/dnsforward/config.go | 3 +- internal/dnsforward/dns.go | 76 +++++++++++++++++ internal/dnsforward/dns_test.go | 146 ++++++++++++++++++++++++++++++++ internal/home/config.go | 1 + 5 files changed, 229 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 047726ff..84f45312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ and this project adheres to ### Added +- Support for Discovery of Designated Resolvers (DDR) according to the + [RFC draft][ddr-draft-06] ([#4463]). - The ability to control each source of runtime clients separately via `clients.runtime_sources` configuration object ([#3020]). - The ability to customize the set of networks that are considered private @@ -143,8 +145,9 @@ In this release, the schema version has changed from 12 to 14. [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 -[repr]: https://reproducible-builds.org/docs/source-date-epoch/ +[ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 +[repr]: https://reproducible-builds.org/docs/source-date-epoch/ diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 9a050f52..16a6325e 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -122,6 +122,7 @@ type FilteringConfig struct { EnableDNSSEC bool `yaml:"enable_dnssec"` // Set AD flag in outcoming DNS request EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option MaxGoroutines uint32 `yaml:"max_goroutines"` // Max. number of parallel goroutines for processing incoming requests + HandleDDR bool `yaml:"handle_ddr"` // Handle DDR requests // IpsetList is the ipset configuration that allows AdGuard Home to add // IP addresses of the specified domain names to an ipset list. Syntax: @@ -151,7 +152,7 @@ type TLSConfig struct { PrivateKeyData []byte `yaml:"-" json:"-"` // ServerName is the hostname of the server. Currently, it is only being - // used for ClientID checking. + // used for ClientID checking and Discovery of Designated Resolvers (DDR). ServerName string `yaml:"-" json:"-"` cert tls.Certificate diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index d423482a..19d54d91 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -76,6 +76,10 @@ const ( resultCodeError ) +// ddrHostFQDN is the FQDN used in Discovery of Designated Resolvers (DDR) requests. +// See https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html. +const ddrHostFQDN = "_dns.resolver.arpa." + // handleDNSRequest filters the incoming DNS requests and writes them to the query log func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error { ctx := &dnsContext{ @@ -94,6 +98,7 @@ func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error { mods := []modProcessFunc{ s.processRecursion, s.processInitial, + s.processDDRQuery, s.processDetermineLocal, s.processInternalHosts, s.processRestrictLocal, @@ -241,6 +246,77 @@ func (s *Server) onDHCPLeaseChanged(flags int) { s.setTableIPToHost(ipToHost) } +// processDDRQuery responds to SVCB query for a special use domain name +// ‘_dns.resolver.arpa’. The result contains different types of encryption +// supported by current user configuration. +// +// See https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html. +func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) { + d := ctx.proxyCtx + question := d.Req.Question[0] + + if !s.conf.HandleDDR { + return resultCodeSuccess + } + + if question.Name == ddrHostFQDN { + // TODO(a.garipov): Check DoQ support in next RFC drafts. + if s.dnsProxy.TLSListenAddr == nil && s.dnsProxy.HTTPSListenAddr == nil || + question.Qtype != dns.TypeSVCB { + d.Res = s.makeResponse(d.Req) + + return resultCodeFinish + } + + d.Res = s.makeDDRResponse(d.Req) + + return resultCodeFinish + } + + return resultCodeSuccess +} + +// makeDDRResponse creates DDR answer according to server configuration. +func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) { + resp = s.makeResponse(req) + domainName := s.conf.ServerName + + for _, addr := range s.dnsProxy.HTTPSListenAddr { + values := []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"h2"}}, + &dns.SVCBPort{Port: uint16(addr.Port)}, + &dns.SVCBDoHPath{Template: "/dns-query?dns"}, + } + + ans := &dns.SVCB{ + Hdr: s.hdr(req, dns.TypeSVCB), + Priority: 1, + Target: domainName, + Value: values, + } + + resp.Answer = append(resp.Answer, ans) + } + + for _, addr := range s.dnsProxy.TLSListenAddr { + values := []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"dot"}}, + &dns.SVCBPort{Port: uint16(addr.Port)}, + } + + ans := &dns.SVCB{ + Hdr: s.hdr(req, dns.TypeSVCB), + Priority: 2, + Target: domainName, + Value: values, + } + + resp.Answer = append(resp.Answer, ans) + } + + return resp +} + // processDetermineLocal determines if the client's IP address is from // locally-served network and saves the result into the context. func (s *Server) processDetermineLocal(dctx *dnsContext) (rc resultCode) { diff --git a/internal/dnsforward/dns_test.go b/internal/dnsforward/dns_test.go index 54104268..8ab7501c 100644 --- a/internal/dnsforward/dns_test.go +++ b/internal/dnsforward/dns_test.go @@ -14,6 +14,152 @@ import ( "github.com/stretchr/testify/require" ) +const ddrTestDomainName = "dns.example.net" + +func TestServer_ProcessDDRQuery(t *testing.T) { + dohSVCB := &dns.SVCB{ + Priority: 1, + Target: ddrTestDomainName, + Value: []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"h2"}}, + &dns.SVCBPort{Port: 8044}, + &dns.SVCBDoHPath{Template: "/dns-query?dns"}, + }, + } + + dotSVCB := &dns.SVCB{ + Priority: 2, + Target: ddrTestDomainName, + Value: []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"dot"}}, + &dns.SVCBPort{Port: 8043}, + }, + } + + testCases := []struct { + name string + host string + want []*dns.SVCB + wantRes resultCode + portDoH int + portDoT int + qtype uint16 + ddrEnabled bool + }{{ + name: "pass_host", + wantRes: resultCodeSuccess, + host: "example.net.", + qtype: dns.TypeSVCB, + ddrEnabled: true, + portDoH: 8043, + }, { + name: "pass_qtype", + wantRes: resultCodeFinish, + host: ddrHostFQDN, + qtype: dns.TypeA, + ddrEnabled: true, + portDoH: 8043, + }, { + name: "pass_disabled_tls", + wantRes: resultCodeFinish, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: true, + }, { + name: "pass_disabled_ddr", + wantRes: resultCodeSuccess, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: false, + portDoH: 8043, + }, { + name: "dot", + wantRes: resultCodeFinish, + want: []*dns.SVCB{dotSVCB}, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: true, + portDoT: 8043, + }, { + name: "doh", + wantRes: resultCodeFinish, + want: []*dns.SVCB{dohSVCB}, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: true, + portDoH: 8044, + }, { + name: "dot_doh", + wantRes: resultCodeFinish, + want: []*dns.SVCB{dotSVCB, dohSVCB}, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: true, + portDoT: 8043, + portDoH: 8044, + }} + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + s := prepareTestServer(t, tc.portDoH, tc.portDoT, tc.ddrEnabled) + + req := createTestMessageWithType(tc.host, tc.qtype) + + dctx := &dnsContext{ + proxyCtx: &proxy.DNSContext{ + Req: req, + }, + } + + res := s.processDDRQuery(dctx) + require.Equal(t, tc.wantRes, res) + + if tc.wantRes != resultCodeFinish { + return + } + + msg := dctx.proxyCtx.Res + require.NotNil(t, msg) + + for _, v := range tc.want { + v.Hdr = s.hdr(req, dns.TypeSVCB) + } + + assert.ElementsMatch(t, tc.want, msg.Answer) + }) + } +} + +func prepareTestServer(t *testing.T, portDoH, portDoT int, ddrEnabled bool) (s *Server) { + t.Helper() + + proxyConf := proxy.Config{} + + if portDoH > 0 { + proxyConf.HTTPSListenAddr = []*net.TCPAddr{{Port: portDoH}} + } + + if portDoT > 0 { + proxyConf.TLSListenAddr = []*net.TCPAddr{{Port: portDoT}} + } + + s = &Server{ + dnsProxy: &proxy.Proxy{ + Config: proxyConf, + }, + conf: ServerConfig{ + FilteringConfig: FilteringConfig{ + HandleDDR: ddrEnabled, + }, + TLSConfig: TLSConfig{ + ServerName: ddrTestDomainName, + }, + }, + } + + return s +} + func TestServer_ProcessDetermineLocal(t *testing.T) { s := &Server{ privateNets: netutil.SubnetSetFunc(netutil.IsLocallyServed), diff --git a/internal/home/config.go b/internal/home/config.go index 720683a1..14f5781e 100644 --- a/internal/home/config.go +++ b/internal/home/config.go @@ -187,6 +187,7 @@ var config = &configuration{ Ratelimit: 20, RefuseAny: true, AllServers: false, + HandleDDR: true, FastestTimeout: timeutil.Duration{ Duration: fastip.DefaultPingWaitTimeout, }, From 5d52e68d264b77dd27ac53616027e6a26637c6e8 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 27 Apr 2022 14:06:10 +0300 Subject: [PATCH 25/99] Pull request: home: imp client finding logging Updates #4526. Squashed commit of the following: commit 970476ea238cbab797912e1c50eca35e3f74a52f Merge: 3e2dde81 c4ff80fd Author: Ainar Garipov Date: Wed Apr 27 14:01:17 2022 +0300 Merge branch 'master' into 4526-add-client-logs commit 3e2dde81d7325b75c257f333e2c4e417f4ae203d Author: Ainar Garipov Date: Wed Apr 27 13:59:19 2022 +0300 home: imp logs commit 094bfe34770b4bdc504b5ae97dd2d3842b2f73cf Author: Ainar Garipov Date: Tue Apr 26 21:11:18 2022 +0300 home: imp client finding logging --- internal/home/dns.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/home/dns.go b/internal/home/dns.go index e28193ee..1c04c6c3 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -330,24 +330,28 @@ func getDNSEncryption() (de dnsEncryption) { // applyAdditionalFiltering adds additional client information and settings if // the client has them. -func applyAdditionalFiltering(clientAddr net.IP, clientID string, setts *filtering.Settings) { +func applyAdditionalFiltering(clientIP net.IP, clientID string, setts *filtering.Settings) { Context.dnsFilter.ApplyBlockedServices(setts, nil, true) - if clientAddr == nil { + log.Debug("looking up settings for client with ip %s and clientid %q", clientIP, clientID) + + if clientIP == nil { return } - setts.ClientIP = clientAddr + setts.ClientIP = clientIP c, ok := Context.clients.Find(clientID) if !ok { - c, ok = Context.clients.Find(clientAddr.String()) + c, ok = Context.clients.Find(clientIP.String()) if !ok { + log.Debug("client with ip %s and clientid %q not found", clientIP, clientID) + return } } - log.Debug("using settings for client %s with ip %s and clientid %q", c.Name, clientAddr, clientID) + log.Debug("using settings for client %q with ip %s and clientid %q", c.Name, clientIP, clientID) if c.UseOwnBlockedServices { Context.dnsFilter.ApplyBlockedServices(setts, c.BlockedServices, false) From 6dc9e73ce4d8bdc01ed3b99facc7d4062288a760 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 27 Apr 2022 14:18:50 +0300 Subject: [PATCH 26/99] Pull request: client: upd i18n Merge in DNS/adguard-home from upd-i18n to master Squashed commit of the following: commit 0e0a3290a02780b147aacff529c4ba3bd3ace68f Author: Ainar Garipov Date: Wed Apr 27 14:13:24 2022 +0300 client: upd i18n --- client/src/__locales/cs.json | 4 ++-- client/src/__locales/da.json | 4 ++-- client/src/__locales/de.json | 16 ++++++++-------- client/src/__locales/es.json | 4 ++-- client/src/__locales/fi.json | 2 +- client/src/__locales/nl.json | 2 +- client/src/__locales/ro.json | 18 +++++++++--------- client/src/__locales/tr.json | 20 ++++++++++---------- client/src/__locales/uk.json | 22 +++++++++++----------- client/src/__locales/zh-cn.json | 23 +++++++++++------------ client/src/__locales/zh-tw.json | 2 +- 11 files changed, 58 insertions(+), 59 deletions(-) diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index 26759394..8331dd50 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Bootstrap DNS servery", "bootstrap_dns_desc": "Servery Bootstrap DNS se používají k řešení IP adres DoH/DoT, které zadáváte jako upstreamy.", "local_ptr_title": "Soukromé reverzní DNS servery", - "local_ptr_desc": "Servery DNS, které AdGuard Home používá pro lokální dotazy PTR. Tyto servery se používají k rozlišení názvů hostitelů klientů se soukromými adresami IP, například \"192.168.12.34\" pomocí rDNS. Pokud není nastaveno, AdGuard Home automaticky použije výchozí řešitele vašeho OS s výjimkou adres samotného AdGuard Home.", + "local_ptr_desc": "Servery DNS, které AdGuard Home používá pro lokální dotazy PTR. Tyto servery se používají k řešení požadavků PTR na adresy v soukromých rozmezích IP, například \"192.168.12.34\", pomocí reverzního DNS. Pokud není nastaveno, AdGuard Home automaticky použije výchozí řešitele vašeho OS s výjimkou adres samotného AdGuard Home.", "local_ptr_default_resolver": "Ve výchozím nastavení používá AdGuard Home následující reverzní DNS řešitele: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home nemohl určit vhodné soukromé reverzní DNS řešitele pro tento systém.", "local_ptr_placeholder": "Zadejte jednu adresu serveru na řádek", @@ -283,7 +283,7 @@ "download_mobileconfig_doh": "Stáhnout .mobileconfig pro DNS skrze HTTPS", "download_mobileconfig_dot": "Stáhnout .mobileconfig pro DNS skrze TLS", "download_mobileconfig": "Stáhnout konfigurační soubor", - "plain_dns": "Čisté DNS", + "plain_dns": "Běžný DNS", "form_enter_rate_limit": "Zadejte rychlostní limit", "rate_limit": "Rychlostní limit", "edns_enable": "Povolit klientskou podsíť EDNS", diff --git a/client/src/__locales/da.json b/client/src/__locales/da.json index 1b12ad06..4b077cf8 100644 --- a/client/src/__locales/da.json +++ b/client/src/__locales/da.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Bootstrap DNS-servere", "bootstrap_dns_desc": "Bootstrap DNS-servere bruges til at fortolke IP-adresser for de DoH-/DoT-resolvere, du angiver som upstream.", "local_ptr_title": "Private reverse DNS-servere", - "local_ptr_desc": "De DNS-servere, som AdGuard Home bruger til lokale PTR-forespørgsler. Disse servere bruges til at opløse klientværtsnavne med private IP-adresser, f.eks. \"192.168.12.34\", vha. rDNS. Hvis ikke indstillet, bruger AdGuard Home dit operativsystems standard DNS-opløsere undtagen for sine egne adresser.", + "local_ptr_desc": "DNS-servere brugt af AdGuard Home til lokale PTR-forespørgsler. Disse servere bruges til at opløse PTR-forespørgsler fra private IP-adresseområder, f.eks. \"192.168.12.34\", vha. reverse DNS. Hvis ikke opsat, bruger AdGuard Home operativsystems standard DNS-opløsere undtagen for sine egne adresser.", "local_ptr_default_resolver": "AdGuard Home bruger som standard flg. reverse DNS-opløsere: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home kunne ikke fastslå egnede private reverse DNS-opløsere for dette system.", "local_ptr_placeholder": "Indtast en serveradresse pr. Linje", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Skift de aktuelle DNS 1- og DNS 2-værdier til dine AdGuard Home-serveradresser.", "install_devices_ios_list_1": "Tryk på Indstillinger på Hjem-skærmen.", "install_devices_ios_list_2": "Vælg Wi-Fi i menuen til venstre (det er umuligt at opsætte DNS for mobilnetværker).", - "install_devices_ios_list_3": "Tryk på navnet på det aktuelt aktive netværk.", + "install_devices_ios_list_3": "Tryk på navnet for det aktuelt aktive netværk.", "install_devices_ios_list_4": "Angiv dine AdGuard Home-serveradresser i DNS-feltet.", "get_started": "Komme I Gang", "next": "Næste", diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index be5666a8..0fe6345d 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -149,9 +149,9 @@ "general_settings": "Allgemeine Einstellungen", "dns_settings": "DNS-Einstellungen", "dns_blocklists": "DNS-Sperrliste", - "dns_allowlists": "DNS-Freigabelisten", + "dns_allowlists": "DNS-Positivlisten", "dns_blocklists_desc": "AdGuard Home sperrt Domains, die in den Sperrlisten enthalten sind.", - "dns_allowlists_desc": "Domains aus DNS-Freigabelisten werden auch dann zugelassen, wenn sie in einer der Sperrlisten enthalten sind.", + "dns_allowlists_desc": "Domains aus DNS-Positivlisten werden auch dann zugelassen, wenn sie in einer der Sperrlisten enthalten sind.", "custom_filtering_rules": "Benutzerdefinierte Filterregeln", "encryption_settings": "Verschlüsselungseinstellungen", "dhcp_settings": "DHCP-Einstellungen", @@ -181,21 +181,21 @@ "elapsed": "Verstrichen", "filters_and_hosts_hint": "AdGuard Home versteht grundlegende Werbefilterregeln und Host-Datei-Syntax.", "no_blocklist_added": "Keine Sperrliste hinzugefügt", - "no_whitelist_added": "Keine Freigabeliste hinzugefügt", + "no_whitelist_added": "Keine Positivliste hinzugefügt", "add_blocklist": "Sperrliste hinzufügen", - "add_allowlist": "Freigabeliste hinzufügen", + "add_allowlist": "Positivliste hinzufügen", "cancel_btn": "Abbrechen", "enter_name_hint": "Name eingeben", "enter_url_or_path_hint": "URL oder absoluten Pfad der Liste eingeben", "check_updates_btn": "Nach Aktualisierungen suchen", "new_blocklist": "Neue Sperrliste", - "new_allowlist": "Neue Freigabeliste", + "new_allowlist": "Neue Positivliste", "edit_blocklist": "Sperrliste bearbeiten", - "edit_allowlist": "Freigabeliste bearbeiten", + "edit_allowlist": "Positivliste bearbeiten", "choose_blocklist": "Sperrliste wählen", - "choose_allowlist": "Freigabeliste wählen", + "choose_allowlist": "Positivliste wählen", "enter_valid_blocklist": "Gültige Webadresse zur Sperrliste eingeben.", - "enter_valid_allowlist": "Gültige Webadresse zur Freigabeliste eingeben.", + "enter_valid_allowlist": "Gültige Webadresse zur Positivliste eingeben.", "form_error_url_format": "Ungültiges URL-Format", "form_error_url_or_path_format": "Ungültige URL oder absoluter Pfad der Liste", "custom_filter_rules": "Benutzerdefinierte Filterregeln", diff --git a/client/src/__locales/es.json b/client/src/__locales/es.json index a83527ed..e495c81d 100644 --- a/client/src/__locales/es.json +++ b/client/src/__locales/es.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Servidores DNS de arranque", "bootstrap_dns_desc": "Los servidores DNS de arranque se utilizan para resolver las direcciones IP de los resolutores DoH/DoT que especifiques como DNS de subida.", "local_ptr_title": "Servidores DNS inversos y privados", - "local_ptr_desc": "Los servidores DNS que AdGuard Home utiliza para las consultas PTR locales. Estos servidores se utilizan para resolver los nombres de hosts de los clientes a direcciones IP privadas, por ejemplo \"192.168.12.34\", utilizando DNS inverso. Si no está establecido, AdGuard Home utilizará los resolutores DNS predeterminados de tu sistema operativo, excepto las direcciones del propio AdGuard Home.", + "local_ptr_desc": "Los servidores DNS que AdGuard Home utiliza para las consultas PTR locales. Estos servidores se utilizan para resolver las peticiones PTR de direcciones en rangos de IP privadas, por ejemplo \"192.168.12.34\", utilizando DNS inverso. Si no está establecido, AdGuard Home utilizará los resolutores DNS predeterminados de tu sistema operativo, excepto las direcciones del propio AdGuard Home.", "local_ptr_default_resolver": "Por defecto, AdGuard Home utiliza los siguientes resolutores DNS inversos: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home no pudo determinar los resolutores DNS inversos y privados adecuados para este sistema.", "local_ptr_placeholder": "Ingresa una dirección de servidor por línea", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Cambia los valores de DNS 1 y DNS 2 a las direcciones de tu servidor AdGuard Home.", "install_devices_ios_list_1": "En la pantalla de inicio, pulsa en Configuración.", "install_devices_ios_list_2": "Elige Wi-Fi en el menú de la izquierda (es imposible configurar DNS para redes móviles).", - "install_devices_ios_list_3": "Pulsa sobre el nombre de la red activa en ese momento.", + "install_devices_ios_list_3": "Pulsa sobre el nombre de la red actualmente activa.", "install_devices_ios_list_4": "En el campo DNS ingresa las direcciones de tu servidor AdGuard Home.", "get_started": "Comenzar", "next": "Siguiente", diff --git a/client/src/__locales/fi.json b/client/src/__locales/fi.json index 5e6c8089..3141b12a 100644 --- a/client/src/__locales/fi.json +++ b/client/src/__locales/fi.json @@ -338,7 +338,7 @@ "install_devices_windows_list_2": "Avaa \"Verkko ja Internet\" -ryhmä ja sitten \"Verkko ja jakamiskeskus\".", "install_devices_windows_list_3": "Paina ikkunan vasemmasta laidasta \"Muuta sovittimen asetuksia\".", "install_devices_windows_list_4": "Paina aktiivista yhteyttäsi hiiren kakkospainikkeella ja valitse \"Ominaisuudet\".", - "install_devices_windows_list_5": "Etsi listasta \"Internet protokolla versio 4 (TCP/IP)\", valitse se ja paina jälleen \"Ominaisuudet\".", + "install_devices_windows_list_5": "Etsi listasta \"Internet Protocol Version 4 (TCP/IPv4)\" (tai IPv6:lle \"Internet Protocol Version 6 (TCP/IPv6)\"), valitse se ja paina jälleen \"Ominaisuudet\".", "install_devices_windows_list_6": "Valitse \"Käytä seuraavia DNS-palvelinten osoitteita\" ja syötä AdGuard Home -palvelimesi osoitteet.", "install_devices_macos_list_1": "Paina Omena-kuvaketta ja valitse \"Järjestelmäasetukset\".", "install_devices_macos_list_2": "Paina \"Verkko\".", diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index 7fc19d73..83278ee3 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Bootstrap DNS-servers", "bootstrap_dns_desc": "Bootstrap DNS-servers worden gebruikt om IP-adressen op te lossen van de DoH / DoT-resolvers die u opgeeft als upstreams.", "local_ptr_title": "Private omgekeerde DNS-servers", - "local_ptr_desc": "De DNS-servers die AdGuard Home zal gebruiken voor lokale PTR zoekopdrachten. Deze server wordt gebruikt om de hostnamen van de clients met private IP-adressen, bijvoorbeeld \"192.168.12.34\", dmv. rDNS. Indien niet ingesteld, gebruikt AdGuard Home automatisch je standaard DNS-resolver.", + "local_ptr_desc": "De DNS-servers die AdGuard Home gebruikt voor lokale PTR-zoekopdrachten. Deze servers worden gebruikt om PTR-verzoeken voor adressen in privé-IP-bereiken op te lossen, bijvoorbeeld \"192.168.12.34\", met behulp van reverse DNS. Indien niet ingesteld, gebruikt AdGuard Home de adressen van de standaard DNS-resolvers van uw besturingssysteem, behalve de adressen van AdGuard Home zelf.", "local_ptr_default_resolver": "Standaard gebruikt AdGuard Home de volgende omgekeerde DNS-resolvers: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home kon voor dit systeem geen geschikte private omgekeerde DNS-resolvers bepalen.", "local_ptr_placeholder": "Voer één serveradres per regel in", diff --git a/client/src/__locales/ro.json b/client/src/__locales/ro.json index b19b8576..097dba59 100644 --- a/client/src/__locales/ro.json +++ b/client/src/__locales/ro.json @@ -7,15 +7,15 @@ "load_balancing": "Echilibrare-sarcini", "load_balancing_desc": "Interoghează câte un server în amonte la un moment dat. AdGuard Home utilizează un algoritm de randomizare ponderat pentru a alege serverul, astfel încât cel mai rapid server să fie utilizat mai des.", "bootstrap_dns": "Serverele DNS Bootstrap", - "bootstrap_dns_desc": "Serverele DNS Bootstrap sunt folosite pentru a rezolva adresele IP ale resolverelor DoH/DoT indicate ca upstreams.", + "bootstrap_dns_desc": "Serverele DNS Bootstrap sunt folosite pentru a rezolva adresele IP ale rezolvatorilor DoH/DoT indicați ca upstreams.", "local_ptr_title": "Servere DNS inverse private", - "local_ptr_desc": "Servere DNS pe care AdGuard Home le utilizează pentru interogări PTR locale. Aceste servere sunt folosite pentru a rezolva numele gazdelor de clienți cu adrese IP private, cum ar fi \"192.168.12.34\", folosind DNS inversat. Dacă nu este setat, AdGuard Home utilizează adresele resolverelor DNS implicite ale SO al dvs., cu excepția adreselor AdGuard Home înseși.", - "local_ptr_default_resolver": "În mod implicit, AdGuard Home utilizează următoarele resolvere DNS inverse: {{ip}}.", - "local_ptr_no_default_resolver": "AdGuard Home nu a putut determina resolvere DNS private adecvate pentru acest sistem.", + "local_ptr_desc": "Serverele DNS pe care AdGuard Home le utilizează pentru interogările PTR locale. Aceste servere sunt utilizate pentru a rezolva solicitările PTR pentru adrese din intervale IP private, de exemplu „192.168.12.34”, utilizând DNS invers. Dacă nu este configurat, AdGuard Home utilizează adresele rezolvatorilor DNS impliciți ai sistemului dvs. de operare, cu excepția adreselor AdGuard Home în sine.", + "local_ptr_default_resolver": "În mod implicit, AdGuard Home utilizează următorii rezolvatori DNS inverși: {{ip}}.", + "local_ptr_no_default_resolver": "AdGuard Home nu a putut determina rezolvatorii DNS privați adecvați pentru acest sistem.", "local_ptr_placeholder": "Introduceți o adresă de server per linie", "resolve_clients_title": "Permiteți rezolvarea inversa a adreselor IP ale clienților", - "resolve_clients_desc": "Rezolvă invers adresele IP ale clienților în numele lor de gazde prin trimiterea interogărilor PTR la resolverele corespunzătoare (servere DNS private pentru clienți locali, servere în amonte pentru clienți cu adrese IP publice).", - "use_private_ptr_resolvers_title": "Utilizați resolvere DNS inverse private", + "resolve_clients_desc": "Rezolvă invers adresele IP ale clienților în numele lor de gazde prin trimiterea interogărilor PTR la rezolvatorii corespunzători (servere DNS private pentru clienți locali, servere în amonte pentru clienți cu adrese IP publice).", + "use_private_ptr_resolvers_title": "Utilizați rezolvatori DNS inverși privați", "use_private_ptr_resolvers_desc": "Efectuează examinări DNS inverse pentru adresele deservite local folosind aceste servere în amonte. Dacă este dezactivată, AdGuard Home răspunde cu NXDOMAIN la toate aceste cereri PTR, cu excepția clienților cunoscuți din DHCP, /etc/hosts și așa mai departe.", "check_dhcp_servers": "Căutați servere DHCP", "save_config": "Salvare configurare", @@ -214,7 +214,7 @@ "example_upstream_dot": "<0>DNS-over-TLS criptat;", "example_upstream_doh": "<0>DNS-over-HTTPS criptat;", "example_upstream_doq": "<0>DNS-over-QUIC criptat (experimental);", - "example_upstream_sdns": "<0>DNS Stamps pentru <1>DNSCrypt sau rezolvere <2>DNS-over-HTTPS;", + "example_upstream_sdns": "<0>DNS Stamps pentru <1>DNSCrypt sau rezolvatori <2>DNS-over-HTTPS;", "example_upstream_tcp": "DNS clasic (over TCP);", "example_upstream_tcp_hostname": "DNS obișnuit (over TCP, nume de gazdă);", "all_lists_up_to_date_toast": "Toate listele sunt deja la zi", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Schimbați valorile DNS 1 și DNS 2 la adresele serverului dvs. AdGuard Home.", "install_devices_ios_list_1": "Din ecranul de start, tapați Setări.", "install_devices_ios_list_2": "Alegeți Wi-Fi în meniul din stânga (este imposibil să configurați DNS pentru rețelele mobile).", - "install_devices_ios_list_3": "Tapați numele rețelei active curente.", + "install_devices_ios_list_3": "Apăsați pe numele rețelei active în prezent.", "install_devices_ios_list_4": "În câmpul DNS, introduceți adresele serverului dvs. AdGuard Home.", "get_started": "Să începem", "next": "Următor", @@ -585,7 +585,7 @@ "list_updated": "{{count}} listă actualizată", "list_updated_plural": "{{count}} liste actualizate", "dnssec_enable": "Activați DNSSEC", - "dnssec_enable_desc": "Activați semnalul DNSSEC în interogările DNS de ieșire și verificați rezultatul (este necesar un resolver compatibil DNSSEC).", + "dnssec_enable_desc": "Activați semnalul DNSSEC în interogările DNS de ieșire și verificați rezultatul (este necesar un rezolvator compatibil DNSSEC).", "validated_with_dnssec": "Validat cu DNSSEC", "all_queries": "Toate interogările", "show_blocked_responses": "Blocat", diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index 74dedd8b..f26e0011 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -9,7 +9,7 @@ "bootstrap_dns": "DNS Önyükleme sunucuları", "bootstrap_dns_desc": "DNS Önyükleme sunucuları, belirttiğiniz üst sunucuların DoH/DoT çözümleyicilerine ait IP adreslerinin çözümlemek için kullanılır.", "local_ptr_title": "Özel ters DNS sunucuları", - "local_ptr_desc": "AdGuard Home'un yerel PTR sorguları için kullandığı DNS sunucuları. Bu sunucular, rDNS kullanarak \"192.168.12.34\" gibi özel IP adreslerine sahip istemcilerin ana makine adlarını çözmek için kullanılır. Ayarlanmadığı durumda AdGuard Home, işletim sisteminizin varsayılan DNS çözümleme adreslerini kullanır.", + "local_ptr_desc": "AdGuard Home'un yerel PTR sorguları için kullandığı DNS sunucuları. Bu sunucular, rDNS kullanarak, örneğin \"192.168.12.34\" gibi özel IP aralıklarındaki adresler için PTR isteklerini çözmek için kullanılır. Ayarlanmadığı durumda AdGuard Home, işletim sisteminizin varsayılan DNS çözümleme adreslerini kullanır.", "local_ptr_default_resolver": "AdGuard Home, varsayılan olarak aşağıdaki ters DNS çözümleyicilerini kullanır: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home, bu sistem için uygun olan özel ters DNS çözümleyicilerini belirleyemedi.", "local_ptr_placeholder": "Her satıra bir sunucu adresi girin", @@ -115,7 +115,7 @@ "blocked_by": "<0>Filtreler tarafından engellenen", "stats_malware_phishing": "Engellenen kötü amaçlı yazılım ve kimlik avı", "stats_adult": "Engellenen yetişkin içerikli siteler", - "stats_query_domain": "En fazla sorgulanan alan adları", + "stats_query_domain": "Başlıca sorgulanan alan adları", "for_last_24_hours": "son 24 saat içindekiler", "for_last_days": "son {{count}} gün boyunca", "for_last_days_plural": "son {{count}} gün boyunca", @@ -123,8 +123,8 @@ "stats_disabled_short": "İstatistikler devre dışı bırakıldı", "no_domains_found": "Alan adı bulunamadı", "requests_count": "İstek sayısı", - "top_blocked_domains": "En fazla engellenen alan adları", - "top_clients": "En aktif istemciler", + "top_blocked_domains": "Başlıca engellenen alan adları", + "top_clients": "Başlıca istemciler", "no_clients_found": "İstemci bulunamadı", "general_statistics": "Genel istatistikler", "number_of_dns_query_days": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "DNS 1 ve DNS 2 değerlerini AdGuard Home sunucunuzun adresleriyle değiştirin.", "install_devices_ios_list_1": "Ana ekrandan Ayarlar'a dokunun.", "install_devices_ios_list_2": "Sol menüde bulunan Wi-Fi bölümüne girin (mobil ağlar için özel DNS sunucusu ayarlanamaz).", - "install_devices_ios_list_3": "Bağlı olduğunuz ağın ismine dokunun.", + "install_devices_ios_list_3": "O anda aktif olan ağın adına dokunun.", "install_devices_ios_list_4": "DNS alanına AdGuard Home sunucunuzun adreslerini girin.", "get_started": "Başlayın", "next": "Sonraki", @@ -602,14 +602,14 @@ "milliseconds_abbreviation": "ms", "cache_size": "Önbellek boyutu", "cache_size_desc": "DNS önbellek boyutu (bayt cinsinden).", - "cache_ttl_min_override": "Minimum TTL'i değiştir", - "cache_ttl_max_override": "Maksimum TTL'i değiştir", + "cache_ttl_min_override": "Minimum kullanım süresini geçersiz kıl", + "cache_ttl_max_override": "Maksimum kullanım süresini geçersiz kıl", "enter_cache_size": "Önbellek boyutunu girin (bayt)", - "enter_cache_ttl_min_override": "Minimum TTL değerini girin (saniye olarak)", - "enter_cache_ttl_max_override": "Maksimum TTL değerini girin (saniye olarak)", + "enter_cache_ttl_min_override": "Minimum kullanım süresi girin (saniye olarak)", + "enter_cache_ttl_max_override": "Maksimum kullanım süresi girin (saniye olarak)", "cache_ttl_min_override_desc": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan kullanım süresi değerini uzatın (saniye olarak).", "cache_ttl_max_override_desc": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak).", - "ttl_cache_validation": "Minimum önbellek TTL geçersiz kılma, maksimuma eşit veya bundan küçük olmalıdır", + "ttl_cache_validation": "Minimum önbellek kullanım süresi geçersiz kılma, maksimum değerden küçük veya ona eşit olmalıdır", "cache_optimistic": "İyimser önbelleğe alma", "cache_optimistic_desc": "Girişlerin süresi dolduğunda bile AdGuard Home'un önbellekten yanıt vermesini sağlayın ve bunları yenilemeye çalışın.", "filter_category_general": "Genel", diff --git a/client/src/__locales/uk.json b/client/src/__locales/uk.json index 5d349618..9fcbd460 100644 --- a/client/src/__locales/uk.json +++ b/client/src/__locales/uk.json @@ -65,7 +65,7 @@ "dhcp_ip_addresses": "IP-адреси", "ip": "IP", "dhcp_table_hostname": "Назва вузла", - "dhcp_table_expires": "Термін дії", + "dhcp_table_expires": "Закінчується", "dhcp_warning": "Якщо ви однаково хочете увімкнути DHCP-сервер, переконайтеся, що у вашій мережі немає інших активних DHCP-серверів. Інакше, це може порушити роботу інтернету на під'єднаних пристроях!", "dhcp_error": "AdGuard Home не зміг визначити, чи є в мережі інший DHCP-сервер", "dhcp_static_ip_error": "Для використання DHCP-сервера необхідно встановити статичну IP-адресу. Нам не вдалося визначити, чи цей мережевий інтерфейс налаштовано для використання статичної IP-адреси. Встановіть статичну IP-адресу вручну.", @@ -137,15 +137,15 @@ "number_of_dns_query_to_safe_search": "Кількість DNS-запитів до пошукових систем, для яких примусово застосований безпечний пошук", "average_processing_time": "Середній час обробки", "average_processing_time_hint": "Середній час обробки DNS запиту в мілісекундах", - "block_domain_use_filters_and_hosts": "Блокувати домени з використанням фільтрів та hosts-файлів", + "block_domain_use_filters_and_hosts": "Блокування доменів за допомогою фільтрів та hosts-файлів", "filters_block_toggle_hint": "Ви можете налаштувати правила блокування в розділі Фільтри.", - "use_adguard_browsing_sec": "Використовувати веб-службу безпечного перегляду AdGuard", + "use_adguard_browsing_sec": "Використовувати Безпечну навігацію AdGuard", "use_adguard_browsing_sec_hint": "AdGuard Home перевірятиме, чи додано домен до списку веб-служби безпечного перегляду браузера. Він використовуватиме API для перевірки — на сервер надсилається лише короткий префікс хешу SHA256 доменного імені.", "use_adguard_parental": "Використовувати вебсервіс Батьківського контролю AdGuard", - "use_adguard_parental_hint": "AdGuard Home перевірятиме, чи домен містить матеріали для дорослих. Він використовує той самий орієнтований на приватність API, що й веб-служба безпечного перегляду.", - "enforce_safe_search": "Використовувати безпечний пошук", + "use_adguard_parental_hint": "AdGuard Home перевірить, чи містить домен матеріали для дорослих. Він використовує то же API, що й Безпечна навігація AdGuard.", + "enforce_safe_search": "Використовувати Безпечний пошук", "enforce_save_search_hint": "AdGuard Home може примусово застосовувати безпечний пошук в таких пошукових системах: Google, YouTube, Bing, DuckDuckGo, Yandex, Pixabay.", - "no_servers_specified": "Не вказано сервери", + "no_servers_specified": "Сервери не вказано", "general_settings": "Загальні налаштування", "dns_settings": "Налаштування DNS", "dns_blocklists": "Список блокування DNS", @@ -158,7 +158,7 @@ "upstream_dns": "Upstream DNS-сервери", "upstream_dns_help": "Введіть адреси серверів по одній на рядок. Докладніше про налаштування DNS-серверів.", "upstream_dns_configured_in_file": "Налаштовано в {{path}}", - "test_upstream_btn": "Тест upstream серверів", + "test_upstream_btn": "Перевірити сервери", "upstreams": "Upstreams", "apply_btn": "Застосувати", "disabled_filtering_toast": "Фільтрування вимкнено", @@ -266,7 +266,7 @@ "dns_cache_config": "Конфігурація кешу DNS", "dns_cache_config_desc": "Тут ви можете налаштувати DNS-кеш", "blocking_mode": "Режим блокування", - "default": "Типовий", + "default": "Усталено", "nxdomain": "NXDOMAIN", "refused": "REFUSED", "null_ip": "Нульовий IP", @@ -316,7 +316,7 @@ "install_settings_dns_desc": "Вам потрібно буде налаштувати свої пристрої або маршрутизатор для використання DNS-сервера за такими адресами:", "install_settings_all_interfaces": "Усі інтерфейси", "install_auth_title": "Авторизація", - "install_auth_desc": "Необходно налаштувати автентифікацію паролем для вебінтерфейсу AdGuard Home. Навіть якщо він доступний лише у вашій локальній мережі, важливо захистити його від необмеженого доступу.\n\nДолжна быть настроена аутентификация паролем для веб-интерфейса AdGuard Home. Даже если он доступен только в вашей локальной сети, важно защитить его от неограниченного доступа.", + "install_auth_desc": "Необхідно налаштувати автентифікацію паролем для вебінтерфейсу AdGuard Home. Навіть якщо він доступний лише у вашій локальній мережі, важливо захистити його від необмеженого доступу.", "install_auth_username": "Ім'я користувача", "install_auth_password": "Пароль", "install_auth_confirm": "Підтвердьте пароль", @@ -336,7 +336,7 @@ "install_devices_router_list_4": "Ви не можете встановити власний DNS-сервер на деяких типах маршрутизаторів. У цьому разі вам може допомогти налаштування AdGuard Home в якості <0>DHCP-сервера. В іншому разі вам потрібно знайти інструкцію щодо налаштування DNS-сервера для вашої конкретної моделі маршрутизатора.", "install_devices_windows_list_1": "Відкрийте Панель керування через меню «Пуск» або пошук Windows.", "install_devices_windows_list_2": "Перейдіть до категорії Мережа й Інтернет, а потім до Центру мереж і спільного доступу.", - "install_devices_windows_list_3": "Зліва на екрані натисніть на «Змінити настройки адаптера».", + "install_devices_windows_list_3": "Зліва на екрані натисніть на «Змінити налаштування адаптера».", "install_devices_windows_list_4": "Клацніть на активному з'єднанні правою кнопкою миші та виберіть «Властивості».", "install_devices_windows_list_5": "Знайдіть у списку пункт «Internet Protocol Version 4 (TCP/IPv4)» або «Internet Protocol Version 6 (TCP/IPv6)», виберіть його та натисніть кнопку Властивості ще раз.", "install_devices_windows_list_6": "Виберіть «Використовувати наступні адреси DNS-серверів» та введіть адреси вашого сервера AdGuard Home.", @@ -375,7 +375,7 @@ "encryption_certificates_desc": "Для використання шифрування потрібно надати дійсний ланцюжок сертифікатів SSL для вашого домену. Ви можете отримати безкоштовний сертифікат на <0>{{link}} або придбати його в одному з надійних Центрів Сертифікації.", "encryption_certificates_input": "Скопіюйте/вставте сюди свої кодовані PEM сертифікати.", "encryption_status": "Статус", - "encryption_expire": "Закічнується", + "encryption_expire": "Закінчується", "encryption_key": "Приватний ключ", "encryption_key_input": "Скопіюйте/вставте сюди свій приватний ключ кодований PEM для вашого сертифіката.", "encryption_enable": "Увімкнути шифрування (HTTPS, DNS-over-HTTPS і DNS-over-TLS)", diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 69d5b8b0..4640432f 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -148,8 +148,8 @@ "no_servers_specified": "未找到指定的服务器", "general_settings": "常规设置", "dns_settings": "DNS 设置", - "dns_blocklists": "DNS封锁清单", - "dns_allowlists": "DNS允许清单", + "dns_blocklists": "DNS 拦截列表", + "dns_allowlists": "DNS 允许列表", "dns_blocklists_desc": "AdGuard Home将阻止匹配DNS拦截清单的域名", "dns_allowlists_desc": "来自DNS允许列表的域将被允许,即使它们位于任意阻止列表中也是如此", "custom_filtering_rules": "自定义过滤规则", @@ -335,23 +335,22 @@ "install_devices_router_list_3": "请在此处输入您的 AdGuard Home 服务器地址。", "install_devices_router_list_4": "在某些类型的路由器上无法设置自定义 DNS 服务器。在此情况下将 AdGuard Home 设置为 <0>DHCP 服务器,可能会有所帮助。否则您应该查找如何根据特定路由器型号设置 DNS 服务器的使用手册。", "install_devices_windows_list_1": "通过开始菜单或 Windows 搜索功能打开控制面板。", - "install_devices_windows_list_2": "点击进入 ”网络和 Internet“ 后,再次点击进入 “网络和共享中心”", + "install_devices_windows_list_2": "点击进入「网络和 Internet」后,再次点击进入「网络和共享中心」", "install_devices_windows_list_3": "在窗口的左侧点击「更改适配器设置」。", "install_devices_windows_list_4": "选择您正在连接的网络设备,右击它并选择「属性”」。", - "install_devices_windows_list_5": "在列表中找到 ”Internet 协议版本 4 (TCP/IPv4)“ ,选择并再次点击 ”属性“ 。", + "install_devices_windows_list_5": "在列表中找到「Internet 协议版本 4 (TCP/IPv4)」,选择并再次点击「属性」。", "install_devices_windows_list_6": "选择“使用下面的 DNS 服务器地址”,并输入您的 AdGuard Home 服务器地址。", "install_devices_macos_list_1": "点击苹果图标,进入「系统首选项」。", "install_devices_macos_list_2": "点击「网络」。", - "install_devices_macos_list_3": "选择在列表中的第一个连接,并点击 ”高级“ 。", - "install_devices_macos_list_4": "选择 ”DNS“ 选项卡,并输入您的 AdGuard Home 服务器地址。", + "install_devices_macos_list_3": "选择在列表中的第一个连接,并点击「高级」。", + "install_devices_macos_list_4": "选择「DNS」选项卡,并输入您的 AdGuard Home 服务器地址。", "install_devices_android_list_1": "在安卓主屏幕菜单中点击设置。", - "install_devices_android_list_2": "点击菜单上的 ”无线局域网“ 选项。在屏幕上将列出所有可用的网络(蜂窝移动网络不支持修改 DNS )。", - "install_devices_android_list_3": "长按当前已连接的网络,然后点击 ”修改网络设置“ 。", - "install_devices_android_list_4": "在某些设备上,您可能需要选中 ”高级“ 复选框以查看进一步的设置。您可能需要调整您安卓设备的 DNS 设置,或是需要将 IP 设置从 DHCP 切换到静态。", + "install_devices_android_list_2": "点击菜单上的「无线局域网」选项。在屏幕上将列出所有可用的网络(蜂窝移动网络不支持修改 DNS )。", + "install_devices_android_list_3": "长按当前已连接的网络,然后点击「修改网络设置」。", + "install_devices_android_list_4": "在某些设备上,您可能需要选中「高级」复选框以查看进一步的设置。您可能需要调整您安卓设备的 DNS 设置,或是需要将 IP 设置从 DHCP 切换到静态。", "install_devices_android_list_5": "将 DNS 1 和 DNS 2 的值改为您的 AdGuard Home 服务器地址。", - "install_devices_ios_list_1": "从主屏幕中点击 ”设置“ 。", - "install_devices_ios_list_2": "从左侧目录中选择 ”无线局域网“(移动数据网络环境下不支持修改 DNS )。", - "install_devices_ios_list_3": "点击当前已连接网络的名称。", + "install_devices_ios_list_1": "从主屏幕中点击「设置」。", + "install_devices_ios_list_2": "从左侧目录中选择「无线局域网」(移动数据网络环境下不支持修改 DNS )。", "install_devices_ios_list_4": "在 DNS 字段中输入您的 AdGuard Home 服务器地址。", "get_started": "开始配置", "next": "下一步", diff --git a/client/src/__locales/zh-tw.json b/client/src/__locales/zh-tw.json index 666ddcc3..435d6b01 100644 --- a/client/src/__locales/zh-tw.json +++ b/client/src/__locales/zh-tw.json @@ -9,7 +9,7 @@ "bootstrap_dns": "自我啟動(Bootstrap)DNS 伺服器", "bootstrap_dns_desc": "自我啟動(Bootstrap)DNS 伺服器被用於解析您明確指定作為上游的 DoH/DoT 解析器之 IP 位址。", "local_ptr_title": "私人反向的 DNS 伺服器", - "local_ptr_desc": "AdGuard Home 用於區域指標(PTR)查詢之 DNS 伺服器。這些伺服器被用於解析含私人 IP 位址的用戶端之主機名稱,例如,\"192.168.12.34\",使用反向的 DNS。如果未被設定,除 AdGuard Home 它本身的位址之外,AdGuard Home 使用您的作業系統之預設 DNS 解析器的位址。", + "local_ptr_desc": "AdGuard Home 用於區域指標(PTR)查詢之 DNS 伺服器。這些伺服器被用於解析有關在私人 IP 範圍的位址之區域指標查詢,例如,\"192.168.12.34\",使用反向的 DNS。如果未被設定,AdGuard Home 使用您的作業系統之預設 DNS 解析器的位址。", "local_ptr_default_resolver": "預設下,AdGuard Home 使用以下反向的 DNS 解析器:{{ip}}。", "local_ptr_no_default_resolver": "AdGuard Home 無法為此系統決定合適的私人反向的 DNS 解析器。", "local_ptr_placeholder": "每行輸入一個伺服器位址", From a580149ad67b604a1e3c6e7b3483d856a51c905a Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 27 Apr 2022 14:32:29 +0300 Subject: [PATCH 27/99] Pull request: all: upd dnsproxy, tools Merge in DNS/adguard-home from upd-dnsproxy to master Squashed commit of the following: commit ea2a88dfd6e3820f0b3319d6aa09313de467e423 Author: Ainar Garipov Date: Wed Apr 27 14:24:49 2022 +0300 all: upd dnsproxy, tools --- go.mod | 12 ++++++------ go.sum | 21 ++++++++++++--------- internal/tools/go.mod | 8 ++++---- internal/tools/go.sum | 15 ++++++++------- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index 30d8b377..3b64e7db 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/AdguardTeam/AdGuardHome go 1.17 require ( - github.com/AdguardTeam/dnsproxy v0.42.1 + github.com/AdguardTeam/dnsproxy v0.42.2 github.com/AdguardTeam/golibs v0.10.8 github.com/AdguardTeam/urlfilter v0.16.0 github.com/NYTimes/gziphandler v1.1.1 github.com/ameshkov/dnscrypt/v2 v2.2.3 github.com/digineo/go-ipset/v2 v2.2.1 - github.com/fsnotify/fsnotify v1.5.1 + github.com/fsnotify/fsnotify v1.5.4 github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 github.com/google/go-cmp v0.5.7 github.com/google/gopacket v1.1.19 @@ -28,8 +28,8 @@ require ( github.com/ti-mo/netfilter v0.4.0 go.etcd.io/bbolt v1.3.6 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 - golang.org/x/net v0.0.0-20220412020605-290c469a71a5 - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 howett.net/plist v1.0.0 @@ -57,10 +57,10 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a // indirect + golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12 // indirect golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index e75df993..06ae9b96 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,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.42.1 h1:RZAtW75cvMX1d9Mibg0CA343V7VWV5PLrXsLhBZfdYc= -github.com/AdguardTeam/dnsproxy v0.42.1/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= +github.com/AdguardTeam/dnsproxy v0.42.2 h1:aBhbuvqg/rZN8Rab5ILSfPFJDkiTviWXXcceJgajnNs= +github.com/AdguardTeam/dnsproxy v0.42.2/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= @@ -58,8 +58,9 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -292,8 +293,9 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -329,8 +331,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -390,8 +392,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -416,8 +419,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a h1:ofrrl6c6NG5/IOSx/R1cyiQxxjqlur0h/TvbUhkH0II= -golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12 h1:pODAJF0uBqx6zFa1MYaiTobVo5FzCbnTVUXeO8o71fE= +golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 2ad6ce16..bb587070 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -11,7 +11,7 @@ require ( github.com/securego/gosec/v2 v2.11.0 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a - honnef.co/go/tools v0.3.0 + honnef.co/go/tools v0.3.1 mvdan.cc/gofumpt v0.3.1 mvdan.cc/unparam v0.0.0-20220316160445-06cc5682983b ) @@ -19,16 +19,16 @@ require ( require ( github.com/BurntSushi/toml v1.1.0 // indirect github.com/client9/misspell v0.3.4 // indirect - github.com/google/go-cmp v0.5.7 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.0 // indirect github.com/kyoh86/nolint v0.0.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4 // indirect + golang.org/x/exp/typeparams v0.0.0-20220426173459-3bcf042a4bf5 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 7dbf5491..2f04e4a6 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -157,8 +157,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -420,8 +421,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4 h1:P5yukcpQfG1ZDKR0pGdaZCVwaNPntMxLFKYg81li58M= -golang.org/x/exp/typeparams v0.0.0-20220407100705-7b9b53b0aca4/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20220426173459-3bcf042a4bf5 h1:pKfHvPtBtqS0+V/V9Y0cZQa2h8HJV/qSRJiGgYu+LQA= +golang.org/x/exp/typeparams v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -559,8 +560,8 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -751,8 +752,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.3.0 h1:2LdYUZ7CIxnYgskbUZfY7FPggmqnh6shBqfWa8Tn3XU= -honnef.co/go/tools v0.3.0/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= +honnef.co/go/tools v0.3.1 h1:1kJlrWJLkaGXgcaeosRXViwviqjI7nkBvU2+sZW0AYc= +honnef.co/go/tools v0.3.1/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= mvdan.cc/unparam v0.0.0-20220316160445-06cc5682983b h1:C8Pi6noat8BcrL9WnSRYeQ63fpkJk3hKVHtF5731kIw= From 21905d98693a58a24560ceac5461a470beb70af8 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Fri, 29 Apr 2022 14:39:02 +0300 Subject: [PATCH 28/99] Pull request: home: imp openbsd init script Closes #4533. Squashed commit of the following: commit 48ca9e100619e714eab565273daeb4ee9adb5b74 Author: Ainar Garipov Date: Thu Apr 28 20:25:15 2022 +0300 home: imp openbsd init script --- CHANGELOG.md | 8 ++++++-- internal/home/service.go | 2 +- internal/v1/cmd/signal.go | 10 +++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84f45312..289b1d2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,8 @@ and this project adheres to ### Added -- Support for Discovery of Designated Resolvers (DDR) according to the - [RFC draft][ddr-draft-06] ([#4463]). +- Support for Discovery of Designated Resolvers (DDR) according to the [RFC + draft][ddr-draft-06] ([#4463]). - The ability to control each source of runtime clients separately via `clients.runtime_sources` configuration object ([#3020]). - The ability to customize the set of networks that are considered private @@ -40,6 +40,9 @@ and this project adheres to ### Changed +- On OpenBSD, the daemon script now uses the recommended `/bin/ksh` shell + instead of the `/bin/sh` one ([#4533]). To apply this change, backup your + data and run `AdGuardHome -s uninstall && AdGuardHome -s install`. - The default DNS-over-QUIC port number is now `853` instead of `754` in accordance with the latest [RFC draft][doq-draft-10] ([#4276]). - Reverse DNS now has a greater priority as the source of runtime clients' @@ -144,6 +147,7 @@ In this release, the schema version has changed from 12 to 14. [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 +[#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 [ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 diff --git a/internal/home/service.go b/internal/home/service.go index 081974e2..70ab3c78 100644 --- a/internal/home/service.go +++ b/internal/home/service.go @@ -609,7 +609,7 @@ command_args="-P ${pidfile} -p ${pidfile_child} -T ${name} -r {{.WorkingDirector run_rc_command "$1" ` -const openBSDScript = `#!/bin/sh +const openBSDScript = `#!/bin/ksh # # $OpenBSD: {{ .SvcInfo }} diff --git a/internal/v1/cmd/signal.go b/internal/v1/cmd/signal.go index b9f09673..b66075f6 100644 --- a/internal/v1/cmd/signal.go +++ b/internal/v1/cmd/signal.go @@ -19,10 +19,10 @@ type signalHandler struct { // handle processes OS signals. func (h *signalHandler) handle() { - defer log.OnPanic("signalProcessor.handle") + defer log.OnPanic("signalHandler.handle") for sig := range h.signal { - log.Info("sigproc: received signal %q", sig) + log.Info("sighdlr: received signal %q", sig) if aghos.IsShutdownSignal(sig) { h.shutdown() @@ -43,16 +43,16 @@ func (h *signalHandler) shutdown() { status := statusSuccess - log.Info("sigproc: shutting down services") + log.Info("sighdlr: shutting down services") for i, service := range h.services { err := service.Shutdown(ctx) if err != nil { - log.Error("sigproc: shutting down service at index %d: %s", i, err) + log.Error("sighdlr: shutting down service at index %d: %s", i, err) status = statusError } } - log.Info("sigproc: shutting down adguard home") + log.Info("sighdlr: shutting down adguard home") os.Exit(status) } From 58515fce4304538ba374305c27d71640993f046e Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 4 May 2022 21:01:41 +0300 Subject: [PATCH 29/99] Pull request: 4542 clientid case Merge in DNS/adguard-home from 4542-clientid-case to master Updates #4542. Squashed commit of the following: commit 2a3111ebcef09460b407cd1c870cad2391cd5650 Author: Eugene Burkov Date: Wed May 4 20:44:18 2022 +0300 all: fix changelog link commit 3732def83e2a36eeff2d682149dc4dcef4e92a7d Author: Eugene Burkov Date: Wed May 4 20:43:37 2022 +0300 all: log changes commit 9fe1001cf586669ae238c9c4818070cf94e23ce8 Author: Eugene Burkov Date: Wed May 4 19:37:33 2022 +0300 dnsforward: lowercase clientid --- CHANGELOG.md | 2 ++ internal/dnsforward/clientid.go | 4 ++-- internal/dnsforward/clientid_test.go | 21 +++++++++++++++++++++ internal/home/clients.go | 3 ++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 289b1d2e..3c2fa06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,6 +127,7 @@ In this release, the schema version has changed from 12 to 14. ### Fixed +- Case-sensitive ClientID ([#4542]). - Slow version update queries making other HTTP APIs unresponsible ([#4499]). - ARP tables refreshing process causing excessive PTR requests ([#3157]). @@ -148,6 +149,7 @@ In this release, the schema version has changed from 12 to 14. [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 +[#4542]: https://github.com/AdguardTeam/AdGuardHome/issues/4542 [ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html [doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 diff --git a/internal/dnsforward/clientid.go b/internal/dnsforward/clientid.go index 481fb84d..bb687a41 100644 --- a/internal/dnsforward/clientid.go +++ b/internal/dnsforward/clientid.go @@ -65,7 +65,7 @@ func clientIDFromClientServerName( return "", err } - return clientID, nil + return strings.ToLower(clientID), nil } // clientIDFromDNSContextHTTPS extracts the client's ID from the path of the @@ -104,7 +104,7 @@ func clientIDFromDNSContextHTTPS(pctx *proxy.DNSContext) (clientID string, err e return "", fmt.Errorf("clientid check: %w", err) } - return clientID, nil + return strings.ToLower(clientID), nil } // tlsConn is a narrow interface for *tls.Conn to simplify testing. diff --git a/internal/dnsforward/clientid_test.go b/internal/dnsforward/clientid_test.go index e62dbe58..6e23d639 100644 --- a/internal/dnsforward/clientid_test.go +++ b/internal/dnsforward/clientid_test.go @@ -143,6 +143,22 @@ func TestServer_clientIDFromDNSContext(t *testing.T) { wantErrMsg: `clientid check: client server name "cli.myexample.com" ` + `doesn't match host server name "example.com"`, strictSNI: true, + }, { + name: "tls_case", + proto: proxy.ProtoTLS, + hostSrvName: "example.com", + cliSrvName: "InSeNsItIvE.example.com", + wantClientID: "insensitive", + wantErrMsg: ``, + strictSNI: true, + }, { + name: "quic_case", + proto: proxy.ProtoQUIC, + hostSrvName: "example.com", + cliSrvName: "InSeNsItIvE.example.com", + wantClientID: "insensitive", + wantErrMsg: ``, + strictSNI: true, }} for _, tc := range testCases { @@ -210,6 +226,11 @@ func TestClientIDFromDNSContextHTTPS(t *testing.T) { path: "/dns-query/cli/", wantClientID: "cli", wantErrMsg: "", + }, { + name: "clientid_case", + path: "/dns-query/InSeNsItIvE", + wantClientID: "insensitive", + wantErrMsg: ``, }, { name: "bad_url", path: "/foo", diff --git a/internal/home/clients.go b/internal/home/clients.go index d4d6b959..4ba6b884 100644 --- a/internal/home/clients.go +++ b/internal/home/clients.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "sort" + "strings" "sync" "time" @@ -546,7 +547,7 @@ func (clients *clientsContainer) check(c *Client) (err error) { } else if mac, err = net.ParseMAC(id); err == nil { c.IDs[i] = mac.String() } else if err = dnsforward.ValidateClientID(id); err == nil { - c.IDs[i] = id + c.IDs[i] = strings.ToLower(id) } else { return fmt.Errorf("invalid clientid at index %d: %q", i, id) } From f289f4b1b6f91f38d99ac8b9e3f9bdc9536609e7 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 12 May 2022 17:41:39 +0300 Subject: [PATCH 30/99] Pull request: websvc: add system info Merge in DNS/adguard-home from websvc-system-info to master Squashed commit of the following: commit 333aaa0602da254e25e0262a10080bf44a3718a7 Author: Ainar Garipov Date: Thu May 12 16:32:32 2022 +0300 websvc: fmt commit d8a35bf71dcc59fdd595494e5b220e3d24516728 Author: Ainar Garipov Date: Thu May 12 16:10:11 2022 +0300 websvc: refactor, imp tests commit dfeb24f3f35513bf51323d3ab6f717f582a1defc Author: Ainar Garipov Date: Wed May 11 20:52:02 2022 +0300 websvc: add system info --- go.mod | 1 + go.sum | 2 + internal/v1/cmd/cmd.go | 4 +- internal/v1/websvc/json.go | 61 +++++++++++++++++++++++++++++++ internal/v1/websvc/middleware.go | 16 ++++++++ internal/v1/websvc/path.go | 8 ++++ internal/v1/websvc/system.go | 35 ++++++++++++++++++ internal/v1/websvc/system_test.go | 36 ++++++++++++++++++ internal/v1/websvc/websvc.go | 46 ++++++++++++++++++++++- internal/v1/websvc/websvc_test.go | 52 ++++++++++++++++++++------ openapi/v1.yaml | 16 +++++++- 11 files changed, 260 insertions(+), 17 deletions(-) create mode 100644 internal/v1/websvc/json.go create mode 100644 internal/v1/websvc/middleware.go create mode 100644 internal/v1/websvc/path.go create mode 100644 internal/v1/websvc/system.go create mode 100644 internal/v1/websvc/system_test.go diff --git a/go.mod b/go.mod index 3b64e7db..8da34653 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/NYTimes/gziphandler v1.1.1 github.com/ameshkov/dnscrypt/v2 v2.2.3 github.com/digineo/go-ipset/v2 v2.2.1 + github.com/dimfeld/httptreemux/v5 v5.4.0 github.com/fsnotify/fsnotify v1.5.4 github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 github.com/google/go-cmp v0.5.7 diff --git a/go.sum b/go.sum index 06ae9b96..807a6849 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/digineo/go-ipset/v2 v2.2.1 h1:k6skY+0fMqeUjjeWO/m5OuWPSZUAn7AucHMnQ1MX77g= github.com/digineo/go-ipset/v2 v2.2.1/go.mod h1:wBsNzJlZlABHUITkesrggFnZQtgW5wkqw1uo8Qxe0VU= +github.com/dimfeld/httptreemux/v5 v5.4.0 h1:IiHYEjh+A7pYbhWyjmGnj5HZK6gpOOvyBXCJ+BE8/Gs= +github.com/dimfeld/httptreemux/v5 v5.4.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= diff --git a/internal/v1/cmd/cmd.go b/internal/v1/cmd/cmd.go index 4c4e252f..1f1cc64e 100644 --- a/internal/v1/cmd/cmd.go +++ b/internal/v1/cmd/cmd.go @@ -20,7 +20,8 @@ import ( func Main(clientBuildFS fs.FS) { // # Initial Configuration - rand.Seed(time.Now().UnixNano()) + start := time.Now() + rand.Seed(start.UnixNano()) // TODO(a.garipov): Set up logging. @@ -35,6 +36,7 @@ func Main(clientBuildFS fs.FS) { IP: net.IP{127, 0, 0, 1}, Port: 3001, }}, + Start: start, Timeout: 60 * time.Second, }) diff --git a/internal/v1/websvc/json.go b/internal/v1/websvc/json.go new file mode 100644 index 00000000..beb7f7ec --- /dev/null +++ b/internal/v1/websvc/json.go @@ -0,0 +1,61 @@ +package websvc + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strconv" + "time" + + "github.com/AdguardTeam/golibs/log" +) + +// JSON Utilities + +// jsonTime is a time.Time that can be decoded from JSON and encoded into JSON +// according to our API conventions. +type jsonTime time.Time + +// type check +var _ json.Marshaler = jsonTime{} + +// nsecPerMsec is the number of nanoseconds in a millisecond. +const nsecPerMsec = float64(time.Millisecond / time.Nanosecond) + +// MarshalJSON implements the json.Marshaler interface for jsonTime. err is +// always nil. +func (t jsonTime) MarshalJSON() (b []byte, err error) { + msec := float64(time.Time(t).UnixNano()) / nsecPerMsec + b = strconv.AppendFloat(nil, msec, 'f', 3, 64) + + return b, nil +} + +// type check +var _ json.Unmarshaler = (*jsonTime)(nil) + +// UnmarshalJSON implements the json.Marshaler interface for *jsonTime. +func (t *jsonTime) UnmarshalJSON(b []byte) (err error) { + if t == nil { + return fmt.Errorf("json time is nil") + } + + msec, err := strconv.ParseFloat(string(b), 64) + if err != nil { + return fmt.Errorf("parsing json time: %w", err) + } + + *t = jsonTime(time.Unix(0, int64(msec*nsecPerMsec)).UTC()) + + return nil +} + +// writeJSONResponse encodes v into w and logs any errors it encounters. r is +// used to get additional information from the request. +func writeJSONResponse(w io.Writer, r *http.Request, v interface{}) { + err := json.NewEncoder(w).Encode(v) + if err != nil { + log.Error("websvc: writing resp to %s %s: %s", r.Method, r.URL.Path, err) + } +} diff --git a/internal/v1/websvc/middleware.go b/internal/v1/websvc/middleware.go new file mode 100644 index 00000000..c87c57d5 --- /dev/null +++ b/internal/v1/websvc/middleware.go @@ -0,0 +1,16 @@ +package websvc + +import "net/http" + +// Middlewares + +// jsonMw sets the content type of the response to application/json. +func jsonMw(h http.Handler) (wrapped http.HandlerFunc) { + f := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + h.ServeHTTP(w, r) + } + + return http.HandlerFunc(f) +} diff --git a/internal/v1/websvc/path.go b/internal/v1/websvc/path.go new file mode 100644 index 00000000..cfd67fd9 --- /dev/null +++ b/internal/v1/websvc/path.go @@ -0,0 +1,8 @@ +package websvc + +// Path constants +const ( + PathHealthCheck = "/health-check" + + PathV1SystemInfo = "/api/v1/system/info" +) diff --git a/internal/v1/websvc/system.go b/internal/v1/websvc/system.go new file mode 100644 index 00000000..47d0c63c --- /dev/null +++ b/internal/v1/websvc/system.go @@ -0,0 +1,35 @@ +package websvc + +import ( + "net/http" + "runtime" + + "github.com/AdguardTeam/AdGuardHome/internal/version" +) + +// System Handlers + +// RespGetV1SystemInfo describes the response of the GET /api/v1/system/info +// HTTP API. +type RespGetV1SystemInfo struct { + Arch string `json:"arch"` + Channel string `json:"channel"` + OS string `json:"os"` + NewVersion string `json:"new_version,omitempty"` + Start jsonTime `json:"start"` + Version string `json:"version"` +} + +// handleGetV1SystemInfo is the handler for the GET /api/v1/system/info HTTP +// API. +func (svc *Service) handleGetV1SystemInfo(w http.ResponseWriter, r *http.Request) { + writeJSONResponse(w, r, &RespGetV1SystemInfo{ + Arch: runtime.GOARCH, + Channel: version.Channel(), + OS: runtime.GOOS, + // TODO(a.garipov): Fill this when we have an updater. + NewVersion: "", + Start: jsonTime(svc.start), + Version: version.Version(), + }) +} diff --git a/internal/v1/websvc/system_test.go b/internal/v1/websvc/system_test.go new file mode 100644 index 00000000..49579ca5 --- /dev/null +++ b/internal/v1/websvc/system_test.go @@ -0,0 +1,36 @@ +package websvc_test + +import ( + "encoding/json" + "net/http" + "net/url" + "runtime" + "testing" + "time" + + "github.com/AdguardTeam/AdGuardHome/internal/v1/websvc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestService_handleGetV1SystemInfo(t *testing.T) { + _, addr := newTestServer(t) + u := &url.URL{ + Scheme: "http", + Host: addr, + Path: websvc.PathV1SystemInfo, + } + + body := httpGet(t, u, http.StatusOK) + resp := &websvc.RespGetV1SystemInfo{} + err := json.Unmarshal(body, resp) + require.NoError(t, err) + + // TODO(a.garipov): Consider making version.Channel and version.Version + // testable and test these better. + assert.NotEmpty(t, resp.Channel) + + assert.Equal(t, resp.Arch, runtime.GOARCH) + assert.Equal(t, resp.OS, runtime.GOOS) + assert.Equal(t, testStart, time.Time(resp.Start)) +} diff --git a/internal/v1/websvc/websvc.go b/internal/v1/websvc/websvc.go index e741ff3d..9af22a15 100644 --- a/internal/v1/websvc/websvc.go +++ b/internal/v1/websvc/websvc.go @@ -17,6 +17,7 @@ import ( "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/netutil" + httptreemux "github.com/dimfeld/httptreemux/v5" ) // Config is the AdGuard Home web service configuration structure. @@ -32,6 +33,9 @@ type Config struct { // SecureAddresses is not empty, TLS must not be nil. SecureAddresses []*netutil.IPPort + // Start is the time of start of AdGuard Home. + Start time.Time + // Timeout is the timeout for all server operations. Timeout time.Duration } @@ -41,6 +45,7 @@ type Config struct { type Service struct { tls *tls.Config servers []*http.Server + start time.Time timeout time.Duration } @@ -53,11 +58,11 @@ func New(c *Config) (svc *Service) { svc = &Service{ tls: c.TLS, + start: c.Start, timeout: c.Timeout, } - mux := http.NewServeMux() - mux.HandleFunc("/health-check", svc.handleGetHealthCheck) + mux := newMux(svc) for _, a := range c.Addresses { addr := a.String() @@ -91,6 +96,43 @@ func New(c *Config) (svc *Service) { return svc } +// newMux returns a new HTTP request multiplexor for the AdGuard Home web +// service. +func newMux(svc *Service) (mux *httptreemux.ContextMux) { + mux = httptreemux.NewContextMux() + + routes := []struct { + handler http.HandlerFunc + method string + path string + isJSON bool + }{{ + handler: svc.handleGetHealthCheck, + method: http.MethodGet, + path: PathHealthCheck, + isJSON: false, + }, { + handler: svc.handleGetV1SystemInfo, + method: http.MethodGet, + path: PathV1SystemInfo, + isJSON: true, + }} + + for _, r := range routes { + var h http.HandlerFunc + if r.isJSON { + // TODO(a.garipov): Consider using httptreemux's MiddlewareFunc. + h = jsonMw(r.handler) + } else { + h = r.handler + } + + mux.Handle(r.method, r.path, h) + } + + return mux +} + // Addrs returns all addresses on which this server serves the HTTP API. Addrs // must not be called until Start returns. func (svc *Service) Addrs() (addrs []string) { diff --git a/internal/v1/websvc/websvc_test.go b/internal/v1/websvc/websvc_test.go index 01b892cd..459ffd14 100644 --- a/internal/v1/websvc/websvc_test.go +++ b/internal/v1/websvc/websvc_test.go @@ -18,7 +18,17 @@ import ( const testTimeout = 1 * time.Second -func TestService_Start_getHealthCheck(t *testing.T) { +// testStart is the server start value for tests. +var testStart = time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) + +// newTestServer creates and starts a new web service instance as well as its +// sole address. It also registers a cleanup procedure, which shuts the +// instance down. +// +// TODO(a.garipov): Use svc or remove it. +func newTestServer(t testing.TB) (svc *websvc.Service, addr string) { + t.Helper() + c := &websvc.Config{ TLS: nil, Addresses: []*netutil.IPPort{{ @@ -27,9 +37,10 @@ func TestService_Start_getHealthCheck(t *testing.T) { }}, SecureAddresses: nil, Timeout: testTimeout, + Start: testStart, } - svc := websvc.New(c) + svc = websvc.New(c) err := svc.Start() require.NoError(t, err) @@ -44,26 +55,43 @@ func TestService_Start_getHealthCheck(t *testing.T) { addrs := svc.Addrs() require.Len(t, addrs, 1) - u := &url.URL{ - Scheme: "http", - Host: addrs[0], - Path: "/health-check", - } + return svc, addrs[0] +} + +// httpGet is a helper that performs an HTTP GET request and returns the body of +// the response as well as checks that the status code is correct. +// +// TODO(a.garipov): Add helpers for other methods. +func httpGet(t testing.TB, u *url.URL, wantCode int) (body []byte) { + t.Helper() + req, err := http.NewRequest(http.MethodGet, u.String(), nil) - require.NoError(t, err) + require.NoErrorf(t, err, "creating req") httpCli := &http.Client{ Timeout: testTimeout, } resp, err := httpCli.Do(req) - require.NoError(t, err) + require.NoErrorf(t, err, "performing req") + require.Equal(t, wantCode, resp.StatusCode) testutil.CleanupAndRequireSuccess(t, resp.Body.Close) - assert.Equal(t, http.StatusOK, resp.StatusCode) + body, err = io.ReadAll(resp.Body) + require.NoErrorf(t, err, "reading body") - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) + return body +} + +func TestService_Start_getHealthCheck(t *testing.T) { + _, addr := newTestServer(t) + u := &url.URL{ + Scheme: "http", + Host: addr, + Path: websvc.PathHealthCheck, + } + + body := httpGet(t, u, http.StatusOK) assert.Equal(t, []byte("OK"), body) } diff --git a/openapi/v1.yaml b/openapi/v1.yaml index 30c318bc..a9092c98 100644 --- a/openapi/v1.yaml +++ b/openapi/v1.yaml @@ -3393,11 +3393,17 @@ 'description': > Information about the AdGuard Home server. 'example': + 'arch': 'amd64' 'channel': 'release' - 'new_version': 'v0.106.1' + 'new_version': 'v0.108.1' + 'os': 'linux' 'start': 1614345496000 - 'version': 'v0.106.0' + 'version': 'v0.108.0' 'properties': + 'arch': + 'description': > + CPU architecture. + 'type': 'string' 'channel': '$ref': '#/components/schemas/Channel' 'new_version': @@ -3405,6 +3411,10 @@ New available version of AdGuard Home to which the server can be updated, if any. If there are none, this field is absent. 'type': 'string' + 'os': + 'description': > + Operating system type. + 'type': 'string' 'start': 'description': > Unix time at which AdGuard Home started working, in milliseconds. @@ -3415,7 +3425,9 @@ Current AdGuard Home version. 'type': 'string' 'required': + - 'arch' - 'channel' + - 'os' - 'start' - 'version' 'type': 'object' From 79d85a24e970450767997d2e3a1b1876f652f0f7 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Wed, 18 May 2022 15:00:36 +0300 Subject: [PATCH 31/99] Pull request: all: log changes Updates #4273. Squashed commit of the following: commit ebae1a4d0944fa348b7dcb7e73e59d083c7a5e97 Author: Eugene Burkov Date: Wed May 18 14:48:16 2022 +0300 all: log changes --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2fa06c..d183c45d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,6 +127,7 @@ In this release, the schema version has changed from 12 to 14. ### Fixed +- Detection of the stopped service status on macOS and Linux ([#4273]). - Case-sensitive ClientID ([#4542]). - Slow version update queries making other HTTP APIs unresponsible ([#4499]). - ARP tables refreshing process causing excessive PTR requests ([#3157]). @@ -146,6 +147,7 @@ In this release, the schema version has changed from 12 to 14. [#4213]: https://github.com/AdguardTeam/AdGuardHome/issues/4213 [#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221 [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 +[#4273]: https://github.com/AdguardTeam/AdGuardHome/issues/4273 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 From 24d7dc8e8a36654bc8d2d64c2014419bd7a9eb25 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Mon, 23 May 2022 16:04:14 +0300 Subject: [PATCH 32/99] Pull request: all: upd dnsproxy Merge in DNS/adguard-home from 4503-upstream-conf to master Squashed commit of the following: commit c6cb1babd4cbf9aacafe902e3d54ce17e8d2cc81 Merge: 75d85ed1 79d85a24 Author: Dimitry Kolyshev Date: Mon May 23 13:06:00 2022 +0200 Merge remote-tracking branch 'origin/master' into 4503-upstream-conf commit 75d85ed1f4d8d5060800b2f8a4cde662db02ae30 Author: Dimitry Kolyshev Date: Fri May 20 13:14:16 2022 +0200 all: upd dnsproxy commit 781768d639388a60fc90631f819cfc5dd90b9eba Author: Dimitry Kolyshev Date: Mon May 16 16:27:25 2022 +0200 all: docs commit 0dafb5b3fe11b1952d9a04294bcaaa8091b9c2a7 Author: Dimitry Kolyshev Date: Mon May 16 16:17:35 2022 +0200 all: docs commit 0d5463e4157132b0e6be78fd97eaf5a5cb8d1edc Merge: e2c86909 f289f4b1 Author: Dimitry Kolyshev Date: Mon May 16 16:01:40 2022 +0200 Merge remote-tracking branch 'origin/master' into 4503-upstream-conf # Conflicts: # go.mod # go.sum commit e2c869091b1386065076f44dbf9498a31c9d5451 Author: Dimitry Kolyshev Date: Mon May 16 15:29:17 2022 +0200 all: upd dnsrpoxy --- CHANGELOG.md | 2 ++ go.mod | 2 +- go.sum | 4 ++-- internal/dnsforward/http.go | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d183c45d..8aca8f15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to ### Added +- Support upstreams for subdomains of a domain only ([#4503]). - Support for Discovery of Designated Resolvers (DDR) according to the [RFC draft][ddr-draft-06] ([#4463]). - The ability to control each source of runtime clients separately via @@ -150,6 +151,7 @@ In this release, the schema version has changed from 12 to 14. [#4273]: https://github.com/AdguardTeam/AdGuardHome/issues/4273 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 +[#4503]: https://github.com/AdguardTeam/AdGuardHome/issues/4503 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 [#4542]: https://github.com/AdguardTeam/AdGuardHome/issues/4542 diff --git a/go.mod b/go.mod index 8da34653..4d9d2191 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.17 require ( - github.com/AdguardTeam/dnsproxy v0.42.2 + github.com/AdguardTeam/dnsproxy v0.42.4 github.com/AdguardTeam/golibs v0.10.8 github.com/AdguardTeam/urlfilter v0.16.0 github.com/NYTimes/gziphandler v1.1.1 diff --git a/go.sum b/go.sum index 807a6849..73accb25 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,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.42.2 h1:aBhbuvqg/rZN8Rab5ILSfPFJDkiTviWXXcceJgajnNs= -github.com/AdguardTeam/dnsproxy v0.42.2/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= +github.com/AdguardTeam/dnsproxy v0.42.4 h1:Rf45a3H6U/8XqWMYAMEsC1g/dVudyfgx4WY8N2syJMw= +github.com/AdguardTeam/dnsproxy v0.42.4/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go index 2b7cfd13..50ab9643 100644 --- a/internal/dnsforward/http.go +++ b/internal/dnsforward/http.go @@ -510,6 +510,7 @@ func separateUpstream(upstreamStr string) (upstream string, isDomainSpec bool, e continue } + host = strings.TrimPrefix(host, "*.") err = netutil.ValidateDomainName(host) if err != nil { return "", true, fmt.Errorf("domain at index %d: %w", i, err) From c0ac82be6a91cd4f5e43e7de6281d2854bbf63c2 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Tue, 24 May 2022 14:43:54 +0300 Subject: [PATCH 33/99] Pull request: 4480 fix sysv service script Merge in DNS/adguard-home from 4480-sysv-boot to master Updates #4480. Squashed commit of the following: commit c9645b1f3bd22a249c666e4485818bab6769f32d Author: Eugene Burkov Date: Tue May 24 14:25:09 2022 +0300 home: imp sysv script commit cc323364ba6cce0284cbc6be9133a50a51b71f56 Author: Eugene Burkov Date: Mon May 23 21:13:06 2022 +0300 home: fix sysv service script --- CHANGELOG.md | 2 ++ internal/home/service.go | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aca8f15..9d837c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,6 +128,7 @@ In this release, the schema version has changed from 12 to 14. ### Fixed +- Service startup on boot on systems using SysV-init ([#4480]). - Detection of the stopped service status on macOS and Linux ([#4273]). - Case-sensitive ClientID ([#4542]). - Slow version update queries making other HTTP APIs unresponsible ([#4499]). @@ -150,6 +151,7 @@ In this release, the schema version has changed from 12 to 14. [#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238 [#4273]: https://github.com/AdguardTeam/AdGuardHome/issues/4273 [#4276]: https://github.com/AdguardTeam/AdGuardHome/issues/4276 +[#4480]: https://github.com/AdguardTeam/AdGuardHome/issues/4480 [#4499]: https://github.com/AdguardTeam/AdGuardHome/issues/4499 [#4503]: https://github.com/AdguardTeam/AdGuardHome/issues/4503 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 diff --git a/internal/home/service.go b/internal/home/service.go index 70ab3c78..831a80d0 100644 --- a/internal/home/service.go +++ b/internal/home/service.go @@ -433,8 +433,11 @@ EnvironmentFile=-/etc/sysconfig/{{.Name}} WantedBy=multi-user.target ` -// Note: we should keep it in sync with the template from service_sysv_linux.go file -// Use "ps | grep -v grep | grep $(get_pid)" because "ps PID" may not work on OpenWrt +// sysvScript is the source of the daemon script for SysV-based Linux systems. +// Keep as close as possible to the https://github.com/kardianos/service/blob/29f8c79c511bc18422bb99992779f96e6bc33921/service_sysv_linux.go#L187. +// +// Use ps command instead of reading the procfs since it's a more +// implementation-independent approach. const sysvScript = `#!/bin/sh # For RedHat and cousins: # chkconfig: - 99 01 @@ -465,7 +468,7 @@ get_pid() { } is_running() { - [ -f "$pid_file" ] && ps | grep -v grep | grep $(get_pid) > /dev/null 2>&1 + [ -f "$pid_file" ] && ps -p "$(get_pid)" > /dev/null 2>&1 } case "$1" in From a82ec09afdfbc66a8f07614b77e825f527a3b35b Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Tue, 24 May 2022 19:47:09 +0300 Subject: [PATCH 34/99] Pull request: all: upd dnsproxy, supp rfc 9250 Updates #4592. Squashed commit of the following: commit 1a80875d6aa7811d7d1d978f6fa8d558dec1ca87 Author: Ainar Garipov Date: Tue May 24 19:28:27 2022 +0300 all: upd dnsproxy, supp rfc 9250 --- CHANGELOG.md | 10 ++++++---- go.mod | 4 ++-- go.sum | 14 ++++---------- internal/dnsforward/clientid.go | 12 ++++++------ internal/dnsforward/clientid_test.go | 25 +++++++++++++------------ 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d837c95..e0c32ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to ### Added +- Support for the final DNS-over-QUIC standard, [RFC 9250][rfc-9250] ([#4592]). - Support upstreams for subdomains of a domain only ([#4503]). - Support for Discovery of Designated Resolvers (DDR) according to the [RFC draft][ddr-draft-06] ([#4463]). @@ -45,7 +46,7 @@ and this project adheres to instead of the `/bin/sh` one ([#4533]). To apply this change, backup your data and run `AdGuardHome -s uninstall && AdGuardHome -s install`. - The default DNS-over-QUIC port number is now `853` instead of `754` in - accordance with the latest [RFC draft][doq-draft-10] ([#4276]). + accordance with [RFC 9250][rfc-9250] ([#4276]). - Reverse DNS now has a greater priority as the source of runtime clients' information than ARP neighborhood. - Improved detection of runtime clients through more resilient ARP processing @@ -100,7 +101,7 @@ In this release, the schema version has changed from 12 to 14. `dns.resolve_clients` property. To rollback this change, remove the `runtime_sources` property, move the contents of `persistent` into the `clients` itself, the value of `clients.runtime_sources.rdns` into the - `dns.resolve_clietns`, and change the `schema_version` back to `13`. + `dns.resolve_clients`, and change the `schema_version` back to `13`. - Property `local_domain_name`, which in schema versions 12 and earlier used to be a part of the `dns` object, is now a part of the `dhcp` object: @@ -131,7 +132,7 @@ In this release, the schema version has changed from 12 to 14. - Service startup on boot on systems using SysV-init ([#4480]). - Detection of the stopped service status on macOS and Linux ([#4273]). - Case-sensitive ClientID ([#4542]). -- Slow version update queries making other HTTP APIs unresponsible ([#4499]). +- Slow version update queries making other HTTP APIs unresponsive ([#4499]). - ARP tables refreshing process causing excessive PTR requests ([#3157]). [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 @@ -156,9 +157,10 @@ In this release, the schema version has changed from 12 to 14. [#4503]: https://github.com/AdguardTeam/AdGuardHome/issues/4503 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 [#4542]: https://github.com/AdguardTeam/AdGuardHome/issues/4542 +[#4592]: https://github.com/AdguardTeam/AdGuardHome/issues/4592 +[rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250 [ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html -[doq-draft-10]: https://datatracker.ietf.org/doc/html/draft-ietf-dprive-dnsoquic-10#section-10.2 [repr]: https://reproducible-builds.org/docs/source-date-epoch/ diff --git a/go.mod b/go.mod index 4d9d2191..d3c3e1de 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.17 require ( - github.com/AdguardTeam/dnsproxy v0.42.4 + github.com/AdguardTeam/dnsproxy v0.43.0 github.com/AdguardTeam/golibs v0.10.8 github.com/AdguardTeam/urlfilter v0.16.0 github.com/NYTimes/gziphandler v1.1.1 @@ -17,7 +17,7 @@ require ( github.com/google/renameio v1.0.1 github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 github.com/kardianos/service v1.2.1 - github.com/lucas-clemente/quic-go v0.26.0 + github.com/lucas-clemente/quic-go v0.27.1 github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 github.com/mdlayher/netlink v1.6.0 // TODO(a.garipov): This package is deprecated; find a new one or use diff --git a/go.sum b/go.sum index 73accb25..ae65fdab 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,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.42.4 h1:Rf45a3H6U/8XqWMYAMEsC1g/dVudyfgx4WY8N2syJMw= -github.com/AdguardTeam/dnsproxy v0.42.4/go.mod h1:thHuk3599mgmucsv5J9HR9lBVQHnf4YleE08EbxNrN0= +github.com/AdguardTeam/dnsproxy v0.43.0 h1:K082nx37DaNqSyT3kDtAfgBACNWc+ZDI1Yr/kGppu1k= +github.com/AdguardTeam/dnsproxy v0.43.0/go.mod h1:JUGTm5dmlll47JltztsT0N//pVJjdg6zu0SNeUeaA7g= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= @@ -143,21 +143,15 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= -github.com/lucas-clemente/quic-go v0.26.0 h1:ALBQXr9UJ8A1LyzvceX4jd9QFsHvlI0RR6BkV16o00A= -github.com/lucas-clemente/quic-go v0.26.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= +github.com/lucas-clemente/quic-go v0.27.1 h1:sOw+4kFSVrdWOYmUjufQ9GBVPqZ+tu+jMtXxXNmRJyk= +github.com/lucas-clemente/quic-go v0.27.1/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc= github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= -github.com/marten-seemann/qtls-go1-18 v0.1.0/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y= github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= diff --git a/internal/dnsforward/clientid.go b/internal/dnsforward/clientid.go index bb687a41..16bac881 100644 --- a/internal/dnsforward/clientid.go +++ b/internal/dnsforward/clientid.go @@ -112,8 +112,8 @@ type tlsConn interface { ConnectionState() (cs tls.ConnectionState) } -// quicSession is a narrow interface for quic.Session to simplify testing. -type quicSession interface { +// quicConnection is a narrow interface for quic.Connection to simplify testing. +type quicConnection interface { ConnectionState() (cs quic.ConnectionState) } @@ -148,16 +148,16 @@ func (s *Server) clientIDFromDNSContext(pctx *proxy.DNSContext) (clientID string cliSrvName = tc.ConnectionState().ServerName case proxy.ProtoQUIC: - qs, ok := pctx.QUICSession.(quicSession) + conn, ok := pctx.QUICConnection.(quicConnection) if !ok { return "", fmt.Errorf( - "proxy ctx quic session of proto %s is %T, want quic.Session", + "proxy ctx quic conn of proto %s is %T, want quic.Connection", proto, - pctx.QUICSession, + pctx.QUICConnection, ) } - cliSrvName = qs.ConnectionState().TLS.ServerName + cliSrvName = conn.ConnectionState().TLS.ServerName } clientID, err = clientIDFromClientServerName( diff --git a/internal/dnsforward/clientid_test.go b/internal/dnsforward/clientid_test.go index 6e23d639..31c55fcd 100644 --- a/internal/dnsforward/clientid_test.go +++ b/internal/dnsforward/clientid_test.go @@ -29,17 +29,18 @@ func (c testTLSConn) ConnectionState() (cs tls.ConnectionState) { return cs } -// testQUICSession is a quicSession for tests. -type testQUICSession struct { - // Session is embedded here simply to make testQUICSession a quic.Session - // without actually implementing all methods. - quic.Session +// testQUICConnection is a quicConnection for tests. +type testQUICConnection struct { + // Connection is embedded here simply to make testQUICConnection a + // quic.Connection without actually implementing all methods. + quic.Connection serverName string } -// ConnectionState implements the quicSession interface for testQUICSession. -func (c testQUICSession) ConnectionState() (cs quic.ConnectionState) { +// ConnectionState implements the quicConnection interface for +// testQUICConnection. +func (c testQUICConnection) ConnectionState() (cs quic.ConnectionState) { cs.TLS.ServerName = c.serverName return cs @@ -179,17 +180,17 @@ func TestServer_clientIDFromDNSContext(t *testing.T) { } } - var qs quic.Session + var qconn quic.Connection if tc.proto == proxy.ProtoQUIC { - qs = testQUICSession{ + qconn = testQUICConnection{ serverName: tc.cliSrvName, } } pctx := &proxy.DNSContext{ - Proto: tc.proto, - Conn: conn, - QUICSession: qs, + Proto: tc.proto, + Conn: conn, + QUICConnection: qconn, } clientID, err := srv.clientIDFromDNSContext(pctx) From 75f01d51f7312601cd323bdbdd4648dfd673ea75 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Wed, 25 May 2022 14:31:32 +0300 Subject: [PATCH 35/99] Pull request: all: filters json Merge in DNS/adguard-home from 4581-filters-json to master Squashed commit of the following: commit da0b86983432ac1791645da328df5848daac5ea6 Merge: 62fa4fc6 a82ec09a Author: Dimitry Kolyshev Date: Wed May 25 12:58:25 2022 +0200 Merge remote-tracking branch 'origin/master' into 4581-filters-json commit 62fa4fc6ff150ebb8dbd8888a58819fb644d43ad Author: Dimitry Kolyshev Date: Wed May 25 11:55:52 2022 +0200 all: filters json commit 96486ffbb41947b5e748f6e35eb96ee73867eba1 Merge: 9956f0af c0ac82be Author: Dimitry Kolyshev Date: Tue May 24 15:57:52 2022 +0200 Merge branch 'master' into 4581-filters-json commit 9956f0aff1b7029f336d22013a62f2871a964322 Author: Dimitry Kolyshev Date: Tue May 24 15:53:43 2022 +0200 all: filters json --- client/src/helpers/filters/filters.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/helpers/filters/filters.json b/client/src/helpers/filters/filters.json index 565cd74d..63fe0995 100644 --- a/client/src/helpers/filters/filters.json +++ b/client/src/helpers/filters/filters.json @@ -81,8 +81,8 @@ "urlhaus-filter-online": { "name": "Online Malicious URL Blocklist", "categoryId": "security", - "homepage": "https://gitlab.com/curben/urlhaus-filter", - "source": "https://curben.gitlab.io/malware-filter/urlhaus-filter-agh-online.txt" + "homepage": "https://gitlab.com/malware-filter/urlhaus-filter", + "source": "https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-agh-online.txt" }, "dandelion-sprouts-anti-malware-list": { "name": "Dandelion Sprout's Anti-Malware List", From 549b20bdea3c3215bb355ffc39546f7bb3260d80 Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Wed, 25 May 2022 18:00:50 +0300 Subject: [PATCH 36/99] Pull request: querylog: fix oldest calc Updates #4591. Squashed commit of the following: commit 70b70c78c85311363535536c7ea12336b21accf8 Author: Ainar Garipov Date: Wed May 25 17:35:54 2022 +0300 querylog: fix oldest calc --- CHANGELOG.md | 2 ++ internal/dnsforward/stats.go | 2 +- internal/home/dns.go | 2 +- internal/querylog/http.go | 2 +- internal/querylog/qlog.go | 2 +- internal/querylog/qlog_test.go | 2 +- internal/querylog/querylog.go | 18 +++++++++--------- internal/querylog/search.go | 17 ++++++++++++----- 8 files changed, 28 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0c32ce7..4a72447c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,6 +129,7 @@ In this release, the schema version has changed from 12 to 14. ### Fixed +- Query log occasionally going into an infinite loop ([#4591]). - Service startup on boot on systems using SysV-init ([#4480]). - Detection of the stopped service status on macOS and Linux ([#4273]). - Case-sensitive ClientID ([#4542]). @@ -157,6 +158,7 @@ In this release, the schema version has changed from 12 to 14. [#4503]: https://github.com/AdguardTeam/AdGuardHome/issues/4503 [#4533]: https://github.com/AdguardTeam/AdGuardHome/issues/4533 [#4542]: https://github.com/AdguardTeam/AdGuardHome/issues/4542 +[#4591]: https://github.com/AdguardTeam/AdGuardHome/issues/4591 [#4592]: https://github.com/AdguardTeam/AdGuardHome/issues/4592 [rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250 diff --git a/internal/dnsforward/stats.go b/internal/dnsforward/stats.go index 56cc19c5..9a7b1ddb 100644 --- a/internal/dnsforward/stats.go +++ b/internal/dnsforward/stats.go @@ -64,9 +64,9 @@ func (s *Server) logQuery( Answer: pctx.Res, OrigAnswer: dctx.origResp, Result: dctx.result, - Elapsed: elapsed, ClientID: dctx.clientID, ClientIP: ip, + Elapsed: elapsed, AuthenticatedData: dctx.responseAD, } diff --git a/internal/home/dns.go b/internal/home/dns.go index 1c04c6c3..9eabfefa 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -58,6 +58,7 @@ func initDNSServer() (err error) { } conf := querylog.Config{ + Anonymizer: anonymizer, ConfigModified: onConfigModified, HTTPRegister: httpRegister, FindClient: Context.clients.findMultiple, @@ -67,7 +68,6 @@ func initDNSServer() (err error) { Enabled: config.DNS.QueryLogEnabled, FileEnabled: config.DNS.QueryLogFileEnabled, AnonymizeClientIP: config.DNS.AnonymizeClientIP, - Anonymizer: anonymizer, } Context.queryLog = querylog.New(conf) diff --git a/internal/querylog/http.go b/internal/querylog/http.go index 6a2bdcee..11f62d0d 100644 --- a/internal/querylog/http.go +++ b/internal/querylog/http.go @@ -19,10 +19,10 @@ import ( ) type qlogConfig struct { - Enabled bool `json:"enabled"` // Use float64 here to support fractional numbers and not mess the API // users by changing the units. Interval float64 `json:"interval"` + Enabled bool `json:"enabled"` AnonymizeClientIP bool `json:"anonymize_client_ip"` } diff --git a/internal/querylog/qlog.go b/internal/querylog/qlog.go index 8856fd9c..24eec40e 100644 --- a/internal/querylog/qlog.go +++ b/internal/querylog/qlog.go @@ -149,7 +149,7 @@ func (l *queryLog) clear() { log.Error("removing log file %q: %s", l.logFile, err) } - log.Debug("Query log: cleared") + log.Debug("querylog: cleared") } func (l *queryLog) Add(params *AddParams) { diff --git a/internal/querylog/qlog_test.go b/internal/querylog/qlog_test.go index fbfc459d..6beed1be 100644 --- a/internal/querylog/qlog_test.go +++ b/internal/querylog/qlog_test.go @@ -285,8 +285,8 @@ func addEntry(l *queryLog, host string, answerStr, client net.IP) { Answer: &a, OrigAnswer: &a, Result: &res, - ClientIP: client, Upstream: "upstream", + ClientIP: client, } l.Add(params) diff --git a/internal/querylog/querylog.go b/internal/querylog/querylog.go index bd6e1569..a854c2c4 100644 --- a/internal/querylog/querylog.go +++ b/internal/querylog/querylog.go @@ -28,8 +28,11 @@ type QueryLog interface { WriteDiskConfig(c *Config) } -// Config - configuration object +// Config is the query log configuration structure. type Config struct { + // Anonymizer processes the IP addresses to anonymize those if needed. + Anonymizer *aghnet.IPMut + // ConfigModified is called when the configuration is changed, for // example by HTTP requests. ConfigModified func() @@ -68,9 +71,6 @@ type Config struct { // AnonymizeClientIP tells if the query log should anonymize clients' IP // addresses. AnonymizeClientIP bool - - // Anonymizer processes the IP addresses to anonymize those if needed. - Anonymizer *aghnet.IPMut } // AddParams is the parameters for adding an entry. @@ -91,18 +91,18 @@ type AddParams struct { // Result is the filtering result (optional). Result *filtering.Result - // Elapsed is the time spent for processing the request. - Elapsed time.Duration - ClientID string - ClientIP net.IP - // Upstream is the URL of the upstream DNS server. Upstream string ClientProto ClientProto + ClientIP net.IP + + // Elapsed is the time spent for processing the request. + Elapsed time.Duration + // Cached indicates if the response is served from cache. Cached bool diff --git a/internal/querylog/search.go b/internal/querylog/search.go index 4a3de979..8fb32e60 100644 --- a/internal/querylog/search.go +++ b/internal/querylog/search.go @@ -73,7 +73,7 @@ func (l *queryLog) searchMemory(params *searchParams, cache clientCache) (entrie // search - searches log entries in the query log using specified parameters // returns the list of entries found + time of the oldest entry -func (l *queryLog) search(params *searchParams) ([]*logEntry, time.Time) { +func (l *queryLog) search(params *searchParams) (entries []*logEntry, oldest time.Time) { now := time.Now() if params.limit == 0 { @@ -88,7 +88,7 @@ func (l *queryLog) search(params *searchParams) ([]*logEntry, time.Time) { totalLimit := params.offset + params.limit // now let's get a unified collection - entries := append(memoryEntries, fileEntries...) + entries = append(memoryEntries, fileEntries...) if len(entries) > totalLimit { // remove extra records entries = entries[:totalLimit] @@ -111,13 +111,18 @@ func (l *queryLog) search(params *searchParams) ([]*logEntry, time.Time) { } } - if len(entries) > 0 && len(entries) <= totalLimit { + if len(entries) > 0 { // Update oldest after merging in the memory buffer. oldest = entries[len(entries)-1].Time } - log.Debug("QueryLog: prepared data (%d/%d) older than %s in %s", - len(entries), total, params.olderThan, time.Since(now)) + log.Debug( + "querylog: prepared data (%d/%d) older than %s in %s", + len(entries), + total, + params.olderThan, + time.Since(now), + ) return entries, oldest } @@ -180,6 +185,8 @@ func (l *queryLog) searchFiles( e, ts, err = l.readNextEntry(r, params, cache) if err != nil { if err == io.EOF { + oldestNano = 0 + break } From 1a49d2f0c9eff0e084de83598e5e5825125d5905 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Thu, 26 May 2022 12:49:13 +0300 Subject: [PATCH 37/99] Pull request: client: reset filtered logs on url params clear Merge in DNS/adguard-home from fix-querylog-link to master Squashed commit of the following: commit fc4043258eb1e427a76ee44d2a4a525a6d659ab9 Merge: 25b91504 549b20bd Author: Ildar Kamalov Date: Thu May 26 12:42:02 2022 +0300 Merge branch 'master' into fix-querylog-link commit 25b91504e8949bd381e6774148e4a7ecbb81610e Author: Ildar Kamalov Date: Thu May 26 12:21:57 2022 +0300 fix commit f567b9b1e4eeb6499c79b05e4d837e905850a6b9 Author: Ildar Kamalov Date: Thu May 26 12:20:48 2022 +0300 client: reset filtered logs on url params clear --- client/src/components/Logs/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/src/components/Logs/index.js b/client/src/components/Logs/index.js index c3b30703..3e89c3b1 100644 --- a/client/src/components/Logs/index.js +++ b/client/src/components/Logs/index.js @@ -152,6 +152,16 @@ const Logs = () => { }; }, []); + useEffect(() => { + if (!history.location.search) { + (async () => { + setIsLoading(true); + await dispatch(setFilteredLogs()); + setIsLoading(false); + })(); + } + }, [history.location.search]); + const renderPage = () => <> Date: Thu, 26 May 2022 14:20:36 +0300 Subject: [PATCH 38/99] Pull request: client: upd i18n Merge in DNS/adguard-home from upd-i18n to master Squashed commit of the following: commit 7ddd8cb01f8136ad4690a439ee3b810043af749e Author: Ainar Garipov Date: Thu May 26 14:10:31 2022 +0300 client: upd i18n --- client/src/__locales/cs.json | 2 +- client/src/__locales/fi.json | 4 +-- client/src/__locales/pt-br.json | 2 +- client/src/__locales/pt-pt.json | 2 +- client/src/__locales/sl.json | 4 +-- client/src/__locales/tr.json | 12 ++++---- client/src/__locales/uk.json | 50 ++++++++++++++++----------------- client/src/__locales/zh-cn.json | 1 + 8 files changed, 39 insertions(+), 38 deletions(-) diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index 8331dd50..8467df91 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -85,7 +85,7 @@ "form_enter_hostname": "Zadejte název hostitele", "error_details": "Podrobnosti chyby", "response_details": "Detail odpovědi", - "request_details": "Detail požadavku", + "request_details": "Detaily požadavku", "client_details": "Detaily klienta", "details": "Detaily", "back": "Zpět", diff --git a/client/src/__locales/fi.json b/client/src/__locales/fi.json index 3141b12a..a5f3fa01 100644 --- a/client/src/__locales/fi.json +++ b/client/src/__locales/fi.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Bootstrap DNS-palvelimet", "bootstrap_dns_desc": "Bootstrap DNS-palvelimia käytetään ylävirroiksi määritettyjen DoH/DoT-resolvereiden IP-osoitteiden selvitykseen.", "local_ptr_title": "Yksityiset käänteiset DNS-palvelimet", - "local_ptr_desc": "DNS-palvelimet, joita AdGuard Home käyttää paikallisille PTR-pyynnöille. Näitä palvelimia käytetään yksityistä IP-osoitetta käyttävien päätelaitteiden osoitteiden, kuten \"192.168.12.34\", selvitykseen käänteisen DNS:n avulla. Jos ei käytössä, käyttää AdGuard Home käyttöjärjestelmän oletusarvoisia DNS-resolvereita, poislukien AdGuard Homen omat osoitteet.", + "local_ptr_desc": "DNS-palvelimet, joita AdGuard Home käyttää paikallisille PTR-kyselyille. Näitä palvelimia käytetään yksityistä IP-osoitetta käyttävien PTR-kyselyiden osoitteiden, kuten \"192.168.12.34\", selvitykseen käänteisen DNS:n avulla. Jos ei käytössä, AdGuard Home käyttää käyttöjärjestelmän oletusarvoisia DNS-resolvereita, poislukien AdGuard Homen omat osoitteet.", "local_ptr_default_resolver": "Oletusarvoisesti AdGuard Home käyttää seuraavia käänteisiä DNS-resolvereita: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home ei voinut määrittää tälle järjestelmälle sopivaa yksityistä käänteistä DNS-resolveria.", "local_ptr_placeholder": "Syötä yksi palvelimen osoite per rivi", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Syötä \"DNS 1\" ja \"DNS 2\" -kenttiin AdGuard Home -palvelimesi osoitteet.", "install_devices_ios_list_1": "Napauta aloitusnäytöstä \"Asetukset\".", "install_devices_ios_list_2": "Valitse vasemmalta \"Wi-Fi\" (mobiiliverkolle ei ole mahdollista määrittää omaa DNS-palvelinta).", - "install_devices_ios_list_3": "Valitse yhdistetty verkko.", + "install_devices_ios_list_3": "Valitse tällä hetkellä aktiivinen verkko.", "install_devices_ios_list_4": "Syötä \"DNS\" -kenttään AdGuard Home -palvelimesi osoitteet.", "get_started": "Aloita", "next": "Seuraava", diff --git a/client/src/__locales/pt-br.json b/client/src/__locales/pt-br.json index 48d82e0d..d52d6961 100644 --- a/client/src/__locales/pt-br.json +++ b/client/src/__locales/pt-br.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Servidores DNS de inicialização", "bootstrap_dns_desc": "Servidores DNS de inicialização são usados para resolver endereços IP dos resolvedores DoH/DoT que você especifica como upstreams.", "local_ptr_title": "Servidores DNS reversos privados", - "local_ptr_desc": "Os servidores DNS que o AdGuard Home usa para consultas PTR locais. Esses servidores são usados para resolver os nomes de host de clientes com endereços IP privados, por exemplo \"192.168.12.34\", usando DNS reverso. Se não for definido, o AdGuard Home usa os endereços dos resolvedores DNS padrão do seu sistema operacional, exceto os endereços do AdGuard Home.", + "local_ptr_desc": "Os servidores DNS que o AdGuard Home usa para consultas PTR locais. Esses servidores são usados para resolver solicitações de PTR para endereços em intervalos de IP privados, por exemplo \"192.168.12.34\", usando DNS reverso. Se não estiver definido, o AdGuard Home usa os endereços dos resolvedores de DNS padrão do seu sistema operacional, exceto os endereços do próprio AdGuard Home.", "local_ptr_default_resolver": "Por padrão, o AdGuard Home usa os seguintes resolvedores de DNS reverso: {{ip}}.", "local_ptr_no_default_resolver": "A página inicial do AdGuard não conseguiu determinar resolvedores DNS reversos privados adequados para este sistema.", "local_ptr_placeholder": "Insira um endereço de servidor por linha", diff --git a/client/src/__locales/pt-pt.json b/client/src/__locales/pt-pt.json index 1a2d5c7c..6502f9f9 100644 --- a/client/src/__locales/pt-pt.json +++ b/client/src/__locales/pt-pt.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Servidores DNS de arranque", "bootstrap_dns_desc": "Servidores DNS de inicialização são usados para resolver endereços IP dos resolvedores DoH/DoT que especifica como upstreams.", "local_ptr_title": "Servidores DNS reversos privados", - "local_ptr_desc": "Os servidores DNS que o AdGuard Home usa para consultas PTR locais. Esses servidores são usados para resolver os nomes de host de clientes com endereços IP privados, por exemplo \"192.168.12.34\", usando DNS reverso. Se não for definido, o AdGuard Home usa os endereços dos resolvedores DNS padrão do seu sistema operacional, exceto os endereços do AdGuard Home.", + "local_ptr_desc": "Os servidores DNS que o AdGuard Home usa para consultas PTR locais. Esses servidores são usados para resolver solicitações de PTR para endereços em intervalos de IP privados, por exemplo \"192.168.12.34\", usando DNS reverso. Se não estiver definido, o AdGuard Home usa os endereços dos resolvedores de DNS padrão do seu sistema operacional, exceto os endereços do próprio AdGuard Home.", "local_ptr_default_resolver": "Por predefinição, o AdGuard Home usa os seguintes resolvedores de DNS reverso: {{ip}}.", "local_ptr_no_default_resolver": "A página inicial do AdGuard não conseguiu determinar resolvedores DNS reversos privados adequados para este sistema.", "local_ptr_placeholder": "Insira um endereço de servidor por linha", diff --git a/client/src/__locales/sl.json b/client/src/__locales/sl.json index 8dffefc7..80dfd9aa 100644 --- a/client/src/__locales/sl.json +++ b/client/src/__locales/sl.json @@ -9,7 +9,7 @@ "bootstrap_dns": "Zagonski DNS strežniki", "bootstrap_dns_desc": "Zagonski DNS strežniki se uporabljajo za razreševanje IP naslovov DoH/DoT reševalcev, ki jih določite kot navzgornje.", "local_ptr_title": "Zasebni povratni strežniki DNS", - "local_ptr_desc": "Strežniki DNS, ki jih AdGuard Home uporablja za lokalne poizvedbe PTR. Ti strežniki se uporabljajo za razreševanje imen gostiteljev z zasebnimi naslovi IP, na primer \"192.168.12.34\" uporablja DNS. Če ni nastavljen, uporablja naslove privzetih razreševalnikov DNS vašega OS, razen naslovov samega AdGuard Home.", + "local_ptr_desc": "Strežniki DNS, ki jih AdGuard Home uporablja za lokalne PTR poizvedbe. Ti strežniki se uporabljajo za reševanje zahtev PTR za naslove v zasebnih obsegih IP, na primer \"192.168.12.34\", z uporabo obratnega DNS. Če ni nastavljen, AdGuard Home uporablja naslove privzetih razreševalnikov DNS vašega OS, razen naslovov samega AdGuard Home.", "local_ptr_default_resolver": "AdGuard Home privzeto uporablja te povratne razreševalnike DNS: {{ip}}.", "local_ptr_no_default_resolver": "AdGuard Home ni mogel določiti ustreznih zasebnih povratnih reševalcev DNS za ta sistem.", "local_ptr_placeholder": "V vrstico vnesite en naslov strežnika", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Spremeni nastavitev vrednosti DNS 1 in DNS 2 na naslove strežnikov AdGuard Home.", "install_devices_ios_list_1": "Na začetnem zaslonu izberite Nastavitve.", "install_devices_ios_list_2": "V levem meniju izberite Wi-Fi (nemogoče je konfigurirati DNS za mobilna omrežja).", - "install_devices_ios_list_3": "Dotaknite se imena trenutno aktivnega omrežja.", + "install_devices_ios_list_3": "Tapnite na ime trenutno aktivnega omrežja.", "install_devices_ios_list_4": "V polje DNS vnesite vaše naslove AdGuard Home strežnika.", "get_started": "Začnimo", "next": "Naprej", diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index f26e0011..6fd679ac 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -336,16 +336,16 @@ "install_devices_router_list_4": "Bazı yönlendirici türlerinde özel bir DNS sunucusu ayarlanamaz. Bu durumda, AdGuard Home'u <0>DHCP sunucusu olarak ayarlamak yardımcı olabilir. Aksi takdirde, yönlendirici modeliniz için DNS sunucularını nasıl ayarlayacağınız konusunda yönlendirici kılavuzuna bakmalısınız.", "install_devices_windows_list_1": "Başlat menüsünden veya Windows araması aracılığıyla Denetim Masası'nı açın.", "install_devices_windows_list_2": "Ağ ve İnternet kategorisine girin ve ardından Ağ ve Paylaşım Merkezi'ne girin.", - "install_devices_windows_list_3": "Sol panelde \"Bağdaştırıcı ayarlarını değiştirin'e\" tıklayın.", + "install_devices_windows_list_3": "Sol panelde \"Bağdaştırıcı ayarlarını değiştirin\" öğesine tıklayın.", "install_devices_windows_list_4": "Kullandığınız aktif bağlantının üzerine sağ tıklayın ve Özellikler öğesine tıklayın.", - "install_devices_windows_list_5": "Listede \"İnternet Protokolü Sürüm 4 (TCP/IPv4)\" (veya IPv6 için \"İnternet Protokolü Sürüm 6 (TCP/IPv6)\") öğesini bulun, seçin ve ardından tekrar Özellikler'e tıklayın.", + "install_devices_windows_list_5": "Listede \"İnternet Protokolü Sürüm 4 (TCP/IPv4)\" (veya IPv6 için \"İnternet Protokolü Sürüm 6 (TCP/IPv6)\") öğesini bulun, seçin ve ardından tekrar Özellikler öğesine tıklayın.", "install_devices_windows_list_6": "\"Aşağıdaki DNS sunucu adreslerini kullan\"ı seçin ve AdGuard Home sunucu adreslerinizi girin.", - "install_devices_macos_list_1": "Apple simgesine tıklayın ve Sistem Tercihleri'ne gidin.", - "install_devices_macos_list_2": "Ağ'a tıklayın.", + "install_devices_macos_list_1": "Apple simgesine tıklayın ve Sistem Tercihleri öğesine gidin.", + "install_devices_macos_list_2": "Ağ öğesine tıklayın.", "install_devices_macos_list_3": "Listedeki ilk bağlantıyı seçin ve Gelişmiş öğesine tıklayın.", "install_devices_macos_list_4": "DNS sekmesini seçin ve AdGuard Home sunucunuzun adreslerini girin.", "install_devices_android_list_1": "Android Menüsü ana ekranından Ayarlar'a dokunun.", - "install_devices_android_list_2": "Menüde bulunan Wi-Fi seçeneğine dokunun. Mevcut tüm ağlar listelenecektir (mobil ağlar için özel DNS sunucusu ayarlanamaz).", + "install_devices_android_list_2": "Menüde bulunan Wi-Fi öğesine dokunun. Mevcut tüm ağlar listelenecektir (mobil ağlar için özel DNS sunucusu ayarlanamaz).", "install_devices_android_list_3": "Bağlı olduğunuz ağın üzerine basılı tutun ve Ağı Değiştir'e dokunun.", "install_devices_android_list_4": "Bazı cihazlarda, diğer ayarları görmek için \"Gelişmiş\" seçeneğini seçmeniz gerekebilir. Android DNS ayarlarınızı yapmak için IP ayarlarını DHCP modundan Statik moda almanız gerekecektir.", "install_devices_android_list_5": "DNS 1 ve DNS 2 değerlerini AdGuard Home sunucunuzun adresleriyle değiştirin.", @@ -453,7 +453,7 @@ "setup_dns_privacy_2": "<0>DNS-over-HTTPS: <1>{{address}} dizesini kullan.", "setup_dns_privacy_3": "<0>İşte, kullanabileceğiniz yazılımların bir listesi.", "setup_dns_privacy_4": "Bir iOS 14 veya macOS Big Sur cihazında, DNS ayarlarına DNS-over-HTTPS veya DNS-over-TLS sunucuları ekleyen özel '.mobileconfig' dosyasını indirebilirsiniz.", - "setup_dns_privacy_android_1": "Android 9, yerel olarak DNS-over-TLS protokolünü destekler. Yapılandırmak için Ayarlar → Ağ ve İnternet → Gelişmiş → Özel DNS seçeneğine gidin ve alan adınızı girin.", + "setup_dns_privacy_android_1": "Android 9, yerel olarak DNS-over-TLS protokolünü destekler. Yapılandırmak için Ayarlar → Ağ ve İnternet → Gelişmiş → Özel DNS öğesine gidin ve alan adınızı girin.", "setup_dns_privacy_android_2": "<0>Android için AdGuard, <1>DNS-over-HTTPS ve <1>DNS-over-TLS protokolünü destekler.", "setup_dns_privacy_android_3": "<0>Intra Android'e <1>DNS-over-HTTPS protokol desteğini ekler.", "setup_dns_privacy_ios_1": "<0>DNSCloak, <1>DNS-over-HTTPS protokolünü destekler, ancak kendi sunucunuzu kullanacak şekilde yapılandırmak için bir <2>DNS Damgası oluşturmanız gerekir.", diff --git a/client/src/__locales/uk.json b/client/src/__locales/uk.json index 9fcbd460..84a6974e 100644 --- a/client/src/__locales/uk.json +++ b/client/src/__locales/uk.json @@ -7,16 +7,16 @@ "load_balancing": "Балансування навантаження", "load_balancing_desc": "Запитувати один сервер за раз. AdGuard Home використовуватиме зважений випадковий алгоритм для вибору сервера, щоб найшвидший сервер використовувався частіше.", "bootstrap_dns": "Bootstrap DNS-сервери", - "bootstrap_dns_desc": "Bootstrap DNS-сервери використовуються для пошуку IP-адреси DoH/DoT серверів, які ви встановили.", + "bootstrap_dns_desc": "Bootstrap DNS-сервери використовуються для вирішення IP-адрес встановлених серверів DoH/DoT.", "local_ptr_title": "Приватні сервери для зворотного DNS", - "local_ptr_desc": "DNS-сервери, які AdGuard Home використовує для локальних PTR-запитів. Ці сервери, використовуючи rDNS, використовуються для отримання доменних імен клієнтів у приватних мережах, наприклад, «192.168.12.34». Якщо список порожній, буде використовуватись системний DNS-сервер.", - "local_ptr_default_resolver": "AdGuard Home усталено використовує такі зворотні DNS-резолвери: {{ip}}.", - "local_ptr_no_default_resolver": "AdGuard Home не зміг визначити приватні реверсивні DNS-резолвери, що були б придатними для цієї системи.", + "local_ptr_desc": "DNS-сервери, які AdGuard Home використовує для локальних PTR-запитів. Ці сервери використовуються для вирішення PTR-запитів для адрес у приватних мережах, наприклад, «192.168.12.34». Якщо список порожній, AdGuard Home буде усталено використовувати системний DNS-сервер.", + "local_ptr_default_resolver": "Стандартно AdGuard Home користується такими зворотними DNS-вирішувачами: {{ip}}.", + "local_ptr_no_default_resolver": "AdGuard Home не зміг визначити приватні зворотні DNS-вирішувачі, які підійшли б для цієї системи.", "local_ptr_placeholder": "Вводьте одну адресу на рядок", - "resolve_clients_title": "Увімкнути запитування доменних імен для IP-адрес клієнтів", + "resolve_clients_title": "Увімкнути зворотне вирішення IP-адрес клієнтів", "resolve_clients_desc": "Визначати доменні імена клієнтів за допомогою PTR-запитів до відповідних серверів — приватних DNS-серверів для локальних клієнтів та upstream-серверів для клієнтів з публічними IP-адресами.", "use_private_ptr_resolvers_title": "Використовувати приватні зворотні DNS-резолвери", - "use_private_ptr_resolvers_desc": "Надсилати зворотні DNS-запити до вказаних серверів для клієнтів, що обслуговуються локально. Якщо вимкнено, AdGuard Home буде відповідати NXDOMAIN на всі такі PTR-запити, окрім запитів про клієнтів, що уже відомі по DHCP, /etc/hosts тощо.", + "use_private_ptr_resolvers_desc": "Надсилати зворотні DNS-запити до вказаних серверів для клієнтів, що обслуговуються локально. Якщо вимкнено, AdGuard Home буде відповідати NXDOMAIN на всі такі PTR-запити, окрім запитів про клієнтів, що уже відомі завдяки DHCP, /etc/hosts тощо.", "check_dhcp_servers": "Перевірити DHCP-сервери", "save_config": "Зберегти конфігурацію", "enabled_dhcp": "DHCP-сервер увімкнено", @@ -60,7 +60,7 @@ "dhcp_form_range_end": "Кінець діапазону", "dhcp_form_lease_title": "Час оренди DHCP (в секундах)", "dhcp_form_lease_input": "Тривалість оренди", - "dhcp_interface_select": "Оберіть інтерфейс DHCP", + "dhcp_interface_select": "Вибрати DHCP-інтерфейс", "dhcp_hardware_address": "Апаратна адреса", "dhcp_ip_addresses": "IP-адреси", "ip": "IP", @@ -117,11 +117,11 @@ "stats_adult": "Заблоковано вебсайтів для дорослих", "stats_query_domain": "Найчастіші запити доменів", "for_last_24_hours": "за останні 24 години", - "for_last_days": "за останній день", + "for_last_days": "за останній {{count}} день", "for_last_days_plural": "за останні {{count}} днів", "stats_disabled": "Статистику вимкнено. Ви можете увімкнути її на <0>сторінці налаштувань.", "stats_disabled_short": "Статистику вимкнено", - "no_domains_found": "Доменів не знайдено", + "no_domains_found": "Не знайдено жодного домену", "requests_count": "Кількість запитів", "top_blocked_domains": "Найчастіше блоковані домени", "top_clients": "Найактивніші клієнти", @@ -131,7 +131,7 @@ "number_of_dns_query_days_plural": "Кількість DNS-запитів, оброблених за останні {{count}} днів", "number_of_dns_query_24_hours": "Кількість DNS-запитів, оброблених за останні 24 години", "number_of_dns_query_blocked_24_hours": "Кількість DNS-запитів, заблокованих фільтрами і списками блокування hosts", - "number_of_dns_query_blocked_24_hours_by_sec": "Кількість DNS-запитів, заблокованих модулем безпеки перегляду AdGuard", + "number_of_dns_query_blocked_24_hours_by_sec": "Кількість DNS-запитів, заблокованих модулем «Безпека перегляду» AdGuard", "number_of_dns_query_blocked_24_hours_adult": "Кількість заблокованих вебсайтів для дорослих", "enforced_save_search": "Примусовий безпечний пошук", "number_of_dns_query_to_safe_search": "Кількість DNS-запитів до пошукових систем, для яких примусово застосований безпечний пошук", @@ -139,10 +139,10 @@ "average_processing_time_hint": "Середній час обробки DNS запиту в мілісекундах", "block_domain_use_filters_and_hosts": "Блокування доменів за допомогою фільтрів та hosts-файлів", "filters_block_toggle_hint": "Ви можете налаштувати правила блокування в розділі Фільтри.", - "use_adguard_browsing_sec": "Використовувати Безпечну навігацію AdGuard", - "use_adguard_browsing_sec_hint": "AdGuard Home перевірятиме, чи додано домен до списку веб-служби безпечного перегляду браузера. Він використовуватиме API для перевірки — на сервер надсилається лише короткий префікс хешу SHA256 доменного імені.", - "use_adguard_parental": "Використовувати вебсервіс Батьківського контролю AdGuard", - "use_adguard_parental_hint": "AdGuard Home перевірить, чи містить домен матеріали для дорослих. Він використовує то же API, що й Безпечна навігація AdGuard.", + "use_adguard_browsing_sec": "Використовувати вебслужбу «Безпека перегляду» AdGuard", + "use_adguard_browsing_sec_hint": "AdGuard Home перевірятиме, чи підлягає домен блокуванню завдяки вебслужбі «Безпека перегляду». Для перевірки буде використано безпечний API — на сервер надсилається лише короткий префікс хешу SHA256 доменного імені.", + "use_adguard_parental": "Використовувати вебслужбу «Батьківський контроль» AdGuard", + "use_adguard_parental_hint": "AdGuard Home перевірить, чи містить домен матеріали для дорослих. Буде використано той же безпечний API, що й для «Безпеки перегляду» AdGuard.", "enforce_safe_search": "Використовувати Безпечний пошук", "enforce_save_search_hint": "AdGuard Home може примусово застосовувати безпечний пошук в таких пошукових системах: Google, YouTube, Bing, DuckDuckGo, Yandex, Pixabay.", "no_servers_specified": "Сервери не вказано", @@ -165,8 +165,8 @@ "enabled_filtering_toast": "Фільтрування увімкнено", "disabled_safe_browsing_toast": "Безпечний перегляд вимкнено", "enabled_safe_browsing_toast": "Безпечний перегляд увімкнено", - "disabled_parental_toast": "Батьківський контроль вимкнено", - "enabled_parental_toast": "Батьківський контроль увімкнено", + "disabled_parental_toast": "«Батьківський контроль» вимкнено", + "enabled_parental_toast": "«Батьківський контроль» увімкнено", "disabled_safe_search_toast": "Безпечний пошук вимкнено", "enabled_save_search_toast": "Безпечний пошук увімкнено", "enabled_table_header": "Увімкнено", @@ -193,7 +193,7 @@ "edit_blocklist": "Змінити список блокування", "edit_allowlist": "Змінити список дозволів", "choose_blocklist": "Виберіть списки блокування", - "choose_allowlist": "Обрати списки дозволених сайтів", + "choose_allowlist": "Виберіть списки дозволів", "enter_valid_blocklist": "Введіть дійсну URL-адресу в список блокування.", "enter_valid_allowlist": "Введіть дійсну URL-адресу в список дозволів.", "form_error_url_format": "Неправильний формат URL", @@ -214,7 +214,7 @@ "example_upstream_dot": "зашифрований <0>DNS-over-TLS;", "example_upstream_doh": "зашифрований <0>DNS-over-HTTPS;", "example_upstream_doq": "зашифрований <0>DNS-over-QUIC (експериментальний);", - "example_upstream_sdns": "<0>DNS Stamps для <1>DNSCrypt або <2>DNS-over-HTTPS серверів;", + "example_upstream_sdns": "<0>DNS Stamps для <1>DNSCrypt- або <2>DNS-over-HTTPS-вирішувачів;", "example_upstream_tcp": "звичайний DNS (через TCP);", "example_upstream_tcp_hostname": "звичайний DNS (поверх TCP, з назвою вузла);", "all_lists_up_to_date_toast": "Всі списки вже оновлені", @@ -351,7 +351,7 @@ "install_devices_android_list_5": "Змініть встановлені значення DNS 1 і DNS 2 на адреси вашого домашнього сервера AdGuard.", "install_devices_ios_list_1": "На головному екрані торкніться Налаштування.", "install_devices_ios_list_2": "Виберіть Wi-Fi у меню ліворуч (неможливо налаштувати DNS для мобільних мереж).", - "install_devices_ios_list_3": "Натисніть на назву поточно активної мережі.", + "install_devices_ios_list_3": "Натисніть на назву поточної активної мережі.", "install_devices_ios_list_4": "У полі DNS введіть адреси вашого сервера AdGuard Home.", "get_started": "Розпочати", "next": "Наступні", @@ -372,7 +372,7 @@ "encryption_doq": "Порт DNS-over-QUIC (експериментальний)", "encryption_doq_desc": "Якщо цей порт налаштовано, AdGuard Home запустить на цьому порту сервер DNS-over-QUIC. Це експериментально і може бути ненадійним. Крім того, зараз не так багато клієнтів, які це підтримують.", "encryption_certificates": "Сертифікати", - "encryption_certificates_desc": "Для використання шифрування потрібно надати дійсний ланцюжок сертифікатів SSL для вашого домену. Ви можете отримати безкоштовний сертифікат на <0>{{link}} або придбати його в одному з надійних Центрів Сертифікації.", + "encryption_certificates_desc": "Для використання шифрування потрібно надати дійсний ланцюжок сертифікатів SSL для вашого домену. Ви можете отримати безплатний сертифікат на <0>{{link}} або придбати його в одному з надійних Центрів Сертифікації.", "encryption_certificates_input": "Скопіюйте/вставте сюди свої кодовані PEM сертифікати.", "encryption_status": "Статус", "encryption_expire": "Закінчується", @@ -552,16 +552,16 @@ "fastest_addr": "Найшвидша IP-адреса", "fastest_addr_desc": "Опитати всі DNS-сервери й повернути найшвидшу IP-адресу серед усіх наданих. Це сповільнить швидкість DNS-запитів, оскільки AdGuard Home повинен буде чекати відповіді усіх DNS-серверів, але водночас може покращити якість з'єднання.", "autofix_warning_text": "Якщо ви натиснете «Виправити», AdGuard Home налаштує вашу систему на використання DNS-сервера AdGuard Home.", - "autofix_warning_list": "Це виконає наступні завдання: <0>Деактивує систему DNSStubListener <0>Змінить адресу DNS сервера на 127.0.0.1 <0>Замінить символічне посилання /etc/resolv.conf на /run/systemd/resolve/resolv.conf <0>Зупинить DNSStubListener (перезапустить сервіс systemd-resolved)", + "autofix_warning_list": "Будуть виконані такі дії: <0>Деактивація системи DNSStubListener <0>Зміна адреси DNS-сервера на «127.0.0.1» <0>Заміна символічного посилання «/etc/resolv.conf» на «/run/systemd/resolve/resolv.conf» <0>Зупинка DNSStubListener (перезапуск системної служби systemd-resolved)", "autofix_warning_result": "В результаті буде усталено, що усі DNS-запити вашої системи будуть опрацьовані AdGuard Home.", "tags_title": "Теги", "tags_desc": "Ви можете вибрати теги, які відповідають клієнту. Теги можна використати в правилах фільтрування, щоб точніше застосовувати їх. <0>Докладніше.", "form_select_tags": "Виберіть теги клієнта", - "check_title": "Перевірте фільтрування", + "check_title": "Перевірити фільтрування", "check_desc": "Перевірити чи фільтрується назва вузла.", "check": "Перевірити", "form_enter_host": "Введіть назву вузла", - "filtered_custom_rules": "Відфільтровано за власними правилами фільтрування", + "filtered_custom_rules": "Відфільтровано завдяки власним правилам фільтрування", "choose_from_list": "Виберіть зі списку", "add_custom_list": "Додати власний список", "host_whitelisted": "Вузол додано до списку дозволів", @@ -585,14 +585,14 @@ "list_updated": "{{count}} список оновлено", "list_updated_plural": "{{count}} списки оновлено", "dnssec_enable": "Увімкнути DNSSEC", - "dnssec_enable_desc": "Встановити прапорець DNSSEC для вихідних DNS запитів та перевірити результат (потрібен розпізнавач з підтримкою DNSSEC).", + "dnssec_enable_desc": "Увімкнути DNSSEC для вихідних DNS-запитів та перевірити результат (потрібен вирішувач з підтримкою DNSSEC).", "validated_with_dnssec": "Засвідчено DNSSEC", "all_queries": "Усі запити", "show_blocked_responses": "Заблоковані", "show_whitelisted_responses": "Дозволені", "show_processed_responses": "Оброблені", "blocked_safebrowsing": "Заблоковано Безпечним переглядом", - "blocked_adult_websites": "Заблоковано Батьківським контролем", + "blocked_adult_websites": "Заблоковано «Батьківським контролем»", "blocked_threats": "Заблоковано загроз", "allowed": "Дозволено", "filtered": "Відфільтровано", diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 4640432f..8903052f 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -351,6 +351,7 @@ "install_devices_android_list_5": "将 DNS 1 和 DNS 2 的值改为您的 AdGuard Home 服务器地址。", "install_devices_ios_list_1": "从主屏幕中点击「设置」。", "install_devices_ios_list_2": "从左侧目录中选择「无线局域网」(移动数据网络环境下不支持修改 DNS )。", + "install_devices_ios_list_3": "点击当前已连接网络的名称。", "install_devices_ios_list_4": "在 DNS 字段中输入您的 AdGuard Home 服务器地址。", "get_started": "开始配置", "next": "下一步", From c3d5fcc6692bbbf7271c5ee44dac7d984fa7cd80 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Thu, 26 May 2022 16:21:59 +0300 Subject: [PATCH 39/99] Pull request: locales: DoQ status Merge in DNS/adguard-home from 4592-doq-status to master Squashed commit of the following: commit 96bc041b736a45711419160aebb79296f13ff84d Author: Dimitry Kolyshev Date: Thu May 26 14:21:10 2022 +0200 all: locales --- client/src/__locales/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index f39d2f51..a5c21109 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -213,7 +213,7 @@ "example_upstream_udp": "regular DNS (over UDP, hostname);", "example_upstream_dot": "encrypted <0>DNS-over-TLS;", "example_upstream_doh": "encrypted <0>DNS-over-HTTPS;", - "example_upstream_doq": "encrypted <0>DNS-over-QUIC (experimental);", + "example_upstream_doq": "encrypted <0>DNS-over-QUIC;", "example_upstream_sdns": "<0>DNS Stamps for <1>DNSCrypt or <2>DNS-over-HTTPS resolvers;", "example_upstream_tcp": "regular DNS (over TCP);", "example_upstream_tcp_hostname": "regular DNS (over TCP, hostname);", @@ -369,8 +369,8 @@ "encryption_https_desc": "If HTTPS port is configured, AdGuard Home admin interface will be accessible via HTTPS, and it will also provide DNS-over-HTTPS on '/dns-query' location.", "encryption_dot": "DNS-over-TLS port", "encryption_dot_desc": "If this port is configured, AdGuard Home will run a DNS-over-TLS server on this port.", - "encryption_doq": "DNS-over-QUIC port (experimental)", - "encryption_doq_desc": "If this port is configured, AdGuard Home will run a DNS-over-QUIC server on this port. It's experimental and may not be reliable. Also, there are not too many clients that support it at the moment.", + "encryption_doq": "DNS-over-QUIC port", + "encryption_doq_desc": "If this port is configured, AdGuard Home will run a DNS-over-QUIC server on this port.", "encryption_certificates": "Certificates", "encryption_certificates_desc": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on <0>{{link}} or you can buy it from one of the trusted Certificate Authorities.", "encryption_certificates_input": "Copy/paste your PEM-encoded certificates here.", From 756c932e372e36b5a6814d73fa6dac6c8799c9a1 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Thu, 26 May 2022 17:53:11 +0300 Subject: [PATCH 40/99] Pull request: dnsforward: add doq alpn Merge in DNS/adguard-home from 4592-doq-alpn to master Squashed commit of the following: commit 5985445dbf5158ae1e5b0235b404dd188c856e60 Author: Dimitry Kolyshev Date: Thu May 26 16:42:06 2022 +0200 dnsforward: add doq alpn commit 9dcd6fee615a1a5ac1f80641ac16c18371b67096 Merge: 2564c870 c3d5fcc6 Author: Dimitry Kolyshev Date: Thu May 26 15:24:07 2022 +0200 Merge remote-tracking branch 'origin/master' into 4592-doq-alpn commit 2564c870e704ff453d0ad2fb22fa295ef725dd13 Author: Dimitry Kolyshev Date: Thu May 26 15:20:16 2022 +0200 dnsforward: add doq alpn --- internal/dnsforward/dns.go | 21 ++++++++++++++++++--- internal/dnsforward/dns_test.go | 26 ++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index 19d54d91..e049bef0 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -260,9 +260,8 @@ func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) { } if question.Name == ddrHostFQDN { - // TODO(a.garipov): Check DoQ support in next RFC drafts. - if s.dnsProxy.TLSListenAddr == nil && s.dnsProxy.HTTPSListenAddr == nil || - question.Qtype != dns.TypeSVCB { + if s.dnsProxy.TLSListenAddr == nil && s.dnsProxy.HTTPSListenAddr == nil && + s.dnsProxy.QUICListenAddr == nil || question.Qtype != dns.TypeSVCB { d.Res = s.makeResponse(d.Req) return resultCodeFinish @@ -314,6 +313,22 @@ func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) { resp.Answer = append(resp.Answer, ans) } + for _, addr := range s.dnsProxy.QUICListenAddr { + values := []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"doq"}}, + &dns.SVCBPort{Port: uint16(addr.Port)}, + } + + ans := &dns.SVCB{ + Hdr: s.hdr(req, dns.TypeSVCB), + Priority: 3, + Target: domainName, + Value: values, + } + + resp.Answer = append(resp.Answer, ans) + } + return resp } diff --git a/internal/dnsforward/dns_test.go b/internal/dnsforward/dns_test.go index 8ab7501c..b40b7bc2 100644 --- a/internal/dnsforward/dns_test.go +++ b/internal/dnsforward/dns_test.go @@ -36,6 +36,15 @@ func TestServer_ProcessDDRQuery(t *testing.T) { }, } + doqSVCB := &dns.SVCB{ + Priority: 3, + Target: ddrTestDomainName, + Value: []dns.SVCBKeyValue{ + &dns.SVCBAlpn{Alpn: []string{"doq"}}, + &dns.SVCBPort{Port: 8042}, + }, + } + testCases := []struct { name string host string @@ -43,6 +52,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) { wantRes resultCode portDoH int portDoT int + portDoQ int qtype uint16 ddrEnabled bool }{{ @@ -88,6 +98,14 @@ func TestServer_ProcessDDRQuery(t *testing.T) { qtype: dns.TypeSVCB, ddrEnabled: true, portDoH: 8044, + }, { + name: "doq", + wantRes: resultCodeFinish, + want: []*dns.SVCB{doqSVCB}, + host: ddrHostFQDN, + qtype: dns.TypeSVCB, + ddrEnabled: true, + portDoQ: 8042, }, { name: "dot_doh", wantRes: resultCodeFinish, @@ -101,7 +119,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - s := prepareTestServer(t, tc.portDoH, tc.portDoT, tc.ddrEnabled) + s := prepareTestServer(t, tc.portDoH, tc.portDoT, tc.portDoQ, tc.ddrEnabled) req := createTestMessageWithType(tc.host, tc.qtype) @@ -130,7 +148,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) { } } -func prepareTestServer(t *testing.T, portDoH, portDoT int, ddrEnabled bool) (s *Server) { +func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled bool) (s *Server) { t.Helper() proxyConf := proxy.Config{} @@ -143,6 +161,10 @@ func prepareTestServer(t *testing.T, portDoH, portDoT int, ddrEnabled bool) (s * proxyConf.TLSListenAddr = []*net.TCPAddr{{Port: portDoT}} } + if portDoQ > 0 { + proxyConf.QUICListenAddr = []*net.UDPAddr{{Port: portDoQ}} + } + s = &Server{ dnsProxy: &proxy.Proxy{ Config: proxyConf, From 7ce7e908654579789f23ea5302416b67885494ae Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Mon, 30 May 2022 16:04:28 +0300 Subject: [PATCH 41/99] Pull request: dnsforward: fix ddr target Updates #4463. Squashed commit of the following: commit 047155b585a1c762d709874f44abb2d8c5a9dbca Author: Eugene Burkov Date: Mon May 30 15:34:38 2022 +0300 dnsforward: imp code commit b0508ffec13ccf5fc5d3d2e37c9e1bd83c3c039e Author: Eugene Burkov Date: Mon May 30 15:27:02 2022 +0300 dnsforward: fix ddr target --- internal/dnsforward/dns.go | 4 +++- internal/dnsforward/dns_test.go | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index e049bef0..2865bc84 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -278,7 +278,9 @@ func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) { // makeDDRResponse creates DDR answer according to server configuration. func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) { resp = s.makeResponse(req) - domainName := s.conf.ServerName + // TODO(e.burkov): Think about stroing the FQDN version of the server's + // name somewhere. + domainName := dns.Fqdn(s.conf.ServerName) for _, addr := range s.dnsProxy.HTTPSListenAddr { values := []dns.SVCBKeyValue{ diff --git a/internal/dnsforward/dns_test.go b/internal/dnsforward/dns_test.go index b40b7bc2..129e3c2f 100644 --- a/internal/dnsforward/dns_test.go +++ b/internal/dnsforward/dns_test.go @@ -14,12 +14,15 @@ import ( "github.com/stretchr/testify/require" ) -const ddrTestDomainName = "dns.example.net" +const ( + ddrTestDomainName = "dns.example.net" + ddrTestFQDN = ddrTestDomainName + "." +) func TestServer_ProcessDDRQuery(t *testing.T) { dohSVCB := &dns.SVCB{ Priority: 1, - Target: ddrTestDomainName, + Target: ddrTestFQDN, Value: []dns.SVCBKeyValue{ &dns.SVCBAlpn{Alpn: []string{"h2"}}, &dns.SVCBPort{Port: 8044}, @@ -29,7 +32,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) { dotSVCB := &dns.SVCB{ Priority: 2, - Target: ddrTestDomainName, + Target: ddrTestFQDN, Value: []dns.SVCBKeyValue{ &dns.SVCBAlpn{Alpn: []string{"dot"}}, &dns.SVCBPort{Port: 8043}, @@ -38,7 +41,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) { doqSVCB := &dns.SVCB{ Priority: 3, - Target: ddrTestDomainName, + Target: ddrTestFQDN, Value: []dns.SVCBKeyValue{ &dns.SVCBAlpn{Alpn: []string{"doq"}}, &dns.SVCBPort{Port: 8042}, From 4b884ace622f86fa2b77efb7c5ade513ff5ae3b5 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Tue, 31 May 2022 17:28:50 +0300 Subject: [PATCH 42/99] Pull request: all: fix doh ddr Merge in DNS/adguard-home from fix-ddr-doh to master Squashed commit of the following: commit 53d3147b22044061d78b3bf4badca60505ac245a Author: Dimitry Kolyshev Date: Tue May 31 15:02:17 2022 +0200 all: fix doh ddr --- internal/dnsforward/config.go | 5 +++-- internal/dnsforward/dns.go | 6 +++--- internal/dnsforward/dns_test.go | 8 ++++---- internal/home/dns.go | 4 ++++ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 16a6325e..f9234155 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -134,8 +134,9 @@ type FilteringConfig struct { // TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS type TLSConfig struct { - TLSListenAddrs []*net.TCPAddr `yaml:"-" json:"-"` - QUICListenAddrs []*net.UDPAddr `yaml:"-" json:"-"` + TLSListenAddrs []*net.TCPAddr `yaml:"-" json:"-"` + QUICListenAddrs []*net.UDPAddr `yaml:"-" json:"-"` + HTTPSListenAddrs []*net.TCPAddr `yaml:"-" json:"-"` // Reject connection if the client uses server name (in SNI) that doesn't match the certificate StrictSNICheck bool `yaml:"strict_sni_check" json:"-"` diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index 2865bc84..55a38a2f 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -260,7 +260,7 @@ func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) { } if question.Name == ddrHostFQDN { - if s.dnsProxy.TLSListenAddr == nil && s.dnsProxy.HTTPSListenAddr == nil && + if s.dnsProxy.TLSListenAddr == nil && s.conf.HTTPSListenAddrs == nil && s.dnsProxy.QUICListenAddr == nil || question.Qtype != dns.TypeSVCB { d.Res = s.makeResponse(d.Req) @@ -278,11 +278,11 @@ func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) { // makeDDRResponse creates DDR answer according to server configuration. func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) { resp = s.makeResponse(req) - // TODO(e.burkov): Think about stroing the FQDN version of the server's + // TODO(e.burkov): Think about storing the FQDN version of the server's // name somewhere. domainName := dns.Fqdn(s.conf.ServerName) - for _, addr := range s.dnsProxy.HTTPSListenAddr { + for _, addr := range s.conf.HTTPSListenAddrs { values := []dns.SVCBKeyValue{ &dns.SVCBAlpn{Alpn: []string{"h2"}}, &dns.SVCBPort{Port: uint16(addr.Port)}, diff --git a/internal/dnsforward/dns_test.go b/internal/dnsforward/dns_test.go index 129e3c2f..b9c7e47b 100644 --- a/internal/dnsforward/dns_test.go +++ b/internal/dnsforward/dns_test.go @@ -156,10 +156,6 @@ func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled b proxyConf := proxy.Config{} - if portDoH > 0 { - proxyConf.HTTPSListenAddr = []*net.TCPAddr{{Port: portDoH}} - } - if portDoT > 0 { proxyConf.TLSListenAddr = []*net.TCPAddr{{Port: portDoT}} } @@ -182,6 +178,10 @@ func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled b }, } + if portDoH > 0 { + s.conf.TLSConfig.HTTPSListenAddrs = []*net.TCPAddr{{Port: portDoH}} + } + return s } diff --git a/internal/home/dns.go b/internal/home/dns.go index 9eabfefa..d51a6dd2 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -221,6 +221,10 @@ func generateServerConfig() (newConf dnsforward.ServerConfig, err error) { newConf.TLSConfig = tlsConf.TLSConfig newConf.TLSConfig.ServerName = tlsConf.ServerName + if tlsConf.PortHTTPS != 0 { + newConf.HTTPSListenAddrs = ipsToTCPAddrs(hosts, tlsConf.PortHTTPS) + } + if tlsConf.PortDNSOverTLS != 0 { newConf.TLSListenAddrs = ipsToTCPAddrs(hosts, tlsConf.PortDNSOverTLS) } From f46c9f74d5b03f8caa60d8e648bbc46fe306714d Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 2 Jun 2022 15:57:06 +0300 Subject: [PATCH 43/99] Pull request: all: upd go Merge in DNS/adguard-home from upd-go to master Squashed commit of the following: commit b0bec8926508fb7ee3f26c2303d9628e21f0b62f Author: Ainar Garipov Date: Thu Jun 2 15:47:51 2022 +0300 all: upd go --- CHANGELOG.md | 15 +++++++++++---- bamboo-specs/release.yaml | 6 +++--- bamboo-specs/test.yaml | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a72447c..3bdd37ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ and this project adheres to ### Security +- Go version was updated to prevent the possibility of exploiting the + [CVE-2022-29526], [CVE-2022-30634], [CVE-2022-30629], [CVE-2022-30580], and + [CVE-2022-29804] vulnerabilities. - Enforced password strength policy ([#3503]). - Weaker cipher suites that use the CBC (cipher block chaining) mode of operation have been disabled ([#2993]). @@ -161,10 +164,14 @@ In this release, the schema version has changed from 12 to 14. [#4591]: https://github.com/AdguardTeam/AdGuardHome/issues/4591 [#4592]: https://github.com/AdguardTeam/AdGuardHome/issues/4592 -[rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250 -[ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html -[repr]: https://reproducible-builds.org/docs/source-date-epoch/ - +[CVE-2022-29526]: https://www.cvedetails.com/cve/CVE-2022-29526 +[CVE-2022-29804]: https://www.cvedetails.com/cve/CVE-2022-29804 +[CVE-2022-30580]: https://www.cvedetails.com/cve/CVE-2022-30580 +[CVE-2022-30629]: https://www.cvedetails.com/cve/CVE-2022-30629 +[CVE-2022-30634]: https://www.cvedetails.com/cve/CVE-2022-30634 +[ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html +[repr]: https://reproducible-builds.org/docs/source-date-epoch/ +[rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250 ### Security +- Weaker cipher suites that use the CBC (cipher block chaining) mode of + operation have been disabled ([#2993]). + +### Added + +- Support for Discovery of Designated Resolvers (DDR) according to the [RFC + draft][ddr-draft-06] ([#4463]). +- `windows/arm64` support ([#3057]). + +### Deprecated + +- Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. + +[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993 +[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057 + +[ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html + + + + + + + +## [v0.107.7] - 2022-06-06 + +See also the [v0.107.7 GitHub milestone][ms-v0.107.7]. + +### Security + - Go version was updated to prevent the possibility of exploiting the [CVE-2022-29526], [CVE-2022-30634], [CVE-2022-30629], [CVE-2022-30580], and [CVE-2022-29804] vulnerabilities. - Enforced password strength policy ([#3503]). -- Weaker cipher suites that use the CBC (cipher block chaining) mode of - operation have been disabled ([#2993]). ### Added - Support for the final DNS-over-QUIC standard, [RFC 9250][rfc-9250] ([#4592]). - Support upstreams for subdomains of a domain only ([#4503]). -- Support for Discovery of Designated Resolvers (DDR) according to the [RFC - draft][ddr-draft-06] ([#4463]). - The ability to control each source of runtime clients separately via `clients.runtime_sources` configuration object ([#3020]). - The ability to customize the set of networks that are considered private @@ -41,7 +69,6 @@ and this project adheres to ([#4166]). - Logs are now collected by default on FreeBSD and OpenBSD when AdGuard Home is installed as a service ([#4213]). -- `windows/arm64` support ([#3057]). ### Changed @@ -125,10 +152,9 @@ In this release, the schema version has changed from 12 to 14. ### Deprecated -- The `--no-etc-hosts` option. Its' functionality is now controlled by +- The `--no-etc-hosts` option. Its functionality is now controlled by `clients.runtime_sources.hosts` configuration property. v0.109.0 will remove the flag completely. -- Go 1.17 support. v0.109.0 will require at least Go 1.18 to build. ### Fixed @@ -140,9 +166,7 @@ In this release, the schema version has changed from 12 to 14. - ARP tables refreshing process causing excessive PTR requests ([#3157]). [#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730 -[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993 [#3020]: https://github.com/AdguardTeam/AdGuardHome/issues/3020 -[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057 [#3142]: https://github.com/AdguardTeam/AdGuardHome/issues/3142 [#3157]: https://github.com/AdguardTeam/AdGuardHome/issues/3157 [#3367]: https://github.com/AdguardTeam/AdGuardHome/issues/3367 @@ -169,20 +193,10 @@ In this release, the schema version has changed from 12 to 14. [CVE-2022-30580]: https://www.cvedetails.com/cve/CVE-2022-30580 [CVE-2022-30629]: https://www.cvedetails.com/cve/CVE-2022-30629 [CVE-2022-30634]: https://www.cvedetails.com/cve/CVE-2022-30634 -[ddr-draft-06]: https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html -[repr]: https://reproducible-builds.org/docs/source-date-epoch/ +[ms-v0.107.7]: https://github.com/AdguardTeam/AdGuardHome/milestone/43?closed=1 [rfc-9250]: https://datatracker.ietf.org/doc/html/rfc9250 - - - ## [v0.107.6] - 2022-04-13 @@ -234,6 +248,7 @@ See also the [v0.107.6 GitHub milestone][ms-v0.107.6]. [CVE-2022-28327]: https://www.cvedetails.com/cve/CVE-2022-28327 [dns-draft-02]: https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02#section-5.1 [ms-v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/milestone/42?closed=1 +[repr]: https://reproducible-builds.org/docs/source-date-epoch/ [svcb-draft-08]: https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-08.html @@ -995,11 +1010,12 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2]. -[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.6...HEAD +[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.7...HEAD +[v0.107.7]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.6...v0.107.7 [v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.5...v0.107.6 [v0.107.5]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.4...v0.107.5 [v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...v0.107.4 From 1c1ca1c6e3d490ddfaf2f176a54f5b93b24a9c1a Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Thu, 9 Jun 2022 11:57:58 +0300 Subject: [PATCH 48/99] Pull request: 4641 fix button clickable area Updates #4641 Squashed commit of the following: commit f9f018388a198d7712e5caabba94035e42e393c4 Author: Ildar Kamalov Date: Tue Jun 7 16:21:37 2022 +0300 client: fix button clickable area --- client/src/components/Settings/Settings.css | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/components/Settings/Settings.css b/client/src/components/Settings/Settings.css index 4efb0868..3fd560f9 100644 --- a/client/src/components/Settings/Settings.css +++ b/client/src/components/Settings/Settings.css @@ -113,6 +113,7 @@ width: 30px; height: 30px; background-color: transparent; + overflow: hidden; } .btn-icon--green { From 302faca32f849cb1d63202b0a905077fba56bfa9 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Thu, 9 Jun 2022 12:07:29 +0300 Subject: [PATCH 49/99] Pull request: 4642 update dns addresses on encryption update Updates #4642 Squashed commit of the following: commit 75729120d3532dc2bd12b6c9e724a691043a1870 Merge: 5b681867 1c1ca1c6 Author: Ildar Kamalov Date: Thu Jun 9 11:58:13 2022 +0300 Merge branch 'master' into 4642-dns-privacy commit 5b68186705c3a9287a44e33c8cf7ab79060f35a4 Author: Ildar Kamalov Date: Tue Jun 7 18:39:02 2022 +0300 fix commit 46a9346154d33206e829a97021f3ef47ac2a5611 Author: Ildar Kamalov Date: Tue Jun 7 18:18:18 2022 +0300 client: update dns addresses on encryption update --- client/src/actions/encryption.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/actions/encryption.js b/client/src/actions/encryption.js index 36faf2ec..2f58abd3 100644 --- a/client/src/actions/encryption.js +++ b/client/src/actions/encryption.js @@ -24,6 +24,7 @@ export const getTlsStatus = () => async (dispatch) => { export const setTlsConfigRequest = createAction('SET_TLS_CONFIG_REQUEST'); export const setTlsConfigFailure = createAction('SET_TLS_CONFIG_FAILURE'); export const setTlsConfigSuccess = createAction('SET_TLS_CONFIG_SUCCESS'); +export const dnsStatusSuccess = createAction('DNS_STATUS_SUCCESS'); export const setTlsConfig = (config) => async (dispatch, getState) => { dispatch(setTlsConfigRequest()); @@ -39,6 +40,12 @@ export const setTlsConfig = (config) => async (dispatch, getState) => { const response = await apiClient.setTlsConfig(values); response.certificate_chain = atob(response.certificate_chain); response.private_key = atob(response.private_key); + + const dnsStatus = await apiClient.getGlobalStatus(); + if (dnsStatus) { + dispatch(dnsStatusSuccess(dnsStatus)); + } + dispatch(setTlsConfigSuccess(response)); dispatch(addSuccessToast('encryption_config_saved')); redirectToCurrentProtocol(response, httpPort); From e738508d7a5e09e257724c557069000506e055ad Mon Sep 17 00:00:00 2001 From: Ainar Garipov Date: Thu, 9 Jun 2022 17:47:05 +0300 Subject: [PATCH 50/99] Pull request: all: imp updater Merge in DNS/adguard-home from imp-updater to master Squashed commit of the following: commit 6ed487359e56a35b36f13dcbf2efbf2a7a2d8734 Author: Ainar Garipov Date: Thu Jun 9 16:29:35 2022 +0300 all: imp logs, err handling commit e930044cb619a43e5a44c230dadbe2228e9a93f5 Author: Ainar Garipov Date: Thu Jun 9 15:53:35 2022 +0300 all: imp updater --- client/src/__locales/en.json | 2 +- internal/aghalg/nullbool.go | 59 +++++++++++++++++++++ internal/{dhcpd => aghalg}/nullbool_test.go | 23 ++++---- internal/dhcpd/http.go | 19 +++---- internal/dhcpd/nullbool.go | 58 -------------------- internal/home/controlupdate.go | 7 +-- internal/updater/check.go | 30 +++++------ internal/updater/updater.go | 34 +++++++----- internal/updater/updater_test.go | 16 ++---- scripts/make/build-release.sh | 1 + 10 files changed, 124 insertions(+), 125 deletions(-) create mode 100644 internal/aghalg/nullbool.go rename internal/{dhcpd => aghalg}/nullbool_test.go (72%) delete mode 100644 internal/dhcpd/nullbool.go diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index a5c21109..dd885677 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -445,7 +445,7 @@ "access_blocked_title": "Disallowed domains", "access_blocked_desc": "Not to be confused with filters. AdGuard Home drops DNS queries matching these domains, and these queries don't even appear in the query log. You can specify exact domain names, wildcards, or URL filter rules, e.g. \"example.org\", \"*.example.org\", or \"||example.org^\" correspondingly.", "access_settings_saved": "Access settings successfully saved", - "updates_checked": "Updates successfully checked", + "updates_checked": "A new version of AdGuard Home is available", "updates_version_equal": "AdGuard Home is up-to-date", "check_updates_now": "Check for updates now", "dns_privacy": "DNS Privacy", diff --git a/internal/aghalg/nullbool.go b/internal/aghalg/nullbool.go new file mode 100644 index 00000000..3c5633e3 --- /dev/null +++ b/internal/aghalg/nullbool.go @@ -0,0 +1,59 @@ +package aghalg + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// NullBool is a nullable boolean. Use these in JSON requests and responses +// instead of pointers to bool. +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 +} + +// type check +var _ json.Unmarshaler = (*NullBool)(nil) + +// 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("unmarshalling json data into aghalg.NullBool: bad value %q", b) + } + + return nil +} diff --git a/internal/dhcpd/nullbool_test.go b/internal/aghalg/nullbool_test.go similarity index 72% rename from internal/dhcpd/nullbool_test.go rename to internal/aghalg/nullbool_test.go index 549df608..0fe7f203 100644 --- a/internal/dhcpd/nullbool_test.go +++ b/internal/aghalg/nullbool_test.go @@ -1,9 +1,10 @@ -package dhcpd +package aghalg_test import ( "encoding/json" "testing" + "github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/golibs/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,37 +15,37 @@ func TestNullBool_UnmarshalJSON(t *testing.T) { name string wantErrMsg string data []byte - want nullBool + want aghalg.NullBool }{{ name: "empty", wantErrMsg: "", data: []byte{}, - want: nbNull, + want: aghalg.NBNull, }, { name: "null", wantErrMsg: "", data: []byte("null"), - want: nbNull, + want: aghalg.NBNull, }, { name: "true", wantErrMsg: "", data: []byte("true"), - want: nbTrue, + want: aghalg.NBTrue, }, { name: "false", wantErrMsg: "", data: []byte("false"), - want: nbFalse, + want: aghalg.NBFalse, }, { name: "invalid", - wantErrMsg: `invalid nullBool value "invalid"`, + wantErrMsg: `unmarshalling json data into aghalg.NullBool: bad value "invalid"`, data: []byte("invalid"), - want: nbNull, + want: aghalg.NBNull, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - var got nullBool + var got aghalg.NullBool err := got.UnmarshalJSON(tc.data) testutil.AssertErrorMsg(t, tc.wantErrMsg, err) @@ -53,9 +54,9 @@ func TestNullBool_UnmarshalJSON(t *testing.T) { } t.Run("json", func(t *testing.T) { - want := nbTrue + want := aghalg.NBTrue var got struct { - A nullBool + A aghalg.NullBool } err := json.Unmarshal([]byte(`{"A":true}`), &got) diff --git a/internal/dhcpd/http.go b/internal/dhcpd/http.go index e340addb..62a08f66 100644 --- a/internal/dhcpd/http.go +++ b/internal/dhcpd/http.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/golibs/errors" @@ -145,7 +146,7 @@ type dhcpServerConfigJSON struct { V4 *v4ServerConfJSON `json:"v4"` V6 *v6ServerConfJSON `json:"v6"` InterfaceName string `json:"interface_name"` - Enabled nullBool `json:"enabled"` + Enabled aghalg.NullBool `json:"enabled"` } func (s *Server) handleDHCPSetConfigV4( @@ -156,7 +157,7 @@ func (s *Server) handleDHCPSetConfigV4( } v4Conf := v4JSONToServerConf(conf.V4) - v4Conf.Enabled = conf.Enabled == nbTrue + v4Conf.Enabled = conf.Enabled == aghalg.NBTrue if len(v4Conf.RangeStart) == 0 { v4Conf.Enabled = false } @@ -183,7 +184,7 @@ func (s *Server) handleDHCPSetConfigV6( } v6Conf := v6JSONToServerConf(conf.V6) - v6Conf.Enabled = conf.Enabled == nbTrue + v6Conf.Enabled = conf.Enabled == aghalg.NBTrue if len(v6Conf.RangeStart) == 0 { v6Conf.Enabled = false } @@ -206,7 +207,7 @@ func (s *Server) handleDHCPSetConfigV6( func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { conf := &dhcpServerConfigJSON{} - conf.Enabled = boolToNullBool(s.conf.Enabled) + conf.Enabled = aghalg.BoolToNullBool(s.conf.Enabled) conf.InterfaceName = s.conf.InterfaceName err := json.NewDecoder(r.Body).Decode(conf) @@ -230,7 +231,7 @@ func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { return } - if conf.Enabled == nbTrue && !v4Enabled && !v6Enabled { + if conf.Enabled == aghalg.NBTrue && !v4Enabled && !v6Enabled { aghhttp.Error(r, w, http.StatusBadRequest, "dhcpv4 or dhcpv6 configuration must be complete") return @@ -243,8 +244,8 @@ func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { return } - if conf.Enabled != nbNull { - s.conf.Enabled = conf.Enabled == nbTrue + if conf.Enabled != aghalg.NBNull { + s.conf.Enabled = conf.Enabled == aghalg.NBTrue } if conf.InterfaceName != "" { @@ -279,11 +280,11 @@ func (s *Server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) { type netInterfaceJSON struct { Name string `json:"name"` - GatewayIP net.IP `json:"gateway_ip"` HardwareAddr string `json:"hardware_address"` + Flags string `json:"flags"` + GatewayIP net.IP `json:"gateway_ip"` Addrs4 []net.IP `json:"ipv4_addresses"` Addrs6 []net.IP `json:"ipv6_addresses"` - Flags string `json:"flags"` } func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) { diff --git a/internal/dhcpd/nullbool.go b/internal/dhcpd/nullbool.go deleted file mode 100644 index b07f6768..00000000 --- a/internal/dhcpd/nullbool.go +++ /dev/null @@ -1,58 +0,0 @@ -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/home/controlupdate.go b/internal/home/controlupdate.go index ae469598..08ddd455 100644 --- a/internal/home/controlupdate.go +++ b/internal/home/controlupdate.go @@ -12,6 +12,7 @@ import ( "syscall" "time" + "github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghnet" "github.com/AdguardTeam/AdGuardHome/internal/updater" @@ -147,8 +148,8 @@ type versionResponse struct { // setAllowedToAutoUpdate sets CanAutoUpdate to true if AdGuard Home is actually // allowed to perform an automatic update by the OS. func (vr *versionResponse) setAllowedToAutoUpdate() (err error) { - if vr.CanAutoUpdate == nil || !*vr.CanAutoUpdate { - return + if vr.CanAutoUpdate != aghalg.NBTrue { + return nil } tlsConf := &tlsConfigSettings{} @@ -162,7 +163,7 @@ func (vr *versionResponse) setAllowedToAutoUpdate() (err error) { } } - vr.CanAutoUpdate = &canUpdate + vr.CanAutoUpdate = aghalg.BoolToNullBool(canUpdate) return nil } diff --git a/internal/updater/check.go b/internal/updater/check.go index ec7176b2..2bac6153 100644 --- a/internal/updater/check.go +++ b/internal/updater/check.go @@ -5,9 +5,9 @@ import ( "fmt" "io" "net/http" - "strings" "time" + "github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghio" "github.com/AdguardTeam/golibs/errors" ) @@ -17,11 +17,12 @@ const versionCheckPeriod = 8 * time.Hour // VersionInfo contains information about a new version. type VersionInfo struct { - CanAutoUpdate *bool `json:"can_autoupdate,omitempty"` - NewVersion string `json:"new_version,omitempty"` - Announcement string `json:"announcement,omitempty"` - AnnouncementURL string `json:"announcement_url,omitempty"` - SelfUpdateMinVersion string `json:"-"` + NewVersion string `json:"new_version,omitempty"` + Announcement string `json:"announcement,omitempty"` + AnnouncementURL string `json:"announcement_url,omitempty"` + // TODO(a.garipov): See if the frontend actually still cares about + // nullability. + CanAutoUpdate aghalg.NullBool `json:"can_autoupdate,omitempty"` } // MaxResponseSize is responses on server's requests maximum length in bytes. @@ -67,15 +68,13 @@ func (u *Updater) VersionInfo(forceRecheck bool) (vi VersionInfo, err error) { } func (u *Updater) parseVersionResponse(data []byte) (VersionInfo, error) { - var canAutoUpdate bool info := VersionInfo{ - CanAutoUpdate: &canAutoUpdate, + CanAutoUpdate: aghalg.NBFalse, } versionJSON := map[string]string{ - "version": "", - "announcement": "", - "announcement_url": "", - "selfupdate_min_version": "", + "version": "", + "announcement": "", + "announcement_url": "", } err := json.Unmarshal(data, &versionJSON) if err != nil { @@ -91,14 +90,9 @@ func (u *Updater) parseVersionResponse(data []byte) (VersionInfo, error) { info.NewVersion = versionJSON["version"] info.Announcement = versionJSON["announcement"] info.AnnouncementURL = versionJSON["announcement_url"] - info.SelfUpdateMinVersion = versionJSON["selfupdate_min_version"] packageURL, ok := u.downloadURL(versionJSON) - if ok && - info.NewVersion != u.version && - strings.TrimPrefix(u.version, "v") >= strings.TrimPrefix(info.SelfUpdateMinVersion, "v") { - canAutoUpdate = true - } + info.CanAutoUpdate = aghalg.BoolToNullBool(ok && info.NewVersion != u.version) u.newVersion = info.NewVersion u.packageURL = packageURL diff --git a/internal/updater/updater.go b/internal/updater/updater.go index 0cc49f9e..d975d977 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -104,11 +104,14 @@ func NewUpdater(conf *Config) *Updater { } // Update performs the auto-update. -func (u *Updater) Update() error { +func (u *Updater) Update() (err error) { u.mu.Lock() defer u.mu.Unlock() - err := u.prepare() + log.Info("updater: updating") + defer func() { log.Info("updater: finished; errors: %v", err) }() + + err = u.prepare() if err != nil { return err } @@ -178,7 +181,12 @@ func (u *Updater) prepare() (err error) { u.backupExeName = filepath.Join(u.backupDir, exeName) u.updateExeName = filepath.Join(u.updateDir, exeName) - log.Info("Updating from %s to %s. URL:%s", version.Version(), u.newVersion, u.packageURL) + log.Debug( + "updater: updating from %s to %s using url: %s", + version.Version(), + u.newVersion, + u.packageURL, + ) // TODO(a.garipov): Use os.Args[0] instead? u.currentExeName = filepath.Join(u.workDir, exeName) @@ -194,7 +202,7 @@ func (u *Updater) unpack() error { var err error _, pkgNameOnly := filepath.Split(u.packageURL) - log.Debug("updater: unpacking the package") + log.Debug("updater: unpacking package") if strings.HasSuffix(pkgNameOnly, ".zip") { u.unpackedFiles, err = zipFileUnpack(u.packageName, u.updateDir) if err != nil { @@ -229,7 +237,7 @@ func (u *Updater) check() error { } func (u *Updater) backup() error { - log.Debug("updater: backing up the current configuration") + log.Debug("updater: backing up current configuration") _ = os.Mkdir(u.backupDir, 0o755) err := copyFile(u.confName, filepath.Join(u.backupDir, "AdGuardHome.yaml")) if err != nil { @@ -252,7 +260,7 @@ func (u *Updater) replace() error { return fmt.Errorf("copySupportingFiles(%s, %s) failed: %s", u.updateDir, u.workDir, err) } - log.Debug("updater: renaming: %s -> %s", u.currentExeName, u.backupExeName) + log.Debug("updater: renaming: %s to %s", u.currentExeName, u.backupExeName) err = os.Rename(u.currentExeName, u.backupExeName) if err != nil { return err @@ -268,7 +276,7 @@ func (u *Updater) replace() error { return err } - log.Debug("updater: renamed: %s -> %s", u.updateExeName, u.currentExeName) + log.Debug("updater: renamed: %s to %s", u.updateExeName, u.currentExeName) return nil } @@ -297,7 +305,7 @@ func (u *Updater) downloadPackageFile(url, filename string) (err error) { return fmt.Errorf("http request failed: %w", err) } - log.Debug("updater: reading HTTP body") + log.Debug("updater: reading http body") // This use of ReadAll is now safe, because we limited body's Reader. body, err := io.ReadAll(r) if err != nil { @@ -343,7 +351,7 @@ func tarGzFileUnpackOne(outDir string, tr *tar.Reader, hdr *tar.Header) (name st } if hdr.Typeflag != tar.TypeReg { - log.Debug("updater: %s: unknown file type %d, skipping", name, hdr.Typeflag) + log.Info("updater: %s: unknown file type %d, skipping", name, hdr.Typeflag) return "", nil } @@ -364,7 +372,7 @@ func tarGzFileUnpackOne(outDir string, tr *tar.Reader, hdr *tar.Header) (name st return "", fmt.Errorf("io.Copy(): %w", err) } - log.Tracef("updater: created file %s", outputName) + log.Debug("updater: created file %q", outputName) return name, nil } @@ -440,7 +448,7 @@ func zipFileUnpackOne(outDir string, zf *zip.File) (name string, err error) { return "", fmt.Errorf("os.Mkdir(%q): %w", outputName, err) } - log.Tracef("created directory %q", outputName) + log.Debug("updater: created directory %q", outputName) return "", nil } @@ -457,7 +465,7 @@ func zipFileUnpackOne(outDir string, zf *zip.File) (name string, err error) { return "", fmt.Errorf("io.Copy(): %w", err) } - log.Tracef("created file %s", outputName) + log.Debug("updater: created file %q", outputName) return name, nil } @@ -516,7 +524,7 @@ func copySupportingFiles(files []string, srcdir, dstdir string) error { return err } - log.Debug("updater: copied: %q -> %q", src, dst) + log.Debug("updater: copied: %q to %q", src, dst) } return nil diff --git a/internal/updater/updater_test.go b/internal/updater/updater_test.go index 3a29d277..771fb6d4 100644 --- a/internal/updater/updater_test.go +++ b/internal/updater/updater_test.go @@ -10,6 +10,7 @@ import ( "strconv" "testing" + "github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghtest" "github.com/AdguardTeam/AdGuardHome/internal/version" "github.com/AdguardTeam/golibs/testutil" @@ -92,10 +93,7 @@ func TestUpdateGetVersion(t *testing.T) { assert.Equal(t, "v0.103.0-beta.2", info.NewVersion) assert.Equal(t, "AdGuard Home v0.103.0-beta.2 is now available!", info.Announcement) assert.Equal(t, "https://github.com/AdguardTeam/AdGuardHome/internal/releases", info.AnnouncementURL) - assert.Equal(t, "v0.0", info.SelfUpdateMinVersion) - if assert.NotNil(t, info.CanAutoUpdate) { - assert.True(t, *info.CanAutoUpdate) - } + assert.Equal(t, aghalg.NBTrue, info.CanAutoUpdate) // check cached _, err = u.VersionInfo(false) @@ -290,10 +288,7 @@ func TestUpdater_VersionInto_ARM(t *testing.T) { assert.Equal(t, "v0.103.0-beta.2", info.NewVersion) assert.Equal(t, "AdGuard Home v0.103.0-beta.2 is now available!", info.Announcement) assert.Equal(t, "https://github.com/AdguardTeam/AdGuardHome/internal/releases", info.AnnouncementURL) - assert.Equal(t, "v0.0", info.SelfUpdateMinVersion) - if assert.NotNil(t, info.CanAutoUpdate) { - assert.True(t, *info.CanAutoUpdate) - } + assert.Equal(t, aghalg.NBTrue, info.CanAutoUpdate) } func TestUpdater_VersionInto_MIPS(t *testing.T) { @@ -330,8 +325,5 @@ func TestUpdater_VersionInto_MIPS(t *testing.T) { assert.Equal(t, "v0.103.0-beta.2", info.NewVersion) assert.Equal(t, "AdGuard Home v0.103.0-beta.2 is now available!", info.Announcement) assert.Equal(t, "https://github.com/AdguardTeam/AdGuardHome/internal/releases", info.AnnouncementURL) - assert.Equal(t, "v0.0", info.SelfUpdateMinVersion) - if assert.NotNil(t, info.CanAutoUpdate) { - assert.True(t, *info.CanAutoUpdate) - } + assert.Equal(t, aghalg.NBTrue, info.CanAutoUpdate) } diff --git a/scripts/make/build-release.sh b/scripts/make/build-release.sh index 36fc98f7..2cf95086 100644 --- a/scripts/make/build-release.sh +++ b/scripts/make/build-release.sh @@ -363,6 +363,7 @@ else fi readonly announcement_url +# TODO(a.garipov): Remove "selfupdate_min_version" in future versions. rm -f "$version_json" echo "{ \"version\": \"${version}\", From d3f39b0aa168ddf89755e769a1477ae3c91ece3a Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Fri, 10 Jun 2022 12:41:20 +0300 Subject: [PATCH 51/99] Pull request: 4637 fix blocked services icons and actions highlight Updates #4637 Squashed commit of the following: commit d69887586d15582406fab642e576a46f8984107b Merge: 65453371 e738508d Author: Ildar Kamalov Date: Fri Jun 10 12:07:29 2022 +0300 Merge branch 'master' into 4637-table commit 65453371fc7309e772a12fb9f522247e1392a64a Author: Ildar Kamalov Date: Thu Jun 9 18:43:44 2022 +0300 client: fix blocked services icons and actions highlight --- client/src/components/Filters/Rewrites/Table.js | 2 ++ client/src/components/Filters/Table.js | 4 +++- client/src/components/Logs/Logs.css | 9 +++++++++ client/src/components/Settings/Clients/ClientsTable.js | 4 +++- .../src/components/Settings/Dhcp/StaticLeases/index.js | 2 ++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/components/Filters/Rewrites/Table.js b/client/src/components/Filters/Rewrites/Table.js index 45638ec0..28009ca3 100644 --- a/client/src/components/Filters/Rewrites/Table.js +++ b/client/src/components/Filters/Rewrites/Table.js @@ -29,6 +29,8 @@ class Table extends Component { Header: this.props.t('actions_table_header'), accessor: 'actions', maxWidth: 100, + sortable: false, + resizable: false, Cell: (value) => (
@@ -101,6 +103,7 @@ Form.propTypes = { ip: PropTypes.string.isRequired, hostname: PropTypes.string.isRequired, cidr: PropTypes.string.isRequired, + gatewayIp: PropTypes.string, }), pristine: PropTypes.bool.isRequired, handleSubmit: PropTypes.func.isRequired, diff --git a/client/src/components/Settings/Dhcp/StaticLeases/Modal.js b/client/src/components/Settings/Dhcp/StaticLeases/Modal.js index 8ad0f009..0baf487e 100644 --- a/client/src/components/Settings/Dhcp/StaticLeases/Modal.js +++ b/client/src/components/Settings/Dhcp/StaticLeases/Modal.js @@ -13,6 +13,7 @@ const Modal = ({ cidr, rangeStart, rangeEnd, + gatewayIp, }) => { const dispatch = useDispatch(); @@ -42,6 +43,7 @@ const Modal = ({ cidr, rangeStart, rangeEnd, + gatewayIp, }} onSubmit={handleSubmit} processingAdding={processingAdding} @@ -61,6 +63,7 @@ Modal.propTypes = { cidr: PropTypes.string.isRequired, rangeStart: PropTypes.string, rangeEnd: PropTypes.string, + gatewayIp: PropTypes.string, }; export default withTranslation()(Modal); diff --git a/client/src/components/Settings/Dhcp/StaticLeases/index.js b/client/src/components/Settings/Dhcp/StaticLeases/index.js index a63f78cd..2374f044 100644 --- a/client/src/components/Settings/Dhcp/StaticLeases/index.js +++ b/client/src/components/Settings/Dhcp/StaticLeases/index.js @@ -24,6 +24,7 @@ const StaticLeases = ({ cidr, rangeStart, rangeEnd, + gatewayIp, }) => { const [t] = useTranslation(); const dispatch = useDispatch(); @@ -106,6 +107,7 @@ const StaticLeases = ({ cidr={cidr} rangeStart={rangeStart} rangeEnd={rangeEnd} + gatewayIp={gatewayIp} /> ); @@ -119,6 +121,7 @@ StaticLeases.propTypes = { cidr: PropTypes.string.isRequired, rangeStart: PropTypes.string, rangeEnd: PropTypes.string, + gatewayIp: PropTypes.string, }; cellWrap.propTypes = { diff --git a/client/src/components/Settings/Dhcp/index.js b/client/src/components/Settings/Dhcp/index.js index a84e0a93..bd3a45e3 100644 --- a/client/src/components/Settings/Dhcp/index.js +++ b/client/src/components/Settings/Dhcp/index.js @@ -278,6 +278,7 @@ const Dhcp = () => { cidr={cidr} rangeStart={dhcp?.values?.v4?.range_start} rangeEnd={dhcp?.values?.v4?.range_end} + gatewayIp={dhcp?.values?.v4?.gateway_ip} />
; + const blockButton = ( + <> +
+ + + ); const blockForClientButton =