mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
Sync v2.6.0
This commit is contained in:
parent
150f2d733f
commit
b6e37914aa
43
CHANGELOG.md
43
CHANGELOG.md
@ -11,6 +11,49 @@ The format is **not** based on [Keep a Changelog][kec], since the project
|
||||
|
||||
|
||||
|
||||
## AGDNS-1954 / Build 719
|
||||
|
||||
* The objects within `server_groups` array have a new property
|
||||
`block_page_redirect`:
|
||||
|
||||
```yaml
|
||||
block_page_redirect:
|
||||
enabled: true
|
||||
ipv4:
|
||||
- address: '127.0.0.1'
|
||||
- address: '127.0.0.2'
|
||||
ipv6:
|
||||
- address: '::1'
|
||||
- address: '::2'
|
||||
apply:
|
||||
client:
|
||||
- address: '192.168.0.0/16'
|
||||
- address: '1.2.3.4'
|
||||
skip:
|
||||
client:
|
||||
- address: '1.2.0.0/16'
|
||||
question:
|
||||
- domain: 'do-not-show-block.site.example'
|
||||
probability: 0.01
|
||||
```
|
||||
|
||||
For server groups that do not require a block-page redirect, set:
|
||||
|
||||
```yaml
|
||||
block_page_redirect:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
|
||||
|
||||
## AGDNS-1888 / Build 717
|
||||
|
||||
* The new environment variable `PROFILES_ENABLED` has been added. With `0`
|
||||
value it disables user profiles and devices recognition, and billing. Its
|
||||
default value is `1`. Adjust the value, if necessary.
|
||||
|
||||
|
||||
|
||||
## AGDNS-1761 / Build 702
|
||||
|
||||
* The property `upstream` has been modified. Its property `timeout` has been
|
||||
|
13
Makefile
13
Makefile
@ -8,7 +8,7 @@
|
||||
# Makefile. Bump this number every time a significant change is made to
|
||||
# this Makefile.
|
||||
#
|
||||
# AdGuard-Project-Version: 2
|
||||
# AdGuard-Project-Version: 4
|
||||
|
||||
# Don't name these macros "GO" etc., because GNU Make apparently makes
|
||||
# them exported environment variables with the literal value of
|
||||
@ -23,7 +23,7 @@ VERBOSE.MACRO = $${VERBOSE:-0}
|
||||
BRANCH = $$( git rev-parse --abbrev-ref HEAD )
|
||||
GOAMD64 = v1
|
||||
GOPROXY = https://goproxy.cn|https://proxy.golang.org|direct
|
||||
GOTOOLCHAIN = go1.21.5
|
||||
GOTOOLCHAIN = go1.21.8
|
||||
RACE = 0
|
||||
REVISION = $$( git rev-parse --short HEAD )
|
||||
VERSION = 0
|
||||
@ -59,6 +59,8 @@ go-lint: ; $(ENV) "$(SHELL)" ./scripts/make/go-lint.sh
|
||||
go-test: ; $(ENV) RACE='1' "$(SHELL)" ./scripts/make/go-test.sh
|
||||
go-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-tools.sh
|
||||
|
||||
go-upd-tools: ; $(ENV) "$(SHELL)" ./scripts/make/go-upd-tools.sh
|
||||
|
||||
go-check: go-tools go-lint go-test
|
||||
|
||||
# A quick check to make sure that all operating systems relevant to the
|
||||
@ -73,11 +75,4 @@ go-os-check:
|
||||
|
||||
txt-lint: ; $(ENV) "$(SHELL)" ./scripts/make/txt-lint.sh
|
||||
|
||||
# TODO(a.garipov): Consider adding to scripts/ and the common project
|
||||
# structure.
|
||||
go-upd-tools:
|
||||
cd ./internal/tools/ &&\
|
||||
"$(GO.MACRO)" get -u &&\
|
||||
"$(GO.MACRO)" mod tidy
|
||||
|
||||
sync-github: ; $(ENV) "$(SHELL)" ./scripts/make/github-sync.sh
|
||||
|
@ -274,7 +274,7 @@ filters:
|
||||
# FILTER_INDEX_URL environment variable.
|
||||
refresh_interval: 1h
|
||||
# The timeout for the entire filter update operation. Be aware that each
|
||||
# individual refresh operation also has its own hardcoded 30s timeout.
|
||||
# individual refresh operation also has its own hardcoded 3m timeout.
|
||||
refresh_timeout: 5m
|
||||
# MaxSize is the maximum size of the downloadable filtering rule-list.
|
||||
max_size: 256MB
|
||||
@ -351,15 +351,38 @@ server_groups:
|
||||
- name: 'adguard_dns_default'
|
||||
# This filtering_group is used for all anonymous clients.
|
||||
filtering_group: 'default'
|
||||
tls:
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
session_keys:
|
||||
- './test/tls_key_1'
|
||||
- './test/tls_key_2'
|
||||
device_id_wildcards:
|
||||
- '*.dns.example.com'
|
||||
# Settings for redirection to a block page.
|
||||
block_page_redirect:
|
||||
# If enabled is false, other fields can be skipped.
|
||||
enabled: true
|
||||
# Addresses to use for A queries. If enabled is true, ipv4, ipv6, or
|
||||
# both must be filled.
|
||||
ipv4:
|
||||
- address: '127.0.0.1'
|
||||
- address: '127.0.0.2'
|
||||
# Addresses to use for AAAA queries. If enabled is true, ipv4, ipv6, or
|
||||
# both must be filled.
|
||||
ipv6:
|
||||
- address: '::1'
|
||||
- address: '::2'
|
||||
# Request parameters based on which the block page is always shown. For
|
||||
# requests matching these parameters, both skip and probability are
|
||||
# ignored.
|
||||
apply:
|
||||
client:
|
||||
- address: '192.168.0.0/16'
|
||||
- address: '1.2.3.4'
|
||||
# Request parameters based on which the block page is never shown. For
|
||||
# requests matching these parameters, probability is ignored.
|
||||
skip:
|
||||
client:
|
||||
- address: '1.2.0.0/16'
|
||||
- address: '5.6.7.8'
|
||||
question:
|
||||
- domain: 'do-not-show-block.site.example'
|
||||
# The probability of responding with the block page IPs based on remote
|
||||
# address. Must be between 0.0 and 1.0.
|
||||
probability: 0.01
|
||||
ddr:
|
||||
enabled: true
|
||||
# Device ID domain name suffix to DDR record template mapping. Keep in
|
||||
@ -386,6 +409,15 @@ server_groups:
|
||||
- '127.0.0.1'
|
||||
ipv6_hints:
|
||||
- '::1'
|
||||
tls:
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
session_keys:
|
||||
- './test/tls_key_1'
|
||||
- './test/tls_key_2'
|
||||
device_id_wildcards:
|
||||
- '*.dns.example.com'
|
||||
servers:
|
||||
- name: 'default_dns'
|
||||
# See README for the list of protocol values.
|
||||
|
@ -28,8 +28,9 @@ configuration file with comments.
|
||||
* [Filtering groups](#filtering_groups)
|
||||
* [Network interface listeners](#interface_listeners)
|
||||
* [Server groups](#server_groups)
|
||||
* [TLS](#server_groups-*-tls)
|
||||
* [Block-page redirecting](#server_groups-*-block_page_redirect)
|
||||
* [DDR](#server_groups-*-ddr)
|
||||
* [TLS](#server_groups-*-tls)
|
||||
* [Servers](#server_groups-*-servers-*)
|
||||
* [Connectivity check](#connectivity-check)
|
||||
* [Network settings](#network)
|
||||
@ -108,9 +109,10 @@ Currently, there are the following recommendations for parameters
|
||||
TCP sockets. That is, if the instance currently has a maximum of 100 000
|
||||
TCP sockets in use every day, `resume` should be set to about `120000`.
|
||||
|
||||
**NOTE:** The number of active stream-connections includes sockets that are
|
||||
in the process of accepting new connections but have not yet accepted one. That
|
||||
means that `resume` should be greater than the number of bound addresses.
|
||||
> [!NOTE]
|
||||
> The number of active stream-connections includes sockets that are in the
|
||||
> process of accepting new connections but have not yet accepted one. That
|
||||
> means that `resume` should be greater than the number of bound addresses.
|
||||
|
||||
These recommendations are to be revised based on the metrics.
|
||||
|
||||
@ -776,7 +778,7 @@ The `filters` object has the following properties:
|
||||
* <a href="#filters-refresh_timeout" id="filters-refresh_timeout" name="filters-refresh_timeout">`refresh_timeout`</a>:
|
||||
The timeout for the *entire* filter update operation, as a human-readable
|
||||
duration. Be aware that each individual refresh operation also has its own
|
||||
hardcoded 30s timeout.
|
||||
hardcoded 3m timeout.
|
||||
|
||||
**Example:** `5m`.
|
||||
|
||||
@ -890,9 +892,10 @@ The items of the `filtering_groups` array have the following properties:
|
||||
|
||||
## <a href="#interface_listeners" id="interface_listeners" name="interface_listeners">Network interface listeners</a>
|
||||
|
||||
**NOTE:** The network interface listening works only on Linux with
|
||||
`SO_BINDTODEVICE` support (2.0.30 and later) and properly setup IP routes. See
|
||||
the [section on testing `SO_BINDTODEVICE` using Docker][dev-btd].
|
||||
> [!NOTE]
|
||||
> The network interface listening works only on Linux with `SO_BINDTODEVICE`
|
||||
> support (2.0.30 and later) and properly setup IP routes. See the [section
|
||||
> on testing `SO_BINDTODEVICE` using Docker][dev-btd].
|
||||
|
||||
The `interface_listeners` object has the following properties:
|
||||
|
||||
@ -936,52 +939,83 @@ The items of the `server_groups` array have the following properties:
|
||||
|
||||
**Example:** `default`.
|
||||
|
||||
* `tls`: The optional TLS configuration object. See
|
||||
[below](#server_groups-*-tls).
|
||||
* `block_page_redirect`: The block-page redirect configuration object. See
|
||||
[below](#server_groups-*-block_page_redirect).
|
||||
|
||||
* `ddr`: The DDR configuration object. See [below](#server_groups-*-ddr).
|
||||
|
||||
* `tls`: The TLS configuration object. See [below](#server_groups-*-tls).
|
||||
|
||||
> [!NOTE]
|
||||
> The `tls` object is optional unless the [`servers`
|
||||
> array](#server_groups-*-servers-*) contains at least one item with an
|
||||
> encrypted protocol.
|
||||
|
||||
* `servers`: Server configuration for this filtering group. See
|
||||
[below](#server_groups-*-servers-*).
|
||||
|
||||
|
||||
|
||||
### <a href="#server_groups-*-tls" id="server_groups-*-tls" name="server_groups-*-tls">TLS</a>
|
||||
### <a href="#server_groups-*-block_page_redirect" id="server_groups-*-block_page_redirect" name="server_groups-*-block_page_redirect">Block-page redirecting</a>
|
||||
|
||||
* <a href="#sg-*-tls-certificates" id="sg-*-tls-certificates" name="sg-*-tls-certificates">`certificates`</a>:
|
||||
The array of objects with paths to the certificate and the private key for
|
||||
this server group.
|
||||
The block-page redirect configuration object. If enabled, AdGuard DNS responds
|
||||
with the configured IP addresses to “redirect” users to an informative block
|
||||
page.
|
||||
|
||||
* <a href="#sg-*-bpr-enabled" id="sg-*-bpr-enabled" name="sg-*-bpr-enabled">`enabled`</a>:
|
||||
|
||||
Shows if the block-page redirect is enabled. If `false`, the fields below
|
||||
can be skipped.
|
||||
|
||||
* <a href="#sg-*-bpr-ipv4" id="sg-*-bpr-ipv4" name="sg-*-bpr-ipv4">`ipv4`</a>:
|
||||
|
||||
Arrays of IPv4 addresses with which to respond to blocked `A` queries.
|
||||
|
||||
If `enabled` is true, `ipv4`, `ipv6`, or both must be filled.
|
||||
|
||||
* <a href="#sg-*-bpr-ipv6" id="sg-*-bpr-ipv6" name="sg-*-bpr-ipv6">`ipv6`</a>:
|
||||
|
||||
Arrays of IPv6 addresses with which to respond to blocked `AAAA` queries.
|
||||
|
||||
If `enabled` is true, `ipv4`, `ipv6`, or both must be filled.
|
||||
|
||||
* <a href="#sg-*-bpr-apply" id="sg-*-bpr-apply" name="sg-*-bpr-apply">`apply`</a>:
|
||||
|
||||
Request parameters based on which the block-page redirect is always
|
||||
performed. For requests matching these parameters, both `skip` and
|
||||
`probability` are
|
||||
ignored.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'certificates':
|
||||
- 'certificate': '/etc/dns/cert.crt'
|
||||
'key': '/etc/dns/cert.key'
|
||||
apply:
|
||||
client:
|
||||
- address: '192.168.0.0/16'
|
||||
- address: '1.2.3.4'
|
||||
```
|
||||
|
||||
* <a href="#sg-*-tls-session_keys" id="sg-*-tls-session_keys" name="sg-*-tls-session_keys">`session_keys`</a>:
|
||||
The array of file paths from which the each server's TLS session keys are
|
||||
updated. Session ticket key files must contain at least 32 bytes.
|
||||
* <a href="#sg-*-bpr-skip" id="sg-*-bpr-skip" name="sg-*-bpr-skip">`skip`</a>:
|
||||
|
||||
Request parameters based on which the block-page redirect is never
|
||||
performed. For requests matching these parameters, `probability` is
|
||||
ignored.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'session_keys':
|
||||
- './private/key_1'
|
||||
- './private/key_2'
|
||||
skip:
|
||||
client:
|
||||
- address: '1.2.0.0/16'
|
||||
- address: '5.6.7.8'
|
||||
question:
|
||||
- domain: 'do-not-show-block.site.example'
|
||||
```
|
||||
|
||||
* <a href="#sg-*-tls-device_id_wildcards" id="sg-*-tls-device_id_wildcards" name="sg-*-tls-device_id_wildcards">`device_id_wildcards`</a>:
|
||||
The array of domain name wildcards to use to detect clients' device IDs.
|
||||
Use this to prevent conflicts when using certificates for subdomains.
|
||||
* <a href="#sg-*-bpr-probability" id="sg-*-bpr-probability" name="sg-*-bpr-probability">`probability`</a>:
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'device_id_wildcards':
|
||||
- '*.d.dns.example.com'
|
||||
```
|
||||
The probability of responding with the block page IPs based on remote
|
||||
address. Must be between `0.0` and `1.0`.
|
||||
|
||||
|
||||
|
||||
@ -1062,6 +1096,45 @@ collected the required data was not self-describing and flexible enough.
|
||||
|
||||
|
||||
|
||||
### <a href="#server_groups-*-tls" id="server_groups-*-tls" name="server_groups-*-tls">TLS</a>
|
||||
|
||||
* <a href="#sg-*-tls-certificates" id="sg-*-tls-certificates" name="sg-*-tls-certificates">`certificates`</a>:
|
||||
The array of objects with paths to the certificate and the private key for
|
||||
this server group.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'certificates':
|
||||
- 'certificate': '/etc/dns/cert.crt'
|
||||
'key': '/etc/dns/cert.key'
|
||||
```
|
||||
|
||||
* <a href="#sg-*-tls-session_keys" id="sg-*-tls-session_keys" name="sg-*-tls-session_keys">`session_keys`</a>:
|
||||
The array of file paths from which the each server's TLS session keys are
|
||||
updated. Session ticket key files must contain at least 32 bytes.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'session_keys':
|
||||
- './private/key_1'
|
||||
- './private/key_2'
|
||||
```
|
||||
|
||||
* <a href="#sg-*-tls-device_id_wildcards" id="sg-*-tls-device_id_wildcards" name="sg-*-tls-device_id_wildcards">`device_id_wildcards`</a>:
|
||||
The array of domain name wildcards to use to detect clients' device IDs.
|
||||
Use this to prevent conflicts when using certificates for subdomains.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
'device_id_wildcards':
|
||||
- '*.d.dns.example.com'
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <a href="#server_groups-*-servers-*" id="server_groups-*-servers-*" name="server_groups-*-servers-*">Servers</a>
|
||||
|
||||
The items of the `servers` array have the following properties:
|
||||
|
@ -27,8 +27,9 @@ The response is sent with the `Transfer-Encoding` set to `chunked` and with an
|
||||
HTTP trailer named `X-Error` which describes errors that might have occurred
|
||||
during the database dump.
|
||||
|
||||
**NOTE:** For legacy software reasons, despite the endpoint being a `GET` one,
|
||||
it rotates the database, and so changes the internal state.
|
||||
> [!NOTE]
|
||||
> For legacy software reasons, despite the endpoint being a `GET` one, it
|
||||
> rotates the database, and so changes the internal state.
|
||||
|
||||
|
||||
|
||||
|
@ -315,8 +315,8 @@ Open `http://127.0.0.1:8081/metrics` to see the server's metrics.
|
||||
DNSCrypt is a bit trickier. You need to open `dnscrypt.yml` and use values from
|
||||
there to generate an SDNS stamp on <https://dnscrypt.info/stamps>.
|
||||
|
||||
**NOTE:** The example below is for a test configuration that won't work for
|
||||
you.
|
||||
> [!NOTE]
|
||||
> The example below is for a test configuration that won't work for you.
|
||||
|
||||
```sh
|
||||
dnslookup example.org sdns://AQcAAAAAAAAADjEyNy4wLjAuMTo1NDQzIAbKgP3dmXybr1DaKIFgKjsc8zSFX4rgT_hFgymSq6w1FzIuZG5zY3J5cHQtY2VydC50ZXN0ZG5z
|
||||
|
@ -23,6 +23,7 @@ sensitive configuration. All other configuration is stored in the
|
||||
* [`LOG_TIMESTAMP`](#LOG_TIMESTAMP)
|
||||
* [`NEW_REG_DOMAINS_URL`](#NEW_REG_DOMAINS_URL)
|
||||
* [`PROFILES_CACHE_PATH`](#PROFILES_CACHE_PATH)
|
||||
* [`PROFILES_ENABLED`](#PROFILES_ENABLED)
|
||||
* [`PROFILES_URL`](#PROFILES_URL)
|
||||
* [`QUERYLOG_PATH`](#QUERYLOG_PATH)
|
||||
* [`RESEARCH_LOGS`](#RESEARCH_LOGS)
|
||||
@ -236,6 +237,14 @@ The profile cache is read on start and is later updated on every
|
||||
|
||||
|
||||
|
||||
## <a href="#PROFILES_ENABLED" id="PROFILES_ENABLED" name="PROFILES_ENABLED">`PROFILES_ENABLED`</a>
|
||||
|
||||
If `0`, disables user profiles and devices recognition and billing.
|
||||
|
||||
**Default:** `1`.
|
||||
|
||||
|
||||
|
||||
## <a href="#PROFILES_URL" id="PROFILES_URL" name="PROFILES_URL">`PROFILES_URL`</a>
|
||||
|
||||
The base backend URL for profiles API. Supports GRPC (`grpc://` and`grpcs://`)
|
||||
|
@ -30,9 +30,11 @@ document should set the `Server` header in their replies.
|
||||
|
||||
This is the service to which the [`BILLSTAT_URL`][env-billstat_url] environment
|
||||
variable points. Supports `grpc(s)` URLs. The service must correspond to
|
||||
`./internal/backendpb/backend.proto`.
|
||||
`./internal/backendpb/backend.proto`. This service can be disabled with the
|
||||
[`PROFILES_ENABLED`][env-profiles_enabled] environment variable.
|
||||
|
||||
[env-billstat_url]: environment.md#BILLSTAT_URL
|
||||
[env-profiles_enabled]: environment.md#PROFILES_ENABLED
|
||||
|
||||
|
||||
|
||||
@ -40,7 +42,8 @@ variable points. Supports `grpc(s)` URLs. The service must correspond to
|
||||
|
||||
This is the service to which the [`PROFILES_URL`][env-profiles_url] environment
|
||||
variable points. Supports `grpc(s)` URLs. The service must correspond to
|
||||
`./internal/backendpb/backend.proto`.
|
||||
`./internal/backendpb/backend.proto`. This service can be disabled with the
|
||||
[`PROFILES_ENABLED`][env-profiles_enabled] environment variable.
|
||||
|
||||
[env-profiles_url]: environment.md#PROFILES_URL
|
||||
|
||||
|
@ -42,8 +42,9 @@ rules to remember, which property means what. The properties are:
|
||||
alpha-2][wiki-iso] country code, if any. If none could be detected, this
|
||||
property is absent. The short name `c` stands for “client country”.
|
||||
|
||||
**NOTE:** AdGuard DNS uses the common user-assigned ISO 3166-1 alpha-2 code
|
||||
`XK` for the partially-recognized state of the Republic of Kosovo.
|
||||
> [!NOTE]
|
||||
> AdGuard DNS uses the common user-assigned ISO 3166-1 alpha-2 code `XK`
|
||||
> for the partially-recognized state of the Republic of Kosovo.
|
||||
|
||||
**Example:** `"AU"`
|
||||
|
||||
@ -53,8 +54,9 @@ rules to remember, which property means what. The properties are:
|
||||
could be detected, this property is absent. The short name `d` stands for
|
||||
“destination”.
|
||||
|
||||
**NOTE:** AdGuard DNS uses the common user-assigned ISO 3166-1 alpha-2 code
|
||||
`XK` for the partially-recognized state of the Republic of Kosovo.
|
||||
> [!NOTE]
|
||||
> AdGuard DNS uses the common user-assigned ISO 3166-1 alpha-2 code `XK`
|
||||
> for the partially-recognized state of the Republic of Kosovo.
|
||||
|
||||
**Example:** `"US"`
|
||||
|
||||
|
52
go.mod
52
go.mod
@ -1,32 +1,32 @@
|
||||
module github.com/AdguardTeam/AdGuardDNS
|
||||
|
||||
go 1.21.5
|
||||
go 1.21.8
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-00010101000000-000000000000
|
||||
github.com/AdguardTeam/golibs v0.18.1
|
||||
github.com/AdguardTeam/urlfilter v0.17.2
|
||||
github.com/AdguardTeam/golibs v0.20.1
|
||||
github.com/AdguardTeam/urlfilter v0.18.0
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20230201085229-3ddf4bad03dc
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
|
||||
github.com/caarlos0/env/v7 v7.1.0
|
||||
github.com/getsentry/sentry-go v0.25.0
|
||||
github.com/getsentry/sentry-go v0.27.0
|
||||
github.com/google/renameio/v2 v2.0.0
|
||||
github.com/miekg/dns v1.1.56
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/oschwald/maxminddb-golang v1.12.0
|
||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/prometheus/client_model v0.5.0
|
||||
github.com/prometheus/common v0.44.0
|
||||
github.com/quic-go/quic-go v0.39.0
|
||||
github.com/prometheus/common v0.46.0
|
||||
github.com/quic-go/quic-go v0.41.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0
|
||||
golang.org/x/time v0.3.0
|
||||
google.golang.org/grpc v1.58.3
|
||||
google.golang.org/protobuf v1.31.0
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/grpc v1.61.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@ -40,20 +40,18 @@ require (
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
|
||||
github.com/panjf2000/ants/v2 v2.8.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/panjf2000/ants/v2 v2.9.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
118
go.sum
118
go.sum
@ -1,7 +1,7 @@
|
||||
github.com/AdguardTeam/golibs v0.18.1 h1:6u0fvrIj2qjUsRdbIGJ9AR0g5QRSWdKIo/DYl3tp5aM=
|
||||
github.com/AdguardTeam/golibs v0.18.1/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
|
||||
github.com/AdguardTeam/urlfilter v0.17.2 h1:xTntfr1UWah8m6wwoXJmFgplFk/+kL/hDu204ptrM1U=
|
||||
github.com/AdguardTeam/urlfilter v0.17.2/go.mod h1:Jru7jFfeH2CoDf150uDs+rRYcZBzHHBz05r9REyDKyE=
|
||||
github.com/AdguardTeam/golibs v0.20.1 h1:ol8qLjWGZhU9paMMwN+OLWVTUigGsXa29iVTyd62VKY=
|
||||
github.com/AdguardTeam/golibs v0.20.1/go.mod h1:bgcMgRviCKyU6mkrX+RtT/OsKPFzyppelfRsksMG3KU=
|
||||
github.com/AdguardTeam/urlfilter v0.18.0 h1:ZZzwODC/ADpjJSODxySrrUnt/fvOCfGFaCW6j+wsGfQ=
|
||||
github.com/AdguardTeam/urlfilter v0.18.0/go.mod h1:IXxBwedLiZA2viyHkaFxY/8mjub0li2PXRg8a3d9Z1s=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||
@ -10,14 +10,14 @@ github.com/ameshkov/dnscrypt/v2 v2.2.7 h1:aEitLIR8HcxVodZ79mgRcCiC0A0I5kZPBuWGFw
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7/go.mod h1:qPWhwz6FdSmuK7W4sMyvogrez4MWdtzosdqlr0Rg3ow=
|
||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20230201085229-3ddf4bad03dc h1:Keo7wQ7UODUaHcEi7ltENhbAK2VgZjfat6mLy03tQzo=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20230201085229-3ddf4bad03dc/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b h1:F3yMzKumBUQ6Fn0sYI1YQ16vQRucpZOfBQ9HXWl5+XI=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY=
|
||||
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4=
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/caarlos0/env/v7 v7.1.0 h1:9lzTF5amyQeWHZzuZeKlCb5FWSUxpG1js43mhbY8ozg=
|
||||
github.com/caarlos0/env/v7 v7.1.0/go.mod h1:LPPWniDUq4JaO6Q41vtlyikhMknqymCLBw0eX4dcH1E=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
@ -28,25 +28,24 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
|
||||
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-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-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@ -55,18 +54,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||
github.com/panjf2000/ants/v2 v2.8.2 h1:D1wfANttg8uXhC9149gRt1PDQ+dLVFjNXkCEycMcvQQ=
|
||||
github.com/panjf2000/ants/v2 v2.8.2/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||
github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo=
|
||||
github.com/panjf2000/ants/v2 v2.9.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/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
@ -77,20 +74,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So=
|
||||
github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
|
||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
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/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
|
||||
@ -112,37 +107,36 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk=
|
||||
google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY=
|
||||
google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
43
go.work.sum
43
go.work.sum
@ -4,8 +4,11 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
||||
cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=
|
||||
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
|
||||
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
|
||||
cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
|
||||
@ -23,7 +26,9 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:OR8VhtwhcAI3U48/
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AdguardTeam/golibs v0.10.7/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
||||
github.com/AdguardTeam/golibs v0.17.2/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
|
||||
github.com/AdguardTeam/golibs v0.19.0/go.mod h1:3WunclLLfrVAq7fYQRhd6f168FHOEMssnipVXCxDL/w=
|
||||
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/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
@ -46,6 +51,7 @@ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjK
|
||||
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||
@ -64,10 +70,14 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2 h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@ -86,8 +96,11 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
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/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
||||
@ -98,8 +111,10 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
||||
github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM=
|
||||
github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
@ -141,8 +156,11 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
|
||||
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
||||
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
@ -151,7 +169,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
@ -180,6 +200,7 @@ 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/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
@ -292,6 +313,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
|
||||
@ -336,6 +358,7 @@ github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.38.0/go.mod h1:MPCuRq7KBK2hNcfKj/1iD1BGuN3eAYMeNxp3T42LRUg=
|
||||
github.com/quic-go/quic-go v0.39.4/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
|
||||
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
@ -446,12 +469,14 @@ go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d h1:E2M5QgjZ/Jg+ObCQAudsXxuTsLj7Nl5RV/lZcQZmKSo=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
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-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
@ -497,7 +522,9 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq
|
||||
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852 h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -508,6 +535,7 @@ golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -523,6 +551,9 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
@ -532,7 +563,13 @@ golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
@ -553,6 +590,7 @@ golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
@ -566,6 +604,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
@ -576,7 +615,11 @@ google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWof
|
||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
|
||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
|
||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
|
||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU=
|
||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/AdguardTeam/urlfilter"
|
||||
"github.com/AdguardTeam/urlfilter/filterlist"
|
||||
@ -23,26 +24,20 @@ type Interface interface {
|
||||
|
||||
// IsBlockedIP returns the status of the IP address blocking as well as the
|
||||
// rule that blocked it.
|
||||
IsBlockedIP(ip netip.Addr) (blocked bool, rule string)
|
||||
IsBlockedIP(ip netip.Addr) (blocked bool)
|
||||
}
|
||||
|
||||
// Global controls IP and client blocking that takes place before all other
|
||||
// processing. Global is safe for concurrent use.
|
||||
type Global struct {
|
||||
blockedIPs map[netip.Addr]string
|
||||
blockedHostsEng *urlfilter.DNSEngine
|
||||
blockedNets []netip.Prefix
|
||||
blockedNets netutil.SubnetSet
|
||||
}
|
||||
|
||||
// NewGlobal create a new Global from provided parameters.
|
||||
func NewGlobal(blockedDomains, blockedSubnets []string) (g *Global, err error) {
|
||||
func NewGlobal(blockedDomains []string, blockedSubnets []netip.Prefix) (g *Global, err error) {
|
||||
g = &Global{
|
||||
blockedIPs: map[netip.Addr]string{},
|
||||
}
|
||||
|
||||
err = processAccessList(blockedSubnets, g.blockedIPs, &g.blockedNets)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("adding blocked hosts: %w", err)
|
||||
blockedNets: netutil.SliceSubnetSet(blockedSubnets),
|
||||
}
|
||||
|
||||
b := &strings.Builder{}
|
||||
@ -68,24 +63,6 @@ func NewGlobal(blockedDomains, blockedSubnets []string) (g *Global, err error) {
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// processAccessList is a helper for processing a list of strings, each of them
|
||||
// could be an IP address or a CIDR.
|
||||
func processAccessList(strs []string, ips map[netip.Addr]string, nets *[]netip.Prefix) (err error) {
|
||||
for _, s := range strs {
|
||||
var ip netip.Addr
|
||||
var ipnet netip.Prefix
|
||||
if ip, err = netip.ParseAddr(s); err == nil {
|
||||
ips[ip] = ip.String()
|
||||
} else if ipnet, err = netip.ParsePrefix(s); err == nil {
|
||||
*nets = append(*nets, ipnet)
|
||||
} else {
|
||||
return fmt.Errorf("cannot parse subnet or ip address: %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Interface = (*Global)(nil)
|
||||
|
||||
@ -104,16 +81,6 @@ func (g *Global) IsBlockedHost(host string, qt uint16) (blocked bool) {
|
||||
}
|
||||
|
||||
// IsBlockedIP implements the [Interface] interface for *Global.
|
||||
func (g *Global) IsBlockedIP(ip netip.Addr) (blocked bool, rule string) {
|
||||
if ipStr, ok := g.blockedIPs[ip]; ok {
|
||||
return true, ipStr
|
||||
}
|
||||
|
||||
for _, ipnet := range g.blockedNets {
|
||||
if ipnet.Contains(ip) {
|
||||
return true, ipnet.String()
|
||||
}
|
||||
}
|
||||
|
||||
return false, ""
|
||||
func (g *Global) IsBlockedIP(ip netip.Addr) (blocked bool) {
|
||||
return g.blockedNets.Contains(ip)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ func TestGlobal_IsBlockedHost(t *testing.T) {
|
||||
"||block_aaaa.test^$dnstype=AAAA",
|
||||
"||allowlist.test^",
|
||||
"@@||allow.allowlist.test^",
|
||||
}, []string{})
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
@ -76,44 +76,38 @@ func TestGlobal_IsBlockedHost(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGlobal_IsBlockedIP(t *testing.T) {
|
||||
global, err := access.NewGlobal([]string{}, []string{
|
||||
"1.1.1.1",
|
||||
"2.2.2.0/8",
|
||||
global, err := access.NewGlobal([]string{}, []netip.Prefix{
|
||||
netip.MustParsePrefix("1.1.1.1/32"),
|
||||
netip.MustParsePrefix("2.2.2.0/8"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
want assert.BoolAssertionFunc
|
||||
ip netip.Addr
|
||||
wantRule string
|
||||
name string
|
||||
want assert.BoolAssertionFunc
|
||||
ip netip.Addr
|
||||
name string
|
||||
}{{
|
||||
want: assert.False,
|
||||
wantRule: "",
|
||||
name: "pass",
|
||||
ip: netip.MustParseAddr("1.1.1.0"),
|
||||
want: assert.False,
|
||||
name: "pass",
|
||||
ip: netip.MustParseAddr("1.1.1.0"),
|
||||
}, {
|
||||
want: assert.True,
|
||||
wantRule: "1.1.1.1",
|
||||
name: "block_ip",
|
||||
ip: netip.MustParseAddr("1.1.1.1"),
|
||||
want: assert.True,
|
||||
name: "block_ip",
|
||||
ip: netip.MustParseAddr("1.1.1.1"),
|
||||
}, {
|
||||
want: assert.False,
|
||||
wantRule: "",
|
||||
name: "pass_subnet",
|
||||
ip: netip.MustParseAddr("1.2.2.2"),
|
||||
want: assert.False,
|
||||
name: "pass_subnet",
|
||||
ip: netip.MustParseAddr("1.2.2.2"),
|
||||
}, {
|
||||
want: assert.True,
|
||||
wantRule: "2.2.2.0/8",
|
||||
name: "block_subnet",
|
||||
ip: netip.MustParseAddr("2.2.2.2"),
|
||||
want: assert.True,
|
||||
name: "block_subnet",
|
||||
ip: netip.MustParseAddr("2.2.2.2"),
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
blocked, rule := global.IsBlockedIP(tc.ip)
|
||||
blocked := global.IsBlockedIP(tc.ip)
|
||||
tc.want(t, blocked)
|
||||
assert.Equal(t, tc.wantRule, rule)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ func newBlockedHostEngine(rules []string) (e *blockedHostEngine) {
|
||||
}
|
||||
}
|
||||
|
||||
// isBlocked returns true if the req is blocked by this engine.
|
||||
// isBlocked returns true if the req is blocked by this engine. req must have
|
||||
// exactly one question.
|
||||
func (e *blockedHostEngine) isBlocked(req *dns.Msg) (blocked bool) {
|
||||
e.initOnce.Do(func() {
|
||||
start := time.Now()
|
||||
|
@ -131,7 +131,7 @@ func matchASNs(asns []geoip.ASN, l *geoip.Location) (ok bool) {
|
||||
}
|
||||
|
||||
// isBlockedByHostsEng returns true if the req is blocked by
|
||||
// BlocklistDomainRules.
|
||||
// BlocklistDomainRules. req must have exactly one question.
|
||||
func (p *DefaultProfile) isBlockedByHostsEng(req *dns.Msg) (blocked bool) {
|
||||
return p.blockedHostsEng.isBlocked(req)
|
||||
}
|
||||
|
@ -9,76 +9,9 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/netext"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/ameshkov/dnscrypt/v2"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Servers And Server Groups
|
||||
|
||||
// ServerGroup is a group of DNS servers all of which use the same filtering
|
||||
// settings.
|
||||
type ServerGroup struct {
|
||||
// TLS are the TLS settings for this server group. If Servers contains at
|
||||
// least one server with a non-plain protocol (see [Protocol.IsPlain]), TLS
|
||||
// must not be nil.
|
||||
TLS *TLS
|
||||
|
||||
// DDR is the configuration for the server group's Discovery Of Designated
|
||||
// Resolvers (DDR) handlers. DDR is never nil.
|
||||
DDR *DDR
|
||||
|
||||
// Name is the unique name of the server group.
|
||||
Name ServerGroupName
|
||||
|
||||
// FilteringGroup is the ID of the filtering group for this server.
|
||||
FilteringGroup FilteringGroupID
|
||||
|
||||
// Servers are the settings for servers. Each element must be non-nil.
|
||||
Servers []*Server
|
||||
}
|
||||
|
||||
// ServerGroupName is the name of a server group.
|
||||
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
|
||||
|
||||
// DeviceIDWildcards are the domain wildcards used to detect device IDs from
|
||||
// clients' server names.
|
||||
DeviceIDWildcards []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
|
||||
// Resolvers (DDR) handlers.
|
||||
type DDR struct {
|
||||
// DeviceTargets is the set of all domain names, subdomains of which should
|
||||
// be checked for DDR queries with device IDs.
|
||||
DeviceTargets *stringutil.Set
|
||||
|
||||
// PublicTargets is the set of all public domain names, DDR queries for
|
||||
// which should be processed.
|
||||
PublicTargets *stringutil.Set
|
||||
|
||||
// DeviceRecordTemplates are used to respond to DDR queries from recognized
|
||||
// devices.
|
||||
DeviceRecordTemplates []*dns.SVCB
|
||||
|
||||
// PubilcRecordTemplates are used to respond to DDR queries from
|
||||
// unrecognized devices.
|
||||
PublicRecordTemplates []*dns.SVCB
|
||||
|
||||
// Enabled shows if DDR queries are processed. If it is false, DDR domain
|
||||
// name queries receive an NXDOMAIN response.
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// Server represents a single DNS server. That is, an entity that binds to one
|
||||
// or more ports and serves DNS over a single protocol.
|
||||
type Server struct {
|
||||
@ -192,6 +125,24 @@ func (s *Server) BindsToInterfaces() (ok bool) {
|
||||
return len(s.bindData) > 0 && s.bindData[0].PrefixAddr != nil
|
||||
}
|
||||
|
||||
// BindDataPrefixes returns a slice of CIDR networks collected from the bind
|
||||
// data of this server.
|
||||
func (s *Server) BindDataPrefixes() (ps []netip.Prefix) {
|
||||
for _, bd := range s.bindData {
|
||||
var pref netip.Prefix
|
||||
if bd.PrefixAddr == nil {
|
||||
addr := bd.AddrPort.Addr()
|
||||
pref = netip.PrefixFrom(addr, addr.BitLen())
|
||||
} else {
|
||||
pref = bd.PrefixAddr.Prefix
|
||||
}
|
||||
|
||||
ps = append(ps, pref)
|
||||
}
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
// ServerBindData are the socket binding data for a server. Either AddrPort or
|
||||
// ListenConfig with PrefixAddr must be set.
|
||||
//
|
||||
|
@ -13,27 +13,31 @@ import (
|
||||
|
||||
// Common variables for tests.
|
||||
var (
|
||||
addrV4 = netip.MustParseAddr("1.2.3.4")
|
||||
bindDataAddrPortV4 = &agd.ServerBindData{
|
||||
AddrPort: netip.MustParseAddrPort("1.2.3.4:53"),
|
||||
AddrPort: netip.AddrPortFrom(addrV4, 53),
|
||||
}
|
||||
|
||||
addrV6 = netip.MustParseAddr("1234::cdef")
|
||||
bindDataAddrPortV6 = &agd.ServerBindData{
|
||||
AddrPort: netip.MustParseAddrPort("[1234::cdef]:53"),
|
||||
AddrPort: netip.AddrPortFrom(addrV6, 53),
|
||||
}
|
||||
|
||||
prefixV4 = netip.MustParsePrefix("1.2.3.0/24")
|
||||
bindDataIface = &agd.ServerBindData{
|
||||
ListenConfig: &agdtest.ListenConfig{},
|
||||
PrefixAddr: &agdnet.PrefixNetAddr{
|
||||
Prefix: netip.MustParsePrefix("1.2.3.0/24"),
|
||||
Prefix: prefixV4,
|
||||
Net: "",
|
||||
Port: 53,
|
||||
},
|
||||
}
|
||||
|
||||
singleIPPrefixV4 = netip.MustParsePrefix("1.2.3.4/32")
|
||||
bindDataIfaceSingleIP = &agd.ServerBindData{
|
||||
ListenConfig: &agdtest.ListenConfig{},
|
||||
PrefixAddr: &agdnet.PrefixNetAddr{
|
||||
Prefix: netip.MustParsePrefix("1.2.3.4/32"),
|
||||
Prefix: singleIPPrefixV4,
|
||||
Net: "",
|
||||
Port: 53,
|
||||
},
|
||||
@ -105,6 +109,41 @@ func TestServer_BindsToInterfaces(t *testing.T) {
|
||||
assert.True(t, s.BindsToInterfaces())
|
||||
}
|
||||
|
||||
func TestServer_BindDataPrefixes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
bindData *agd.ServerBindData
|
||||
name string
|
||||
want []netip.Prefix
|
||||
}{{
|
||||
bindData: bindDataAddrPortV4,
|
||||
want: []netip.Prefix{netip.PrefixFrom(addrV4, addrV4.BitLen())},
|
||||
name: "addr_port_v4",
|
||||
}, {
|
||||
bindData: bindDataAddrPortV6,
|
||||
want: []netip.Prefix{netip.PrefixFrom(addrV6, addrV6.BitLen())},
|
||||
name: "addr_port_v6",
|
||||
}, {
|
||||
bindData: bindDataIface,
|
||||
want: []netip.Prefix{prefixV4},
|
||||
name: "prefix",
|
||||
}, {
|
||||
bindData: bindDataIfaceSingleIP,
|
||||
want: []netip.Prefix{singleIPPrefixV4},
|
||||
name: "prefix_single_ip",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s := &agd.Server{}
|
||||
require.NotPanics(t, func() {
|
||||
s.SetBindData([]*agd.ServerBindData{tc.bindData})
|
||||
})
|
||||
|
||||
assert.Equal(t, tc.want, s.BindDataPrefixes())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_HasAddr(t *testing.T) {
|
||||
testCases := []struct {
|
||||
bindData *agd.ServerBindData
|
||||
|
158
internal/agd/servergroup.go
Normal file
158
internal/agd/servergroup.go
Normal file
@ -0,0 +1,158 @@
|
||||
package agd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// ServerGroup is a group of DNS servers all of which use the same filtering
|
||||
// settings.
|
||||
type ServerGroup struct {
|
||||
// BlockPageRedirect is the configuration for the server group's block page.
|
||||
// BlockPageRedirect is never nil.
|
||||
//
|
||||
// TODO(a.garipov): Use.
|
||||
BlockPageRedirect *BlockPageRedirect
|
||||
|
||||
// DDR is the configuration for the server group's Discovery Of Designated
|
||||
// Resolvers (DDR) handlers. DDR is never nil.
|
||||
DDR *DDR
|
||||
|
||||
// TLS are the TLS settings for this server group. If Servers contains at
|
||||
// least one server with a non-plain protocol (see [Protocol.IsPlain]), TLS
|
||||
// must not be nil.
|
||||
TLS *TLS
|
||||
|
||||
// Name is the unique name of the server group.
|
||||
Name ServerGroupName
|
||||
|
||||
// FilteringGroup is the ID of the filtering group for this server.
|
||||
FilteringGroup FilteringGroupID
|
||||
|
||||
// Servers are the settings for servers. Each element must be non-nil.
|
||||
Servers []*Server
|
||||
}
|
||||
|
||||
// ServerGroupName is the name of a server group.
|
||||
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
|
||||
|
||||
// DeviceIDWildcards are the domain wildcards used to detect device IDs from
|
||||
// clients' server names.
|
||||
DeviceIDWildcards []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
|
||||
// Resolvers (DDR) handlers.
|
||||
type DDR struct {
|
||||
// DeviceTargets is the set of all domain names, subdomains of which should
|
||||
// be checked for DDR queries with device IDs.
|
||||
DeviceTargets *stringutil.Set
|
||||
|
||||
// PublicTargets is the set of all public domain names, DDR queries for
|
||||
// which should be processed.
|
||||
PublicTargets *stringutil.Set
|
||||
|
||||
// DeviceRecordTemplates are used to respond to DDR queries from recognized
|
||||
// devices.
|
||||
DeviceRecordTemplates []*dns.SVCB
|
||||
|
||||
// PubilcRecordTemplates are used to respond to DDR queries from
|
||||
// unrecognized devices.
|
||||
PublicRecordTemplates []*dns.SVCB
|
||||
|
||||
// Enabled shows if DDR queries are processed. If it is false, DDR domain
|
||||
// name queries receive an NXDOMAIN response.
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// BlockPageRedirect is the configuration for a [ServerGroup]'s block page.
|
||||
type BlockPageRedirect struct {
|
||||
// Apply defines request parameters based on which the block page is shown
|
||||
// always. If a request matches Apply, both [BlockPageRedirect.Skip] and
|
||||
// [BlockPageRedirect.Probability] are ignored.
|
||||
//
|
||||
// If [BlockPageRedirect.Enabled] is true, Apply must not be nil.
|
||||
Apply *BlockPageRedirectApply
|
||||
|
||||
// Skip defines request parameters based on which the block page is not
|
||||
// shown, regardless of [BlockPageRedirect.Probability].
|
||||
//
|
||||
// If [BlockPageRedirect.Enabled] is true, Skip must not be nil.
|
||||
Skip *BlockPageRedirectSkip
|
||||
|
||||
// IPv4 are the IPv4 addresses of the block page, used to respond to A
|
||||
// queries.
|
||||
//
|
||||
// If [BlockPageRedirect.Enabled] is true, IPv4, [BlockPageRedirect.IPv6],
|
||||
// or both must be filled.
|
||||
IPv4 []netip.Addr
|
||||
|
||||
// IPv6 are the IPv6 addresses of the block page, used to respond to AAAA
|
||||
// queries.
|
||||
//
|
||||
// If [BlockPageRedirect.Enabled] is true, [BlockPageRedirect.IPv4], IPv6,
|
||||
// or both must be filled.
|
||||
IPv6 []netip.Addr
|
||||
|
||||
// Probability defines the probability of responding with the block page IPs
|
||||
// based on remote address. Probability must be between 0.0 and 1.0.
|
||||
Probability Probability
|
||||
|
||||
// Enabled defines whether the block-page feature is enabled.
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// Probability is a type for probabilities ranging from 0.0 to 1.0.
|
||||
type Probability float64
|
||||
|
||||
// NewProbability returns a properly converted Probability or an error.
|
||||
func NewProbability(f float64) (prob Probability, err error) {
|
||||
if math.IsNaN(f) || f < 0.0 || f > 1.0 {
|
||||
return 0, fmt.Errorf("probability must be between 0.0 and 1.0; got %v", f)
|
||||
}
|
||||
|
||||
return Probability(f), nil
|
||||
}
|
||||
|
||||
// MustNewProbability returns a properly converted Probability or panics with an
|
||||
// error.
|
||||
func MustNewProbability(f float64) (prob Probability) {
|
||||
prob, err := NewProbability(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return prob
|
||||
}
|
||||
|
||||
// BlockPageRedirectApply defines the conditions for applying the block-page
|
||||
// logic for a particular request.
|
||||
type BlockPageRedirectApply struct {
|
||||
// ClientSubnets are the subnets for which block page is always enabled.
|
||||
ClientSubnets []netip.Prefix
|
||||
}
|
||||
|
||||
// BlockPageRedirectSkip defines the conditions for skipping the block page
|
||||
// logic for a particular request.
|
||||
type BlockPageRedirectSkip struct {
|
||||
// ClientSubnets are the subnets for which block page is always disabled.
|
||||
ClientSubnets []netip.Prefix
|
||||
|
||||
// QuestionDomains are the domain names for which block page is always
|
||||
// disabled.
|
||||
QuestionDomains []string
|
||||
}
|
@ -4,8 +4,6 @@
|
||||
package agdnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -48,33 +46,6 @@ func AndroidMetricDomainReplacement(fqdn string) (repl string) {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ParseSubnets parses IP networks, including single-address ones, from strings.
|
||||
func ParseSubnets(strs ...string) (subnets []netip.Prefix, err error) {
|
||||
subnets = make([]netip.Prefix, len(strs))
|
||||
for i, s := range strs {
|
||||
// Detect if this is a CIDR or an IP early, so that the path to
|
||||
// returning an error is shorter.
|
||||
if strings.Contains(s, "/") {
|
||||
subnets[i], err = netip.ParsePrefix(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("subnet at idx %d: %w", i, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
var ip netip.Addr
|
||||
ip, err = netip.ParseAddr(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ip at idx %d: %w", i, err)
|
||||
}
|
||||
|
||||
subnets[i] = netip.PrefixFrom(ip, ip.BitLen())
|
||||
}
|
||||
|
||||
return subnets, nil
|
||||
}
|
||||
|
||||
// NormalizeDomain returns lowercased version of the host without the final dot.
|
||||
//
|
||||
// TODO(a.garipov): Move to golibs.
|
||||
|
@ -1,38 +1,7 @@
|
||||
// Package agdservice defines types and interfaces for long-running services.
|
||||
//
|
||||
// TODO(a.garipov): Move to golibs.
|
||||
// TODO(a.garipov): Move more to golibs.
|
||||
package agdservice
|
||||
|
||||
import "context"
|
||||
|
||||
// Interface is the interface for long-running services.
|
||||
//
|
||||
// TODO(a.garipov): Define whether or not a service should finish starting or
|
||||
// shutting down before returning from these methods.
|
||||
type Interface interface {
|
||||
// Start starts the service. ctx is used for cancelation.
|
||||
//
|
||||
// TODO(a.garipov): Use contexts with timeouts everywhere.
|
||||
Start(ctx context.Context) (err error)
|
||||
|
||||
// Shutdown gracefully stops the service. ctx is used to determine
|
||||
// a timeout before trying to stop the service less gracefully.
|
||||
//
|
||||
// TODO(a.garipov): Use contexts with timeouts everywhere.
|
||||
Shutdown(ctx context.Context) (err error)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Interface = Empty{}
|
||||
|
||||
// Empty is an [Interface] implementation that does nothing.
|
||||
type Empty struct{}
|
||||
|
||||
// Start implements the [Interface] interface for Empty.
|
||||
func (Empty) Start(_ context.Context) (err error) { return nil }
|
||||
|
||||
// Shutdown implements the [Interface] interface for Empty.
|
||||
func (Empty) Shutdown(_ context.Context) (err error) { return nil }
|
||||
|
||||
// unit is a convenient alias for struct{}.
|
||||
type unit = struct{}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"golang.org/x/exp/rand"
|
||||
)
|
||||
|
||||
@ -111,17 +112,17 @@ func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Interface = (*RefreshWorker)(nil)
|
||||
var _ service.Interface = (*RefreshWorker)(nil)
|
||||
|
||||
// Start implements the [Interface] interface for *RefreshWorker. err is always
|
||||
// nil.
|
||||
// Start implements the [service.Interface] interface for *RefreshWorker. err
|
||||
// is always nil.
|
||||
func (w *RefreshWorker) Start(_ context.Context) (err error) {
|
||||
go w.refreshInALoop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown implements the [Interface] interface for *RefreshWorker.
|
||||
// Shutdown implements the [service.Interface] interface for *RefreshWorker.
|
||||
func (w *RefreshWorker) Shutdown(ctx context.Context) (err error) {
|
||||
if w.refrOnShutdown {
|
||||
err = w.refr.Refresh(ctx)
|
||||
|
@ -39,7 +39,7 @@ var _ access.Interface = (*AccessManager)(nil)
|
||||
// AccessManager is a [access.Interface] for tests.
|
||||
type AccessManager struct {
|
||||
OnIsBlockedHost func(host string, qt uint16) (blocked bool)
|
||||
OnIsBlockedIP func(ip netip.Addr) (blocked bool, rule string)
|
||||
OnIsBlockedIP func(ip netip.Addr) (blocked bool)
|
||||
}
|
||||
|
||||
// IsBlockedHost implements the [access.Interface] interface for *AccessManager.
|
||||
@ -48,7 +48,7 @@ func (a *AccessManager) IsBlockedHost(host string, qt uint16) (blocked bool) {
|
||||
}
|
||||
|
||||
// IsBlockedIP implements the [access.Interface] interface for *AccessManager.
|
||||
func (a *AccessManager) IsBlockedIP(ip netip.Addr) (blocked bool, rule string) {
|
||||
func (a *AccessManager) IsBlockedIP(ip netip.Addr) (blocked bool) {
|
||||
return a.OnIsBlockedIP(ip)
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,10 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
@ -27,6 +29,9 @@ import (
|
||||
// ProfileStorageConfig is the configuration for the business logic backend
|
||||
// profile storage.
|
||||
type ProfileStorageConfig struct {
|
||||
// BindSet is the subnet set created from DNS servers listening addresses.
|
||||
BindSet netutil.SubnetSet
|
||||
|
||||
// ErrColl is the error collector that is used to collect critical and
|
||||
// non-critical errors.
|
||||
ErrColl errcoll.Interface
|
||||
@ -40,6 +45,7 @@ type ProfileStorageConfig struct {
|
||||
// that retrieves the profile and device information from the business logic
|
||||
// backend. It is safe for concurrent use.
|
||||
type ProfileStorage struct {
|
||||
bindSet netutil.SubnetSet
|
||||
errColl errcoll.Interface
|
||||
|
||||
// client is the current GRPC client.
|
||||
@ -56,6 +62,7 @@ func NewProfileStorage(c *ProfileStorageConfig) (s *ProfileStorage, err error) {
|
||||
}
|
||||
|
||||
return &ProfileStorage{
|
||||
bindSet: c.BindSet,
|
||||
client: client,
|
||||
errColl: c.ErrColl,
|
||||
}, nil
|
||||
@ -97,7 +104,7 @@ func (s *ProfileStorage) Profiles(
|
||||
stats.endRecv()
|
||||
|
||||
stats.startDec()
|
||||
prof, devices, profErr := profile.toInternal(ctx, time.Now(), s.errColl)
|
||||
prof, devices, profErr := profile.toInternal(ctx, time.Now(), s.bindSet, s.errColl)
|
||||
if profErr != nil {
|
||||
reportf(ctx, s.errColl, "loading profile: %w", profErr)
|
||||
|
||||
@ -140,6 +147,7 @@ func fixGRPCError(err error) (wErr error) {
|
||||
func (x *DNSProfile) toInternal(
|
||||
ctx context.Context,
|
||||
updTime time.Time,
|
||||
bindSet netutil.SubnetSet,
|
||||
errColl errcoll.Interface,
|
||||
) (profile *agd.Profile, devices []*agd.Device, err error) {
|
||||
if x == nil {
|
||||
@ -156,7 +164,7 @@ func (x *DNSProfile) toInternal(
|
||||
return nil, nil, fmt.Errorf("blocking mode: %w", err)
|
||||
}
|
||||
|
||||
devices, deviceIds := devicesToInternal(ctx, x.Devices, errColl)
|
||||
devices, deviceIds := devicesToInternal(ctx, x.Devices, bindSet, errColl)
|
||||
listsEnabled, listIDs := x.RuleLists.toInternal(ctx, errColl)
|
||||
|
||||
profID, err := agd.NewProfileID(x.DnsId)
|
||||
@ -384,6 +392,7 @@ func blockingModeToInternal(pbm isDNSProfile_BlockingMode) (m dnsmsg.BlockingMod
|
||||
func devicesToInternal(
|
||||
ctx context.Context,
|
||||
ds []*DeviceSettings,
|
||||
bindSet netutil.SubnetSet,
|
||||
errColl errcoll.Interface,
|
||||
) (out []*agd.Device, ids []agd.DeviceID) {
|
||||
l := len(ds)
|
||||
@ -393,9 +402,10 @@ func devicesToInternal(
|
||||
|
||||
out = make([]*agd.Device, 0, l)
|
||||
for _, d := range ds {
|
||||
dev, err := d.toInternal()
|
||||
dev, err := d.toInternal(bindSet)
|
||||
if err != nil {
|
||||
reportf(ctx, errColl, "invalid device settings: %w", err)
|
||||
metrics.DevicesInvalidTotal.Inc()
|
||||
|
||||
continue
|
||||
}
|
||||
@ -409,7 +419,7 @@ func devicesToInternal(
|
||||
|
||||
// toInternal is a helper that converts device settings from backend protobuf
|
||||
// response to AdGuard DNS device object.
|
||||
func (ds *DeviceSettings) toInternal() (dev *agd.Device, err error) {
|
||||
func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device, err error) {
|
||||
if ds == nil {
|
||||
return nil, fmt.Errorf("device is nil")
|
||||
}
|
||||
@ -426,6 +436,13 @@ func (ds *DeviceSettings) toInternal() (dev *agd.Device, err error) {
|
||||
return nil, fmt.Errorf("dedicated ips: %w", err)
|
||||
}
|
||||
|
||||
// TODO(d.kolyshev): Extract business logic validation.
|
||||
for _, addr := range dedicatedIPs {
|
||||
if !bindSet.Contains(addr) {
|
||||
return nil, fmt.Errorf("dedicated ip %q is not in bind data", addr)
|
||||
}
|
||||
}
|
||||
|
||||
id, err := agd.NewDeviceID(ds.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("device id: %s: %w", ds.Id, err)
|
||||
|
@ -30,6 +30,9 @@ const testProfileID agd.ProfileID = "prof1234"
|
||||
// TestUpdTime is the common update time for tests.
|
||||
var TestUpdTime = time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
// testBind includes any IPv4 address.
|
||||
var testBind = netip.MustParsePrefix("0.0.0.0/0")
|
||||
|
||||
func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -40,7 +43,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
got, gotDevices, err := NewTestDNSProfile(t).toInternal(ctx, TestUpdTime, errColl)
|
||||
got, gotDevices, err := NewTestDNSProfile(t).toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, newProfile(t), got)
|
||||
@ -57,18 +60,44 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
got, gotDevices, err := newDNSProfileWithBadData(t).toInternal(
|
||||
ctx,
|
||||
TestUpdTime,
|
||||
testBind,
|
||||
savingErrColl,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Error(t, errCollErr)
|
||||
testutil.AssertErrorMsg(t, "backendpb: invalid device settings:"+
|
||||
" dedicated ips: ip at index 0: unexpected slice size", errCollErr)
|
||||
|
||||
assert.Equal(t, newProfile(t), got)
|
||||
assert.Equal(t, newDevices(t), gotDevices)
|
||||
})
|
||||
|
||||
t.Run("invalid_device_ded_ip", func(t *testing.T) {
|
||||
var errCollErr error
|
||||
savingErrColl := &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, err error) {
|
||||
errCollErr = err
|
||||
},
|
||||
}
|
||||
|
||||
bindSet := netip.MustParsePrefix("2.2.2.2/32")
|
||||
got, gotDevices, err := NewTestDNSProfile(t).toInternal(
|
||||
ctx,
|
||||
TestUpdTime,
|
||||
bindSet,
|
||||
savingErrColl,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
testutil.AssertErrorMsg(t, "backendpb: invalid device settings:"+
|
||||
" dedicated ip \"1.1.1.2\" is not in bind data", errCollErr)
|
||||
|
||||
assert.NotEqual(t, newProfile(t), got)
|
||||
assert.NotEqual(t, newDevices(t), gotDevices)
|
||||
assert.Len(t, gotDevices, 1)
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
var emptyDNSProfile *DNSProfile
|
||||
_, _, err := emptyDNSProfile.toInternal(ctx, TestUpdTime, errColl)
|
||||
_, _, err := emptyDNSProfile.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "profile is nil", err)
|
||||
})
|
||||
|
||||
@ -78,7 +107,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
Deleted: true,
|
||||
}
|
||||
|
||||
got, gotDevices, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
got, gotDevices, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
|
||||
@ -91,7 +120,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
dp := NewTestDNSProfile(t)
|
||||
dp.Parental.Schedule.Tmz = "invalid"
|
||||
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "parental: schedule: loading timezone: unknown time zone invalid", err)
|
||||
})
|
||||
|
||||
@ -102,7 +131,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
End: nil,
|
||||
}
|
||||
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "parental: schedule: weekday Sunday: bad day range: end 0 less than start 16", err)
|
||||
})
|
||||
|
||||
@ -111,7 +140,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
bm := dp.BlockingMode.(*DNSProfile_BlockingModeCustomIp)
|
||||
bm.BlockingModeCustomIp.Ipv4 = []byte("1")
|
||||
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv4: unexpected slice size", err)
|
||||
})
|
||||
|
||||
@ -120,7 +149,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
bm := dp.BlockingMode.(*DNSProfile_BlockingModeCustomIp)
|
||||
bm.BlockingModeCustomIp.Ipv6 = []byte("1")
|
||||
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
||||
})
|
||||
|
||||
@ -128,7 +157,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
dp := NewTestDNSProfile(t)
|
||||
dp.BlockingMode = nil
|
||||
|
||||
got, gotDevices, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
got, gotDevices, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
|
||||
@ -143,7 +172,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
dp := NewTestDNSProfile(t)
|
||||
dp.Access = nil
|
||||
|
||||
got, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
got, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
|
||||
@ -157,7 +186,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
Enabled: false,
|
||||
}
|
||||
|
||||
got, _, err := dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
got, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
|
||||
@ -451,7 +480,7 @@ func BenchmarkDNSProfile_ToInternal(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
profSink, _, errSink = dp.toInternal(ctx, TestUpdTime, errColl)
|
||||
profSink, _, errSink = dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
}
|
||||
|
||||
require.NotNil(b, profSink)
|
||||
|
@ -1,8 +1,9 @@
|
||||
package backendpb_test
|
||||
|
||||
import (
|
||||
context "context"
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"testing"
|
||||
@ -52,6 +53,7 @@ func BenchmarkProfileStorage_Profiles(b *testing.B) {
|
||||
require.NoError(b, err)
|
||||
|
||||
s, err := backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
||||
BindSet: netip.MustParsePrefix("0.0.0.0/0"),
|
||||
ErrColl: errColl,
|
||||
Endpoint: &url.URL{
|
||||
Scheme: "grpc",
|
||||
|
@ -106,6 +106,9 @@ func (c *chanPacketConn) LocalAddr() (addr net.Addr) { return c.laddr }
|
||||
// *chanPacketConn.
|
||||
func (c *chanPacketConn) ReadFrom(b []byte) (n int, raddr net.Addr, err error) {
|
||||
n, sess, err := c.readFromSession(b, "ReadFrom")
|
||||
if sess == nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return n, sess.RemoteAddr(), err
|
||||
}
|
||||
@ -121,6 +124,13 @@ func (c *chanPacketConn) readFromSession(
|
||||
b []byte,
|
||||
fnName string,
|
||||
) (n int, s netext.PacketSession, err error) {
|
||||
var sess *packetSession
|
||||
defer func() {
|
||||
if sess != nil {
|
||||
n = copy(b, sess.readBody)
|
||||
}
|
||||
}()
|
||||
|
||||
var deadline time.Time
|
||||
func() {
|
||||
c.deadlineMu.RLock()
|
||||
@ -137,16 +147,19 @@ func (c *chanPacketConn) readFromSession(
|
||||
}
|
||||
defer stopTimer()
|
||||
|
||||
sess, err := receiveWithTimer(c.sessions, timerCh)
|
||||
sess, err = receiveWithTimer(c.sessions, timerCh)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("receiving: %w", err)
|
||||
|
||||
return 0, nil, wrapConnError(tnChanPConn, fnName, c.laddr, err)
|
||||
// Prevent netext.PacketSession((*packetSession)(nil)).
|
||||
if sess != nil {
|
||||
s = sess
|
||||
}
|
||||
|
||||
return 0, s, wrapConnError(tnChanPConn, fnName, c.laddr, err)
|
||||
}
|
||||
|
||||
n = copy(b, sess.readBody)
|
||||
|
||||
return n, sess, nil
|
||||
return 0, sess, nil
|
||||
}
|
||||
|
||||
// timerFromDeadline converts a deadline value into a timer channel. stopTimer
|
||||
|
@ -10,12 +10,12 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/netext"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/mapsutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/syncutil"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
@ -211,12 +211,12 @@ func (m *Manager) validateIfaceSubnet(ifaceName string, subnet netip.Prefix) (er
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ agdservice.Interface = (*Manager)(nil)
|
||||
var _ service.Interface = (*Manager)(nil)
|
||||
|
||||
// Start implements the [agdservice.Interface] interface for *Manager. If m is
|
||||
// Start implements the [service.Interface] interface for *Manager. If m is
|
||||
// nil, Start returns nil, since this feature is optional.
|
||||
//
|
||||
// TODO(a.garipov): Consider an interface solution.
|
||||
// TODO(a.garipov): Consider an interface solution instead of the nil exception.
|
||||
//
|
||||
// TODO(a.garipov): Use the context for cancelation.
|
||||
func (m *Manager) Start(_ context.Context) (err error) {
|
||||
@ -249,12 +249,15 @@ func (m *Manager) Start(_ context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown implements the [agdservice.Interface] interface for *Manager. If m
|
||||
// is nil, Shutdown returns nil, since this feature is optional.
|
||||
//
|
||||
// TODO(a.garipov): Consider an interface solution.
|
||||
// Shutdown implements the [service.Interface] interface for *Manager. Shutdown
|
||||
// does not actually wait for all sockets to close. If m is nil, Shutdown
|
||||
// returns nil, since this feature is optional.
|
||||
//
|
||||
// TODO(a.garipov): Consider waiting for all sockets to close.
|
||||
//
|
||||
// TODO(a.garipov): Use the context for cancelation.
|
||||
//
|
||||
// TODO(a.garipov): Consider an interface solution instead of the nil exception.
|
||||
func (m *Manager) Shutdown(_ context.Context) (err error) {
|
||||
if m == nil {
|
||||
return nil
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
)
|
||||
|
||||
// Manager creates individual listeners and dispatches connections to them.
|
||||
@ -43,9 +43,9 @@ func (m *Manager) ListenConfig(id ID, subnet netip.Prefix) (c *ListenConfig, err
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ agdservice.Interface = (*Manager)(nil)
|
||||
var _ service.Interface = (*Manager)(nil)
|
||||
|
||||
// Start implements the [agdservice.Interface] interface for *Manager. If m is
|
||||
// Start implements the [service.Interface] interface for *Manager. If m is
|
||||
// nil, Start returns nil, since this feature is optional.
|
||||
//
|
||||
// It is only supported on Linux.
|
||||
@ -57,8 +57,8 @@ func (m *Manager) Start(_ context.Context) (err error) {
|
||||
return fmt.Errorf("bindtodevice: starting: %w; only supported on linux", errors.ErrUnsupported)
|
||||
}
|
||||
|
||||
// Shutdown implements the [agdservice.Interface] interface for *Manager. If m
|
||||
// is nil, Shutdown returns nil, since this feature is optional.
|
||||
// Shutdown implements the [service.Interface] interface for *Manager. If m is
|
||||
// nil, Shutdown returns nil, since this feature is optional.
|
||||
//
|
||||
// It is only supported on Linux.
|
||||
func (m *Manager) Shutdown(_ context.Context) (err error) {
|
||||
|
@ -1,8 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
)
|
||||
|
||||
// accessConfig is the configuration that controls IP and hosts blocking.
|
||||
@ -11,7 +10,7 @@ type accessConfig struct {
|
||||
BlockedQuestionDomains []string `yaml:"blocked_question_domains"`
|
||||
|
||||
// BlockedClientSubnets is a list of IP addresses or subnets to block.
|
||||
BlockedClientSubnets []string `yaml:"blocked_client_subnets"`
|
||||
BlockedClientSubnets []netutil.Prefix `yaml:"blocked_client_subnets"`
|
||||
}
|
||||
|
||||
// validate returns an error if the access configuration is invalid.
|
||||
@ -20,21 +19,5 @@ func (a *accessConfig) validate() (err error) {
|
||||
return errNilConfig
|
||||
}
|
||||
|
||||
for i, s := range a.BlockedClientSubnets {
|
||||
// TODO(a.garipov): Use [netutil.ParseSubnet] after refactoring it to
|
||||
// [netip.Addr].
|
||||
_, parseErr := netip.ParseAddr(s)
|
||||
if parseErr == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
_, parseErr = netip.ParsePrefix(s)
|
||||
if parseErr == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return fmt.Errorf("value %q at index %d: bad ip or cidr: %w", s, i, parseErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -3,14 +3,18 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"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/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
@ -67,17 +71,22 @@ func (c *backendConfig) validate() (err error) {
|
||||
// handler.
|
||||
func setupBackend(
|
||||
conf *backendConfig,
|
||||
grps []*agd.ServerGroup,
|
||||
envs *environments,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (profDB *profiledb.Default, rec *billstat.RuntimeRecorder, err error) {
|
||||
) (profDB profiledb.Interface, rec billstat.Recorder, err error) {
|
||||
if !envs.ProfilesEnabled {
|
||||
return &profiledb.Disabled{}, billstat.EmptyRecorder{}, nil
|
||||
}
|
||||
|
||||
rec, err = setupBillStat(conf, envs, sigHdlr, errColl)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
profDB, err = setupProfDB(conf, envs, sigHdlr, errColl)
|
||||
profDB, err = setupProfDB(conf, grps, envs, sigHdlr, errColl)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return nil, nil, err
|
||||
@ -91,7 +100,7 @@ func setupBackend(
|
||||
func setupBillStat(
|
||||
conf *backendConfig,
|
||||
envs *environments,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (rec *billstat.RuntimeRecorder, err error) {
|
||||
apiURL := netutil.CloneURL(&envs.BillStatURL.URL)
|
||||
@ -124,7 +133,7 @@ func setupBillStat(
|
||||
return nil, fmt.Errorf("starting bill stat recorder refresher: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(billStatRefr)
|
||||
sigHdlr.Add(billStatRefr)
|
||||
|
||||
return rec, nil
|
||||
}
|
||||
@ -133,12 +142,14 @@ func setupBillStat(
|
||||
// registers its refresher in the signal handler.
|
||||
func setupProfDB(
|
||||
conf *backendConfig,
|
||||
grps []*agd.ServerGroup,
|
||||
envs *environments,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (profDB *profiledb.Default, err error) {
|
||||
apiURL := netutil.CloneURL(&envs.ProfilesURL.URL)
|
||||
profStrg, err := setupProfStorage(apiURL, errColl)
|
||||
bindSet := collectBindSubnetSet(grps)
|
||||
profStrg, err := setupProfStorage(apiURL, bindSet, errColl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating profile storage: %w", err)
|
||||
}
|
||||
@ -174,11 +185,40 @@ func setupProfDB(
|
||||
return nil, fmt.Errorf("starting default profile database refresher: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(profDBRefr)
|
||||
sigHdlr.Add(profDBRefr)
|
||||
|
||||
return profDB, nil
|
||||
}
|
||||
|
||||
// collectBindSubnetSet returns a subnet set with IP addresses of servers in the
|
||||
// provided server groups grps.
|
||||
func collectBindSubnetSet(grps []*agd.ServerGroup) (s netutil.SubnetSet) {
|
||||
var serverPrefixes []netip.Prefix
|
||||
allSingleIP := true
|
||||
for _, grp := range grps {
|
||||
for _, srv := range grp.Servers {
|
||||
for _, p := range srv.BindDataPrefixes() {
|
||||
allSingleIP = allSingleIP && p.IsSingleIP()
|
||||
serverPrefixes = append(serverPrefixes, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In cases where an installation only has single-IP prefixes in bind
|
||||
// interfaces, or no bind interfaces at all, only check the dedicated IPs in
|
||||
// profiles for validity.
|
||||
//
|
||||
// TODO(a.garipov): Do not load profiles on such installations at all, as
|
||||
// they don't really need them. See AGDNS-1888.
|
||||
if allSingleIP {
|
||||
log.Info("warning: all bind ifaces are single-ip; only checking validity of dedicated ips")
|
||||
|
||||
return netutil.SubnetSetFunc(netip.Addr.IsValid)
|
||||
}
|
||||
|
||||
return netutil.SliceSubnetSet(serverPrefixes)
|
||||
}
|
||||
|
||||
// Backend API URL schemes.
|
||||
const (
|
||||
schemeGRPC = "grpc"
|
||||
@ -189,11 +229,13 @@ const (
|
||||
// provided API URL.
|
||||
func setupProfStorage(
|
||||
apiURL *url.URL,
|
||||
bindSet netutil.SubnetSet,
|
||||
errColl errcoll.Interface,
|
||||
) (s profiledb.Storage, err error) {
|
||||
scheme := apiURL.Scheme
|
||||
if scheme == schemeGRPC || scheme == schemeGRPCS {
|
||||
return backendpb.NewProfileStorage(&backendpb.ProfileStorageConfig{
|
||||
BindSet: bindSet,
|
||||
Endpoint: apiURL,
|
||||
ErrColl: errColl,
|
||||
})
|
||||
|
@ -24,6 +24,9 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/websvc"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
@ -41,7 +44,8 @@ func Main() {
|
||||
envs, err := readEnvs()
|
||||
check(err)
|
||||
|
||||
envs.configureLogs()
|
||||
// TODO(a.garipov): Use slog everywhere.
|
||||
slogLogger := envs.configureLogs()
|
||||
|
||||
// Signal service startup now that we have the logs set up.
|
||||
log.Info("main: starting adguard dns")
|
||||
@ -70,7 +74,9 @@ func Main() {
|
||||
|
||||
// Signal handler
|
||||
|
||||
sigHdlr := newSignalHandler()
|
||||
sigHdlr := service.NewSignalHandler(&service.SignalHandlerConfig{
|
||||
Logger: slogLogger.With(slogutil.KeyPrefix, service.SignalHandlerPrefix),
|
||||
})
|
||||
|
||||
// GeoIP database
|
||||
|
||||
@ -160,7 +166,7 @@ func Main() {
|
||||
|
||||
accessGlobal, err := access.NewGlobal(
|
||||
c.Access.BlockedQuestionDomains,
|
||||
c.Access.BlockedClientSubnets,
|
||||
netutil.UnembedPrefixes(c.Access.BlockedClientSubnets),
|
||||
)
|
||||
check(err)
|
||||
|
||||
@ -180,12 +186,14 @@ func Main() {
|
||||
srvGrps, err := c.ServerGroups.toInternal(messages, btdMgr, fltGroups, c.RateLimit, c.DNS)
|
||||
check(err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Start the bind-to-device manager here, now that no further calls to
|
||||
// btdMgr.ListenConfig are required.
|
||||
err = btdMgr.Start(context.Background())
|
||||
err = btdMgr.Start(ctx)
|
||||
check(err)
|
||||
|
||||
sigHdlr.add(btdMgr)
|
||||
sigHdlr.Add(btdMgr)
|
||||
|
||||
// TLS keys logging
|
||||
|
||||
@ -202,7 +210,7 @@ func Main() {
|
||||
|
||||
// Profiles database and billing statistics
|
||||
|
||||
profDB, billStatRec, err := setupBackend(c.Backend, envs, sigHdlr, errColl)
|
||||
profDB, billStatRec, err := setupBackend(c.Backend, srvGrps, envs, sigHdlr, errColl)
|
||||
check(err)
|
||||
|
||||
// DNS checker
|
||||
@ -230,7 +238,7 @@ func Main() {
|
||||
// Wait for long-running GeoIP initialization.
|
||||
check(<-geoIPErrCh)
|
||||
|
||||
sigHdlr.add(geoIPRefr)
|
||||
sigHdlr.Add(geoIPRefr)
|
||||
|
||||
// Web service
|
||||
|
||||
@ -240,9 +248,9 @@ func Main() {
|
||||
webSvc := websvc.New(webConf)
|
||||
// The web service is considered critical, so its Start method panics
|
||||
// instead of returning an error.
|
||||
_ = webSvc.Start(context.Background())
|
||||
_ = webSvc.Start(ctx)
|
||||
|
||||
sigHdlr.add(webSvc)
|
||||
sigHdlr.Add(webSvc)
|
||||
|
||||
// DNS service
|
||||
|
||||
@ -284,6 +292,7 @@ func Main() {
|
||||
CacheMinTTL: c.Cache.TTLOverride.Min.Duration,
|
||||
UseCacheTTLOverride: c.Cache.TTLOverride.Enabled,
|
||||
UseECSCache: c.Cache.Type == cacheTypeECS,
|
||||
ProfileDBEnabled: bool(envs.ProfilesEnabled),
|
||||
ResearchMetrics: bool(envs.ResearchMetrics),
|
||||
ResearchLogs: bool(envs.ResearchLogs),
|
||||
}
|
||||
@ -297,16 +306,16 @@ func Main() {
|
||||
check(err)
|
||||
|
||||
upstreamHealthcheckUpd := newUpstreamHealthcheck(handler, c.Upstream, errColl)
|
||||
err = upstreamHealthcheckUpd.Start(context.Background())
|
||||
err = upstreamHealthcheckUpd.Start(ctx)
|
||||
check(err)
|
||||
|
||||
sigHdlr.add(upstreamHealthcheckUpd)
|
||||
sigHdlr.Add(upstreamHealthcheckUpd)
|
||||
|
||||
// The DNS service is considered critical, so its Start method panics
|
||||
// instead of returning an error.
|
||||
_ = dnsSvc.Start(context.Background())
|
||||
_ = dnsSvc.Start(ctx)
|
||||
|
||||
sigHdlr.add(dnsSvc)
|
||||
sigHdlr.Add(dnsSvc)
|
||||
|
||||
// Debug HTTP-service
|
||||
|
||||
@ -314,9 +323,9 @@ func Main() {
|
||||
|
||||
// The debug HTTP service is considered critical, so its Start method panics
|
||||
// instead of returning an error.
|
||||
_ = debugSvc.Start(context.Background())
|
||||
_ = debugSvc.Start(ctx)
|
||||
|
||||
sigHdlr.add(debugSvc)
|
||||
sigHdlr.Add(debugSvc)
|
||||
|
||||
// Signal that the server is started.
|
||||
metrics.SetUpGauge(
|
||||
@ -327,7 +336,7 @@ func Main() {
|
||||
runtime.Version(),
|
||||
)
|
||||
|
||||
os.Exit(sigHdlr.handle())
|
||||
os.Exit(sigHdlr.Handle(ctx))
|
||||
}
|
||||
|
||||
// collectPanics reports all panics in Main. It should be called in a defer.
|
||||
|
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -16,8 +17,10 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/rulestat"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/caarlos0/env/v7"
|
||||
"github.com/getsentry/sentry-go"
|
||||
)
|
||||
@ -56,6 +59,7 @@ type environments struct {
|
||||
|
||||
LogTimestamp strictBool `env:"LOG_TIMESTAMP" envDefault:"1"`
|
||||
LogVerbose strictBool `env:"VERBOSE" envDefault:"0"`
|
||||
ProfilesEnabled strictBool `env:"PROFILES_ENABLED" envDefault:"1"`
|
||||
ResearchMetrics strictBool `env:"RESEARCH_METRICS" envDefault:"0"`
|
||||
ResearchLogs strictBool `env:"RESEARCH_LOGS" envDefault:"0"`
|
||||
}
|
||||
@ -71,8 +75,9 @@ func readEnvs() (envs *environments, err error) {
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
// configureLogs sets the configuration for the plain text logs.
|
||||
func (envs *environments) configureLogs() {
|
||||
// configureLogs sets the configuration for the plain text logs. It also
|
||||
// returns a [slog.Logger] for code that uses it.
|
||||
func (envs *environments) configureLogs() (slogLogger *slog.Logger) {
|
||||
var flags int
|
||||
if envs.LogTimestamp {
|
||||
flags = log.LstdFlags | log.Lmicroseconds
|
||||
@ -83,6 +88,13 @@ func (envs *environments) configureLogs() {
|
||||
if envs.LogVerbose {
|
||||
log.SetLevel(log.DEBUG)
|
||||
}
|
||||
|
||||
return slogutil.New(&slogutil.Config{
|
||||
Output: os.Stdout,
|
||||
Format: slogutil.FormatAdGuardLegacy,
|
||||
AddTimestamp: bool(envs.LogTimestamp),
|
||||
Verbose: bool(envs.LogVerbose),
|
||||
})
|
||||
}
|
||||
|
||||
// buildErrColl builds and returns an error collector from environment.
|
||||
@ -158,7 +170,7 @@ func (envs *environments) debugConf(dnsDB dnsdb.Interface) (conf *debugsvc.Confi
|
||||
// buildRuleStat returns a filtering rule statistics collector from environment and
|
||||
// registers its refresher in sigHdlr, if necessary.
|
||||
func (envs *environments) buildRuleStat(
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (r rulestat.Interface, err error) {
|
||||
if envs.RuleStatURL == nil {
|
||||
@ -187,7 +199,7 @@ func (envs *environments) buildRuleStat(
|
||||
return nil, fmt.Errorf("starting rulestat refresher: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(refr)
|
||||
sigHdlr.Add(refr)
|
||||
|
||||
return httpRuleStat, nil
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/c2h5oh/datasize"
|
||||
)
|
||||
@ -136,7 +137,7 @@ func (c *fltRuleListCache) validate() (err error) {
|
||||
// registers its refresher in the signal handler.
|
||||
func setupFilterStorage(
|
||||
conf *filter.DefaultStorageConfig,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
refreshTimeout time.Duration,
|
||||
) (strg *filter.DefaultStorage, err error) {
|
||||
@ -162,7 +163,7 @@ func setupFilterStorage(
|
||||
return nil, fmt.Errorf("starting default filter storage update: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(refr)
|
||||
sigHdlr.Add(refr)
|
||||
|
||||
return strg, nil
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ func (c *interfaceListenersConfig) toInternal(
|
||||
return errors.Annotate(m.Add(id, l.Interface, l.Port, ctrlConf), "adding listener %q: %w", id)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/connlimiter"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
||||
@ -13,6 +12,8 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/c2h5oh/datasize"
|
||||
)
|
||||
@ -64,7 +65,7 @@ type rateLimitConfig struct {
|
||||
// allowListConfig is the consul allow list configuration.
|
||||
type allowListConfig struct {
|
||||
// List contains IPs and CIDRs.
|
||||
List []string `yaml:"list"`
|
||||
List []netutil.Prefix `yaml:"list"`
|
||||
|
||||
// RefreshIvl time between two updates of allow list from the Consul URL.
|
||||
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
||||
@ -138,14 +139,10 @@ func (c *rateLimitConfig) validate() (err error) {
|
||||
func setupRateLimiter(
|
||||
conf *rateLimitConfig,
|
||||
consulAllowlist *url.URL,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (rateLimiter *ratelimit.Backoff, connLimiter *connlimiter.Limiter, err error) {
|
||||
allowSubnets, err := agdnet.ParseSubnets(conf.Allowlist.List...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("parsing allowlist subnets: %w", err)
|
||||
}
|
||||
|
||||
allowSubnets := netutil.UnembedPrefixes(conf.Allowlist.List)
|
||||
allowlist := ratelimit.NewDynamicAllowlist(allowSubnets, nil)
|
||||
refresher, err := consul.NewAllowlistRefresher(allowlist, consulAllowlist)
|
||||
if err != nil {
|
||||
@ -168,7 +165,7 @@ func setupRateLimiter(
|
||||
return nil, nil, fmt.Errorf("starting allowlist refresher: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(refr)
|
||||
sigHdlr.Add(refr)
|
||||
|
||||
return ratelimit.NewBackoff(conf.toInternal(allowlist)), conf.ConnectionLimit.toInternal(), nil
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
@ -99,7 +100,7 @@ func setupHashPrefixFilter(
|
||||
url *urlutil.URL,
|
||||
cachePath string,
|
||||
maxSize uint64,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (strg *hashprefix.Storage, flt *hashprefix.Filter, err error) {
|
||||
fltConf, err := conf.toInternal(errColl, resolver, cloner, id, url, cachePath, maxSize)
|
||||
@ -127,7 +128,7 @@ func setupHashPrefixFilter(
|
||||
return nil, nil, fmt.Errorf("starting refresher for hash prefix filter %s: %w", id, err)
|
||||
}
|
||||
|
||||
sigHdlr.add(refr)
|
||||
sigHdlr.Add(refr)
|
||||
|
||||
return fltConf.Hashes, flt, nil
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
|
||||
@ -39,10 +41,11 @@ func (srvGrps serverGroups) toInternal(
|
||||
}
|
||||
|
||||
svcSrvGrps[i] = &agd.ServerGroup{
|
||||
TLS: tlsConf,
|
||||
DDR: g.DDR.toInternal(messages),
|
||||
Name: agd.ServerGroupName(g.Name),
|
||||
FilteringGroup: fltGrpID,
|
||||
BlockPageRedirect: g.BlockPageRedirect.toInternal(),
|
||||
DDR: g.DDR.toInternal(messages),
|
||||
TLS: tlsConf,
|
||||
Name: agd.ServerGroupName(g.Name),
|
||||
FilteringGroup: fltGrpID,
|
||||
}
|
||||
|
||||
svcSrvGrps[i].Servers, err = g.Servers.toInternal(tlsConf, btdMgr, ratelimitConf, dnsConf)
|
||||
@ -83,13 +86,16 @@ func (srvGrps serverGroups) validate() (err error) {
|
||||
// TODO(a.garipov): Think about more consistent naming, since this object is a
|
||||
// configuration, but it also stores other configurations.
|
||||
type serverGroup struct {
|
||||
// TLS are the TLS settings for this server, if any.
|
||||
TLS *tlsConfig `yaml:"tls"`
|
||||
// BlockPageRedirect is the configuration for the server group's block page.
|
||||
BlockPageRedirect *serverGroupBlockPageConfig `yaml:"block_page_redirect"`
|
||||
|
||||
// DDR is the Discovery Of Designated Resolvers (DDR) configuration for this
|
||||
// server group.
|
||||
DDR *ddrConfig `yaml:"ddr"`
|
||||
|
||||
// TLS are the TLS settings for this server, if any.
|
||||
TLS *tlsConfig `yaml:"tls"`
|
||||
|
||||
// Name is the unique name of the server group.
|
||||
Name string `yaml:"name"`
|
||||
|
||||
@ -111,6 +117,11 @@ func (g *serverGroup) validate() (err error) {
|
||||
return errors.Error("no filtering_group")
|
||||
}
|
||||
|
||||
err = g.BlockPageRedirect.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("block_page_redirect: %w", err)
|
||||
}
|
||||
|
||||
err = g.DDR.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("ddr: %w", err)
|
||||
@ -128,3 +139,255 @@ func (g *serverGroup) validate() (err error) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serverGroupBlockPageConfig is the configuration for a [serverGroup]'s block
|
||||
// page. See [agd.BlockPageRedirect] and the related types for more
|
||||
// documentation and contracts.
|
||||
type serverGroupBlockPageConfig struct {
|
||||
// Apply defines request parameters based on which the block page is always
|
||||
// shown.
|
||||
Apply *serverGroupBlockPageApplyConfig `yaml:"apply"`
|
||||
|
||||
// Skip defines request parameters based on which the block page is never
|
||||
// shown, regardless of the probability.
|
||||
Skip *serverGroupBlockPageSkipConfig `yaml:"skip"`
|
||||
|
||||
// IPv4 are the IPv4 records of the block page, used to respond to A
|
||||
// queries.
|
||||
IPv4 []*serverGroupBlockPageRecord `yaml:"ipv4"`
|
||||
|
||||
// IPv6 are the IPv6 records of the block page, used to respond to AAAA
|
||||
// queries.
|
||||
IPv6 []*serverGroupBlockPageRecord `yaml:"ipv6"`
|
||||
|
||||
// Probability defines the probability of responding with the block page IPs
|
||||
// based on remote address.
|
||||
Probability float64 `yaml:"probability"`
|
||||
|
||||
// Enabled defines whether the block-page feature is enabled.
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
// toInternal returns the block-page redirect configuration for a server group.
|
||||
// c is assumed to be valid.
|
||||
func (c *serverGroupBlockPageConfig) toInternal() (conf *agd.BlockPageRedirect) {
|
||||
if !c.Enabled {
|
||||
return &agd.BlockPageRedirect{}
|
||||
}
|
||||
|
||||
var ipv4 []netip.Addr
|
||||
for _, r := range c.IPv4 {
|
||||
ipv4 = append(ipv4, r.Address)
|
||||
}
|
||||
|
||||
var ipv6 []netip.Addr
|
||||
for _, r := range c.IPv6 {
|
||||
ipv6 = append(ipv6, r.Address)
|
||||
}
|
||||
|
||||
return &agd.BlockPageRedirect{
|
||||
Apply: c.Apply.toInternal(),
|
||||
Skip: c.Skip.toInternal(),
|
||||
IPv4: ipv4,
|
||||
IPv6: ipv6,
|
||||
Probability: agd.MustNewProbability(c.Probability),
|
||||
Enabled: c.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// validate returns an error if the block-page redirect configuration is
|
||||
// invalid.
|
||||
func (c *serverGroupBlockPageConfig) validate() (err error) {
|
||||
switch {
|
||||
case c == nil:
|
||||
return errNilConfig
|
||||
case !c.Enabled:
|
||||
return nil
|
||||
case len(c.IPv4) == 0 && len(c.IPv6) == 0:
|
||||
return errors.Error("ipv4, ipv6, or both must be set")
|
||||
}
|
||||
|
||||
_, err = agd.NewProbability(c.Probability)
|
||||
if err != nil {
|
||||
return fmt.Errorf("probability: %w", err)
|
||||
}
|
||||
|
||||
err = c.validateAddrs()
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Apply.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("apply: %w", err)
|
||||
}
|
||||
|
||||
err = c.Skip.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("skip: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateAddrs returns an error if the block-page redirect if the IP addresses
|
||||
// in the block-page redirect configuration are invalid.
|
||||
func (c *serverGroupBlockPageConfig) validateAddrs() (err error) {
|
||||
for i, r := range c.IPv4 {
|
||||
err = r.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("ipv4: at index %d: address: %w", i, err)
|
||||
} else if !r.Address.Is4() {
|
||||
return fmt.Errorf("ipv4: at index %d: address: not ipv4: %v", i, r.Address)
|
||||
}
|
||||
}
|
||||
|
||||
for i, r := range c.IPv6 {
|
||||
err = r.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("ipv6: at index %d: %w", i, err)
|
||||
} else if !r.Address.Is6() {
|
||||
return fmt.Errorf("ipv6: at index %d: address: not ipv6: %v", i, r.Address)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serverGroupBlockPageRecord is a structure for defining answer records in
|
||||
// [serverGroupBlockPageConfig].
|
||||
type serverGroupBlockPageRecord struct {
|
||||
Address netip.Addr `yaml:"address"`
|
||||
}
|
||||
|
||||
// validate returns an error if the record configuration is invalid.
|
||||
func (c *serverGroupBlockPageRecord) validate() (err error) {
|
||||
switch {
|
||||
case c == nil:
|
||||
return errNilConfig
|
||||
case !c.Address.IsValid():
|
||||
return errors.Error("invalid addr")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// serverGroupBlockPageApplyConfig defines the conditions for applying the
|
||||
// block-page logic for a particular request.
|
||||
type serverGroupBlockPageApplyConfig struct {
|
||||
// Client are the parameters for clients for which block page is always
|
||||
// enabled.
|
||||
Client []*serverGroupBlockPageClientConfig `yaml:"client"`
|
||||
}
|
||||
|
||||
// toInternal returns the block-page redirect applying configuration for a
|
||||
// server group. c is assumed to be valid.
|
||||
func (c *serverGroupBlockPageApplyConfig) toInternal() (conf *agd.BlockPageRedirectApply) {
|
||||
var subnets []netip.Prefix
|
||||
for _, cli := range c.Client {
|
||||
subnets = append(subnets, cli.Address.Prefix)
|
||||
}
|
||||
|
||||
return &agd.BlockPageRedirectApply{
|
||||
ClientSubnets: subnets,
|
||||
}
|
||||
}
|
||||
|
||||
// validate returns an error if the block-page redirect applying configuration
|
||||
// is invalid.
|
||||
func (c *serverGroupBlockPageApplyConfig) validate() (err error) {
|
||||
if c == nil {
|
||||
return errNilConfig
|
||||
}
|
||||
|
||||
for i, cli := range c.Client {
|
||||
err = cli.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("client: at index %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serverGroupBlockPageClientConfig is a common structure for defining clients
|
||||
// in [serverGroupBlockPageSkipConfig] and [serverGroupBlockPageApplyConfig].
|
||||
type serverGroupBlockPageClientConfig struct {
|
||||
Address netutil.Prefix `yaml:"address"`
|
||||
}
|
||||
|
||||
// validate returns an error if the client configuration is invalid.
|
||||
func (c *serverGroupBlockPageClientConfig) validate() (err error) {
|
||||
switch {
|
||||
case c == nil:
|
||||
return errNilConfig
|
||||
case !c.Address.IsValid():
|
||||
return errors.Error("invalid addr")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// serverGroupBlockPageSkipConfig defines the conditions for skipping the block
|
||||
// page logic for a particular request.
|
||||
type serverGroupBlockPageSkipConfig struct {
|
||||
// Client are the parameters for clients for which block page is always
|
||||
// disabled.
|
||||
Client []*serverGroupBlockPageClientConfig `yaml:"client"`
|
||||
|
||||
// QuestionDomains are the parameters for request questions for which block
|
||||
// page is always disabled.
|
||||
Question []*serverGroupBlockPageQuestionConfig `yaml:"question"`
|
||||
}
|
||||
|
||||
// toInternal returns the block-page redirect skipping configuration for a
|
||||
// server group. c is assumed to be valid.
|
||||
func (c *serverGroupBlockPageSkipConfig) toInternal() (conf *agd.BlockPageRedirectSkip) {
|
||||
var subnets []netip.Prefix
|
||||
for _, cli := range c.Client {
|
||||
subnets = append(subnets, cli.Address.Prefix)
|
||||
}
|
||||
|
||||
var domains []string
|
||||
for _, q := range c.Question {
|
||||
domains = append(domains, q.Domain)
|
||||
}
|
||||
|
||||
return &agd.BlockPageRedirectSkip{
|
||||
ClientSubnets: subnets,
|
||||
QuestionDomains: domains,
|
||||
}
|
||||
}
|
||||
|
||||
// validate returns an error if the block-page redirect skipping configuration
|
||||
// is invalid.
|
||||
func (c *serverGroupBlockPageSkipConfig) validate() (err error) {
|
||||
if c == nil {
|
||||
return errNilConfig
|
||||
}
|
||||
|
||||
for i, cli := range c.Client {
|
||||
err = cli.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("client: at index %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
for i, q := range c.Question {
|
||||
switch {
|
||||
case q == nil:
|
||||
return fmt.Errorf("question: at index %d: %w", i, errNilConfig)
|
||||
case q.Domain == "":
|
||||
return fmt.Errorf("question: at index %d: %w", i, errors.Error("empty domain"))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serverGroupBlockPageQuestionConfig is a structure for defining question
|
||||
// domains in [serverGroupBlockPageRedirectSkip].
|
||||
type serverGroupBlockPageQuestionConfig struct {
|
||||
Domain string `yaml:"domain"`
|
||||
}
|
||||
|
@ -1,85 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// signalHandler processes incoming signals and shuts services down.
|
||||
type signalHandler struct {
|
||||
signal chan os.Signal
|
||||
|
||||
// services are the services that are shut down before application
|
||||
// exiting.
|
||||
services []agdservice.Interface
|
||||
}
|
||||
|
||||
// newSignalHandler returns a new signalHandler that shuts down services.
|
||||
func newSignalHandler() (h signalHandler) {
|
||||
h = signalHandler{
|
||||
signal: make(chan os.Signal, 1),
|
||||
}
|
||||
|
||||
signal.Notify(h.signal, unix.SIGINT, unix.SIGQUIT, unix.SIGTERM)
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// add adds a service to the signal handler.
|
||||
func (h *signalHandler) add(s agdservice.Interface) {
|
||||
h.services = append(h.services, s)
|
||||
}
|
||||
|
||||
// Exit status constants.
|
||||
const (
|
||||
statusSuccess = 0
|
||||
statusError = 1
|
||||
)
|
||||
|
||||
// handle processes OS signals. status is statusSuccess on success and
|
||||
// statusError on error.
|
||||
func (h *signalHandler) handle() (status int) {
|
||||
defer log.OnPanic("signalHandler.handle")
|
||||
|
||||
for sig := range h.signal {
|
||||
log.Info("sighdlr: received signal %q", sig)
|
||||
|
||||
switch sig {
|
||||
case
|
||||
unix.SIGINT,
|
||||
unix.SIGQUIT,
|
||||
unix.SIGTERM:
|
||||
return h.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// Shouldn't happen, since h.signal is currently never closed.
|
||||
return statusError
|
||||
}
|
||||
|
||||
// shutdown gracefully shuts down all services. status is statusSuccess on
|
||||
// success and statusError on error.
|
||||
func (h *signalHandler) shutdown() (status int) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
log.Info("sighdlr: shutting down services")
|
||||
for i := len(h.services) - 1; i >= 0; i-- {
|
||||
s := h.services[i]
|
||||
err := s.Shutdown(ctx)
|
||||
if err != nil {
|
||||
log.Error("sighdlr: shutting down service at index %d: %s", i, err)
|
||||
status = statusError
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("sighdlr: shutting down adguard dns")
|
||||
|
||||
return status
|
||||
}
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
@ -300,7 +301,7 @@ func enableTLSKeyLogging(grps []*agd.ServerGroup, keyLogFileName string) (err er
|
||||
// registers its refresher in the signal handler.
|
||||
func setupTicketRotator(
|
||||
srvGrps []*agd.ServerGroup,
|
||||
sigHdlr signalHandler,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (err error) {
|
||||
tickRot, err := newTicketRotator(srvGrps)
|
||||
@ -324,7 +325,7 @@ func setupTicketRotator(
|
||||
return fmt.Errorf("starting ticket rotator refresh: %w", err)
|
||||
}
|
||||
|
||||
sigHdlr.add(refr)
|
||||
sigHdlr.Add(refr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -13,11 +13,10 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/prometheus"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
// DNS upstream configuration
|
||||
|
||||
// upstreamConfig is the upstream module configuration.
|
||||
type upstreamConfig struct {
|
||||
// Healthcheck contains the upstream healthcheck configuration.
|
||||
@ -160,9 +159,9 @@ func newUpstreamHealthcheck(
|
||||
handler *forward.Handler,
|
||||
conf *upstreamConfig,
|
||||
errColl errcoll.Interface,
|
||||
) (refr agdservice.Interface) {
|
||||
) (refr service.Interface) {
|
||||
if !conf.Healthcheck.Enabled {
|
||||
return agdservice.Empty{}
|
||||
return service.Empty{}
|
||||
}
|
||||
|
||||
return agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
|
@ -7,10 +7,10 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/pprofutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
@ -69,11 +69,15 @@ func startServer(s *server) {
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ agdservice.Interface = (*Service)(nil)
|
||||
var _ service.Interface = (*Service)(nil)
|
||||
|
||||
// Start implements the [agdservice.Interface] interface for *Service. It
|
||||
// starts serving all endpoints. err is always nil, if any endpoint fails to
|
||||
// start, it panics.
|
||||
// Start implements the [service.Interface] interface for *Service. It starts
|
||||
// serving all endpoints but does not wait for them to actually go online. err
|
||||
// is always nil, if any endpoint fails to start, it panics.
|
||||
//
|
||||
// TODO(a.garipov): Wait for the services to go online.
|
||||
//
|
||||
// TODO(a.garipov): Use the context for cancelation.
|
||||
func (svc *Service) Start(_ context.Context) (err error) {
|
||||
for _, srv := range svc.servers {
|
||||
go startServer(srv)
|
||||
@ -82,8 +86,8 @@ func (svc *Service) Start(_ context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown implements the [agdservice.Interface] interface for *Service. It
|
||||
// stops serving all endpoints.
|
||||
// Shutdown implements the [service.Interface] interface for *Service. It stops
|
||||
// serving all endpoints.
|
||||
func (svc *Service) Shutdown(ctx context.Context) (err error) {
|
||||
srvNum := 0
|
||||
for _, srv := range svc.servers {
|
||||
|
@ -76,6 +76,15 @@ func (kv *httpKV) get(ctx context.Context, key string) (inf *info, err error) {
|
||||
}
|
||||
defer func() { err = errors.WithDeferred(err, httpResp.Body.Close()) }()
|
||||
|
||||
// Note that, if no key exists at the given path, a 404 is returned instead
|
||||
// of a normal 200 response.
|
||||
//
|
||||
// See https://developer.hashicorp.com/consul/api-docs/kv#read-key.
|
||||
err = agdhttp.CheckStatus(httpResp, http.StatusOK)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("response for key %q: %w", key, err)
|
||||
}
|
||||
|
||||
var resp []*consulKVResponse
|
||||
err = json.NewDecoder(httpResp.Body).Decode(&resp)
|
||||
if err != nil {
|
||||
@ -153,6 +162,14 @@ func (kv *httpKV) set(ctx context.Context, key string, inf *info) (err error) {
|
||||
}
|
||||
defer func() { err = errors.WithDeferred(err, sessHTTPResp.Body.Close()) }()
|
||||
|
||||
// Status 200 is expected.
|
||||
//
|
||||
// See https://developer.hashicorp.com/consul/api-docs/session.
|
||||
err = agdhttp.CheckStatus(sessHTTPResp, http.StatusOK)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting session for key %q: %w", key, err)
|
||||
}
|
||||
|
||||
sessResp := &consulSessionResponse{}
|
||||
err = json.NewDecoder(sessHTTPResp.Body).Decode(sessResp)
|
||||
if err != nil {
|
||||
@ -176,6 +193,14 @@ func (kv *httpKV) set(ctx context.Context, key string, inf *info) (err error) {
|
||||
}
|
||||
defer func() { err = errors.WithDeferred(err, resp.Body.Close()) }()
|
||||
|
||||
// Status 200 is expected.
|
||||
//
|
||||
// See https://github.com/hashicorp/consul/blob/main/api/kv.go#L224.
|
||||
err = agdhttp.CheckStatus(resp, http.StatusOK)
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting key %q: %w", key, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,75 @@ func TestHTTPKV(t *testing.T) {
|
||||
|
||||
dnsCk.ServeHTTP(rw, r)
|
||||
assert.Equal(t, http.StatusInternalServerError, rw.Code)
|
||||
|
||||
assert.Equal(t, wantResp, rw.Body.String())
|
||||
})
|
||||
}
|
||||
|
||||
// newKVErrorServer returns URLs emulating behavior of Consul KV database
|
||||
// server returning HTTP errors.
|
||||
func newKVErrorServer(t *testing.T) (kv, sess *url.URL) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
|
||||
u, err := url.Parse(srv.URL)
|
||||
require.NoError(t, err)
|
||||
|
||||
return u.JoinPath(kvPath), u.JoinPath(sessPath)
|
||||
}
|
||||
|
||||
func TestHTTPKV_status_error(t *testing.T) {
|
||||
const (
|
||||
randomid = "randomid"
|
||||
localDomain = "example.local"
|
||||
)
|
||||
|
||||
conf := &dnscheck.ConsulConfig{
|
||||
Messages: &dnsmsg.Constructor{},
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) {},
|
||||
},
|
||||
Domains: []string{localDomain},
|
||||
NodeLocation: "some-node-location",
|
||||
NodeName: "some-node-name",
|
||||
TTL: 1 * time.Minute,
|
||||
}
|
||||
|
||||
conf.ConsulKVURL, conf.ConsulSessionURL = newKVErrorServer(t)
|
||||
dnsCk, err := dnscheck.NewConsul(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := dnsservertest.CreateMessage(randomid+"-"+localDomain, dns.TypeA)
|
||||
ri := &agd.RequestInfo{
|
||||
Device: &agd.Device{ID: "some-device-id"},
|
||||
Profile: &agd.Profile{ID: "some-profile-id"},
|
||||
ServerGroup: "some-server-group-name",
|
||||
Server: "some-server-name",
|
||||
Host: randomid + "-" + localDomain,
|
||||
RemoteIP: testRemoteIP,
|
||||
QType: dns.TypeA,
|
||||
Proto: agd.ProtoDNS,
|
||||
}
|
||||
|
||||
_, err = dnsCk.Check(context.Background(), req, ri)
|
||||
require.NoError(t, err)
|
||||
|
||||
dnscheck.FlushConsulCache(t, dnsCk)
|
||||
|
||||
t.Run("fail", func(t *testing.T) {
|
||||
const wantResp = `getting from consul: response for key "randomid": server "": ` +
|
||||
`status code error: expected 200, got 500` + "\n"
|
||||
|
||||
r := httptest.NewRequest(http.MethodGet, (&url.URL{
|
||||
Scheme: "http",
|
||||
Host: randomid + "-" + localDomain,
|
||||
Path: "/dnscheck/test",
|
||||
}).String(), strings.NewReader(""))
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
dnsCk.ServeHTTP(rw, r)
|
||||
assert.Equal(t, http.StatusInternalServerError, rw.Code)
|
||||
assert.Equal(t, wantResp, rw.Body.String())
|
||||
})
|
||||
}
|
||||
|
@ -200,6 +200,7 @@ func (c *Constructor) AppendDebugExtra(req, resp *dns.Msg, str string) (err erro
|
||||
// positive numbers, but we need a ceiling operation here.
|
||||
strNum := (strLen + MaxTXTStringLen - 1) / MaxTXTStringLen
|
||||
|
||||
// TODO(a.garipov): Use slices.Chunk in Go 1.23.
|
||||
newStr := make([]string, strNum)
|
||||
for i := 0; i < strNum; i++ {
|
||||
start := i * MaxTXTStringLen
|
||||
|
@ -1,11 +1,30 @@
|
||||
package dnsserver_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
// testTimeout is a common timeout for tests.
|
||||
const testTimeout = dnsserver.DefaultReadTimeout
|
||||
|
||||
// contextWithTimeout is a helper that creates a new context with timeout and
|
||||
// registers ctx's cleanup with t.Cleanup.
|
||||
//
|
||||
// TODO(a.garipov): Move to golibs and DRY.
|
||||
func contextWithTimeout(tb testing.TB, timeout time.Duration) (ctx context.Context) {
|
||||
tb.Helper()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
tb.Cleanup(cancel)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
@ -189,12 +189,12 @@ func RunLocalQUICServer(
|
||||
tlsConfig *tls.Config,
|
||||
) (s *dnsserver.ServerQUIC, addr *net.UDPAddr, err error) {
|
||||
conf := dnsserver.ConfigQUIC{
|
||||
TLSConfig: tlsConfig,
|
||||
ConfigBase: dnsserver.ConfigBase{
|
||||
Name: "test",
|
||||
Addr: "127.0.0.1:0",
|
||||
Handler: h,
|
||||
},
|
||||
TLSConfig: tlsConfig,
|
||||
}
|
||||
|
||||
s = dnsserver.NewServerQUIC(conf)
|
||||
@ -209,7 +209,7 @@ func RunLocalQUICServer(
|
||||
|
||||
addr, ok := s.LocalUDPAddr().(*net.UDPAddr)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("invalid listen addr: %s", addr)
|
||||
return nil, nil, fmt.Errorf("invalid listen addr: %T(%[1]v)", s.LocalUDPAddr())
|
||||
}
|
||||
|
||||
return s, addr, nil
|
||||
|
@ -1,21 +1,21 @@
|
||||
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
||||
|
||||
go 1.21.5
|
||||
go 1.21.8
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/golibs v0.18.1
|
||||
github.com/AdguardTeam/golibs v0.20.1
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
||||
github.com/ameshkov/dnsstamps v1.0.3
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/miekg/dns v1.1.56
|
||||
github.com/panjf2000/ants/v2 v2.8.2
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/panjf2000/ants/v2 v2.9.0
|
||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/quic-go/quic-go v0.39.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/quic-go/quic-go v0.41.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -24,23 +24,21 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/common v0.46.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
github.com/AdguardTeam/golibs v0.18.1 h1:6u0fvrIj2qjUsRdbIGJ9AR0g5QRSWdKIo/DYl3tp5aM=
|
||||
github.com/AdguardTeam/golibs v0.20.1 h1:ol8qLjWGZhU9paMMwN+OLWVTUigGsXa29iVTyd62VKY=
|
||||
github.com/AdguardTeam/golibs v0.20.1/go.mod h1:bgcMgRviCKyU6mkrX+RtT/OsKPFzyppelfRsksMG3KU=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||
@ -17,48 +18,44 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/panjf2000/ants/v2 v2.8.2 h1:D1wfANttg8uXhC9149gRt1PDQ+dLVFjNXkCEycMcvQQ=
|
||||
github.com/panjf2000/ants/v2 v2.8.2/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo=
|
||||
github.com/panjf2000/ants/v2 v2.9.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/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So=
|
||||
github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
|
||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -70,31 +67,27 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
@ -474,7 +474,7 @@ func (s *ServerBase) waitShutdown(ctx context.Context) (err error) {
|
||||
// isStarted returns true if the server is started.
|
||||
func (s *ServerBase) isStarted() (started bool) {
|
||||
s.lock.RLock()
|
||||
started = s.started
|
||||
s.lock.RUnlock()
|
||||
return started
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.started
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ func BenchmarkServeQUIC(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
resp := sendQUICMessage(b, sess, req, false)
|
||||
resp := requireSendQUICMessage(b, sess, req)
|
||||
require.NotNil(b, resp)
|
||||
require.True(b, resp.Response)
|
||||
}
|
||||
|
@ -108,6 +108,8 @@ func NewServerDNS(conf ConfigDNS) (s *ServerDNS) {
|
||||
// server with a TLS layer on top of it.
|
||||
func newServerDNS(proto Protocol, conf ConfigDNS) (s *ServerDNS) {
|
||||
// Init default settings first.
|
||||
//
|
||||
// TODO(a.garipov): Use cmp.Or in Go 1.22.
|
||||
if conf.ReadTimeout == 0 {
|
||||
conf.ReadTimeout = DefaultReadTimeout
|
||||
}
|
||||
|
@ -246,8 +246,16 @@ func (s *ServerHTTPS) shutdown(ctx context.Context) (err error) {
|
||||
|
||||
s.started = false
|
||||
|
||||
// First step, close the active listener right away.
|
||||
s.closeListeners()
|
||||
// First step, close the active TCP listener right away. Don't close the
|
||||
// UDP one, as if there is one, it is closed by closing the QUIC listener.
|
||||
//
|
||||
// TODO(a.garipov): Fix this mess.
|
||||
if s.tcpListener != nil {
|
||||
err = s.tcpListener.Close()
|
||||
if err != nil {
|
||||
log.Info("[%s]: Failed to close NetworkTCP listener: %v", s.Name(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Second, shutdown the HTTP server.
|
||||
err = s.httpServer.Shutdown(ctx)
|
||||
|
@ -597,7 +597,6 @@ func createJSONRequest(
|
||||
|
||||
requestURL := fmt.Sprintf("%s://test.local%s?%s", proto, dnsserver.PathJSON, q.Encode())
|
||||
r, err = http.NewRequest(method, requestURL, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -66,11 +66,11 @@ var compatProtoDQ = []string{"doq-i00", "doq-i02", "doq-i03", "dq"}
|
||||
// ConfigQUIC is a struct that needs to be passed to NewServerQUIC to
|
||||
// initialize a new ServerQUIC instance.
|
||||
type ConfigQUIC struct {
|
||||
ConfigBase
|
||||
|
||||
// TLSConfig is the TLS configuration for QUIC.
|
||||
TLSConfig *tls.Config
|
||||
|
||||
ConfigBase
|
||||
|
||||
// MaxStreamsPerPeer is the maximum number of concurrent streams that a peer
|
||||
// is allowed to open.
|
||||
MaxStreamsPerPeer int
|
||||
@ -83,8 +83,6 @@ type ConfigQUIC struct {
|
||||
type ServerQUIC struct {
|
||||
*ServerBase
|
||||
|
||||
conf ConfigQUIC
|
||||
|
||||
// pool is a goroutine pool we use to process DNS queries. Complicated
|
||||
// logic may require growing the goroutine's stack and we experienced it
|
||||
// in AdGuard DNS. The easiest way to avoid spending extra time on this is
|
||||
@ -100,6 +98,10 @@ type ServerQUIC struct {
|
||||
|
||||
// quicListener is a listener that we use to accept DoQ connections.
|
||||
quicListener *quic.Listener
|
||||
|
||||
// TODO(a.garipov): Remove this and only save the values a server actually
|
||||
// uses.
|
||||
conf ConfigQUIC
|
||||
}
|
||||
|
||||
// quicBytePoolSize is the size for the QUIC byte pools.
|
||||
@ -120,10 +122,10 @@ func NewServerQUIC(conf ConfigQUIC) (s *ServerQUIC) {
|
||||
|
||||
s = &ServerQUIC{
|
||||
ServerBase: newServerBase(ProtoDoQ, conf.ConfigBase),
|
||||
conf: conf,
|
||||
pool: newPoolNonblocking(),
|
||||
reqPool: syncutil.NewSlicePool[byte](quicBytePoolSize),
|
||||
respPool: syncutil.NewSlicePool[byte](quicBytePoolSize),
|
||||
conf: conf,
|
||||
}
|
||||
|
||||
return s
|
||||
@ -207,7 +209,6 @@ func (s *ServerQUIC) shutdown() (err error) {
|
||||
s.started = false
|
||||
|
||||
// Now close all listeners
|
||||
s.closeListeners()
|
||||
err = s.quicListener.Close()
|
||||
if err != nil {
|
||||
// Log this error but do not return it
|
||||
@ -242,6 +243,12 @@ func (s *ServerQUIC) serveQUIC(ctx context.Context, l *quic.Listener) (err error
|
||||
// Wait until all conns are processed before exiting this method
|
||||
defer wg.Wait()
|
||||
|
||||
// Use a context that is canceled once this connection ends to mitigate
|
||||
// quic-go's mishandling of contexts. See TODO in serveQUICConn.
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
for s.isStarted() {
|
||||
err = s.acceptQUICConn(ctx, l, wg)
|
||||
if err != nil {
|
||||
@ -251,7 +258,6 @@ func (s *ServerQUIC) serveQUIC(ctx context.Context, l *quic.Listener) (err error
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -294,7 +300,7 @@ func (s *ServerQUIC) acceptQUICConn(
|
||||
}
|
||||
|
||||
// serveQUICConnAsync wraps serveQUICConn call and handles all possible errors
|
||||
// that might happen there. It also makes sure that the WaitGroup will be
|
||||
// that might happen there. It also makes sure that the WaitGroup will be
|
||||
// decremented.
|
||||
func (s *ServerQUIC) serveQUICConnAsync(
|
||||
ctx context.Context,
|
||||
@ -331,6 +337,21 @@ func (s *ServerQUIC) serveQUICConn(ctx context.Context, conn quic.Connection) (e
|
||||
// bidirectional stream.
|
||||
var stream quic.Stream
|
||||
acceptCtx, cancel := context.WithDeadline(ctx, time.Now().Add(maxQUICIdleTimeout))
|
||||
|
||||
// For some reason AcceptStream below seems to get stuck even when
|
||||
// acceptCtx is canceled. As a mitigation, check the context manually
|
||||
// right before feeding it into AcceptStream.
|
||||
//
|
||||
// TODO(a.garipov): Try to reproduce and report.
|
||||
select {
|
||||
case <-acceptCtx.Done():
|
||||
cancel()
|
||||
|
||||
return fmt.Errorf("checking accept ctx: %w", acceptCtx.Err())
|
||||
default:
|
||||
// Go on.
|
||||
}
|
||||
|
||||
stream, err = conn.AcceptStream(acceptCtx)
|
||||
// Make sure to call the cancel function to avoid leaks.
|
||||
cancel()
|
||||
@ -396,9 +417,7 @@ func (s *ServerQUIC) serveQUICStream(
|
||||
// that stream.
|
||||
defer log.OnCloserError(stream, log.DEBUG)
|
||||
|
||||
var msg *dns.Msg
|
||||
var doqDraft bool
|
||||
msg, doqDraft, err = s.readQUICMsg(ctx, stream)
|
||||
msg, err := s.readQUICMsg(ctx, stream)
|
||||
if err != nil {
|
||||
closeQUICConn(conn, DOQCodeProtocolError)
|
||||
|
||||
@ -435,15 +454,7 @@ func (s *ServerQUIC) serveQUICStream(
|
||||
bufPtr := s.respPool.Get()
|
||||
defer s.respPool.Put(bufPtr)
|
||||
|
||||
// Depending on the DoQ version we either write a 2-bytes prefixed message
|
||||
// or just write the message (for old draft versions).
|
||||
var b []byte
|
||||
if doqDraft {
|
||||
// TODO(ameshkov): remove draft support in the late 2023.
|
||||
b, err = resp.PackBuffer(*bufPtr)
|
||||
} else {
|
||||
b, err = packWithPrefix(resp, *bufPtr)
|
||||
}
|
||||
b, err := packWithPrefix(resp, *bufPtr)
|
||||
if err != nil {
|
||||
closeQUICConn(conn, DOQCodeProtocolError)
|
||||
|
||||
@ -464,7 +475,7 @@ func (s *ServerQUIC) serveQUICStream(
|
||||
func (s *ServerQUIC) readQUICMsg(
|
||||
ctx context.Context,
|
||||
stream quic.Stream,
|
||||
) (m *dns.Msg, doqDraft bool, err error) {
|
||||
) (m *dns.Msg, err error) {
|
||||
bufPtr := s.reqPool.Get()
|
||||
defer s.reqPool.Put(bufPtr)
|
||||
|
||||
@ -485,35 +496,29 @@ func (s *ServerQUIC) readQUICMsg(
|
||||
// received.
|
||||
if n < DNSHeaderSize {
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to read QUIC message: %w", err)
|
||||
return nil, fmt.Errorf("failed to read QUIC message: %w", err)
|
||||
}
|
||||
s.metrics.OnInvalidMsg(ctx)
|
||||
|
||||
return nil, false, dns.ErrShortRead
|
||||
return nil, dns.ErrShortRead
|
||||
}
|
||||
|
||||
// Note that we support both the old drafts and the new RFC. In the old
|
||||
// draft DNS messages were not prefixed with the message length.
|
||||
// TODO(a.garipov): DRY logic with the TCP one.
|
||||
m = &dns.Msg{}
|
||||
|
||||
// We're checking if the first two bytes contain the length of the message.
|
||||
// According to the spec, the DNS message ID is 0 so the first two bytes
|
||||
// will be zero in the case of an old draft implementation so this check
|
||||
// should be reliable.
|
||||
packetLen := binary.BigEndian.Uint16(buf[:2])
|
||||
if packetLen == uint16(n-2) {
|
||||
wantLen := uint16(n - 2)
|
||||
if packetLen == wantLen {
|
||||
err = m.Unpack(buf[2:])
|
||||
} else {
|
||||
err = m.Unpack(buf)
|
||||
doqDraft = true
|
||||
err = fmt.Errorf("bad buffer size %d, want %d", packetLen, wantLen)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.metrics.OnInvalidMsg(ctx)
|
||||
return nil, false, err
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, doqDraft, nil
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// readAll reads from r until an error or io.EOF into the specified buffer buf.
|
||||
@ -558,7 +563,10 @@ func (s *ServerQUIC) listenQUIC(ctx context.Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save this for s.LocalUDPAddr. Do not close it separately as ql closes
|
||||
// the underlying connection.
|
||||
s.udpListener = conn
|
||||
|
||||
s.quicListener = ql
|
||||
|
||||
return nil
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
@ -30,7 +31,7 @@ func TestServerQUIC_integration_query(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return srv.Shutdown(context.Background())
|
||||
return srv.Shutdown(contextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
// Open a QUIC connection.
|
||||
@ -41,28 +42,29 @@ func TestServerQUIC_integration_query(t *testing.T) {
|
||||
return conn.CloseWithError(0, "")
|
||||
})
|
||||
|
||||
// Send multiple queries to the DNS server in parallel
|
||||
const queriesNum = 100
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(queriesNum)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
wg.Add(1)
|
||||
|
||||
// Create a test message.
|
||||
for i := 0; i < queriesNum; i++ {
|
||||
req := dnsservertest.NewReq("example.org.", dns.TypeA, dns.ClassINET)
|
||||
req.RecursionDesired = true
|
||||
|
||||
// Even requests are sent as if it's an old draft client.
|
||||
doqDraft := i%2 == 0
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
resp := sendQUICMessage(t, conn, req, doqDraft)
|
||||
assert.NotNil(t, resp)
|
||||
resp, reqErr := sendQUICMessage(conn, req)
|
||||
// Do not use require, as this is a separate goroutine.
|
||||
if !assert.NoError(t, reqErr) || !assert.NotNil(t, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
assert.True(t, resp.Response)
|
||||
|
||||
// EDNS0 padding is only present when request also has padding opt.
|
||||
paddingOpt := dnsservertest.FindEDNS0Option[*dns.EDNS0_PADDING](resp)
|
||||
require.Nil(t, paddingOpt)
|
||||
assert.Nil(t, paddingOpt)
|
||||
}()
|
||||
}
|
||||
|
||||
@ -78,7 +80,7 @@ func TestServerQUIC_integration_ENDS0Padding(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return srv.Shutdown(context.Background())
|
||||
return srv.Shutdown(contextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
// Open a QUIC connection.
|
||||
@ -92,7 +94,7 @@ func TestServerQUIC_integration_ENDS0Padding(t *testing.T) {
|
||||
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
||||
req.Extra = []dns.RR{dnsservertest.NewEDNS0Padding(req.Len(), dns.DefaultMsgSize)}
|
||||
|
||||
resp := sendQUICMessage(t, conn, req, false)
|
||||
resp := requireSendQUICMessage(t, conn, req)
|
||||
require.NotNil(t, resp)
|
||||
require.Equal(t, dns.RcodeSuccess, resp.Rcode)
|
||||
require.True(t, resp.Response)
|
||||
@ -112,7 +114,7 @@ func TestServerQUIC_integration_0RTT(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return srv.Shutdown(context.Background())
|
||||
return srv.Shutdown(contextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
quicTracer := dnsservertest.NewQUICTracer()
|
||||
@ -150,7 +152,7 @@ func TestServerQUIC_integration_largeQuery(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return srv.Shutdown(context.Background())
|
||||
return srv.Shutdown(contextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
// Open a QUIC connection.
|
||||
@ -174,7 +176,7 @@ func TestServerQUIC_integration_largeQuery(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
resp := sendQUICMessage(t, conn, req, false)
|
||||
resp := requireSendQUICMessage(t, conn, req)
|
||||
require.NotNil(t, resp)
|
||||
require.True(t, resp.Response)
|
||||
}
|
||||
@ -202,64 +204,77 @@ func testQUICExchange(
|
||||
req := dnsservertest.NewReq("example.org.", dns.TypeA, dns.ClassINET)
|
||||
req.RecursionDesired = true
|
||||
|
||||
resp := sendQUICMessage(t, conn, req, false)
|
||||
resp := requireSendQUICMessage(t, conn, req)
|
||||
require.NotNil(t, resp)
|
||||
}
|
||||
|
||||
// sendQUICMessage is a test helper that sends a test QUIC message.
|
||||
func sendQUICMessage(
|
||||
t testing.TB,
|
||||
conn quic.Connection,
|
||||
req *dns.Msg,
|
||||
doqDraft bool,
|
||||
) (resp *dns.Msg) {
|
||||
t.Helper()
|
||||
|
||||
) (resp *dns.Msg, err error) {
|
||||
stream, err := conn.OpenStreamSync(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
defer log.OnCloserError(stream, log.DEBUG)
|
||||
|
||||
data, err := req.Pack()
|
||||
require.NoError(t, err)
|
||||
|
||||
var buf []byte
|
||||
if doqDraft {
|
||||
buf = data
|
||||
} else {
|
||||
buf = make([]byte, 2+len(data))
|
||||
binary.BigEndian.PutUint16(buf, uint16(len(data)))
|
||||
copy(buf[2:], data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening stream: %w", err)
|
||||
}
|
||||
|
||||
defer log.OnCloserError(stream, log.ERROR)
|
||||
|
||||
data, err := req.Pack()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("packing: %w", err)
|
||||
}
|
||||
|
||||
buf := make([]byte, 2+len(data))
|
||||
binary.BigEndian.PutUint16(buf, uint16(len(data)))
|
||||
copy(buf[2:], data)
|
||||
|
||||
err = writeQUICStream(buf, stream)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("writing: %w", err)
|
||||
}
|
||||
|
||||
// Closes the write-direction of the stream and sends a STREAM FIN packet.
|
||||
// A DoQ client MUST send a FIN packet to indicate that the query is
|
||||
// finished.
|
||||
err = stream.Close()
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("closing stream: %w", err)
|
||||
}
|
||||
|
||||
// Now read the response.
|
||||
respBytes := make([]byte, dns.MaxMsgSize)
|
||||
n, err := stream.Read(respBytes)
|
||||
if !errors.Is(err, io.EOF) {
|
||||
require.NoError(t, err)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return nil, fmt.Errorf("reading stream: %w", err)
|
||||
}
|
||||
|
||||
require.GreaterOrEqual(t, n, dnsserver.DNSHeaderSize)
|
||||
if n < dnsserver.DNSHeaderSize {
|
||||
return nil, fmt.Errorf("read %d, want %d", n, dnsserver.DNSHeaderSize)
|
||||
}
|
||||
|
||||
// Unpack the response.
|
||||
reply := &dns.Msg{}
|
||||
if doqDraft {
|
||||
err = reply.Unpack(respBytes[:n])
|
||||
} else {
|
||||
err = reply.Unpack(respBytes[2:n])
|
||||
err = reply.Unpack(respBytes[2:n])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking: %w", err)
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// requireSendQUICMessage is a test helper that sends a test QUIC message and
|
||||
// requires it to succeed. It must not be used in a goroutine with the outer
|
||||
// test's t.
|
||||
func requireSendQUICMessage(
|
||||
t testing.TB,
|
||||
conn quic.Connection,
|
||||
req *dns.Msg,
|
||||
) (resp *dns.Msg) {
|
||||
t.Helper()
|
||||
|
||||
resp, err := sendQUICMessage(conn, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
return reply
|
||||
return resp
|
||||
}
|
||||
|
||||
// writeQUICStream writes buf to the specified QUIC stream in chunks. This way
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/connlimiter"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||
@ -34,6 +33,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/querylog"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/rulestat"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -144,6 +144,10 @@ type Config struct {
|
||||
// used.
|
||||
UseECSCache bool
|
||||
|
||||
// ProfileDBEnabled is true, if user devices and profiles recognition is
|
||||
// enabled.
|
||||
ProfileDBEnabled bool
|
||||
|
||||
// ResearchMetrics controls whether research metrics are enabled or not.
|
||||
// This is a set of metrics that we may need temporary, so its collection is
|
||||
// controlled by a separate setting.
|
||||
@ -267,10 +271,10 @@ func mustStartListener(
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ agdservice.Interface = (*Service)(nil)
|
||||
var _ service.Interface = (*Service)(nil)
|
||||
|
||||
// Start implements the [agdservice.Interface] interface for *Service. It
|
||||
// panics if one of the listeners could not start.
|
||||
// Start implements the [service.Interface] interface for *Service. It panics
|
||||
// if one of the listeners could not start.
|
||||
func (svc *Service) Start(_ context.Context) (err error) {
|
||||
for _, g := range svc.groups {
|
||||
for _, s := range g.servers {
|
||||
@ -298,7 +302,7 @@ func shutdownListeners(ctx context.Context, listeners []*listener) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown implements the [agdservice.Interface] interface for *Service.
|
||||
// Shutdown implements the [service.Interface] interface for *Service.
|
||||
func (svc *Service) Shutdown(ctx context.Context) (err error) {
|
||||
var errs []error
|
||||
for _, g := range svc.groups {
|
||||
@ -512,13 +516,14 @@ func newServers(
|
||||
})
|
||||
|
||||
imw := initial.New(&initial.Config{
|
||||
Messages: c.Messages,
|
||||
FilteringGroup: fg,
|
||||
ServerGroup: srvGrp,
|
||||
Server: s,
|
||||
ProfileDB: c.ProfileDB,
|
||||
GeoIP: c.GeoIP,
|
||||
ErrColl: c.ErrColl,
|
||||
Messages: c.Messages,
|
||||
FilteringGroup: fg,
|
||||
ServerGroup: srvGrp,
|
||||
Server: s,
|
||||
ProfileDB: c.ProfileDB,
|
||||
GeoIP: c.GeoIP,
|
||||
ErrColl: c.ErrColl,
|
||||
ProfileDBEnabled: c.ProfileDBEnabled,
|
||||
})
|
||||
|
||||
h := dnsserver.WithMiddlewares(
|
||||
|
@ -101,8 +101,8 @@ func newTestService(
|
||||
OnIsBlockedHost: func(host string, qt uint16) (blocked bool) {
|
||||
return false
|
||||
},
|
||||
OnIsBlockedIP: func(ip netip.Addr) (blocked bool, rule string) {
|
||||
return false, ""
|
||||
OnIsBlockedIP: func(ip netip.Addr) (blocked bool) {
|
||||
return false
|
||||
},
|
||||
}
|
||||
|
||||
@ -228,16 +228,18 @@ func newTestService(
|
||||
},
|
||||
},
|
||||
ServerGroups: []*agd.ServerGroup{{
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{dnssvctest.DeviceIDWildcard},
|
||||
},
|
||||
BlockPageRedirect: &agd.BlockPageRedirect{},
|
||||
DDR: &agd.DDR{
|
||||
Enabled: true,
|
||||
},
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{dnssvctest.DeviceIDWildcard},
|
||||
},
|
||||
Name: testSrvGrpName,
|
||||
FilteringGroup: testFltGrpID,
|
||||
Servers: []*agd.Server{srv},
|
||||
}},
|
||||
ProfileDBEnabled: true,
|
||||
}
|
||||
|
||||
svc, err := dnssvc.New(c)
|
||||
|
@ -45,7 +45,7 @@ func (mw *Middleware) Wrap(next dnsserver.Handler) (wrapped dnsserver.Handler) {
|
||||
defer func() { err = errors.Annotate(err, "access mw: %w") }()
|
||||
|
||||
rAddr := netutil.NetAddrToAddrPort(rw.RemoteAddr()).Addr()
|
||||
if blocked, _ := mw.accessManager.IsBlockedIP(rAddr); blocked {
|
||||
if blocked := mw.accessManager.IsBlockedIP(rAddr); blocked {
|
||||
metrics.AccessBlockedForSubnetTotal.Inc()
|
||||
|
||||
return nil
|
||||
|
@ -25,9 +25,9 @@ func TestMiddleware_Wrap(t *testing.T) {
|
||||
"block.test",
|
||||
"UPPERCASE.test",
|
||||
"||block_aaaa.test^$dnstype=AAAA",
|
||||
}, []string{
|
||||
"1.1.1.1",
|
||||
"2.2.2.0/8",
|
||||
}, []netip.Prefix{
|
||||
netip.MustParsePrefix("1.1.1.1/32"),
|
||||
netip.MustParsePrefix("2.2.2.0/8"),
|
||||
})
|
||||
require.NoError(t, accessErr)
|
||||
|
||||
|
@ -55,6 +55,10 @@ type Middleware struct {
|
||||
|
||||
// errColl collects and reports the errors considered non-critical.
|
||||
errColl errcoll.Interface
|
||||
|
||||
// profilesEnabled is true, if user devices and profiles recognition is
|
||||
// enabled.
|
||||
profilesEnabled bool
|
||||
}
|
||||
|
||||
// Config is the configuration structure for the initial middleware. All fields
|
||||
@ -80,6 +84,10 @@ type Config struct {
|
||||
|
||||
// ErrColl collects and reports the errors considered non-critical.
|
||||
ErrColl errcoll.Interface
|
||||
|
||||
// ProfileDBEnabled is true, if user devices and profiles recognition is
|
||||
// enabled.
|
||||
ProfileDBEnabled bool
|
||||
}
|
||||
|
||||
// New returns a new initial middleware. c must not be nil.
|
||||
@ -92,9 +100,10 @@ func New(c *Config) (mw *Middleware) {
|
||||
pool: syncutil.NewPool(func() (v *agd.RequestInfo) {
|
||||
return &agd.RequestInfo{}
|
||||
}),
|
||||
db: c.ProfileDB,
|
||||
geoIP: c.GeoIP,
|
||||
errColl: c.ErrColl,
|
||||
db: c.ProfileDB,
|
||||
geoIP: c.GeoIP,
|
||||
errColl: c.ErrColl,
|
||||
profilesEnabled: c.ProfileDBEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,6 +230,10 @@ func (mw *Middleware) newRequestInfo(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !mw.profilesEnabled {
|
||||
return ri, nil
|
||||
}
|
||||
|
||||
// Add the profile information, if any.
|
||||
localAddr := netutil.NetAddrToAddrPort(lAddr)
|
||||
err = mw.addProfile(ctx, ri, req, localAddr)
|
||||
|
@ -181,6 +181,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
@ -301,6 +302,7 @@ func TestMiddleware_Wrap_error(t *testing.T) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
@ -517,6 +519,7 @@ func TestMiddleware_Wrap_access(t *testing.T) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
@ -565,14 +568,15 @@ func newServers() (srvs map[agd.ServerName]*agd.Server) {
|
||||
|
||||
func newServerGroup(srvs []*agd.Server) (srvGrp *agd.ServerGroup) {
|
||||
srvGrp = &agd.ServerGroup{
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{"*.d." + resolverName},
|
||||
},
|
||||
BlockPageRedirect: &agd.BlockPageRedirect{},
|
||||
DDR: &agd.DDR{
|
||||
DeviceTargets: stringutil.NewSet(),
|
||||
PublicTargets: stringutil.NewSet(),
|
||||
Enabled: true,
|
||||
},
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{"*.d." + resolverName},
|
||||
},
|
||||
Name: "test_server_group",
|
||||
Servers: srvs,
|
||||
}
|
||||
@ -605,14 +609,15 @@ var errSink error
|
||||
func BenchmarkMiddleware_Wrap(b *testing.B) {
|
||||
const devIDTarget = "dns.example.com"
|
||||
srvGrp := &agd.ServerGroup{
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{"*." + devIDTarget},
|
||||
},
|
||||
BlockPageRedirect: &agd.BlockPageRedirect{},
|
||||
DDR: &agd.DDR{
|
||||
DeviceTargets: stringutil.NewSet(),
|
||||
PublicTargets: stringutil.NewSet(),
|
||||
Enabled: true,
|
||||
},
|
||||
TLS: &agd.TLS{
|
||||
DeviceIDWildcards: []string{"*." + devIDTarget},
|
||||
},
|
||||
Name: agd.ServerGroupName("test_server_group"),
|
||||
Servers: []*agd.Server{
|
||||
dnssvctest.NewServer("test_server_dot", agd.ProtoDoT, &agd.ServerBindData{
|
||||
@ -708,6 +713,7 @@ func BenchmarkMiddleware_Wrap(b *testing.B) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
h := mw.Wrap(handler)
|
||||
@ -753,6 +759,7 @@ func BenchmarkMiddleware_Wrap(b *testing.B) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
h := mw.Wrap(handler)
|
||||
@ -806,6 +813,7 @@ func BenchmarkMiddleware_Wrap(b *testing.B) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
h := mw.Wrap(handler)
|
||||
@ -864,6 +872,7 @@ func BenchmarkMiddleware_Wrap(b *testing.B) {
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) { panic("not implemented") },
|
||||
},
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
h := mw.Wrap(handler)
|
||||
|
@ -101,8 +101,9 @@ func TestMiddleware_profile(t *testing.T) {
|
||||
srv.LinkedIPEnabled = tc.linkedIPEnabled
|
||||
|
||||
mw := New(&Config{
|
||||
Server: srv,
|
||||
ProfileDB: newProfileDB(t, prof, dev, tc.wantByWhat),
|
||||
Server: srv,
|
||||
ProfileDB: newProfileDB(t, prof, dev, tc.wantByWhat),
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
@ -196,8 +197,9 @@ func TestMiddleware_profileByAddrs(t *testing.T) {
|
||||
srv.LinkedIPEnabled = tc.linkedIPEnabled
|
||||
|
||||
mw := New(&Config{
|
||||
Server: srv,
|
||||
ProfileDB: newProfileDB(t, prof, dev, tc.wantByWhat),
|
||||
Server: srv,
|
||||
ProfileDB: newProfileDB(t, prof, dev, tc.wantByWhat),
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -198,9 +198,10 @@ func TestMiddleware_ServeDNS_specialDomain(t *testing.T) {
|
||||
Protocol: agd.ProtoDNS,
|
||||
LinkedIPEnabled: true,
|
||||
},
|
||||
ProfileDB: db,
|
||||
GeoIP: geoIP,
|
||||
ErrColl: errColl,
|
||||
ProfileDB: db,
|
||||
GeoIP: geoIP,
|
||||
ErrColl: errColl,
|
||||
ProfileDBEnabled: true,
|
||||
})
|
||||
|
||||
h := mw.Wrap(handler)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,5 @@
|
||||
// Package internal contains common constants, types, and utilities shared by
|
||||
// other subpackages of package filter/.
|
||||
//
|
||||
// TODO(a.garipov): Move more code to subpackages, see AGDNS-824.
|
||||
package internal
|
||||
|
||||
import (
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,15 @@ var DevicesNewCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Help: "The number of user devices that were changed or added since the previous sync.",
|
||||
})
|
||||
|
||||
// DevicesInvalidTotal is a gauge with the number of invalid user devices loaded
|
||||
// from the backend.
|
||||
var DevicesInvalidTotal = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "devices_invalid_total",
|
||||
Subsystem: subsystemBackend,
|
||||
Namespace: namespace,
|
||||
Help: "The total number of invalid user devices loaded from the backend.",
|
||||
})
|
||||
|
||||
// ProfilesCountGauge is a gauge with the total number of user profiles loaded
|
||||
// from the backend.
|
||||
var ProfilesCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
|
@ -21,6 +21,9 @@ var DNSSvcRequestByASNTotal = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystemDNSSvc,
|
||||
Help: "The number of processed DNS requests labeled by country and ASN.",
|
||||
ConstLabels: prometheus.Labels{
|
||||
dontStoreLabel: dontStoreLabelValue,
|
||||
},
|
||||
}, []string{"country", "asn"})
|
||||
|
||||
// DNSSvcRequestByFilterTotal is a counter with the total number of queries
|
||||
|
@ -35,6 +35,16 @@ const (
|
||||
subsystemWebSvc = "websvc"
|
||||
)
|
||||
|
||||
const (
|
||||
// dontStoreLabel is a label that signals that the metric should not be
|
||||
// stored in the long-term storage.
|
||||
dontStoreLabel = "do_not_store_metric"
|
||||
|
||||
// dontStoreLabelValue is a positive value of the [dontStoreLabel] label to
|
||||
// avoid calling [BoolString] every time.
|
||||
dontStoreLabelValue = "1"
|
||||
)
|
||||
|
||||
// SetUpGauge signals that the server has been started. Use a function here to
|
||||
// avoid circular dependencies.
|
||||
func SetUpGauge(version, buildtime, branch, revision, goversion string) {
|
||||
|
@ -39,6 +39,39 @@ type Interface interface {
|
||||
ProfileByLinkedIP(ctx context.Context, ip netip.Addr) (p *agd.Profile, d *agd.Device, err error)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Interface = (*Disabled)(nil)
|
||||
|
||||
// Disabled is a profile database that panics on any call.
|
||||
type Disabled struct{}
|
||||
|
||||
// profilesDBUnexpectedCall is a panic message template for lookup methods when
|
||||
// profiles database is disabled.
|
||||
const profilesDBUnexpectedCall string = "profiles db: unexpected call to %s"
|
||||
|
||||
// ProfileByDeviceID implements the [Interface] interface for *Disabled.
|
||||
func (d *Disabled) ProfileByDeviceID(
|
||||
_ context.Context,
|
||||
_ agd.DeviceID,
|
||||
) (_ *agd.Profile, _ *agd.Device, _ error) {
|
||||
panic(fmt.Errorf(profilesDBUnexpectedCall, "ProfileByDeviceID"))
|
||||
}
|
||||
|
||||
// ProfileByDedicatedIP implements the [Interface] interface for *Disabled.
|
||||
func (d *Disabled) ProfileByDedicatedIP(
|
||||
_ context.Context, _ netip.Addr,
|
||||
) (_ *agd.Profile, _ *agd.Device, _ error) {
|
||||
panic(fmt.Errorf(profilesDBUnexpectedCall, "ProfileByDedicatedIP"))
|
||||
}
|
||||
|
||||
// ProfileByLinkedIP implements the [Interface] interface for *Disabled.
|
||||
func (d *Disabled) ProfileByLinkedIP(
|
||||
_ context.Context,
|
||||
_ netip.Addr,
|
||||
) (_ *agd.Profile, _ *agd.Device, _ error) {
|
||||
panic(fmt.Errorf(profilesDBUnexpectedCall, "ProfileByLinkedIP"))
|
||||
}
|
||||
|
||||
// Config represents the profile database configuration.
|
||||
type Config struct {
|
||||
// Storage returns the data for this profile DB.
|
||||
|
@ -1,38 +1,36 @@
|
||||
module github.com/AdguardTeam/AdGuardDNS/internal/tools
|
||||
|
||||
go 1.21.5
|
||||
go 1.21.8
|
||||
|
||||
require (
|
||||
github.com/fzipp/gocyclo v0.6.0
|
||||
github.com/golangci/misspell v0.4.1
|
||||
github.com/gordonklaus/ineffassign v0.1.0
|
||||
github.com/kisielk/errcheck v1.6.3
|
||||
github.com/kisielk/errcheck v1.7.0
|
||||
github.com/kyoh86/looppointer v0.2.1
|
||||
github.com/securego/gosec/v2 v2.18.2
|
||||
// TODO(a.garipov): Return to latest once the release is tagged
|
||||
// correctly. See uudashr/gocognit#31.
|
||||
github.com/securego/gosec/v2 v2.19.0
|
||||
github.com/uudashr/gocognit v1.1.2
|
||||
golang.org/x/tools v0.16.0
|
||||
golang.org/x/vuln v1.0.1
|
||||
golang.org/x/tools v0.18.0
|
||||
golang.org/x/vuln v1.0.4
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
honnef.co/go/tools v0.4.6
|
||||
mvdan.cc/gofumpt v0.5.0
|
||||
mvdan.cc/unparam v0.0.0-20230917202934-3ee2d22f45fb
|
||||
google.golang.org/protobuf v1.32.0
|
||||
honnef.co/go/tools v0.4.7
|
||||
mvdan.cc/gofumpt v0.6.0
|
||||
mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/ccojocar/zxcvbn-go v1.0.1 // indirect
|
||||
github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/kyoh86/nolint v0.0.1 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20231127185646-65229373498e // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
@ -1,37 +1,35 @@
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4=
|
||||
github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
|
||||
github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
|
||||
github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
||||
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g=
|
||||
github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI=
|
||||
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
|
||||
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s=
|
||||
github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
|
||||
github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8=
|
||||
github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw=
|
||||
github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0=
|
||||
github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@ -40,16 +38,16 @@ github.com/kyoh86/looppointer v0.2.1 h1:Jx9fnkBj/JrIryBLMTYNTj9rvc2SrPS98Dg0w7fx
|
||||
github.com/kyoh86/looppointer v0.2.1/go.mod h1:q358WcM8cMWU+5vzqukvaZtnJi1kw/MpRHQm3xvTrjw=
|
||||
github.com/kyoh86/nolint v0.0.1 h1:GjNxDEkVn2wAxKHtP7iNTrRxytRZ1wXxLV5j4XzGfRU=
|
||||
github.com/kyoh86/nolint v0.0.1/go.mod h1:1ZiZZ7qqrZ9dZegU96phwVcdQOMKIqRzFJL3ewq9gtI=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA=
|
||||
github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
||||
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
||||
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/securego/gosec/v2 v2.18.2 h1:DkDt3wCiOtAHf1XkiXZBhQ6m6mK/b9T/wD257R3/c+I=
|
||||
github.com/securego/gosec/v2 v2.18.2/go.mod h1:xUuqSF6i0So56Y2wwohWAmB07EdBkUN6crbLlHwbyJs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/securego/gosec/v2 v2.19.0 h1:gl5xMkOI0/E6Hxx0XCY2XujA3V7SNSefA8sC+3f1gnk=
|
||||
github.com/securego/gosec/v2 v2.19.0/go.mod h1:hOkDcHz9J/XIgIlPDXalxjeVYsHxoWUc5zJSHxcB8YM=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI=
|
||||
@ -65,27 +63,26 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s=
|
||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp/typeparams v0.0.0-20231127185646-65229373498e h1:Iel2aGgaO80fSb1N54L7SE6XMeVvYy6caKt8u/5LvR8=
|
||||
golang.org/x/exp/typeparams v0.0.0-20231127185646-65229373498e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/exp/typeparams v0.0.0-20240222234643-814bf88cf225 h1:BzKNaIRXh1bD+1557OcFIHlpYBiVbK4zEyn8zBHi1SE=
|
||||
golang.org/x/exp/typeparams v0.0.0-20240222234643-814bf88cf225/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -96,41 +93,38 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
|
||||
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU=
|
||||
golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/vuln v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I=
|
||||
golang.org/x/vuln v1.0.4/go.mod h1:NbJdUQhX8jY++FtuhrXs2Eyx0yePo9pF7nPlIjo9aaQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=
|
||||
honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
|
||||
mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E=
|
||||
mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js=
|
||||
mvdan.cc/unparam v0.0.0-20230917202934-3ee2d22f45fb h1:xiF91GJnDSbyPdiZB5d52N2VpZfGhjM4Ji75cjzuooQ=
|
||||
mvdan.cc/unparam v0.0.0-20230917202934-3ee2d22f45fb/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI=
|
||||
honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs=
|
||||
honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
|
||||
mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo=
|
||||
mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA=
|
||||
mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w=
|
||||
mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI=
|
||||
|
@ -10,10 +10,10 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
)
|
||||
|
||||
// Config is the AdGuard DNS web service configuration structure.
|
||||
@ -201,11 +201,16 @@ func blockPageServers(
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ agdservice.Interface = (*Service)(nil)
|
||||
var _ service.Interface = (*Service)(nil)
|
||||
|
||||
// Start implements the [agdservice.Interface] interface for *Service. svc may
|
||||
// be nil. It panics if one of the servers could not start.
|
||||
func (svc *Service) Start(ctx context.Context) (err error) {
|
||||
// Start implements the [service.Interface] interface for *Service. It starts
|
||||
// serving all endpoints but does not wait for them to actually go online. svc
|
||||
// may be nil. err is always nil; if any endpoint fails to start, it panics.
|
||||
//
|
||||
// TODO(a.garipov): Wait for the services to go online.
|
||||
//
|
||||
// TODO(a.garipov): Use the context for cancelation.
|
||||
func (svc *Service) Start(_ context.Context) (err error) {
|
||||
if svc == nil {
|
||||
return nil
|
||||
}
|
||||
@ -261,8 +266,8 @@ func mustStartServer(srv *http.Server) {
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown implements the [agdservice.Interface] interface for *Service. svc
|
||||
// may be nil.
|
||||
// Shutdown implements the [service.Interface] interface for *Service. svc may
|
||||
// be nil.
|
||||
func (svc *Service) Shutdown(ctx context.Context) (err error) {
|
||||
if svc == nil {
|
||||
return nil
|
||||
|
@ -95,11 +95,11 @@ func mockDNSProfile() (dp *backendpb.DNSProfile) {
|
||||
}
|
||||
|
||||
devices := []*backendpb.DeviceSettings{{
|
||||
Id: "118ffe93",
|
||||
Name: "118ffe93-name",
|
||||
Id: "test",
|
||||
Name: "test-name",
|
||||
FilteringEnabled: false,
|
||||
LinkedIp: []byte{1, 1, 1, 1},
|
||||
DedicatedIps: [][]byte{{1, 1, 1, 2}},
|
||||
DedicatedIps: [][]byte{{127, 0, 0, 1}},
|
||||
}}
|
||||
|
||||
return &backendpb.DNSProfile{
|
||||
|
33
scripts/make/go-upd-tools.sh
Normal file
33
scripts/make/go-upd-tools.sh
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This comment is used to simplify checking local copies of the script. Bump
|
||||
# this number every time a significant change is made to this script.
|
||||
#
|
||||
# AdGuard-Project-Version: 1
|
||||
|
||||
verbose="${VERBOSE:-0}"
|
||||
readonly verbose
|
||||
|
||||
if [ "$verbose" -gt '1' ]
|
||||
then
|
||||
env
|
||||
set -x
|
||||
x_flags='-x=1'
|
||||
elif [ "$verbose" -gt '0' ]
|
||||
then
|
||||
set -x
|
||||
x_flags='-x=0'
|
||||
else
|
||||
set +x
|
||||
x_flags='-x=0'
|
||||
fi
|
||||
readonly x_flags
|
||||
|
||||
set -e -f -u
|
||||
|
||||
go="${GO:-go}"
|
||||
readonly go
|
||||
|
||||
cd ./internal/tools/
|
||||
"$go" get -u
|
||||
"$go" mod tidy
|
Loading…
x
Reference in New Issue
Block a user