mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
Sync v2.11.0
This commit is contained in:
parent
87137bddcf
commit
f1791135af
41
CHANGELOG.md
41
CHANGELOG.md
@ -7,6 +7,47 @@ The format is **not** based on [Keep a Changelog][kec], since the project **does
|
|||||||
[kec]: https://keepachangelog.com/en/1.0.0/
|
[kec]: https://keepachangelog.com/en/1.0.0/
|
||||||
[sem]: https://semver.org/spec/v2.0.0.html
|
[sem]: https://semver.org/spec/v2.0.0.html
|
||||||
|
|
||||||
|
## AGDNS-2507 / Build 926
|
||||||
|
|
||||||
|
- Profile's file cache version was incremented. The file cache structure has been optimized, so messages like the following are to be expected:
|
||||||
|
|
||||||
|
```none
|
||||||
|
profiledb: warning: error loading fs cache err="decoding protobuf: proto: cannot parse invalid wire-format data"
|
||||||
|
```
|
||||||
|
|
||||||
|
## AGDNS-2327 / Build 916
|
||||||
|
|
||||||
|
- Profile's file cache version was incremented. The new field `BlockChromePrefetch` has been added to profile's object.
|
||||||
|
|
||||||
|
- The objects within the `filtering_groups` have a new property, `block_chrome_prefetch`. So replace this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filtering_groups:
|
||||||
|
-
|
||||||
|
id: default
|
||||||
|
# …
|
||||||
|
block_firefox_canary: true
|
||||||
|
block_private_relay: true
|
||||||
|
```
|
||||||
|
|
||||||
|
with this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filtering_groups:
|
||||||
|
-
|
||||||
|
id: default
|
||||||
|
# …
|
||||||
|
block_chrome_prefetch: true
|
||||||
|
block_firefox_canary: true
|
||||||
|
block_private_relay: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## AGDNS-2514 / Build 908
|
||||||
|
|
||||||
|
- The environment variable `DNSCHECK_CACHE_KV_SIZE` has been added.
|
||||||
|
|
||||||
|
- The property `kv.type` within the `check` object now supports the `cache` value.
|
||||||
|
|
||||||
## AGDNS-2484/ Build 886
|
## AGDNS-2484/ Build 886
|
||||||
|
|
||||||
- Property `type` of the `ratelimit` object has been moved to the underlying `allowlist` object. So replace this:
|
- Property `type` of the `ratelimit` object has been moved to the underlying `allowlist` object. So replace this:
|
||||||
|
2
Makefile
2
Makefile
@ -24,7 +24,7 @@ BRANCH = $${BRANCH:-$$(git rev-parse --abbrev-ref HEAD)}
|
|||||||
GOAMD64 = v1
|
GOAMD64 = v1
|
||||||
GOPROXY = https://proxy.golang.org|direct
|
GOPROXY = https://proxy.golang.org|direct
|
||||||
GOTELEMETRY = off
|
GOTELEMETRY = off
|
||||||
GOTOOLCHAIN = go1.23.2
|
GOTOOLCHAIN = go1.23.4
|
||||||
RACE = 0
|
RACE = 0
|
||||||
REVISION = $${REVISION:-$$(git rev-parse --short HEAD)}
|
REVISION = $${REVISION:-$$(git rev-parse --short HEAD)}
|
||||||
VERSION = 0
|
VERSION = 0
|
||||||
|
@ -175,8 +175,8 @@ check:
|
|||||||
# Domains to use for DNS checking.
|
# Domains to use for DNS checking.
|
||||||
kv:
|
kv:
|
||||||
# Defines the type of remote key-value storage. Allowed values are
|
# Defines the type of remote key-value storage. Allowed values are
|
||||||
# "backend", "consul", and "redis".
|
# "backend", "cache", "consul", and "redis".
|
||||||
type: 'consul'
|
type: 'cache'
|
||||||
# For how long to keep the information about the client.
|
# For how long to keep the information about the client.
|
||||||
ttl: 30s
|
ttl: 30s
|
||||||
# Domains to use for DNS checking.
|
# Domains to use for DNS checking.
|
||||||
@ -341,8 +341,9 @@ filtering_groups:
|
|||||||
enabled: true
|
enabled: true
|
||||||
block_dangerous_domains: true
|
block_dangerous_domains: true
|
||||||
block_newly_registered_domains: false
|
block_newly_registered_domains: false
|
||||||
block_private_relay: false
|
block_chrome_prefetch: true
|
||||||
block_firefox_canary: true
|
block_firefox_canary: true
|
||||||
|
block_private_relay: false
|
||||||
- id: 'family'
|
- id: 'family'
|
||||||
parental:
|
parental:
|
||||||
enabled: true
|
enabled: true
|
||||||
@ -357,8 +358,9 @@ filtering_groups:
|
|||||||
enabled: true
|
enabled: true
|
||||||
block_dangerous_domains: true
|
block_dangerous_domains: true
|
||||||
block_newly_registered_domains: false
|
block_newly_registered_domains: false
|
||||||
block_private_relay: false
|
block_chrome_prefetch: true
|
||||||
block_firefox_canary: true
|
block_firefox_canary: true
|
||||||
|
block_private_relay: false
|
||||||
- id: 'non_filtering'
|
- id: 'non_filtering'
|
||||||
rule_lists:
|
rule_lists:
|
||||||
enabled: false
|
enabled: false
|
||||||
@ -368,8 +370,9 @@ filtering_groups:
|
|||||||
enabled: false
|
enabled: false
|
||||||
block_dangerous_domains: true
|
block_dangerous_domains: true
|
||||||
block_newly_registered_domains: false
|
block_newly_registered_domains: false
|
||||||
block_private_relay: false
|
block_chrome_prefetch: false
|
||||||
block_firefox_canary: true
|
block_firefox_canary: true
|
||||||
|
block_private_relay: false
|
||||||
|
|
||||||
# The configuration for the device-listening feature. Works only on Linux with
|
# The configuration for the device-listening feature. Works only on Linux with
|
||||||
# SO_BINDTODEVICE support.
|
# SO_BINDTODEVICE support.
|
||||||
|
@ -378,7 +378,7 @@ The `check` object has the following properties:
|
|||||||
|
|
||||||
- <a href="#check_kv" id="check_kv" name="check_kv">`kv`</a>: Remote key-value storage settings. It has the following properties:
|
- <a href="#check_kv" id="check_kv" name="check_kv">`kv`</a>: Remote key-value storage settings. It has the following properties:
|
||||||
|
|
||||||
- <a href="#check-kv-type" id="check-kv-type" name="check-kv-type">`type`</a>: Type of the remote KV storage. Allowed values are `backend`, `consul`, and `redis`.
|
- <a href="#check-kv-type" id="check-kv-type" name="check-kv-type">`type`</a>: Type of the remote KV storage. Allowed values are `backend`, `cache`, `consul`, and `redis`.
|
||||||
|
|
||||||
**Example:** `consul`.
|
**Example:** `consul`.
|
||||||
|
|
||||||
@ -386,6 +386,8 @@ The `check` object has the following properties:
|
|||||||
|
|
||||||
For `backend`, the TTL must be greater than `0s`.
|
For `backend`, the TTL must be greater than `0s`.
|
||||||
|
|
||||||
|
For `cache`, the TTL is not used.
|
||||||
|
|
||||||
For `consul`, the TTL must be between `10s` and `1d`. Note that the actual TTL can be up to twice as long.
|
For `consul`, the TTL must be between `10s` and `1d`. Note that the actual TTL can be up to twice as long.
|
||||||
|
|
||||||
For `redis`, the TTL must be greater than or equal to `1ms`.
|
For `redis`, the TTL must be greater than or equal to `1ms`.
|
||||||
@ -662,14 +664,18 @@ The items of the `filtering_groups` array have the following properties:
|
|||||||
|
|
||||||
**Example:** `true`.
|
**Example:** `true`.
|
||||||
|
|
||||||
- <a href="#fg-*-block_private_relay" id="fg-*-block_private_relay" name="fg-*-block_private_relay">`private_relay`</a>: If true, Apple Private Relay queries are blocked for requests using this filtering group.
|
- <a href="#fg-*-block_chrome_prefetch" id="fg-*-block_chrome_prefetch" name="fg-*-block_chrome_prefetch">`block_chrome_prefetch`</a>: If true, Chrome prefetch domain queries are blocked for requests using this filtering group, forcing the preferch proxy into preflight mode.
|
||||||
|
|
||||||
**Example:** `false`.
|
**Example:** `true`.
|
||||||
|
|
||||||
- <a href="#fg-*-block_firefox_canary" id="fg-*-block_firefox_canary" name="fg-*-block_firefox_canary">`block_firefox_canary`</a>: If true, Firefox canary domain queries are blocked for requests using this filtering group.
|
- <a href="#fg-*-block_firefox_canary" id="fg-*-block_firefox_canary" name="fg-*-block_firefox_canary">`block_firefox_canary`</a>: If true, Firefox canary domain queries are blocked for requests using this filtering group.
|
||||||
|
|
||||||
**Example:** `true`.
|
**Example:** `true`.
|
||||||
|
|
||||||
|
- <a href="#fg-*-block_private_relay" id="fg-*-block_private_relay" name="fg-*-block_private_relay">`private_relay`</a>: If true, Apple Private Relay queries are blocked for requests using this filtering group.
|
||||||
|
|
||||||
|
**Example:** `false`.
|
||||||
|
|
||||||
## <a href="#interface_listeners" id="interface_listeners" name="interface_listeners">Network interface listeners</a>
|
## <a href="#interface_listeners" id="interface_listeners" name="interface_listeners">Network interface listeners</a>
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
|
@ -112,6 +112,7 @@ Supported IDs:
|
|||||||
- `profiledb`
|
- `profiledb`
|
||||||
- `rulestat`
|
- `rulestat`
|
||||||
- `ticket_rotator`
|
- `ticket_rotator`
|
||||||
|
- `tlsconfig`
|
||||||
|
|
||||||
The special ID `*`, when used alone, causes all available refresh tasks to be performed. Use with caution.
|
The special ID `*`, when used alone, causes all available refresh tasks to be performed. Use with caution.
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ AdGuard DNS uses [environment variables][wiki-env] to store some of the more sen
|
|||||||
- [`CONSUL_ALLOWLIST_URL`](#CONSUL_ALLOWLIST_URL)
|
- [`CONSUL_ALLOWLIST_URL`](#CONSUL_ALLOWLIST_URL)
|
||||||
- [`CONSUL_DNSCHECK_KV_URL`](#CONSUL_DNSCHECK_KV_URL)
|
- [`CONSUL_DNSCHECK_KV_URL`](#CONSUL_DNSCHECK_KV_URL)
|
||||||
- [`CONSUL_DNSCHECK_SESSION_URL`](#CONSUL_DNSCHECK_SESSION_URL)
|
- [`CONSUL_DNSCHECK_SESSION_URL`](#CONSUL_DNSCHECK_SESSION_URL)
|
||||||
|
- [`DNSCHECK_CACHE_KV_SIZE`](#DNSCHECK_CACHE_KV_SIZE)
|
||||||
- [`DNSCHECK_REMOTEKV_API_KEY`](#DNSCHECK_REMOTEKV_API_KEY)
|
- [`DNSCHECK_REMOTEKV_API_KEY`](#DNSCHECK_REMOTEKV_API_KEY)
|
||||||
- [`DNSCHECK_REMOTEKV_URL`](#DNSCHECK_REMOTEKV_URL)
|
- [`DNSCHECK_REMOTEKV_URL`](#DNSCHECK_REMOTEKV_URL)
|
||||||
- [`FILTER_CACHE_PATH`](#FILTER_CACHE_PATH)
|
- [`FILTER_CACHE_PATH`](#FILTER_CACHE_PATH)
|
||||||
@ -142,6 +143,16 @@ The HTTP(S) URL of the session API of the Consul instance used as a key-value da
|
|||||||
|
|
||||||
**Example:** `http://localhost:8500/v1/session/create`
|
**Example:** `http://localhost:8500/v1/session/create`
|
||||||
|
|
||||||
|
## <a href="#DNSCHECK_CACHE_KV_SIZE" id="DNSCHECK_CACHE_KV_SIZE" name="DNSCHECK_CACHE_KV_SIZE">`DNSCHECK_CACHE_KV_SIZE`</a>
|
||||||
|
|
||||||
|
The maximum number of the local cache key-value database entries for the DNS server checking.
|
||||||
|
|
||||||
|
**Default:** No default value, a positive value is required if the [type][conf-dnscheck-type] of the database is set to `cache`.
|
||||||
|
|
||||||
|
**Example:** `1000`
|
||||||
|
|
||||||
|
[conf-dnscheck-type]: configuration.md#check-kv-type
|
||||||
|
|
||||||
## <a href="#DNSCHECK_REMOTEKV_API_KEY" id="DNSCHECK_REMOTEKV_API_KEY" name="DNSCHECK_REMOTEKV_API_KEY">`DNSCHECK_REMOTEKV_API_KEY`</a>
|
## <a href="#DNSCHECK_REMOTEKV_API_KEY" id="DNSCHECK_REMOTEKV_API_KEY" name="DNSCHECK_REMOTEKV_API_KEY">`DNSCHECK_REMOTEKV_API_KEY`</a>
|
||||||
|
|
||||||
The API key to use when authenticating queries to the backend key-value database API, if any. The API key should be valid as defined by [RFC 6750].
|
The API key to use when authenticating queries to the backend key-value database API, if any. The API key should be valid as defined by [RFC 6750].
|
||||||
|
34
go.mod
34
go.mod
@ -1,10 +1,10 @@
|
|||||||
module github.com/AdguardTeam/AdGuardDNS
|
module github.com/AdguardTeam/AdGuardDNS
|
||||||
|
|
||||||
go 1.23.2
|
go 1.23.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-20240607112746-5690301129fe
|
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-20240607112746-5690301129fe
|
||||||
github.com/AdguardTeam/golibs v0.30.1
|
github.com/AdguardTeam/golibs v0.30.4
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0
|
github.com/AdguardTeam/urlfilter v0.20.0
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||||
github.com/axiomhq/hyperloglog v0.2.0
|
github.com/axiomhq/hyperloglog v0.2.0
|
||||||
@ -19,15 +19,15 @@ require (
|
|||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||||
github.com/prometheus/client_golang v1.20.5
|
github.com/prometheus/client_golang v1.20.5
|
||||||
github.com/prometheus/client_model v0.6.1
|
github.com/prometheus/client_model v0.6.1
|
||||||
github.com/prometheus/common v0.60.0
|
github.com/prometheus/common v0.60.1
|
||||||
github.com/quic-go/quic-go v0.48.1
|
github.com/quic-go/quic-go v0.48.2
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/crypto v0.28.0
|
golang.org/x/crypto v0.30.0
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.32.0
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.28.0
|
||||||
golang.org/x/time v0.7.0
|
golang.org/x/time v0.8.0
|
||||||
google.golang.org/grpc v1.67.1
|
google.golang.org/grpc v1.68.0
|
||||||
google.golang.org/protobuf v1.35.1
|
google.golang.org/protobuf v1.35.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
@ -41,20 +41,20 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662 // indirect
|
github.com/google/pprof v0.0.0-20241203143554-1e3fdc7de467 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
|
github.com/onsi/ginkgo/v2 v2.22.0 // indirect
|
||||||
github.com/panjf2000/ants/v2 v2.10.0 // indirect
|
github.com/panjf2000/ants/v2 v2.10.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/tools v0.26.0 // indirect
|
golang.org/x/tools v0.28.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
70
go.sum
70
go.sum
@ -1,5 +1,5 @@
|
|||||||
github.com/AdguardTeam/golibs v0.30.1 h1:/yv7dq2h7WXw/jTDxkE3FP9zHerRT+i03PZRHJX4fPU=
|
github.com/AdguardTeam/golibs v0.30.4 h1:zfFX1v4hkOCz6BifkneiBW2PCwSK523kYNr+VwaFrIw=
|
||||||
github.com/AdguardTeam/golibs v0.30.1/go.mod h1:FkwcNQEJoGsgDGXcalrVa/4gWbE68KsmE2guXWtBQUE=
|
github.com/AdguardTeam/golibs v0.30.4/go.mod h1:Ir9dlHfb8nRQsG3Qgo1zoGL+k1qMbcBtb8tcnsvzdAE=
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
|
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
|
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
@ -37,12 +37,14 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
|||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s=
|
github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s=
|
||||||
github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
|
github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662 h1:SKMkD83p7FwUqKmBsPdLHF5dNyxq3jOWwu9w9UyH5vA=
|
github.com/google/pprof v0.0.0-20241203143554-1e3fdc7de467 h1:keEZFtbLJugfE0qHn+Ge1JCE71spzkchQobDf3mzS/4=
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
github.com/google/pprof v0.0.0-20241203143554-1e3fdc7de467/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
@ -59,10 +61,10 @@ github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
|||||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
||||||
github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8=
|
github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8=
|
||||||
@ -81,14 +83,14 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+
|
|||||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
|
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||||
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA=
|
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||||
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||||
@ -111,29 +113,29 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
|
|||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
37
go.work.sum
37
go.work.sum
@ -1,6 +1,7 @@
|
|||||||
cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w=
|
cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w=
|
||||||
cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
||||||
cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
|
||||||
|
cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
@ -161,6 +162,7 @@ github.com/AdguardTeam/golibs v0.25.3/go.mod h1:HaTyS2wCbxFudjht9N/+/Qf1b5cMad2B
|
|||||||
github.com/AdguardTeam/golibs v0.30.0/go.mod h1:vjw1OVZG6BYyoqGRY88U4LCJLOMfhBFhU0UJBdaSAuQ=
|
github.com/AdguardTeam/golibs v0.30.0/go.mod h1:vjw1OVZG6BYyoqGRY88U4LCJLOMfhBFhU0UJBdaSAuQ=
|
||||||
github.com/AdguardTeam/golibs v0.30.1 h1:/yv7dq2h7WXw/jTDxkE3FP9zHerRT+i03PZRHJX4fPU=
|
github.com/AdguardTeam/golibs v0.30.1 h1:/yv7dq2h7WXw/jTDxkE3FP9zHerRT+i03PZRHJX4fPU=
|
||||||
github.com/AdguardTeam/golibs v0.30.1/go.mod h1:FkwcNQEJoGsgDGXcalrVa/4gWbE68KsmE2guXWtBQUE=
|
github.com/AdguardTeam/golibs v0.30.1/go.mod h1:FkwcNQEJoGsgDGXcalrVa/4gWbE68KsmE2guXWtBQUE=
|
||||||
|
github.com/AdguardTeam/golibs v0.30.3/go.mod h1:Ir9dlHfb8nRQsG3Qgo1zoGL+k1qMbcBtb8tcnsvzdAE=
|
||||||
github.com/AdguardTeam/gomitmproxy v0.2.0 h1:rvCOf17pd1/CnMyMQW891zrEiIQBpQ8cIGjKN9pinUU=
|
github.com/AdguardTeam/gomitmproxy v0.2.0 h1:rvCOf17pd1/CnMyMQW891zrEiIQBpQ8cIGjKN9pinUU=
|
||||||
github.com/AdguardTeam/gomitmproxy v0.2.1 h1:p9gr8Er1TYvf+7ic81Ax1sZ62UNCsMTZNbm7tC59S9o=
|
github.com/AdguardTeam/gomitmproxy v0.2.1 h1:p9gr8Er1TYvf+7ic81Ax1sZ62UNCsMTZNbm7tC59S9o=
|
||||||
github.com/AdguardTeam/gomitmproxy v0.2.1/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
github.com/AdguardTeam/gomitmproxy v0.2.1/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
||||||
@ -251,6 +253,7 @@ github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido6
|
|||||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
|
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
|
||||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||||
github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
||||||
@ -367,8 +370,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
@ -401,6 +402,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
|
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
|
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
@ -488,6 +491,7 @@ github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw
|
|||||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
@ -572,6 +576,8 @@ github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3Ro
|
|||||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||||
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
|
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||||
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
@ -589,12 +595,14 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1
|
|||||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||||
|
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||||
|
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||||
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||||
@ -739,6 +747,7 @@ go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8p
|
|||||||
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
|
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
|
||||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||||
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM=
|
go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d h1:E2M5QgjZ/Jg+ObCQAudsXxuTsLj7Nl5RV/lZcQZmKSo=
|
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d h1:E2M5QgjZ/Jg+ObCQAudsXxuTsLj7Nl5RV/lZcQZmKSo=
|
||||||
@ -758,6 +767,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
|||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
@ -769,6 +780,8 @@ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQ
|
|||||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||||
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||||
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
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=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -784,6 +797,7 @@ golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -820,6 +834,9 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|||||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
|
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
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-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -852,6 +869,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -889,6 +908,9 @@ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g=
|
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g=
|
||||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
||||||
@ -925,6 +947,8 @@ golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
|||||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||||
|
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||||
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
@ -938,6 +962,9 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
@ -963,7 +990,11 @@ golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc
|
|||||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
|
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||||
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
|
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1014,6 +1045,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||||
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8=
|
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||||
@ -1044,6 +1076,7 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
|||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
|
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
|
||||||
|
@ -2,17 +2,13 @@ package agd_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testutil.DiscardLogOutput(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common long strings for tests.
|
// Common long strings for tests.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Move to a new validation package.
|
||||||
var (
|
var (
|
||||||
testLongStr = strings.Repeat("a", 200)
|
testLongStr = strings.Repeat("a", 200)
|
||||||
testLongStrUnicode = strings.Repeat("ы", 200)
|
testLongStrUnicode = strings.Repeat("ы", 200)
|
||||||
|
@ -34,7 +34,8 @@ func TestNewDeviceName(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
name: "too_long_unicode",
|
name: "too_long_unicode",
|
||||||
in: testLongStrUnicode,
|
in: testLongStrUnicode,
|
||||||
wantErrMsg: `bad device name "` + testLongStrUnicode + `": too long: got 200 runes, max 128`,
|
wantErrMsg: `bad device name "` + testLongStrUnicode +
|
||||||
|
`": too long: got 200 runes, max 128`,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
28
internal/agd/filteringgroup.go
Normal file
28
internal/agd/filteringgroup.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package agd
|
||||||
|
|
||||||
|
import "github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
|
|
||||||
|
// FilteringGroup represents a set of filtering settings.
|
||||||
|
type FilteringGroup struct {
|
||||||
|
// FilterConfig is the configuration of the filters used for this filtering
|
||||||
|
// group. It must not be nil.
|
||||||
|
FilterConfig *filter.ConfigGroup
|
||||||
|
|
||||||
|
// ID is the unique ID of this filtering group. It must be set.
|
||||||
|
ID FilteringGroupID
|
||||||
|
|
||||||
|
// BlockChromePrefetch shows if the Chrome prefetch proxy feature should be
|
||||||
|
// disabled for requests using this filtering group.
|
||||||
|
BlockChromePrefetch bool
|
||||||
|
|
||||||
|
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
||||||
|
// requests using this filtering group.
|
||||||
|
BlockFirefoxCanary bool
|
||||||
|
|
||||||
|
// BlockPrivateRelay shows if Apple Private Relay is blocked for requests
|
||||||
|
// using this filtering group.
|
||||||
|
BlockPrivateRelay bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilteringGroupID is the ID of a filter group. It is an opaque string.
|
||||||
|
type FilteringGroupID string
|
@ -1,173 +0,0 @@
|
|||||||
package agd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FilterListID is the ID of a filter list. It is an opaque string.
|
|
||||||
type FilterListID string
|
|
||||||
|
|
||||||
// Special FilterListID values shared across the AdGuard DNS system.
|
|
||||||
//
|
|
||||||
// DO NOT change these as other parts of the system depend on these values.
|
|
||||||
const (
|
|
||||||
// FilterListIDNone means that no filter were applied at all.
|
|
||||||
FilterListIDNone FilterListID = ""
|
|
||||||
|
|
||||||
// FilterListIDBlockedService is the shared filter-list ID used when a
|
|
||||||
// request was blocked by the service blocker.
|
|
||||||
FilterListIDBlockedService FilterListID = "blocked_service"
|
|
||||||
|
|
||||||
// FilterListIDCustom is the special shared filter-list ID used when
|
|
||||||
// a request was filtered by a custom profile rule.
|
|
||||||
FilterListIDCustom FilterListID = "custom"
|
|
||||||
|
|
||||||
// FilterListIDAdultBlocking is the special shared filter-list ID used when
|
|
||||||
// a request was filtered by the adult content blocking filter.
|
|
||||||
FilterListIDAdultBlocking FilterListID = "adult_blocking"
|
|
||||||
|
|
||||||
// FilterListIDSafeBrowsing is the special shared filter-list ID used when
|
|
||||||
// a request was filtered by the safe browsing filter.
|
|
||||||
FilterListIDSafeBrowsing FilterListID = "safe_browsing"
|
|
||||||
|
|
||||||
// FilterListIDNewRegDomains is the special shared filter-list ID used when
|
|
||||||
// a request was filtered by the newly registered domains filter.
|
|
||||||
FilterListIDNewRegDomains FilterListID = "newly_registered_domains"
|
|
||||||
|
|
||||||
// FilterListIDGeneralSafeSearch is the shared filter-list ID used when
|
|
||||||
// a request was modified by the general safe search filter.
|
|
||||||
FilterListIDGeneralSafeSearch FilterListID = "general_safe_search"
|
|
||||||
|
|
||||||
// FilterListIDYoutubeSafeSearch is the special shared filter-list ID used
|
|
||||||
// when a request was modified by the YouTube safe search filter.
|
|
||||||
FilterListIDYoutubeSafeSearch FilterListID = "youtube_safe_search"
|
|
||||||
|
|
||||||
// FilterListIDAdGuardDNS is the special filter-list ID of the main AdGuard
|
|
||||||
// DNS filtering-rule list. For this list, rule statistics are collected.
|
|
||||||
FilterListIDAdGuardDNS FilterListID = "adguard_dns_filter"
|
|
||||||
|
|
||||||
// FilterListIDAdGuardPopup is the special filter-list ID of the AdGuard DNS
|
|
||||||
// list of popup domains.
|
|
||||||
FilterListIDAdGuardPopup FilterListID = "adguard_popup_filter"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The maximum and minimum lengths of a filter list ID.
|
|
||||||
const (
|
|
||||||
MaxFilterListIDLen = 128
|
|
||||||
MinFilterListIDLen = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewFilterListID converts a simple string into a FilterListID and makes sure
|
|
||||||
// that it's valid. This should be preferred to a simple type conversion.
|
|
||||||
func NewFilterListID(s string) (id FilterListID, err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "bad filter list id %q: %w", s) }()
|
|
||||||
|
|
||||||
err = ValidateInclusion(len(s), MaxFilterListIDLen, MinFilterListIDLen, UnitByte)
|
|
||||||
if err != nil {
|
|
||||||
return FilterListIDNone, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow only the printable, non-whitespace ASCII characters. Technically
|
|
||||||
// we only need to exclude carriage return, line feed, and slash characters,
|
|
||||||
// but let's be more strict just in case.
|
|
||||||
if i, r := firstNonIDRune(s, true); i != -1 {
|
|
||||||
return FilterListIDNone, fmt.Errorf("bad rune %q at index %d", r, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return FilterListID(s), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportsDNSRewrite returns true if the $dnsrewrite rules in filtering-rule
|
|
||||||
// lists with this ID should be processed.
|
|
||||||
func (id FilterListID) SupportsDNSRewrite() (ok bool) {
|
|
||||||
switch id {
|
|
||||||
case
|
|
||||||
FilterListIDAdGuardPopup,
|
|
||||||
FilterListIDCustom,
|
|
||||||
FilterListIDGeneralSafeSearch,
|
|
||||||
FilterListIDYoutubeSafeSearch:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterRuleText is the text of a single rule within a filter.
|
|
||||||
type FilterRuleText string
|
|
||||||
|
|
||||||
// MaxFilterRuleTextRuneLen is the maximum length of a filter rule in runes.
|
|
||||||
const MaxFilterRuleTextRuneLen = 1024
|
|
||||||
|
|
||||||
// NewFilterRuleText converts a simple string into a FilterRuleText and makes
|
|
||||||
// sure that it's valid. This should be preferred to a simple type conversion.
|
|
||||||
func NewFilterRuleText(s string) (t FilterRuleText, err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "bad filter rule text %q: %w", s) }()
|
|
||||||
|
|
||||||
err = ValidateInclusion(utf8.RuneCountInString(s), MaxFilterRuleTextRuneLen, 0, UnitRune)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return FilterRuleText(s), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilteringGroup represents a set of filtering settings.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Consider making it closer to the config file and the backend
|
|
||||||
// response by grouping parental, rule list, and safe browsing settings into
|
|
||||||
// separate structs.
|
|
||||||
type FilteringGroup struct {
|
|
||||||
// ID is the unique ID of this filtering group.
|
|
||||||
ID FilteringGroupID
|
|
||||||
|
|
||||||
// RuleListIDs are the filtering rule list IDs used for this filtering
|
|
||||||
// group. They are ignored if RuleListsEnabled is false.
|
|
||||||
RuleListIDs []FilterListID
|
|
||||||
|
|
||||||
// RuleListsEnabled shows whether the rule-list based filtering is enabled.
|
|
||||||
// This must be true in order for all parameters below to work.
|
|
||||||
RuleListsEnabled bool
|
|
||||||
|
|
||||||
// ParentalEnabled shows whether the parental protection functionality is
|
|
||||||
// enabled. This must be true in order for all parameters below to
|
|
||||||
// work.
|
|
||||||
ParentalEnabled bool
|
|
||||||
|
|
||||||
// BlockAdult shows whether the adult content blocking safe browsing
|
|
||||||
// filtering should be enforced.
|
|
||||||
BlockAdult bool
|
|
||||||
|
|
||||||
// SafeBrowsingEnabled shows whether the general safe browsing filtering
|
|
||||||
// should be enforced.
|
|
||||||
SafeBrowsingEnabled bool
|
|
||||||
|
|
||||||
// BlockDangerousDomains shows whether the dangerous domains safe browsing
|
|
||||||
// filtering should be enforced.
|
|
||||||
BlockDangerousDomains bool
|
|
||||||
|
|
||||||
// BlockNewlyRegisteredDomains shows whether the newly registered domains
|
|
||||||
// safe browsing filtering should be enforced.
|
|
||||||
BlockNewlyRegisteredDomains bool
|
|
||||||
|
|
||||||
// GeneralSafeSearch shows whether the general safe search filtering should
|
|
||||||
// be enforced.
|
|
||||||
GeneralSafeSearch bool
|
|
||||||
|
|
||||||
// YoutubeSafeSearch shows whether the YouTube safe search filtering should
|
|
||||||
// be enforced.
|
|
||||||
YoutubeSafeSearch bool
|
|
||||||
|
|
||||||
// BlockPrivateRelay shows if Apple Private Relay is blocked for requests
|
|
||||||
// using this filtering group.
|
|
||||||
BlockPrivateRelay bool
|
|
||||||
|
|
||||||
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
|
||||||
// requests using this filtering group.
|
|
||||||
BlockFirefoxCanary bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilteringGroupID is the ID of a filter group. It is an opaque string.
|
|
||||||
type FilteringGroupID string
|
|
@ -2,13 +2,11 @@ package agd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Profile contains information about an AdGuard DNS profile. In other parts of
|
// Profile contains information about an AdGuard DNS profile. In other parts of
|
||||||
@ -17,141 +15,62 @@ import (
|
|||||||
//
|
//
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
// NOTE: Do not change fields of this structure without incrementing
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
// [internal/profiledb/internal.FileCacheVersion].
|
||||||
//
|
|
||||||
// TODO(a.garipov): Consider making it closer to the config file and the backend
|
|
||||||
// response by grouping parental, rule list, and safe browsing settings into
|
|
||||||
// separate structs.
|
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
// Parental are the parental settings for this profile. They are ignored if
|
// FilterConfig is the configuration of the filters used for this profile
|
||||||
// FilteringEnabled is set to false.
|
// and all its devices that don't have filtering disabled. It must not be
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
Parental *ParentalProtectionSettings
|
|
||||||
|
|
||||||
// Ratelimiter is the custom ratelimiter for this profile. It must not be
|
|
||||||
// nil.
|
// nil.
|
||||||
//
|
FilterConfig *filter.ConfigClient
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
Ratelimiter Ratelimiter
|
|
||||||
|
|
||||||
// SafeBrowsing are the safe browsing settings for this profile. They are
|
|
||||||
// ignored if FilteringEnabled is set to false.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
SafeBrowsing *SafeBrowsingSettings
|
|
||||||
|
|
||||||
// Access is the access manager for this profile. It must not be nil.
|
// Access is the access manager for this profile. It must not be nil.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
Access access.Profile
|
Access access.Profile
|
||||||
|
|
||||||
// BlockingMode defines the way blocked responses are constructed. It must
|
// BlockingMode defines the way blocked responses are constructed. It must
|
||||||
// not be nil.
|
// not be nil.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
BlockingMode dnsmsg.BlockingMode
|
BlockingMode dnsmsg.BlockingMode
|
||||||
|
|
||||||
|
// Ratelimiter is the custom ratelimiter for this profile. It must not be
|
||||||
|
// nil.
|
||||||
|
Ratelimiter Ratelimiter
|
||||||
|
|
||||||
// ID is the unique ID of this profile. It must not be empty.
|
// ID is the unique ID of this profile. It must not be empty.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
ID ProfileID
|
ID ProfileID
|
||||||
|
|
||||||
// UpdateTime shows the last time this profile was updated from the backend.
|
|
||||||
// This is NOT the time of update in the backend's database, since the
|
|
||||||
// backend doesn't send this information.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
UpdateTime time.Time
|
|
||||||
|
|
||||||
// DeviceIDs are the IDs of devices attached to this profile.
|
// DeviceIDs are the IDs of devices attached to this profile.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
DeviceIDs []DeviceID
|
DeviceIDs []DeviceID
|
||||||
|
|
||||||
// RuleListIDs are the IDs of the filtering rule lists enabled for this
|
|
||||||
// profile. They are ignored if FilteringEnabled or RuleListsEnabled are
|
|
||||||
// set to false.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
RuleListIDs []FilterListID
|
|
||||||
|
|
||||||
// CustomRules are the custom filtering rules for this profile. They are
|
|
||||||
// ignored if RuleListsEnabled is set to false.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
CustomRules []FilterRuleText
|
|
||||||
|
|
||||||
// FilteredResponseTTL is the time-to-live value used for responses sent to
|
// FilteredResponseTTL is the time-to-live value used for responses sent to
|
||||||
// the devices of this profile.
|
// the devices of this profile.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
FilteredResponseTTL time.Duration
|
FilteredResponseTTL time.Duration
|
||||||
|
|
||||||
// FilteringEnabled defines whether queries from devices of this profile
|
|
||||||
// should be filtered in any way at all.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
FilteringEnabled bool
|
|
||||||
|
|
||||||
// RuleListsEnabled defines whether queries from devices of this profile
|
|
||||||
// should be filtered using the filtering rule lists in RuleListIDs.
|
|
||||||
// Requires FilteringEnabled to be set to true.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
RuleListsEnabled bool
|
|
||||||
|
|
||||||
// QueryLogEnabled defines whether query logs should be saved for the
|
|
||||||
// devices of this profile.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
QueryLogEnabled bool
|
|
||||||
|
|
||||||
// Deleted shows if this profile is deleted.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
Deleted bool
|
|
||||||
|
|
||||||
// BlockPrivateRelay shows if Apple Private Relay queries are blocked for
|
|
||||||
// requests from all devices in this profile.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
BlockPrivateRelay bool
|
|
||||||
|
|
||||||
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
|
||||||
// requests from all devices in this profile.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
BlockFirefoxCanary bool
|
|
||||||
|
|
||||||
// IPLogEnabled shows if client IP addresses are logged.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
IPLogEnabled bool
|
|
||||||
|
|
||||||
// AutoDevicesEnabled shows if the automatic creation of devices using
|
// AutoDevicesEnabled shows if the automatic creation of devices using
|
||||||
// HumanIDs should be enabled for this profile.
|
// HumanIDs should be enabled for this profile.
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
AutoDevicesEnabled bool
|
AutoDevicesEnabled bool
|
||||||
|
|
||||||
|
// BlockChromePrefetch shows if the Chrome prefetch proxy feature should be
|
||||||
|
// forced into preflight mode for all devices in this profile.
|
||||||
|
BlockChromePrefetch bool
|
||||||
|
|
||||||
|
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
||||||
|
// requests from all devices in this profile.
|
||||||
|
BlockFirefoxCanary bool
|
||||||
|
|
||||||
|
// BlockPrivateRelay shows if Apple Private Relay queries are blocked for
|
||||||
|
// requests from all devices in this profile.
|
||||||
|
BlockPrivateRelay bool
|
||||||
|
|
||||||
|
// Deleted shows if this profile is deleted.
|
||||||
|
Deleted bool
|
||||||
|
|
||||||
|
// FilteringEnabled defines whether queries from devices of this profile
|
||||||
|
// should be filtered in any way at all.
|
||||||
|
FilteringEnabled bool
|
||||||
|
|
||||||
|
// IPLogEnabled shows if client IP addresses are logged.
|
||||||
|
IPLogEnabled bool
|
||||||
|
|
||||||
|
// QueryLogEnabled defines whether query logs should be saved for the
|
||||||
|
// devices of this profile.
|
||||||
|
QueryLogEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProfileID is the ID of a profile. It is an opaque string.
|
// ProfileID is the ID of a profile. It is an opaque string.
|
||||||
@ -179,165 +98,3 @@ func NewProfileID(s string) (id ProfileID, err error) {
|
|||||||
|
|
||||||
return ProfileID(s), nil
|
return ProfileID(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DayRange is a range within a single day. Start and End are minutes from the
|
|
||||||
// start of day, with 0 being 00:00:00.(0) and 1439, 23:59:59.(9).
|
|
||||||
//
|
|
||||||
// Additionally, if both Start and End are set to [math.MaxUint16], the range is
|
|
||||||
// a special zero-length range. This is needed, because when both Start and End
|
|
||||||
// are zero, such DayRange indicates one minute after midnight; as well as to
|
|
||||||
// reduce the amount of pointers and thus GC time.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Refactor. See AGDNS-1516.
|
|
||||||
type DayRange struct {
|
|
||||||
Start uint16
|
|
||||||
End uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxDayRangeMinutes is the maximum value for DayRange.Start and DayRange.End
|
|
||||||
// fields, excluding the zero-length range ones.
|
|
||||||
const MaxDayRangeMinutes = 24*60 - 1
|
|
||||||
|
|
||||||
// ZeroLengthDayRange returns a new zero-length day range.
|
|
||||||
func ZeroLengthDayRange() (r DayRange) {
|
|
||||||
return DayRange{
|
|
||||||
Start: math.MaxUint16,
|
|
||||||
End: math.MaxUint16,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZeroLength returns true if r is a zero-length range.
|
|
||||||
func (r DayRange) IsZeroLength() (ok bool) {
|
|
||||||
return r.Start == math.MaxUint16 && r.End == math.MaxUint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate returns the day range validation errors, if any.
|
|
||||||
func (r DayRange) Validate() (err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "bad day range: %w") }()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case r.IsZeroLength():
|
|
||||||
return nil
|
|
||||||
case r.End < r.Start:
|
|
||||||
return fmt.Errorf("end %d less than start %d", r.End, r.Start)
|
|
||||||
case r.Start > MaxDayRangeMinutes:
|
|
||||||
return fmt.Errorf("start %d greater than %d", r.Start, MaxDayRangeMinutes)
|
|
||||||
case r.End > MaxDayRangeMinutes:
|
|
||||||
return fmt.Errorf("end %d greater than %d", r.End, MaxDayRangeMinutes)
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WeeklySchedule is a schedule for one week. The index is the same as
|
|
||||||
// time.Weekday values. That is, 0 is Sunday, 1 is Monday, etc. An empty
|
|
||||||
// DayRange means that there is no schedule for this day.
|
|
||||||
type WeeklySchedule [7]DayRange
|
|
||||||
|
|
||||||
// ParentalProtectionSchedule is the schedule of a client's parental protection.
|
|
||||||
// All fields must not be nil.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
type ParentalProtectionSchedule struct {
|
|
||||||
// Week is the parental protection schedule for every day of the week.
|
|
||||||
Week *WeeklySchedule
|
|
||||||
|
|
||||||
// TimeZone is the profile's time zone.
|
|
||||||
TimeZone *agdtime.Location
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains returns true if t is within the allowed schedule.
|
|
||||||
func (s *ParentalProtectionSchedule) Contains(t time.Time) (ok bool) {
|
|
||||||
t = t.In(&s.TimeZone.Location)
|
|
||||||
r := s.Week[int(t.Weekday())]
|
|
||||||
if r.IsZeroLength() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
day := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, &s.TimeZone.Location)
|
|
||||||
start := day.Add(time.Duration(r.Start) * time.Minute)
|
|
||||||
end := day.Add(time.Duration(r.End+1)*time.Minute - 1*time.Nanosecond)
|
|
||||||
|
|
||||||
return !t.Before(start) && !t.After(end)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParentalProtectionSettings are the parental protection settings of a profile.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
type ParentalProtectionSettings struct {
|
|
||||||
Schedule *ParentalProtectionSchedule
|
|
||||||
|
|
||||||
// BlockedServices are the IDs of the services blocked for this profile.
|
|
||||||
BlockedServices []BlockedServiceID
|
|
||||||
|
|
||||||
// Enabled tells whether the parental protection should be enabled at all.
|
|
||||||
// This must be true in order for all parameters below to work.
|
|
||||||
Enabled bool
|
|
||||||
|
|
||||||
// BlockAdult tells if AdGuard DNS should enforce blocking of adult content
|
|
||||||
// using the safe browsing filter.
|
|
||||||
BlockAdult bool
|
|
||||||
|
|
||||||
// GeneralSafeSearch tells if AdGuard DNS should enforce general safe search
|
|
||||||
// in most search engines.
|
|
||||||
GeneralSafeSearch bool
|
|
||||||
|
|
||||||
// YoutubeSafeSearch tells if AdGuard DNS should enforce safe search on
|
|
||||||
// YouTube.
|
|
||||||
YoutubeSafeSearch bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// SafeBrowsingSettings are the safe browsing settings of a profile.
|
|
||||||
//
|
|
||||||
// NOTE: Do not change fields of this structure without incrementing
|
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
|
||||||
type SafeBrowsingSettings struct {
|
|
||||||
// Enabled defines whether queries from devices of this profile should be
|
|
||||||
// filtered using the safe browsing filter. This must be true in order for
|
|
||||||
// all parameters below to work.
|
|
||||||
Enabled bool
|
|
||||||
|
|
||||||
// BlockDangerousDomains shows whether the dangerous domains safe browsing
|
|
||||||
// filtering should be enforced.
|
|
||||||
BlockDangerousDomains bool
|
|
||||||
|
|
||||||
// BlockNewlyRegisteredDomains shows whether the newly registered domains
|
|
||||||
// safe browsing filtering should be enforced.
|
|
||||||
BlockNewlyRegisteredDomains bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockedServiceID is the ID of a blocked service. While these are usually
|
|
||||||
// human-readable, clients should treat them as opaque strings.
|
|
||||||
//
|
|
||||||
// When a request is blocked by the service blocker, this ID is used as the
|
|
||||||
// text of the blocking rule.
|
|
||||||
type BlockedServiceID string
|
|
||||||
|
|
||||||
// The maximum and minimum lengths of a blocked service ID.
|
|
||||||
const (
|
|
||||||
MaxBlockedServiceIDLen = 64
|
|
||||||
MinBlockedServiceIDLen = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewBlockedServiceID converts a simple string into a BlockedServiceID and
|
|
||||||
// makes sure that it's valid. This should be preferred to a simple type
|
|
||||||
// conversion.
|
|
||||||
func NewBlockedServiceID(s string) (id BlockedServiceID, err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "bad blocked service id %q: %w", s) }()
|
|
||||||
|
|
||||||
err = ValidateInclusion(len(s), MaxBlockedServiceIDLen, MinBlockedServiceIDLen, UnitByte)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow only the printable, non-whitespace ASCII characters. Technically
|
|
||||||
// we only need to exclude carriage return, line feed, and slash characters,
|
|
||||||
// but let's be more strict just in case.
|
|
||||||
if i, r := firstNonIDRune(s, true); i != -1 {
|
|
||||||
return "", fmt.Errorf("bad char %q at index %d", r, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return BlockedServiceID(s), nil
|
|
||||||
}
|
|
||||||
|
@ -63,7 +63,7 @@ func (GlobalRatelimiter) Config() (_ *RatelimitConfig) { return &RatelimitConfig
|
|||||||
// CountResponses implements the [Ratelimiter] interface for GlobalRatelimiter.
|
// CountResponses implements the [Ratelimiter] interface for GlobalRatelimiter.
|
||||||
func (GlobalRatelimiter) CountResponses(_ context.Context, _ *dns.Msg, _ netip.Addr) {}
|
func (GlobalRatelimiter) CountResponses(_ context.Context, _ *dns.Msg, _ netip.Addr) {}
|
||||||
|
|
||||||
// DefaultRatelimiter is the default [Ratelimiter] impelentation.
|
// DefaultRatelimiter is the default [Ratelimiter] implementation.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Add tests.
|
// TODO(a.garipov): Add tests.
|
||||||
type DefaultRatelimiter struct {
|
type DefaultRatelimiter struct {
|
||||||
|
@ -19,7 +19,7 @@ type Server struct {
|
|||||||
DNSCrypt *DNSCryptConfig
|
DNSCrypt *DNSCryptConfig
|
||||||
|
|
||||||
// TLS is the TLS configuration for this server, if any.
|
// TLS is the TLS configuration for this server, if any.
|
||||||
TLS *tls.Config
|
TLS *TLSConfig
|
||||||
|
|
||||||
// QUICConf is the QUIC configuration for this server.
|
// QUICConf is the QUIC configuration for this server.
|
||||||
QUICConf *QUICConfig
|
QUICConf *QUICConfig
|
||||||
@ -200,3 +200,13 @@ type QUICConfig struct {
|
|||||||
// QUICLimitsEnabled, if true, enables QUIC limiting.
|
// QUICLimitsEnabled, if true, enables QUIC limiting.
|
||||||
QUICLimitsEnabled bool
|
QUICLimitsEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TLSConfig is the TLS configuration of a DNS server. Metrics and ALPs must be
|
||||||
|
// set for saved configurations.
|
||||||
|
type TLSConfig struct {
|
||||||
|
// Default is the defult TLS configuration. It must not be nil.
|
||||||
|
Default *tls.Config
|
||||||
|
|
||||||
|
// H3 is the TLS configuration for DoH3.
|
||||||
|
H3 *tls.Config
|
||||||
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package agd
|
package agd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/container"
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
@ -14,10 +12,11 @@ type ServerGroup struct {
|
|||||||
// Resolvers (DDR) handlers. DDR must not be nil.
|
// Resolvers (DDR) handlers. DDR must not be nil.
|
||||||
DDR *DDR
|
DDR *DDR
|
||||||
|
|
||||||
// TLS are the TLS settings for this server group. If Servers contains at
|
// DeviceDomains is the list of domain names used to detect device IDs from
|
||||||
// least one server with a non-plain protocol (see [Protocol.IsPlain]), TLS
|
// clients' server names.
|
||||||
// must not be nil.
|
//
|
||||||
TLS *TLS
|
// TODO(s.chzhen): Consider using a custom type.
|
||||||
|
DeviceDomains []string
|
||||||
|
|
||||||
// Name is the unique name of the server group.
|
// Name is the unique name of the server group.
|
||||||
Name ServerGroupName
|
Name ServerGroupName
|
||||||
@ -36,20 +35,6 @@ type ServerGroup struct {
|
|||||||
// ServerGroupName is the name of a server group.
|
// ServerGroupName is the name of a server group.
|
||||||
type ServerGroupName string
|
type ServerGroupName string
|
||||||
|
|
||||||
// TLS is the TLS configuration of a DNS server group.
|
|
||||||
type TLS struct {
|
|
||||||
// Conf is the server's TLS configuration.
|
|
||||||
Conf *tls.Config
|
|
||||||
|
|
||||||
// DeviceDomains are the domain names used to detect device IDs from
|
|
||||||
// clients' server names.
|
|
||||||
DeviceDomains []string
|
|
||||||
|
|
||||||
// SessionKeys are paths to files containing the TLS session keys for this
|
|
||||||
// server.
|
|
||||||
SessionKeys []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// DDR is the configuration for the server group's Discovery Of Designated
|
// DDR is the configuration for the server group's Discovery Of Designated
|
||||||
// Resolvers (DDR) handlers.
|
// Resolvers (DDR) handlers.
|
||||||
type DDR struct {
|
type DDR struct {
|
||||||
|
@ -10,7 +10,11 @@ import (
|
|||||||
|
|
||||||
// LRUConfig is a configuration structure of a cache.
|
// LRUConfig is a configuration structure of a cache.
|
||||||
type LRUConfig struct {
|
type LRUConfig struct {
|
||||||
Size int
|
// Count is the maximum number of elements to keep in the cache. It must be
|
||||||
|
// positive.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Make uint64.
|
||||||
|
Count int
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRU is an [Interface] implementation.
|
// LRU is an [Interface] implementation.
|
||||||
@ -21,7 +25,7 @@ type LRU[K, T any] struct {
|
|||||||
// NewLRU returns a new initialized LRU cache.
|
// NewLRU returns a new initialized LRU cache.
|
||||||
func NewLRU[K, T any](conf *LRUConfig) (c *LRU[K, T]) {
|
func NewLRU[K, T any](conf *LRUConfig) (c *LRU[K, T]) {
|
||||||
return &LRU[K, T]{
|
return &LRU[K, T]{
|
||||||
cache: gcache.New(conf.Size).LRU().Build(),
|
cache: gcache.New(conf.Count).LRU().Build(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ func TestLRU(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
||||||
Size: 10,
|
Count: 10,
|
||||||
})
|
})
|
||||||
|
|
||||||
cache.Set(key, val)
|
cache.Set(key, val)
|
||||||
|
@ -5,16 +5,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testutil.DiscardLogOutput(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPasswordHashBcrypt_Authenticate(t *testing.T) {
|
func TestPasswordHashBcrypt_Authenticate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -22,6 +22,18 @@ type Refresher interface {
|
|||||||
Refresh(ctx context.Context) (err error)
|
Refresh(ctx context.Context) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefresherFunc is an adapter to allow the use of ordinary functions as
|
||||||
|
// [Refresher].
|
||||||
|
type RefresherFunc func(ctx context.Context) (err error)
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Refresher = RefresherFunc(nil)
|
||||||
|
|
||||||
|
// Refresh implements the [Refresher] interface for RefresherFunc.
|
||||||
|
func (f RefresherFunc) Refresh(ctx context.Context) (err error) {
|
||||||
|
return f(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// RefreshWorker is an [Interface] implementation that updates its [Refresher]
|
// RefreshWorker is an [Interface] implementation that updates its [Refresher]
|
||||||
// every tick of the provided ticker.
|
// every tick of the provided ticker.
|
||||||
type RefreshWorker struct {
|
type RefreshWorker struct {
|
||||||
|
@ -96,9 +96,9 @@ func TestRefreshWorker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("error", func(t *testing.T) {
|
t.Run("error", func(t *testing.T) {
|
||||||
errRefr, syncCh := newTestRefresher(t, testError)
|
refrWithError, syncCh := newTestRefresher(t, testError)
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvl, false))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, refrWithError, testIvl, false))
|
||||||
|
|
||||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -110,9 +110,9 @@ func TestRefreshWorker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("error_on_shutdown", func(t *testing.T) {
|
t.Run("error_on_shutdown", func(t *testing.T) {
|
||||||
errRefr, syncCh := newTestRefresher(t, testError)
|
refrWithError, syncCh := newTestRefresher(t, testError)
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvlLong, true))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, refrWithError, testIvlLong, true))
|
||||||
|
|
||||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
||||||
@ -111,6 +112,21 @@ func (r *Refresher) Refresh(ctx context.Context) (err error) {
|
|||||||
return r.OnRefresh(ctx)
|
return r.OnRefresh(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Package agdtime
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ agdtime.Clock = (*Clock)(nil)
|
||||||
|
|
||||||
|
// Clock is a [agdtime.Clock] for tests.
|
||||||
|
type Clock struct {
|
||||||
|
OnNow func() (now time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now implements the [agdtime.Clock] interface for *Clock.
|
||||||
|
func (c *Clock) Now() (now time.Time) {
|
||||||
|
return c.OnNow()
|
||||||
|
}
|
||||||
|
|
||||||
// Package billstat
|
// Package billstat
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
@ -220,34 +236,24 @@ var _ filter.Interface = (*Filter)(nil)
|
|||||||
|
|
||||||
// Filter is a [filter.Interface] for tests.
|
// Filter is a [filter.Interface] for tests.
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
OnFilterRequest func(
|
OnFilterRequest func(ctx context.Context, req *filter.Request) (r filter.Result, err error)
|
||||||
ctx context.Context,
|
OnFilterResponse func(ctx context.Context, resp *filter.Response) (r filter.Result, err error)
|
||||||
req *dns.Msg,
|
|
||||||
ri *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error)
|
|
||||||
OnFilterResponse func(
|
|
||||||
ctx context.Context,
|
|
||||||
resp *dns.Msg,
|
|
||||||
ri *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterRequest implements the [filter.Interface] interface for *Filter.
|
// FilterRequest implements the [filter.Interface] interface for *Filter.
|
||||||
func (f *Filter) FilterRequest(
|
func (f *Filter) FilterRequest(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *dns.Msg,
|
req *filter.Request,
|
||||||
ri *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return f.OnFilterRequest(ctx, req, ri)
|
return f.OnFilterRequest(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterResponse implements the [filter.Interface] interface for *Filter.
|
// FilterResponse implements the [filter.Interface] interface for *Filter.
|
||||||
func (f *Filter) FilterResponse(
|
func (f *Filter) FilterResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
resp *dns.Msg,
|
resp *filter.Response,
|
||||||
ri *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return f.OnFilterResponse(ctx, resp, ri)
|
return f.OnFilterResponse(ctx, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
@ -274,21 +280,18 @@ var _ filter.Storage = (*FilterStorage)(nil)
|
|||||||
|
|
||||||
// FilterStorage is a [filter.Storage] for tests.
|
// FilterStorage is a [filter.Storage] for tests.
|
||||||
type FilterStorage struct {
|
type FilterStorage struct {
|
||||||
OnFilterFromContext func(ctx context.Context, ri *agd.RequestInfo) (f filter.Interface)
|
OnForConfig func(ctx context.Context, c filter.Config) (f filter.Interface)
|
||||||
OnHasListID func(id agd.FilterListID) (ok bool)
|
OnHasListID func(id filter.ID) (ok bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterFromContext implements the [filter.Storage] interface for
|
// ForConfig implements the [filter.Storage] interface for
|
||||||
// *FilterStorage.
|
// *FilterStorage.
|
||||||
func (s *FilterStorage) FilterFromContext(
|
func (s *FilterStorage) ForConfig(ctx context.Context, c filter.Config) (f filter.Interface) {
|
||||||
ctx context.Context,
|
return s.OnForConfig(ctx, c)
|
||||||
ri *agd.RequestInfo,
|
|
||||||
) (f filter.Interface) {
|
|
||||||
return s.OnFilterFromContext(ctx, ri)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasListID implements the [filter.Storage] interface for *FilterStorage.
|
// HasListID implements the [filter.Storage] interface for *FilterStorage.
|
||||||
func (s *FilterStorage) HasListID(id agd.FilterListID) (ok bool) {
|
func (s *FilterStorage) HasListID(id filter.ID) (ok bool) {
|
||||||
return s.OnHasListID(id)
|
return s.OnHasListID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,11 +525,11 @@ var _ rulestat.Interface = (*RuleStat)(nil)
|
|||||||
|
|
||||||
// RuleStat is a [rulestat.Interface] for tests.
|
// RuleStat is a [rulestat.Interface] for tests.
|
||||||
type RuleStat struct {
|
type RuleStat struct {
|
||||||
OnCollect func(ctx context.Context, id agd.FilterListID, text agd.FilterRuleText)
|
OnCollect func(ctx context.Context, id filter.ID, text filter.RuleText)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect implements the [rulestat.Interface] interface for *RuleStat.
|
// Collect implements the [rulestat.Interface] interface for *RuleStat.
|
||||||
func (s *RuleStat) Collect(ctx context.Context, id agd.FilterListID, text agd.FilterRuleText) {
|
func (s *RuleStat) Collect(ctx context.Context, id filter.ID, text filter.RuleText) {
|
||||||
s.OnCollect(ctx, id, text)
|
s.OnCollect(ctx, id, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,24 @@ import (
|
|||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Clock is an interface for time-related operations.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Expand with operations like After or Tick.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Move to golibs/timeutil.
|
||||||
|
type Clock interface {
|
||||||
|
Now() (now time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SystemClock is a [Clock] that uses the functions from package time.
|
||||||
|
type SystemClock struct{}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Clock = SystemClock{}
|
||||||
|
|
||||||
|
// Now implements the [Clock] interface for SystemClock.
|
||||||
|
func (SystemClock) Now() (now time.Time) { return time.Now() }
|
||||||
|
|
||||||
// Location is a wrapper around time.Location that can de/serialize itself from
|
// Location is a wrapper around time.Location that can de/serialize itself from
|
||||||
// and to JSON.
|
// and to JSON.
|
||||||
//
|
//
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
|
||||||
"github.com/AdguardTeam/golibs/httphdr"
|
"github.com/AdguardTeam/golibs/httphdr"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
@ -41,11 +40,6 @@ func newClient(apiURL *url.URL) (client *grpc.ClientConn, err error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// reportf is a helper method for reporting non-critical errors.
|
|
||||||
func reportf(ctx context.Context, errColl errcoll.Interface, format string, args ...any) {
|
|
||||||
errcoll.Collectf(ctx, errColl, "backendpb: "+format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ctxWithAuthentication adds the API key authentication header to the outgoing
|
// ctxWithAuthentication adds the API key authentication header to the outgoing
|
||||||
// request context if apiKey is not empty. If it is empty, ctx is parent.
|
// request context if apiKey is not empty. If it is empty, ctx is parent.
|
||||||
func ctxWithAuthentication(parent context.Context, apiKey string) (ctx context.Context) {
|
func ctxWithAuthentication(parent context.Context, apiKey string) (ctx context.Context) {
|
||||||
|
@ -2,18 +2,13 @@ package backendpb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testutil.DiscardLogOutput(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common IDs for tests and their string forms.
|
// Common IDs for tests and their string forms.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Move all or most tests into external and unexport these.
|
// TODO(a.garipov): Move all or most tests into external and unexport these.
|
||||||
@ -37,5 +32,8 @@ var TestUpdTime = time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
|
|||||||
// TODO(a.garipov): Add to golibs/netutil.
|
// TODO(a.garipov): Add to golibs/netutil.
|
||||||
var TestBind = netip.MustParsePrefix("0.0.0.0/0")
|
var TestBind = netip.MustParsePrefix("0.0.0.0/0")
|
||||||
|
|
||||||
|
// TestLogger is the common logger for tests.
|
||||||
|
var TestLogger = slogutil.NewDiscardLogger()
|
||||||
|
|
||||||
// TestRespSzEst is a response-size estimate for tests.
|
// TestRespSzEst is a response-size estimate for tests.
|
||||||
const TestRespSzEst datasize.ByteSize = 1 * datasize.KB
|
const TestRespSzEst datasize.ByteSize = 1 * datasize.KB
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
@ -16,13 +17,18 @@ import (
|
|||||||
// BillStatConfig is the configuration structure for the business logic backend
|
// BillStatConfig is the configuration structure for the business logic backend
|
||||||
// billing statistics uploader.
|
// billing statistics uploader.
|
||||||
type BillStatConfig struct {
|
type BillStatConfig struct {
|
||||||
|
// Logger is used for logging the operation of the billing statistics
|
||||||
|
// uploader. It must not be nil.
|
||||||
|
Logger *slog.Logger
|
||||||
|
|
||||||
|
// GRPCMetrics is used for the collection of the protobuf communication
|
||||||
|
// statistics.
|
||||||
|
GRPCMetrics GRPCMetrics
|
||||||
|
|
||||||
// ErrColl is the error collector that is used to collect critical and
|
// ErrColl is the error collector that is used to collect critical and
|
||||||
// non-critical errors.
|
// non-critical errors.
|
||||||
ErrColl errcoll.Interface
|
ErrColl errcoll.Interface
|
||||||
|
|
||||||
// Metrics is used for the collection of the protobuf errors.
|
|
||||||
Metrics Metrics
|
|
||||||
|
|
||||||
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
||||||
// "grpcs".
|
// "grpcs".
|
||||||
Endpoint *url.URL
|
Endpoint *url.URL
|
||||||
@ -31,6 +37,20 @@ type BillStatConfig struct {
|
|||||||
APIKey string
|
APIKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BillStat is the implementation of the [billstat.Uploader] interface that
|
||||||
|
// uploads the billing statistics to the business logic backend. It is safe for
|
||||||
|
// concurrent use.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Consider uniting with [ProfileStorage] into a single
|
||||||
|
// backendpb.Client.
|
||||||
|
type BillStat struct {
|
||||||
|
logger *slog.Logger
|
||||||
|
errColl errcoll.Interface
|
||||||
|
grpcMetrics GRPCMetrics
|
||||||
|
client DNSServiceClient
|
||||||
|
apiKey string
|
||||||
|
}
|
||||||
|
|
||||||
// NewBillStat creates a new billing statistics uploader. c must not be nil.
|
// NewBillStat creates a new billing statistics uploader. c must not be nil.
|
||||||
func NewBillStat(c *BillStatConfig) (b *BillStat, err error) {
|
func NewBillStat(c *BillStatConfig) (b *BillStat, err error) {
|
||||||
client, err := newClient(c.Endpoint)
|
client, err := newClient(c.Endpoint)
|
||||||
@ -40,26 +60,14 @@ func NewBillStat(c *BillStatConfig) (b *BillStat, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &BillStat{
|
return &BillStat{
|
||||||
|
logger: c.Logger,
|
||||||
errColl: c.ErrColl,
|
errColl: c.ErrColl,
|
||||||
metrics: c.Metrics,
|
grpcMetrics: c.GRPCMetrics,
|
||||||
client: NewDNSServiceClient(client),
|
client: NewDNSServiceClient(client),
|
||||||
apiKey: c.APIKey,
|
apiKey: c.APIKey,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BillStat is the implementation of the [billstat.Uploader] interface that
|
|
||||||
// uploads the billing statistics to the business logic backend. It is safe for
|
|
||||||
// concurrent use.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Consider uniting with [ProfileStorage] into a single
|
|
||||||
// backendpb.Client.
|
|
||||||
type BillStat struct {
|
|
||||||
errColl errcoll.Interface
|
|
||||||
metrics Metrics
|
|
||||||
client DNSServiceClient
|
|
||||||
apiKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ billstat.Uploader = (*BillStat)(nil)
|
var _ billstat.Uploader = (*BillStat)(nil)
|
||||||
|
|
||||||
@ -72,12 +80,13 @@ func (b *BillStat) Upload(ctx context.Context, records billstat.Records) (err er
|
|||||||
ctx = ctxWithAuthentication(ctx, b.apiKey)
|
ctx = ctxWithAuthentication(ctx, b.apiKey)
|
||||||
stream, err := b.client.SaveDevicesBillingStat(ctx)
|
stream, err := b.client.SaveDevicesBillingStat(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("opening stream: %w", fixGRPCError(ctx, b.metrics, err))
|
return fmt.Errorf("opening stream: %w", fixGRPCError(ctx, b.grpcMetrics, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
for deviceID, record := range records {
|
for deviceID, record := range records {
|
||||||
if record == nil {
|
if record == nil {
|
||||||
reportf(ctx, b.errColl, "device %q: null record", deviceID)
|
err = fmt.Errorf("device %q: null record", deviceID)
|
||||||
|
errcoll.Collect(ctx, b.errColl, b.logger, "uploading records", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -87,7 +96,7 @@ func (b *BillStat) Upload(ctx context.Context, records billstat.Records) (err er
|
|||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"uploading device %q record: %w",
|
"uploading device %q record: %w",
|
||||||
deviceID,
|
deviceID,
|
||||||
fixGRPCError(ctx, b.metrics, sendErr),
|
fixGRPCError(ctx, b.grpcMetrics, sendErr),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,13 +101,14 @@ func TestBillStat_Upload(t *testing.T) {
|
|||||||
|
|
||||||
errColl := &agdtest.ErrorCollector{
|
errColl := &agdtest.ErrorCollector{
|
||||||
OnCollect: func(_ context.Context, err error) {
|
OnCollect: func(_ context.Context, err error) {
|
||||||
testutil.AssertErrorMsg(t, `backendpb: device "invalid": null record`, err)
|
testutil.AssertErrorMsg(t, `uploading records: device "invalid": null record`, err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := backendpb.NewBillStat(&backendpb.BillStatConfig{
|
b, err := backendpb.NewBillStat(&backendpb.BillStatConfig{
|
||||||
|
Logger: backendpb.TestLogger,
|
||||||
ErrColl: errColl,
|
ErrColl: errColl,
|
||||||
Metrics: backendpb.EmptyMetrics{},
|
GRPCMetrics: backendpb.EmptyGRPCMetrics{},
|
||||||
Endpoint: &url.URL{
|
Endpoint: &url.URL{
|
||||||
Scheme: "grpc",
|
Scheme: "grpc",
|
||||||
Host: l.Addr().String(),
|
Host: l.Addr().String(),
|
||||||
|
@ -3,6 +3,7 @@ package backendpb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
@ -19,7 +20,8 @@ func devicesToInternal(
|
|||||||
ds []*DeviceSettings,
|
ds []*DeviceSettings,
|
||||||
bindSet netutil.SubnetSet,
|
bindSet netutil.SubnetSet,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
mtrc Metrics,
|
logger *slog.Logger,
|
||||||
|
mtrc ProfileDBMetrics,
|
||||||
) (out []*agd.Device, ids []agd.DeviceID) {
|
) (out []*agd.Device, ids []agd.DeviceID) {
|
||||||
l := len(ds)
|
l := len(ds)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
@ -35,7 +37,8 @@ func devicesToInternal(
|
|||||||
id = d.Id
|
id = d.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
reportf(ctx, errColl, "bad device settings for device with id %q: %w", id, err)
|
err = fmt.Errorf("bad settings for device with id %q: %w", id, err)
|
||||||
|
errcoll.Collect(ctx, errColl, logger, "converting device", err)
|
||||||
|
|
||||||
// TODO(s.chzhen): Add a return result structure and move the
|
// TODO(s.chzhen): Add a return result structure and move the
|
||||||
// metrics collection to the layer above.
|
// metrics collection to the layer above.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.35.1
|
// protoc-gen-go v1.35.2
|
||||||
// protoc v5.28.3
|
// protoc v5.28.3
|
||||||
// source: dns.proto
|
// source: dns.proto
|
||||||
|
|
||||||
@ -247,6 +247,7 @@ type DNSProfile struct {
|
|||||||
Access *AccessSettings `protobuf:"bytes,18,opt,name=access,proto3" json:"access,omitempty"`
|
Access *AccessSettings `protobuf:"bytes,18,opt,name=access,proto3" json:"access,omitempty"`
|
||||||
AutoDevicesEnabled bool `protobuf:"varint,19,opt,name=auto_devices_enabled,json=autoDevicesEnabled,proto3" json:"auto_devices_enabled,omitempty"`
|
AutoDevicesEnabled bool `protobuf:"varint,19,opt,name=auto_devices_enabled,json=autoDevicesEnabled,proto3" json:"auto_devices_enabled,omitempty"`
|
||||||
RateLimit *RateLimitSettings `protobuf:"bytes,20,opt,name=rate_limit,json=rateLimit,proto3" json:"rate_limit,omitempty"`
|
RateLimit *RateLimitSettings `protobuf:"bytes,20,opt,name=rate_limit,json=rateLimit,proto3" json:"rate_limit,omitempty"`
|
||||||
|
BlockChromePrefetch bool `protobuf:"varint,21,opt,name=block_chrome_prefetch,json=blockChromePrefetch,proto3" json:"block_chrome_prefetch,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DNSProfile) Reset() {
|
func (x *DNSProfile) Reset() {
|
||||||
@ -426,6 +427,13 @@ func (x *DNSProfile) GetRateLimit() *RateLimitSettings {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *DNSProfile) GetBlockChromePrefetch() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.BlockChromePrefetch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type isDNSProfile_BlockingMode interface {
|
type isDNSProfile_BlockingMode interface {
|
||||||
isDNSProfile_BlockingMode()
|
isDNSProfile_BlockingMode()
|
||||||
}
|
}
|
||||||
@ -2001,7 +2009,7 @@ var file_dns_proto_rawDesc = []byte{
|
|||||||
0x09, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
0x09, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x73, 0x79,
|
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x73, 0x79,
|
||||||
0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xad, 0x08, 0x0a, 0x0a, 0x44, 0x4e, 0x53, 0x50, 0x72,
|
0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xe1, 0x08, 0x0a, 0x0a, 0x44, 0x4e, 0x53, 0x50, 0x72,
|
||||||
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6e, 0x73, 0x5f, 0x69, 0x64, 0x18,
|
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6e, 0x73, 0x5f, 0x69, 0x64, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x6e, 0x73, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x6e, 0x73, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11,
|
||||||
0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
@ -2067,223 +2075,226 @@ var file_dns_proto_rawDesc = []byte{
|
|||||||
0x65, 0x64, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
0x65, 0x64, 0x12, 0x31, 0x0a, 0x0a, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||||
0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d,
|
0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d,
|
||||||
0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x09, 0x72, 0x61, 0x74, 0x65,
|
0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x09, 0x72, 0x61, 0x74, 0x65,
|
||||||
0x4c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x0f, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e,
|
0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
|
||||||
0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x53, 0x61, 0x66, 0x65, 0x42,
|
0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x15,
|
||||||
0x72, 0x6f, 0x77, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x68, 0x72, 0x6f, 0x6d,
|
||||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x74, 0x63, 0x68, 0x42, 0x0f, 0x0a, 0x0d, 0x62, 0x6c, 0x6f,
|
||||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x62, 0x6c, 0x6f,
|
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x53,
|
||||||
0x63, 0x6b, 0x5f, 0x64, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x6f, 0x6d,
|
0x61, 0x66, 0x65, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x61, 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x62, 0x6c, 0x6f, 0x63,
|
0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01,
|
||||||
0x6b, 0x44, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x36, 0x0a,
|
||||||
0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x72, 0x64, 0x18, 0x03,
|
0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73,
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x64, 0x22, 0x8a,
|
0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15,
|
||||||
0x02, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
|
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x44, 0x6f,
|
||||||
0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
|
0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e,
|
||||||
0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e,
|
||||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69,
|
0x72, 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74,
|
||||||
0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x52, 0x10, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c,
|
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
|
||||||
0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x70, 0x18,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x49, 0x70, 0x12,
|
0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03,
|
||||||
0x23, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x70, 0x73,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x45,
|
||||||
0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65,
|
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64,
|
||||||
0x64, 0x49, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
|
||||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x41,
|
0x64, 0x49, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64,
|
||||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74,
|
0x5f, 0x69, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x64, 0x69,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
0x63, 0x61, 0x74, 0x65, 0x64, 0x49, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x5f, 0x69,
|
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x64, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x68,
|
0x32, 0x17, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||||
0x75, 0x6d, 0x61, 0x6e, 0x49, 0x64, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x22, 0x87, 0x02, 0x0a, 0x10,
|
0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65,
|
||||||
0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x68, 0x75, 0x6d,
|
||||||
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x61, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c,
|
0x09, 0x52, 0x0c, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x49, 0x64, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x22,
|
||||||
0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x64, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x87, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x65, 0x74, 0x74,
|
||||||
0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x64, 0x75, 0x6c, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67,
|
0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18,
|
||||||
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72,
|
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f,
|
||||||
0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x64, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20,
|
||||||
0x6c, 0x53, 0x61, 0x66, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x79,
|
0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x64, 0x75, 0x6c, 0x74, 0x12,
|
||||||
0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72,
|
0x2e, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f,
|
||||||
0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62,
|
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x67, 0x65,
|
||||||
0x65, 0x53, 0x61, 0x66, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x62,
|
0x6e, 0x65, 0x72, 0x61, 0x6c, 0x53, 0x61, 0x66, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12,
|
||||||
0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
|
0x2e, 0x0a, 0x13, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f,
|
||||||
0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x65,
|
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x79, 0x6f,
|
||||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
|
0x75, 0x74, 0x75, 0x62, 0x65, 0x53, 0x61, 0x66, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12,
|
||||||
0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64,
|
0x29, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||||
0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x63, 0x68,
|
0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||||
0x65, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x54, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
|
0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63,
|
||||||
0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x6d, 0x7a,
|
0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12, 0x2e, 0x0a, 0x0b, 0x77,
|
0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52,
|
||||||
0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x54, 0x0a, 0x10, 0x53, 0x63, 0x68,
|
||||||
0x32, 0x0c, 0x2e, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b,
|
0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a,
|
||||||
0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x0b,
|
0x03, 0x74, 0x6d, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12,
|
||||||
0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x6d,
|
0x2e, 0x0a, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02,
|
||||||
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e,
|
||||||
0x6e, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x75, 0x65, 0x18,
|
0x67, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65,
|
0xd8, 0x01, 0x0a, 0x0b, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
|
||||||
0x52, 0x03, 0x74, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01,
|
0x1b, 0x0a, 0x03, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44,
|
||||||
0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x77,
|
0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03,
|
||||||
0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x68, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x74, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52,
|
||||||
0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x68, 0x75, 0x12,
|
0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64,
|
||||||
0x1b, 0x0a, 0x03, 0x66, 0x72, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67,
|
||||||
0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x66, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x03,
|
0x65, 0x52, 0x03, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x68, 0x75, 0x18, 0x04, 0x20,
|
||||||
0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52,
|
0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x75, 0x6e,
|
0x74, 0x68, 0x75, 0x12, 0x1b, 0x0a, 0x03, 0x66, 0x72, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67,
|
0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x66, 0x72, 0x69,
|
||||||
0x65, 0x52, 0x03, 0x73, 0x75, 0x6e, 0x22, 0x68, 0x0a, 0x08, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e,
|
0x12, 0x1b, 0x0a, 0x03, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e,
|
||||||
0x67, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a,
|
||||||
0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x03, 0x73, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79,
|
||||||
0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74,
|
0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x75, 0x6e, 0x22, 0x68, 0x0a, 0x08, 0x44, 0x61,
|
||||||
0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
|
||||||
0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||||
0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64,
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x22, 0x3f, 0x0a, 0x11, 0x52, 0x75, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x53, 0x65, 0x74,
|
0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
|
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
||||||
0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64,
|
0x03, 0x65, 0x6e, 0x64, 0x22, 0x3f, 0x0a, 0x11, 0x52, 0x75, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x73, 0x22, 0x3e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64,
|
0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61,
|
||||||
0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76,
|
0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||||
0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a,
|
0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
|
||||||
0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76,
|
0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x3e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e,
|
||||||
0x36, 0x22, 0x16, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64,
|
0x67, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a,
|
||||||
0x65, 0x4e, 0x58, 0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a, 0x12, 0x42, 0x6c, 0x6f,
|
0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76,
|
||||||
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x49, 0x50, 0x22,
|
0x34, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
0x15, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x52,
|
0x04, 0x69, 0x70, 0x76, 0x36, 0x22, 0x16, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e,
|
||||||
0x45, 0x46, 0x55, 0x53, 0x45, 0x44, 0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63,
|
0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x58, 0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a,
|
||||||
0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x48, 0x0a, 0x12,
|
0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c,
|
||||||
0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69,
|
0x6c, 0x49, 0x50, 0x22, 0x15, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d,
|
||||||
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
0x6f, 0x64, 0x65, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45, 0x44, 0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44,
|
||||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74,
|
||||||
0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69,
|
0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
|
||||||
0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
|
0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
|
||||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63,
|
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
|
||||||
0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f,
|
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63,
|
||||||
0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69,
|
0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65,
|
||||||
0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72,
|
0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64,
|
||||||
0x6f, 0x74, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61,
|
0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x73, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20,
|
0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x14,
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a,
|
0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70,
|
||||||
0x0e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x31, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64,
|
0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65,
|
||||||
0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61,
|
0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73,
|
||||||
0x6e, 0x67, 0x65, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69,
|
0x22, 0x90, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x64, 0x72, 0x12, 0x31, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f,
|
0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74,
|
||||||
0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64,
|
0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69,
|
||||||
0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73,
|
0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69,
|
||||||
0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69,
|
0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x31, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c,
|
||||||
0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6c,
|
0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a,
|
||||||
0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x6c,
|
0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63,
|
||||||
0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28,
|
0x6b, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c,
|
||||||
0x0d, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12,
|
0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d,
|
||||||
0x34, 0x0a, 0x16, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d,
|
0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x23,
|
||||||
0x61, 0x69, 0x6e, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18,
|
||||||
0x14, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74,
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
0x41, 0x73, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74,
|
||||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22,
|
0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20,
|
||||||
0x3d, 0x0a, 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
0x03, 0x28, 0x09, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f,
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61,
|
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
|
0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x85,
|
0x6c, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65,
|
||||||
0x01, 0x0a, 0x16, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x6f, 0x68,
|
0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72,
|
||||||
0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66,
|
||||||
0x52, 0x0b, 0x64, 0x6f, 0x68, 0x41, 0x75, 0x74, 0x68, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x32, 0x0a,
|
0x69, 0x78, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||||
0x14, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x62,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x22, 0x0a,
|
||||||
0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x12, 0x70,
|
0x0d, 0x64, 0x6f, 0x68, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01,
|
||||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x42, 0x63, 0x72, 0x79, 0x70,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6f, 0x68, 0x41, 0x75, 0x74, 0x68, 0x4f, 0x6e, 0x6c,
|
||||||
0x74, 0x42, 0x13, 0x0a, 0x11, 0x64, 0x6f, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
0x79, 0x12, 0x32, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61,
|
||||||
0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x22, 0x75, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
0x73, 0x68, 0x5f, 0x62, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48,
|
||||||
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a,
|
0x00, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x42,
|
||||||
0x06, 0x64, 0x6e, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64,
|
0x63, 0x72, 0x79, 0x70, 0x74, 0x42, 0x13, 0x0a, 0x11, 0x64, 0x6f, 0x68, 0x5f, 0x70, 0x61, 0x73,
|
||||||
0x6e, 0x73, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x5f, 0x69, 0x64,
|
0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x22, 0x75, 0x0a, 0x13, 0x43, 0x72,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x49, 0x64, 0x12,
|
0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x2c, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
|
0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6e, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70,
|
0x09, 0x52, 0x05, 0x64, 0x6e, 0x73, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x75, 0x6d, 0x61,
|
||||||
0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3f, 0x0a,
|
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x75, 0x6d, 0x61,
|
||||||
0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73,
|
0x6e, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18,
|
0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65,
|
0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x68,
|
0x65, 0x22, 0x3f, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||||
0x0a, 0x10, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x45, 0x72, 0x72,
|
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x64, 0x65, 0x76,
|
||||||
0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
|
0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x44, 0x65, 0x76, 0x69,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x0b,
|
0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69,
|
||||||
0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x63, 0x65, 0x22, 0x68, 0x0a, 0x10, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65,
|
||||||
0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||||
0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x72, 0x65,
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x22, 0x34, 0x0a, 0x18, 0x44, 0x65, 0x76, 0x69,
|
0x12, 0x3a, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18,
|
||||||
0x63, 0x65, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x45,
|
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||||
0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2b,
|
0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x22, 0x34, 0x0a, 0x18,
|
||||||
0x0a, 0x0f, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f,
|
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x45, 0x78, 0x63, 0x65, 0x65,
|
||||||
0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
|
0x64, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
|
||||||
0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x35, 0x0a, 0x19, 0x41,
|
|
||||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69,
|
|
||||||
0x6c, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
|
|
||||||
0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||||
0x67, 0x65, 0x22, 0x6c, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53,
|
0x67, 0x65, 0x22, 0x2b, 0x0a, 0x0f, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
|
||||||
0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03,
|
0x35, 0x0a, 0x19, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||||
0x72, 0x70, 0x73, 0x12, 0x2b, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x69,
|
0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07,
|
||||||
0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52,
|
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x69, 0x64, 0x72,
|
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x6c, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69,
|
||||||
0x22, 0x26, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52,
|
0x6d, 0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x64, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f,
|
0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
0x28, 0x0d, 0x52, 0x03, 0x72, 0x70, 0x73, 0x12, 0x2b, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
0x14, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52,
|
0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43,
|
||||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x02,
|
0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
0x43, 0x69, 0x64, 0x72, 0x22, 0x26, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56,
|
||||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x05,
|
0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||||
0x65, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x67,
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x64, 0x0a, 0x13,
|
||||||
0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71,
|
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02,
|
|
||||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74,
|
|
||||||
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x74,
|
|
||||||
0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x87,
|
|
||||||
0x01, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
|
|
||||||
0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x49,
|
|
||||||
0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x44, 0x52, 0x4f,
|
|
||||||
0x49, 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x4d, 0x41, 0x43, 0x10, 0x03, 0x12, 0x07, 0x0a,
|
|
||||||
0x03, 0x49, 0x4f, 0x53, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x10,
|
|
||||||
0x05, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x10, 0x06, 0x12, 0x0c, 0x0a,
|
|
||||||
0x08, 0x53, 0x4d, 0x41, 0x52, 0x54, 0x5f, 0x54, 0x56, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x47,
|
|
||||||
0x41, 0x4d, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x4f, 0x4c, 0x45, 0x10, 0x08, 0x12, 0x09, 0x0a,
|
|
||||||
0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x09, 0x32, 0xd0, 0x01, 0x0a, 0x0a, 0x44, 0x4e, 0x53,
|
|
||||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x44, 0x4e,
|
|
||||||
0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x13, 0x2e, 0x44, 0x4e, 0x53, 0x50,
|
|
||||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b,
|
|
||||||
0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a,
|
|
||||||
0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x6c, 0x6c,
|
|
||||||
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
|
|
||||||
0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
|
|
||||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
|
||||||
0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x44, 0x0a, 0x15, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44,
|
|
||||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x79, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x14,
|
|
||||||
0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71,
|
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76,
|
|
||||||
0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x61, 0x0a, 0x10, 0x52,
|
|
||||||
0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
|
||||||
0x4d, 0x0a, 0x14, 0x67, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53,
|
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69,
|
|
||||||
0x6d, 0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
|
||||||
0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x65,
|
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x75,
|
|
||||||
0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
|
||||||
0x65, 0x12, 0x30, 0x0a, 0x03, 0x67, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74,
|
|
||||||
0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e,
|
|
||||||
0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x52, 0x65, 0x6d,
|
0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x0c, 0x48, 0x00, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6d, 0x70,
|
||||||
0x14, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73,
|
0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x67,
|
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
||||||
0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x73,
|
0x48, 0x00, 0x52, 0x05, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
||||||
0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x10, 0x44, 0x4e, 0x53, 0x50,
|
0x75, 0x65, 0x22, 0x67, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65,
|
||||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02,
|
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||||
0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
|
||||||
|
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b,
|
||||||
|
0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
|
||||||
|
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
|
||||||
|
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x22, 0x15, 0x0a, 0x13, 0x52,
|
||||||
|
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x2a, 0x87, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70,
|
||||||
|
0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b,
|
||||||
|
0x0a, 0x07, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41,
|
||||||
|
0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x4d, 0x41, 0x43, 0x10,
|
||||||
|
0x03, 0x12, 0x07, 0x0a, 0x03, 0x49, 0x4f, 0x53, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x49,
|
||||||
|
0x4e, 0x55, 0x58, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x10,
|
||||||
|
0x06, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x4d, 0x41, 0x52, 0x54, 0x5f, 0x54, 0x56, 0x10, 0x07, 0x12,
|
||||||
|
0x10, 0x0a, 0x0c, 0x47, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x4f, 0x4c, 0x45, 0x10,
|
||||||
|
0x08, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x09, 0x32, 0xd0, 0x01, 0x0a,
|
||||||
|
0x0a, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0e, 0x67,
|
||||||
|
0x65, 0x74, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x13, 0x2e,
|
||||||
|
0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
|
0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x30,
|
||||||
|
0x01, 0x12, 0x46, 0x0a, 0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||||
|
0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12, 0x2e, 0x44, 0x65,
|
||||||
|
0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x1a,
|
||||||
|
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||||
|
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x44, 0x0a, 0x15, 0x63, 0x72, 0x65,
|
||||||
|
0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x79, 0x48, 0x75, 0x6d, 0x61, 0x6e,
|
||||||
|
0x49, 0x64, 0x12, 0x14, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||||
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||||
|
0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32,
|
||||||
|
0x61, 0x0a, 0x10, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x65, 0x72, 0x76,
|
||||||
|
0x69, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x14, 0x67, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69,
|
||||||
|
0x6d, 0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x2e, 0x52, 0x61,
|
||||||
|
0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52,
|
||||||
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d,
|
||||||
|
0x69, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x32, 0x75, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65,
|
||||||
|
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x03, 0x67, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x52,
|
||||||
|
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
|
0x74, 0x1a, 0x14, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x47, 0x65, 0x74, 0x52,
|
||||||
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x12, 0x13,
|
||||||
|
0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||||
|
0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x56, 0x53, 0x65,
|
||||||
|
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, 0x0a, 0x21, 0x63, 0x6f, 0x6d,
|
||||||
|
0x2e, 0x61, 0x64, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
|
||||||
|
0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x10,
|
||||||
|
0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x50, 0x01, 0xa2, 0x02, 0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -108,6 +108,7 @@ message DNSProfile {
|
|||||||
AccessSettings access = 18;
|
AccessSettings access = 18;
|
||||||
bool auto_devices_enabled = 19;
|
bool auto_devices_enabled = 19;
|
||||||
RateLimitSettings rate_limit = 20;
|
RateLimitSettings rate_limit = 20;
|
||||||
|
bool block_chrome_prefetch = 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SafeBrowsingSettings {
|
message SafeBrowsingSettings {
|
||||||
|
@ -9,30 +9,15 @@ import (
|
|||||||
status "google.golang.org/grpc/status"
|
status "google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GRPCError is a type alias for string that contains the gRPC error type.
|
|
||||||
//
|
|
||||||
// TODO(s.chzhen): Rewrite as soon as the import cycle is resolved.
|
|
||||||
type GRPCError = string
|
|
||||||
|
|
||||||
// gRPC errors of [GRPCError] type.
|
|
||||||
const (
|
|
||||||
GRPCErrAuthentication GRPCError = "auth"
|
|
||||||
GRPCErrBadRequest GRPCError = "bad_req"
|
|
||||||
GRPCErrDeviceQuota GRPCError = "dev_quota"
|
|
||||||
GRPCErrOther GRPCError = "other"
|
|
||||||
GRPCErrRateLimit GRPCError = "rate_limit"
|
|
||||||
GRPCErrTimeout GRPCError = "timeout"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fixGRPCError converts a gRPC error into an application error, if necessary.
|
// fixGRPCError converts a gRPC error into an application error, if necessary.
|
||||||
// That includes gRPC deadlines, which do not match [context.DeadlineExceeded]
|
// That includes gRPC deadlines, which do not match [context.DeadlineExceeded]
|
||||||
// correctly.
|
// correctly.
|
||||||
//
|
//
|
||||||
// It also updates the backend gRPC metrics depending on the type, see
|
// It also updates the backend gRPC metrics depending on the type, see
|
||||||
// [Metrics.IncrementGRPCErrorCount].
|
// [GRPCMetrics.IncrementErrorCount].
|
||||||
func fixGRPCError(ctx context.Context, mtrc Metrics, err error) (res error) {
|
func fixGRPCError(ctx context.Context, mtrc GRPCMetrics, err error) (res error) {
|
||||||
metricsType := GRPCErrOther
|
metricsType := GRPCErrOther
|
||||||
defer func() { mtrc.IncrementGRPCErrorCount(ctx, metricsType) }()
|
defer func() { mtrc.IncrementErrorCount(ctx, metricsType) }()
|
||||||
|
|
||||||
s, ok := status.FromError(err)
|
s, ok := status.FromError(err)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -5,13 +5,47 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Metrics is an interface that is used for the collection of the protobuf
|
// GRPCError is a type alias for string that contains the gRPC error type.
|
||||||
// errors statistics.
|
//
|
||||||
type Metrics interface {
|
// See [GRPCMetrics.IncrementErrorCount].
|
||||||
// IncrementGRPCErrorCount increments the gRPC error count of errType.
|
//
|
||||||
// errType must be one of GRPCError values.
|
// TODO(s.chzhen): Rewrite as soon as the import cycle is resolved.
|
||||||
IncrementGRPCErrorCount(ctx context.Context, errType GRPCError)
|
type GRPCError = string
|
||||||
|
|
||||||
|
// gRPC errors of [GRPCError] type.
|
||||||
|
//
|
||||||
|
// NOTE: Keep in sync with [metrics.GRPCError].
|
||||||
|
const (
|
||||||
|
GRPCErrAuthentication GRPCError = "auth"
|
||||||
|
GRPCErrBadRequest GRPCError = "bad_req"
|
||||||
|
GRPCErrDeviceQuota GRPCError = "dev_quota"
|
||||||
|
GRPCErrOther GRPCError = "other"
|
||||||
|
GRPCErrRateLimit GRPCError = "rate_limit"
|
||||||
|
GRPCErrTimeout GRPCError = "timeout"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GRPCMetrics is an interface that is used for the collection of the protobuf
|
||||||
|
// communication statistics.
|
||||||
|
type GRPCMetrics interface {
|
||||||
|
// IncrementErrorCount increments the gRPC error count of errType. errType
|
||||||
|
// must be one of [GRPCError] values.
|
||||||
|
IncrementErrorCount(ctx context.Context, errType GRPCError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyGRPCMetrics is the implementation of the [GRPCMetrics] interface that
|
||||||
|
// does nothing.
|
||||||
|
type EmptyGRPCMetrics struct{}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ GRPCMetrics = EmptyGRPCMetrics{}
|
||||||
|
|
||||||
|
// IncrementErrorCount implements the [GRPCMetrics] interface for
|
||||||
|
// EmptyGRPCMetrics.
|
||||||
|
func (EmptyGRPCMetrics) IncrementErrorCount(_ context.Context, _ GRPCError) {}
|
||||||
|
|
||||||
|
// ProfileDBMetrics is an interface that is used for the collection of the
|
||||||
|
// profile database statistics.
|
||||||
|
type ProfileDBMetrics interface {
|
||||||
// IncrementInvalidDevicesCount increments the number of invalid devices.
|
// IncrementInvalidDevicesCount increments the number of invalid devices.
|
||||||
IncrementInvalidDevicesCount(ctx context.Context)
|
IncrementInvalidDevicesCount(ctx context.Context)
|
||||||
|
|
||||||
@ -19,18 +53,61 @@ type Metrics interface {
|
|||||||
UpdateStats(ctx context.Context, avgRecv, avgDec time.Duration)
|
UpdateStats(ctx context.Context, avgRecv, avgDec time.Duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmptyMetrics is the implementation of the [Metrics] interface that does
|
// EmptyProfileDBMetrics is the implementation of the [ProfileDBMetrics]
|
||||||
// nothing.
|
// interface that does nothing.
|
||||||
type EmptyMetrics struct{}
|
type EmptyProfileDBMetrics struct{}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ Metrics = EmptyMetrics{}
|
var _ ProfileDBMetrics = EmptyProfileDBMetrics{}
|
||||||
|
|
||||||
// IncrementGRPCErrorCount implements the [Metrics] interface for EmptyMetrics.
|
// IncrementInvalidDevicesCount implements the [ProfileDBMetrics] interface for
|
||||||
func (EmptyMetrics) IncrementGRPCErrorCount(_ context.Context, errType GRPCError) {}
|
// EmptyProfileDBMetrics.
|
||||||
|
func (EmptyProfileDBMetrics) IncrementInvalidDevicesCount(_ context.Context) {}
|
||||||
|
|
||||||
// IncrementInvalidDevicesCount implements the [Metrics] interface for EmptyMetrics.
|
// UpdateStats implements the [ProfileDBMetrics] interface for
|
||||||
func (EmptyMetrics) IncrementInvalidDevicesCount(_ context.Context) {}
|
// EmptyProfileDBMetrics.
|
||||||
|
func (EmptyProfileDBMetrics) UpdateStats(_ context.Context, _, _ time.Duration) {}
|
||||||
|
|
||||||
// UpdateStats implements the [Metrics] interface for EmptyMetrics.
|
// RemoteKVOp is the type alias for string that contains remote key-value
|
||||||
func (EmptyMetrics) UpdateStats(_ context.Context, _, _ time.Duration) {}
|
// storage operation name.
|
||||||
|
//
|
||||||
|
// See [RemoteKVMetrics.ObserveOperation].
|
||||||
|
type RemoteKVOp = string
|
||||||
|
|
||||||
|
// Remote key-value storage operation names for [RemoteKVOp].
|
||||||
|
//
|
||||||
|
// NOTE: Keep in sync with [metrics.RemoteKVOp].
|
||||||
|
const (
|
||||||
|
RemoteKVOpGet RemoteKVOp = "get"
|
||||||
|
RemoteKVOpSet RemoteKVOp = "set"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemoteKVMetrics is an interface that is used for the collection of the remote
|
||||||
|
// key-value storage statistics.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): It may actually describe metrics for any remote key-value
|
||||||
|
// storage implementation, consider declaring it in the [remotekv] package.
|
||||||
|
type RemoteKVMetrics interface {
|
||||||
|
// ObserveOperation updates the remote key-value storage statistics. op
|
||||||
|
// must be one of [RemoteKVOp] values.
|
||||||
|
ObserveOperation(ctx context.Context, op string, dur time.Duration)
|
||||||
|
|
||||||
|
// IncrementLookups increments the number of lookups. hit is true if the
|
||||||
|
// lookup returned a value.
|
||||||
|
IncrementLookups(ctx context.Context, hit bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyRemoteKVMetrics is the implementation of the [RemoteKVMetrics] interface
|
||||||
|
// that does nothing.
|
||||||
|
type EmptyRemoteKVMetrics struct{}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ RemoteKVMetrics = EmptyRemoteKVMetrics{}
|
||||||
|
|
||||||
|
// ObserveOperation implements the [RemoteKVMetrics] interface for
|
||||||
|
// EmptyRemoteKVMetrics.
|
||||||
|
func (EmptyRemoteKVMetrics) ObserveOperation(_ context.Context, _ string, _ time.Duration) {}
|
||||||
|
|
||||||
|
// IncrementLookups implements the [RemoteKVMetrics] interface for
|
||||||
|
// EmptyRemoteKVMetrics.
|
||||||
|
func (EmptyRemoteKVMetrics) IncrementLookups(_ context.Context, _ bool) {}
|
||||||
|
@ -3,6 +3,7 @@ package backendpb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
@ -20,20 +22,21 @@ import (
|
|||||||
// toInternal converts the protobuf-encoded data into a profile structure and
|
// toInternal converts the protobuf-encoded data into a profile structure and
|
||||||
// its device structures.
|
// its device structures.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Refactor into a method of [*ProfileStorage]?
|
// TODO(a.garipov): Refactor into methods of [*ProfileStorage].
|
||||||
func (x *DNSProfile) toInternal(
|
func (x *DNSProfile) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
updTime time.Time,
|
updTime time.Time,
|
||||||
bindSet netutil.SubnetSet,
|
bindSet netutil.SubnetSet,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
mtrc Metrics,
|
logger *slog.Logger,
|
||||||
|
mtrc ProfileDBMetrics,
|
||||||
respSzEst datasize.ByteSize,
|
respSzEst datasize.ByteSize,
|
||||||
) (profile *agd.Profile, devices []*agd.Device, err error) {
|
) (profile *agd.Profile, devices []*agd.Device, err error) {
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, nil, fmt.Errorf("profile is nil")
|
return nil, nil, fmt.Errorf("profile is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
parental, err := x.Parental.toInternal(ctx, errColl)
|
parental, err := x.Parental.toInternal(ctx, errColl, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("parental: %w", err)
|
return nil, nil, fmt.Errorf("parental: %w", err)
|
||||||
}
|
}
|
||||||
@ -43,8 +46,7 @@ func (x *DNSProfile) toInternal(
|
|||||||
return nil, nil, fmt.Errorf("blocking mode: %w", err)
|
return nil, nil, fmt.Errorf("blocking mode: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
devices, deviceIds := devicesToInternal(ctx, x.Devices, bindSet, errColl, mtrc)
|
devices, deviceIds := devicesToInternal(ctx, x.Devices, bindSet, errColl, logger, mtrc)
|
||||||
listsEnabled, listIDs := x.RuleLists.toInternal(ctx, errColl)
|
|
||||||
|
|
||||||
profID, err := agd.NewProfileID(x.DnsId)
|
profID, err := agd.NewProfileID(x.DnsId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -56,52 +58,63 @@ func (x *DNSProfile) toInternal(
|
|||||||
fltRespTTL = respTTL.AsDuration()
|
fltRespTTL = respTTL.AsDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &agd.Profile{
|
customRules := rulesToInternal(ctx, x.CustomRules, errColl, logger)
|
||||||
Parental: parental,
|
custom := &filter.ConfigCustom{
|
||||||
BlockingMode: m,
|
ID: string(x.DnsId),
|
||||||
ID: profID,
|
|
||||||
UpdateTime: updTime,
|
UpdateTime: updTime,
|
||||||
DeviceIDs: deviceIds,
|
Rules: customRules,
|
||||||
RuleListIDs: listIDs,
|
// TODO(a.garipov): Consider adding an explicit flag to the protocol.
|
||||||
CustomRules: rulesToInternal(ctx, x.CustomRules, errColl),
|
Enabled: len(customRules) > 0,
|
||||||
FilteredResponseTTL: fltRespTTL,
|
}
|
||||||
FilteringEnabled: x.FilteringEnabled,
|
|
||||||
Ratelimiter: x.RateLimit.toInternal(ctx, errColl, respSzEst),
|
return &agd.Profile{
|
||||||
|
FilterConfig: &filter.ConfigClient{
|
||||||
|
Custom: custom,
|
||||||
|
Parental: parental,
|
||||||
|
RuleList: x.RuleLists.toInternal(ctx, errColl, logger),
|
||||||
SafeBrowsing: x.SafeBrowsing.toInternal(),
|
SafeBrowsing: x.SafeBrowsing.toInternal(),
|
||||||
Access: x.Access.toInternal(ctx, errColl),
|
},
|
||||||
RuleListsEnabled: listsEnabled,
|
Access: x.Access.toInternal(ctx, errColl, logger),
|
||||||
QueryLogEnabled: x.QueryLogEnabled,
|
BlockingMode: m,
|
||||||
Deleted: x.Deleted,
|
Ratelimiter: x.RateLimit.toInternal(ctx, errColl, logger, respSzEst),
|
||||||
BlockPrivateRelay: x.BlockPrivateRelay,
|
ID: profID,
|
||||||
BlockFirefoxCanary: x.BlockFirefoxCanary,
|
DeviceIDs: deviceIds,
|
||||||
IPLogEnabled: x.IpLogEnabled,
|
FilteredResponseTTL: fltRespTTL,
|
||||||
AutoDevicesEnabled: x.AutoDevicesEnabled,
|
AutoDevicesEnabled: x.AutoDevicesEnabled,
|
||||||
|
BlockChromePrefetch: x.BlockChromePrefetch,
|
||||||
|
BlockFirefoxCanary: x.BlockFirefoxCanary,
|
||||||
|
BlockPrivateRelay: x.BlockPrivateRelay,
|
||||||
|
Deleted: x.Deleted,
|
||||||
|
FilteringEnabled: x.FilteringEnabled,
|
||||||
|
IPLogEnabled: x.IpLogEnabled,
|
||||||
|
QueryLogEnabled: x.QueryLogEnabled,
|
||||||
}, devices, nil
|
}, devices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts a protobuf parental-settings structure to an internal
|
// toInternal converts a protobuf parental-protection settings structure to an
|
||||||
// one. If x is nil, toInternal returns nil.
|
// internal one. If x is nil, toInternal returns a disabled configuration.
|
||||||
func (x *ParentalSettings) toInternal(
|
func (x *ParentalSettings) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
) (s *agd.ParentalProtectionSettings, err error) {
|
logger *slog.Logger,
|
||||||
|
) (c *filter.ConfigParental, err error) {
|
||||||
|
c = &filter.ConfigParental{}
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule, err := x.Schedule.toInternal()
|
c.AdultBlockingEnabled = x.BlockAdult
|
||||||
|
c.BlockedServices = blockedSvcsToInternal(ctx, errColl, logger, x.BlockedServices)
|
||||||
|
c.Enabled = x.Enabled
|
||||||
|
c.SafeSearchGeneralEnabled = x.GeneralSafeSearch
|
||||||
|
c.SafeSearchYouTubeEnabled = x.YoutubeSafeSearch
|
||||||
|
|
||||||
|
c.PauseSchedule, err = x.Schedule.toInternal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("schedule: %w", err)
|
return nil, fmt.Errorf("pause schedule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &agd.ParentalProtectionSettings{
|
return c, nil
|
||||||
Schedule: schedule,
|
|
||||||
BlockedServices: blockedSvcsToInternal(ctx, errColl, x.BlockedServices),
|
|
||||||
Enabled: x.Enabled,
|
|
||||||
BlockAdult: x.BlockAdult,
|
|
||||||
GeneralSafeSearch: x.GeneralSafeSearch,
|
|
||||||
YoutubeSafeSearch: x.YoutubeSafeSearch,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts protobuf rate-limiting settings to an internal structure.
|
// toInternal converts protobuf rate-limiting settings to an internal structure.
|
||||||
@ -109,6 +122,7 @@ func (x *ParentalSettings) toInternal(
|
|||||||
func (x *RateLimitSettings) toInternal(
|
func (x *RateLimitSettings) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
|
logger *slog.Logger,
|
||||||
respSzEst datasize.ByteSize,
|
respSzEst datasize.ByteSize,
|
||||||
) (r agd.Ratelimiter) {
|
) (r agd.Ratelimiter) {
|
||||||
if x == nil || !x.Enabled {
|
if x == nil || !x.Enabled {
|
||||||
@ -116,24 +130,26 @@ func (x *RateLimitSettings) toInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return agd.NewDefaultRatelimiter(&agd.RatelimitConfig{
|
return agd.NewDefaultRatelimiter(&agd.RatelimitConfig{
|
||||||
ClientSubnets: cidrRangeToInternal(ctx, errColl, x.ClientCidr),
|
ClientSubnets: cidrRangeToInternal(ctx, errColl, logger, x.ClientCidr),
|
||||||
RPS: x.Rps,
|
RPS: x.Rps,
|
||||||
Enabled: x.Enabled,
|
Enabled: x.Enabled,
|
||||||
}, respSzEst)
|
}, respSzEst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts protobuf safe-browsing settings to an internal structure.
|
// toInternal converts protobuf safe-browsing settings to an internal
|
||||||
// If x is nil, toInternal returns nil.
|
// safe-browsing configuration. If x is nil, toInternal returns a disabled
|
||||||
func (x *SafeBrowsingSettings) toInternal() (sb *agd.SafeBrowsingSettings) {
|
// configuration.
|
||||||
|
func (x *SafeBrowsingSettings) toInternal() (c *filter.ConfigSafeBrowsing) {
|
||||||
|
c = &filter.ConfigSafeBrowsing{}
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return nil
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
return &agd.SafeBrowsingSettings{
|
c.Enabled = x.Enabled
|
||||||
Enabled: x.Enabled,
|
c.DangerousDomainsEnabled = x.BlockDangerousDomains
|
||||||
BlockDangerousDomains: x.BlockDangerousDomains,
|
c.NewlyRegisteredDomainsEnabled = x.BlockNrd
|
||||||
BlockNewlyRegisteredDomains: x.BlockNrd,
|
|
||||||
}
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts protobuf access settings to an internal structure. If x
|
// toInternal converts protobuf access settings to an internal structure. If x
|
||||||
@ -141,14 +157,15 @@ func (x *SafeBrowsingSettings) toInternal() (sb *agd.SafeBrowsingSettings) {
|
|||||||
func (x *AccessSettings) toInternal(
|
func (x *AccessSettings) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
|
logger *slog.Logger,
|
||||||
) (a access.Profile) {
|
) (a access.Profile) {
|
||||||
if x == nil || !x.Enabled {
|
if x == nil || !x.Enabled {
|
||||||
return access.EmptyProfile{}
|
return access.EmptyProfile{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.NewDefaultProfile(&access.ProfileConfig{
|
return access.NewDefaultProfile(&access.ProfileConfig{
|
||||||
AllowedNets: cidrRangeToInternal(ctx, errColl, x.AllowlistCidr),
|
AllowedNets: cidrRangeToInternal(ctx, errColl, logger, x.AllowlistCidr),
|
||||||
BlockedNets: cidrRangeToInternal(ctx, errColl, x.BlocklistCidr),
|
BlockedNets: cidrRangeToInternal(ctx, errColl, logger, x.BlocklistCidr),
|
||||||
AllowedASN: asnToInternal(x.AllowlistAsn),
|
AllowedASN: asnToInternal(x.AllowlistAsn),
|
||||||
BlockedASN: asnToInternal(x.BlocklistAsn),
|
BlockedASN: asnToInternal(x.BlocklistAsn),
|
||||||
BlocklistDomainRules: x.BlocklistDomainRules,
|
BlocklistDomainRules: x.BlocklistDomainRules,
|
||||||
@ -160,12 +177,14 @@ func (x *AccessSettings) toInternal(
|
|||||||
func cidrRangeToInternal(
|
func cidrRangeToInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
|
logger *slog.Logger,
|
||||||
cidrs []*CidrRange,
|
cidrs []*CidrRange,
|
||||||
) (out []netip.Prefix) {
|
) (out []netip.Prefix) {
|
||||||
for i, c := range cidrs {
|
for i, c := range cidrs {
|
||||||
addr, ok := netip.AddrFromSlice(c.Address)
|
addr, ok := netip.AddrFromSlice(c.Address)
|
||||||
if !ok {
|
if !ok {
|
||||||
reportf(ctx, errColl, "bad cidr at index %d: %v", i, c.Address)
|
err := fmt.Errorf("bad cidr at index %d: %v", i, c.Address)
|
||||||
|
errcoll.Collect(ctx, errColl, logger, "converting cidrs", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -187,71 +206,71 @@ func asnToInternal(asns []uint32) (out []geoip.ASN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blockedSvcsToInternal is a helper that converts the blocked service IDs from
|
// blockedSvcsToInternal is a helper that converts the blocked service IDs from
|
||||||
// the backend response to AdGuard DNS blocked service IDs.
|
// the backend response to AdGuard DNS blocked-service IDs.
|
||||||
func blockedSvcsToInternal(
|
func blockedSvcsToInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
|
logger *slog.Logger,
|
||||||
respSvcs []string,
|
respSvcs []string,
|
||||||
) (svcs []agd.BlockedServiceID) {
|
) (ids []filter.BlockedServiceID) {
|
||||||
l := len(respSvcs)
|
l := len(respSvcs)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
svcs = make([]agd.BlockedServiceID, 0, l)
|
ids = make([]filter.BlockedServiceID, 0, l)
|
||||||
for i, s := range respSvcs {
|
for i, idStr := range respSvcs {
|
||||||
id, err := agd.NewBlockedServiceID(s)
|
id, err := filter.NewBlockedServiceID(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportf(ctx, errColl, "blocked service at index %d: %w", i, err)
|
err = fmt.Errorf("at index %d: %w", i, err)
|
||||||
|
errcoll.Collect(ctx, errColl, logger, "converting blocked services", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
svcs = append(svcs, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return svcs
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts a protobuf protection-schedule structure to an internal
|
// toInternal converts a protobuf protection-schedule structure to an internal
|
||||||
// one. If x is nil, toInternal returns nil.
|
// one. If x is nil, toInternal returns nil.
|
||||||
func (x *ScheduleSettings) toInternal() (sch *agd.ParentalProtectionSchedule, err error) {
|
func (x *ScheduleSettings) toInternal() (c *filter.ConfigSchedule, err error) {
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sch = &agd.ParentalProtectionSchedule{}
|
c = &filter.ConfigSchedule{
|
||||||
|
Week: &filter.WeeklySchedule{},
|
||||||
|
}
|
||||||
|
|
||||||
sch.TimeZone, err = agdtime.LoadLocation(x.Tmz)
|
c.TimeZone, err = agdtime.LoadLocation(x.Tmz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("loading timezone: %w", err)
|
return nil, fmt.Errorf("loading timezone: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sch.Week = &agd.WeeklySchedule{}
|
|
||||||
|
|
||||||
w := x.WeeklyRange
|
w := x.WeeklyRange
|
||||||
days := []*DayRange{w.Sun, w.Mon, w.Tue, w.Wed, w.Thu, w.Fri, w.Sat}
|
days := []*DayRange{w.Sun, w.Mon, w.Tue, w.Wed, w.Thu, w.Fri, w.Sat}
|
||||||
for i, d := range days {
|
for i, d := range days {
|
||||||
if d == nil {
|
if d == nil {
|
||||||
sch.Week[i] = agd.ZeroLengthDayRange()
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sch.Week[i] = agd.DayRange{
|
ivl := &filter.DayInterval{
|
||||||
Start: uint16(d.Start.AsDuration().Minutes()),
|
Start: uint16(d.Start.AsDuration().Minutes()),
|
||||||
End: uint16(d.End.AsDuration().Minutes()),
|
End: uint16(d.End.AsDuration().Minutes() + 1),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, r := range sch.Week {
|
err = ivl.Validate()
|
||||||
err = r.Validate()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("weekday %s: %w", time.Weekday(i), err)
|
return nil, fmt.Errorf("weekday %s: %w", time.Weekday(i), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.Week[i] = ivl
|
||||||
}
|
}
|
||||||
|
|
||||||
return sch, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts a protobuf custom blocking-mode to an internal one.
|
// toInternal converts a protobuf custom blocking-mode to an internal one.
|
||||||
@ -312,17 +331,19 @@ func rulesToInternal(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
respRules []string,
|
respRules []string,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
) (rules []agd.FilterRuleText) {
|
logger *slog.Logger,
|
||||||
|
) (rules []filter.RuleText) {
|
||||||
l := len(respRules)
|
l := len(respRules)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rules = make([]agd.FilterRuleText, 0, l)
|
rules = make([]filter.RuleText, 0, l)
|
||||||
for i, r := range respRules {
|
for i, r := range respRules {
|
||||||
text, err := agd.NewFilterRuleText(r)
|
text, err := filter.NewRuleText(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportf(ctx, errColl, "rule at index %d: %w", i, err)
|
err = fmt.Errorf("at index %d: %w", i, err)
|
||||||
|
errcoll.Collect(ctx, errColl, logger, "converting rules", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -334,32 +355,32 @@ func rulesToInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// toInternal is a helper that converts the filter lists from the backend
|
// toInternal is a helper that converts the filter lists from the backend
|
||||||
// response to AdGuard DNS filter list ids. If x is nil, toInternal returns
|
// response to AdGuard DNS rule-list configuration. If x is nil, toInternal
|
||||||
// false and nil.
|
// returns a disabled configuration.
|
||||||
func (x *RuleListsSettings) toInternal(
|
func (x *RuleListsSettings) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
) (enabled bool, filterLists []agd.FilterListID) {
|
logger *slog.Logger,
|
||||||
|
) (c *filter.ConfigRuleList) {
|
||||||
|
c = &filter.ConfigRuleList{}
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return false, nil
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
l := len(x.Ids)
|
c.Enabled = x.Enabled
|
||||||
if l == 0 {
|
c.IDs = make([]filter.ID, 0, len(x.Ids))
|
||||||
return x.Enabled, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
filterLists = make([]agd.FilterListID, 0, l)
|
for i, idStr := range x.Ids {
|
||||||
for i, f := range x.Ids {
|
id, err := filter.NewID(idStr)
|
||||||
id, err := agd.NewFilterListID(f)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportf(ctx, errColl, "filter id: at index %d: %w", i, err)
|
err = fmt.Errorf("at index %d: %w", i, err)
|
||||||
|
errcoll.Collect(ctx, errColl, logger, "converting filter id", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
filterLists = append(filterLists, id)
|
c.IDs = append(c.IDs, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return x.Enabled, filterLists
|
return c
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
@ -35,7 +36,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -58,14 +60,15 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
savingErrColl,
|
savingErrColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.AssertErrorMsg(
|
testutil.AssertErrorMsg(
|
||||||
t,
|
t,
|
||||||
`backendpb: bad device settings for device with id "inv-d-ip":`+
|
`converting device: bad settings for device with id "inv-d-ip":`+
|
||||||
" dedicated ips: ip at index 0: unexpected slice size",
|
` dedicated ips: ip at index 0: unexpected slice size`,
|
||||||
errCollErr,
|
errCollErr,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,13 +92,14 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
bindSet,
|
bindSet,
|
||||||
savingErrColl,
|
savingErrColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.AssertErrorMsg(
|
testutil.AssertErrorMsg(
|
||||||
t,
|
t,
|
||||||
`backendpb: bad device settings for device with id "`+TestDeviceIDStr+`":`+
|
`converting device: bad settings for device with id "`+TestDeviceIDStr+`":`+
|
||||||
" dedicated ips: at index 0: \"1.1.1.2\" is not in bind data",
|
" dedicated ips: at index 0: \"1.1.1.2\" is not in bind data",
|
||||||
errCollErr,
|
errCollErr,
|
||||||
)
|
)
|
||||||
@ -114,7 +118,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(t, "profile is nil", err)
|
testutil.AssertErrorMsg(t, "profile is nil", err)
|
||||||
@ -133,7 +138,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -155,12 +161,13 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(
|
testutil.AssertErrorMsg(
|
||||||
t,
|
t,
|
||||||
"parental: schedule: loading timezone: unknown time zone invalid",
|
"parental: pause schedule: loading timezone: unknown time zone invalid",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -179,12 +186,13 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(
|
testutil.AssertErrorMsg(
|
||||||
t,
|
t,
|
||||||
"parental: schedule: weekday Sunday: bad day range: end 0 less than start 16",
|
"parental: pause schedule: weekday Sunday: end: out of range: 1 is less than start 16",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -201,7 +209,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv4: unexpected slice size", err)
|
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv4: unexpected slice size", err)
|
||||||
@ -219,7 +228,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
||||||
@ -238,7 +248,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
testutil.AssertErrorMsg(t, "blocking mode: no valid custom ips found", err)
|
testutil.AssertErrorMsg(t, "blocking mode: no valid custom ips found", err)
|
||||||
@ -255,7 +266,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -279,7 +291,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -302,7 +315,8 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -464,6 +478,7 @@ func NewTestDNSProfile(tb testing.TB) (dp *DNSProfile) {
|
|||||||
Prefix: 24,
|
Prefix: 24,
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
BlockChromePrefetch: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,35 +499,37 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
|||||||
wantLoc, err := agdtime.LoadLocation("GMT")
|
wantLoc, err := agdtime.LoadLocation("GMT")
|
||||||
require.NoError(tb, err)
|
require.NoError(tb, err)
|
||||||
|
|
||||||
dayRange := agd.DayRange{
|
dayIvl := &filter.DayInterval{
|
||||||
Start: 0,
|
Start: 0,
|
||||||
End: 59,
|
End: 60,
|
||||||
}
|
}
|
||||||
|
|
||||||
wantParental := &agd.ParentalProtectionSettings{
|
wantParental := &filter.ConfigParental{
|
||||||
Schedule: &agd.ParentalProtectionSchedule{
|
PauseSchedule: &filter.ConfigSchedule{
|
||||||
Week: &agd.WeeklySchedule{
|
Week: &filter.WeeklySchedule{
|
||||||
agd.ZeroLengthDayRange(),
|
nil,
|
||||||
dayRange,
|
dayIvl,
|
||||||
dayRange,
|
dayIvl,
|
||||||
dayRange,
|
dayIvl,
|
||||||
dayRange,
|
dayIvl,
|
||||||
dayRange,
|
dayIvl,
|
||||||
agd.ZeroLengthDayRange(),
|
nil,
|
||||||
},
|
},
|
||||||
TimeZone: wantLoc,
|
TimeZone: wantLoc,
|
||||||
},
|
},
|
||||||
BlockedServices: []agd.BlockedServiceID{"youtube"},
|
BlockedServices: []filter.BlockedServiceID{
|
||||||
|
"youtube",
|
||||||
|
},
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
BlockAdult: false,
|
AdultBlockingEnabled: false,
|
||||||
GeneralSafeSearch: false,
|
SafeSearchGeneralEnabled: false,
|
||||||
YoutubeSafeSearch: false,
|
SafeSearchYouTubeEnabled: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
wantSafeBrowsing := &agd.SafeBrowsingSettings{
|
wantSafeBrowsing := &filter.ConfigSafeBrowsing{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
BlockDangerousDomains: true,
|
DangerousDomainsEnabled: true,
|
||||||
BlockNewlyRegisteredDomains: false,
|
NewlyRegisteredDomainsEnabled: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
wantBlockingMode := &dnsmsg.BlockingModeCustomIP{
|
wantBlockingMode := &dnsmsg.BlockingModeCustomIP{
|
||||||
@ -535,30 +552,39 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
|||||||
}, 1*datasize.KB)
|
}, 1*datasize.KB)
|
||||||
|
|
||||||
return &agd.Profile{
|
return &agd.Profile{
|
||||||
Parental: wantParental,
|
FilterConfig: &filter.ConfigClient{
|
||||||
BlockingMode: wantBlockingMode,
|
Custom: &filter.ConfigCustom{
|
||||||
ID: TestProfileID,
|
ID: TestProfileIDStr,
|
||||||
UpdateTime: TestUpdTime,
|
UpdateTime: TestUpdTime,
|
||||||
|
Rules: []filter.RuleText{"||example.org^"},
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
Parental: wantParental,
|
||||||
|
RuleList: &filter.ConfigRuleList{
|
||||||
|
IDs: []filter.ID{"1"},
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
SafeBrowsing: wantSafeBrowsing,
|
||||||
|
},
|
||||||
|
Access: wantAccess,
|
||||||
|
BlockingMode: wantBlockingMode,
|
||||||
|
Ratelimiter: wantRateLimiter,
|
||||||
|
ID: TestProfileID,
|
||||||
DeviceIDs: []agd.DeviceID{
|
DeviceIDs: []agd.DeviceID{
|
||||||
TestDeviceID,
|
TestDeviceID,
|
||||||
"2222bbbb",
|
"2222bbbb",
|
||||||
"3333cccc",
|
"3333cccc",
|
||||||
"4444dddd",
|
"4444dddd",
|
||||||
},
|
},
|
||||||
RuleListIDs: []agd.FilterListID{"1"},
|
|
||||||
CustomRules: []agd.FilterRuleText{"||example.org^"},
|
|
||||||
FilteredResponseTTL: 10 * time.Second,
|
FilteredResponseTTL: 10 * time.Second,
|
||||||
Ratelimiter: wantRateLimiter,
|
|
||||||
SafeBrowsing: wantSafeBrowsing,
|
|
||||||
Access: wantAccess,
|
|
||||||
RuleListsEnabled: true,
|
|
||||||
FilteringEnabled: true,
|
|
||||||
QueryLogEnabled: true,
|
|
||||||
Deleted: false,
|
|
||||||
BlockPrivateRelay: true,
|
|
||||||
BlockFirefoxCanary: true,
|
|
||||||
IPLogEnabled: true,
|
|
||||||
AutoDevicesEnabled: true,
|
AutoDevicesEnabled: true,
|
||||||
|
BlockChromePrefetch: true,
|
||||||
|
BlockFirefoxCanary: true,
|
||||||
|
BlockPrivateRelay: true,
|
||||||
|
Deleted: false,
|
||||||
|
FilteringEnabled: true,
|
||||||
|
IPLogEnabled: true,
|
||||||
|
QueryLogEnabled: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +657,8 @@ func BenchmarkDNSProfile_ToInternal(b *testing.B) {
|
|||||||
TestUpdTime,
|
TestUpdTime,
|
||||||
TestBind,
|
TestBind,
|
||||||
errColl,
|
errColl,
|
||||||
EmptyMetrics{},
|
TestLogger,
|
||||||
|
EmptyProfileDBMetrics{},
|
||||||
TestRespSzEst,
|
TestRespSzEst,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -639,10 +666,10 @@ func BenchmarkDNSProfile_ToInternal(b *testing.B) {
|
|||||||
require.NotNil(b, profSink)
|
require.NotNil(b, profSink)
|
||||||
require.NoError(b, errSink)
|
require.NoError(b, errSink)
|
||||||
|
|
||||||
// Most recent result, on a ThinkPad X13:
|
// Most recent results:
|
||||||
// goos: linux
|
// goos: linux
|
||||||
// goarch: amd64
|
// goarch: amd64
|
||||||
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/backendpb
|
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/backendpb
|
||||||
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
|
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
|
||||||
// BenchmarkDNSProfile_ToInternal-16 67160 22130 ns/op 3048 B/op 51 allocs/op
|
// BenchmarkDNSProfile_ToInternal-16 79732 14686 ns/op 3160 B/op 59 allocs/op
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,16 @@ type ProfileStorageConfig struct {
|
|||||||
// non-critical errors. It must not be nil.
|
// non-critical errors. It must not be nil.
|
||||||
ErrColl errcoll.Interface
|
ErrColl errcoll.Interface
|
||||||
|
|
||||||
// Logger is used as the base logger for the profile storage. It must not
|
// Logger is used for logging the operation of the profile storage. It must
|
||||||
// be nil.
|
// not be nil.
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
|
|
||||||
// Metrics is used for the collection of the protobuf errors.
|
// GRPCMetrics is used for the collection of the protobuf communication
|
||||||
Metrics Metrics
|
// statistics.
|
||||||
|
GRPCMetrics GRPCMetrics
|
||||||
|
|
||||||
|
// Metrics is used for the collection of the profiles storage statistics.
|
||||||
|
Metrics ProfileDBMetrics
|
||||||
|
|
||||||
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
||||||
// "grpcs". It must not be nil.
|
// "grpcs". It must not be nil.
|
||||||
@ -63,7 +67,8 @@ type ProfileStorage struct {
|
|||||||
errColl errcoll.Interface
|
errColl errcoll.Interface
|
||||||
client DNSServiceClient
|
client DNSServiceClient
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
metrics Metrics
|
grpcMetrics GRPCMetrics
|
||||||
|
metrics ProfileDBMetrics
|
||||||
apiKey string
|
apiKey string
|
||||||
respSzEst datasize.ByteSize
|
respSzEst datasize.ByteSize
|
||||||
maxProfSize datasize.ByteSize
|
maxProfSize datasize.ByteSize
|
||||||
@ -83,6 +88,7 @@ func NewProfileStorage(c *ProfileStorageConfig) (s *ProfileStorage, err error) {
|
|||||||
errColl: c.ErrColl,
|
errColl: c.ErrColl,
|
||||||
client: NewDNSServiceClient(client),
|
client: NewDNSServiceClient(client),
|
||||||
logger: c.Logger,
|
logger: c.Logger,
|
||||||
|
grpcMetrics: c.GRPCMetrics,
|
||||||
metrics: c.Metrics,
|
metrics: c.Metrics,
|
||||||
apiKey: c.APIKey,
|
apiKey: c.APIKey,
|
||||||
respSzEst: c.ResponseSizeEstimate,
|
respSzEst: c.ResponseSizeEstimate,
|
||||||
@ -115,7 +121,7 @@ func (s *ProfileStorage) CreateAutoDevice(
|
|||||||
DeviceType: DeviceType(req.DeviceType),
|
DeviceType: DeviceType(req.DeviceType),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calling backend: %w", fixGRPCError(ctx, s.metrics, err))
|
return nil, fmt.Errorf("calling backend: %w", fixGRPCError(ctx, s.grpcMetrics, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := backendResp.Device.toInternal(s.bindSet)
|
d, err := backendResp.Device.toInternal(s.bindSet)
|
||||||
@ -140,7 +146,7 @@ func (s *ProfileStorage) Profiles(
|
|||||||
respSzOpt := grpc.MaxCallRecvMsgSize(int(s.maxProfSize.Bytes()))
|
respSzOpt := grpc.MaxCallRecvMsgSize(int(s.maxProfSize.Bytes()))
|
||||||
stream, err := s.client.GetDNSProfiles(ctx, toProtobuf(req), respSzOpt)
|
stream, err := s.client.GetDNSProfiles(ctx, toProtobuf(req), respSzOpt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("loading profiles: %w", fixGRPCError(ctx, s.metrics, err))
|
return nil, fmt.Errorf("loading profiles: %w", fixGRPCError(ctx, s.grpcMetrics, err))
|
||||||
}
|
}
|
||||||
defer func() { err = errors.WithDeferred(err, stream.CloseSend()) }()
|
defer func() { err = errors.WithDeferred(err, stream.CloseSend()) }()
|
||||||
|
|
||||||
@ -165,7 +171,7 @@ func (s *ProfileStorage) Profiles(
|
|||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"receiving profile #%d: %w",
|
"receiving profile #%d: %w",
|
||||||
n,
|
n,
|
||||||
fixGRPCError(ctx, s.metrics, profErr),
|
fixGRPCError(ctx, s.grpcMetrics, profErr),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
stats.endRecv()
|
stats.endRecv()
|
||||||
@ -176,11 +182,12 @@ func (s *ProfileStorage) Profiles(
|
|||||||
time.Now(),
|
time.Now(),
|
||||||
s.bindSet,
|
s.bindSet,
|
||||||
s.errColl,
|
s.errColl,
|
||||||
|
s.logger,
|
||||||
s.metrics,
|
s.metrics,
|
||||||
s.respSzEst,
|
s.respSzEst,
|
||||||
)
|
)
|
||||||
if profErr != nil {
|
if profErr != nil {
|
||||||
reportf(ctx, s.errColl, "loading profile: %w", profErr)
|
errcoll.Collect(ctx, s.errColl, s.logger, "loading profile", profErr)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
|
||||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -69,8 +68,9 @@ func TestProfileStorage_CreateAutoDevice(t *testing.T) {
|
|||||||
s, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
s, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
||||||
BindSet: backendpb.TestBind,
|
BindSet: backendpb.TestBind,
|
||||||
ErrColl: agdtest.NewErrorCollector(),
|
ErrColl: agdtest.NewErrorCollector(),
|
||||||
Logger: slogutil.NewDiscardLogger(),
|
Logger: backendpb.TestLogger,
|
||||||
Metrics: backendpb.EmptyMetrics{},
|
GRPCMetrics: backendpb.EmptyGRPCMetrics{},
|
||||||
|
Metrics: backendpb.EmptyProfileDBMetrics{},
|
||||||
Endpoint: &url.URL{
|
Endpoint: &url.URL{
|
||||||
Scheme: "grpc",
|
Scheme: "grpc",
|
||||||
Host: l.Addr().String(),
|
Host: l.Addr().String(),
|
||||||
@ -159,8 +159,9 @@ func BenchmarkProfileStorage_Profiles(b *testing.B) {
|
|||||||
s, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
s, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
||||||
BindSet: netip.MustParsePrefix("0.0.0.0/0"),
|
BindSet: netip.MustParsePrefix("0.0.0.0/0"),
|
||||||
ErrColl: agdtest.NewErrorCollector(),
|
ErrColl: agdtest.NewErrorCollector(),
|
||||||
Logger: slogutil.NewDiscardLogger(),
|
Logger: backendpb.TestLogger,
|
||||||
Metrics: backendpb.EmptyMetrics{},
|
GRPCMetrics: backendpb.EmptyGRPCMetrics{},
|
||||||
|
Metrics: backendpb.EmptyProfileDBMetrics{},
|
||||||
Endpoint: &url.URL{
|
Endpoint: &url.URL{
|
||||||
Scheme: "grpc",
|
Scheme: "grpc",
|
||||||
Host: l.Addr().String(),
|
Host: l.Addr().String(),
|
||||||
@ -195,8 +196,10 @@ func BenchmarkProfileStorage_Profiles(b *testing.B) {
|
|||||||
require.NoError(b, errSink)
|
require.NoError(b, errSink)
|
||||||
require.NotNil(b, respSink)
|
require.NotNil(b, respSink)
|
||||||
|
|
||||||
// goos: darwin
|
// Most recent results:
|
||||||
// goarch: arm64
|
// goos: linux
|
||||||
|
// goarch: amd64
|
||||||
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/backendpb
|
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/backendpb
|
||||||
// BenchmarkProfileStorage_Profiles-8 11599 104725 ns/op 18281 B/op 328 allocs/op
|
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
|
||||||
|
// BenchmarkProfileStorage_Profiles-16 4501 258657 ns/op 20020 B/op 350 allocs/op
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,9 @@ type RateLimiterConfig struct {
|
|||||||
// not be nil.
|
// not be nil.
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
|
|
||||||
// GRPCMetrics is used for the collection of the protobuf errors.
|
// GRPCMetrics is used for the collection of the protobuf communication
|
||||||
GRPCMetrics Metrics
|
// statistics.
|
||||||
|
GRPCMetrics GRPCMetrics
|
||||||
|
|
||||||
// Metrics is used to collect allowlist statistics.
|
// Metrics is used to collect allowlist statistics.
|
||||||
Metrics consul.Metrics
|
Metrics consul.Metrics
|
||||||
@ -44,7 +45,7 @@ type RateLimiterConfig struct {
|
|||||||
// that retrieves the rate limit settings from the business logic backend.
|
// that retrieves the rate limit settings from the business logic backend.
|
||||||
type RateLimiter struct {
|
type RateLimiter struct {
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
grpcMetrics Metrics
|
grpcMetrics GRPCMetrics
|
||||||
metrics consul.Metrics
|
metrics consul.Metrics
|
||||||
allowlist *ratelimit.DynamicAllowlist
|
allowlist *ratelimit.DynamicAllowlist
|
||||||
errColl errcoll.Interface
|
errColl errcoll.Interface
|
||||||
@ -92,7 +93,7 @@ func (l *RateLimiter) Refresh(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
allowedSubnets := backendResp.AllowedSubnets
|
allowedSubnets := backendResp.AllowedSubnets
|
||||||
prefixes := cidrRangeToInternal(ctx, l.errColl, allowedSubnets)
|
prefixes := cidrRangeToInternal(ctx, l.errColl, l.logger, allowedSubnets)
|
||||||
l.allowlist.Update(prefixes)
|
l.allowlist.Update(prefixes)
|
||||||
|
|
||||||
l.logger.InfoContext(ctx, "refresh successful", "num_records", len(prefixes))
|
l.logger.InfoContext(ctx, "refresh successful", "num_records", len(prefixes))
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
||||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -83,9 +82,9 @@ func TestRateLimiter_Refresh(t *testing.T) {
|
|||||||
|
|
||||||
allowlist := ratelimit.NewDynamicAllowlist(nil, nil)
|
allowlist := ratelimit.NewDynamicAllowlist(nil, nil)
|
||||||
l, err := backendpb.NewRateLimiter(&backendpb.RateLimiterConfig{
|
l, err := backendpb.NewRateLimiter(&backendpb.RateLimiterConfig{
|
||||||
Logger: slogutil.NewDiscardLogger(),
|
Logger: backendpb.TestLogger,
|
||||||
Metrics: consul.EmptyMetrics{},
|
Metrics: consul.EmptyMetrics{},
|
||||||
GRPCMetrics: backendpb.EmptyMetrics{},
|
GRPCMetrics: backendpb.EmptyGRPCMetrics{},
|
||||||
Allowlist: allowlist,
|
Allowlist: allowlist,
|
||||||
Endpoint: &url.URL{
|
Endpoint: &url.URL{
|
||||||
Scheme: "grpc",
|
Scheme: "grpc",
|
||||||
|
@ -7,18 +7,20 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv"
|
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv"
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoteKVConfig is the configuration for the business logic backend key-value
|
// RemoteKVConfig is the configuration for the business logic backend key-value
|
||||||
// storage.
|
// storage.
|
||||||
type RemoteKVConfig struct {
|
type RemoteKVConfig struct {
|
||||||
// Metrics is used for the collection of the remote key-value storage
|
// Metrics is used for the collection of the backend remote key-value
|
||||||
|
// storage statistics.
|
||||||
|
Metrics RemoteKVMetrics
|
||||||
|
|
||||||
|
// GRPCMetrics is used for the collection of the protobuf communication
|
||||||
// statistics.
|
// statistics.
|
||||||
//
|
GRPCMetrics GRPCMetrics
|
||||||
// TODO(e.burkov): Perhaps, it worths of a separate metrics interface,
|
|
||||||
// since it's only used for the collection of the protobuf errors.
|
|
||||||
Metrics Metrics
|
|
||||||
|
|
||||||
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
// Endpoint is the backend API URL. The scheme should be either "grpc" or
|
||||||
// "grpcs".
|
// "grpcs".
|
||||||
@ -35,7 +37,8 @@ type RemoteKVConfig struct {
|
|||||||
// uses the business logic backend as the key-value storage. It is safe for
|
// uses the business logic backend as the key-value storage. It is safe for
|
||||||
// concurrent use.
|
// concurrent use.
|
||||||
type RemoteKV struct {
|
type RemoteKV struct {
|
||||||
metrics Metrics
|
grpcMetrics GRPCMetrics
|
||||||
|
metrics RemoteKVMetrics
|
||||||
client RemoteKVServiceClient
|
client RemoteKVServiceClient
|
||||||
apiKey string
|
apiKey string
|
||||||
ttl time.Duration
|
ttl time.Duration
|
||||||
@ -51,6 +54,7 @@ func NewRemoteKV(c *RemoteKVConfig) (kv *RemoteKV, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &RemoteKV{
|
return &RemoteKV{
|
||||||
|
grpcMetrics: c.GRPCMetrics,
|
||||||
metrics: c.Metrics,
|
metrics: c.Metrics,
|
||||||
client: NewRemoteKVServiceClient(client),
|
client: NewRemoteKVServiceClient(client),
|
||||||
apiKey: c.APIKey,
|
apiKey: c.APIKey,
|
||||||
@ -68,14 +72,34 @@ func (kv *RemoteKV) Get(ctx context.Context, key string) (val []byte, ok bool, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx = ctxWithAuthentication(ctx, kv.apiKey)
|
ctx = ctxWithAuthentication(ctx, kv.apiKey)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
resp, err := kv.client.Get(ctx, req)
|
resp, err := kv.client.Get(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("getting %q key: %w", key, fixGRPCError(ctx, kv.metrics, err))
|
err = fmt.Errorf("getting %q key: %w", key, fixGRPCError(ctx, kv.grpcMetrics, err))
|
||||||
|
|
||||||
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
val = resp.GetData()
|
kv.metrics.ObserveOperation(ctx, RemoteKVOpGet, time.Since(start))
|
||||||
|
|
||||||
return val, val != nil, nil
|
defer func() { kv.metrics.IncrementLookups(ctx, ok) }()
|
||||||
|
|
||||||
|
received := resp.GetValue()
|
||||||
|
|
||||||
|
switch received := received.(type) {
|
||||||
|
case *RemoteKVGetResponse_Data:
|
||||||
|
return received.Data, true, nil
|
||||||
|
case *RemoteKVGetResponse_Empty:
|
||||||
|
return nil, false, nil
|
||||||
|
default:
|
||||||
|
return nil, false, fmt.Errorf(
|
||||||
|
"getting %q key: response type: %w: %T(%[3]v)",
|
||||||
|
key,
|
||||||
|
errors.ErrBadEnumValue,
|
||||||
|
received,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set implements the [remotekv.Interface] interface for *RemoteKV.
|
// Set implements the [remotekv.Interface] interface for *RemoteKV.
|
||||||
@ -87,10 +111,14 @@ func (kv *RemoteKV) Set(ctx context.Context, key string, val []byte) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx = ctxWithAuthentication(ctx, kv.apiKey)
|
ctx = ctxWithAuthentication(ctx, kv.apiKey)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
_, err = kv.client.Set(ctx, req)
|
_, err = kv.client.Set(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setting %q key: %w", key, fixGRPCError(ctx, kv.metrics, err))
|
return fmt.Errorf("setting %q key: %w", key, fixGRPCError(ctx, kv.grpcMetrics, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kv.metrics.ObserveOperation(ctx, RemoteKVOpSet, time.Since(start))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,8 @@ func TestRemoteKV_Get(t *testing.T) {
|
|||||||
t.Cleanup(grpcSrv.GracefulStop)
|
t.Cleanup(grpcSrv.GracefulStop)
|
||||||
|
|
||||||
kv, err := backendpb.NewRemoteKV(&backendpb.RemoteKVConfig{
|
kv, err := backendpb.NewRemoteKV(&backendpb.RemoteKVConfig{
|
||||||
Metrics: backendpb.EmptyMetrics{},
|
GRPCMetrics: backendpb.EmptyGRPCMetrics{},
|
||||||
|
Metrics: backendpb.EmptyRemoteKVMetrics{},
|
||||||
Endpoint: &url.URL{
|
Endpoint: &url.URL{
|
||||||
Scheme: "grpc",
|
Scheme: "grpc",
|
||||||
Host: l.Addr().String(),
|
Host: l.Addr().String(),
|
||||||
|
@ -54,7 +54,7 @@ func (s *profilesCallStats) endDec() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// report writes the statistics to the log and the metrics.
|
// report writes the statistics to the log and the metrics.
|
||||||
func (s *profilesCallStats) report(ctx context.Context, mtrc Metrics) {
|
func (s *profilesCallStats) report(ctx context.Context, mtrc ProfileDBMetrics) {
|
||||||
lvl := slog.LevelDebug
|
lvl := slog.LevelDebug
|
||||||
if s.isFullSync {
|
if s.isFullSync {
|
||||||
lvl = slog.LevelInfo
|
lvl = slog.LevelInfo
|
||||||
|
@ -54,7 +54,9 @@ func newChanPacketConn(
|
|||||||
sessions: sessions,
|
sessions: sessions,
|
||||||
writeRequests: writeRequests,
|
writeRequests: writeRequests,
|
||||||
|
|
||||||
sessionsGauge: metrics.BindToDeviceUDPSessionsChanSize.WithLabelValues(subnet.String()),
|
sessionsGauge: metrics.BindToDeviceUDPSessionsChanSize.WithLabelValues(
|
||||||
|
subnet.String(),
|
||||||
|
),
|
||||||
writeRequestsGauge: writeRequestsGauge,
|
writeRequestsGauge: writeRequestsGauge,
|
||||||
|
|
||||||
deadlineMu: &sync.RWMutex{},
|
deadlineMu: &sync.RWMutex{},
|
||||||
|
@ -70,7 +70,12 @@ func listenControlWithSO(
|
|||||||
opts,
|
opts,
|
||||||
newIntSetSockOptFunc("IP_RECVORIGDSTADDR", unix.IPPROTO_IP, unix.IP_RECVORIGDSTADDR, 1),
|
newIntSetSockOptFunc("IP_RECVORIGDSTADDR", unix.IPPROTO_IP, unix.IP_RECVORIGDSTADDR, 1),
|
||||||
newIntSetSockOptFunc("IP_FREEBIND", unix.IPPROTO_IP, unix.IP_FREEBIND, 1),
|
newIntSetSockOptFunc("IP_FREEBIND", unix.IPPROTO_IP, unix.IP_FREEBIND, 1),
|
||||||
newIntSetSockOptFunc("IPV6_RECVORIGDSTADDR", unix.IPPROTO_IPV6, unix.IPV6_RECVORIGDSTADDR, 1),
|
newIntSetSockOptFunc(
|
||||||
|
"IPV6_RECVORIGDSTADDR",
|
||||||
|
unix.IPPROTO_IPV6,
|
||||||
|
unix.IPV6_RECVORIGDSTADDR,
|
||||||
|
1,
|
||||||
|
),
|
||||||
newIntSetSockOptFunc("IPV6_FREEBIND", unix.IPPROTO_IPV6, unix.IPV6_FREEBIND, 1),
|
newIntSetSockOptFunc("IPV6_FREEBIND", unix.IPPROTO_IPV6, unix.IPV6_FREEBIND, 1),
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
|
@ -6,14 +6,9 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,24 +86,3 @@ func initProfDB(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBillStatUploader creates and returns a billstat uploader depending on the
|
|
||||||
// provided API URL.
|
|
||||||
func newBillStatUploader(
|
|
||||||
envs *environment,
|
|
||||||
errColl errcoll.Interface,
|
|
||||||
mtrc backendpb.Metrics,
|
|
||||||
) (s billstat.Uploader, err error) {
|
|
||||||
apiURL := netutil.CloneURL(&envs.BillStatURL.URL)
|
|
||||||
err = urlutil.ValidateGRPCURL(apiURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("billstat api url: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return backendpb.NewBillStat(&backendpb.BillStatConfig{
|
|
||||||
ErrColl: errColl,
|
|
||||||
Metrics: mtrc,
|
|
||||||
Endpoint: apiURL,
|
|
||||||
APIKey: envs.BillStatAPIKey,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||||
@ -32,6 +33,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnssvc"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnssvc"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter/filterstorage"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
@ -57,6 +59,7 @@ const (
|
|||||||
debugIDProfileDB = "profiledb"
|
debugIDProfileDB = "profiledb"
|
||||||
debugIDRuleStat = "rulestat"
|
debugIDRuleStat = "rulestat"
|
||||||
debugIDTicketRotator = "ticket_rotator"
|
debugIDTicketRotator = "ticket_rotator"
|
||||||
|
debugIDTLSConfig = "tlsconfig"
|
||||||
debugIDWebSvc = "websvc"
|
debugIDWebSvc = "websvc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,6 +79,7 @@ type builder struct {
|
|||||||
cacheManager *agdcache.DefaultManager
|
cacheManager *agdcache.DefaultManager
|
||||||
cloner *dnsmsg.Cloner
|
cloner *dnsmsg.Cloner
|
||||||
conf *configuration
|
conf *configuration
|
||||||
|
debugRefrs debugsvc.Refreshers
|
||||||
env *environment
|
env *environment
|
||||||
errColl errcoll.Interface
|
errColl errcoll.Interface
|
||||||
geoIPError chan error
|
geoIPError chan error
|
||||||
@ -91,7 +95,7 @@ type builder struct {
|
|||||||
access *access.Global
|
access *access.Global
|
||||||
adultBlocking *hashprefix.Filter
|
adultBlocking *hashprefix.Filter
|
||||||
adultBlockingHashes *hashprefix.Storage
|
adultBlockingHashes *hashprefix.Storage
|
||||||
backendGRPCMtrc *metrics.BackendPB
|
backendGRPCMtrc *metrics.BackendGRPC
|
||||||
billStat billstat.Recorder
|
billStat billstat.Recorder
|
||||||
bindSet netutil.SubnetSet
|
bindSet netutil.SubnetSet
|
||||||
btdManager *bindtodevice.Manager
|
btdManager *bindtodevice.Manager
|
||||||
@ -100,7 +104,8 @@ type builder struct {
|
|||||||
dnsCheck dnscheck.Interface
|
dnsCheck dnscheck.Interface
|
||||||
dnsDB dnsdb.Interface
|
dnsDB dnsdb.Interface
|
||||||
dnsSvc *dnssvc.Service
|
dnsSvc *dnssvc.Service
|
||||||
filterStorage *filter.DefaultStorage
|
filterMtrc filter.Metrics
|
||||||
|
filterStorage *filterstorage.Default
|
||||||
filteringGroups map[agd.FilteringGroupID]*agd.FilteringGroup
|
filteringGroups map[agd.FilteringGroupID]*agd.FilteringGroup
|
||||||
fwdHandler *forward.Handler
|
fwdHandler *forward.Handler
|
||||||
geoIP *geoip.File
|
geoIP *geoip.File
|
||||||
@ -110,12 +115,11 @@ type builder struct {
|
|||||||
newRegDomainsHashes *hashprefix.Storage
|
newRegDomainsHashes *hashprefix.Storage
|
||||||
profileDB profiledb.Interface
|
profileDB profiledb.Interface
|
||||||
rateLimit *ratelimit.Backoff
|
rateLimit *ratelimit.Backoff
|
||||||
debugRefrs debugsvc.Refreshers
|
|
||||||
ruleStat rulestat.Interface
|
ruleStat rulestat.Interface
|
||||||
safeBrowsing *hashprefix.Filter
|
safeBrowsing *hashprefix.Filter
|
||||||
safeBrowsingHashes *hashprefix.Storage
|
safeBrowsingHashes *hashprefix.Storage
|
||||||
sdeConf *dnsmsg.StructuredDNSErrorsConfig
|
sdeConf *dnsmsg.StructuredDNSErrorsConfig
|
||||||
tlsMtrc tlsconfig.Metrics
|
tlsManager *tlsconfig.DefaultManager
|
||||||
webSvc *websvc.Service
|
webSvc *websvc.Service
|
||||||
|
|
||||||
// The fields below are initialized later, just like with the fields above,
|
// The fields below are initialized later, just like with the fields above,
|
||||||
@ -201,8 +205,8 @@ func (b *builder) initGeoIP(ctx context.Context) {
|
|||||||
CacheManager: b.cacheManager,
|
CacheManager: b.cacheManager,
|
||||||
ASNPath: asn,
|
ASNPath: asn,
|
||||||
CountryPath: ctry,
|
CountryPath: ctry,
|
||||||
HostCacheSize: c.HostCacheSize,
|
HostCacheCount: c.HostCacheSize,
|
||||||
IPCacheSize: c.IPCacheSize,
|
IPCacheCount: c.IPCacheSize,
|
||||||
AllTopASNs: geoip.DefaultTopASNs,
|
AllTopASNs: geoip.DefaultTopASNs,
|
||||||
CountryTopASNs: geoip.DefaultCountryTopASNs,
|
CountryTopASNs: geoip.DefaultCountryTopASNs,
|
||||||
})
|
})
|
||||||
@ -225,6 +229,11 @@ func (b *builder) initHashPrefixFilters(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
matchers := map[string]*hashprefix.Storage{}
|
matchers := map[string]*hashprefix.Storage{}
|
||||||
|
|
||||||
|
b.filterMtrc, err = metrics.NewFilter(b.mtrcNamespace, b.promRegisterer)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("registering filter metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(a.garipov): Merge the three functions below together.
|
// TODO(a.garipov): Merge the three functions below together.
|
||||||
|
|
||||||
err = b.initAdultBlocking(ctx, matchers, maxSize, cacheDir)
|
err = b.initAdultBlocking(ctx, matchers, maxSize, cacheDir)
|
||||||
@ -251,8 +260,7 @@ func (b *builder) initHashPrefixFilters(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
// initAdultBlocking initializes the adult-blocking filter and hash storage. It
|
// initAdultBlocking initializes the adult-blocking filter and hash storage. It
|
||||||
// also adds the refresher with ID
|
// also adds the refresher with ID
|
||||||
// [hashprefix.IDPrefix]/[agd.FilterListIDAdultBlocking] to the debug
|
// [hashprefix.IDPrefix]/[filter.IDAdultBlocking] to the debug refreshers.
|
||||||
// refreshers.
|
|
||||||
//
|
//
|
||||||
// It must be called from [builder.initHashPrefixFilters].
|
// It must be called from [builder.initHashPrefixFilters].
|
||||||
func (b *builder) initAdultBlocking(
|
func (b *builder) initAdultBlocking(
|
||||||
@ -272,7 +280,7 @@ func (b *builder) initAdultBlocking(
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := b.conf.AdultBlocking
|
c := b.conf.AdultBlocking
|
||||||
id := agd.FilterListIDAdultBlocking
|
id := filter.IDAdultBlocking
|
||||||
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
||||||
b.adultBlocking, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
b.adultBlocking, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
||||||
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
||||||
@ -281,6 +289,7 @@ func (b *builder) initAdultBlocking(
|
|||||||
Hashes: b.adultBlockingHashes,
|
Hashes: b.adultBlockingHashes,
|
||||||
URL: &b.env.AdultBlockingURL.URL,
|
URL: &b.env.AdultBlockingURL.URL,
|
||||||
ErrColl: b.errColl,
|
ErrColl: b.errColl,
|
||||||
|
Metrics: b.filterMtrc,
|
||||||
ID: id,
|
ID: id,
|
||||||
CachePath: filepath.Join(cacheDir, string(id)),
|
CachePath: filepath.Join(cacheDir, string(id)),
|
||||||
ReplacementHost: c.BlockHost,
|
ReplacementHost: c.BlockHost,
|
||||||
@ -289,7 +298,7 @@ func (b *builder) initAdultBlocking(
|
|||||||
CacheTTL: c.CacheTTL.Duration,
|
CacheTTL: c.CacheTTL.Duration,
|
||||||
// TODO(a.garipov): Make all sizes [datasize.ByteSize] and rename cache
|
// TODO(a.garipov): Make all sizes [datasize.ByteSize] and rename cache
|
||||||
// entity counts to fooCount.
|
// entity counts to fooCount.
|
||||||
CacheSize: c.CacheSize,
|
CacheCount: c.CacheSize,
|
||||||
MaxSize: maxSize,
|
MaxSize: maxSize,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -327,8 +336,7 @@ func (b *builder) initAdultBlocking(
|
|||||||
|
|
||||||
// initNewRegDomains initializes the newly-registered domain filter and hash
|
// initNewRegDomains initializes the newly-registered domain filter and hash
|
||||||
// storage. It also adds the refresher with ID
|
// storage. It also adds the refresher with ID
|
||||||
// [hashprefix.IDPrefix]/[agd.FilterListIDNewRegDomains] to the debug
|
// [hashprefix.IDPrefix]/[filter.IDNewRegDomains] to the debug refreshers.
|
||||||
// refreshers.
|
|
||||||
//
|
//
|
||||||
// It must be called from [builder.initHashPrefixFilters].
|
// It must be called from [builder.initHashPrefixFilters].
|
||||||
func (b *builder) initNewRegDomains(
|
func (b *builder) initNewRegDomains(
|
||||||
@ -349,7 +357,7 @@ func (b *builder) initNewRegDomains(
|
|||||||
// Reuse the general safe-browsing filter configuration with a new URL and
|
// Reuse the general safe-browsing filter configuration with a new URL and
|
||||||
// ID.
|
// ID.
|
||||||
c := b.conf.SafeBrowsing
|
c := b.conf.SafeBrowsing
|
||||||
id := agd.FilterListIDNewRegDomains
|
id := filter.IDNewRegDomains
|
||||||
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
||||||
b.newRegDomains, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
b.newRegDomains, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
||||||
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
||||||
@ -358,13 +366,14 @@ func (b *builder) initNewRegDomains(
|
|||||||
Hashes: b.newRegDomainsHashes,
|
Hashes: b.newRegDomainsHashes,
|
||||||
URL: &b.env.NewRegDomainsURL.URL,
|
URL: &b.env.NewRegDomainsURL.URL,
|
||||||
ErrColl: b.errColl,
|
ErrColl: b.errColl,
|
||||||
|
Metrics: b.filterMtrc,
|
||||||
ID: id,
|
ID: id,
|
||||||
CachePath: filepath.Join(cacheDir, string(id)),
|
CachePath: filepath.Join(cacheDir, string(id)),
|
||||||
ReplacementHost: c.BlockHost,
|
ReplacementHost: c.BlockHost,
|
||||||
Staleness: c.RefreshIvl.Duration,
|
Staleness: c.RefreshIvl.Duration,
|
||||||
RefreshTimeout: c.RefreshTimeout.Duration,
|
RefreshTimeout: c.RefreshTimeout.Duration,
|
||||||
CacheTTL: c.CacheTTL.Duration,
|
CacheTTL: c.CacheTTL.Duration,
|
||||||
CacheSize: c.CacheSize,
|
CacheCount: c.CacheSize,
|
||||||
MaxSize: maxSize,
|
MaxSize: maxSize,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -399,8 +408,8 @@ func (b *builder) initNewRegDomains(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initSafeBrowsing initializes the safe-browsing filter and hash storage. It
|
// initSafeBrowsing initializes the safe-browsing filter and hash storage. It
|
||||||
// also adds the refresher with ID
|
// also adds the refresher with ID [hashprefix.IDPrefix]/[filter.IDSafeBrowsing]
|
||||||
// [hashprefix.IDPrefix]/[agd.FilterListIDSafeBrowsing] to the debug refreshers.
|
// to the debug refreshers.
|
||||||
//
|
//
|
||||||
// It must be called from [builder.initHashPrefixFilters].
|
// It must be called from [builder.initHashPrefixFilters].
|
||||||
func (b *builder) initSafeBrowsing(
|
func (b *builder) initSafeBrowsing(
|
||||||
@ -420,7 +429,7 @@ func (b *builder) initSafeBrowsing(
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := b.conf.SafeBrowsing
|
c := b.conf.SafeBrowsing
|
||||||
id := agd.FilterListIDSafeBrowsing
|
id := filter.IDSafeBrowsing
|
||||||
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
prefix := path.Join(hashprefix.IDPrefix, string(id))
|
||||||
b.safeBrowsing, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
b.safeBrowsing, err = hashprefix.NewFilter(&hashprefix.FilterConfig{
|
||||||
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, prefix),
|
||||||
@ -429,13 +438,14 @@ func (b *builder) initSafeBrowsing(
|
|||||||
Hashes: b.safeBrowsingHashes,
|
Hashes: b.safeBrowsingHashes,
|
||||||
URL: &b.env.SafeBrowsingURL.URL,
|
URL: &b.env.SafeBrowsingURL.URL,
|
||||||
ErrColl: b.errColl,
|
ErrColl: b.errColl,
|
||||||
|
Metrics: b.filterMtrc,
|
||||||
ID: id,
|
ID: id,
|
||||||
CachePath: filepath.Join(cacheDir, string(id)),
|
CachePath: filepath.Join(cacheDir, string(id)),
|
||||||
ReplacementHost: c.BlockHost,
|
ReplacementHost: c.BlockHost,
|
||||||
Staleness: c.RefreshIvl.Duration,
|
Staleness: c.RefreshIvl.Duration,
|
||||||
RefreshTimeout: c.RefreshTimeout.Duration,
|
RefreshTimeout: c.RefreshTimeout.Duration,
|
||||||
CacheTTL: c.CacheTTL.Duration,
|
CacheTTL: c.CacheTTL.Duration,
|
||||||
CacheSize: c.CacheSize,
|
CacheCount: c.CacheSize,
|
||||||
MaxSize: maxSize,
|
MaxSize: maxSize,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -477,26 +487,78 @@ func (b *builder) initSafeBrowsing(
|
|||||||
// [builder.initHashPrefixFilters] must be called before this method.
|
// [builder.initHashPrefixFilters] must be called before this method.
|
||||||
func (b *builder) initFilterStorage(ctx context.Context) (err error) {
|
func (b *builder) initFilterStorage(ctx context.Context) (err error) {
|
||||||
c := b.conf.Filters
|
c := b.conf.Filters
|
||||||
b.filterStorage = filter.NewDefaultStorage(c.toInternal(
|
refrIvl := c.RefreshIvl.Duration
|
||||||
b.baseLogger,
|
refrTimeout := c.RefreshTimeout.Duration
|
||||||
b.errColl,
|
|
||||||
b.cacheManager,
|
|
||||||
b.env,
|
|
||||||
b.safeBrowsing,
|
|
||||||
b.adultBlocking,
|
|
||||||
b.newRegDomains,
|
|
||||||
))
|
|
||||||
|
|
||||||
err = b.filterStorage.RefreshInitial(ctx)
|
b.filterStorage, err = filterstorage.New(&filterstorage.Config{
|
||||||
|
BaseLogger: b.baseLogger,
|
||||||
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, filter.StoragePrefix),
|
||||||
|
BlockedServices: &filterstorage.ConfigBlockedServices{
|
||||||
|
IndexURL: &b.env.BlockedServiceIndexURL.URL,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
IndexMaxSize: c.MaxSize,
|
||||||
|
// TODO(a.garipov): Consider making configurable.
|
||||||
|
IndexRefreshTimeout: 3 * time.Minute,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
IndexStaleness: refrIvl,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
ResultCacheCount: c.RuleListCache.Size,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
ResultCacheEnabled: c.RuleListCache.Enabled,
|
||||||
|
Enabled: bool(b.env.BlockedServiceEnabled),
|
||||||
|
},
|
||||||
|
Custom: &filterstorage.ConfigCustom{
|
||||||
|
CacheCount: c.CustomFilterCacheSize,
|
||||||
|
},
|
||||||
|
HashPrefix: &filterstorage.ConfigHashPrefix{
|
||||||
|
Adult: b.adultBlocking,
|
||||||
|
Dangerous: b.safeBrowsing,
|
||||||
|
NewlyRegistered: b.newRegDomains,
|
||||||
|
},
|
||||||
|
RuleLists: &filterstorage.ConfigRuleLists{
|
||||||
|
IndexURL: &b.env.FilterIndexURL.URL,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
IndexMaxSize: c.MaxSize,
|
||||||
|
MaxSize: c.MaxSize,
|
||||||
|
IndexRefreshTimeout: c.IndexRefreshTimeout.Duration,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
IndexStaleness: refrIvl,
|
||||||
|
RefreshTimeout: refrTimeout,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
Staleness: refrIvl,
|
||||||
|
ResultCacheCount: c.RuleListCache.Size,
|
||||||
|
ResultCacheEnabled: c.RuleListCache.Enabled,
|
||||||
|
},
|
||||||
|
SafeSearchGeneral: b.newSafeSearchConfig(
|
||||||
|
b.env.GeneralSafeSearchURL,
|
||||||
|
filter.IDGeneralSafeSearch,
|
||||||
|
bool(b.env.GeneralSafeSearchEnabled),
|
||||||
|
),
|
||||||
|
SafeSearchYouTube: b.newSafeSearchConfig(
|
||||||
|
b.env.YoutubeSafeSearchURL,
|
||||||
|
filter.IDYoutubeSafeSearch,
|
||||||
|
bool(b.env.YoutubeSafeSearchEnabled),
|
||||||
|
),
|
||||||
|
CacheManager: b.cacheManager,
|
||||||
|
Clock: agdtime.SystemClock{},
|
||||||
|
ErrColl: b.errColl,
|
||||||
|
Metrics: b.filterMtrc,
|
||||||
|
CacheDir: b.env.FilterCachePath,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating default filter storage: %w", err)
|
return fmt.Errorf("creating default filter storage: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = b.filterStorage.RefreshInitial(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("refreshing default filter storage: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: newCtxWithTimeoutCons(c.RefreshIvl.Duration),
|
Context: newCtxWithTimeoutCons(refrTimeout),
|
||||||
Refresher: b.filterStorage,
|
Refresher: b.filterStorage,
|
||||||
Logger: b.baseLogger.With(slogutil.KeyPrefix, "filters/storage_refresh"),
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, "filters/storage_refresh"),
|
||||||
Interval: c.RefreshIvl.Duration,
|
Interval: refrIvl,
|
||||||
RefreshOnShutdown: false,
|
RefreshOnShutdown: false,
|
||||||
RandomizeStart: false,
|
RandomizeStart: false,
|
||||||
})
|
})
|
||||||
@ -514,6 +576,35 @@ func (b *builder) initFilterStorage(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newSafeSearchConfig returns a new safe-search configuration for the given URL
|
||||||
|
// and ID if enabled; otherwise, it returns an empty configuration.
|
||||||
|
func (b *builder) newSafeSearchConfig(
|
||||||
|
u *urlutil.URL,
|
||||||
|
id filter.ID,
|
||||||
|
enabled bool,
|
||||||
|
) (c *filterstorage.ConfigSafeSearch) {
|
||||||
|
if !enabled {
|
||||||
|
return &filterstorage.ConfigSafeSearch{}
|
||||||
|
}
|
||||||
|
|
||||||
|
fltConf := b.conf.Filters
|
||||||
|
|
||||||
|
return &filterstorage.ConfigSafeSearch{
|
||||||
|
URL: &u.URL,
|
||||||
|
ID: id,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
MaxSize: fltConf.MaxSize,
|
||||||
|
// TODO(a.garipov): Consider making this configurable.
|
||||||
|
ResultCacheTTL: 1 * time.Hour,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
RefreshTimeout: fltConf.RefreshTimeout.Duration,
|
||||||
|
// TODO(a.garipov): Consider adding a separate parameter here.
|
||||||
|
Staleness: fltConf.RefreshIvl.Duration,
|
||||||
|
ResultCacheCount: fltConf.SafeSearchCacheSize,
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// initFilteringGroups initializes the filtering groups.
|
// initFilteringGroups initializes the filtering groups.
|
||||||
//
|
//
|
||||||
// [builder.initFilterStorage] must be called before this method.
|
// [builder.initFilterStorage] must be called before this method.
|
||||||
@ -606,26 +697,54 @@ func (b *builder) initMsgConstructor(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initTLSManager initializes the TLS manager and the TLS-related metrics. It
|
||||||
|
// also adds the refresher with ID [debugIDTLSConfig] to the debug refreshers.
|
||||||
|
func (b *builder) initTLSManager(ctx context.Context) (err error) {
|
||||||
|
mtrc, err := metrics.NewTLSConfig(b.mtrcNamespace, b.promRegisterer)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("registering tls metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logFile := b.env.SSLKeyLogFile
|
||||||
|
if logFile != "" {
|
||||||
|
b.logger.WarnContext(ctx, "tls key logging is enabled", "file", logFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
ticketPaths := b.conf.ServerGroups.collectSessTicketPaths()
|
||||||
|
|
||||||
|
mgr, err := tlsconfig.NewDefaultManager(&tlsconfig.DefaultManagerConfig{
|
||||||
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, "tlsconfig"),
|
||||||
|
ErrColl: b.errColl,
|
||||||
|
Metrics: mtrc,
|
||||||
|
KeyLogFilename: logFile,
|
||||||
|
SessionTicketPaths: ticketPaths,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("initializing tls manager: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.tlsManager = mgr
|
||||||
|
b.debugRefrs[debugIDTLSConfig] = mgr
|
||||||
|
|
||||||
|
b.logger.DebugContext(ctx, "initialized tls manager")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// initServerGroups initializes the server groups.
|
// initServerGroups initializes the server groups.
|
||||||
//
|
//
|
||||||
// The following methods must be called before this one:
|
// The following methods must be called before this one:
|
||||||
// - [builder.initBindToDevice]
|
// - [builder.initBindToDevice]
|
||||||
// - [builder.initFilteringGroups]
|
// - [builder.initFilteringGroups]
|
||||||
// - [builder.initMsgConstructor]
|
// - [builder.initMsgConstructor]
|
||||||
|
// - [builder.initTLSManager]
|
||||||
func (b *builder) initServerGroups(ctx context.Context) (err error) {
|
func (b *builder) initServerGroups(ctx context.Context) (err error) {
|
||||||
mtrc, err := metrics.NewTLSConfig(b.mtrcNamespace, b.promRegisterer)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("registering tls metrics: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.tlsMtrc = mtrc
|
|
||||||
|
|
||||||
c := b.conf
|
c := b.conf
|
||||||
b.serverGroups, err = c.ServerGroups.toInternal(
|
b.serverGroups, err = c.ServerGroups.toInternal(
|
||||||
ctx,
|
ctx,
|
||||||
mtrc,
|
|
||||||
b.messages,
|
b.messages,
|
||||||
b.btdManager,
|
b.btdManager,
|
||||||
|
b.tlsManager,
|
||||||
b.filteringGroups,
|
b.filteringGroups,
|
||||||
c.RateLimit,
|
c.RateLimit,
|
||||||
c.DNS,
|
c.DNS,
|
||||||
@ -699,22 +818,12 @@ func (b *builder) startBindToDevice(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initTLS initializes the optional TLS key logging and session-ticket rotation.
|
// initTicketRotator initializes the TLS session ticket rotator. It also adds
|
||||||
// It also adds the refresher with ID [debugIDTicketRotator] to the debug
|
// the refresher with ID [debugIDTicketRotator] to the debug refreshers.
|
||||||
// refreshers.
|
|
||||||
//
|
//
|
||||||
// [builder.initServerGroups] must be called before this method.
|
// [builder.initTLSManager] must be called before this method.
|
||||||
func (b *builder) initTLS(ctx context.Context) (err error) {
|
func (b *builder) initTicketRotator(ctx context.Context) (err error) {
|
||||||
if f := b.env.SSLKeyLogFile; f != "" {
|
tickRot := agdservice.RefresherFunc(b.tlsManager.RotateTickets)
|
||||||
b.logger.WarnContext(ctx, "IMPORTANT: TLS KEY LOGGING IS ENABLED", "ssl_key_log_file", f)
|
|
||||||
|
|
||||||
err = enableTLSKeyLogging(b.serverGroups, f)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("enabling tls key logging: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tickRot := newTicketRotator(b.baseLogger, b.errColl, b.tlsMtrc, b.serverGroups)
|
|
||||||
err = tickRot.Refresh(ctx)
|
err = tickRot.Refresh(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initial session ticket refresh: %w", err)
|
return fmt.Errorf("initial session ticket refresh: %w", err)
|
||||||
@ -744,6 +853,7 @@ func (b *builder) initTLS(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initGRPCMetrics initializes the gRPC metrics if necessary.
|
// initGRPCMetrics initializes the gRPC metrics if necessary.
|
||||||
|
// [builder.initServerGroups] must be called before this method.
|
||||||
func (b *builder) initGRPCMetrics(ctx context.Context) (err error) {
|
func (b *builder) initGRPCMetrics(ctx context.Context) (err error) {
|
||||||
switch {
|
switch {
|
||||||
case
|
case
|
||||||
@ -756,18 +866,19 @@ func (b *builder) initGRPCMetrics(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
b.backendGRPCMtrc, err = metrics.NewBackendPB(b.mtrcNamespace, b.promRegisterer)
|
b.backendGRPCMtrc, err = metrics.NewBackendGRPC(b.mtrcNamespace, b.promRegisterer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("registering backendbp metrics: %w", err)
|
return fmt.Errorf("registering backend grpc metrics: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.logger.DebugContext(ctx, "initialized grpc metrics")
|
b.logger.DebugContext(ctx, "initialized backend grpc metrics")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initBillStat initializes the billing-statistics recorder if necessary. It
|
// initBillStat initializes the billing-statistics recorder if necessary. It
|
||||||
// also adds the refresher with ID [debugIDBillStat] to the debug refreshers.
|
// also adds the refresher with ID [debugIDBillStat] to the debug refreshers.
|
||||||
|
// [builder.initGRPCMetrics] must be called before this method.
|
||||||
func (b *builder) initBillStat(ctx context.Context) (err error) {
|
func (b *builder) initBillStat(ctx context.Context) (err error) {
|
||||||
if !b.profilesEnabled {
|
if !b.profilesEnabled {
|
||||||
b.billStat = billstat.EmptyRecorder{}
|
b.billStat = billstat.EmptyRecorder{}
|
||||||
@ -775,7 +886,7 @@ func (b *builder) initBillStat(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
upl, err := newBillStatUploader(b.env, b.errColl, b.backendGRPCMtrc)
|
upl, err := b.newBillStatUploader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating billstat uploader: %w", err)
|
return fmt.Errorf("creating billstat uploader: %w", err)
|
||||||
}
|
}
|
||||||
@ -819,11 +930,28 @@ func (b *builder) initBillStat(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newBillStatUploader creates and returns a billstat uploader depending on the
|
||||||
|
// provided API URL.
|
||||||
|
func (b *builder) newBillStatUploader() (s billstat.Uploader, err error) {
|
||||||
|
apiURL := netutil.CloneURL(&b.env.BillStatURL.URL)
|
||||||
|
err = urlutil.ValidateGRPCURL(apiURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("billstat api url: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return backendpb.NewBillStat(&backendpb.BillStatConfig{
|
||||||
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, "billstat_uploader"),
|
||||||
|
ErrColl: b.errColl,
|
||||||
|
GRPCMetrics: b.backendGRPCMtrc,
|
||||||
|
Endpoint: apiURL,
|
||||||
|
APIKey: b.env.BillStatAPIKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// initProfileDB initializes the profile database if necessary.
|
// initProfileDB initializes the profile database if necessary.
|
||||||
//
|
//
|
||||||
// [builder.initGRPCMetrics] and [builder.initServerGroups] must be called
|
// [builder.initGRPCMetrics] must be called before this method. It also adds
|
||||||
// before this method. It also adds the refresher with ID [debugIDProfileDB] to
|
// the refresher with ID [debugIDProfileDB] to the debug refreshers.
|
||||||
// the debug refreshers.
|
|
||||||
func (b *builder) initProfileDB(ctx context.Context) (err error) {
|
func (b *builder) initProfileDB(ctx context.Context) (err error) {
|
||||||
if !b.profilesEnabled {
|
if !b.profilesEnabled {
|
||||||
b.profileDB = &profiledb.Disabled{}
|
b.profileDB = &profiledb.Disabled{}
|
||||||
@ -837,12 +965,18 @@ func (b *builder) initProfileDB(ctx context.Context) (err error) {
|
|||||||
return fmt.Errorf("profile api url: %w", err)
|
return fmt.Errorf("profile api url: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backendProfileDBMtrc, err := metrics.NewBackendProfileDB(b.mtrcNamespace, b.promRegisterer)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("registering backend grpc profile metrics: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
respSzEst := b.conf.RateLimit.ResponseSizeEstimate
|
respSzEst := b.conf.RateLimit.ResponseSizeEstimate
|
||||||
strg, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
strg, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
||||||
BindSet: b.bindSet,
|
BindSet: b.bindSet,
|
||||||
ErrColl: b.errColl,
|
ErrColl: b.errColl,
|
||||||
Logger: b.baseLogger.With(slogutil.KeyPrefix, "backendpb"),
|
Logger: b.baseLogger.With(slogutil.KeyPrefix, "profilestorage"),
|
||||||
Metrics: b.backendGRPCMtrc,
|
GRPCMetrics: b.backendGRPCMtrc,
|
||||||
|
Metrics: backendProfileDBMtrc,
|
||||||
Endpoint: apiURL,
|
Endpoint: apiURL,
|
||||||
APIKey: b.env.ProfilesAPIKey,
|
APIKey: b.env.ProfilesAPIKey,
|
||||||
ResponseSizeEstimate: respSzEst,
|
ResponseSizeEstimate: respSzEst,
|
||||||
@ -917,6 +1051,7 @@ func (b *builder) initDNSCheck(ctx context.Context) (err error) {
|
|||||||
c := b.conf.Check
|
c := b.conf.Check
|
||||||
|
|
||||||
checkConf, err := c.toInternal(
|
checkConf, err := c.toInternal(
|
||||||
|
b.baseLogger,
|
||||||
b.env,
|
b.env,
|
||||||
b.messages,
|
b.messages,
|
||||||
b.errColl,
|
b.errColl,
|
||||||
@ -1051,12 +1186,10 @@ func (b *builder) initRateLimiter(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initWeb initializes the web service, starts it, and registers it in the
|
// initWeb initializes the web service, starts it, and registers it in the
|
||||||
// signal handler.
|
// signal handler. [builder.initDNSCheck] must be call before this method.
|
||||||
//
|
|
||||||
// [builder.initServerGroups] must be called before this method.
|
|
||||||
func (b *builder) initWeb(ctx context.Context) (err error) {
|
func (b *builder) initWeb(ctx context.Context) (err error) {
|
||||||
c := b.conf.Web
|
c := b.conf.Web
|
||||||
webConf, err := c.toInternal(ctx, b.env, b.dnsCheck, b.errColl, b.tlsMtrc)
|
webConf, err := c.toInternal(ctx, b.env, b.dnsCheck, b.errColl, b.tlsManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("converting web configuration: %w", err)
|
return fmt.Errorf("converting web configuration: %w", err)
|
||||||
}
|
}
|
||||||
@ -1142,7 +1275,6 @@ func (b *builder) waitGeoIP(ctx context.Context) (err error) {
|
|||||||
// - [builder.initAccess]
|
// - [builder.initAccess]
|
||||||
// - [builder.initBillStat]
|
// - [builder.initBillStat]
|
||||||
// - [builder.initBindToDevice]
|
// - [builder.initBindToDevice]
|
||||||
// - [builder.initDNSCheck]
|
|
||||||
// - [builder.initFilterStorage]
|
// - [builder.initFilterStorage]
|
||||||
// - [builder.initFilteringGroups]
|
// - [builder.initFilteringGroups]
|
||||||
// - [builder.initMsgConstructor]
|
// - [builder.initMsgConstructor]
|
||||||
@ -1153,7 +1285,7 @@ func (b *builder) waitGeoIP(ctx context.Context) (err error) {
|
|||||||
// - [builder.waitGeoIP]
|
// - [builder.waitGeoIP]
|
||||||
func (b *builder) initDNS(ctx context.Context) (err error) {
|
func (b *builder) initDNS(ctx context.Context) (err error) {
|
||||||
b.fwdHandler = forward.NewHandler(b.conf.Upstream.toInternal(b.baseLogger))
|
b.fwdHandler = forward.NewHandler(b.conf.Upstream.toInternal(b.baseLogger))
|
||||||
b.dnsDB = b.conf.DNSDB.toInternal(b.errColl)
|
b.dnsDB = b.conf.DNSDB.toInternal(b.baseLogger, b.errColl)
|
||||||
|
|
||||||
dnsHdlrsConf := &dnssvc.HandlersConfig{
|
dnsHdlrsConf := &dnssvc.HandlersConfig{
|
||||||
BaseLogger: b.baseLogger,
|
BaseLogger: b.baseLogger,
|
||||||
|
@ -2,10 +2,12 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/backendpb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||||
@ -17,6 +19,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv/rediskv"
|
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv/rediskv"
|
||||||
"github.com/AdguardTeam/golibs/container"
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
@ -50,14 +53,15 @@ type checkConfig struct {
|
|||||||
// toInternal converts c to the DNS server check configuration for the DNS
|
// toInternal converts c to the DNS server check configuration for the DNS
|
||||||
// server. c must be valid.
|
// server. c must be valid.
|
||||||
func (c *checkConfig) toInternal(
|
func (c *checkConfig) toInternal(
|
||||||
|
baseLogger *slog.Logger,
|
||||||
envs *environment,
|
envs *environment,
|
||||||
messages *dnsmsg.Constructor,
|
messages *dnsmsg.Constructor,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
namespace string,
|
namespace string,
|
||||||
reg prometheus.Registerer,
|
reg prometheus.Registerer,
|
||||||
backendMtrc backendpb.Metrics,
|
grpcMtrc backendpb.GRPCMetrics,
|
||||||
) (conf *dnscheck.RemoteKVConfig, err error) {
|
) (conf *dnscheck.RemoteKVConfig, err error) {
|
||||||
kv, err := newRemoteKV(c.RemoteKV, envs, namespace, reg, backendMtrc)
|
kv, err := c.RemoteKV.newRemoteKV(envs, namespace, reg, grpcMtrc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -69,6 +73,7 @@ func (c *checkConfig) toInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &dnscheck.RemoteKVConfig{
|
return &dnscheck.RemoteKVConfig{
|
||||||
|
Logger: baseLogger.With(slogutil.KeyPrefix, "dnscheck"),
|
||||||
Messages: messages,
|
Messages: messages,
|
||||||
RemoteKV: kv,
|
RemoteKV: kv,
|
||||||
ErrColl: errColl,
|
ErrColl: errColl,
|
||||||
@ -87,33 +92,42 @@ const maxRespSize = 1 * datasize.MB
|
|||||||
// [remotekv.KeyNamespace].
|
// [remotekv.KeyNamespace].
|
||||||
const keyNamespaceCheck = "check"
|
const keyNamespaceCheck = "check"
|
||||||
|
|
||||||
// newRemoteKV returns a new properly initialized remote key-value storage.
|
// newRemoteKV returns a new properly initialized remote key-value storage. c
|
||||||
func newRemoteKV(
|
// must be valid. grpcMtrc should be registered before calling this method.
|
||||||
c *remoteKVConfig,
|
func (c *remoteKVConfig) newRemoteKV(
|
||||||
envs *environment,
|
envs *environment,
|
||||||
namespace string,
|
namespace string,
|
||||||
reg prometheus.Registerer,
|
reg prometheus.Registerer,
|
||||||
backendMtrc backendpb.Metrics,
|
grpcMtrc backendpb.GRPCMetrics,
|
||||||
) (kv remotekv.Interface, err error) {
|
) (kv remotekv.Interface, err error) {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case kvModeBackend:
|
case kvModeBackend:
|
||||||
kv, err = backendpb.NewRemoteKV(&backendpb.RemoteKVConfig{
|
var backendKVMtrc *metrics.BackendRemoteKV
|
||||||
Metrics: backendMtrc,
|
backendKVMtrc, err = metrics.NewBackendRemoteKV(namespace, reg)
|
||||||
Endpoint: &envs.DNSCheckRemoteKVURL.URL,
|
if err != nil {
|
||||||
APIKey: envs.DNSCheckRemoteKVAPIKey,
|
return nil, fmt.Errorf("registering backend kv metrics: %w", err)
|
||||||
TTL: c.TTL.Duration,
|
}
|
||||||
})
|
|
||||||
|
kv, err = c.newBackendRemoteKV(envs, backendKVMtrc, grpcMtrc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("initializing backend dnscheck kv: %w", err)
|
return nil, fmt.Errorf("initializing backend dnscheck kv: %w", err)
|
||||||
}
|
}
|
||||||
|
case kvModeCache:
|
||||||
|
// TODO(e.burkov): The local cache in [dnscheck.RemoteKV] becomes
|
||||||
|
// pointless with this mode.
|
||||||
|
return remotekv.NewCache(&remotekv.CacheConfig{
|
||||||
|
Cache: agdcache.NewLRU[string, []byte](&agdcache.LRUConfig{
|
||||||
|
Count: envs.DNSCheckCacheKVSize,
|
||||||
|
}),
|
||||||
|
}), nil
|
||||||
case kvModeRedis:
|
case kvModeRedis:
|
||||||
var redisKVMtrc rediskv.Metrics
|
var redisKVMtrc *metrics.RedisKV
|
||||||
redisKVMtrc, err = metrics.NewRedisKV(namespace, reg)
|
redisKVMtrc, err = metrics.NewRedisKV(namespace, reg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("registering redis kv metrics: %w", err)
|
return nil, fmt.Errorf("registering redis kv metrics: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
redisKV := rediskv.NewRedisKV(&rediskv.RedisKVConfig{
|
kv = rediskv.NewRedisKV(&rediskv.RedisKVConfig{
|
||||||
Metrics: redisKVMtrc,
|
Metrics: redisKVMtrc,
|
||||||
Addr: &netutil.HostPort{
|
Addr: &netutil.HostPort{
|
||||||
Host: envs.RedisAddr,
|
Host: envs.RedisAddr,
|
||||||
@ -124,12 +138,59 @@ func newRemoteKV(
|
|||||||
IdleTimeout: envs.RedisIdleTimeout.Duration,
|
IdleTimeout: envs.RedisIdleTimeout.Duration,
|
||||||
TTL: c.TTL.Duration,
|
TTL: c.TTL.Duration,
|
||||||
})
|
})
|
||||||
|
|
||||||
kv = remotekv.NewKeyNamespace(&remotekv.KeyNamespaceConfig{
|
|
||||||
KV: redisKV,
|
|
||||||
Prefix: fmt.Sprintf("%s:%s:", envs.RedisKeyPrefix, keyNamespaceCheck),
|
|
||||||
})
|
|
||||||
case kvModeConsul:
|
case kvModeConsul:
|
||||||
|
kv, err = c.newConsulRemoteKV(envs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("initializing consul dnscheck kv: %w", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("dnscheck kv type: %w: %q", errors.ErrBadEnumValue, c.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
return remotekv.NewKeyNamespace(&remotekv.KeyNamespaceConfig{
|
||||||
|
KV: kv,
|
||||||
|
Prefix: newRemoveKVPrefix(envs, c.Type),
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBackendRemoteKV returns a new properly initialized backend remote
|
||||||
|
// key-value storage. c must be valid.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Add key namespace.
|
||||||
|
func (c *remoteKVConfig) newBackendRemoteKV(
|
||||||
|
envs *environment,
|
||||||
|
backendKVMtrc *metrics.BackendRemoteKV,
|
||||||
|
grpcMtrc backendpb.GRPCMetrics,
|
||||||
|
) (kv *backendpb.RemoteKV, err error) {
|
||||||
|
kv, err = backendpb.NewRemoteKV(&backendpb.RemoteKVConfig{
|
||||||
|
GRPCMetrics: grpcMtrc,
|
||||||
|
Metrics: backendKVMtrc,
|
||||||
|
Endpoint: &envs.DNSCheckRemoteKVURL.URL,
|
||||||
|
APIKey: envs.DNSCheckRemoteKVAPIKey,
|
||||||
|
TTL: c.TTL.Duration,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("initializing backend dnscheck kv: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return kv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRemoveKVPrefix returns a remote KV custom prefix for the keys.
|
||||||
|
func newRemoveKVPrefix(envs *environment, kvType string) (pref string) {
|
||||||
|
switch kvType {
|
||||||
|
case kvModeBackend, kvModeCache, kvModeConsul:
|
||||||
|
return fmt.Sprintf("%s:%s:", kvType, keyNamespaceCheck)
|
||||||
|
case kvModeRedis:
|
||||||
|
return fmt.Sprintf("%s:%s:", envs.RedisKeyPrefix, keyNamespaceCheck)
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("dnscheck kv type: %w: %q", errors.ErrBadEnumValue, kvType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newConsulRemoteKV returns a new properly initialized Consul-based remote
|
||||||
|
// key-value storage. c must be valid.
|
||||||
|
func (c *remoteKVConfig) newConsulRemoteKV(envs *environment) (kv remotekv.Interface, err error) {
|
||||||
consulKVURL := envs.ConsulDNSCheckKVURL
|
consulKVURL := envs.ConsulDNSCheckKVURL
|
||||||
consulSessionURL := envs.ConsulDNSCheckSessionURL
|
consulSessionURL := envs.ConsulDNSCheckSessionURL
|
||||||
if consulKVURL == nil || consulSessionURL == nil {
|
if consulKVURL == nil || consulSessionURL == nil {
|
||||||
@ -151,9 +212,6 @@ func newRemoteKV(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("initializing consul dnscheck kv: %w", err)
|
return nil, fmt.Errorf("initializing consul dnscheck kv: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return remotekv.Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return kv, nil
|
return kv, nil
|
||||||
}
|
}
|
||||||
@ -238,6 +296,7 @@ func validateNonNilIPs(ips []netip.Addr, fam netutil.AddrFamily) (err error) {
|
|||||||
// DNSCheck key-value database modes.
|
// DNSCheck key-value database modes.
|
||||||
const (
|
const (
|
||||||
kvModeBackend = "backend"
|
kvModeBackend = "backend"
|
||||||
|
kvModeCache = "cache"
|
||||||
kvModeConsul = "consul"
|
kvModeConsul = "consul"
|
||||||
kvModeRedis = "redis"
|
kvModeRedis = "redis"
|
||||||
)
|
)
|
||||||
@ -246,7 +305,7 @@ const (
|
|||||||
// checking.
|
// checking.
|
||||||
type remoteKVConfig struct {
|
type remoteKVConfig struct {
|
||||||
// Type defines the type of remote key-value store. Allowed values are
|
// Type defines the type of remote key-value store. Allowed values are
|
||||||
// [kvModeBackend], [kvModeConsul] and [kvModeRedis].
|
// [kvModeBackend], [kvModeCache], [kvModeConsul] and [kvModeRedis].
|
||||||
Type string `yaml:"type"`
|
Type string `yaml:"type"`
|
||||||
|
|
||||||
// TTL defines, for how long to keep the information about a single client.
|
// TTL defines, for how long to keep the information about a single client.
|
||||||
@ -269,6 +328,8 @@ func (c *remoteKVConfig) validate() (err error) {
|
|||||||
if ttl.Duration <= 0 {
|
if ttl.Duration <= 0 {
|
||||||
return newNotPositiveError("ttl", ttl)
|
return newNotPositiveError("ttl", ttl)
|
||||||
}
|
}
|
||||||
|
case kvModeCache:
|
||||||
|
// Go on.
|
||||||
case kvModeConsul:
|
case kvModeConsul:
|
||||||
if ttl.Duration < consulkv.MinTTL || ttl.Duration > consulkv.MaxTTL {
|
if ttl.Duration < consulkv.MinTTL || ttl.Duration > consulkv.MaxTTL {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
@ -288,8 +349,6 @@ func (c *remoteKVConfig) validate() (err error) {
|
|||||||
ttl,
|
ttl,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case "":
|
|
||||||
return fmt.Errorf("type: %w", errors.ErrEmptyValue)
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("type: %w: %q", errors.ErrBadEnumValue, c.Type)
|
return fmt.Errorf("type: %w: %q", errors.ErrBadEnumValue, c.Type)
|
||||||
}
|
}
|
||||||
|
@ -94,11 +94,13 @@ func Main(plugins *plugin.Registry) {
|
|||||||
|
|
||||||
errors.Check(b.initMsgConstructor(ctx))
|
errors.Check(b.initMsgConstructor(ctx))
|
||||||
|
|
||||||
|
errors.Check(b.initTLSManager(ctx))
|
||||||
|
|
||||||
errors.Check(b.initServerGroups(ctx))
|
errors.Check(b.initServerGroups(ctx))
|
||||||
|
|
||||||
errors.Check(b.startBindToDevice(ctx))
|
errors.Check(b.startBindToDevice(ctx))
|
||||||
|
|
||||||
errors.Check(b.initTLS(ctx))
|
errors.Check(b.initTicketRotator(ctx))
|
||||||
|
|
||||||
errors.Check(b.initGRPCMetrics(ctx))
|
errors.Check(b.initGRPCMetrics(ctx))
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ func connectivityCheck(srvGrps []*agd.ServerGroup, connCheck *connCheckConfig) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
errClose := errors.Annotate(conn4.Close(), "connectivity check: closing ipv4: %w")
|
closeErr := errors.Annotate(conn4.Close(), "connectivity check: closing ipv4: %w")
|
||||||
err = errors.WithDeferred(err, errClose)
|
err = errors.WithDeferred(err, closeErr)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !requireIPv6ConnCheck(srvGrps) {
|
if !requireIPv6ConnCheck(srvGrps) {
|
||||||
@ -69,8 +69,8 @@ func connectivityCheck(srvGrps []*agd.ServerGroup, connCheck *connCheckConfig) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
errClose := errors.Annotate(conn6.Close(), "connectivity check: closing ipv6: %w")
|
closeErr := errors.Annotate(conn6.Close(), "connectivity check: closing ipv6: %w")
|
||||||
err = errors.WithDeferred(err, errClose)
|
err = errors.WithDeferred(err, closeErr)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dnsDBConfig is the configuration of the DNSDB module.
|
// dnsDBConfig is the configuration of the DNSDB module.
|
||||||
@ -34,12 +37,16 @@ func (c *dnsDBConfig) validate() (err error) {
|
|||||||
|
|
||||||
// toInternal builds and returns an anonymous statistics collector. c must be
|
// toInternal builds and returns an anonymous statistics collector. c must be
|
||||||
// valid.
|
// valid.
|
||||||
func (c *dnsDBConfig) toInternal(errColl errcoll.Interface) (d dnsdb.Interface) {
|
func (c *dnsDBConfig) toInternal(
|
||||||
|
baseLogger *slog.Logger,
|
||||||
|
errColl errcoll.Interface,
|
||||||
|
) (d dnsdb.Interface) {
|
||||||
if !c.Enabled {
|
if !c.Enabled {
|
||||||
return dnsdb.Empty{}
|
return dnsdb.Empty{}
|
||||||
}
|
}
|
||||||
|
|
||||||
db := dnsdb.New(&dnsdb.DefaultConfig{
|
db := dnsdb.New(&dnsdb.DefaultConfig{
|
||||||
|
Logger: baseLogger.With(slogutil.KeyPrefix, "dnsdb"),
|
||||||
ErrColl: errColl,
|
ErrColl: errColl,
|
||||||
MaxSize: c.MaxSize,
|
MaxSize: c.MaxSize,
|
||||||
})
|
})
|
||||||
|
@ -68,6 +68,8 @@ type environment struct {
|
|||||||
|
|
||||||
RedisIdleTimeout timeutil.Duration `env:"REDIS_IDLE_TIMEOUT" envDefault:"30s"`
|
RedisIdleTimeout timeutil.Duration `env:"REDIS_IDLE_TIMEOUT" envDefault:"30s"`
|
||||||
|
|
||||||
|
// TODO(a.garipov): Rename to DNSCHECK_CACHE_KV_COUNT?
|
||||||
|
DNSCheckCacheKVSize int `env:"DNSCHECK_CACHE_KV_SIZE"`
|
||||||
RedisMaxActive int `env:"REDIS_MAX_ACTIVE" envDefault:"10"`
|
RedisMaxActive int `env:"REDIS_MAX_ACTIVE" envDefault:"10"`
|
||||||
RedisMaxIdle int `env:"REDIS_MAX_IDLE" envDefault:"3"`
|
RedisMaxIdle int `env:"REDIS_MAX_IDLE" envDefault:"3"`
|
||||||
|
|
||||||
@ -233,10 +235,12 @@ func (envs *environment) validateFromValidConfig(conf *configuration) (err error
|
|||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
switch typ := conf.Check.RemoteKV.Type; typ {
|
switch typ := conf.Check.RemoteKV.Type; typ {
|
||||||
case kvModeRedis:
|
|
||||||
errs = envs.validateRedis(errs)
|
|
||||||
case kvModeBackend:
|
case kvModeBackend:
|
||||||
errs = envs.validateBackendKV(errs)
|
errs = envs.validateBackendKV(errs)
|
||||||
|
case kvModeCache:
|
||||||
|
errs = envs.validateCache(errs)
|
||||||
|
case kvModeRedis:
|
||||||
|
errs = envs.validateRedis(errs)
|
||||||
default:
|
default:
|
||||||
// Probably consul.
|
// Probably consul.
|
||||||
}
|
}
|
||||||
@ -259,38 +263,51 @@ func (envs *environment) validateFromValidConfig(conf *configuration) (err error
|
|||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateCache appends validation errors to the given errs if environment
|
||||||
|
// variables for KV Cache contain errors.
|
||||||
|
func (envs *environment) validateCache(errs []error) (res []error) {
|
||||||
|
res = errs
|
||||||
|
|
||||||
|
if envs.DNSCheckCacheKVSize <= 0 {
|
||||||
|
err := newNotPositiveError("DNSCHECK_CACHE_KV_SIZE", envs.DNSCheckCacheKVSize)
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// validateRedis appends validation errors to the given errs if environment
|
// validateRedis appends validation errors to the given errs if environment
|
||||||
// variables for Redis contain errors.
|
// variables for Redis contain errors.
|
||||||
func (envs *environment) validateRedis(errs []error) (withRedis []error) {
|
func (envs *environment) validateRedis(errs []error) (res []error) {
|
||||||
withRedis = errs
|
res = errs
|
||||||
|
|
||||||
if envs.RedisAddr == "" {
|
if envs.RedisAddr == "" {
|
||||||
err := fmt.Errorf("REDIS_ADDR: %q", errors.ErrEmptyValue)
|
err := fmt.Errorf("REDIS_ADDR: %w", errors.ErrEmptyValue)
|
||||||
withRedis = append(withRedis, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envs.RedisIdleTimeout.Duration <= 0 {
|
if envs.RedisIdleTimeout.Duration <= 0 {
|
||||||
err := newNotPositiveError("REDIS_IDLE_TIMEOUT", envs.RedisIdleTimeout)
|
err := newNotPositiveError("REDIS_IDLE_TIMEOUT", envs.RedisIdleTimeout)
|
||||||
withRedis = append(withRedis, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envs.RedisMaxActive < 0 {
|
if envs.RedisMaxActive < 0 {
|
||||||
err := newNegativeError("REDIS_MAX_ACTIVE", envs.RedisMaxActive)
|
err := newNegativeError("REDIS_MAX_ACTIVE", envs.RedisMaxActive)
|
||||||
withRedis = append(withRedis, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envs.RedisMaxIdle < 0 {
|
if envs.RedisMaxIdle < 0 {
|
||||||
err := newNegativeError("REDIS_MAX_IDLE", envs.RedisMaxIdle)
|
err := newNegativeError("REDIS_MAX_IDLE", envs.RedisMaxIdle)
|
||||||
withRedis = append(withRedis, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return withRedis
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateBackendKV appends validation errors to the given errs if environment
|
// validateBackendKV appends validation errors to the given errs if environment
|
||||||
// variables for a backend key-value store contain errors.
|
// variables for a backend key-value store contain errors.
|
||||||
func (envs *environment) validateBackendKV(errs []error) (withKV []error) {
|
func (envs *environment) validateBackendKV(errs []error) (res []error) {
|
||||||
withKV = errs
|
res = errs
|
||||||
|
|
||||||
var u *url.URL
|
var u *url.URL
|
||||||
if envs.DNSCheckRemoteKVURL != nil {
|
if envs.DNSCheckRemoteKVURL != nil {
|
||||||
@ -299,16 +316,16 @@ func (envs *environment) validateBackendKV(errs []error) (withKV []error) {
|
|||||||
|
|
||||||
err := urlutil.ValidateGRPCURL(u)
|
err := urlutil.ValidateGRPCURL(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
withKV = append(withKV, fmt.Errorf("env DNSCHECK_REMOTEKV_URL: %w", err))
|
res = append(res, fmt.Errorf("env DNSCHECK_REMOTEKV_URL: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return withKV
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateProfilesURLs appends validation errors to the given errs if profiles
|
// validateProfilesURLs appends validation errors to the given errs if profiles
|
||||||
// URLs in environment variables are invalid.
|
// URLs in environment variables are invalid.
|
||||||
func (envs *environment) validateProfilesURLs(errs []error) (withURLs []error) {
|
func (envs *environment) validateProfilesURLs(errs []error) (res []error) {
|
||||||
withURLs = errs
|
res = errs
|
||||||
|
|
||||||
grpcOnlyURLs := []*urlEnvData{{
|
grpcOnlyURLs := []*urlEnvData{{
|
||||||
url: envs.BillStatURL,
|
url: envs.BillStatURL,
|
||||||
@ -332,11 +349,11 @@ func (envs *environment) validateProfilesURLs(errs []error) (withURLs []error) {
|
|||||||
|
|
||||||
err := urlutil.ValidateGRPCURL(u)
|
err := urlutil.ValidateGRPCURL(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
withURLs = append(withURLs, fmt.Errorf("env %s: %w", urlData.name, err))
|
res = append(res, fmt.Errorf("env %s: %w", urlData.name, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withURLs
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateRateLimitURLs appends validation errors to the given errs if rate
|
// validateRateLimitURLs appends validation errors to the given errs if rate
|
||||||
|
@ -2,16 +2,8 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
)
|
)
|
||||||
@ -27,9 +19,13 @@ type filtersConfig struct {
|
|||||||
|
|
||||||
// CustomFilterCacheSize is the size of the LRU cache of compiled filtering
|
// CustomFilterCacheSize is the size of the LRU cache of compiled filtering
|
||||||
// engines for profiles with custom filtering rules.
|
// engines for profiles with custom filtering rules.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Rename to "custom_filter_cache_count"?
|
||||||
CustomFilterCacheSize int `yaml:"custom_filter_cache_size"`
|
CustomFilterCacheSize int `yaml:"custom_filter_cache_size"`
|
||||||
|
|
||||||
// SafeSearchCacheSize is the size of the LRU cache of safe-search results.
|
// SafeSearchCacheSize is the size of the LRU cache of safe-search results.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Rename to "safe_search_cache_count"?
|
||||||
SafeSearchCacheSize int `yaml:"safe_search_cache_size"`
|
SafeSearchCacheSize int `yaml:"safe_search_cache_size"`
|
||||||
|
|
||||||
// ResponseTTL is the TTL to set for DNS responses to requests for filtered
|
// ResponseTTL is the TTL to set for DNS responses to requests for filtered
|
||||||
@ -66,58 +62,6 @@ type filtersConfig struct {
|
|||||||
SDEEnabled bool `yaml:"sde_enabled"`
|
SDEEnabled bool `yaml:"sde_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts c to the filter storage configuration for the DNS server.
|
|
||||||
// cacheDir must exist. c must be valid.
|
|
||||||
func (c *filtersConfig) toInternal(
|
|
||||||
logger *slog.Logger,
|
|
||||||
errColl errcoll.Interface,
|
|
||||||
cacheManager agdcache.Manager,
|
|
||||||
envs *environment,
|
|
||||||
safeBrowsing *hashprefix.Filter,
|
|
||||||
adultBlocking *hashprefix.Filter,
|
|
||||||
newRegDomains *hashprefix.Filter,
|
|
||||||
) (conf *filter.DefaultStorageConfig) {
|
|
||||||
var blockedServiceIndexURL *url.URL
|
|
||||||
if envs.BlockedServiceEnabled {
|
|
||||||
blockedServiceIndexURL = netutil.CloneURL(&envs.BlockedServiceIndexURL.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
var generalSafeSearchRulesURL *url.URL
|
|
||||||
if envs.GeneralSafeSearchEnabled {
|
|
||||||
generalSafeSearchRulesURL = netutil.CloneURL(&envs.GeneralSafeSearchURL.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
var youtubeSafeSearchRulesURL *url.URL
|
|
||||||
if envs.YoutubeSafeSearchEnabled {
|
|
||||||
youtubeSafeSearchRulesURL = netutil.CloneURL(&envs.YoutubeSafeSearchURL.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &filter.DefaultStorageConfig{
|
|
||||||
BaseLogger: logger,
|
|
||||||
FilterIndexURL: netutil.CloneURL(&envs.FilterIndexURL.URL),
|
|
||||||
BlockedServiceIndexURL: blockedServiceIndexURL,
|
|
||||||
GeneralSafeSearchRulesURL: generalSafeSearchRulesURL,
|
|
||||||
YoutubeSafeSearchRulesURL: youtubeSafeSearchRulesURL,
|
|
||||||
SafeBrowsing: safeBrowsing,
|
|
||||||
AdultBlocking: adultBlocking,
|
|
||||||
NewRegDomains: newRegDomains,
|
|
||||||
Now: time.Now,
|
|
||||||
ErrColl: errColl,
|
|
||||||
CacheManager: cacheManager,
|
|
||||||
CacheDir: envs.FilterCachePath,
|
|
||||||
CustomFilterCacheSize: c.CustomFilterCacheSize,
|
|
||||||
SafeSearchCacheSize: c.SafeSearchCacheSize,
|
|
||||||
// TODO(a.garipov): Consider making this configurable.
|
|
||||||
SafeSearchCacheTTL: 1 * time.Hour,
|
|
||||||
RuleListCacheSize: c.RuleListCache.Size,
|
|
||||||
RefreshIvl: c.RefreshIvl.Duration,
|
|
||||||
IndexRefreshTimeout: c.IndexRefreshTimeout.Duration,
|
|
||||||
RuleListRefreshTimeout: c.RuleListRefreshTimeout.Duration,
|
|
||||||
UseRuleListCache: c.RuleListCache.Enabled,
|
|
||||||
MaxRuleListSize: c.MaxSize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*filtersConfig)(nil)
|
var _ validator = (*filtersConfig)(nil)
|
||||||
|
|
||||||
@ -153,6 +97,8 @@ func (c *filtersConfig) validate() (err error) {
|
|||||||
// fltRuleListCache contains filtering rule-list cache configuration.
|
// fltRuleListCache contains filtering rule-list cache configuration.
|
||||||
type fltRuleListCache struct {
|
type fltRuleListCache struct {
|
||||||
// Size defines the size of the LRU cache of rule-list filtering results.
|
// Size defines the size of the LRU cache of rule-list filtering results.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Rename to "count"?
|
||||||
Size int `yaml:"size"`
|
Size int `yaml:"size"`
|
||||||
|
|
||||||
// Enabled shows if the rule-list cache is enabled. If it is false, the
|
// Enabled shows if the rule-list cache is enabled. If it is false, the
|
||||||
|
@ -24,13 +24,17 @@ type filteringGroup struct {
|
|||||||
// ID is a filtering group ID. Must be unique.
|
// ID is a filtering group ID. Must be unique.
|
||||||
ID string `yaml:"id"`
|
ID string `yaml:"id"`
|
||||||
|
|
||||||
// BlockPrivateRelay shows if Apple Private Relay queries are blocked for
|
// BlockChromePrefetch shows if the Chrome prefetch proxy feature should be
|
||||||
// requests using this filtering group.
|
// disabled for requests using this filtering group.
|
||||||
BlockPrivateRelay bool `yaml:"block_private_relay"`
|
BlockChromePrefetch bool `yaml:"block_chrome_prefetch"`
|
||||||
|
|
||||||
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
// BlockFirefoxCanary shows if Firefox canary domain is blocked for
|
||||||
// requests using this filtering group.
|
// requests using this filtering group.
|
||||||
BlockFirefoxCanary bool `yaml:"block_firefox_canary"`
|
BlockFirefoxCanary bool `yaml:"block_firefox_canary"`
|
||||||
|
|
||||||
|
// BlockPrivateRelay shows if Apple Private Relay queries are blocked for
|
||||||
|
// requests using this filtering group.
|
||||||
|
BlockPrivateRelay bool `yaml:"block_private_relay"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// fltGrpRuleLists contains filter rule lists configuration for a filtering
|
// fltGrpRuleLists contains filter rule lists configuration for a filtering
|
||||||
@ -44,6 +48,15 @@ type fltGrpRuleLists struct {
|
|||||||
Enabled bool `yaml:"enabled"`
|
Enabled bool `yaml:"enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toInternal converts c to the rule-list configuration for the filtering group.
|
||||||
|
// c must be valid.
|
||||||
|
func (c *fltGrpRuleLists) toInternal(ids []filter.ID) (fltConf *filter.ConfigRuleList) {
|
||||||
|
return &filter.ConfigRuleList{
|
||||||
|
IDs: ids,
|
||||||
|
Enabled: c.Enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fltGrpParental contains parental protection configuration for a filtering
|
// fltGrpParental contains parental protection configuration for a filtering
|
||||||
// group.
|
// group.
|
||||||
type fltGrpParental struct {
|
type fltGrpParental struct {
|
||||||
@ -64,6 +77,19 @@ type fltGrpParental struct {
|
|||||||
YoutubeSafeSearch bool `yaml:"youtube_safe_search"`
|
YoutubeSafeSearch bool `yaml:"youtube_safe_search"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toInternal converts c to the parental-control configuration for the filtering
|
||||||
|
// group. c must be valid.
|
||||||
|
func (c *fltGrpParental) toInternal() (fltConf *filter.ConfigParental) {
|
||||||
|
return &filter.ConfigParental{
|
||||||
|
PauseSchedule: nil,
|
||||||
|
BlockedServices: nil,
|
||||||
|
Enabled: c.Enabled,
|
||||||
|
AdultBlockingEnabled: c.BlockAdult,
|
||||||
|
SafeSearchGeneralEnabled: c.GeneralSafeSearch,
|
||||||
|
SafeSearchYouTubeEnabled: c.YoutubeSafeSearch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fltGrpSafeBrowsing contains general safe browsing configuration for
|
// fltGrpSafeBrowsing contains general safe browsing configuration for
|
||||||
// a filtering group.
|
// a filtering group.
|
||||||
type fltGrpSafeBrowsing struct {
|
type fltGrpSafeBrowsing struct {
|
||||||
@ -79,6 +105,16 @@ type fltGrpSafeBrowsing struct {
|
|||||||
BlockNewlyRegisteredDomains bool `yaml:"block_newly_registered_domains"`
|
BlockNewlyRegisteredDomains bool `yaml:"block_newly_registered_domains"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toInternal converts c to the safe-browsing configuration for the filtering
|
||||||
|
// group. c must be valid.
|
||||||
|
func (c *fltGrpSafeBrowsing) toInternal() (fltConf *filter.ConfigSafeBrowsing) {
|
||||||
|
return &filter.ConfigSafeBrowsing{
|
||||||
|
Enabled: c.Enabled,
|
||||||
|
DangerousDomainsEnabled: c.BlockDangerousDomains,
|
||||||
|
NewlyRegisteredDomainsEnabled: c.BlockNewlyRegisteredDomains,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*filteringGroup)(nil)
|
var _ validator = (*filteringGroup)(nil)
|
||||||
|
|
||||||
@ -87,21 +123,23 @@ func (g *filteringGroup) validate() (err error) {
|
|||||||
switch {
|
switch {
|
||||||
case g == nil:
|
case g == nil:
|
||||||
return errors.ErrNoValue
|
return errors.ErrNoValue
|
||||||
case g.RuleLists == nil:
|
|
||||||
return fmt.Errorf("rule_lists: %w", errors.ErrNoValue)
|
|
||||||
case g.ID == "":
|
|
||||||
return fmt.Errorf("id: %w", errors.ErrEmptyValue)
|
|
||||||
case g.Parental == nil:
|
case g.Parental == nil:
|
||||||
return fmt.Errorf("parental: %w", errors.ErrNoValue)
|
return fmt.Errorf("parental: %w", errors.ErrNoValue)
|
||||||
|
case g.RuleLists == nil:
|
||||||
|
return fmt.Errorf("rule_lists: %w", errors.ErrNoValue)
|
||||||
|
case g.SafeBrowsing == nil:
|
||||||
|
return fmt.Errorf("safe_browsing: %w", errors.ErrNoValue)
|
||||||
|
case g.ID == "":
|
||||||
|
return fmt.Errorf("id: %w", errors.ErrEmptyValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fltIDs := container.NewMapSet[string]()
|
fltIDs := container.NewMapSet[string]()
|
||||||
for i, fltID := range g.RuleLists.IDs {
|
for i, fltID := range g.RuleLists.IDs {
|
||||||
if fltIDs.Has(fltID) {
|
if fltIDs.Has(fltID) {
|
||||||
return fmt.Errorf("rule_lists: at index %d: duplicate id %q", i, fltID)
|
return fmt.Errorf("rule_lists: at index %d: id: %w: %q", i, errors.ErrDuplicated, fltID)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = agd.NewFilterListID(fltID)
|
_, err = filter.NewID(fltID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("rule_lists: at index %d: %w", i, err)
|
return fmt.Errorf("rule_lists: at index %d: %w", i, err)
|
||||||
}
|
}
|
||||||
@ -123,32 +161,29 @@ func (groups filteringGroups) toInternal(
|
|||||||
) (fltGrps map[agd.FilteringGroupID]*agd.FilteringGroup, err error) {
|
) (fltGrps map[agd.FilteringGroupID]*agd.FilteringGroup, err error) {
|
||||||
fltGrps = make(map[agd.FilteringGroupID]*agd.FilteringGroup, len(groups))
|
fltGrps = make(map[agd.FilteringGroupID]*agd.FilteringGroup, len(groups))
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
filterIDs := make([]agd.FilterListID, len(g.RuleLists.IDs))
|
filterIDs := make([]filter.ID, len(g.RuleLists.IDs))
|
||||||
for i, fltID := range g.RuleLists.IDs {
|
for i, fltID := range g.RuleLists.IDs {
|
||||||
// Assume that these have already been validated in
|
// Assume that these have already been validated in
|
||||||
// [filteringGroup.validate].
|
// [filteringGroup.validate].
|
||||||
id := agd.FilterListID(fltID)
|
id := filter.ID(fltID)
|
||||||
if !s.HasListID(id) {
|
if !s.HasListID(id) {
|
||||||
return nil, fmt.Errorf("filter list id %q is not in the index", id)
|
return nil, fmt.Errorf("filter list id %q is not in the index", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
filterIDs[i] = agd.FilterListID(fltID)
|
filterIDs[i] = filter.ID(fltID)
|
||||||
}
|
}
|
||||||
|
|
||||||
id := agd.FilteringGroupID(g.ID)
|
id := agd.FilteringGroupID(g.ID)
|
||||||
fltGrps[id] = &agd.FilteringGroup{
|
fltGrps[id] = &agd.FilteringGroup{
|
||||||
|
FilterConfig: &filter.ConfigGroup{
|
||||||
|
Parental: g.Parental.toInternal(),
|
||||||
|
RuleList: g.RuleLists.toInternal(filterIDs),
|
||||||
|
SafeBrowsing: g.SafeBrowsing.toInternal(),
|
||||||
|
},
|
||||||
ID: id,
|
ID: id,
|
||||||
RuleListsEnabled: g.RuleLists.Enabled,
|
BlockChromePrefetch: g.BlockChromePrefetch,
|
||||||
RuleListIDs: filterIDs,
|
|
||||||
ParentalEnabled: g.Parental.Enabled,
|
|
||||||
BlockAdult: g.Parental.BlockAdult,
|
|
||||||
SafeBrowsingEnabled: g.SafeBrowsing.Enabled,
|
|
||||||
BlockDangerousDomains: g.SafeBrowsing.BlockDangerousDomains,
|
|
||||||
BlockNewlyRegisteredDomains: g.SafeBrowsing.BlockNewlyRegisteredDomains,
|
|
||||||
GeneralSafeSearch: g.Parental.GeneralSafeSearch,
|
|
||||||
YoutubeSafeSearch: g.Parental.YoutubeSafeSearch,
|
|
||||||
BlockPrivateRelay: g.BlockPrivateRelay,
|
|
||||||
BlockFirefoxCanary: g.BlockFirefoxCanary,
|
BlockFirefoxCanary: g.BlockFirefoxCanary,
|
||||||
|
BlockPrivateRelay: g.BlockPrivateRelay,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +207,7 @@ func (groups filteringGroups) validate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ids.Has(string(g.ID)) {
|
if ids.Has(string(g.ID)) {
|
||||||
return fmt.Errorf("at index %d: duplicate id %q", i, g.ID)
|
return fmt.Errorf("at index %d: id: %w: %q", i, errors.ErrDuplicated, g.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
ids.Add(g.ID)
|
ids.Add(g.ID)
|
||||||
|
@ -8,9 +8,13 @@ import (
|
|||||||
// geoIPConfig is the GeoIP database configuration.
|
// geoIPConfig is the GeoIP database configuration.
|
||||||
type geoIPConfig struct {
|
type geoIPConfig struct {
|
||||||
// HostCacheSize is the size of the hostname lookup cache, in entries.
|
// HostCacheSize is the size of the hostname lookup cache, in entries.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Rename to "host_cache_count"?
|
||||||
HostCacheSize int `yaml:"host_cache_size"`
|
HostCacheSize int `yaml:"host_cache_size"`
|
||||||
|
|
||||||
// IPCacheSize is the size of the IP lookup cache, in entries.
|
// IPCacheSize is the size of the IP lookup cache, in entries.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Rename to "ip_cache_count"?
|
||||||
IPCacheSize int `yaml:"ip_cache_size"`
|
IPCacheSize int `yaml:"ip_cache_size"`
|
||||||
|
|
||||||
// RefreshIvl defines how often AdGuard DNS reopens the GeoIP database
|
// RefreshIvl defines how often AdGuard DNS reopens the GeoIP database
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
|
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
|
||||||
"github.com/AdguardTeam/golibs/container"
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
@ -14,11 +17,11 @@ import (
|
|||||||
// toInternal returns the configuration of DNS servers for a single server
|
// toInternal returns the configuration of DNS servers for a single server
|
||||||
// group. srvs and other parts of the configuration must be valid.
|
// group. srvs and other parts of the configuration must be valid.
|
||||||
func (srvs servers) toInternal(
|
func (srvs servers) toInternal(
|
||||||
mtrc tlsconfig.Metrics,
|
|
||||||
tlsConfig *agd.TLS,
|
|
||||||
btdMgr *bindtodevice.Manager,
|
btdMgr *bindtodevice.Manager,
|
||||||
|
tlsMgr tlsconfig.Manager,
|
||||||
ratelimitConf *rateLimitConfig,
|
ratelimitConf *rateLimitConfig,
|
||||||
dnsConf *dnsConfig,
|
dnsConf *dnsConfig,
|
||||||
|
deviceDomains []string,
|
||||||
) (dnsSrvs []*agd.Server, err error) {
|
) (dnsSrvs []*agd.Server, err error) {
|
||||||
dnsSrvs = make([]*agd.Server, 0, len(srvs))
|
dnsSrvs = make([]*agd.Server, 0, len(srvs))
|
||||||
for _, srv := range srvs {
|
for _, srv := range srvs {
|
||||||
@ -66,18 +69,7 @@ func (srvs servers) toInternal(
|
|||||||
QUICLimitsEnabled: ratelimitConf.QUIC.Enabled,
|
QUICLimitsEnabled: ratelimitConf.QUIC.Enabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConf := tlsConfig.Conf.Clone()
|
dnsSrv.TLS = newTLSConfig(dnsSrv, tlsMgr, deviceDomains, srv)
|
||||||
|
|
||||||
// Attach the functions that will count TLS handshake metrics.
|
|
||||||
tlsConf.GetConfigForClient = mtrc.BeforeHandshake(string(srv.Protocol))
|
|
||||||
tlsConf.VerifyConnection = mtrc.AfterHandshake(
|
|
||||||
string(srv.Protocol),
|
|
||||||
srv.Name,
|
|
||||||
tlsConfig.DeviceDomains,
|
|
||||||
tlsConf.Certificates,
|
|
||||||
)
|
|
||||||
|
|
||||||
dnsSrv.TLS = tlsConf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsSrv.SetBindData(bindData)
|
dnsSrv.SetBindData(bindData)
|
||||||
@ -88,6 +80,35 @@ func (srvs servers) toInternal(
|
|||||||
return dnsSrvs, nil
|
return dnsSrvs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newTLSConfig returns the TLS configuration with metrics and ALPs set.
|
||||||
|
//
|
||||||
|
// TODO(s.chzhen): Consider moving to agd package as soon as the import cycle
|
||||||
|
// is resolved.
|
||||||
|
func newTLSConfig(
|
||||||
|
dnsSrv *agd.Server,
|
||||||
|
tlsMgr tlsconfig.Manager,
|
||||||
|
deviceDomains []string,
|
||||||
|
srv *server,
|
||||||
|
) (c *agd.TLSConfig) {
|
||||||
|
tlsConf := tlsMgr.CloneWithMetrics(string(srv.Protocol), srv.Name, deviceDomains)
|
||||||
|
|
||||||
|
var tlsConfH3 *tls.Config
|
||||||
|
switch dnsSrv.Protocol {
|
||||||
|
case agd.ProtoDoH:
|
||||||
|
tlsConfH3 = tlsMgr.CloneWithMetrics(string(srv.Protocol), srv.Name, deviceDomains)
|
||||||
|
|
||||||
|
tlsConf.NextProtos = slices.Clone(dnsserver.NextProtoDoH)
|
||||||
|
tlsConfH3.NextProtos = slices.Clone(dnsserver.NextProtoDoH3)
|
||||||
|
case agd.ProtoDoQ:
|
||||||
|
tlsConf.NextProtos = slices.Clone(dnsserver.NextProtoDoQ)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &agd.TLSConfig{
|
||||||
|
Default: tlsConf,
|
||||||
|
H3: tlsConfH3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// servers is a slice of server settings. A valid instance of servers has no
|
// servers is a slice of server settings. A valid instance of servers has no
|
||||||
// nil items.
|
// nil items.
|
||||||
type servers []*server
|
type servers []*server
|
||||||
@ -110,7 +131,7 @@ func (srvs servers) validate() (needsTLS bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if names.Has(s.Name) {
|
if names.Has(s.Name) {
|
||||||
return false, fmt.Errorf("at index %d: duplicate name %q", i, s.Name)
|
return false, fmt.Errorf("at index %d: name: %w: %q", i, errors.ErrDuplicated, s.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
names.Add(s.Name)
|
names.Add(s.Name)
|
||||||
@ -337,11 +358,11 @@ func (c *serverBindInterface) validate() (err error) {
|
|||||||
set := container.NewMapSet[netip.Prefix]()
|
set := container.NewMapSet[netip.Prefix]()
|
||||||
for i, subnet := range c.Subnets {
|
for i, subnet := range c.Subnets {
|
||||||
if !subnet.IsValid() {
|
if !subnet.IsValid() {
|
||||||
return fmt.Errorf("bad subnet at index %d", i)
|
return fmt.Errorf("subnets: at index %d: bad subnet", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if set.Has(subnet) {
|
if set.Has(subnet) {
|
||||||
return fmt.Errorf("duplicate subnet %s at index %d", subnet, i)
|
return fmt.Errorf("subnets: at index %d: %w: %s", i, errors.ErrDuplicated, subnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
set.Add(subnet)
|
set.Add(subnet)
|
||||||
|
@ -20,9 +20,9 @@ type serverGroups []*serverGroup
|
|||||||
// service. srvGrps and other parts of the configuration must be valid.
|
// service. srvGrps and other parts of the configuration must be valid.
|
||||||
func (srvGrps serverGroups) toInternal(
|
func (srvGrps serverGroups) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
|
||||||
messages *dnsmsg.Constructor,
|
messages *dnsmsg.Constructor,
|
||||||
btdMgr *bindtodevice.Manager,
|
btdMgr *bindtodevice.Manager,
|
||||||
|
tlsMgr tlsconfig.Manager,
|
||||||
fltGrps map[agd.FilteringGroupID]*agd.FilteringGroup,
|
fltGrps map[agd.FilteringGroupID]*agd.FilteringGroup,
|
||||||
ratelimitConf *rateLimitConfig,
|
ratelimitConf *rateLimitConfig,
|
||||||
dnsConf *dnsConfig,
|
dnsConf *dnsConfig,
|
||||||
@ -35,26 +35,26 @@ func (srvGrps serverGroups) toInternal(
|
|||||||
return nil, fmt.Errorf("server group %q: unknown filtering group %q", g.Name, fltGrpID)
|
return nil, fmt.Errorf("server group %q: unknown filtering group %q", g.Name, fltGrpID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConf *agd.TLS
|
var deviceDomains []string
|
||||||
tlsConf, err = g.TLS.toInternal(ctx, mtrc)
|
deviceDomains, err = g.TLS.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("tls: %w", err)
|
return nil, fmt.Errorf("tls %q: %w", g.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
svcSrvGrps[i] = &agd.ServerGroup{
|
svcSrvGrps[i] = &agd.ServerGroup{
|
||||||
DDR: g.DDR.toInternal(messages),
|
DDR: g.DDR.toInternal(messages),
|
||||||
TLS: tlsConf,
|
DeviceDomains: deviceDomains,
|
||||||
Name: agd.ServerGroupName(g.Name),
|
Name: agd.ServerGroupName(g.Name),
|
||||||
FilteringGroup: fltGrpID,
|
FilteringGroup: fltGrpID,
|
||||||
ProfilesEnabled: g.ProfilesEnabled,
|
ProfilesEnabled: g.ProfilesEnabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
svcSrvGrps[i].Servers, err = g.Servers.toInternal(
|
svcSrvGrps[i].Servers, err = g.Servers.toInternal(
|
||||||
mtrc,
|
|
||||||
tlsConf,
|
|
||||||
btdMgr,
|
btdMgr,
|
||||||
|
tlsMgr,
|
||||||
ratelimitConf,
|
ratelimitConf,
|
||||||
dnsConf,
|
dnsConf,
|
||||||
|
deviceDomains,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("server group %q: %w", g.Name, err)
|
return nil, fmt.Errorf("server group %q: %w", g.Name, err)
|
||||||
@ -81,7 +81,7 @@ func (srvGrps serverGroups) validate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if names.Has(g.Name) {
|
if names.Has(g.Name) {
|
||||||
return fmt.Errorf("at index %d: duplicate name %q", i, g.Name)
|
return fmt.Errorf("at index %d: name: %w: %q", i, errors.ErrDuplicated, g.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
names.Add(g.Name)
|
names.Add(g.Name)
|
||||||
@ -148,3 +148,16 @@ func (g *serverGroup) validate() (err error) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collectSessTicketPaths returns the list of unique session ticket file paths
|
||||||
|
// for all server groups.
|
||||||
|
func (srvGrps serverGroups) collectSessTicketPaths() (paths []string) {
|
||||||
|
set := container.NewSortedSliceSet[string]()
|
||||||
|
for _, g := range srvGrps {
|
||||||
|
for _, k := range g.TLS.SessionKeys {
|
||||||
|
set.Add(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return set.Values()
|
||||||
|
}
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
|
|
||||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ticketRotator is a refresh worker that rereads and resets TLS session
|
|
||||||
// tickets. It should be initially refreshed before use.
|
|
||||||
type ticketRotator struct {
|
|
||||||
logger *slog.Logger
|
|
||||||
errColl errcoll.Interface
|
|
||||||
mtrc tlsconfig.Metrics
|
|
||||||
confs map[*tls.Config][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// newTicketRotator creates a new TLS session ticket rotator that rotates
|
|
||||||
// tickets for the TLS configurations of all servers in grps.
|
|
||||||
//
|
|
||||||
// grps must be valid.
|
|
||||||
func newTicketRotator(
|
|
||||||
logger *slog.Logger,
|
|
||||||
errColl errcoll.Interface,
|
|
||||||
mtrc tlsconfig.Metrics,
|
|
||||||
grps []*agd.ServerGroup,
|
|
||||||
) (tr *ticketRotator) {
|
|
||||||
confs := map[*tls.Config][]string{}
|
|
||||||
|
|
||||||
for _, g := range grps {
|
|
||||||
t := g.TLS
|
|
||||||
if t == nil || len(t.SessionKeys) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, srv := range g.Servers {
|
|
||||||
if srv.TLS != nil {
|
|
||||||
confs[srv.TLS] = t.SessionKeys
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ticketRotator{
|
|
||||||
logger: logger.With(slogutil.KeyPrefix, "tickrot"),
|
|
||||||
errColl: errColl,
|
|
||||||
mtrc: mtrc,
|
|
||||||
confs: confs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sessTickLen is the length of a single TLS session ticket key in bytes.
|
|
||||||
//
|
|
||||||
// NOTE: Unlike Nginx, Go's crypto/tls doesn't use the random bytes from the
|
|
||||||
// session ticket keys as-is, but instead hashes these bytes and uses the first
|
|
||||||
// 48 bytes of the hashed data as the key name, the AES key, and the HMAC key.
|
|
||||||
const sessTickLen = 32
|
|
||||||
|
|
||||||
// type check
|
|
||||||
var _ agdservice.Refresher = (*ticketRotator)(nil)
|
|
||||||
|
|
||||||
// Refresh implements the [agdservice.Refresher] interface for *ticketRotator.
|
|
||||||
func (r *ticketRotator) Refresh(ctx context.Context) (err error) {
|
|
||||||
r.logger.DebugContext(ctx, "refresh started")
|
|
||||||
defer r.logger.DebugContext(ctx, "refresh finished")
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
errcoll.Collect(ctx, r.errColl, r.logger, "ticket rotation failed", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for conf, files := range r.confs {
|
|
||||||
keys := make([][sessTickLen]byte, 0, len(files))
|
|
||||||
|
|
||||||
for _, fileName := range files {
|
|
||||||
var key [sessTickLen]byte
|
|
||||||
key, err = readSessionTicketKey(fileName)
|
|
||||||
if err != nil {
|
|
||||||
r.mtrc.SetSessionTicketRotationStatus(ctx, false)
|
|
||||||
|
|
||||||
return fmt.Errorf("session ticket for srv %s: %w", conf.ServerName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(keys) == 0 {
|
|
||||||
return fmt.Errorf("no session tickets for srv %s in %q", conf.ServerName, files)
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.SetSessionTicketKeys(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.mtrc.SetSessionTicketRotationStatus(ctx, true)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// readSessionTicketKey reads a single TLS session ticket key from a file.
|
|
||||||
func readSessionTicketKey(fn string) (key [sessTickLen]byte, err error) {
|
|
||||||
// #nosec G304 -- Trust the file paths that are given to us in the
|
|
||||||
// configuration file.
|
|
||||||
b, err := os.ReadFile(fn)
|
|
||||||
if err != nil {
|
|
||||||
return key, fmt.Errorf("reading session ticket: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(b) < sessTickLen {
|
|
||||||
return key, fmt.Errorf("session ticket in %s: bad len %d, want %d", fn, len(b), sessTickLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [sessTickLen]byte(b), nil
|
|
||||||
}
|
|
@ -3,13 +3,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
|
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
|
||||||
"github.com/AdguardTeam/golibs/container"
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
@ -39,27 +35,22 @@ type tlsConfig struct {
|
|||||||
// valid.
|
// valid.
|
||||||
func (c *tlsConfig) toInternal(
|
func (c *tlsConfig) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (conf *agd.TLS, err error) {
|
) (deviceDomains []string, err error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConf, err := c.Certificates.toInternal(ctx, mtrc)
|
err = c.Certificates.store(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("certificates: %w", err)
|
return nil, fmt.Errorf("certificates: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var deviceDomains []string
|
|
||||||
for _, w := range c.DeviceIDWildcards {
|
for _, w := range c.DeviceIDWildcards {
|
||||||
deviceDomains = append(deviceDomains, strings.TrimPrefix(w, "*."))
|
deviceDomains = append(deviceDomains, strings.TrimPrefix(w, "*."))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &agd.TLS{
|
return deviceDomains, nil
|
||||||
Conf: tlsConf,
|
|
||||||
DeviceDomains: deviceDomains,
|
|
||||||
SessionKeys: c.SessionKeys,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate returns an error if the TLS configuration is invalid for the given
|
// validate returns an error if the TLS configuration is invalid for the given
|
||||||
@ -101,9 +92,9 @@ func validateDeviceIDWildcards(wildcards []string) (err error) {
|
|||||||
for i, w := range wildcards {
|
for i, w := range wildcards {
|
||||||
// TODO(e.burkov): Consider removing this requirement.
|
// TODO(e.burkov): Consider removing this requirement.
|
||||||
if !strings.HasPrefix(w, "*.") {
|
if !strings.HasPrefix(w, "*.") {
|
||||||
return fmt.Errorf("at index %d: not a wildcard", i)
|
return fmt.Errorf("at index %d: not a wildcard: %q", i, w)
|
||||||
} else if s.Has(w) {
|
} else if s.Has(w) {
|
||||||
return fmt.Errorf("at index %d: duplicated wildcard", i)
|
return fmt.Errorf("at index %d: wildcard: %w: %q", i, errors.ErrDuplicated, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Add(w)
|
s.Add(w)
|
||||||
@ -125,42 +116,40 @@ type tlsConfigCert struct {
|
|||||||
// no nil items.
|
// no nil items.
|
||||||
type tlsConfigCerts []*tlsConfigCert
|
type tlsConfigCerts []*tlsConfigCert
|
||||||
|
|
||||||
// toInternal converts certs to a TLS configuration. certs must be valid.
|
// store stores the TLS certificates in the TLS manager. certs must be valid.
|
||||||
|
func (certs tlsConfigCerts) store(ctx context.Context, tlsMgr tlsconfig.Manager) (err error) {
|
||||||
|
var errs []error
|
||||||
|
for i, c := range certs {
|
||||||
|
err = tlsMgr.Add(ctx, c.Certificate, c.Key)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("adding certificate at index %d: %w", i, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) != 0 {
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toInternal is like [tlsConfigCerts.store] but it also returns the TLS
|
||||||
|
// configuration. certs must be valid.
|
||||||
func (certs tlsConfigCerts) toInternal(
|
func (certs tlsConfigCerts) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (conf *tls.Config, err error) {
|
) (conf *tls.Config, err error) {
|
||||||
if len(certs) == 0 {
|
if len(certs) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsCerts := make([]tls.Certificate, len(certs))
|
err = certs.store(ctx, tlsMgr)
|
||||||
for i, c := range certs {
|
|
||||||
var cert tls.Certificate
|
|
||||||
cert, err = tls.LoadX509KeyPair(c.Certificate, c.Key)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("certificate at index %d: %w", i, err)
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var leaf *x509.Certificate
|
return tlsMgr.Clone(), nil
|
||||||
leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid leaf, certificate at index %d: %w", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert.Leaf = leaf
|
|
||||||
tlsCerts[i] = cert
|
|
||||||
|
|
||||||
authAlgo, subj := leaf.PublicKeyAlgorithm.String(), leaf.Subject.String()
|
|
||||||
|
|
||||||
mtrc.SetCertificateInfo(ctx, authAlgo, subj, leaf.NotAfter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tls.Config{
|
|
||||||
Certificates: tlsCerts,
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
MaxVersion: tls.VersionTLS13,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
@ -181,24 +170,3 @@ func (certs tlsConfigCerts) validate() (err error) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// enableTLSKeyLogging enables TLS key logging (use for debug purposes only).
|
|
||||||
func enableTLSKeyLogging(grps []*agd.ServerGroup, keyLogFileName string) (err error) {
|
|
||||||
path := filepath.Clean(keyLogFileName)
|
|
||||||
|
|
||||||
// TODO(a.garipov): Consider closing the file when we add SIGHUP support.
|
|
||||||
kl, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("opening SSL_KEY_LOG_FILE: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, g := range grps {
|
|
||||||
for _, s := range g.Servers {
|
|
||||||
if s.TLS != nil {
|
|
||||||
s.TLS.KeyLogWriter = kl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -41,7 +41,10 @@ func (c *upstreamConfig) toInternal(logger *slog.Logger) (fwdConf *forward.Handl
|
|||||||
|
|
||||||
upsConfs := toUpstreamConfigs(upstreams)
|
upsConfs := toUpstreamConfigs(upstreams)
|
||||||
fallbackConfs := toUpstreamConfigs(fallbacks)
|
fallbackConfs := toUpstreamConfigs(fallbacks)
|
||||||
metricsListener := prometheus.NewForwardMetricsListener(metrics.Namespace(), len(upstreams)+len(fallbacks))
|
metricsListener := prometheus.NewForwardMetricsListener(
|
||||||
|
metrics.Namespace(),
|
||||||
|
len(upstreams)+len(fallbacks),
|
||||||
|
)
|
||||||
|
|
||||||
var hcInit time.Duration
|
var hcInit time.Duration
|
||||||
if c.Healthcheck.Enabled {
|
if c.Healthcheck.Enabled {
|
||||||
|
@ -68,7 +68,7 @@ func (c *webConfig) toInternal(
|
|||||||
envs *environment,
|
envs *environment,
|
||||||
dnsCk dnscheck.Interface,
|
dnsCk dnscheck.Interface,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (conf *websvc.Config, err error) {
|
) (conf *websvc.Config, err error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -87,7 +87,7 @@ func (c *webConfig) toInternal(
|
|||||||
conf.RootRedirectURL = netutil.CloneURL(&c.RootRedirectURL.URL)
|
conf.RootRedirectURL = netutil.CloneURL(&c.RootRedirectURL.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.LinkedIP, err = c.LinkedIP.toInternal(ctx, mtrc, envs.LinkedIPTargetURL)
|
conf.LinkedIP, err = c.LinkedIP.toInternal(ctx, tlsMgr, envs.LinkedIPTargetURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("converting linked_ip: %w", err)
|
return nil, fmt.Errorf("converting linked_ip: %w", err)
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ func (c *webConfig) toInternal(
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
for _, bp := range blockPages {
|
for _, bp := range blockPages {
|
||||||
*bp.webConfPtr, err = bp.conf.toInternal(ctx, mtrc)
|
*bp.webConfPtr, err = bp.conf.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %w", bp.name, err)
|
return nil, fmt.Errorf("%s: %w", bp.name, err)
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (c *webConfig) toInternal(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.NonDoHBind, err = c.NonDoHBind.toInternal(ctx, mtrc)
|
conf.NonDoHBind, err = c.NonDoHBind.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("converting non_doh_bind: %w", err)
|
return nil, fmt.Errorf("converting non_doh_bind: %w", err)
|
||||||
}
|
}
|
||||||
@ -230,7 +230,7 @@ type linkedIPServer struct {
|
|||||||
// toInternal converts s to a linkedIP server configuration. s must be valid.
|
// toInternal converts s to a linkedIP server configuration. s must be valid.
|
||||||
func (s *linkedIPServer) toInternal(
|
func (s *linkedIPServer) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
targetURL *urlutil.URL,
|
targetURL *urlutil.URL,
|
||||||
) (srv *websvc.LinkedIPServer, err error) {
|
) (srv *websvc.LinkedIPServer, err error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
@ -238,7 +238,7 @@ func (s *linkedIPServer) toInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
srv = &websvc.LinkedIPServer{}
|
srv = &websvc.LinkedIPServer{}
|
||||||
srv.Bind, err = s.Bind.toInternal(ctx, mtrc)
|
srv.Bind, err = s.Bind.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("converting bind: %w", err)
|
return nil, fmt.Errorf("converting bind: %w", err)
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ type blockPageServer struct {
|
|||||||
// toInternal converts s to a block page server configuration. s must be valid.
|
// toInternal converts s to a block page server configuration. s must be valid.
|
||||||
func (s *blockPageServer) toInternal(
|
func (s *blockPageServer) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (conf *websvc.BlockPageServerConfig, err error) {
|
) (conf *websvc.BlockPageServerConfig, err error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -298,7 +298,7 @@ func (s *blockPageServer) toInternal(
|
|||||||
ContentFilePath: s.BlockPage,
|
ContentFilePath: s.BlockPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Bind, err = s.Bind.toInternal(ctx, mtrc)
|
conf.Bind, err = s.Bind.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("converting bind: %w", err)
|
return nil, fmt.Errorf("converting bind: %w", err)
|
||||||
}
|
}
|
||||||
@ -337,12 +337,12 @@ type bindData []*bindItem
|
|||||||
// be valid.
|
// be valid.
|
||||||
func (bd bindData) toInternal(
|
func (bd bindData) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (data []*websvc.BindData, err error) {
|
) (data []*websvc.BindData, err error) {
|
||||||
data = make([]*websvc.BindData, len(bd))
|
data = make([]*websvc.BindData, len(bd))
|
||||||
|
|
||||||
for i, d := range bd {
|
for i, d := range bd {
|
||||||
data[i], err = d.toInternal(ctx, mtrc)
|
data[i], err = d.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bind data at index %d: %w", i, err)
|
return nil, fmt.Errorf("bind data at index %d: %w", i, err)
|
||||||
}
|
}
|
||||||
@ -383,9 +383,9 @@ type bindItem struct {
|
|||||||
// be valid.
|
// be valid.
|
||||||
func (i *bindItem) toInternal(
|
func (i *bindItem) toInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mtrc tlsconfig.Metrics,
|
tlsMgr tlsconfig.Manager,
|
||||||
) (data *websvc.BindData, err error) {
|
) (data *websvc.BindData, err error) {
|
||||||
tlsConf, err := i.Certificates.toInternal(ctx, mtrc)
|
tlsConf, err := i.Certificates.toInternal(ctx, tlsMgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("certificates: %w", err)
|
return nil, fmt.Errorf("certificates: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -17,27 +17,27 @@ import (
|
|||||||
|
|
||||||
func TestListenConfig(t *testing.T) {
|
func TestListenConfig(t *testing.T) {
|
||||||
pc := &fakenet.PacketConn{
|
pc := &fakenet.PacketConn{
|
||||||
OnClose: func() (err error) { panic("not implemented") },
|
OnClose: func() (_ error) { panic("not implemented") },
|
||||||
OnLocalAddr: func() (laddr net.Addr) { panic("not implemented") },
|
OnLocalAddr: func() (_ net.Addr) { panic("not implemented") },
|
||||||
OnReadFrom: func(b []byte) (n int, addr net.Addr, err error) { panic("not implemented") },
|
OnReadFrom: func(_ []byte) (_ int, _ net.Addr, _ error) {
|
||||||
OnSetDeadline: func(t time.Time) (err error) { panic("not implemented") },
|
panic("not implemented")
|
||||||
OnSetReadDeadline: func(t time.Time) (err error) { panic("not implemented") },
|
},
|
||||||
OnSetWriteDeadline: func(t time.Time) (err error) { panic("not implemented") },
|
OnSetDeadline: func(_ time.Time) (_ error) { panic("not implemented") },
|
||||||
OnWriteTo: func(b []byte, addr net.Addr) (n int, err error) { panic("not implemented") },
|
OnSetReadDeadline: func(_ time.Time) (_ error) { panic("not implemented") },
|
||||||
|
OnSetWriteDeadline: func(_ time.Time) (_ error) { panic("not implemented") },
|
||||||
|
OnWriteTo: func(_ []byte, _ net.Addr) (_ int, _ error) {
|
||||||
|
panic("not implemented")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
lsnr := &fakenet.Listener{
|
lsnr := &fakenet.Listener{
|
||||||
OnAccept: func() (c net.Conn, err error) { panic("not implemented") },
|
OnAccept: func() (_ net.Conn, _ error) { panic("not implemented") },
|
||||||
OnAddr: func() (addr net.Addr) { panic("not implemented") },
|
OnAddr: func() (_ net.Addr) { panic("not implemented") },
|
||||||
OnClose: func() (err error) { return nil },
|
OnClose: func() (_ error) { return nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &agdtest.ListenConfig{
|
c := &agdtest.ListenConfig{
|
||||||
OnListen: func(
|
OnListen: func(ctx context.Context, network, address string) (l net.Listener, err error) {
|
||||||
ctx context.Context,
|
|
||||||
network string,
|
|
||||||
address string,
|
|
||||||
) (l net.Listener, err error) {
|
|
||||||
return lsnr, nil
|
return lsnr, nil
|
||||||
},
|
},
|
||||||
OnListenPacket: func(
|
OnListenPacket: func(
|
||||||
|
@ -162,7 +162,7 @@ func TestService_Start(t *testing.T) {
|
|||||||
resp, err = client.Post(ctx, refreshURL, agdhttp.HdrValApplicationJSON, reqBody)
|
resp, err = client.Post(ctx, refreshURL, agdhttp.HdrValApplicationJSON, reqBody)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Len(t, refreshed, 0)
|
assert.Empty(t, refreshed)
|
||||||
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
||||||
|
|
||||||
respBody = readRespBody(t, resp)
|
respBody = readRespBody(t, resp)
|
||||||
|
@ -2,15 +2,8 @@ package dnscheck_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testutil.DiscardLogOutput(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test data.
|
// Test data.
|
||||||
var (
|
var (
|
||||||
testRemoteIP = netip.MustParseAddr("1.2.3.4")
|
testRemoteIP = netip.MustParseAddr("1.2.3.4")
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"slices"
|
"slices"
|
||||||
@ -19,7 +20,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv/consulkv"
|
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv/consulkv"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/httphdr"
|
"github.com/AdguardTeam/golibs/httphdr"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
cache "github.com/patrickmn/go-cache"
|
cache "github.com/patrickmn/go-cache"
|
||||||
@ -28,8 +29,10 @@ import (
|
|||||||
|
|
||||||
// RemoteKV is the RemoteKV KV based DNS checker.
|
// RemoteKV is the RemoteKV KV based DNS checker.
|
||||||
type RemoteKV struct {
|
type RemoteKV struct {
|
||||||
// mu protects cache. Don't use an RWMutex here, since the ratio of read
|
logger *slog.Logger
|
||||||
// and write access is expected to be approximately equal.
|
|
||||||
|
// mu protects cache. Don't use an RWMutex here, since it is expected that
|
||||||
|
// there are about as many reads as there are writes.
|
||||||
mu *sync.Mutex
|
mu *sync.Mutex
|
||||||
cache *cache.Cache
|
cache *cache.Cache
|
||||||
|
|
||||||
@ -49,6 +52,9 @@ type RemoteKV struct {
|
|||||||
// RemoteKVConfig is the configuration structure for remote KV based DNS
|
// RemoteKVConfig is the configuration structure for remote KV based DNS
|
||||||
// checker. All fields must be non-empty.
|
// checker. All fields must be non-empty.
|
||||||
type RemoteKVConfig struct {
|
type RemoteKVConfig struct {
|
||||||
|
// Logger is used to log the operation of the DNS checker.
|
||||||
|
Logger *slog.Logger
|
||||||
|
|
||||||
// Messages is the message constructor used to create DNS responses with
|
// Messages is the message constructor used to create DNS responses with
|
||||||
// IPv4 and IPv6 IPs.
|
// IPv4 and IPv6 IPs.
|
||||||
Messages *dnsmsg.Constructor
|
Messages *dnsmsg.Constructor
|
||||||
@ -85,8 +91,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewRemoteKV creates a new remote KV based DNS checker. c must be non-nil.
|
// NewRemoteKV creates a new remote KV based DNS checker. c must be non-nil.
|
||||||
func NewRemoteKV(c *RemoteKVConfig) (cc *RemoteKV) {
|
func NewRemoteKV(c *RemoteKVConfig) (dc *RemoteKV) {
|
||||||
return &RemoteKV{
|
return &RemoteKV{
|
||||||
|
logger: c.Logger,
|
||||||
mu: &sync.Mutex{},
|
mu: &sync.Mutex{},
|
||||||
cache: cache.New(defaultCacheExp, defaultCacheGC),
|
cache: cache.New(defaultCacheExp, defaultCacheGC),
|
||||||
kv: c.RemoteKV,
|
kv: c.RemoteKV,
|
||||||
@ -104,7 +111,7 @@ func NewRemoteKV(c *RemoteKVConfig) (cc *RemoteKV) {
|
|||||||
var _ Interface = (*RemoteKV)(nil)
|
var _ Interface = (*RemoteKV)(nil)
|
||||||
|
|
||||||
// Check implements the Interface interface for *RemoteKV.
|
// Check implements the Interface interface for *RemoteKV.
|
||||||
func (cc *RemoteKV) Check(
|
func (dc *RemoteKV) Check(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *dns.Msg,
|
req *dns.Msg,
|
||||||
ri *agd.RequestInfo,
|
ri *agd.RequestInfo,
|
||||||
@ -124,7 +131,7 @@ func (cc *RemoteKV) Check(
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var randomID string
|
var randomID string
|
||||||
randomID, matched, err = randomIDFromDomain(ri.Host, cc.domains)
|
randomID, matched, err = randomIDFromDomain(ri.Host, dc.domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -132,32 +139,32 @@ func (cc *RemoteKV) Check(
|
|||||||
// Not a dnscheck domain, just ignore the request.
|
// Not a dnscheck domain, just ignore the request.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else if randomID == "" {
|
} else if randomID == "" {
|
||||||
return cc.resp(ri, req)
|
return dc.resp(ri, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
inf := cc.newInfo(ri)
|
inf := dc.newInfo(ri)
|
||||||
b, err := json.Marshal(inf)
|
b, err := json.Marshal(inf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("encoding value for key %q for remote kv: %w", randomID, err)
|
return nil, fmt.Errorf("encoding value for key %q for remote kv: %w", randomID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cc.addToCache(randomID, b)
|
dc.addToCache(randomID, b)
|
||||||
|
|
||||||
err = cc.kv.Set(ctx, randomID, b)
|
err = dc.kv.Set(ctx, randomID, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errcoll.Collectf(ctx, cc.errColl, "dnscheck: remote kv setting: %w", err)
|
errcoll.Collect(ctx, dc.errColl, dc.logger, "remote kv setting", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc.resp(ri, req)
|
return dc.resp(ri, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addToCache adds inf into cache using randomID as key. It's safe for
|
// addToCache adds inf into cache using randomID as key. It's safe for
|
||||||
// concurrent use.
|
// concurrent use.
|
||||||
func (cc *RemoteKV) addToCache(randomID string, inf []byte) {
|
func (dc *RemoteKV) addToCache(randomID string, inf []byte) {
|
||||||
cc.mu.Lock()
|
dc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer dc.mu.Unlock()
|
||||||
|
|
||||||
cc.cache.SetDefault(randomID, inf)
|
dc.cache.SetDefault(randomID, inf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverType is a type for the enum of server types in the DNS checker HTTP
|
// serverType is a type for the enum of server types in the DNS checker HTTP
|
||||||
@ -172,7 +179,7 @@ const (
|
|||||||
|
|
||||||
// newInfo returns an information record with all available data about the
|
// newInfo returns an information record with all available data about the
|
||||||
// server and the request. ri must not be nil.
|
// server and the request. ri must not be nil.
|
||||||
func (cc *RemoteKV) newInfo(ri *agd.RequestInfo) (inf *info) {
|
func (dc *RemoteKV) newInfo(ri *agd.RequestInfo) (inf *info) {
|
||||||
g := ri.ServerGroup
|
g := ri.ServerGroup
|
||||||
|
|
||||||
srvType := serverTypePublic
|
srvType := serverTypePublic
|
||||||
@ -186,8 +193,8 @@ func (cc *RemoteKV) newInfo(ri *agd.RequestInfo) (inf *info) {
|
|||||||
ServerType: srvType,
|
ServerType: srvType,
|
||||||
|
|
||||||
Protocol: ri.Proto.String(),
|
Protocol: ri.Proto.String(),
|
||||||
NodeLocation: cc.nodeLocation,
|
NodeLocation: dc.nodeLocation,
|
||||||
NodeName: cc.nodeName,
|
NodeName: dc.nodeName,
|
||||||
|
|
||||||
ClientIP: ri.RemoteIP,
|
ClientIP: ri.RemoteIP,
|
||||||
}
|
}
|
||||||
@ -204,7 +211,7 @@ func (cc *RemoteKV) newInfo(ri *agd.RequestInfo) (inf *info) {
|
|||||||
//
|
//
|
||||||
// TODO(e.burkov): Inspect the reason for using different message constructors
|
// TODO(e.burkov): Inspect the reason for using different message constructors
|
||||||
// for different DNS types, and consider using only one of them.
|
// for different DNS types, and consider using only one of them.
|
||||||
func (cc *RemoteKV) resp(ri *agd.RequestInfo, req *dns.Msg) (resp *dns.Msg, err error) {
|
func (dc *RemoteKV) resp(ri *agd.RequestInfo, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||||
qt := ri.QType
|
qt := ri.QType
|
||||||
|
|
||||||
if qt != dns.TypeA && qt != dns.TypeAAAA {
|
if qt != dns.TypeA && qt != dns.TypeAAAA {
|
||||||
@ -212,24 +219,23 @@ func (cc *RemoteKV) resp(ri *agd.RequestInfo, req *dns.Msg) (resp *dns.Msg, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if qt == dns.TypeA {
|
if qt == dns.TypeA {
|
||||||
return cc.messages.NewRespIP(req, cc.ipv4...)
|
return dc.messages.NewRespIP(req, dc.ipv4...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc.messages.NewRespIP(req, cc.ipv6...)
|
return dc.messages.NewRespIP(req, dc.ipv6...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ http.Handler = (*RemoteKV)(nil)
|
var _ http.Handler = (*RemoteKV)(nil)
|
||||||
|
|
||||||
// ServeHTTP implements the http.Handler interface for *RemoteKV.
|
// ServeHTTP implements the http.Handler interface for *RemoteKV.
|
||||||
func (cc *RemoteKV) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
//
|
||||||
m, p, raddr := r.Method, r.URL.Path, r.RemoteAddr
|
// TODO(a.garipov): Consider using the websvc logger once it switches to
|
||||||
log.Debug("dnscheck: http req %s %s from %s", m, p, raddr)
|
// log/slog.
|
||||||
defer log.Debug("dnscheck: finished http req %s %s from %s", m, p, raddr)
|
func (dc *RemoteKV) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// TODO(a.garipov): Put this into constant here and in package dnssvc.
|
// TODO(a.garipov): Put this into constant here and in package dnssvc.
|
||||||
if r.URL.Path == "/dnscheck/test" {
|
if r.URL.Path == "/dnscheck/test" {
|
||||||
cc.serveCheckTest(r.Context(), w, r)
|
dc.serveCheckTest(r.Context(), w, r)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -241,48 +247,48 @@ func (cc *RemoteKV) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
//
|
//
|
||||||
// TODO(a.garipov): Refactor this and other HTTP handlers to return wrapped
|
// TODO(a.garipov): Refactor this and other HTTP handlers to return wrapped
|
||||||
// errors and centralize the error handling.
|
// errors and centralize the error handling.
|
||||||
func (cc *RemoteKV) serveCheckTest(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
func (dc *RemoteKV) serveCheckTest(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
raddr := r.RemoteAddr
|
l := dc.logger.With("raddr", r.RemoteAddr)
|
||||||
|
|
||||||
name, err := netutil.SplitHost(r.Host)
|
host, err := netutil.SplitHost(r.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("dnscheck: http req from %s: bad host %q: %s", raddr, r.Host, err)
|
l.DebugContext(ctx, "bad host", "hostport", r.Host, slogutil.KeyError, err)
|
||||||
|
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
randomID, matched, err := randomIDFromDomain(name, cc.domains)
|
randomID, matched, err := randomIDFromDomain(host, dc.domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("dnscheck: http req from %s: id: %s", raddr, err)
|
l.DebugContext(ctx, "bad request", "host", host, slogutil.KeyError, err)
|
||||||
|
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
|
|
||||||
return
|
return
|
||||||
} else if !matched || randomID == "" {
|
} else if !matched || randomID == "" {
|
||||||
// We expect dnscheck requests to have a unique ID in the domain name.
|
// We expect dnscheck requests to have a unique ID in the domain name.
|
||||||
log.Debug("dnscheck: http req from %s: bad domain %q", raddr, name)
|
l.DebugContext(ctx, "bad domain", "host", host, slogutil.KeyError, err)
|
||||||
|
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inf, ok, err := cc.info(ctx, randomID)
|
inf, ok, err := dc.info(ctx, randomID)
|
||||||
// TODO(s.chzhen): Use error interface instead of error value.
|
// TODO(s.chzhen): Use error interface instead of error value.
|
||||||
if errors.Is(err, consulkv.ErrRateLimited) {
|
if errors.Is(err, consulkv.ErrRateLimited) {
|
||||||
http.Error(w, err.Error(), http.StatusTooManyRequests)
|
http.Error(w, err.Error(), http.StatusTooManyRequests)
|
||||||
|
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Debug("dnscheck: http req from %s: getting info: %s", raddr, err)
|
l.DebugContext(ctx, "getting info", "random_id", randomID, slogutil.KeyError, err)
|
||||||
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
||||||
return
|
return
|
||||||
} else if !ok {
|
} else if !ok {
|
||||||
log.Debug("dnscheck: http req from %s: no info for %q", raddr, randomID)
|
l.DebugContext(ctx, "no info", "random_id", randomID, slogutil.KeyError, err)
|
||||||
|
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
|
|
||||||
@ -295,12 +301,12 @@ func (cc *RemoteKV) serveCheckTest(ctx context.Context, w http.ResponseWriter, r
|
|||||||
|
|
||||||
_, err = w.Write(inf)
|
_, err = w.Write(inf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errcoll.Collectf(ctx, cc.errColl, "dnscheck: http resp write error: %w", err)
|
errcoll.Collect(ctx, dc.errColl, dc.logger, "http resp write", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// info returns an information record by the random request ID.
|
// info returns an information record by the random request ID.
|
||||||
func (cc *RemoteKV) info(ctx context.Context, randomID string) (inf []byte, ok bool, err error) {
|
func (dc *RemoteKV) info(ctx context.Context, randomID string) (inf []byte, ok bool, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
metrics.DNSCheckRequestTotal.With(prometheus.Labels{
|
metrics.DNSCheckRequestTotal.With(prometheus.Labels{
|
||||||
"type": "http",
|
"type": "http",
|
||||||
@ -312,17 +318,17 @@ func (cc *RemoteKV) info(ctx context.Context, randomID string) (inf []byte, ok b
|
|||||||
|
|
||||||
defer func() { err = errors.Annotate(err, "getting from remote kv: %w") }()
|
defer func() { err = errors.Annotate(err, "getting from remote kv: %w") }()
|
||||||
|
|
||||||
cc.mu.Lock()
|
dc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer dc.mu.Unlock()
|
||||||
|
|
||||||
infoVal, ok := cc.cache.Get(randomID)
|
infoVal, ok := dc.cache.Get(randomID)
|
||||||
if ok {
|
if ok {
|
||||||
return infoVal.([]byte), true, nil
|
return infoVal.([]byte), true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
inf, ok, err = cc.kv.Get(ctx, randomID)
|
inf, ok, err = dc.kv.Get(ctx, randomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errcoll.Collectf(ctx, cc.errColl, "dnscheck: remote kv getting: %w", err)
|
errcoll.Collect(ctx, dc.errColl, dc.logger, "remote kv getting", err)
|
||||||
|
|
||||||
// Don't wrap the error, as it will get annotated.
|
// Don't wrap the error, as it will get annotated.
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv"
|
"github.com/AdguardTeam/AdGuardDNS/internal/remotekv"
|
||||||
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -46,6 +47,7 @@ func TestConsul_ServeHTTP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf := &dnscheck.RemoteKVConfig{
|
conf := &dnscheck.RemoteKVConfig{
|
||||||
|
Logger: slogutil.NewDiscardLogger(),
|
||||||
Messages: &dnsmsg.Constructor{},
|
Messages: &dnsmsg.Constructor{},
|
||||||
RemoteKV: remotekv.Empty{},
|
RemoteKV: remotekv.Empty{},
|
||||||
ErrColl: agdtest.NewErrorCollector(),
|
ErrColl: agdtest.NewErrorCollector(),
|
||||||
@ -171,6 +173,7 @@ func TestConsul_Check(t *testing.T) {
|
|||||||
msgs := agdtest.NewConstructorWithTTL(t, ttl*time.Second)
|
msgs := agdtest.NewConstructorWithTTL(t, ttl*time.Second)
|
||||||
|
|
||||||
conf := &dnscheck.RemoteKVConfig{
|
conf := &dnscheck.RemoteKVConfig{
|
||||||
|
Logger: slogutil.NewDiscardLogger(),
|
||||||
Messages: msgs,
|
Messages: msgs,
|
||||||
RemoteKV: remotekv.Empty{},
|
RemoteKV: remotekv.Empty{},
|
||||||
Domains: []string{checkDomain},
|
Domains: []string{checkDomain},
|
||||||
|
@ -6,6 +6,7 @@ package dnsdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -35,6 +36,7 @@ func (Empty) Record(_ context.Context, _ *dns.Msg, _ *agd.RequestInfo) {}
|
|||||||
|
|
||||||
// Default is the default DNSDB implementation.
|
// Default is the default DNSDB implementation.
|
||||||
type Default struct {
|
type Default struct {
|
||||||
|
logger *slog.Logger
|
||||||
buffer *atomic.Pointer[buffer]
|
buffer *atomic.Pointer[buffer]
|
||||||
errColl errcoll.Interface
|
errColl errcoll.Interface
|
||||||
maxSize int
|
maxSize int
|
||||||
@ -42,6 +44,9 @@ type Default struct {
|
|||||||
|
|
||||||
// DefaultConfig is the default DNS database configuration structure.
|
// DefaultConfig is the default DNS database configuration structure.
|
||||||
type DefaultConfig struct {
|
type DefaultConfig struct {
|
||||||
|
// Logger is used to log the operation of the DNS database.
|
||||||
|
Logger *slog.Logger
|
||||||
|
|
||||||
// ErrColl is used to collect HTTP errors.
|
// ErrColl is used to collect HTTP errors.
|
||||||
ErrColl errcoll.Interface
|
ErrColl errcoll.Interface
|
||||||
|
|
||||||
@ -52,6 +57,7 @@ type DefaultConfig struct {
|
|||||||
// New creates a new default DNS database. c must not be nil.
|
// New creates a new default DNS database. c must not be nil.
|
||||||
func New(c *DefaultConfig) (db *Default) {
|
func New(c *DefaultConfig) (db *Default) {
|
||||||
db = &Default{
|
db = &Default{
|
||||||
|
logger: c.Logger,
|
||||||
buffer: &atomic.Pointer[buffer]{},
|
buffer: &atomic.Pointer[buffer]{},
|
||||||
errColl: c.ErrColl,
|
errColl: c.ErrColl,
|
||||||
maxSize: c.MaxSize,
|
maxSize: c.MaxSize,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package dnsdb_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
testutil.DiscardLogOutput(m)
|
|
||||||
}
|
|
@ -31,7 +31,7 @@ func (db *Default) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Set(httphdr.XError, err.Error())
|
h.Set(httphdr.XError, err.Error())
|
||||||
errcoll.Collectf(ctx, db.errColl, "dnsdb: http handler error: %w", err)
|
errcoll.Collect(ctx, db.errColl, db.logger, "handling http", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsdb"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/dnsservertest"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/dnsservertest"
|
||||||
"github.com/AdguardTeam/golibs/httphdr"
|
"github.com/AdguardTeam/golibs/httphdr"
|
||||||
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -120,6 +121,7 @@ func TestDefault_ServeHTTP(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
db := dnsdb.New(&dnsdb.DefaultConfig{
|
db := dnsdb.New(&dnsdb.DefaultConfig{
|
||||||
|
Logger: slogutil.NewDiscardLogger(),
|
||||||
ErrColl: agdtest.NewErrorCollector(),
|
ErrColl: agdtest.NewErrorCollector(),
|
||||||
MaxSize: 100,
|
MaxSize: 100,
|
||||||
})
|
})
|
||||||
|
8
internal/dnsserver/cache/cache.go
vendored
8
internal/dnsserver/cache/cache.go
vendored
@ -42,9 +42,9 @@ type MiddlewareConfig struct {
|
|||||||
// performance metrics. If not set, EmptyMetricsListener is used.
|
// performance metrics. If not set, EmptyMetricsListener is used.
|
||||||
MetricsListener MetricsListener
|
MetricsListener MetricsListener
|
||||||
|
|
||||||
// Size is the number of entities to hold in the cache. It must be greater
|
// Count is the number of entities to hold in the cache. It must be
|
||||||
// than zero.
|
// positive.
|
||||||
Size int
|
Count int
|
||||||
|
|
||||||
// MinTTL is the minimum supported TTL for cache items.
|
// MinTTL is the minimum supported TTL for cache items.
|
||||||
MinTTL time.Duration
|
MinTTL time.Duration
|
||||||
@ -64,7 +64,7 @@ func NewMiddleware(c *MiddlewareConfig) (m *Middleware) {
|
|||||||
|
|
||||||
return &Middleware{
|
return &Middleware{
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
cache: gcache.New(c.Size).LRU().Build(),
|
cache: gcache.New(c.Count).LRU().Build(),
|
||||||
cacheMinTTL: c.MinTTL,
|
cacheMinTTL: c.MinTTL,
|
||||||
overrideTTL: c.OverrideTTL,
|
overrideTTL: c.OverrideTTL,
|
||||||
}
|
}
|
||||||
|
30
internal/dnsserver/cache/cache_test.go
vendored
30
internal/dnsserver/cache/cache_test.go
vendored
@ -19,8 +19,8 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
const (
|
const (
|
||||||
servFailMaxCacheTTL = 30
|
servFailMaxCacheTTL = 30
|
||||||
|
|
||||||
reqHostname = "example.com"
|
reqHost = "example.com"
|
||||||
reqCname = "cname.example.com"
|
reqCNAME = "cname.example.com"
|
||||||
reqNs1 = "ns1.example.com"
|
reqNs1 = "ns1.example.com"
|
||||||
reqNs2 = "ns2.example.com"
|
reqNs2 = "ns2.example.com"
|
||||||
|
|
||||||
@ -30,10 +30,10 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
reqAddr := netip.MustParseAddr("1.2.3.4")
|
reqAddr := netip.MustParseAddr("1.2.3.4")
|
||||||
testTTL := 60 * time.Second
|
testTTL := 60 * time.Second
|
||||||
|
|
||||||
aReq := dnsservertest.NewReq(reqHostname, dns.TypeA, dns.ClassINET)
|
aReq := dnsservertest.NewReq(reqHost, dns.TypeA, dns.ClassINET)
|
||||||
cnameReq := dnsservertest.NewReq(reqHostname, dns.TypeCNAME, dns.ClassINET)
|
cnameReq := dnsservertest.NewReq(reqHost, dns.TypeCNAME, dns.ClassINET)
|
||||||
cnameAns := dnsservertest.SectionAnswer{dnsservertest.NewCNAME(reqHostname, defaultTTL, reqCname)}
|
cnameAns := dnsservertest.SectionAnswer{dnsservertest.NewCNAME(reqHost, defaultTTL, reqCNAME)}
|
||||||
soaNs := dnsservertest.SectionNs{dnsservertest.NewSOA(reqHostname, defaultTTL, reqNs1, reqNs2)}
|
soaNs := dnsservertest.SectionNs{dnsservertest.NewSOA(reqHost, defaultTTL, reqNs1, reqNs2)}
|
||||||
|
|
||||||
const N = 5
|
const N = 5
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -46,7 +46,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}{{
|
}{{
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, defaultTTL, reqAddr),
|
dnsservertest.NewA(reqHost, defaultTTL, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "simple_a",
|
name: "simple_a",
|
||||||
wantNumReq: 1,
|
wantNumReq: 1,
|
||||||
@ -83,7 +83,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeNameError, aReq, dnsservertest.SectionNs{
|
resp: dnsservertest.NewResp(dns.RcodeNameError, aReq, dnsservertest.SectionNs{
|
||||||
dnsservertest.NewNS(reqHostname, defaultTTL, reqNs1),
|
dnsservertest.NewNS(reqHost, defaultTTL, reqNs1),
|
||||||
}),
|
}),
|
||||||
name: "non_authoritative_nxdomain",
|
name: "non_authoritative_nxdomain",
|
||||||
// TODO(ameshkov): Consider https://datatracker.ietf.org/doc/html/rfc2308#section-3.
|
// TODO(ameshkov): Consider https://datatracker.ietf.org/doc/html/rfc2308#section-3.
|
||||||
@ -107,7 +107,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: cnameReq,
|
req: cnameReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, cnameReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, cnameReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewCNAME(reqHostname, defaultTTL, reqCname),
|
dnsservertest.NewCNAME(reqHost, defaultTTL, reqCNAME),
|
||||||
}),
|
}),
|
||||||
name: "simple_cname_ans",
|
name: "simple_cname_ans",
|
||||||
wantNumReq: 1,
|
wantNumReq: 1,
|
||||||
@ -116,7 +116,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, 0, reqAddr),
|
dnsservertest.NewA(reqHost, 0, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "expired_one",
|
name: "expired_one",
|
||||||
wantNumReq: N,
|
wantNumReq: N,
|
||||||
@ -125,7 +125,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, 10, reqAddr),
|
dnsservertest.NewA(reqHost, 10, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "override_ttl_ok",
|
name: "override_ttl_ok",
|
||||||
wantNumReq: 1,
|
wantNumReq: 1,
|
||||||
@ -134,7 +134,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, 1000, reqAddr),
|
dnsservertest.NewA(reqHost, 1000, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "override_ttl_max",
|
name: "override_ttl_max",
|
||||||
wantNumReq: 1,
|
wantNumReq: 1,
|
||||||
@ -143,7 +143,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeSuccess, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, 0, reqAddr),
|
dnsservertest.NewA(reqHost, 0, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "override_ttl_zero",
|
name: "override_ttl_zero",
|
||||||
wantNumReq: N,
|
wantNumReq: N,
|
||||||
@ -152,7 +152,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
req: aReq,
|
req: aReq,
|
||||||
resp: dnsservertest.NewResp(dns.RcodeServerFailure, aReq, dnsservertest.SectionAnswer{
|
resp: dnsservertest.NewResp(dns.RcodeServerFailure, aReq, dnsservertest.SectionAnswer{
|
||||||
dnsservertest.NewA(reqHostname, servFailMaxCacheTTL, reqAddr),
|
dnsservertest.NewA(reqHost, servFailMaxCacheTTL, reqAddr),
|
||||||
}),
|
}),
|
||||||
name: "override_ttl_servfail",
|
name: "override_ttl_servfail",
|
||||||
wantNumReq: 1,
|
wantNumReq: 1,
|
||||||
@ -186,7 +186,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
withCache := dnsserver.WithMiddlewares(
|
withCache := dnsserver.WithMiddlewares(
|
||||||
handler,
|
handler,
|
||||||
cache.NewMiddleware(&cache.MiddlewareConfig{
|
cache.NewMiddleware(&cache.MiddlewareConfig{
|
||||||
Size: 100,
|
Count: 100,
|
||||||
MinTTL: minTTL,
|
MinTTL: minTTL,
|
||||||
OverrideTTL: tc.minTTL != nil,
|
OverrideTTL: tc.minTTL != nil,
|
||||||
}),
|
}),
|
||||||
|
@ -158,6 +158,14 @@ func RunLocalHTTPSServer(
|
|||||||
network = dnsserver.NetworkTCP
|
network = dnsserver.NetworkTCP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tlsConfigH3 *tls.Config
|
||||||
|
if tlsConfig != nil {
|
||||||
|
tlsConfigH3 = tlsConfig.Clone()
|
||||||
|
|
||||||
|
tlsConfig.NextProtos = dnsserver.NextProtoDoH
|
||||||
|
tlsConfigH3.NextProtos = dnsserver.NextProtoDoH3
|
||||||
|
}
|
||||||
|
|
||||||
conf := dnsserver.ConfigHTTPS{
|
conf := dnsserver.ConfigHTTPS{
|
||||||
ConfigBase: dnsserver.ConfigBase{
|
ConfigBase: dnsserver.ConfigBase{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
@ -165,7 +173,8 @@ func RunLocalHTTPSServer(
|
|||||||
Handler: h,
|
Handler: h,
|
||||||
Network: network,
|
Network: network,
|
||||||
},
|
},
|
||||||
TLSConfig: tlsConfig,
|
TLSConfDefault: tlsConfig,
|
||||||
|
TLSConfH3: tlsConfigH3,
|
||||||
NonDNSHandler: nonDNSHandler,
|
NonDNSHandler: nonDNSHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,20 +38,30 @@ func CreateServerTLSConfig(tlsServerName string) (tlsConfig *tls.Config) {
|
|||||||
NotBefore: notBefore,
|
NotBefore: notBefore,
|
||||||
NotAfter: notAfter,
|
NotAfter: notAfter,
|
||||||
|
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature |
|
||||||
|
x509.KeyUsageCertSign,
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
}
|
}
|
||||||
template.DNSNames = append(template.DNSNames, tlsServerName)
|
template.DNSNames = append(template.DNSNames, tlsServerName)
|
||||||
|
|
||||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey)
|
derBytes, err := x509.CreateCertificate(
|
||||||
|
rand.Reader,
|
||||||
|
&template,
|
||||||
|
&template,
|
||||||
|
publicKey(privateKey),
|
||||||
|
privateKey,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("failed to create certificate: %v", err))
|
panic(fmt.Sprintf("failed to create certificate: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
keyPem := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
|
keyPem := pem.EncodeToMemory(&pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
||||||
|
})
|
||||||
|
|
||||||
cert, err := tls.X509KeyPair(certPem, keyPem)
|
cert, err := tls.X509KeyPair(certPem, keyPem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
||||||
|
|
||||||
go 1.23.2
|
go 1.23.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/golibs v0.30.1
|
github.com/AdguardTeam/golibs v0.30.4
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||||
github.com/ameshkov/dnsstamps v1.0.3
|
github.com/ameshkov/dnsstamps v1.0.3
|
||||||
github.com/bluele/gcache v0.0.2
|
github.com/bluele/gcache v0.0.2
|
||||||
@ -12,11 +12,11 @@ require (
|
|||||||
github.com/panjf2000/ants/v2 v2.10.0
|
github.com/panjf2000/ants/v2 v2.10.0
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||||
github.com/prometheus/client_golang v1.20.5
|
github.com/prometheus/client_golang v1.20.5
|
||||||
github.com/quic-go/quic-go v0.48.1
|
github.com/quic-go/quic-go v0.48.2
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.32.0
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.28.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -26,23 +26,23 @@ require (
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662 // indirect
|
github.com/google/pprof v0.0.0-20241203143554-1e3fdc7de467 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
|
github.com/onsi/ginkgo/v2 v2.22.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.60.0 // indirect
|
github.com/prometheus/common v0.60.1 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/crypto v0.28.0 // indirect
|
golang.org/x/crypto v0.30.0 // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.8.0 // indirect
|
||||||
golang.org/x/tools v0.26.0 // indirect
|
golang.org/x/tools v0.28.0 // indirect
|
||||||
google.golang.org/protobuf v1.35.1 // indirect
|
google.golang.org/protobuf v1.35.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
github.com/AdguardTeam/golibs v0.30.1 h1:/yv7dq2h7WXw/jTDxkE3FP9zHerRT+i03PZRHJX4fPU=
|
github.com/AdguardTeam/golibs v0.30.4 h1:zfFX1v4hkOCz6BifkneiBW2PCwSK523kYNr+VwaFrIw=
|
||||||
github.com/AdguardTeam/golibs v0.30.1/go.mod h1:FkwcNQEJoGsgDGXcalrVa/4gWbE68KsmE2guXWtBQUE=
|
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
github.com/aead/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 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||||
@ -26,8 +25,7 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
|
|||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662 h1:SKMkD83p7FwUqKmBsPdLHF5dNyxq3jOWwu9w9UyH5vA=
|
github.com/google/pprof v0.0.0-20241203143554-1e3fdc7de467 h1:keEZFtbLJugfE0qHn+Ge1JCE71spzkchQobDf3mzS/4=
|
||||||
github.com/google/pprof v0.0.0-20241023014458-598669927662/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@ -38,10 +36,8 @@ github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
|||||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
|
||||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
|
||||||
github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8=
|
github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8=
|
||||||
github.com/panjf2000/ants/v2 v2.10.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
github.com/panjf2000/ants/v2 v2.10.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
||||||
@ -52,14 +48,12 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+
|
|||||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
|
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||||
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA=
|
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||||
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
@ -72,25 +66,16 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
|||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
|
||||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
func TestCacheMetricsListener_integration_cache(t *testing.T) {
|
func TestCacheMetricsListener_integration_cache(t *testing.T) {
|
||||||
cacheMiddleware := cache.NewMiddleware(&cache.MiddlewareConfig{
|
cacheMiddleware := cache.NewMiddleware(&cache.MiddlewareConfig{
|
||||||
MetricsListener: prometheus.NewCacheMetricsListener(testNamespace),
|
MetricsListener: prometheus.NewCacheMetricsListener(testNamespace),
|
||||||
Size: 100,
|
Count: 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
handlerWithMiddleware := dnsserver.WithMiddlewares(
|
handlerWithMiddleware := dnsserver.WithMiddlewares(
|
||||||
|
@ -61,7 +61,7 @@ func (p Protocol) ALPN() (alpn []string) {
|
|||||||
case ProtoDoQ:
|
case ProtoDoQ:
|
||||||
return []string{nextProtoDoQ}
|
return []string{nextProtoDoQ}
|
||||||
case ProtoDoH:
|
case ProtoDoH:
|
||||||
return slices.Clone(nextProtoDoH3)
|
return slices.Clone(NextProtoDoH3)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,15 @@ const (
|
|||||||
httpIdleTimeout = 120 * time.Second
|
httpIdleTimeout = 120 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// nextProtoDoH is a list of ALPN that we would add by default to the server's
|
// NextProtoDoH is a list of ALPN protocols added by default to the server's
|
||||||
// *tls.Config if no NextProto is specified there. Note, that with this order,
|
// *tls.Config if no NextProto is specified there. Note that with this order,
|
||||||
// we prioritize HTTP/2 over HTTP/1.1.
|
// HTTP/2 is prioritized over HTTP/1.1.
|
||||||
var nextProtoDoH = []string{http2.NextProtoTLS, "http/1.1"}
|
var NextProtoDoH = []string{http2.NextProtoTLS, "http/1.1"}
|
||||||
|
|
||||||
// nextProtoDoH3 is a list of ALPN that we should add by default to the server's
|
// NextProtoDoH3 is a list of ALPN protocols added by default to the server's
|
||||||
// *tls.Config if no NextProto is specified there and DoH3 is supposed to be
|
// *tls.Config if no NextProto is specified there and DoH3 is supposed to be
|
||||||
// used.
|
// used. Note that with this order, HTTP/2 is prioritized over HTTP/1.1.
|
||||||
var nextProtoDoH3 = []string{http3.NextProtoH3, http2.NextProtoTLS, "http/1.1"}
|
var NextProtoDoH3 = []string{http3.NextProtoH3, http2.NextProtoTLS, "http/1.1"}
|
||||||
|
|
||||||
// ConfigHTTPS is a struct that needs to be passed to NewServerHTTPS to
|
// ConfigHTTPS is a struct that needs to be passed to NewServerHTTPS to
|
||||||
// initialize a new ServerHTTPS instance. You can choose whether HTTP/3 is
|
// initialize a new ServerHTTPS instance. You can choose whether HTTP/3 is
|
||||||
@ -59,10 +59,14 @@ var nextProtoDoH3 = []string{http3.NextProtoH3, http2.NextProtoTLS, "http/1.1"}
|
|||||||
// will listen to both HTTP/2 and HTTP/3, but if you set it to NetworkTCP, the
|
// will listen to both HTTP/2 and HTTP/3, but if you set it to NetworkTCP, the
|
||||||
// server will only use HTTP/2 and NetworkUDP will mean HTTP/3 only.
|
// server will only use HTTP/2 and NetworkUDP will mean HTTP/3 only.
|
||||||
type ConfigHTTPS struct {
|
type ConfigHTTPS struct {
|
||||||
// TLSConfig is the TLS configuration for HTTPS. If not set and
|
// TLSConfDefault is the TLS configuration for HTTPS. If not set and
|
||||||
// [ConfigBase.Network] is set to NetworkTCP the server will listen to
|
// [ConfigBase.Network] is set to NetworkTCP the server will listen to plain
|
||||||
// plain HTTP.
|
// HTTP. If it is not nil, it must be set to [NextProtoDoH].
|
||||||
TLSConfig *tls.Config
|
TLSConfDefault *tls.Config
|
||||||
|
|
||||||
|
// TLSConfH3 is the TLS configuration for DoH3. If it is not nil, it must
|
||||||
|
// be set to [NextProtoDoH3].
|
||||||
|
TLSConfH3 *tls.Config
|
||||||
|
|
||||||
// NonDNSHandler handles requests with the path not equal to /dns-query.
|
// NonDNSHandler handles requests with the path not equal to /dns-query.
|
||||||
// If it is empty, the server will return 404 for requests like that.
|
// If it is empty, the server will return 404 for requests like that.
|
||||||
@ -306,7 +310,7 @@ func (s *ServerHTTPS) serveHTTPS(ctx context.Context, hs *http.Server, l net.Lis
|
|||||||
defer s.handlePanicAndExit(ctx)
|
defer s.handlePanicAndExit(ctx)
|
||||||
|
|
||||||
scheme := urlutil.SchemeHTTPS
|
scheme := urlutil.SchemeHTTPS
|
||||||
if s.conf.TLSConfig == nil {
|
if s.conf.TLSConfDefault == nil {
|
||||||
scheme = urlutil.SchemeHTTP
|
scheme = urlutil.SchemeHTTP
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,12 +520,9 @@ func (s *ServerHTTPS) listenTLS(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the TLS configuration of the server.
|
// Prepare the TLS configuration of the server.
|
||||||
tlsConf := s.conf.TLSConfig
|
tlsConf := s.conf.TLSConfDefault
|
||||||
if tlsConf == nil {
|
if tlsConf == nil {
|
||||||
return nil
|
return nil
|
||||||
} else if len(tlsConf.NextProtos) == 0 {
|
|
||||||
tlsConf = tlsConf.Clone()
|
|
||||||
tlsConf.NextProtos = nextProtoDoH
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tcpListener = tls.NewListener(s.tcpListener, tlsConf)
|
s.tcpListener = tls.NewListener(s.tcpListener, tlsConf)
|
||||||
@ -532,11 +533,7 @@ func (s *ServerHTTPS) listenTLS(ctx context.Context) (err error) {
|
|||||||
// listenQUIC starts a QUIC listener that will be used to serve HTTP/3 requests.
|
// listenQUIC starts a QUIC listener that will be used to serve HTTP/3 requests.
|
||||||
func (s *ServerHTTPS) listenQUIC(ctx context.Context) (err error) {
|
func (s *ServerHTTPS) listenQUIC(ctx context.Context) (err error) {
|
||||||
// Prepare the TLS configuration of the server.
|
// Prepare the TLS configuration of the server.
|
||||||
tlsConf := s.conf.TLSConfig
|
tlsConf := s.conf.TLSConfH3
|
||||||
if tlsConf != nil && len(tlsConf.NextProtos) == 0 {
|
|
||||||
tlsConf = tlsConf.Clone()
|
|
||||||
tlsConf.NextProtos = nextProtoDoH3
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := s.listenConfig.ListenPacket(ctx, "udp", s.addr)
|
conn, err := s.listenConfig.ListenPacket(ctx, "udp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -307,7 +307,8 @@ func TestDNSMsgToJSONMsg(t *testing.T) {
|
|||||||
Type: dns.TypeHTTPS,
|
Type: dns.TypeHTTPS,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
TTL: 100,
|
TTL: 100,
|
||||||
Data: `0 example.com alpn="h2,h3" ech="AQI=" ipv4hint="127.0.0.1,127.0.0.2" ipv6hint="2000::,2001::"`,
|
Data: `0 example.com alpn="h2,h3" ech="AQI=" ipv4hint="127.0.0.1,127.0.0.2" ` +
|
||||||
|
`ipv6hint="2000::,2001::"`,
|
||||||
}}, jsonMsg.Answer)
|
}}, jsonMsg.Answer)
|
||||||
require.Equal(t, []dnsserver.JSONAnswer{{
|
require.Equal(t, []dnsserver.JSONAnswer{{
|
||||||
Name: "example.org",
|
Name: "example.org",
|
||||||
|
@ -62,10 +62,16 @@ const (
|
|||||||
// compatProtoDQ are ALPNs for backwards compatibility.
|
// compatProtoDQ are ALPNs for backwards compatibility.
|
||||||
var compatProtoDQ = []string{"doq-i00", "doq-i02", "doq-i03", "dq"}
|
var compatProtoDQ = []string{"doq-i00", "doq-i02", "doq-i03", "dq"}
|
||||||
|
|
||||||
|
// NextProtoDoQ is a list of ALPN protocols added by default to the server's
|
||||||
|
// *tls.Config if no NextProto is specified there and DoQ is supposed to be
|
||||||
|
// used.
|
||||||
|
var NextProtoDoQ = append([]string{nextProtoDoQ}, compatProtoDQ...)
|
||||||
|
|
||||||
// ConfigQUIC is a struct that needs to be passed to NewServerQUIC to
|
// ConfigQUIC is a struct that needs to be passed to NewServerQUIC to
|
||||||
// initialize a new ServerQUIC instance.
|
// initialize a new ServerQUIC instance.
|
||||||
type ConfigQUIC struct {
|
type ConfigQUIC struct {
|
||||||
// TLSConfig is the TLS configuration for QUIC.
|
// TLSConfig is the TLS configuration for QUIC. If it is not nil, it must
|
||||||
|
// be set to [NextProtoDoQ].
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
|
|
||||||
ConfigBase
|
ConfigBase
|
||||||
@ -111,12 +117,6 @@ const quicBytePoolSize = dns.MaxMsgSize
|
|||||||
|
|
||||||
// NewServerQUIC creates a new ServerQUIC instance.
|
// NewServerQUIC creates a new ServerQUIC instance.
|
||||||
func NewServerQUIC(conf ConfigQUIC) (s *ServerQUIC) {
|
func NewServerQUIC(conf ConfigQUIC) (s *ServerQUIC) {
|
||||||
// Make sure DOQ ALPNs are enabled in the TLS config.
|
|
||||||
tlsConfig := conf.TLSConfig
|
|
||||||
if len(tlsConfig.NextProtos) == 0 {
|
|
||||||
tlsConfig.NextProtos = append([]string{nextProtoDoQ}, compatProtoDQ...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.ListenConfig == nil {
|
if conf.ListenConfig == nil {
|
||||||
// Do not enable OOB here as quic-go will do that on its own.
|
// Do not enable OOB here as quic-go will do that on its own.
|
||||||
conf.ListenConfig = netext.DefaultListenConfig(nil)
|
conf.ListenConfig = netext.DefaultListenConfig(nil)
|
||||||
|
@ -107,6 +107,7 @@ func TestServerQUIC_integration_ENDS0Padding(t *testing.T) {
|
|||||||
|
|
||||||
func TestServerQUIC_integration_0RTT(t *testing.T) {
|
func TestServerQUIC_integration_0RTT(t *testing.T) {
|
||||||
tlsConfig := dnsservertest.CreateServerTLSConfig("example.org")
|
tlsConfig := dnsservertest.CreateServerTLSConfig("example.org")
|
||||||
|
tlsConfig.NextProtos = dnsserver.NextProtoDoQ
|
||||||
srv, addr, err := dnsservertest.RunLocalQUICServer(
|
srv, addr, err := dnsservertest.RunLocalQUICServer(
|
||||||
dnsservertest.NewDefaultHandler(),
|
dnsservertest.NewDefaultHandler(),
|
||||||
tlsConfig,
|
tlsConfig,
|
||||||
|
@ -347,14 +347,15 @@ func NewListener(
|
|||||||
case agd.ProtoDoH:
|
case agd.ProtoDoH:
|
||||||
l = dnsserver.NewServerHTTPS(dnsserver.ConfigHTTPS{
|
l = dnsserver.NewServerHTTPS(dnsserver.ConfigHTTPS{
|
||||||
ConfigBase: baseConf,
|
ConfigBase: baseConf,
|
||||||
TLSConfig: s.TLS,
|
TLSConfDefault: s.TLS.Default,
|
||||||
|
TLSConfH3: s.TLS.H3,
|
||||||
NonDNSHandler: nonDNS,
|
NonDNSHandler: nonDNS,
|
||||||
MaxStreamsPerPeer: quicConf.MaxStreamsPerPeer,
|
MaxStreamsPerPeer: quicConf.MaxStreamsPerPeer,
|
||||||
QUICLimitsEnabled: quicConf.QUICLimitsEnabled,
|
QUICLimitsEnabled: quicConf.QUICLimitsEnabled,
|
||||||
})
|
})
|
||||||
case agd.ProtoDoQ:
|
case agd.ProtoDoQ:
|
||||||
l = dnsserver.NewServerQUIC(dnsserver.ConfigQUIC{
|
l = dnsserver.NewServerQUIC(dnsserver.ConfigQUIC{
|
||||||
TLSConfig: s.TLS,
|
TLSConfig: s.TLS.Default,
|
||||||
ConfigBase: baseConf,
|
ConfigBase: baseConf,
|
||||||
MaxStreamsPerPeer: quicConf.MaxStreamsPerPeer,
|
MaxStreamsPerPeer: quicConf.MaxStreamsPerPeer,
|
||||||
QUICLimitsEnabled: quicConf.QUICLimitsEnabled,
|
QUICLimitsEnabled: quicConf.QUICLimitsEnabled,
|
||||||
@ -369,7 +370,7 @@ func NewListener(
|
|||||||
MaxPipelineCount: tcpConf.MaxPipelineCount,
|
MaxPipelineCount: tcpConf.MaxPipelineCount,
|
||||||
TCPIdleTimeout: tcpConf.IdleTimeout,
|
TCPIdleTimeout: tcpConf.IdleTimeout,
|
||||||
},
|
},
|
||||||
TLSConfig: s.TLS,
|
TLSConfig: s.TLS.Default,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("protocol: %w: %d", errors.ErrBadEnumValue, p)
|
return nil, fmt.Errorf("protocol: %w: %d", errors.ErrBadEnumValue, p)
|
||||||
|
@ -88,7 +88,7 @@ func wrapPreUpstreamMw(ctx context.Context, c *HandlersConfig) (wrapped dnsserve
|
|||||||
cacheMw := cache.NewMiddleware(&cache.MiddlewareConfig{
|
cacheMw := cache.NewMiddleware(&cache.MiddlewareConfig{
|
||||||
// TODO(a.garipov): Do not use promauto and refactor.
|
// TODO(a.garipov): Do not use promauto and refactor.
|
||||||
MetricsListener: dnssrvprom.NewCacheMetricsListener(metrics.Namespace()),
|
MetricsListener: dnssrvprom.NewCacheMetricsListener(metrics.Namespace()),
|
||||||
Size: conf.NoECSCount,
|
Count: conf.NoECSCount,
|
||||||
MinTTL: conf.MinTTL,
|
MinTTL: conf.MinTTL,
|
||||||
OverrideTTL: conf.OverrideCacheTTL,
|
OverrideTTL: conf.OverrideCacheTTL,
|
||||||
})
|
})
|
||||||
@ -146,7 +146,10 @@ func newMainMiddlewareMetrics(c *HandlersConfig) (mainMwMtrc MainMiddlewareMetri
|
|||||||
// newHandlersForServers returns a handler map for each server group and each
|
// newHandlersForServers returns a handler map for each server group and each
|
||||||
// server.
|
// server.
|
||||||
func newHandlersForServers(c *HandlersConfig, h dnsserver.Handler) (handlers Handlers, err error) {
|
func newHandlersForServers(c *HandlersConfig, h dnsserver.Handler) (handlers Handlers, err error) {
|
||||||
rlMwMtrc, err := metrics.NewDefaultRatelimitMiddleware(c.MetricsNamespace, c.PrometheusRegisterer)
|
rlMwMtrc, err := metrics.NewDefaultRatelimitMiddleware(
|
||||||
|
c.MetricsNamespace,
|
||||||
|
c.PrometheusRegisterer,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ratelimit middleware metrics: %w", err)
|
return nil, fmt.Errorf("ratelimit middleware metrics: %w", err)
|
||||||
}
|
}
|
||||||
@ -206,6 +209,6 @@ func newDeviceFinder(c *HandlersConfig, g *agd.ServerGroup, s *agd.Server) (df a
|
|||||||
ProfileDB: c.ProfileDB,
|
ProfileDB: c.ProfileDB,
|
||||||
HumanIDParser: c.HumanIDParser,
|
HumanIDParser: c.HumanIDParser,
|
||||||
Server: s,
|
Server: s,
|
||||||
DeviceDomains: g.TLS.DeviceDomains,
|
DeviceDomains: g.DeviceDomains,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -60,19 +60,27 @@ func TestNewHandlers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fltGrps := map[agd.FilteringGroupID]*agd.FilteringGroup{
|
fltGrp := &agd.FilteringGroup{
|
||||||
dnssvctest.FilteringGroupID: {
|
FilterConfig: &filter.ConfigGroup{
|
||||||
ID: dnssvctest.FilteringGroupID,
|
Parental: &filter.ConfigParental{},
|
||||||
RuleListIDs: []agd.FilterListID{dnssvctest.FilterListID1},
|
RuleList: &filter.ConfigRuleList{
|
||||||
RuleListsEnabled: true,
|
IDs: []filter.ID{dnssvctest.FilterListID1},
|
||||||
|
Enabled: true,
|
||||||
},
|
},
|
||||||
|
SafeBrowsing: &filter.ConfigSafeBrowsing{},
|
||||||
|
},
|
||||||
|
ID: dnssvctest.FilteringGroupID,
|
||||||
|
}
|
||||||
|
|
||||||
|
fltGrps := map[agd.FilteringGroupID]*agd.FilteringGroup{
|
||||||
|
dnssvctest.FilteringGroupID: fltGrp,
|
||||||
}
|
}
|
||||||
|
|
||||||
fltStrg := &agdtest.FilterStorage{
|
fltStrg := &agdtest.FilterStorage{
|
||||||
OnFilterFromContext: func(_ context.Context, _ *agd.RequestInfo) (f filter.Interface) {
|
OnForConfig: func(_ context.Context, _ filter.Config) (f filter.Interface) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
},
|
},
|
||||||
OnHasListID: func(_ agd.FilterListID) (ok bool) { panic("not implemented") },
|
OnHasListID: func(_ filter.ID) (ok bool) { panic("not implemented") },
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMatcher := &agdtest.HashMatcher{
|
hashMatcher := &agdtest.HashMatcher{
|
||||||
@ -91,7 +99,7 @@ func TestNewHandlers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ruleStat := &agdtest.RuleStat{
|
ruleStat := &agdtest.RuleStat{
|
||||||
OnCollect: func(_ context.Context, _ agd.FilterListID, _ agd.FilterRuleText) {
|
OnCollect: func(_ context.Context, _ filter.ID, _ filter.RuleText) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -104,7 +112,6 @@ func TestNewHandlers(t *testing.T) {
|
|||||||
DDR: &agd.DDR{
|
DDR: &agd.DDR{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
TLS: &agd.TLS{},
|
|
||||||
Name: dnssvctest.ServerGroupName,
|
Name: dnssvctest.ServerGroupName,
|
||||||
FilteringGroup: dnssvctest.FilteringGroupID,
|
FilteringGroup: dnssvctest.FilteringGroupID,
|
||||||
Servers: []*agd.Server{srv},
|
Servers: []*agd.Server{srv},
|
||||||
|
@ -57,7 +57,7 @@ func newTestService(
|
|||||||
querylogCh chan<- *querylog.Entry,
|
querylogCh chan<- *querylog.Entry,
|
||||||
geoIPCh chan<- string,
|
geoIPCh chan<- string,
|
||||||
dnsDBCh chan<- *agd.RequestInfo,
|
dnsDBCh chan<- *agd.RequestInfo,
|
||||||
ruleStatCh chan<- agd.FilterRuleText,
|
ruleStatCh chan<- filter.RuleText,
|
||||||
) (svc *dnssvc.Service, srvAddr netip.AddrPort) {
|
) (svc *dnssvc.Service, srvAddr netip.AddrPort) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
@ -73,11 +73,19 @@ func newTestService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
prof := &agd.Profile{
|
prof := &agd.Profile{
|
||||||
|
FilterConfig: &filter.ConfigClient{
|
||||||
|
Custom: &filter.ConfigCustom{},
|
||||||
|
Parental: &filter.ConfigParental{},
|
||||||
|
RuleList: &filter.ConfigRuleList{
|
||||||
|
IDs: []filter.ID{dnssvctest.FilterListID1},
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
SafeBrowsing: &filter.ConfigSafeBrowsing{},
|
||||||
|
},
|
||||||
Access: access.EmptyProfile{},
|
Access: access.EmptyProfile{},
|
||||||
BlockingMode: &dnsmsg.BlockingModeNullIP{},
|
BlockingMode: &dnsmsg.BlockingModeNullIP{},
|
||||||
ID: dnssvctest.ProfileID,
|
ID: dnssvctest.ProfileID,
|
||||||
DeviceIDs: []agd.DeviceID{dnssvctest.DeviceID},
|
DeviceIDs: []agd.DeviceID{dnssvctest.DeviceID},
|
||||||
RuleListIDs: []agd.FilterListID{dnssvctest.FilterListID1},
|
|
||||||
FilteredResponseTTL: agdtest.FilteredResponseTTL,
|
FilteredResponseTTL: agdtest.FilteredResponseTTL,
|
||||||
FilteringEnabled: true,
|
FilteringEnabled: true,
|
||||||
QueryLogEnabled: true,
|
QueryLogEnabled: true,
|
||||||
@ -124,10 +132,10 @@ func newTestService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fltStrg := &agdtest.FilterStorage{
|
fltStrg := &agdtest.FilterStorage{
|
||||||
OnFilterFromContext: func(_ context.Context, _ *agd.RequestInfo) (f filter.Interface) {
|
OnForConfig: func(_ context.Context, _ filter.Config) (f filter.Interface) {
|
||||||
return flt
|
return flt
|
||||||
},
|
},
|
||||||
OnHasListID: func(_ agd.FilterListID) (ok bool) { panic("not implemented") },
|
OnHasListID: func(_ filter.ID) (ok bool) { panic("not implemented") },
|
||||||
}
|
}
|
||||||
|
|
||||||
var ql querylog.Interface = &agdtest.QueryLog{
|
var ql querylog.Interface = &agdtest.QueryLog{
|
||||||
@ -164,7 +172,7 @@ func newTestService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ruleStat := &agdtest.RuleStat{
|
ruleStat := &agdtest.RuleStat{
|
||||||
OnCollect: func(_ context.Context, _ agd.FilterListID, text agd.FilterRuleText) {
|
OnCollect: func(_ context.Context, _ filter.ID, text filter.RuleText) {
|
||||||
testutil.RequireSend(pt, ruleStatCh, text, dnssvctest.Timeout)
|
testutil.RequireSend(pt, ruleStatCh, text, dnssvctest.Timeout)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -182,15 +190,25 @@ func newTestService(
|
|||||||
DDR: &agd.DDR{
|
DDR: &agd.DDR{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
TLS: &agd.TLS{
|
|
||||||
DeviceDomains: []string{dnssvctest.DomainForDevices},
|
DeviceDomains: []string{dnssvctest.DomainForDevices},
|
||||||
},
|
|
||||||
Name: dnssvctest.ServerGroupName,
|
Name: dnssvctest.ServerGroupName,
|
||||||
FilteringGroup: dnssvctest.FilteringGroupID,
|
FilteringGroup: dnssvctest.FilteringGroupID,
|
||||||
Servers: []*agd.Server{srv},
|
Servers: []*agd.Server{srv},
|
||||||
ProfilesEnabled: true,
|
ProfilesEnabled: true,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
fltGrp := &agd.FilteringGroup{
|
||||||
|
FilterConfig: &filter.ConfigGroup{
|
||||||
|
Parental: &filter.ConfigParental{},
|
||||||
|
RuleList: &filter.ConfigRuleList{
|
||||||
|
IDs: []filter.ID{dnssvctest.FilterListID1},
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
SafeBrowsing: &filter.ConfigSafeBrowsing{},
|
||||||
|
},
|
||||||
|
ID: dnssvctest.FilteringGroupID,
|
||||||
|
}
|
||||||
|
|
||||||
hdlrConf := &dnssvc.HandlersConfig{
|
hdlrConf := &dnssvc.HandlersConfig{
|
||||||
BaseLogger: slogutil.NewDiscardLogger(),
|
BaseLogger: slogutil.NewDiscardLogger(),
|
||||||
Cache: &dnssvc.CacheConfig{
|
Cache: &dnssvc.CacheConfig{
|
||||||
@ -227,11 +245,7 @@ func newTestService(
|
|||||||
RuleStat: ruleStat,
|
RuleStat: ruleStat,
|
||||||
MetricsNamespace: path.Base(t.Name()),
|
MetricsNamespace: path.Base(t.Name()),
|
||||||
FilteringGroups: map[agd.FilteringGroupID]*agd.FilteringGroup{
|
FilteringGroups: map[agd.FilteringGroupID]*agd.FilteringGroup{
|
||||||
dnssvctest.FilteringGroupID: {
|
dnssvctest.FilteringGroupID: fltGrp,
|
||||||
ID: dnssvctest.FilteringGroupID,
|
|
||||||
RuleListIDs: []agd.FilterListID{dnssvctest.FilterListID1},
|
|
||||||
RuleListsEnabled: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ServerGroups: srvGrps,
|
ServerGroups: srvGrps,
|
||||||
EDEEnabled: true,
|
EDEEnabled: true,
|
||||||
@ -271,7 +285,7 @@ func TestService_Wrap(t *testing.T) {
|
|||||||
querylogCh := make(chan *querylog.Entry, 1)
|
querylogCh := make(chan *querylog.Entry, 1)
|
||||||
geoIPCh := make(chan string, 2)
|
geoIPCh := make(chan string, 2)
|
||||||
dnsDBCh := make(chan *agd.RequestInfo, 1)
|
dnsDBCh := make(chan *agd.RequestInfo, 1)
|
||||||
ruleStatCh := make(chan agd.FilterRuleText, 1)
|
ruleStatCh := make(chan filter.RuleText, 1)
|
||||||
|
|
||||||
errCollCh := make(chan error, 1)
|
errCollCh := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -291,21 +305,27 @@ func TestService_Wrap(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("simple_success", func(t *testing.T) {
|
t.Run("simple_success", func(t *testing.T) {
|
||||||
noMatch := func(
|
flt := &agdtest.Filter{
|
||||||
|
OnFilterRequest: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
m *dns.Msg,
|
fltReq *filter.Request,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
pt := testutil.PanicT{}
|
pt := testutil.PanicT{}
|
||||||
require.NotEmpty(pt, m.Question)
|
require.NotEmpty(pt, fltReq.DNS.Question)
|
||||||
require.Equal(pt, dnssvctest.DomainFQDN, m.Question[0].Name)
|
require.Equal(pt, dnssvctest.DomainFQDN, fltReq.DNS.Question[0].Name)
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
},
|
||||||
|
OnFilterResponse: func(
|
||||||
|
_ context.Context,
|
||||||
|
fltResp *filter.Response,
|
||||||
|
) (r filter.Result, err error) {
|
||||||
|
pt := testutil.PanicT{}
|
||||||
|
require.NotEmpty(pt, fltResp.DNS.Question)
|
||||||
|
require.Equal(pt, dnssvctest.DomainFQDN, fltResp.DNS.Question[0].Name)
|
||||||
|
|
||||||
flt := &agdtest.Filter{
|
return nil, nil
|
||||||
OnFilterRequest: noMatch,
|
},
|
||||||
OnFilterResponse: noMatch,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svc, srvAddr := newTestService(
|
svc, srvAddr := newTestService(
|
||||||
@ -346,13 +366,13 @@ func TestService_Wrap(t *testing.T) {
|
|||||||
|
|
||||||
dnsDBReqInfo := <-dnsDBCh
|
dnsDBReqInfo := <-dnsDBCh
|
||||||
assert.NotNil(t, dnsDBReqInfo)
|
assert.NotNil(t, dnsDBReqInfo)
|
||||||
assert.Equal(t, agd.FilterRuleText(""), <-ruleStatCh)
|
assert.Equal(t, filter.RuleText(""), <-ruleStatCh)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("request_cname", func(t *testing.T) {
|
t.Run("request_cname", func(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
cname = "cname.example.org"
|
cname = "cname.example.org"
|
||||||
cnameRule agd.FilterRuleText = "||" + dnssvctest.Domain + "^$dnsrewrite=" + cname
|
cnameRule filter.RuleText = "||" + dnssvctest.Domain + "^$dnsrewrite=" + cname
|
||||||
)
|
)
|
||||||
|
|
||||||
cnameFQDN := dns.Fqdn(cname)
|
cnameFQDN := dns.Fqdn(cname)
|
||||||
@ -360,11 +380,10 @@ func TestService_Wrap(t *testing.T) {
|
|||||||
flt := &agdtest.Filter{
|
flt := &agdtest.Filter{
|
||||||
OnFilterRequest: func(
|
OnFilterRequest: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
m *dns.Msg,
|
fltReq *filter.Request,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
// Pretend a CNAME rewrite matched the request.
|
// Pretend a CNAME rewrite matched the request.
|
||||||
mod := dnsmsg.Clone(m)
|
mod := dnsmsg.Clone(fltReq.DNS)
|
||||||
mod.Question[0].Name = cnameFQDN
|
mod.Question[0].Name = cnameFQDN
|
||||||
|
|
||||||
return &filter.ResultModifiedRequest{
|
return &filter.ResultModifiedRequest{
|
||||||
@ -373,11 +392,7 @@ func TestService_Wrap(t *testing.T) {
|
|||||||
Rule: cnameRule,
|
Rule: cnameRule,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
OnFilterResponse: func(
|
OnFilterResponse: func(_ context.Context, _ *filter.Response) (filter.Result, error) {
|
||||||
_ context.Context,
|
|
||||||
_ *dns.Msg,
|
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (filter.Result, error) {
|
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,8 @@ func TestDefault_Find_byHumanID(t *testing.T) {
|
|||||||
|
|
||||||
// Use uppercase versions to make sure that the device finder recognizes the
|
// Use uppercase versions to make sure that the device finder recognizes the
|
||||||
// device-type and profile data regardless of the case.
|
// device-type and profile data regardless of the case.
|
||||||
extIDStr := "OTR-" + strings.ToUpper(dnssvctest.ProfileIDStr) + "-" + dnssvctest.HumanIDStr + "-!!!"
|
extIDStr := "OTR-" + strings.ToUpper(dnssvctest.ProfileIDStr) + "-" +
|
||||||
|
dnssvctest.HumanIDStr + "-!!!"
|
||||||
|
|
||||||
profDB := agdtest.NewProfileDB()
|
profDB := agdtest.NewProfileDB()
|
||||||
profDB.OnCreateAutoDevice = func(
|
profDB.OnCreateAutoDevice = func(
|
||||||
|
@ -408,7 +408,12 @@ func BenchmarkDefault(b *testing.B) {
|
|||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for range b.N {
|
for range b.N {
|
||||||
sinkDevResult = df.Find(ctx, bc.req, dnssvctest.ClientAddrPort, dnssvctest.ServerAddrPort)
|
sinkDevResult = df.Find(
|
||||||
|
ctx,
|
||||||
|
bc.req,
|
||||||
|
dnssvctest.ClientAddrPort,
|
||||||
|
dnssvctest.ServerAddrPort,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = testutil.RequireTypeAssert[*agd.DeviceResultOK](b, sinkDevResult)
|
_ = testutil.RequireTypeAssert[*agd.DeviceResultOK](b, sinkDevResult)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,8 +37,8 @@ const (
|
|||||||
|
|
||||||
// Common filtering-rule list ID for tests.
|
// Common filtering-rule list ID for tests.
|
||||||
const (
|
const (
|
||||||
FilterListID1 agd.FilterListID = FilterListID1Str
|
FilterListID1 filter.ID = FilterListID1Str
|
||||||
FilterListID2 agd.FilterListID = FilterListID2Str
|
FilterListID2 filter.ID = FilterListID2Str
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common domains and FQDNs for tests.
|
// Common domains and FQDNs for tests.
|
||||||
@ -144,7 +145,9 @@ func NewServer(
|
|||||||
|
|
||||||
if proto.IsStdEncrypted() {
|
if proto.IsStdEncrypted() {
|
||||||
// #nosec G402 -- This is a test helper.
|
// #nosec G402 -- This is a test helper.
|
||||||
srv.TLS = &tls.Config{}
|
srv.TLS = &agd.TLSConfig{
|
||||||
|
Default: &tls.Config{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch proto {
|
switch proto {
|
||||||
|
@ -29,6 +29,12 @@ const (
|
|||||||
// Resolvers for querying the resolver with unknown or absent name.
|
// Resolvers for querying the resolver with unknown or absent name.
|
||||||
DDRDomain = DDRLabel + "." + ResolverARPADomain
|
DDRDomain = DDRLabel + "." + ResolverARPADomain
|
||||||
|
|
||||||
|
// ChromePrefetchHost is the hostname that Chrome uses to check if it should
|
||||||
|
// use the Chrome Private Prefetch Proxy feature.
|
||||||
|
//
|
||||||
|
// See https://developer.chrome.com/docs/privacy-security/private-prefetch-proxy-for-network-admins.
|
||||||
|
ChromePrefetchHost = "dns-tunnel-check.googlezip.net"
|
||||||
|
|
||||||
// FirefoxCanaryHost is the hostname that Firefox uses to check if it should
|
// FirefoxCanaryHost is the hostname that Firefox uses to check if it should
|
||||||
// use its own DNS-over-HTTPS settings.
|
// use its own DNS-over-HTTPS settings.
|
||||||
//
|
//
|
||||||
@ -251,6 +257,10 @@ func (mw *Middleware) specialDomainHandler(
|
|||||||
if shouldBlockPrivateRelay(ri, prof) {
|
if shouldBlockPrivateRelay(ri, prof) {
|
||||||
return mw.handlePrivateRelay, "apple_private_relay"
|
return mw.handlePrivateRelay, "apple_private_relay"
|
||||||
}
|
}
|
||||||
|
case ChromePrefetchHost:
|
||||||
|
if shouldBlockChromePrefetch(ri, prof) {
|
||||||
|
return mw.handleChromePrefetch, "chrome_prefetch"
|
||||||
|
}
|
||||||
case FirefoxCanaryHost:
|
case FirefoxCanaryHost:
|
||||||
if shouldBlockFirefoxCanary(ri, prof) {
|
if shouldBlockFirefoxCanary(ri, prof) {
|
||||||
return mw.handleFirefoxCanary, "firefox"
|
return mw.handleFirefoxCanary, "firefox"
|
||||||
@ -262,36 +272,34 @@ func (mw *Middleware) specialDomainHandler(
|
|||||||
return nil, ""
|
return nil, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldBlockPrivateRelay returns true if the query is for an Apple Private
|
// shouldBlockChromePrefetch returns true request information or profile
|
||||||
// Relay check domain and the request information or profile indicates that
|
// indicate that the Chrome prefetch domain should be blocked.
|
||||||
// Apple Private Relay should be blocked.
|
func shouldBlockChromePrefetch(ri *agd.RequestInfo, prof *agd.Profile) (ok bool) {
|
||||||
func shouldBlockPrivateRelay(ri *agd.RequestInfo, prof *agd.Profile) (ok bool) {
|
|
||||||
if prof != nil {
|
if prof != nil {
|
||||||
return prof.BlockPrivateRelay
|
return prof.BlockChromePrefetch
|
||||||
}
|
}
|
||||||
|
|
||||||
return ri.FilteringGroup.BlockPrivateRelay
|
return ri.FilteringGroup.BlockChromePrefetch
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePrivateRelay responds to Apple Private Relay queries with an NXDOMAIN
|
// handleChromePrefetch responds to Chrome prefetch domain queries with an
|
||||||
// response.
|
// NXDOMAIN response.
|
||||||
func (mw *Middleware) handlePrivateRelay(
|
func (mw *Middleware) handleChromePrefetch(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
rw dnsserver.ResponseWriter,
|
rw dnsserver.ResponseWriter,
|
||||||
req *dns.Msg,
|
req *dns.Msg,
|
||||||
ri *agd.RequestInfo,
|
ri *agd.RequestInfo,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
metrics.DNSSvcApplePrivateRelayRequestsTotal.Inc()
|
metrics.DNSSvcChromePrefetchRequestsTotal.Inc()
|
||||||
|
|
||||||
resp := ri.Messages.NewRespRCode(req, dns.RcodeNameError)
|
resp := ri.Messages.NewRespRCode(req, dns.RcodeNameError)
|
||||||
err = rw.WriteMsg(ctx, req, resp)
|
err = rw.WriteMsg(ctx, req, resp)
|
||||||
|
|
||||||
return errors.Annotate(err, "writing private relay resp: %w")
|
return errors.Annotate(err, "writing chrome prefetch resp: %w")
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldBlockFirefoxCanary returns true if the query is for a Firefox canary
|
// shouldBlockFirefoxCanary returns true request information or profile indicate
|
||||||
// domain and the request information or profile indicates that Firefox canary
|
// that the Firefox canary domain should be blocked.
|
||||||
// domain should be blocked.
|
|
||||||
func shouldBlockFirefoxCanary(ri *agd.RequestInfo, prof *agd.Profile) (ok bool) {
|
func shouldBlockFirefoxCanary(ri *agd.RequestInfo, prof *agd.Profile) (ok bool) {
|
||||||
if prof != nil {
|
if prof != nil {
|
||||||
return prof.BlockFirefoxCanary
|
return prof.BlockFirefoxCanary
|
||||||
@ -315,3 +323,29 @@ func (mw *Middleware) handleFirefoxCanary(
|
|||||||
|
|
||||||
return errors.Annotate(err, "writing firefox canary resp: %w")
|
return errors.Annotate(err, "writing firefox canary resp: %w")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldBlockPrivateRelay returns true request information or profile indicate
|
||||||
|
// that the Apple Private Relay domain should be blocked.
|
||||||
|
func shouldBlockPrivateRelay(ri *agd.RequestInfo, prof *agd.Profile) (ok bool) {
|
||||||
|
if prof != nil {
|
||||||
|
return prof.BlockPrivateRelay
|
||||||
|
}
|
||||||
|
|
||||||
|
return ri.FilteringGroup.BlockPrivateRelay
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePrivateRelay responds to Apple Private Relay queries with an NXDOMAIN
|
||||||
|
// response.
|
||||||
|
func (mw *Middleware) handlePrivateRelay(
|
||||||
|
ctx context.Context,
|
||||||
|
rw dnsserver.ResponseWriter,
|
||||||
|
req *dns.Msg,
|
||||||
|
ri *agd.RequestInfo,
|
||||||
|
) (err error) {
|
||||||
|
metrics.DNSSvcApplePrivateRelayRequestsTotal.Inc()
|
||||||
|
|
||||||
|
resp := ri.Messages.NewRespRCode(req, dns.RcodeNameError)
|
||||||
|
err = rw.WriteMsg(ctx, req, resp)
|
||||||
|
|
||||||
|
return errors.Annotate(err, "writing private relay resp: %w")
|
||||||
|
}
|
||||||
|
@ -24,31 +24,36 @@ func TestMiddleware_Wrap_specialDomain(t *testing.T) {
|
|||||||
var (
|
var (
|
||||||
profAllowed = &agd.Profile{
|
profAllowed = &agd.Profile{
|
||||||
Access: access.EmptyProfile{},
|
Access: access.EmptyProfile{},
|
||||||
BlockPrivateRelay: false,
|
BlockChromePrefetch: false,
|
||||||
BlockFirefoxCanary: false,
|
BlockFirefoxCanary: false,
|
||||||
|
BlockPrivateRelay: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
profBlocked = &agd.Profile{
|
profBlocked = &agd.Profile{
|
||||||
Access: access.EmptyProfile{},
|
Access: access.EmptyProfile{},
|
||||||
BlockPrivateRelay: true,
|
BlockChromePrefetch: true,
|
||||||
BlockFirefoxCanary: true,
|
BlockFirefoxCanary: true,
|
||||||
|
BlockPrivateRelay: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fltGrpAllowed = &agd.FilteringGroup{
|
fltGrpAllowed = &agd.FilteringGroup{
|
||||||
BlockPrivateRelay: false,
|
BlockChromePrefetch: false,
|
||||||
BlockFirefoxCanary: false,
|
BlockFirefoxCanary: false,
|
||||||
|
BlockPrivateRelay: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
fltGrpBlocked = &agd.FilteringGroup{
|
fltGrpBlocked = &agd.FilteringGroup{
|
||||||
BlockPrivateRelay: true,
|
BlockChromePrefetch: true,
|
||||||
BlockFirefoxCanary: true,
|
BlockFirefoxCanary: true,
|
||||||
|
BlockPrivateRelay: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
appleHost = initial.ApplePrivateRelayMaskHost
|
appleHost = initial.ApplePrivateRelayMaskHost
|
||||||
|
chromeHost = initial.ChromePrefetchHost
|
||||||
firefoxHost = initial.FirefoxCanaryHost
|
firefoxHost = initial.FirefoxCanaryHost
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -100,29 +105,27 @@ func TestMiddleware_Wrap_specialDomain(t *testing.T) {
|
|||||||
reqInfo: newSpecDomReqInfo(t, nil, fltGrpBlocked, firefoxHost, dns.TypeA),
|
reqInfo: newSpecDomReqInfo(t, nil, fltGrpBlocked, firefoxHost, dns.TypeA),
|
||||||
name: "firefox_canary_blocked_by_fltgrp",
|
name: "firefox_canary_blocked_by_fltgrp",
|
||||||
wantRCode: dns.RcodeRefused,
|
wantRCode: dns.RcodeRefused,
|
||||||
|
}, {
|
||||||
|
reqInfo: newSpecDomReqInfo(t, profAllowed, fltGrpAllowed, chromeHost, dns.TypeA),
|
||||||
|
name: "chrome_prefetch_allowed_by_both",
|
||||||
|
wantRCode: dns.RcodeSuccess,
|
||||||
|
}, {
|
||||||
|
reqInfo: newSpecDomReqInfo(t, profBlocked, fltGrpAllowed, chromeHost, dns.TypeA),
|
||||||
|
name: "chrome_prefetch_blocked_by_prof",
|
||||||
|
wantRCode: dns.RcodeNameError,
|
||||||
|
}, {
|
||||||
|
reqInfo: newSpecDomReqInfo(t, nil, fltGrpBlocked, chromeHost, dns.TypeA),
|
||||||
|
name: "chrome_prefetch_blocked_by_fltgrp",
|
||||||
|
wantRCode: dns.RcodeNameError,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var handler dnsserver.Handler = dnsserver.HandlerFunc(func(
|
|
||||||
ctx context.Context,
|
|
||||||
rw dnsserver.ResponseWriter,
|
|
||||||
req *dns.Msg,
|
|
||||||
) (err error) {
|
|
||||||
if tc.wantRCode != dns.RcodeSuccess {
|
|
||||||
return errors.Error("unexpectedly reached handler")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := (&dns.Msg{}).SetReply(req)
|
|
||||||
|
|
||||||
return rw.WriteMsg(ctx, req, resp)
|
|
||||||
})
|
|
||||||
|
|
||||||
mw := initial.New(&initial.Config{
|
mw := initial.New(&initial.Config{
|
||||||
Logger: slogutil.NewDiscardLogger(),
|
Logger: slogutil.NewDiscardLogger(),
|
||||||
})
|
})
|
||||||
|
|
||||||
h := mw.Wrap(handler)
|
h := mw.Wrap(newSpecDomHandler(tc.wantRCode == dns.RcodeSuccess))
|
||||||
|
|
||||||
ctx := testutil.ContextWithTimeout(t, dnssvctest.Timeout)
|
ctx := testutil.ContextWithTimeout(t, dnssvctest.Timeout)
|
||||||
ctx = agd.ContextWithRequestInfo(ctx, tc.reqInfo)
|
ctx = agd.ContextWithRequestInfo(ctx, tc.reqInfo)
|
||||||
@ -185,3 +188,21 @@ func newSpecDomReqInfo(
|
|||||||
|
|
||||||
return ri
|
return ri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newSpecDomHandler is a helper that creates a DNS handler for the
|
||||||
|
// special-domain tests. The handler returns an error if wantReach is false.
|
||||||
|
func newSpecDomHandler(wantReach bool) (h dnsserver.Handler) {
|
||||||
|
return dnsserver.HandlerFunc(func(
|
||||||
|
ctx context.Context,
|
||||||
|
rw dnsserver.ResponseWriter,
|
||||||
|
req *dns.Msg,
|
||||||
|
) (err error) {
|
||||||
|
if !wantReach {
|
||||||
|
return errors.Error("unexpectedly reached handler")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := (&dns.Msg{}).SetReply(req)
|
||||||
|
|
||||||
|
return rw.WriteMsg(ctx, req, resp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -221,7 +221,10 @@ func TestMiddleware_writeDebugResponse(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
rw := dnsserver.NewNonWriterResponseWriter(dnssvctest.ServerTCPAddr, dnssvctest.ClientTCPAddr)
|
rw := dnsserver.NewNonWriterResponseWriter(
|
||||||
|
dnssvctest.ServerTCPAddr,
|
||||||
|
dnssvctest.ClientTCPAddr,
|
||||||
|
)
|
||||||
|
|
||||||
ctx := agd.ContextWithRequestInfo(context.Background(), tc.reqInfo)
|
ctx := agd.ContextWithRequestInfo(context.Background(), tc.reqInfo)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
@ -57,9 +58,12 @@ func (mw *Middleware) filterRequest(
|
|||||||
) {
|
) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
reqRes, err := f.FilterRequest(ctx, fctx.originalRequest, ri)
|
fltReq := mw.reqInfoToFltReq(fctx.originalRequest, ri)
|
||||||
|
defer mw.putFltReq(fltReq)
|
||||||
|
|
||||||
|
reqRes, err := f.FilterRequest(ctx, fltReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.reportf(ctx, "filtering request: %w", err)
|
errcoll.Collect(ctx, mw.errColl, mw.logger, "filtering request", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if mod, ok := reqRes.(*filter.ResultModifiedRequest); ok {
|
if mod, ok := reqRes.(*filter.ResultModifiedRequest); ok {
|
||||||
@ -70,6 +74,38 @@ func (mw *Middleware) filterRequest(
|
|||||||
fctx.elapsed += time.Since(start)
|
fctx.elapsed += time.Since(start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reqInfoToFltReq converts data from a DNS request and request info into a
|
||||||
|
// *filter.Request. The returned request data should be put back into the pool
|
||||||
|
// by using [Middleware.putFltReq].
|
||||||
|
func (mw *Middleware) reqInfoToFltReq(req *dns.Msg, ri *agd.RequestInfo) (fltReq *filter.Request) {
|
||||||
|
fltReq = mw.fltReqPool.Get()
|
||||||
|
|
||||||
|
// NOTE: Fill all fields of fltReq since it is reused from the pool.
|
||||||
|
fltReq.DNS = req
|
||||||
|
fltReq.Messages = ri.Messages
|
||||||
|
fltReq.RemoteIP = ri.RemoteIP
|
||||||
|
|
||||||
|
if _, d := ri.DeviceData(); d != nil {
|
||||||
|
fltReq.ClientName = string(d.Name)
|
||||||
|
} else {
|
||||||
|
fltReq.ClientName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fltReq.Host = ri.Host
|
||||||
|
fltReq.QType = ri.QType
|
||||||
|
fltReq.QClass = ri.QClass
|
||||||
|
|
||||||
|
return fltReq
|
||||||
|
}
|
||||||
|
|
||||||
|
// putFltReq sets req.DNS to nil, to prevent the message being contained in the
|
||||||
|
// pool, which can lead to conflicts with the cloner of the middleware, and puts
|
||||||
|
// req back into the pool.
|
||||||
|
func (mw *Middleware) putFltReq(req *filter.Request) {
|
||||||
|
req.DNS = nil
|
||||||
|
mw.fltReqPool.Put(req)
|
||||||
|
}
|
||||||
|
|
||||||
// filterResponse applies f to resp and sets the result of filtering in fctx.
|
// filterResponse applies f to resp and sets the result of filtering in fctx.
|
||||||
// If origReq has a different question name than resp, the request assumed being
|
// If origReq has a different question name than resp, the request assumed being
|
||||||
// CNAME-rewritten and no filtering performed on resp, the CNAME is prepended to
|
// CNAME-rewritten and no filtering performed on resp, the CNAME is prepended to
|
||||||
@ -95,9 +131,12 @@ func (mw *Middleware) filterResponse(
|
|||||||
var rr dns.RR = ri.Messages.NewAnswerCNAME(origReq, modReq.Question[0].Name)
|
var rr dns.RR = ri.Messages.NewAnswerCNAME(origReq, modReq.Question[0].Name)
|
||||||
origResp.Answer = slices.Insert(origResp.Answer, 0, rr)
|
origResp.Answer = slices.Insert(origResp.Answer, 0, rr)
|
||||||
} else {
|
} else {
|
||||||
respRes, err := f.FilterResponse(ctx, fctx.originalResponse, ri)
|
fltResp := mw.reqInfoToFltResp(fctx.originalResponse, ri)
|
||||||
|
defer mw.putFltResp(fltResp)
|
||||||
|
|
||||||
|
respRes, err := f.FilterResponse(ctx, fltResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.reportf(ctx, "filtering response: %w", err)
|
errcoll.Collect(ctx, mw.errColl, mw.logger, "filtering response", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fctx.responseResult = respRes
|
fctx.responseResult = respRes
|
||||||
@ -106,11 +145,41 @@ func (mw *Middleware) filterResponse(
|
|||||||
fctx.elapsed += time.Since(start)
|
fctx.elapsed += time.Since(start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reqInfoToFltResp converts data from a DNS response and request info into a
|
||||||
|
// *filter.Response. The returned response data should be put back into
|
||||||
|
// the pool by using [Middleware.putFltResp].
|
||||||
|
func (mw *Middleware) reqInfoToFltResp(
|
||||||
|
resp *dns.Msg,
|
||||||
|
ri *agd.RequestInfo,
|
||||||
|
) (fltResp *filter.Response) {
|
||||||
|
fltResp = mw.fltRespPool.Get()
|
||||||
|
|
||||||
|
// NOTE: Fill all fields of fltResp since it is reused from the pool.
|
||||||
|
fltResp.DNS = resp
|
||||||
|
fltResp.RemoteIP = ri.RemoteIP
|
||||||
|
|
||||||
|
if _, d := ri.DeviceData(); d != nil {
|
||||||
|
fltResp.ClientName = string(d.Name)
|
||||||
|
} else {
|
||||||
|
fltResp.ClientName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fltResp
|
||||||
|
}
|
||||||
|
|
||||||
|
// putFltResp sets resp.DNS to nil, to prevent the message being contained in
|
||||||
|
// the pool, which can lead to conflicts with the cloner of the middleware, and
|
||||||
|
// puts resp back into the pool.
|
||||||
|
func (mw *Middleware) putFltResp(resp *filter.Response) {
|
||||||
|
resp.DNS = nil
|
||||||
|
mw.fltRespPool.Put(resp)
|
||||||
|
}
|
||||||
|
|
||||||
// filteringData returns the data necessary for request information recording
|
// filteringData returns the data necessary for request information recording
|
||||||
// from the filtering context.
|
// from the filtering context.
|
||||||
func filteringData(
|
func filteringData(
|
||||||
fctx *filteringContext,
|
fctx *filteringContext,
|
||||||
) (id agd.FilterListID, text agd.FilterRuleText, blocked bool) {
|
) (id filter.ID, text filter.RuleText, blocked bool) {
|
||||||
if fctx.requestResult != nil {
|
if fctx.requestResult != nil {
|
||||||
return resultData(fctx.requestResult, "reqRes")
|
return resultData(fctx.requestResult, "reqRes")
|
||||||
}
|
}
|
||||||
@ -123,9 +192,9 @@ func filteringData(
|
|||||||
func resultData(
|
func resultData(
|
||||||
res filter.Result,
|
res filter.Result,
|
||||||
argName string,
|
argName string,
|
||||||
) (id agd.FilterListID, text agd.FilterRuleText, blocked bool) {
|
) (id filter.ID, text filter.RuleText, blocked bool) {
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return agd.FilterListIDNone, "", false
|
return filter.IDNone, "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
id, text = res.MatchedRule()
|
id, text = res.MatchedRule()
|
||||||
@ -164,7 +233,13 @@ func (mw *Middleware) setFilteredResponse(
|
|||||||
var err error
|
var err error
|
||||||
fctx.filteredResponse, err = ri.Messages.NewBlockedResp(fctx.originalRequest)
|
fctx.filteredResponse, err = ri.Messages.NewBlockedResp(fctx.originalRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.reportf(ctx, "creating blocked resp for filtered req: %w", err)
|
errcoll.Collect(
|
||||||
|
ctx,
|
||||||
|
mw.errColl,
|
||||||
|
mw.logger,
|
||||||
|
"creating blocked resp for filtered req",
|
||||||
|
err,
|
||||||
|
)
|
||||||
fctx.filteredResponse = fctx.originalResponse
|
fctx.filteredResponse = fctx.originalResponse
|
||||||
}
|
}
|
||||||
case *filter.ResultAllowed, *filter.ResultModifiedRequest:
|
case *filter.ResultAllowed, *filter.ResultModifiedRequest:
|
||||||
@ -201,7 +276,13 @@ func (mw *Middleware) setFilteredResponseNoReq(
|
|||||||
var err error
|
var err error
|
||||||
fctx.filteredResponse, err = ri.Messages.NewBlockedResp(fctx.originalRequest)
|
fctx.filteredResponse, err = ri.Messages.NewBlockedResp(fctx.originalRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.reportf(ctx, "creating blocked resp for filtered resp: %w", err)
|
errcoll.Collect(
|
||||||
|
ctx,
|
||||||
|
mw.errColl,
|
||||||
|
mw.logger,
|
||||||
|
"creating blocked resp for filtered resp",
|
||||||
|
err,
|
||||||
|
)
|
||||||
fctx.filteredResponse = fctx.originalResponse
|
fctx.filteredResponse = fctx.originalResponse
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
type Middleware struct {
|
type Middleware struct {
|
||||||
cloner *dnsmsg.Cloner
|
cloner *dnsmsg.Cloner
|
||||||
fltCtxPool *syncutil.Pool[filteringContext]
|
fltCtxPool *syncutil.Pool[filteringContext]
|
||||||
|
fltReqPool *syncutil.Pool[filter.Request]
|
||||||
|
fltRespPool *syncutil.Pool[filter.Response]
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
messages *dnsmsg.Constructor
|
messages *dnsmsg.Constructor
|
||||||
billStat billstat.Recorder
|
billStat billstat.Recorder
|
||||||
@ -84,6 +86,12 @@ func New(c *Config) (mw *Middleware) {
|
|||||||
fltCtxPool: syncutil.NewPool(func() (v *filteringContext) {
|
fltCtxPool: syncutil.NewPool(func() (v *filteringContext) {
|
||||||
return &filteringContext{}
|
return &filteringContext{}
|
||||||
}),
|
}),
|
||||||
|
fltReqPool: syncutil.NewPool(func() (v *filter.Request) {
|
||||||
|
return &filter.Request{}
|
||||||
|
}),
|
||||||
|
fltRespPool: syncutil.NewPool(func() (v *filter.Response) {
|
||||||
|
return &filter.Response{}
|
||||||
|
}),
|
||||||
logger: c.Logger,
|
logger: c.Logger,
|
||||||
messages: c.Messages,
|
messages: c.Messages,
|
||||||
billStat: c.BillStat,
|
billStat: c.BillStat,
|
||||||
@ -125,7 +133,7 @@ func (mw *Middleware) Wrap(next dnsserver.Handler) (wrapped dnsserver.Handler) {
|
|||||||
"remote_ip", ri.RemoteIP,
|
"remote_ip", ri.RemoteIP,
|
||||||
)
|
)
|
||||||
|
|
||||||
flt := mw.fltStrg.FilterFromContext(ctx, ri)
|
flt := mw.filter(ctx, ri)
|
||||||
mw.filterRequest(ctx, fctx, flt, ri)
|
mw.filterRequest(ctx, fctx, flt, ri)
|
||||||
|
|
||||||
// Check the context error here, since the context could have already
|
// Check the context error here, since the context could have already
|
||||||
@ -171,6 +179,20 @@ func (mw *Middleware) Wrap(next dnsserver.Handler) (wrapped dnsserver.Handler) {
|
|||||||
return dnsserver.HandlerFunc(f)
|
return dnsserver.HandlerFunc(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filter returns a filter based on the request information.
|
||||||
|
func (mw *Middleware) filter(ctx context.Context, ri *agd.RequestInfo) (f filter.Interface) {
|
||||||
|
p, d := ri.DeviceData()
|
||||||
|
if p == nil {
|
||||||
|
return mw.fltStrg.ForConfig(ctx, ri.FilteringGroup.FilterConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.FilteringEnabled && d.FilteringEnabled {
|
||||||
|
return mw.fltStrg.ForConfig(ctx, p.FilterConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mw.fltStrg.ForConfig(ctx, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// nextParams is a helper that returns the parameters to call the next handler
|
// nextParams is a helper that returns the parameters to call the next handler
|
||||||
// with taking the filtering context into account.
|
// with taking the filtering context into account.
|
||||||
func (mw *Middleware) nextParams(
|
func (mw *Middleware) nextParams(
|
||||||
@ -239,8 +261,3 @@ func (mw *Middleware) reportMetrics(
|
|||||||
IsBlocked: isBlocked,
|
IsBlocked: isBlocked,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// reportf is a helper method for reporting non-critical errors.
|
|
||||||
func (mw *Middleware) reportf(ctx context.Context, format string, args ...any) {
|
|
||||||
errcoll.Collectf(ctx, mw.errColl, "mainmw: "+format, args...)
|
|
||||||
}
|
|
||||||
|
@ -34,12 +34,12 @@ const (
|
|||||||
testRespAddr4Str = "3.4.5.6"
|
testRespAddr4Str = "3.4.5.6"
|
||||||
testRewriteAddrStr = "7.8.9.0"
|
testRewriteAddrStr = "7.8.9.0"
|
||||||
|
|
||||||
testRuleAllow agd.FilterRuleText = "@@||" + dnssvctest.DomainAllowed + "^"
|
testRuleAllow filter.RuleText = "@@||" + dnssvctest.DomainAllowed + "^"
|
||||||
testRuleBlockReq agd.FilterRuleText = "||" + dnssvctest.DomainBlocked + "^"
|
testRuleBlockReq filter.RuleText = "||" + dnssvctest.DomainBlocked + "^"
|
||||||
testRuleBlockResp agd.FilterRuleText = "||" + testRespAddr4Str + "^"
|
testRuleBlockResp filter.RuleText = "||" + testRespAddr4Str + "^"
|
||||||
testRuleRewrite agd.FilterRuleText = "||" + dnssvctest.DomainRewritten +
|
testRuleRewrite filter.RuleText = "||" + dnssvctest.DomainRewritten +
|
||||||
"^$dnsrewrite=NOERROR;A;" + testRewriteAddrStr
|
"^$dnsrewrite=NOERROR;A;" + testRewriteAddrStr
|
||||||
testRuleRewriteCNAME agd.FilterRuleText = "||" + dnssvctest.DomainRewritten +
|
testRuleRewriteCNAME filter.RuleText = "||" + dnssvctest.DomainRewritten +
|
||||||
"^$dnsrewrite=NOERROR;CNAME;" + dnssvctest.DomainRewrittenCNAME
|
"^$dnsrewrite=NOERROR;CNAME;" + dnssvctest.DomainRewrittenCNAME
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,25 +96,23 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
flt := &agdtest.Filter{
|
flt := &agdtest.Filter{
|
||||||
OnFilterRequest: func(
|
OnFilterRequest: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
_ *dns.Msg,
|
_ *filter.Request,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
OnFilterResponse: func(
|
OnFilterResponse: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
_ *dns.Msg,
|
_ *filter.Response,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fltStrg := &agdtest.FilterStorage{
|
fltStrg := &agdtest.FilterStorage{
|
||||||
OnFilterFromContext: func(_ context.Context, _ *agd.RequestInfo) (f filter.Interface) {
|
OnForConfig: func(_ context.Context, _ filter.Config) (f filter.Interface) {
|
||||||
return flt
|
return flt
|
||||||
},
|
},
|
||||||
OnHasListID: func(_ agd.FilterListID) (ok bool) { panic("not implemented") },
|
OnHasListID: func(_ filter.ID) (ok bool) { panic("not implemented") },
|
||||||
}
|
}
|
||||||
|
|
||||||
geoIP := agdtest.NewGeoIP()
|
geoIP := agdtest.NewGeoIP()
|
||||||
@ -131,10 +129,10 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ruleStat := &agdtest.RuleStat{
|
ruleStat := &agdtest.RuleStat{
|
||||||
OnCollect: func(_ context.Context, id agd.FilterListID, text agd.FilterRuleText) {
|
OnCollect: func(_ context.Context, id filter.ID, text filter.RuleText) {
|
||||||
pt := testutil.PanicT{}
|
pt := testutil.PanicT{}
|
||||||
require.Equal(pt, agd.FilterListID(""), id)
|
require.Equal(pt, filter.ID(""), id)
|
||||||
require.Equal(pt, agd.FilterRuleText(""), text)
|
require.Equal(pt, filter.RuleText(""), text)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +236,10 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
h := mw.Wrap(newSimpleHandler(t, tc.req, wantResp))
|
h := mw.Wrap(newSimpleHandler(t, tc.req, wantResp))
|
||||||
|
|
||||||
ctx := newContext(t, tc.device, tc.profile, reqHost, reqQType, reqStart)
|
ctx := newContext(t, tc.device, tc.profile, reqHost, reqQType, reqStart)
|
||||||
rw := dnsserver.NewNonWriterResponseWriter(dnssvctest.ServerTCPAddr, dnssvctest.ClientTCPAddr)
|
rw := dnsserver.NewNonWriterResponseWriter(
|
||||||
|
dnssvctest.ServerTCPAddr,
|
||||||
|
dnssvctest.ClientTCPAddr,
|
||||||
|
)
|
||||||
|
|
||||||
serveErr := h.ServeDNS(ctx, rw, tc.req)
|
serveErr := h.ServeDNS(ctx, rw, tc.req)
|
||||||
testutil.AssertErrorMsg(t, tc.wantErrMsg, serveErr)
|
testutil.AssertErrorMsg(t, tc.wantErrMsg, serveErr)
|
||||||
@ -332,6 +333,19 @@ func newContext(
|
|||||||
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
||||||
StartTime: start,
|
StartTime: start,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
fltConf := &filter.ConfigGroup{
|
||||||
|
Parental: &filter.ConfigParental{},
|
||||||
|
RuleList: &filter.ConfigRuleList{
|
||||||
|
IDs: []filter.ID{
|
||||||
|
dnssvctest.FilterListID1,
|
||||||
|
dnssvctest.FilterListID2,
|
||||||
|
},
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
SafeBrowsing: &filter.ConfigSafeBrowsing{},
|
||||||
|
}
|
||||||
|
|
||||||
ctx = agd.ContextWithRequestInfo(ctx, &agd.RequestInfo{
|
ctx = agd.ContextWithRequestInfo(ctx, &agd.RequestInfo{
|
||||||
DeviceResult: &agd.DeviceResultOK{
|
DeviceResult: &agd.DeviceResultOK{
|
||||||
Device: d,
|
Device: d,
|
||||||
@ -342,11 +356,7 @@ func newContext(
|
|||||||
ASN: testASN,
|
ASN: testASN,
|
||||||
},
|
},
|
||||||
FilteringGroup: &agd.FilteringGroup{
|
FilteringGroup: &agd.FilteringGroup{
|
||||||
RuleListIDs: []agd.FilterListID{
|
FilterConfig: fltConf,
|
||||||
dnssvctest.FilterListID1,
|
|
||||||
dnssvctest.FilterListID2,
|
|
||||||
},
|
|
||||||
RuleListsEnabled: true,
|
|
||||||
},
|
},
|
||||||
Messages: agdtest.NewConstructor(tb),
|
Messages: agdtest.NewConstructor(tb),
|
||||||
RemoteIP: dnssvctest.ClientAddr,
|
RemoteIP: dnssvctest.ClientAddr,
|
||||||
@ -540,7 +550,7 @@ func TestMiddleware_Wrap_filtering(t *testing.T) {
|
|||||||
respRes filter.Result
|
respRes filter.Result
|
||||||
name string
|
name string
|
||||||
wantErrMsg string
|
wantErrMsg string
|
||||||
wantRule agd.FilterRuleText
|
wantRule filter.RuleText
|
||||||
}{{
|
}{{
|
||||||
req: reqAllow,
|
req: reqAllow,
|
||||||
device: nil,
|
device: nil,
|
||||||
@ -641,28 +651,23 @@ func TestMiddleware_Wrap_filtering(t *testing.T) {
|
|||||||
flt := &agdtest.Filter{
|
flt := &agdtest.Filter{
|
||||||
OnFilterRequest: func(
|
OnFilterRequest: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
_ *dns.Msg,
|
_ *filter.Request,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return tc.reqRes, nil
|
return tc.reqRes, nil
|
||||||
},
|
},
|
||||||
OnFilterResponse: func(
|
OnFilterResponse: func(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
_ *dns.Msg,
|
_ *filter.Response,
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (r filter.Result, err error) {
|
) (r filter.Result, err error) {
|
||||||
return tc.respRes, nil
|
return tc.respRes, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fltStrg := &agdtest.FilterStorage{
|
fltStrg := &agdtest.FilterStorage{
|
||||||
OnFilterFromContext: func(
|
OnForConfig: func(_ context.Context, _ filter.Config) (f filter.Interface) {
|
||||||
_ context.Context,
|
|
||||||
_ *agd.RequestInfo,
|
|
||||||
) (f filter.Interface) {
|
|
||||||
return flt
|
return flt
|
||||||
},
|
},
|
||||||
OnHasListID: func(_ agd.FilterListID) (ok bool) { panic("not implemented") },
|
OnHasListID: func(_ filter.ID) (ok bool) { panic("not implemented") },
|
||||||
}
|
}
|
||||||
|
|
||||||
q := tc.req.Question[0]
|
q := tc.req.Question[0]
|
||||||
@ -680,7 +685,7 @@ func TestMiddleware_Wrap_filtering(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ruleStat := &agdtest.RuleStat{
|
ruleStat := &agdtest.RuleStat{
|
||||||
OnCollect: func(_ context.Context, id agd.FilterListID, text agd.FilterRuleText) {
|
OnCollect: func(_ context.Context, id filter.ID, text filter.RuleText) {
|
||||||
pt := testutil.PanicT{}
|
pt := testutil.PanicT{}
|
||||||
require.Equal(pt, dnssvctest.FilterListID1, id)
|
require.Equal(pt, dnssvctest.FilterListID1, id)
|
||||||
require.Equal(pt, tc.wantRule, text)
|
require.Equal(pt, tc.wantRule, text)
|
||||||
@ -705,7 +710,10 @@ func TestMiddleware_Wrap_filtering(t *testing.T) {
|
|||||||
h := mw.Wrap(newSimpleHandler(t, tc.wantUpsReq, tc.upsResp))
|
h := mw.Wrap(newSimpleHandler(t, tc.wantUpsReq, tc.upsResp))
|
||||||
|
|
||||||
ctx := newContext(t, tc.device, tc.profile, reqHost, reqQType, reqStart)
|
ctx := newContext(t, tc.device, tc.profile, reqHost, reqQType, reqStart)
|
||||||
rw := dnsserver.NewNonWriterResponseWriter(dnssvctest.ServerTCPAddr, dnssvctest.ClientTCPAddr)
|
rw := dnsserver.NewNonWriterResponseWriter(
|
||||||
|
dnssvctest.ServerTCPAddr,
|
||||||
|
dnssvctest.ClientTCPAddr,
|
||||||
|
)
|
||||||
|
|
||||||
serveErr := h.ServeDNS(ctx, rw, tc.req)
|
serveErr := h.ServeDNS(ctx, rw, tc.req)
|
||||||
testutil.AssertErrorMsg(t, tc.wantErrMsg, serveErr)
|
testutil.AssertErrorMsg(t, tc.wantErrMsg, serveErr)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/optslog"
|
"github.com/AdguardTeam/AdGuardDNS/internal/optslog"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/querylog"
|
"github.com/AdguardTeam/AdGuardDNS/internal/querylog"
|
||||||
@ -87,7 +88,7 @@ func (mw *Middleware) recordQueryInfo(
|
|||||||
err := mw.queryLog.Write(ctx, e)
|
err := mw.queryLog.Write(ctx, e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Consider query logging errors non-critical.
|
// Consider query logging errors non-critical.
|
||||||
mw.reportf(ctx, "writing query log: %w", err)
|
errcoll.Collect(ctx, mw.errColl, mw.logger, "writing query log", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ func (mw *Middleware) responseData(
|
|||||||
|
|
||||||
ip, err := ipFromAnswer(resp.Answer)
|
ip, err := ipFromAnswer(resp.Answer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.reportf(ctx, "getting response data: %w", err)
|
errcoll.Collect(ctx, mw.errColl, mw.logger, "getting response data", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rcode, ip, dnssec
|
return rcode, ip, dnssec
|
||||||
@ -228,7 +229,7 @@ func (mw *Middleware) country(ctx context.Context, host string, ip netip.Addr) (
|
|||||||
l, err := mw.geoIP.Data(host, ip)
|
l, err := mw.geoIP.Data(host, ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Consider GeoIP errors non-critical.
|
// Consider GeoIP errors non-critical.
|
||||||
mw.reportf(ctx, "getting geoip data: %w", err)
|
errcoll.Collect(ctx, mw.errColl, mw.logger, "getting geoip data", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if l != nil {
|
if l != nil {
|
||||||
|
@ -42,7 +42,7 @@ func TestMiddleware_Wrap_access(t *testing.T) {
|
|||||||
blockedClient2Prefix = netip.MustParsePrefix("2001:db8::/120")
|
blockedClient2Prefix = netip.MustParsePrefix("2001:db8::/120")
|
||||||
)
|
)
|
||||||
|
|
||||||
accessMgr, errAccess := access.NewGlobal(
|
accessMgr, accessErr := access.NewGlobal(
|
||||||
[]string{
|
[]string{
|
||||||
domainBlockedNormal,
|
domainBlockedNormal,
|
||||||
domainBlockedUppercase,
|
domainBlockedUppercase,
|
||||||
@ -53,7 +53,7 @@ func TestMiddleware_Wrap_access(t *testing.T) {
|
|||||||
blockedClient2Prefix,
|
blockedClient2Prefix,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
require.NoError(t, errAccess)
|
require.NoError(t, accessErr)
|
||||||
|
|
||||||
geoIP := agdtest.NewGeoIP()
|
geoIP := agdtest.NewGeoIP()
|
||||||
geoIP.OnData = func(_ string, _ netip.Addr) (l *geoip.Location, err error) {
|
geoIP.OnData = func(_ string, _ netip.Addr) (l *geoip.Location, err error) {
|
||||||
@ -154,9 +154,11 @@ func TestMiddleware_Wrap_access(t *testing.T) {
|
|||||||
qtype: dns.TypeAAAA,
|
qtype: dns.TypeAAAA,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
handler := dnsserver.HandlerFunc(func(ctx context.Context, rw dnsserver.ResponseWriter, req *dns.Msg) (_ error) {
|
handler := dnsserver.HandlerFunc(
|
||||||
|
func(ctx context.Context, rw dnsserver.ResponseWriter, req *dns.Msg) (err error) {
|
||||||
return rw.WriteMsg(ctx, req, dnsservertest.NewResp(dns.RcodeSuccess, req))
|
return rw.WriteMsg(ctx, req, dnsservertest.NewResp(dns.RcodeSuccess, req))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
@ -15,10 +15,10 @@ var msgSink *dns.Msg
|
|||||||
func BenchmarkMiddleware_Get(b *testing.B) {
|
func BenchmarkMiddleware_Get(b *testing.B) {
|
||||||
mw := &Middleware{
|
mw := &Middleware{
|
||||||
cache: agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
cache: agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
||||||
Size: 10,
|
Count: 10,
|
||||||
}),
|
}),
|
||||||
ecsCache: agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
ecsCache: agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
||||||
Size: 10,
|
Count: 10,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -91,10 +91,10 @@ type MiddlewareConfig struct {
|
|||||||
// manager. c must not be nil.
|
// manager. c must not be nil.
|
||||||
func NewMiddleware(c *MiddlewareConfig) (m *Middleware) {
|
func NewMiddleware(c *MiddlewareConfig) (m *Middleware) {
|
||||||
cache := agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
cache := agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
||||||
Size: c.NoECSCount,
|
Count: c.NoECSCount,
|
||||||
})
|
})
|
||||||
ecsCache := agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
ecsCache := agdcache.NewLRU[uint64, *cacheItem](&agdcache.LRUConfig{
|
||||||
Size: c.ECSCount,
|
Count: c.ECSCount,
|
||||||
})
|
})
|
||||||
|
|
||||||
c.CacheManager.Add(cacheIDNoECS, cache)
|
c.CacheManager.Add(cacheIDNoECS, cache)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user