mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
Sync v2.7.0
This commit is contained in:
parent
b6e37914aa
commit
5690301129
95
CHANGELOG.md
95
CHANGELOG.md
@ -11,6 +11,98 @@ The format is **not** based on [Keep a Changelog][kec], since the project
|
||||
|
||||
|
||||
|
||||
## AGDNS-2048 / Build 750
|
||||
|
||||
* The environment variables `RESEARCH_LOGS` and `RESEARCH_METRICS` have been
|
||||
removed.
|
||||
|
||||
|
||||
|
||||
## AGDNS-2022 / Build 746
|
||||
|
||||
* The property `block_page_redirect` of objects within `server_groups` array
|
||||
has been removed.
|
||||
|
||||
|
||||
|
||||
## AGDNS-1981 / Build 744
|
||||
|
||||
* The objects within `server_groups` array had a change in their
|
||||
`block_page_redirect` configuration, it now supports arrays of IP addresses
|
||||
in `ipv4` and `ipv6` fields.
|
||||
|
||||
* Profile's file cache version was incremented. In case of
|
||||
`BlockingModeCustomIP` the `profile.blocking_mode` IPv4/IPv6 fields are now
|
||||
arrays of IP addresses.
|
||||
|
||||
|
||||
|
||||
## AGDNS-2012 / Build 732
|
||||
|
||||
* The querylog now has a new field, `"rn"`, which is a 16-bit unsigned random
|
||||
number. Field `"u"`, the unique request ID, is deprecated and may be
|
||||
removed in the future.
|
||||
|
||||
|
||||
|
||||
## AGDNS-1879 / Build 729
|
||||
|
||||
* Profile's file cache version was incremented. The new field
|
||||
`authentication` has been added to profile's device object.
|
||||
|
||||
|
||||
|
||||
## AGDNS-1934 / Build 728
|
||||
|
||||
* The object `filters` has new properties: `index_refresh_timeout`, and
|
||||
`rule_list_refresh_timeout`. So replace this:
|
||||
|
||||
```yaml
|
||||
filters:
|
||||
# …
|
||||
```
|
||||
|
||||
with this:
|
||||
|
||||
```yaml
|
||||
filters:
|
||||
# …
|
||||
index_refresh_timeout: 1m
|
||||
rule_list_refresh_timeout: 1m
|
||||
```
|
||||
|
||||
* The objects `safe_browsing` and `adult_blocking` have a new property:
|
||||
`refresh_timeout`. So replace this:
|
||||
|
||||
```yaml
|
||||
safe_browsing:
|
||||
# …
|
||||
# …
|
||||
adult_blocking:
|
||||
# …
|
||||
```
|
||||
|
||||
with this:
|
||||
|
||||
```yaml
|
||||
safe_browsing:
|
||||
# …
|
||||
refresh_timeout: 1m
|
||||
# …
|
||||
adult_blocking:
|
||||
# …
|
||||
refresh_timeout: 1m
|
||||
```
|
||||
|
||||
|
||||
|
||||
## AGDNS-1954 / Build 726
|
||||
|
||||
* The object `web` has a new optional property, `general_blocking`. Its
|
||||
format is the same as in `adult_blocking` and `safe_browsing`.
|
||||
|
||||
|
||||
|
||||
## AGDNS-1954 / Build 719
|
||||
|
||||
* The objects within `server_groups` array have a new property
|
||||
@ -37,6 +129,9 @@ The format is **not** based on [Keep a Changelog][kec], since the project
|
||||
probability: 0.01
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For `ipv4` and `ipv6` only one address is currently supported.
|
||||
|
||||
For server groups that do not require a block-page redirect, set:
|
||||
|
||||
```yaml
|
||||
|
6
Makefile
6
Makefile
@ -8,7 +8,7 @@
|
||||
# Makefile. Bump this number every time a significant change is made to
|
||||
# this Makefile.
|
||||
#
|
||||
# AdGuard-Project-Version: 4
|
||||
# AdGuard-Project-Version: 5
|
||||
|
||||
# Don't name these macros "GO" etc., because GNU Make apparently makes
|
||||
# them exported environment variables with the literal value of
|
||||
@ -22,8 +22,8 @@ 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.8
|
||||
GOPROXY = https://proxy.golang.org|direct
|
||||
GOTOOLCHAIN = go1.22.4
|
||||
RACE = 0
|
||||
REVISION = $$( git rev-parse --short HEAD )
|
||||
VERSION = 0
|
||||
|
@ -196,33 +196,44 @@ web:
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
# Optional safe browsing web server configuration. static_content is not
|
||||
# Optional adult blocking web server configuration. static_content is not
|
||||
# served on these addresses. The addresses should be the same as in the
|
||||
# safe_browsing object.
|
||||
safe_browsing:
|
||||
# general_blocking and safe_browsing objects.
|
||||
adult_blocking:
|
||||
bind:
|
||||
- address: '127.0.0.1:9081'
|
||||
- address: '127.0.0.1:9444'
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
block_page: './test/block_page_sb.html'
|
||||
# Optional adult blocking web server configuration. static_content is not
|
||||
block_page: './test/block_page_adult.html'
|
||||
# Optional general blocking web server configuration. static_content is not
|
||||
# served on these addresses. The addresses should be the same as in the
|
||||
# adult_blocking object.
|
||||
adult_blocking:
|
||||
# adult_blocking and safe_browsing objects.
|
||||
general_blocking:
|
||||
bind:
|
||||
- address: '127.0.0.1:9082'
|
||||
- address: '127.0.0.1:9445'
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
block_page: './test/block_page_adult.html'
|
||||
block_page: './test/block_page_general.html'
|
||||
# Optional safe browsing web server configuration. static_content is not
|
||||
# served on these addresses. The addresses should be the same as in the
|
||||
# general_blocking and safe_browsing objects.
|
||||
safe_browsing:
|
||||
bind:
|
||||
- address: '127.0.0.1:9083'
|
||||
- address: '127.0.0.1:9446'
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
block_page: './test/block_page_sb.html'
|
||||
# Listen addresses for the web service in addition to the ones in the
|
||||
# DNS-over-HTTPS handlers.
|
||||
non_doh_bind:
|
||||
- address: '127.0.0.1:9083'
|
||||
- address: '127.0.0.1:9446'
|
||||
- address: '127.0.0.1:9084'
|
||||
- address: '127.0.0.1:9447'
|
||||
certificates:
|
||||
- certificate: './test/cert.crt'
|
||||
key: './test/cert.key'
|
||||
@ -253,6 +264,7 @@ safe_browsing:
|
||||
cache_size: 1024
|
||||
cache_ttl: 1h
|
||||
refresh_interval: 1h
|
||||
refresh_timeout: 1m
|
||||
|
||||
# AdGuard adult content blocking filter configuration.
|
||||
adult_blocking:
|
||||
@ -260,8 +272,12 @@ adult_blocking:
|
||||
cache_size: 1024
|
||||
cache_ttl: 1h
|
||||
refresh_interval: 1h
|
||||
refresh_timeout: 1m
|
||||
|
||||
# Settings for rule-list-based filters.
|
||||
#
|
||||
# TODO(a.garipov): Add the timeout for the blocked-service index refresh. It
|
||||
# is currently hardcoded to 3 minutes.
|
||||
filters:
|
||||
# The TTL to set for responses to requests for filtered domains.
|
||||
response_ttl: 5m
|
||||
@ -273,9 +289,17 @@ filters:
|
||||
# How often to update filters from the index. See the documentation for the
|
||||
# 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 3m timeout.
|
||||
# The timeout for the entire filter update operation. Note that filter
|
||||
# rule-list index and each filter rule-list update operations have their own
|
||||
# timeouts, see index_refresh_timeout and rule_list_refresh_timeout.
|
||||
refresh_timeout: 5m
|
||||
# The timeout for the filter rule-list index update operation. See also
|
||||
# refresh_timeout for the entire filter update operation.
|
||||
index_refresh_timeout: 1m
|
||||
# The timeout for the filter update operation of each rule-list, including
|
||||
# the safe-search ones. See also refresh_timeout for the entire filter
|
||||
# update operation.
|
||||
rule_list_refresh_timeout: 1m
|
||||
# MaxSize is the maximum size of the downloadable filtering rule-list.
|
||||
max_size: 256MB
|
||||
# Rule list cache.
|
||||
@ -351,38 +375,6 @@ server_groups:
|
||||
- name: 'adguard_dns_default'
|
||||
# This filtering_group is used for all anonymous clients.
|
||||
filtering_group: 'default'
|
||||
# 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
|
||||
|
@ -28,7 +28,6 @@ configuration file with comments.
|
||||
* [Filtering groups](#filtering_groups)
|
||||
* [Network interface listeners](#interface_listeners)
|
||||
* [Server groups](#server_groups)
|
||||
* [Block-page redirecting](#server_groups-*-block_page_redirect)
|
||||
* [DDR](#server_groups-*-ddr)
|
||||
* [TLS](#server_groups-*-tls)
|
||||
* [Servers](#server_groups-*-servers-*)
|
||||
@ -609,9 +608,9 @@ The optional `web` object has the following properties:
|
||||
```
|
||||
|
||||
* <a href="#web-safe_browsing" id="web-safe_browsing" name="web-safe_browsing">`safe_browsing`</a>:
|
||||
The optional safe browsing web server configurations. Every request is
|
||||
responded with the content from the file to which the `block_page` property
|
||||
points.
|
||||
The optional safe browsing block-page web server configurations. Every
|
||||
request is responded with the content from the file to which the
|
||||
`block_page` property points.
|
||||
|
||||
See the [full description of this API][http-block-pages] on the HTTP API
|
||||
page.
|
||||
@ -639,10 +638,15 @@ The optional `web` object has the following properties:
|
||||
```
|
||||
|
||||
* <a href="#web-adult_blocking" id="web-adult_blocking" name="web-adult_blocking">`adult_blocking`</a>:
|
||||
The optional adult blocking web server configurations. The format of the
|
||||
The optional adult block-page web server configuration. The format of the
|
||||
values is the same as in the [`safe_browsing`](#web-safe_browsing) object
|
||||
above.
|
||||
|
||||
* <a href="#web-general_blocking" id="web-general_blocking" name="web-general_blocking">`general_blocking`</a>:
|
||||
The optional general block-page web server configuration. The format of
|
||||
the values is the same as in the [`safe_browsing`](#web-safe_browsing)
|
||||
object above.
|
||||
|
||||
* <a href="#web-non_doh_bind" id="web-non_doh_bind" name="web-non_doh_bind">`non_doh_bind`</a>:
|
||||
The optional listen addresses and optional TLS configuration for the web
|
||||
service in addition to the ones in the DNS-over-HTTPS handlers. The
|
||||
@ -669,6 +673,9 @@ The optional `web` object has the following properties:
|
||||
|
||||
Inside of the `headers` map, the header `Content-Type` is required.
|
||||
|
||||
> [!NOTE]
|
||||
> Paths are case-sensitive.
|
||||
|
||||
**Property example:**
|
||||
|
||||
```yaml
|
||||
@ -735,6 +742,11 @@ The `safe_browsing` object has the following properties:
|
||||
|
||||
**Example:** `1m`.
|
||||
|
||||
* <a href="#safe_browsing-refresh_timeout" id="safe_browsing-refresh_timeout" name="safe_browsing-refresh_timeout">`refresh_timeout`</a>:
|
||||
The timeout for the update operation, as a human-readable duration.
|
||||
|
||||
**Example:** `1m`.
|
||||
|
||||
|
||||
|
||||
## <a href="#adult_blocking" id="adult_blocking" name="adult_blocking">Adult-content blocking</a>
|
||||
@ -746,6 +758,9 @@ The `adult_blocking` object has the same properties as the
|
||||
|
||||
## <a href="#filters" id="filters" name="filters">Filter Lists</a>
|
||||
|
||||
**TODO(a.garipov):** Add the timeout for the blocked-service index refresh. It
|
||||
is currently hardcoded to 3 minutes.
|
||||
|
||||
The `filters` object has the following properties:
|
||||
|
||||
* <a href="#filters-response_ttl" id="filters-response_ttl" name="filters-response_ttl">`response_ttl`</a>:
|
||||
@ -777,11 +792,29 @@ 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 3m timeout.
|
||||
duration. Note that filter rule-list index and each filter rule-list
|
||||
update operations have their own timeouts, see
|
||||
[`index_refresh_timeout`](#filters-index_refresh_timeout) and
|
||||
[`rule_list_refresh_timeout`](#filters-rule_list_refresh_timeout).
|
||||
|
||||
**Example:** `5m`.
|
||||
|
||||
* <a href="#filters-index_refresh_timeout" id="filters-index_refresh_timeout" name="filters-index_refresh_timeout">`index_refresh_timeout`</a>:
|
||||
The timeout for the filter rule-list index update operation, as a
|
||||
human-readable duration. See also
|
||||
[`refresh_timeout`](#filters-refresh_timeout) for the entire filter update
|
||||
operation.
|
||||
|
||||
**Example:** `1m`.
|
||||
|
||||
* <a href="#filters-rule_list_refresh_timeout" id="filters-rule_list_refresh_timeout" name="filters-rule_list_refresh_timeout">`rule_list_refresh_timeout`</a>:
|
||||
The timeout for the filter update operation of each rule-list, including the
|
||||
safe-search ones, as a human-readable duration. See also
|
||||
[`refresh_timeout`](#filters-refresh_timeout) for the entire filter update
|
||||
operation.
|
||||
|
||||
**Example:** `1m`.
|
||||
|
||||
* <a href="#filters-max_size" id="filters-max_size" name="filters-max_size">`max_size`</a>:
|
||||
The maximum size of the downloadable content for a rule-list in a
|
||||
human-readable format.
|
||||
@ -939,9 +972,6 @@ The items of the `server_groups` array have the following properties:
|
||||
|
||||
**Example:** `default`.
|
||||
|
||||
* `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).
|
||||
@ -956,69 +986,6 @@ The items of the `server_groups` array have the following properties:
|
||||
|
||||
|
||||
|
||||
### <a href="#server_groups-*-block_page_redirect" id="server_groups-*-block_page_redirect" name="server_groups-*-block_page_redirect">Block-page redirecting</a>
|
||||
|
||||
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
|
||||
apply:
|
||||
client:
|
||||
- address: '192.168.0.0/16'
|
||||
- address: '1.2.3.4'
|
||||
```
|
||||
|
||||
* <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
|
||||
skip:
|
||||
client:
|
||||
- address: '1.2.0.0/16'
|
||||
- address: '5.6.7.8'
|
||||
question:
|
||||
- domain: 'do-not-show-block.site.example'
|
||||
```
|
||||
|
||||
* <a href="#sg-*-bpr-probability" id="sg-*-bpr-probability" name="sg-*-bpr-probability">`probability`</a>:
|
||||
|
||||
The probability of responding with the block page IPs based on remote
|
||||
address. Must be between `0.0` and `1.0`.
|
||||
|
||||
|
||||
|
||||
### <a href="#server_groups-*-ddr" id="server_groups-*-ddr" name="server_groups-*-ddr">DDR</a>
|
||||
|
||||
The DDR configuration object. Many of these data duplicate data from objects in
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
Development is supported on Linux and macOS (aka Darwin) systems.
|
||||
|
||||
1. Install Go 1.21 or later.
|
||||
1. Install Go 1.22 or later.
|
||||
|
||||
1. Call `make init` to set up the Git pre-commit hook.
|
||||
|
||||
@ -219,15 +219,15 @@ curl 'https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/GeoIP2
|
||||
|
||||
You'll need to supply the following:
|
||||
|
||||
* [`ADULT_BLOCKING_URL`](#env-ADULT_BLOCKING_URL)
|
||||
* [`BILLSTAT_URL`](#env-BILLSTAT_URL)
|
||||
* [`CONSUL_ALLOWLIST_URL`](#env-CONSUL_ALLOWLIST_URL)
|
||||
* [`GENERAL_SAFE_SEARCH_URL`](#env-GENERAL_SAFE_SEARCH_URL)
|
||||
* [`LINKED_IP_TARGET_URL`](#env-LINKED_IP_TARGET_URL)
|
||||
* [`NEW_REG_DOMAINS_URL`](#env-NEW_REG_DOMAINS_URL)
|
||||
* [`PROFILES_URL`](#env-PROFILES_URL)
|
||||
* [`SAFE_BROWSING_URL`](#env-SAFE_BROWSING_URL)
|
||||
* [`YOUTUBE_SAFE_SEARCH_URL`](#env-YOUTUBE_SAFE_SEARCH_URL)
|
||||
* [`ADULT_BLOCKING_URL`][env-ADULT_BLOCKING_URL]
|
||||
* [`BILLSTAT_URL`][env-BILLSTAT_URL]
|
||||
* [`CONSUL_ALLOWLIST_URL`][env-CONSUL_ALLOWLIST_URL]
|
||||
* [`GENERAL_SAFE_SEARCH_URL`][env-GENERAL_SAFE_SEARCH_URL]
|
||||
* [`LINKED_IP_TARGET_URL`][env-LINKED_IP_TARGET_URL]
|
||||
* [`NEW_REG_DOMAINS_URL`][env-NEW_REG_DOMAINS_URL]
|
||||
* [`PROFILES_URL`][env-PROFILES_URL]
|
||||
* [`SAFE_BROWSING_URL`][env-SAFE_BROWSING_URL]
|
||||
* [`YOUTUBE_SAFE_SEARCH_URL`][env-YOUTUBE_SAFE_SEARCH_URL]
|
||||
|
||||
See the [external HTTP API documentation][externalhttp].
|
||||
|
||||
@ -280,6 +280,16 @@ env \
|
||||
./AdGuardDNS
|
||||
```
|
||||
|
||||
[env-ADULT_BLOCKING_URL]: environment.md#ADULT_BLOCKING_URL
|
||||
[env-BILLSTAT_URL]: environment.md#BILLSTAT_URL
|
||||
[env-CONSUL_ALLOWLIST_URL]: environment.md#CONSUL_ALLOWLIST_URL
|
||||
[env-GENERAL_SAFE_SEARCH_URL]: environment.md#GENERAL_SAFE_SEARCH_URL
|
||||
[env-LINKED_IP_TARGET_URL]: environment.md#LINKED_IP_TARGET_URL
|
||||
[env-NEW_REG_DOMAINS_URL]: environment.md#NEW_REG_DOMAINS_URL
|
||||
[env-PROFILES_URL]: environment.md#PROFILES_URL
|
||||
[env-SAFE_BROWSING_URL]: environment.md#SAFE_BROWSING_URL
|
||||
[env-YOUTUBE_SAFE_SEARCH_URL]: environment.md#YOUTUBE_SAFE_SEARCH_URL
|
||||
|
||||
[externalhttp]: externalhttp.md
|
||||
|
||||
|
||||
|
@ -26,8 +26,6 @@ sensitive configuration. All other configuration is stored in the
|
||||
* [`PROFILES_ENABLED`](#PROFILES_ENABLED)
|
||||
* [`PROFILES_URL`](#PROFILES_URL)
|
||||
* [`QUERYLOG_PATH`](#QUERYLOG_PATH)
|
||||
* [`RESEARCH_LOGS`](#RESEARCH_LOGS)
|
||||
* [`RESEARCH_METRICS`](#RESEARCH_METRICS)
|
||||
* [`RULESTAT_URL`](#RULESTAT_URL)
|
||||
* [`SAFE_BROWSING_URL`](#SAFE_BROWSING_URL)
|
||||
* [`SENTRY_DSN`](#SENTRY_DSN)
|
||||
@ -264,25 +262,6 @@ The path to the file into which the query log is going to be written.
|
||||
|
||||
|
||||
|
||||
## <a href="#RESEARCH_METRICS" id="RESEARCH_METRICS" name="RESEARCH_METRICS">`RESEARCH_METRICS`</a>
|
||||
|
||||
If `1`, enable collection of a set of special prometheus metrics (prefix is
|
||||
`dns_research`). If `0`, disable collection of those metrics.
|
||||
|
||||
**Default:** `0`.
|
||||
|
||||
|
||||
|
||||
## <a href="#RESEARCH_LOGS" id="RESEARCH_LOGS" name="RESEARCH_LOGS">`RESEARCH_LOGS`</a>
|
||||
|
||||
If `1`, enable logging of additional info that may be required for research
|
||||
purposes (prefix `research:`). The log will only be written when
|
||||
`RESEARCH_METRICS` is also set to `1`. If `0`, disable logging of this info.
|
||||
|
||||
**Default:** `0`.
|
||||
|
||||
|
||||
|
||||
## <a href="#RULESTAT_URL" id="RULESTAT_URL" name="RULESTAT_URL">`RULESTAT_URL`</a>
|
||||
|
||||
The URL to send filtering rule list statistics to. If empty or unset, the
|
||||
|
@ -17,9 +17,9 @@ appropriately.
|
||||
|
||||
## <a href="#block-pages" id="block-pages" name="block-pages">Block Pages</a>
|
||||
|
||||
The safe browsing and adult blocking servers. Every request is responded with
|
||||
the content from the configured file, with the exception of `GET /favicon.ico`
|
||||
and `GET /robots.txt` requests, which are handled separately:
|
||||
The safe-browsing, adult-blocking, and popup-blocking servers. Every request is
|
||||
responded with the content from the configured file, with the exception of `GET
|
||||
/favicon.ico` and `GET /robots.txt` requests, which are handled separately:
|
||||
|
||||
* `GET /favicon.ico` requests are responded with a plain-text `404 Not Found`
|
||||
response.
|
||||
|
@ -5,8 +5,8 @@ entries are designed to be concise and easily compressable. An example of the
|
||||
log output:
|
||||
|
||||
```jsonl
|
||||
{"u":"ABCD","b":"prof1234","i":"dev1234","c":"RU","d":"US","n":"example.com.","l":"cdef5678","m":"||example.com^","t":1628590394000,"a":1234,"e":5,"q":1,"f":2,"s":0,"p":8,"r":0}
|
||||
{"u":"DEFG","b":"prof1234","i":"dev1234","c":"RU","d":"JP","n":"example.org.","l":"hijk9012","m":"||example.org^","t":1628590394100,"a":6789,"e":6,"q":1,"f":2,"s":0,"p":8,"r":0}
|
||||
{"u":"ABCD","b":"prof1234","i":"dev1234","c":"RU","d":"US","n":"example.com.","l":"cdef5678","m":"||example.com^","t":1628590394000,"a":1234,"e":5,"q":1,"rn":1234,"f":2,"s":0,"p":8,"r":0}
|
||||
{"u":"DEFG","b":"prof1234","i":"dev1234","c":"RU","d":"JP","n":"example.org.","l":"hijk9012","m":"||example.org^","t":1628590394100,"a":6789,"e":6,"q":1,"rn":56789,"f":2,"s":0,"p":8,"r":0}
|
||||
```
|
||||
|
||||
AdGuard DNS opens and closes the log file on each write to prevent issues with
|
||||
@ -24,6 +24,9 @@ rules to remember, which property means what. The properties are:
|
||||
* <a href="#properties-u" id="properties-u" name="properties-u">`u`</a>:
|
||||
The unique ID of the request. The short name `u` stands for “unique”.
|
||||
|
||||
> [!NOTE]
|
||||
> This field is deprecated and may be removed in the future.
|
||||
|
||||
**Example:** `"ABCD1234"`
|
||||
|
||||
* <a href="#properties-b" id="properties-b" name="properties-b">`b`</a>:
|
||||
@ -141,6 +144,12 @@ rules to remember, which property means what. The properties are:
|
||||
|
||||
See [this Wikipedia list][wiki-dnsrr] for numeric values and their meanings.
|
||||
|
||||
* <a href="#properties-rn" id="properties-rn" name="properties-rn">`rn`</a>:
|
||||
A random 16-bit unsigned integer added to an entry for easier deduplication
|
||||
when `"u"` is not used for that.
|
||||
|
||||
**Example:** `12345`
|
||||
|
||||
* <a href="#properties-f" id="properties-f" name="properties-f">`f`</a>:
|
||||
The action taken with this request. The short name `f` stands for
|
||||
“filtering”. The possible values are:
|
||||
|
48
go.mod
48
go.mod
@ -1,13 +1,13 @@
|
||||
module github.com/AdguardTeam/AdGuardDNS
|
||||
|
||||
go 1.21.8
|
||||
go 1.22.4
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-00010101000000-000000000000
|
||||
github.com/AdguardTeam/golibs v0.20.1
|
||||
github.com/AdguardTeam/golibs v0.23.2
|
||||
github.com/AdguardTeam/urlfilter v0.18.0
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
|
||||
github.com/caarlos0/env/v7 v7.1.0
|
||||
@ -16,17 +16,18 @@ require (
|
||||
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.18.0
|
||||
github.com/prometheus/client_model v0.5.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-20240213143201-ec583247a57a
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/common v0.52.3
|
||||
github.com/quic-go/quic-go v0.42.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/crypto v0.22.0
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/grpc v1.61.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/protobuf v1.33.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@ -35,23 +36,22 @@ require (
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||
github.com/ameshkov/dnsstamps v1.0.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
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-20240207164012-fb44976bdcd5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/panjf2000/ants/v2 v2.9.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||
github.com/panjf2000/ants/v2 v2.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/procfs v0.13.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.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/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.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
|
||||
golang.org/x/tools v0.20.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
101
go.sum
101
go.sum
@ -1,17 +1,17 @@
|
||||
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/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
|
||||
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
|
||||
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=
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7 h1:aEitLIR8HcxVodZ79mgRcCiC0A0I5kZPBuWGFwwulAw=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7/go.mod h1:qPWhwz6FdSmuK7W4sMyvogrez4MWdtzosdqlr0Rg3ow=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0 h1:pDXDF7eFa6Lw+04C0hoMh8kCAQM8NwUdFEllSP2zNLs=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0/go.mod h1:N5hDwgx2cNb4Ay7AhvOSKst+eUiOZ/vbKRO9qMpQttE=
|
||||
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-20240124082744-24bca3a5b39b h1:F3yMzKumBUQ6Fn0sYI1YQ16vQRucpZOfBQ9HXWl5+XI=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02 h1:bXAPYSbdYbS5VTy92NIUbeDI1qyggi+JYh5op9IFlcQ=
|
||||
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02/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=
|
||||
@ -20,8 +20,8 @@ github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXye
|
||||
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=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
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=
|
||||
@ -38,14 +38,12 @@ 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.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/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
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=
|
||||
@ -56,14 +54,14 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
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/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
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.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo=
|
||||
github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||
github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw=
|
||||
github.com/panjf2000/ants/v2 v2.9.1/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=
|
||||
@ -74,18 +72,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.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.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/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
||||
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||
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/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
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=
|
||||
@ -99,8 +97,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
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=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
@ -109,34 +107,31 @@ github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFi
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
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/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
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/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.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-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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 h1:zviK8GX4VlMstrK3JkexM5UHjH1VOkRebH9y3jhSBGk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.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=
|
||||
|
53
go.work.sum
53
go.work.sum
@ -6,7 +6,10 @@ 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 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
|
||||
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
|
||||
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=
|
||||
@ -51,6 +54,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 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||
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=
|
||||
@ -100,7 +104,10 @@ github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nC
|
||||
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 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
||||
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=
|
||||
@ -113,9 +120,13 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi
|
||||
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/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
|
||||
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
|
||||
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/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
||||
@ -171,7 +182,10 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekf
|
||||
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 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
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=
|
||||
@ -200,7 +214,10 @@ 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 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/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=
|
||||
@ -223,6 +240,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/influxdata/influxdb v1.7.6 h1:8mQ7A/V+3noMGCt/P9pD09ISaiz9XvgCk303UYA3gcs=
|
||||
github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
|
||||
github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
|
||||
@ -313,6 +332,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 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
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=
|
||||
@ -424,6 +444,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -477,12 +499,15 @@ golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0
|
||||
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/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
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=
|
||||
golang.org/x/exp v0.0.0-20230306221820-f0f767cdffd6/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp v0.0.0-20230807204917-050eac23e9de/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
||||
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -514,6 +539,9 @@ golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -524,7 +552,10 @@ 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 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
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=
|
||||
@ -553,7 +584,13 @@ 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/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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=
|
||||
@ -568,7 +605,12 @@ 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 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
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=
|
||||
@ -591,6 +633,7 @@ 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
@ -604,6 +647,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 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
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=
|
||||
@ -615,11 +659,16 @@ 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 v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo=
|
||||
google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
|
||||
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 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
|
||||
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=
|
||||
|
@ -71,7 +71,6 @@ func TestBlockedHostEngine_IsBlocked(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -90,7 +89,7 @@ func TestBlockedHostEngine_IsBlocked_concurrent(t *testing.T) {
|
||||
engine := newBlockedHostEngine(rules)
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
for i := 0; i < routinesLimit; i++ {
|
||||
for i := range routinesLimit {
|
||||
wg.Add(1)
|
||||
|
||||
host := fmt.Sprintf("%d.%s", i, "block.test")
|
||||
|
@ -236,7 +236,7 @@ func BenchmarkDefaultProfile_IsBlocked(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
_ = a.IsBlocked(passReq, passAddrPort, nil)
|
||||
}
|
||||
})
|
||||
@ -247,7 +247,7 @@ func BenchmarkDefaultProfile_IsBlocked(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
_ = a.IsBlocked(blockReq, passAddrPort, nil)
|
||||
}
|
||||
})
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"net/netip"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
)
|
||||
@ -16,6 +17,9 @@ import (
|
||||
// NOTE: Do not change fields of this structure without incrementing
|
||||
// [internal/profiledb/internal.FileCacheVersion].
|
||||
type Device struct {
|
||||
// Auth defines authentication settings of this device. It's never nil.
|
||||
Auth *AuthSettings
|
||||
|
||||
// ID is the unique ID of the device.
|
||||
ID DeviceID
|
||||
|
||||
@ -104,3 +108,20 @@ func NewDeviceName(s string) (n DeviceName, err error) {
|
||||
|
||||
return DeviceName(s), nil
|
||||
}
|
||||
|
||||
// AuthSettings are the authentication settings of a device.
|
||||
//
|
||||
// NOTE: Do not change fields of this structure without incrementing
|
||||
// [internal/profiledb/internal.FileCacheVersion].
|
||||
type AuthSettings struct {
|
||||
// PasswordHash is the hash of the auth password. It is never nil.
|
||||
PasswordHash agdpasswd.Authenticator
|
||||
|
||||
// Enabled tells whether the authentication should be enabled at all.
|
||||
// This must be true in order for all parameters to work.
|
||||
Enabled bool
|
||||
|
||||
// DoHAuthOnly defines if the device should only be authenticated through
|
||||
// DoH protocol.
|
||||
DoHAuthOnly bool
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ func TestNewDeviceName(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -17,33 +17,41 @@ const (
|
||||
// FilterListIDNone means that no filter were applied at all.
|
||||
FilterListIDNone FilterListID = ""
|
||||
|
||||
// FilterListIDBlockedService is the shared filter list ID used when a
|
||||
// FilterListIDBlockedService is the shared filter-list ID used when a
|
||||
// request was blocked by the service blocker.
|
||||
FilterListIDBlockedService FilterListID = "blocked_service"
|
||||
|
||||
// FilterListIDCustom is the special shared filter list ID used when
|
||||
// FilterListIDCustom is the special shared filter-list ID used when
|
||||
// a request was filtered by a custom profile rule.
|
||||
FilterListIDCustom FilterListID = "custom"
|
||||
|
||||
// FilterListIDAdultBlocking is the special shared filter list ID used when
|
||||
// FilterListIDAdultBlocking is the special shared filter-list ID used when
|
||||
// a request was filtered by the adult content blocking filter.
|
||||
FilterListIDAdultBlocking FilterListID = "adult_blocking"
|
||||
|
||||
// FilterListIDSafeBrowsing is the special shared filter list ID used when
|
||||
// FilterListIDSafeBrowsing is the special shared filter-list ID used when
|
||||
// a request was filtered by the safe browsing filter.
|
||||
FilterListIDSafeBrowsing FilterListID = "safe_browsing"
|
||||
|
||||
// FilterListIDNewRegDomains is the special shared filter list ID used when
|
||||
// FilterListIDNewRegDomains is the special shared filter-list ID used when
|
||||
// a request was filtered by the newly registered domains filter.
|
||||
FilterListIDNewRegDomains FilterListID = "newly_registered_domains"
|
||||
|
||||
// FilterListIDGeneralSafeSearch is the shared filter list ID used when
|
||||
// FilterListIDGeneralSafeSearch is the shared filter-list ID used when
|
||||
// a request was modified by the general safe search filter.
|
||||
FilterListIDGeneralSafeSearch FilterListID = "general_safe_search"
|
||||
|
||||
// FilterListIDYoutubeSafeSearch is the special shared filter list ID used
|
||||
// FilterListIDYoutubeSafeSearch is the special shared filter-list ID used
|
||||
// when a request was modified by the YouTube safe search filter.
|
||||
FilterListIDYoutubeSafeSearch FilterListID = "youtube_safe_search"
|
||||
|
||||
// FilterListIDAdGuardDNS is the special filter-list ID of the main AdGuard
|
||||
// DNS filtering-rule list. For this list, rule statistics are collected.
|
||||
FilterListIDAdGuardDNS FilterListID = "adguard_dns_filter"
|
||||
|
||||
// FilterListIDAdGuardPopup is the special filter-list ID of the AdGuard DNS
|
||||
// list of popup domains.
|
||||
FilterListIDAdGuardPopup FilterListID = "adguard_popup_filter"
|
||||
)
|
||||
|
||||
// The maximum and minimum lengths of a filter list ID.
|
||||
@ -72,6 +80,21 @@ func NewFilterListID(s string) (id FilterListID, err error) {
|
||||
return FilterListID(s), nil
|
||||
}
|
||||
|
||||
// SupportsDNSRewrite returns true if the $dnsrewrite rules in filtering-rule
|
||||
// lists with this ID should be processed.
|
||||
func (id FilterListID) SupportsDNSRewrite() (ok bool) {
|
||||
switch id {
|
||||
case
|
||||
FilterListIDAdGuardPopup,
|
||||
FilterListIDCustom,
|
||||
FilterListIDGeneralSafeSearch,
|
||||
FilterListIDYoutubeSafeSearch:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// FilterRuleText is the text of a single rule within a filter.
|
||||
type FilterRuleText string
|
||||
|
||||
|
@ -37,7 +37,6 @@ func TestNewFilterListID(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -86,7 +85,6 @@ func TestNewFilterRuleText(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -14,7 +14,7 @@ func BenchmarkNewRequestID(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
reqIDSink = agd.NewRequestID()
|
||||
}
|
||||
|
||||
|
@ -2,23 +2,14 @@ package agd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"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
|
||||
@ -60,11 +51,11 @@ type TLS struct {
|
||||
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
|
||||
DeviceTargets *container.MapSet[string]
|
||||
|
||||
// PublicTargets is the set of all public domain names, DDR queries for
|
||||
// which should be processed.
|
||||
PublicTargets *stringutil.Set
|
||||
PublicTargets *container.MapSet[string]
|
||||
|
||||
// DeviceRecordTemplates are used to respond to DDR queries from recognized
|
||||
// devices.
|
||||
@ -78,81 +69,3 @@ type DDR struct {
|
||||
// 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
|
||||
}
|
||||
|
59
internal/agdcache/agdcache.go
Normal file
59
internal/agdcache/agdcache.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Package agdcache contains cache interfaces, helpers, and implementations.
|
||||
package agdcache
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Interface is the cache interface.
|
||||
type Interface[K, T any] interface {
|
||||
// Set sets key and val as cache pair.
|
||||
Set(key K, val T)
|
||||
|
||||
// SetWithExpire sets key and val as cache pair with expiration time.
|
||||
SetWithExpire(key K, val T, expiration time.Duration)
|
||||
|
||||
// Get gets val from the cache using key.
|
||||
Get(key K) (val T, ok bool)
|
||||
|
||||
// Clearer completely clears cache.
|
||||
Clearer
|
||||
|
||||
// Len returns the number of items in the cache.
|
||||
Len() (n int)
|
||||
}
|
||||
|
||||
// Clearer is a partial cache interface.
|
||||
type Clearer interface {
|
||||
// Clear completely clears cache.
|
||||
Clear()
|
||||
}
|
||||
|
||||
// Empty is an [Interface] implementation that does nothing.
|
||||
type Empty[K, T any] struct{}
|
||||
|
||||
// type check
|
||||
var _ Interface[any, any] = Empty[any, any]{}
|
||||
|
||||
// Set implements the [Interface] interface for Empty.
|
||||
func (c Empty[K, T]) Set(key K, val T) {}
|
||||
|
||||
// SetWithExpire implements the [Interface] interface for Empty.
|
||||
func (c Empty[K, T]) SetWithExpire(key K, val T, expiration time.Duration) {}
|
||||
|
||||
// Get implements the [Interface] interface for Empty.
|
||||
func (c Empty[K, T]) Get(key K) (val T, ok bool) {
|
||||
return val, false
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Clearer = Empty[any, any]{}
|
||||
|
||||
// Clear implements the [Interface] interface for Empty.
|
||||
func (c Empty[K, T]) Clear() {}
|
||||
|
||||
// Len implements the [Interface] interface for Empty. n may include items that
|
||||
// have expired, but have not yet been cleaned up.
|
||||
func (c Empty[K, T]) Len() (n int) {
|
||||
return 0
|
||||
}
|
106
internal/agdcache/lru.go
Normal file
106
internal/agdcache/lru.go
Normal file
@ -0,0 +1,106 @@
|
||||
package agdcache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/bluele/gcache"
|
||||
)
|
||||
|
||||
// LRUConfig is a configuration structure of a cache.
|
||||
type LRUConfig struct {
|
||||
Size int
|
||||
}
|
||||
|
||||
// LRU is an [Interface] implementation.
|
||||
type LRU[K, T any] struct {
|
||||
cache gcache.Cache
|
||||
}
|
||||
|
||||
// NewLRU returns a new initialized LRU cache.
|
||||
func NewLRU[K, T any](conf *LRUConfig) (c *LRU[K, T]) {
|
||||
return &LRU[K, T]{
|
||||
cache: gcache.New(conf.Size).LRU().Build(),
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Interface[any, any] = (*LRU[any, any])(nil)
|
||||
|
||||
// Set implements the [Interface] interface for *LRU.
|
||||
func (c *LRU[K, T]) Set(key K, val T) {
|
||||
err := c.cache.Set(key, val)
|
||||
if err != nil {
|
||||
// Shouldn't happen, since we don't set a serialization function.
|
||||
panic(fmt.Errorf("agdcache: setting cache item: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// SetWithExpire implements the [Interface] interface for *LRU.
|
||||
func (c *LRU[K, T]) SetWithExpire(key K, val T, expiration time.Duration) {
|
||||
err := c.cache.SetWithExpire(key, val, expiration)
|
||||
if err != nil {
|
||||
// Shouldn't happen, since we don't set a serialization function.
|
||||
panic(fmt.Errorf("agdcache: setting cache item with expiration: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Get implements the [Interface] interface for *LRU.
|
||||
func (c *LRU[K, T]) Get(key K) (val T, ok bool) {
|
||||
v, err := c.cache.Get(key)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gcache.KeyNotFoundError) {
|
||||
// Shouldn't happen, since we don't set a serialization function.
|
||||
panic(fmt.Errorf("agdcache: getting cache item: %w", err))
|
||||
}
|
||||
|
||||
return val, false
|
||||
}
|
||||
|
||||
// T may be an interface type, so check v against nil explicitly to prevent
|
||||
// v.(T) below from panicking.
|
||||
if v == nil {
|
||||
return val, true
|
||||
}
|
||||
|
||||
return v.(T), true
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Clearer = (*LRU[any, any])(nil)
|
||||
|
||||
// Clear implements the [Interface] interface for *LRU.
|
||||
func (c *LRU[K, T]) Clear() {
|
||||
c.cache.Purge()
|
||||
}
|
||||
|
||||
// Len implements the [Interface] interface for *LRU. n may include items
|
||||
// that have expired, but have not yet been cleaned up.
|
||||
func (c *LRU[K, T]) Len() (n int) {
|
||||
const checkExpired = false
|
||||
|
||||
return c.cache.Len(checkExpired)
|
||||
}
|
||||
|
||||
// Manager manages caches.
|
||||
type Manager struct {
|
||||
caches map[string]Clearer
|
||||
}
|
||||
|
||||
// NewManager returns a new initialized *Manager.
|
||||
func NewManager() (m *Manager) {
|
||||
return &Manager{
|
||||
caches: map[string]Clearer{},
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds cache by id.
|
||||
func (m *Manager) Add(id string, cache Clearer) {
|
||||
m.caches[id] = cache
|
||||
}
|
||||
|
||||
// ClearByID clears cache by id.
|
||||
func (m *Manager) ClearByID(id string) {
|
||||
m.caches[id].Clear()
|
||||
}
|
69
internal/agdcache/lru_test.go
Normal file
69
internal/agdcache/lru_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
package agdcache_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLRU(t *testing.T) {
|
||||
const (
|
||||
key = "key"
|
||||
val = 123
|
||||
|
||||
nonExistingKey = "nonExistingKey"
|
||||
)
|
||||
|
||||
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
||||
Size: 10,
|
||||
})
|
||||
|
||||
cache.Set(key, val)
|
||||
|
||||
assert.Equal(t, 1, cache.Len())
|
||||
|
||||
v, ok := cache.Get(key)
|
||||
assert.Equal(t, val, v)
|
||||
assert.True(t, ok)
|
||||
|
||||
v, ok = cache.Get(nonExistingKey)
|
||||
assert.Equal(t, 0, v)
|
||||
assert.False(t, ok)
|
||||
|
||||
cache.Clear()
|
||||
|
||||
assert.Equal(t, 0, cache.Len())
|
||||
}
|
||||
|
||||
func TestManager(t *testing.T) {
|
||||
const (
|
||||
key = "key"
|
||||
val = 123
|
||||
id = "cacheID"
|
||||
|
||||
nonExistingKey = "nonExistingKey"
|
||||
)
|
||||
|
||||
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
||||
Size: 10,
|
||||
})
|
||||
|
||||
cache.Set(key, val)
|
||||
|
||||
assert.Equal(t, 1, cache.Len())
|
||||
|
||||
v, ok := cache.Get(key)
|
||||
assert.Equal(t, val, v)
|
||||
assert.True(t, ok)
|
||||
|
||||
v, ok = cache.Get(nonExistingKey)
|
||||
assert.Equal(t, 0, v)
|
||||
assert.False(t, ok)
|
||||
|
||||
m := agdcache.NewManager()
|
||||
m.Add(id, cache)
|
||||
m.ClearByID(id)
|
||||
|
||||
assert.Equal(t, 0, cache.Len())
|
||||
}
|
@ -15,6 +15,7 @@ import (
|
||||
// HTTP header value constants.
|
||||
const (
|
||||
HdrValApplicationJSON = "application/json"
|
||||
HdrValGzip = "gzip"
|
||||
HdrValTextCSV = "text/csv"
|
||||
HdrValTextHTML = "text/html"
|
||||
HdrValTextPlain = "text/plain"
|
||||
|
@ -34,22 +34,18 @@ func NewClient(conf *ClientConfig) (c *Client) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get is a wrapper around http.Client.Get.
|
||||
// Get is a wrapper around [http.Client.Get].
|
||||
//
|
||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||
// close resp.Body when done reading from it.
|
||||
//
|
||||
// See also go doc http.Client.Get.
|
||||
func (c *Client) Get(ctx context.Context, u *url.URL) (resp *http.Response, err error) {
|
||||
return c.do(ctx, http.MethodGet, u, "", nil)
|
||||
}
|
||||
|
||||
// Post is a wrapper around http.Client.Post.
|
||||
// Post is a wrapper around [http.Client.Post].
|
||||
//
|
||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||
// close resp.Body when done reading from it.
|
||||
//
|
||||
// See also go doc http.Client.Post.
|
||||
func (c *Client) Post(
|
||||
ctx context.Context,
|
||||
u *url.URL,
|
||||
@ -59,7 +55,7 @@ func (c *Client) Post(
|
||||
return c.do(ctx, http.MethodPost, u, contentType, body)
|
||||
}
|
||||
|
||||
// Put is a wrapper around http.Client.Do.
|
||||
// Put is a wrapper around [http.Client.Put].
|
||||
//
|
||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||
// close resp.Body when done reading from it.
|
||||
@ -72,7 +68,7 @@ func (c *Client) Put(
|
||||
return c.do(ctx, http.MethodPut, u, contentType, body)
|
||||
}
|
||||
|
||||
// do is a wrapper around http.Client.Do.
|
||||
// do is a wrapper around [http.Client.Do].
|
||||
func (c *Client) do(
|
||||
ctx context.Context,
|
||||
method string,
|
||||
@ -98,7 +94,8 @@ func (c *Client) do(
|
||||
|
||||
resp, err = c.http.Do(req)
|
||||
if err != nil && resp != nil && resp.Header != nil {
|
||||
// A non-nil Response with a non-nil error only occurs when CheckRedirect fails.
|
||||
// A non-nil Response with a non-nil error only occurs when
|
||||
// CheckRedirect fails.
|
||||
return resp, WrapServerError(err, resp)
|
||||
}
|
||||
|
||||
|
@ -1,213 +0,0 @@
|
||||
package agdnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
)
|
||||
|
||||
// Resolver is the DNS resolver interface.
|
||||
//
|
||||
// See [net.Resolver].
|
||||
//
|
||||
// TODO(a.garipov): Move to golibs and unite with the one in module dnsproxy.
|
||||
type Resolver interface {
|
||||
// LookupNetIP returns a slice of host's IP addresses of family specified by
|
||||
// fam, which must be either [netutil.AddrFamilyIPv4] or
|
||||
// [netutil.AddrFamilyIPv6].
|
||||
LookupNetIP(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error)
|
||||
}
|
||||
|
||||
// DefaultResolver uses [net.DefaultResolver] to resolve addresses.
|
||||
type DefaultResolver struct{}
|
||||
|
||||
// type check
|
||||
var _ Resolver = DefaultResolver{}
|
||||
|
||||
// LookupNetIP implements the [Resolver] interface for DefaultResolver.
|
||||
func (DefaultResolver) LookupNetIP(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error) {
|
||||
switch fam {
|
||||
case netutil.AddrFamilyIPv4:
|
||||
return net.DefaultResolver.LookupNetIP(ctx, "ip4", host)
|
||||
case netutil.AddrFamilyIPv6:
|
||||
return net.DefaultResolver.LookupNetIP(ctx, "ip6", host)
|
||||
default:
|
||||
return nil, net.UnknownNetworkError(fam.String())
|
||||
}
|
||||
}
|
||||
|
||||
// resolveCache is a simple address resolving cache.
|
||||
type resolveCache map[string]*resolveCacheItem
|
||||
|
||||
// resolveCacheItem is an item of [resolveCache].
|
||||
type resolveCacheItem struct {
|
||||
refrTime time.Time
|
||||
ips []netip.Addr
|
||||
}
|
||||
|
||||
// CachingResolver caches resolved results for hosts for a certain time,
|
||||
// regardless of the actual TTLs of the records. It is used for caching the
|
||||
// results of lookups of hostnames that don't change their IP addresses often.
|
||||
type CachingResolver struct {
|
||||
resolver Resolver
|
||||
|
||||
// mu protects ip4 and ip6.
|
||||
mu *sync.Mutex
|
||||
ipv4 resolveCache
|
||||
ipv6 resolveCache
|
||||
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
// NewCachingResolver returns a new caching resolver.
|
||||
func NewCachingResolver(resolver Resolver, ttl time.Duration) (c *CachingResolver) {
|
||||
return &CachingResolver{
|
||||
resolver: resolver,
|
||||
|
||||
mu: &sync.Mutex{},
|
||||
ipv4: resolveCache{},
|
||||
ipv6: resolveCache{},
|
||||
|
||||
ttl: ttl,
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Resolver = (*CachingResolver)(nil)
|
||||
|
||||
// LookupNetIP implements the [Resolver] interface for *CachingResolver. host
|
||||
// should be normalized. Slice ips and its elements must not be mutated.
|
||||
func (c *CachingResolver) LookupNetIP(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var item *resolveCacheItem
|
||||
switch fam {
|
||||
case netutil.AddrFamilyIPv4:
|
||||
item = c.ipv4[host]
|
||||
case netutil.AddrFamilyIPv6:
|
||||
item = c.ipv6[host]
|
||||
default:
|
||||
return nil, net.UnknownNetworkError(fam.String())
|
||||
}
|
||||
|
||||
if item == nil || time.Since(item.refrTime) > c.ttl {
|
||||
item, err = c.resolve(ctx, fam, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return item.ips, nil
|
||||
}
|
||||
|
||||
// resolve looks up the IP addresses for host and puts them into the cache.
|
||||
func (c *CachingResolver) resolve(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (item *resolveCacheItem, err error) {
|
||||
var ips []netip.Addr
|
||||
|
||||
refrTime := time.Now()
|
||||
|
||||
// Don't resolve IP addresses.
|
||||
ip := ipFromHost(host, fam)
|
||||
if ip != (netip.Addr{}) {
|
||||
ips = []netip.Addr{ip}
|
||||
|
||||
// Set the refresh time to the maximum date that time.Duration allows to
|
||||
// prevent this item from refreshing.
|
||||
refrTime = time.Unix(0, math.MaxInt64)
|
||||
} else {
|
||||
ips, err = c.resolver.LookupNetIP(ctx, fam, host)
|
||||
if err != nil {
|
||||
if !isExpectedLookupError(fam, err) {
|
||||
return nil, fmt.Errorf("resolving %s addr for %q: %w", fam, host, err)
|
||||
}
|
||||
|
||||
log.Debug("caching resolver: warning: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
var cache resolveCache
|
||||
if fam == netutil.AddrFamilyIPv4 {
|
||||
cache = c.ipv4
|
||||
} else {
|
||||
cache = c.ipv6
|
||||
}
|
||||
|
||||
item = &resolveCacheItem{
|
||||
refrTime: refrTime,
|
||||
ips: ips,
|
||||
}
|
||||
|
||||
cache[host] = item
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// ipFromHost parses host as if it'd be an IP address of specified fam. It
|
||||
// returns an empty netip.
|
||||
func ipFromHost(host string, fam netutil.AddrFamily) (ip netip.Addr) {
|
||||
var famFunc func(netip.Addr) (ok bool)
|
||||
switch fam {
|
||||
case netutil.AddrFamilyIPv4:
|
||||
famFunc = netip.Addr.Is4
|
||||
case netutil.AddrFamilyIPv6:
|
||||
famFunc = netip.Addr.Is6
|
||||
default:
|
||||
return netip.Addr{}
|
||||
}
|
||||
|
||||
ip, err := netip.ParseAddr(host)
|
||||
if err != nil || !famFunc(ip) {
|
||||
return netip.Addr{}
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
// isExpectedLookupError returns true if the error is an expected lookup error.
|
||||
func isExpectedLookupError(fam netutil.AddrFamily, err error) (ok bool) {
|
||||
var dnsErr *net.DNSError
|
||||
if fam == netutil.AddrFamilyIPv6 && errors.As(err, &dnsErr) {
|
||||
// It's expected that Go default DNS resolver returns a DNS error in
|
||||
// some cases when it receives an empty response. It's unclear what
|
||||
// exactly triggers this error, though.
|
||||
//
|
||||
// TODO(ameshkov): Consider researching this in detail.
|
||||
return true
|
||||
}
|
||||
|
||||
var addrErr *net.AddrError
|
||||
if !errors.As(err, &addrErr) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Expect the error about no suitable addresses. For example, no IPv6
|
||||
// addresses for a host that does have IPv4 ones.
|
||||
//
|
||||
// See function filterAddrList in ${GOROOT}/src/net/ipsock.go.
|
||||
return addrErr.Err == "no suitable address found"
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package agdnet_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCachingResolver_Resolve(t *testing.T) {
|
||||
const testHost = "addr.example"
|
||||
|
||||
var numLookups uint64
|
||||
wantIPv4 := []netip.Addr{netip.MustParseAddr("1.2.3.4")}
|
||||
wantIPv6 := []netip.Addr{netip.MustParseAddr("1234::5678")}
|
||||
r := &agdtest.Resolver{
|
||||
OnLookupNetIP: func(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error) {
|
||||
numLookups++
|
||||
|
||||
if fam == netutil.AddrFamilyIPv4 {
|
||||
return wantIPv4, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
cached := agdnet.NewCachingResolver(r, 1*timeutil.Day)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
host string
|
||||
wantIPs []netip.Addr
|
||||
wantNum uint64
|
||||
fam netutil.AddrFamily
|
||||
}{{
|
||||
name: "initial",
|
||||
host: testHost,
|
||||
wantIPs: wantIPv4,
|
||||
wantNum: 1,
|
||||
fam: netutil.AddrFamilyIPv4,
|
||||
}, {
|
||||
name: "cached",
|
||||
host: testHost,
|
||||
wantIPs: wantIPv4,
|
||||
wantNum: 1,
|
||||
fam: netutil.AddrFamilyIPv4,
|
||||
}, {
|
||||
name: "other_network",
|
||||
host: testHost,
|
||||
wantIPs: nil,
|
||||
wantNum: 2,
|
||||
fam: netutil.AddrFamilyIPv6,
|
||||
}, {
|
||||
name: "ipv4",
|
||||
host: wantIPv4[0].String(),
|
||||
wantIPs: wantIPv4,
|
||||
wantNum: 2,
|
||||
fam: netutil.AddrFamilyIPv4,
|
||||
}, {
|
||||
name: "ipv6",
|
||||
host: wantIPv6[0].String(),
|
||||
wantIPs: wantIPv6,
|
||||
wantNum: 2,
|
||||
fam: netutil.AddrFamilyIPv6,
|
||||
}}
|
||||
|
||||
ctx := context.Background()
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got, err := cached.LookupNetIP(ctx, tc.fam, tc.host)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.wantNum, numLookups)
|
||||
assert.Equal(t, tc.wantIPs, got)
|
||||
})
|
||||
}
|
||||
}
|
51
internal/agdpasswd/authenticator.go
Normal file
51
internal/agdpasswd/authenticator.go
Normal file
@ -0,0 +1,51 @@
|
||||
// Package agdpasswd contains authentication utils.
|
||||
package agdpasswd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// Authenticator represents a password authenticator.
|
||||
type Authenticator interface {
|
||||
// Authenticate returns true if the given passwd is allowed.
|
||||
Authenticate(ctx context.Context, passwd []byte) (ok bool)
|
||||
}
|
||||
|
||||
// AllowAuthenticator is an empty authenticator implementation that always
|
||||
// grants access, regardless of any restrictions.
|
||||
type AllowAuthenticator struct{}
|
||||
|
||||
// type check
|
||||
var _ Authenticator = AllowAuthenticator{}
|
||||
|
||||
// Authenticate implements the [Authenticator] interface for AllowAuthenticator.
|
||||
func (AllowAuthenticator) Authenticate(_ context.Context, _ []byte) (ok bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
// PasswordHashBcrypt is the Bcrypt implementation of [Authenticator].
|
||||
type PasswordHashBcrypt struct {
|
||||
// bytes contains the password hash.
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
// NewPasswordHashBcrypt returns a new bcrypt hashed password authenticator.
|
||||
func NewPasswordHashBcrypt(hashedPassword []byte) (p *PasswordHashBcrypt) {
|
||||
return &PasswordHashBcrypt{bytes: hashedPassword}
|
||||
}
|
||||
|
||||
// PasswordHash returns password hash bytes slice.
|
||||
func (p *PasswordHashBcrypt) PasswordHash() (b []byte) {
|
||||
return p.bytes
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Authenticator = (*PasswordHashBcrypt)(nil)
|
||||
|
||||
// Authenticate implements the [Authenticator] interface for
|
||||
// *PasswordHashBcrypt.
|
||||
func (p *PasswordHashBcrypt) Authenticate(_ context.Context, passwd []byte) (ok bool) {
|
||||
return bcrypt.CompareHashAndPassword(p.bytes, passwd) == nil
|
||||
}
|
49
internal/agdpasswd/authenticator_test.go
Normal file
49
internal/agdpasswd/authenticator_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package agdpasswd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
func TestPasswordHashBcrypt_Authenticate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const passwd = "mypassword"
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(passwd), 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
authenticator := agdpasswd.NewPasswordHashBcrypt(hash)
|
||||
|
||||
testCases := []struct {
|
||||
want assert.BoolAssertionFunc
|
||||
name string
|
||||
pass string
|
||||
}{{
|
||||
want: assert.True,
|
||||
name: "success",
|
||||
pass: passwd,
|
||||
}, {
|
||||
want: assert.False,
|
||||
name: "fail",
|
||||
pass: "an-other-passwd",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tc.want(t, authenticator.Authenticate(context.Background(), []byte(tc.pass)))
|
||||
})
|
||||
}
|
||||
}
|
@ -13,6 +13,10 @@ import (
|
||||
|
||||
// Refresher is the interface for entities that can update themselves.
|
||||
type Refresher interface {
|
||||
// Refresh is called by a [RefreshWorker]. The error returned by Refresh is
|
||||
// only returned from [RefreshWorker.Shutdown] and only when
|
||||
// [RefreshWorkerConfig.RefreshOnShutdown] is true. In all other cases, the
|
||||
// error is ignored, and refreshers must handle error reporting themselves.
|
||||
Refresh(ctx context.Context) (err error)
|
||||
}
|
||||
|
||||
@ -21,11 +25,9 @@ type Refresher interface {
|
||||
type RefreshWorker struct {
|
||||
done chan unit
|
||||
context func() (ctx context.Context, cancel context.CancelFunc)
|
||||
logRoutine func(format string, args ...any)
|
||||
tick *time.Ticker
|
||||
rand *rand.Rand
|
||||
refr Refresher
|
||||
errColl errcoll.Interface
|
||||
name string
|
||||
maxStartSleep time.Duration
|
||||
|
||||
@ -40,12 +42,6 @@ type RefreshWorkerConfig struct {
|
||||
// Refresher is the entity being refreshed.
|
||||
Refresher Refresher
|
||||
|
||||
// ErrColl is used to collect errors during refreshes.
|
||||
//
|
||||
// TODO(a.garipov): Remove this and make all Refreshers handle their own
|
||||
// errors.
|
||||
ErrColl errcoll.Interface
|
||||
|
||||
// Name is the name of this worker. It is used for logging and error
|
||||
// collecting.
|
||||
//
|
||||
@ -64,12 +60,6 @@ type RefreshWorkerConfig struct {
|
||||
// that should persist to disk or remote storage before shutting down.
|
||||
RefreshOnShutdown bool
|
||||
|
||||
// RoutineLogsAreDebug, if true, instructs the worker to write initial and
|
||||
// final log messages for each singular refresh on the Debug level rather
|
||||
// than on the Info one. This is useful to prevent routine logs from
|
||||
// workers with a small interval from overflowing with messages.
|
||||
RoutineLogsAreDebug bool
|
||||
|
||||
// RandomizeStart, if true, instructs the worker to sleep before starting a
|
||||
// refresh. The duration of the sleep is a random duration of up to 10 % of
|
||||
// Interval.
|
||||
@ -82,14 +72,6 @@ type RefreshWorkerConfig struct {
|
||||
// NewRefreshWorker returns a new valid *RefreshWorker with the provided
|
||||
// parameters. c must not be nil.
|
||||
func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
||||
// TODO(a.garipov): Add log.WithLevel.
|
||||
var logRoutine func(format string, args ...any)
|
||||
if c.RoutineLogsAreDebug {
|
||||
logRoutine = log.Debug
|
||||
} else {
|
||||
logRoutine = log.Info
|
||||
}
|
||||
|
||||
var maxStartSleep time.Duration
|
||||
var rng *rand.Rand
|
||||
if c.RandomizeStart {
|
||||
@ -100,11 +82,9 @@ func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
||||
return &RefreshWorker{
|
||||
done: make(chan unit),
|
||||
context: c.Context,
|
||||
logRoutine: logRoutine,
|
||||
tick: time.NewTicker(c.Interval),
|
||||
rand: rng,
|
||||
refr: c.Refresher,
|
||||
errColl: c.ErrColl,
|
||||
name: c.Name,
|
||||
maxStartSleep: maxStartSleep,
|
||||
refrOnShutdown: c.RefreshOnShutdown,
|
||||
@ -172,7 +152,7 @@ func (w *RefreshWorker) sleepRandom() (shouldRefresh bool) {
|
||||
}
|
||||
|
||||
sleepDur := time.Duration(w.rand.Int63n(int64(w.maxStartSleep)))
|
||||
w.logRoutine("worker %q: sleeping for %s before refresh", w.name, sleepDur)
|
||||
log.Debug("worker %q: sleeping for %s before refresh", w.name, sleepDur)
|
||||
|
||||
timer := time.NewTimer(sleepDur)
|
||||
defer func() {
|
||||
@ -197,24 +177,51 @@ func (w *RefreshWorker) sleepRandom() (shouldRefresh bool) {
|
||||
|
||||
// refresh refreshes the entity and logs the status of the refresh.
|
||||
func (w *RefreshWorker) refresh() {
|
||||
name := w.name
|
||||
w.logRoutine("worker %q: refreshing", name)
|
||||
|
||||
// TODO(a.garipov): Consider adding a helper for enriching errors with
|
||||
// context deadline data without duplication. See an example in method
|
||||
// filter.refreshableFilter.refresh.
|
||||
ctx, cancel := w.context()
|
||||
defer cancel()
|
||||
|
||||
log.Debug("worker %q: starting refresh", name)
|
||||
err := w.refr.Refresh(ctx)
|
||||
log.Debug("worker %q: finished refresh", name)
|
||||
_ = w.refr.Refresh(ctx)
|
||||
}
|
||||
|
||||
// RefresherWithErrColl reports all refresh errors to errColl and logs them
|
||||
// using a provided logging function.
|
||||
type RefresherWithErrColl struct {
|
||||
refr Refresher
|
||||
log func(format string, args ...any)
|
||||
errColl errcoll.Interface
|
||||
prefix string
|
||||
}
|
||||
|
||||
// NewRefresherWithErrColl wraps refr into a refresher that collects errors and
|
||||
// logs them.
|
||||
func NewRefresherWithErrColl(
|
||||
refr Refresher,
|
||||
logFunc func(format string, args ...any),
|
||||
errColl errcoll.Interface,
|
||||
prefix string,
|
||||
) (wrapped *RefresherWithErrColl) {
|
||||
return &RefresherWithErrColl{
|
||||
refr: refr,
|
||||
log: logFunc,
|
||||
errColl: errColl,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ Refresher = (*RefresherWithErrColl)(nil)
|
||||
|
||||
// Refresh implements the [Refresher] interface for *RefresherWithErrColl.
|
||||
func (r *RefresherWithErrColl) Refresh(ctx context.Context) (err error) {
|
||||
err = r.refr.Refresh(ctx)
|
||||
if err != nil {
|
||||
errcoll.Collectf(ctx, w.errColl, "%s: %w", name, err)
|
||||
|
||||
return
|
||||
err = fmt.Errorf("%s: %w", r.prefix, err)
|
||||
r.log("%s", err)
|
||||
r.errColl.Collect(ctx, err)
|
||||
}
|
||||
|
||||
w.logRoutine("worker %q: refreshed successfully", name)
|
||||
return err
|
||||
}
|
||||
|
@ -42,34 +42,23 @@ func newTestRefresher(t *testing.T, respErr error) (refr *agdtest.Refresher, syn
|
||||
return refr, syncCh
|
||||
}
|
||||
|
||||
// newRefrConf returns worker configuration.
|
||||
func newRefrConf(
|
||||
// newRefrConfig returns worker configuration.
|
||||
func newRefrConfig(
|
||||
t *testing.T,
|
||||
refr agdservice.Refresher,
|
||||
ivl time.Duration,
|
||||
refrOnShutDown bool,
|
||||
errCh chan sig,
|
||||
) (conf *agdservice.RefreshWorkerConfig) {
|
||||
t.Helper()
|
||||
|
||||
pt := testutil.PanicT{}
|
||||
|
||||
errColl := &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) {
|
||||
testutil.RequireSend(pt, errCh, sig{}, testTimeout)
|
||||
},
|
||||
}
|
||||
|
||||
return &agdservice.RefreshWorkerConfig{
|
||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||
return context.WithTimeout(context.Background(), testTimeout)
|
||||
},
|
||||
Refresher: refr,
|
||||
ErrColl: errColl,
|
||||
Name: name,
|
||||
Interval: ivl,
|
||||
RefreshOnShutdown: refrOnShutDown,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
}
|
||||
}
|
||||
@ -77,17 +66,15 @@ func newRefrConf(
|
||||
func TestRefreshWorker(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
refr, syncCh := newTestRefresher(t, nil)
|
||||
errCh := make(chan sig, 1)
|
||||
|
||||
w := agdservice.NewRefreshWorker(newRefrConf(t, refr, testIvl, false, errCh))
|
||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, refr, testIvl, false))
|
||||
|
||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||
require.Empty(t, errCh)
|
||||
|
||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
@ -95,12 +82,12 @@ func TestRefreshWorker(t *testing.T) {
|
||||
refr, syncCh := newTestRefresher(t, nil)
|
||||
errCh := make(chan sig, 1)
|
||||
|
||||
w := agdservice.NewRefreshWorker(newRefrConf(t, refr, testIvlLong, true, errCh))
|
||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, refr, testIvlLong, true))
|
||||
|
||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||
@ -109,33 +96,29 @@ func TestRefreshWorker(t *testing.T) {
|
||||
|
||||
t.Run("error", func(t *testing.T) {
|
||||
errRefr, syncCh := newTestRefresher(t, testError)
|
||||
errCh := make(chan sig, 1)
|
||||
|
||||
w := agdservice.NewRefreshWorker(newRefrConf(t, errRefr, testIvl, false, errCh))
|
||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvl, false))
|
||||
|
||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||
testutil.RequireReceive(t, errCh, testTimeout)
|
||||
|
||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("error_on_shutdown", func(t *testing.T) {
|
||||
errRefr, syncCh := newTestRefresher(t, testError)
|
||||
errCh := make(chan sig, 1)
|
||||
|
||||
w := agdservice.NewRefreshWorker(newRefrConf(t, errRefr, testIvlLong, true, errCh))
|
||||
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvlLong, true))
|
||||
|
||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
assert.ErrorIs(t, err, testError)
|
||||
|
||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||
require.Empty(t, errCh)
|
||||
})
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
package agdtest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
@ -27,16 +25,3 @@ func NewConstructor() (c *dnsmsg.Constructor) {
|
||||
func NewCloner() (c *dnsmsg.Cloner) {
|
||||
return dnsmsg.NewCloner(dnsmsg.EmptyClonerStat{})
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||
@ -52,27 +52,20 @@ func (a *AccessManager) IsBlockedIP(ip netip.Addr) (blocked bool) {
|
||||
return a.OnIsBlockedIP(ip)
|
||||
}
|
||||
|
||||
// Package agdnet
|
||||
// Package agdpasswd
|
||||
|
||||
// type check
|
||||
var _ agdnet.Resolver = (*Resolver)(nil)
|
||||
var _ agdpasswd.Authenticator = (*Authenticator)(nil)
|
||||
|
||||
// Resolver is an [agdnet.Resolver] for tests.
|
||||
type Resolver struct {
|
||||
OnLookupNetIP func(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error)
|
||||
// Authenticator is an [agdpasswd.Authenticator] for tests.
|
||||
type Authenticator struct {
|
||||
OnAuthenticate func(ctx context.Context, passwd []byte) (ok bool)
|
||||
}
|
||||
|
||||
// LookupNetIP implements the [agdnet.Resolver] interface for *Resolver.
|
||||
func (r *Resolver) LookupNetIP(
|
||||
ctx context.Context,
|
||||
fam netutil.AddrFamily,
|
||||
host string,
|
||||
) (ips []netip.Addr, err error) {
|
||||
return r.OnLookupNetIP(ctx, fam, host)
|
||||
// Authenticate implements the [agdpasswd.Authenticator] interface for
|
||||
// *Authenticator.
|
||||
func (a *Authenticator) Authenticate(ctx context.Context, passwd []byte) (ok bool) {
|
||||
return a.OnAuthenticate(ctx, passwd)
|
||||
}
|
||||
|
||||
// Package agdservice
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.1
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.25.3
|
||||
// source: backend.proto
|
||||
|
||||
package backendpb
|
||||
@ -364,6 +364,7 @@ type DeviceSettings struct {
|
||||
FilteringEnabled bool `protobuf:"varint,3,opt,name=filtering_enabled,json=filteringEnabled,proto3" json:"filtering_enabled,omitempty"`
|
||||
LinkedIp []byte `protobuf:"bytes,4,opt,name=linked_ip,json=linkedIp,proto3" json:"linked_ip,omitempty"`
|
||||
DedicatedIps [][]byte `protobuf:"bytes,5,rep,name=dedicated_ips,json=dedicatedIps,proto3" json:"dedicated_ips,omitempty"`
|
||||
Authentication *AuthenticationSettings `protobuf:"bytes,6,opt,name=authentication,proto3" json:"authentication,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeviceSettings) Reset() {
|
||||
@ -433,6 +434,13 @@ func (x *DeviceSettings) GetDedicatedIps() [][]byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DeviceSettings) GetAuthentication() *AuthenticationSettings {
|
||||
if x != nil {
|
||||
return x.Authentication
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ParentalSettings struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -1179,6 +1187,81 @@ func (x *CidrRange) GetPrefix() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type AuthenticationSettings struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
DohAuthOnly bool `protobuf:"varint,1,opt,name=doh_auth_only,json=dohAuthOnly,proto3" json:"doh_auth_only,omitempty"`
|
||||
// Types that are assignable to DohPasswordHash:
|
||||
//
|
||||
// *AuthenticationSettings_PasswordHashBcrypt
|
||||
DohPasswordHash isAuthenticationSettings_DohPasswordHash `protobuf_oneof:"doh_password_hash"`
|
||||
}
|
||||
|
||||
func (x *AuthenticationSettings) Reset() {
|
||||
*x = AuthenticationSettings{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_backend_proto_msgTypes[16]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *AuthenticationSettings) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AuthenticationSettings) ProtoMessage() {}
|
||||
|
||||
func (x *AuthenticationSettings) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_backend_proto_msgTypes[16]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AuthenticationSettings.ProtoReflect.Descriptor instead.
|
||||
func (*AuthenticationSettings) Descriptor() ([]byte, []int) {
|
||||
return file_backend_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
func (x *AuthenticationSettings) GetDohAuthOnly() bool {
|
||||
if x != nil {
|
||||
return x.DohAuthOnly
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *AuthenticationSettings) GetDohPasswordHash() isAuthenticationSettings_DohPasswordHash {
|
||||
if m != nil {
|
||||
return m.DohPasswordHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AuthenticationSettings) GetPasswordHashBcrypt() []byte {
|
||||
if x, ok := x.GetDohPasswordHash().(*AuthenticationSettings_PasswordHashBcrypt); ok {
|
||||
return x.PasswordHashBcrypt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isAuthenticationSettings_DohPasswordHash interface {
|
||||
isAuthenticationSettings_DohPasswordHash()
|
||||
}
|
||||
|
||||
type AuthenticationSettings_PasswordHashBcrypt struct {
|
||||
PasswordHashBcrypt []byte `protobuf:"bytes,2,opt,name=password_hash_bcrypt,json=passwordHashBcrypt,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*AuthenticationSettings_PasswordHashBcrypt) isAuthenticationSettings_DohPasswordHash() {}
|
||||
|
||||
var File_backend_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_backend_proto_rawDesc = []byte{
|
||||
@ -1263,7 +1346,7 @@ var file_backend_proto_rawDesc = []byte{
|
||||
0x63, 0x6b, 0x44, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x72, 0x64, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x64, 0x22,
|
||||
0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0xe4, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
|
||||
@ -1273,110 +1356,123 @@ var file_backend_proto_rawDesc = []byte{
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x49, 0x70,
|
||||
0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x70,
|
||||
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x64, 0x49, 0x70, 0x73, 0x22, 0x87, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x61, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x64,
|
||||
0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x41, 0x64, 0x75, 0x6c, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
|
||||
0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x53, 0x61, 0x66, 0x65, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65,
|
||||
0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x11, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x53, 0x61, 0x66, 0x65, 0x53,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64,
|
||||
0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x22,
|
||||
0x54, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x6d, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12, 0x2e, 0x0a, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52,
|
||||
0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x57, 0x65, 0x65,
|
||||
0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x0b, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x6d,
|
||||
0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x75, 0x65, 0x12,
|
||||
0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44,
|
||||
0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03,
|
||||
0x74, 0x68, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52,
|
||||
0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x68, 0x75, 0x12, 0x1b, 0x0a, 0x03, 0x66, 0x72, 0x69,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x52, 0x03, 0x66, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20,
|
||||
0x65, 0x64, 0x49, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65,
|
||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x87, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x61, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65,
|
||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61,
|
||||
0x64, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x41, 0x64, 0x75, 0x6c, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
||||
0x6c, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x53, 0x61, 0x66, 0x65,
|
||||
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62,
|
||||
0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x11, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x53, 0x61, 0x66, 0x65,
|
||||
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65,
|
||||
0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65,
|
||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
|
||||
0x22, 0x54, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x6d, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12, 0x2e, 0x0a, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x57, 0x65,
|
||||
0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c,
|
||||
0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x0b, 0x57, 0x65, 0x65, 0x6b, 0x6c,
|
||||
0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03,
|
||||
0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x75, 0x6e,
|
||||
0x22, 0x68, 0x0a, 0x08, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x05,
|
||||
0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
|
||||
0x6d, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x75, 0x65,
|
||||
0x12, 0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e,
|
||||
0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a,
|
||||
0x03, 0x74, 0x68, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79,
|
||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x68, 0x75, 0x12, 0x1b, 0x0a, 0x03, 0x66, 0x72,
|
||||
0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e,
|
||||
0x67, 0x65, 0x52, 0x03, 0x66, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x61, 0x74, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
|
||||
0x03, 0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x75,
|
||||
0x6e, 0x22, 0x68, 0x0a, 0x08, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a,
|
||||
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44,
|
||||
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b,
|
||||
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a,
|
||||
0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x3f, 0x0a, 0x11, 0x52, 0x75,
|
||||
0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x3e, 0x0a, 0x14, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f,
|
||||
0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x22, 0x16, 0x0a, 0x14, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x58, 0x44, 0x4f, 0x4d,
|
||||
0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d,
|
||||
0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x49, 0x50, 0x22, 0x15, 0x0a, 0x13, 0x42, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45, 0x44,
|
||||
0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69,
|
||||
0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61,
|
||||
0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10,
|
||||
0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a,
|
||||
0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73,
|
||||
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x71,
|
||||
0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x61, 0x6c, 0x6c,
|
||||
0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x61,
|
||||
0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x31, 0x0a, 0x0e,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65,
|
||||
0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12,
|
||||
0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e,
|
||||
0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73,
|
||||
0x74, 0x41, 0x73, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73,
|
||||
0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x75,
|
||||
0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x69, 0x64,
|
||||
0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x32, 0x8a, 0x01, 0x0a, 0x0a, 0x44, 0x4e, 0x53,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x44, 0x4e,
|
||||
0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x13, 0x2e, 0x44, 0x4e, 0x53, 0x50,
|
||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b,
|
||||
0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a,
|
||||
0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x6c, 0x6c,
|
||||
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
|
||||
0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x3d, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x67,
|
||||
0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x73,
|
||||
0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x10, 0x44, 0x4e, 0x53, 0x50,
|
||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02,
|
||||
0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x3f, 0x0a, 0x11, 0x52,
|
||||
0x75, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64,
|
||||
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x3e, 0x0a, 0x14,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x75, 0x73, 0x74,
|
||||
0x6f, 0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x22, 0x16, 0x0a, 0x14,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x58, 0x44, 0x4f,
|
||||
0x4d, 0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67,
|
||||
0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x49, 0x50, 0x22, 0x15, 0x0a, 0x13, 0x42, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45,
|
||||
0x44, 0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c,
|
||||
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f,
|
||||
0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
|
||||
0x10, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25,
|
||||
0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x61,
|
||||
0x73, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
|
||||
0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x65,
|
||||
0x73, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x61, 0x6c,
|
||||
0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d,
|
||||
0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x31, 0x0a,
|
||||
0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18,
|
||||
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72,
|
||||
0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73,
|
||||
0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69,
|
||||
0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69,
|
||||
0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x72,
|
||||
0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x69,
|
||||
0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x41, 0x75,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74,
|
||||
0x69, 0x6e, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x6f, 0x68, 0x5f, 0x61, 0x75, 0x74, 0x68,
|
||||
0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6f, 0x68,
|
||||
0x41, 0x75, 0x74, 0x68, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x32, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x62, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x42, 0x63, 0x72, 0x79, 0x70, 0x74, 0x42, 0x13, 0x0a, 0x11,
|
||||
0x64, 0x6f, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
|
||||
0x68, 0x32, 0x8a, 0x01, 0x0a, 0x0a, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x12, 0x34, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
|
||||
0x65, 0x73, 0x12, 0x13, 0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74,
|
||||
0x12, 0x12, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67,
|
||||
0x53, 0x74, 0x61, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x3d,
|
||||
0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
||||
0x74, 0x65, 0x64, 0x42, 0x10, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02, 0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -1391,7 +1487,7 @@ func file_backend_proto_rawDescGZIP() []byte {
|
||||
return file_backend_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
|
||||
var file_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||
var file_backend_proto_goTypes = []interface{}{
|
||||
(*DNSProfilesRequest)(nil), // 0: DNSProfilesRequest
|
||||
(*DNSProfile)(nil), // 1: DNSProfile
|
||||
@ -1409,45 +1505,47 @@ var file_backend_proto_goTypes = []interface{}{
|
||||
(*DeviceBillingStat)(nil), // 13: DeviceBillingStat
|
||||
(*AccessSettings)(nil), // 14: AccessSettings
|
||||
(*CidrRange)(nil), // 15: CidrRange
|
||||
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
|
||||
(*durationpb.Duration)(nil), // 17: google.protobuf.Duration
|
||||
(*emptypb.Empty)(nil), // 18: google.protobuf.Empty
|
||||
(*AuthenticationSettings)(nil), // 16: AuthenticationSettings
|
||||
(*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp
|
||||
(*durationpb.Duration)(nil), // 18: google.protobuf.Duration
|
||||
(*emptypb.Empty)(nil), // 19: google.protobuf.Empty
|
||||
}
|
||||
var file_backend_proto_depIdxs = []int32{
|
||||
16, // 0: DNSProfilesRequest.sync_time:type_name -> google.protobuf.Timestamp
|
||||
17, // 0: DNSProfilesRequest.sync_time:type_name -> google.protobuf.Timestamp
|
||||
2, // 1: DNSProfile.safe_browsing:type_name -> SafeBrowsingSettings
|
||||
4, // 2: DNSProfile.parental:type_name -> ParentalSettings
|
||||
8, // 3: DNSProfile.rule_lists:type_name -> RuleListsSettings
|
||||
3, // 4: DNSProfile.devices:type_name -> DeviceSettings
|
||||
17, // 5: DNSProfile.filtered_response_ttl:type_name -> google.protobuf.Duration
|
||||
18, // 5: DNSProfile.filtered_response_ttl:type_name -> google.protobuf.Duration
|
||||
9, // 6: DNSProfile.blocking_mode_custom_ip:type_name -> BlockingModeCustomIP
|
||||
10, // 7: DNSProfile.blocking_mode_nxdomain:type_name -> BlockingModeNXDOMAIN
|
||||
11, // 8: DNSProfile.blocking_mode_null_ip:type_name -> BlockingModeNullIP
|
||||
12, // 9: DNSProfile.blocking_mode_refused:type_name -> BlockingModeREFUSED
|
||||
14, // 10: DNSProfile.access:type_name -> AccessSettings
|
||||
5, // 11: ParentalSettings.schedule:type_name -> ScheduleSettings
|
||||
6, // 12: ScheduleSettings.weeklyRange:type_name -> WeeklyRange
|
||||
7, // 13: WeeklyRange.mon:type_name -> DayRange
|
||||
7, // 14: WeeklyRange.tue:type_name -> DayRange
|
||||
7, // 15: WeeklyRange.wed:type_name -> DayRange
|
||||
7, // 16: WeeklyRange.thu:type_name -> DayRange
|
||||
7, // 17: WeeklyRange.fri:type_name -> DayRange
|
||||
7, // 18: WeeklyRange.sat:type_name -> DayRange
|
||||
7, // 19: WeeklyRange.sun:type_name -> DayRange
|
||||
17, // 20: DayRange.start:type_name -> google.protobuf.Duration
|
||||
17, // 21: DayRange.end:type_name -> google.protobuf.Duration
|
||||
16, // 22: DeviceBillingStat.last_activity_time:type_name -> google.protobuf.Timestamp
|
||||
15, // 23: AccessSettings.allowlist_cidr:type_name -> CidrRange
|
||||
15, // 24: AccessSettings.blocklist_cidr:type_name -> CidrRange
|
||||
0, // 25: DNSService.getDNSProfiles:input_type -> DNSProfilesRequest
|
||||
13, // 26: DNSService.saveDevicesBillingStat:input_type -> DeviceBillingStat
|
||||
1, // 27: DNSService.getDNSProfiles:output_type -> DNSProfile
|
||||
18, // 28: DNSService.saveDevicesBillingStat:output_type -> google.protobuf.Empty
|
||||
27, // [27:29] is the sub-list for method output_type
|
||||
25, // [25:27] is the sub-list for method input_type
|
||||
25, // [25:25] is the sub-list for extension type_name
|
||||
25, // [25:25] is the sub-list for extension extendee
|
||||
0, // [0:25] is the sub-list for field type_name
|
||||
16, // 11: DeviceSettings.authentication:type_name -> AuthenticationSettings
|
||||
5, // 12: ParentalSettings.schedule:type_name -> ScheduleSettings
|
||||
6, // 13: ScheduleSettings.weeklyRange:type_name -> WeeklyRange
|
||||
7, // 14: WeeklyRange.mon:type_name -> DayRange
|
||||
7, // 15: WeeklyRange.tue:type_name -> DayRange
|
||||
7, // 16: WeeklyRange.wed:type_name -> DayRange
|
||||
7, // 17: WeeklyRange.thu:type_name -> DayRange
|
||||
7, // 18: WeeklyRange.fri:type_name -> DayRange
|
||||
7, // 19: WeeklyRange.sat:type_name -> DayRange
|
||||
7, // 20: WeeklyRange.sun:type_name -> DayRange
|
||||
18, // 21: DayRange.start:type_name -> google.protobuf.Duration
|
||||
18, // 22: DayRange.end:type_name -> google.protobuf.Duration
|
||||
17, // 23: DeviceBillingStat.last_activity_time:type_name -> google.protobuf.Timestamp
|
||||
15, // 24: AccessSettings.allowlist_cidr:type_name -> CidrRange
|
||||
15, // 25: AccessSettings.blocklist_cidr:type_name -> CidrRange
|
||||
0, // 26: DNSService.getDNSProfiles:input_type -> DNSProfilesRequest
|
||||
13, // 27: DNSService.saveDevicesBillingStat:input_type -> DeviceBillingStat
|
||||
1, // 28: DNSService.getDNSProfiles:output_type -> DNSProfile
|
||||
19, // 29: DNSService.saveDevicesBillingStat:output_type -> google.protobuf.Empty
|
||||
28, // [28:30] is the sub-list for method output_type
|
||||
26, // [26:28] is the sub-list for method input_type
|
||||
26, // [26:26] is the sub-list for extension type_name
|
||||
26, // [26:26] is the sub-list for extension extendee
|
||||
0, // [0:26] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_backend_proto_init() }
|
||||
@ -1648,6 +1746,18 @@ func file_backend_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_backend_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AuthenticationSettings); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_backend_proto_msgTypes[1].OneofWrappers = []interface{}{
|
||||
(*DNSProfile_BlockingModeCustomIp)(nil),
|
||||
@ -1655,13 +1765,16 @@ func file_backend_proto_init() {
|
||||
(*DNSProfile_BlockingModeNullIp)(nil),
|
||||
(*DNSProfile_BlockingModeRefused)(nil),
|
||||
}
|
||||
file_backend_proto_msgTypes[16].OneofWrappers = []interface{}{
|
||||
(*AuthenticationSettings_PasswordHashBcrypt)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_backend_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 16,
|
||||
NumMessages: 17,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@ -66,6 +66,7 @@ message DeviceSettings {
|
||||
bool filtering_enabled = 3;
|
||||
bytes linked_ip = 4;
|
||||
repeated bytes dedicated_ips = 5;
|
||||
AuthenticationSettings authentication = 6;
|
||||
}
|
||||
|
||||
message ParentalSettings {
|
||||
@ -136,3 +137,10 @@ message CidrRange {
|
||||
bytes address = 1;
|
||||
uint32 prefix = 2;
|
||||
}
|
||||
|
||||
message AuthenticationSettings {
|
||||
bool doh_auth_only = 1;
|
||||
oneof doh_password_hash {
|
||||
bytes password_hash_bcrypt = 2;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.25.1
|
||||
// - protoc v4.25.3
|
||||
// source: backend.proto
|
||||
|
||||
package backendpb
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdprotobuf"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
@ -355,6 +356,37 @@ func (x *ScheduleSettings) toInternal() (sch *agd.ParentalProtectionSchedule, er
|
||||
return sch, nil
|
||||
}
|
||||
|
||||
// toInternal converts a protobuf custom blocking-mode to an internal one.
|
||||
// Assumes that at least one IP address is specified in the result blocking-mode
|
||||
// object.
|
||||
func (pbm *BlockingModeCustomIP) toInternal() (m dnsmsg.BlockingMode, err error) {
|
||||
custom := &dnsmsg.BlockingModeCustomIP{}
|
||||
|
||||
// TODO(a.garipov): Only one IPv4 address is supported on protobuf side.
|
||||
var ipv4Addr netip.Addr
|
||||
err = ipv4Addr.UnmarshalBinary(pbm.Ipv4)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad custom ipv4: %w", err)
|
||||
} else if ipv4Addr.IsValid() {
|
||||
custom.IPv4 = []netip.Addr{ipv4Addr}
|
||||
}
|
||||
|
||||
// TODO(a.garipov): Only one IPv6 address is supported on protobuf side.
|
||||
var ipv6Addr netip.Addr
|
||||
err = ipv6Addr.UnmarshalBinary(pbm.Ipv6)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad custom ipv6: %w", err)
|
||||
} else if ipv6Addr.IsValid() {
|
||||
custom.IPv6 = []netip.Addr{ipv6Addr}
|
||||
}
|
||||
|
||||
if len(custom.IPv4)+len(custom.IPv6) == 0 {
|
||||
return nil, errors.Error("no valid custom ips found")
|
||||
}
|
||||
|
||||
return custom, nil
|
||||
}
|
||||
|
||||
// blockingModeToInternal converts a protobuf blocking-mode sum-type to an
|
||||
// internal one. If pbm is nil, blockingModeToInternal returns a null-IP
|
||||
// blocking mode.
|
||||
@ -363,18 +395,7 @@ func blockingModeToInternal(pbm isDNSProfile_BlockingMode) (m dnsmsg.BlockingMod
|
||||
case nil:
|
||||
return &dnsmsg.BlockingModeNullIP{}, nil
|
||||
case *DNSProfile_BlockingModeCustomIp:
|
||||
custom := &dnsmsg.BlockingModeCustomIP{}
|
||||
err = custom.IPv4.UnmarshalBinary(pbm.BlockingModeCustomIp.Ipv4)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad custom ipv4: %w", err)
|
||||
}
|
||||
|
||||
err = custom.IPv6.UnmarshalBinary(pbm.BlockingModeCustomIp.Ipv6)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad custom ipv6: %w", err)
|
||||
}
|
||||
|
||||
return custom, nil
|
||||
return pbm.BlockingModeCustomIp.toInternal()
|
||||
case *DNSProfile_BlockingModeNxdomain:
|
||||
return &dnsmsg.BlockingModeNXDOMAIN{}, nil
|
||||
case *DNSProfile_BlockingModeNullIp:
|
||||
@ -443,6 +464,11 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
||||
}
|
||||
}
|
||||
|
||||
auth, err := ds.Authentication.toInternal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("auth: %s: %w", ds.Id, err)
|
||||
}
|
||||
|
||||
id, err := agd.NewDeviceID(ds.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("device id: %s: %w", ds.Id, err)
|
||||
@ -454,6 +480,7 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
||||
}
|
||||
|
||||
return &agd.Device{
|
||||
Auth: auth,
|
||||
ID: id,
|
||||
Name: name,
|
||||
LinkedIP: linkedIP,
|
||||
@ -462,6 +489,44 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
||||
}, nil
|
||||
}
|
||||
|
||||
// toInternal converts a protobuf auth settings structure to an internal one.
|
||||
// If x is nil, toInternal returns non-nil settings with enabled field set to
|
||||
// false.
|
||||
func (x *AuthenticationSettings) toInternal() (s *agd.AuthSettings, err error) {
|
||||
if x == nil {
|
||||
return &agd.AuthSettings{
|
||||
Enabled: false,
|
||||
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
ph, err := dohPasswordToInternal(x.DohPasswordHash)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("password hash: %w", err)
|
||||
}
|
||||
|
||||
return &agd.AuthSettings{
|
||||
PasswordHash: ph,
|
||||
Enabled: true,
|
||||
DoHAuthOnly: x.DohAuthOnly,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// dohPasswordToInternal converts a protobuf DoH password hash sum-type to an
|
||||
// internal one.
|
||||
func dohPasswordToInternal(
|
||||
pbp isAuthenticationSettings_DohPasswordHash,
|
||||
) (p agdpasswd.Authenticator, err error) {
|
||||
switch pbp := pbp.(type) {
|
||||
case nil:
|
||||
return agdpasswd.AllowAuthenticator{}, nil
|
||||
case *AuthenticationSettings_PasswordHashBcrypt:
|
||||
return agdpasswd.NewPasswordHashBcrypt(pbp.PasswordHashBcrypt), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("bad pb auth doh password hash %T(%[1]v)", pbp)
|
||||
}
|
||||
}
|
||||
|
||||
// rulesToInternal is a helper that converts the filter rules from the backend
|
||||
// response to AdGuard DNS filtering rules.
|
||||
func rulesToInternal(
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
@ -92,7 +93,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
|
||||
assert.NotEqual(t, newProfile(t), got)
|
||||
assert.NotEqual(t, newDevices(t), gotDevices)
|
||||
assert.Len(t, gotDevices, 1)
|
||||
assert.Len(t, gotDevices, 2)
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
@ -153,6 +154,16 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
||||
})
|
||||
|
||||
t.Run("nil_ips_blocking_mode", func(t *testing.T) {
|
||||
dp := NewTestDNSProfile(t)
|
||||
bm := dp.BlockingMode.(*DNSProfile_BlockingModeCustomIp)
|
||||
bm.BlockingModeCustomIp.Ipv4 = nil
|
||||
bm.BlockingModeCustomIp.Ipv6 = nil
|
||||
|
||||
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
testutil.AssertErrorMsg(t, "blocking mode: no valid custom ips found", err)
|
||||
})
|
||||
|
||||
t.Run("nil_blocking_mode", func(t *testing.T) {
|
||||
dp := NewTestDNSProfile(t)
|
||||
dp.BlockingMode = nil
|
||||
@ -244,17 +255,33 @@ func NewTestDNSProfile(tb testing.TB) (dp *DNSProfile) {
|
||||
}
|
||||
|
||||
devices := []*DeviceSettings{{
|
||||
Id: "118ffe93",
|
||||
Name: "118ffe93-name",
|
||||
Id: "1111aaaa",
|
||||
Name: "1111aaaa-name",
|
||||
FilteringEnabled: false,
|
||||
LinkedIp: ipToBytes(tb, netip.MustParseAddr("1.1.1.1")),
|
||||
DedicatedIps: [][]byte{ipToBytes(tb, netip.MustParseAddr("1.1.1.2"))},
|
||||
}, {
|
||||
Id: "b9e1a762",
|
||||
Name: "b9e1a762-name",
|
||||
Id: "2222bbbb",
|
||||
Name: "2222bbbb-name",
|
||||
FilteringEnabled: true,
|
||||
LinkedIp: ipToBytes(tb, netip.MustParseAddr("2.2.2.2")),
|
||||
DedicatedIps: nil,
|
||||
Authentication: &AuthenticationSettings{
|
||||
DohAuthOnly: true,
|
||||
DohPasswordHash: &AuthenticationSettings_PasswordHashBcrypt{
|
||||
PasswordHashBcrypt: []byte("test-hash"),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
Id: "3333cccc",
|
||||
Name: "3333cccc-name",
|
||||
FilteringEnabled: false,
|
||||
LinkedIp: ipToBytes(tb, netip.MustParseAddr("3.3.3.3")),
|
||||
DedicatedIps: nil,
|
||||
Authentication: &AuthenticationSettings{
|
||||
DohAuthOnly: false,
|
||||
DohPasswordHash: nil,
|
||||
},
|
||||
}}
|
||||
|
||||
return &DNSProfile{
|
||||
@ -358,8 +385,8 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
||||
}
|
||||
|
||||
wantBlockingMode := &dnsmsg.BlockingModeCustomIP{
|
||||
IPv4: netip.MustParseAddr("1.2.3.4"),
|
||||
IPv6: netip.MustParseAddr("1234::cdef"),
|
||||
IPv4: []netip.Addr{netip.MustParseAddr("1.2.3.4")},
|
||||
IPv6: []netip.Addr{netip.MustParseAddr("1234::cdef")},
|
||||
}
|
||||
|
||||
wantAccess := access.NewDefaultProfile(&access.ProfileConfig{
|
||||
@ -376,8 +403,9 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
||||
ID: testProfileID,
|
||||
UpdateTime: TestUpdTime,
|
||||
DeviceIDs: []agd.DeviceID{
|
||||
"118ffe93",
|
||||
"b9e1a762",
|
||||
"1111aaaa",
|
||||
"2222bbbb",
|
||||
"3333cccc",
|
||||
},
|
||||
RuleListIDs: []agd.FilterListID{"1"},
|
||||
CustomRules: []agd.FilterRuleText{"||example.org^"},
|
||||
@ -399,17 +427,38 @@ func newDevices(t *testing.T) (d []*agd.Device) {
|
||||
t.Helper()
|
||||
|
||||
return []*agd.Device{{
|
||||
ID: "118ffe93",
|
||||
Auth: &agd.AuthSettings{
|
||||
Enabled: false,
|
||||
DoHAuthOnly: false,
|
||||
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||
},
|
||||
ID: "1111aaaa",
|
||||
LinkedIP: netip.MustParseAddr("1.1.1.1"),
|
||||
Name: "118ffe93-name",
|
||||
Name: "1111aaaa-name",
|
||||
DedicatedIPs: []netip.Addr{netip.MustParseAddr("1.1.1.2")},
|
||||
FilteringEnabled: false,
|
||||
}, {
|
||||
ID: "b9e1a762",
|
||||
Auth: &agd.AuthSettings{
|
||||
Enabled: true,
|
||||
DoHAuthOnly: true,
|
||||
PasswordHash: agdpasswd.NewPasswordHashBcrypt([]byte("test-hash")),
|
||||
},
|
||||
ID: "2222bbbb",
|
||||
LinkedIP: netip.MustParseAddr("2.2.2.2"),
|
||||
Name: "b9e1a762-name",
|
||||
Name: "2222bbbb-name",
|
||||
DedicatedIPs: nil,
|
||||
FilteringEnabled: true,
|
||||
}, {
|
||||
Auth: &agd.AuthSettings{
|
||||
Enabled: true,
|
||||
DoHAuthOnly: false,
|
||||
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||
},
|
||||
ID: "3333cccc",
|
||||
LinkedIP: netip.MustParseAddr("3.3.3.3"),
|
||||
Name: "3333cccc-name",
|
||||
DedicatedIPs: nil,
|
||||
FilteringEnabled: false,
|
||||
}}
|
||||
}
|
||||
|
||||
@ -479,7 +528,7 @@ func BenchmarkDNSProfile_ToInternal(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
profSink, _, errSink = dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ func BenchmarkProfileStorage_Profiles(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
respSink, errSink = s.Profiles(ctx, req)
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,12 @@ package billstat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
@ -18,6 +18,9 @@ import (
|
||||
// RuntimeRecorderConfig is the configuration structure for a runtime billing
|
||||
// statistics recorder. All fields must be non-empty.
|
||||
type RuntimeRecorderConfig struct {
|
||||
// ErrColl is used to collect errors during refreshes.
|
||||
ErrColl errcoll.Interface
|
||||
|
||||
// Uploader is used to upload the billing statistics records to.
|
||||
Uploader Uploader
|
||||
}
|
||||
@ -29,6 +32,7 @@ func NewRuntimeRecorder(c *RuntimeRecorderConfig) (r *RuntimeRecorder) {
|
||||
mu: &sync.Mutex{},
|
||||
records: Records{},
|
||||
uploader: c.Uploader,
|
||||
errColl: c.ErrColl,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +48,9 @@ type RuntimeRecorder struct {
|
||||
// uploader is the uploader to which the billing statistics records are
|
||||
// uploaded.
|
||||
uploader Uploader
|
||||
|
||||
// errColl is used to collect errors during refreshes.
|
||||
errColl errcoll.Interface
|
||||
}
|
||||
|
||||
// type check
|
||||
@ -58,6 +65,10 @@ func (r *RuntimeRecorder) Record(
|
||||
start time.Time,
|
||||
proto agd.Protocol,
|
||||
) {
|
||||
// TODO(a.garipov): Use slog.
|
||||
log.Debug("billstat_refresh: started")
|
||||
defer log.Debug("billstat_refresh: finished")
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
@ -96,7 +107,7 @@ func (r *RuntimeRecorder) Refresh(ctx context.Context) (err error) {
|
||||
|
||||
if err != nil {
|
||||
r.remergeRecords(records)
|
||||
log.Info("billstat: refresh failed, records remerged")
|
||||
log.Info("billstat_refresh: failed, records remerged")
|
||||
} else {
|
||||
metrics.BillStatUploadTimestamp.SetToCurrentTime()
|
||||
}
|
||||
@ -106,10 +117,10 @@ func (r *RuntimeRecorder) Refresh(ctx context.Context) (err error) {
|
||||
|
||||
err = r.uploader.Upload(ctx, records)
|
||||
if err != nil {
|
||||
return fmt.Errorf("uploading billstat records: %w", err)
|
||||
errcoll.Collectf(ctx, r.errColl, "billstat_refresh: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// resetRecords returns the current data and resets the records map to an empty
|
||||
|
@ -30,6 +30,11 @@ const (
|
||||
func TestRuntimeRecorder_success(t *testing.T) {
|
||||
var gotRecord *billstat.Record
|
||||
c := &billstat.RuntimeRecorderConfig{
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, _ error) {
|
||||
panic("not implemented")
|
||||
},
|
||||
},
|
||||
Uploader: &agdtest.BillStatUploader{
|
||||
OnUpload: func(_ context.Context, records billstat.Records) (err error) {
|
||||
gotRecord = records[devID]
|
||||
@ -48,7 +53,7 @@ func TestRuntimeRecorder_success(t *testing.T) {
|
||||
// incremented.
|
||||
const reqNum = 2
|
||||
var err error
|
||||
for i := 0; i < reqNum; i++ {
|
||||
for range reqNum {
|
||||
r.Record(ctx, devID, clientCtry, clientASN, start, proto)
|
||||
}
|
||||
|
||||
@ -89,7 +94,13 @@ func TestRuntimeRecorder_fail(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var gotCollErr error
|
||||
c := &billstat.RuntimeRecorderConfig{
|
||||
ErrColl: &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, err error) {
|
||||
gotCollErr = err
|
||||
},
|
||||
},
|
||||
Uploader: &agdtest.BillStatUploader{
|
||||
OnUpload: onUpload,
|
||||
},
|
||||
@ -118,6 +129,7 @@ func TestRuntimeRecorder_fail(t *testing.T) {
|
||||
|
||||
err := r.Refresh(context.Background())
|
||||
require.ErrorIs(t, err, testError)
|
||||
require.ErrorIs(t, gotCollErr, testError)
|
||||
require.Nil(t, gotRecord)
|
||||
|
||||
// Request the backend again, expect the correct, merged data.
|
||||
|
@ -46,6 +46,7 @@ func newChanPacketConn(
|
||||
sessions chan *packetSession,
|
||||
subnet netip.Prefix,
|
||||
writeRequests chan *packetConnWriteReq,
|
||||
writeRequestsGauge prometheus.Gauge,
|
||||
laddr net.Addr,
|
||||
) (c *chanPacketConn) {
|
||||
return &chanPacketConn{
|
||||
@ -54,7 +55,7 @@ func newChanPacketConn(
|
||||
writeRequests: writeRequests,
|
||||
|
||||
sessionsGauge: metrics.BindToDeviceUDPSessionsChanSize.WithLabelValues(subnet.String()),
|
||||
writeRequestsGauge: metrics.BindToDeviceUDPWriteRequestsChanSize.WithLabelValues(subnet.String()),
|
||||
writeRequestsGauge: writeRequestsGauge,
|
||||
|
||||
deadlineMu: &sync.RWMutex{},
|
||||
|
||||
@ -64,9 +65,9 @@ func newChanPacketConn(
|
||||
}
|
||||
|
||||
// packetConnWriteReq is a request to write a piece of data to the original
|
||||
// packet connection. resp, body, and either raddr or session must be set.
|
||||
// packet connection. respCh, body, and either raddr or session must be set.
|
||||
type packetConnWriteReq struct {
|
||||
resp chan *packetConnWriteResp
|
||||
respCh chan *packetConnWriteResp
|
||||
session *packetSession
|
||||
raddr net.Addr
|
||||
deadline time.Time
|
||||
@ -265,7 +266,7 @@ func (c *chanPacketConn) writeToSession(
|
||||
|
||||
resp := make(chan *packetConnWriteResp, 1)
|
||||
req := &packetConnWriteReq{
|
||||
resp: resp,
|
||||
respCh: resp,
|
||||
session: s,
|
||||
raddr: raddr,
|
||||
deadline: deadline,
|
||||
|
@ -8,13 +8,14 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestChanPacketConn_Close(t *testing.T) {
|
||||
sessions := make(chan *packetSession)
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, testLAddr)
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, nil, testLAddr)
|
||||
err := c.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
@ -23,14 +24,14 @@ func TestChanPacketConn_Close(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestChanPacketConn_LocalAddr(t *testing.T) {
|
||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||
got := c.LocalAddr()
|
||||
assert.Equal(t, testLAddr, got)
|
||||
}
|
||||
|
||||
func TestChanPacketConn_ReadFromSession(t *testing.T) {
|
||||
sessions := make(chan *packetSession, 1)
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, testLAddr)
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, nil, testLAddr)
|
||||
|
||||
body := []byte("hello")
|
||||
bodyLen := len(body)
|
||||
@ -79,7 +80,9 @@ func TestChanPacketConn_ReadFromSession(t *testing.T) {
|
||||
func TestChanPacketConn_WriteToSession(t *testing.T) {
|
||||
sessions := make(chan *packetSession, 1)
|
||||
writes := make(chan *packetConnWriteReq, 1)
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, writes, testLAddr)
|
||||
|
||||
gauge := prometheus.NewGauge(prometheus.GaugeOpts{})
|
||||
c := newChanPacketConn(sessions, testSubnetIPv4, writes, gauge, testLAddr)
|
||||
|
||||
body := []byte("hello")
|
||||
bodyLen := len(body)
|
||||
@ -125,7 +128,7 @@ func checkWriteReqAndRespond(
|
||||
|
||||
req, ok := testutil.RequireReceive(pt, writes, testTimeout)
|
||||
require.NotNil(pt, req)
|
||||
require.NotNil(pt, req.resp)
|
||||
require.NotNil(pt, req.respCh)
|
||||
require.True(pt, ok)
|
||||
|
||||
if wantRaddr != nil {
|
||||
@ -141,14 +144,14 @@ func checkWriteReqAndRespond(
|
||||
assert.Equal(pt, wantDeadline, req.deadline)
|
||||
assert.Equal(pt, wantBody, req.body)
|
||||
|
||||
testutil.RequireSend(pt, req.resp, &packetConnWriteResp{
|
||||
testutil.RequireSend(pt, req.respCh, &packetConnWriteResp{
|
||||
err: nil,
|
||||
written: len(wantBody),
|
||||
}, testTimeout)
|
||||
}
|
||||
|
||||
func TestChanPacketConn_deadlines(t *testing.T) {
|
||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||
deadline := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
testCases := []struct {
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/syncutil"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// interfaceListener contains information about a single interface listener.
|
||||
@ -26,6 +27,8 @@ type interfaceListener struct {
|
||||
writeRequests chan *packetConnWriteReq
|
||||
done chan unit
|
||||
errColl errcoll.Interface
|
||||
writeRequestsGauge prometheus.Gauge
|
||||
writeDurationHist prometheus.Observer
|
||||
ifaceName string
|
||||
port uint16
|
||||
}
|
||||
@ -113,7 +116,7 @@ func (l *interfaceListener) listenUDP(errCh chan<- error) {
|
||||
|
||||
errCh <- nil
|
||||
|
||||
go l.writeUDP(udpConn)
|
||||
go l.writeUDPResponses(udpConn)
|
||||
|
||||
logPrefix := fmt.Sprintf("bindtodevice: listener %s:%d: udp", l.ifaceName, l.port)
|
||||
|
||||
@ -185,46 +188,60 @@ func (l *interfaceListener) readUDP(c *net.UDPConn, logPrefix string) (err error
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeUDP runs the UDP write loop. It is intended to be used as a goroutine.
|
||||
func (l *interfaceListener) writeUDP(c *net.UDPConn) {
|
||||
// writeUDPResponses runs the UDP write loop. It is intended to be used as a
|
||||
// goroutine.
|
||||
func (l *interfaceListener) writeUDPResponses(c *net.UDPConn) {
|
||||
defer log.OnPanic("interfaceListener.writeUDP")
|
||||
|
||||
logPrefix := fmt.Sprintf("bindtodevice: listener %s:%d: udp write", l.ifaceName, l.port)
|
||||
for {
|
||||
var req *packetConnWriteReq
|
||||
select {
|
||||
case <-l.done:
|
||||
optlog.Debug1("%s: done", logPrefix)
|
||||
optlog.Debug2("bindtodevice: listener %s:%d: udp write: done", l.ifaceName, l.port)
|
||||
|
||||
return
|
||||
case req = <-l.writeRequests:
|
||||
// Go on.
|
||||
case req := <-l.writeRequests:
|
||||
l.writeUDP(c, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writeUDP handles a single write operation and writes a response to
|
||||
// req.respCh.
|
||||
func (l *interfaceListener) writeUDP(c *net.UDPConn, req *packetConnWriteReq) {
|
||||
resp := &packetConnWriteResp{}
|
||||
resp.err = c.SetWriteDeadline(req.deadline)
|
||||
if resp.err != nil {
|
||||
req.resp <- resp
|
||||
req.respCh <- resp
|
||||
|
||||
continue
|
||||
return
|
||||
}
|
||||
|
||||
if s := req.session; s == nil {
|
||||
resp.written, resp.err = c.WriteTo(req.body, req.raddr)
|
||||
} else {
|
||||
resp.written, _, resp.err = c.WriteMsgUDP(
|
||||
req.body,
|
||||
s.respOOB,
|
||||
req.session.raddr,
|
||||
)
|
||||
|
||||
l.bodyPool.Put(&s.readBody)
|
||||
}
|
||||
l.writeToUDPConn(c, req, resp)
|
||||
|
||||
resetDeadlineErr := c.SetWriteDeadline(time.Time{})
|
||||
|
||||
resp.err = errors.WithDeferred(resp.err, resetDeadlineErr)
|
||||
|
||||
req.resp <- resp
|
||||
}
|
||||
req.respCh <- resp
|
||||
}
|
||||
|
||||
// writeToUDPConn writes to c, depending on what kind of session req contains,
|
||||
// and sets resp.written and resp.err accordingly.
|
||||
func (l *interfaceListener) writeToUDPConn(
|
||||
c *net.UDPConn,
|
||||
req *packetConnWriteReq,
|
||||
resp *packetConnWriteResp,
|
||||
) {
|
||||
start := time.Now()
|
||||
defer func() { l.writeDurationHist.Observe(time.Since(start).Seconds()) }()
|
||||
|
||||
s := req.session
|
||||
if s == nil {
|
||||
resp.written, resp.err = c.WriteTo(req.body, req.raddr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
resp.written, _, resp.err = c.WriteMsgUDP(req.body, s.respOOB, req.session.raddr)
|
||||
|
||||
l.bodyPool.Put(&s.readBody)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestListenConfig(t *testing.T) {
|
||||
pc := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
||||
pc := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||
lsnr := newChanListener(nil, testSubnetIPv4, testLAddr)
|
||||
addr := &agdnet.PrefixNetAddr{
|
||||
Prefix: testSubnetIPv4,
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/netext"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/mapsutil"
|
||||
@ -84,7 +85,7 @@ func (m *Manager) Add(id ID, ifaceName string, port uint16, ctrlConf *ControlCon
|
||||
return nil
|
||||
}
|
||||
|
||||
err = mapsutil.OrderedRangeError(m.ifaceListeners, validateDup)
|
||||
err = mapsutil.SortedRangeError(m.ifaceListeners, validateDup)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
@ -116,6 +117,8 @@ func (m *Manager) newInterfaceListener(
|
||||
writeRequests: make(chan *packetConnWriteReq, m.chanBufSize),
|
||||
done: m.done,
|
||||
errColl: m.errColl,
|
||||
writeRequestsGauge: metrics.BindToDeviceUDPWriteRequestsChanSize.WithLabelValues(ifaceName),
|
||||
writeDurationHist: metrics.BindToDeviceUDPWriteDurationSeconds.WithLabelValues(ifaceName),
|
||||
ifaceName: ifaceName,
|
||||
port: port,
|
||||
}
|
||||
@ -159,11 +162,17 @@ func (m *Manager) ListenConfig(id ID, subnet netip.Prefix) (c *ListenConfig, err
|
||||
}
|
||||
|
||||
sessCh := make(chan *packetSession, m.chanBufSize)
|
||||
pConn := newChanPacketConn(sessCh, subnet, l.writeRequests, &agdnet.PrefixNetAddr{
|
||||
pConn := newChanPacketConn(
|
||||
sessCh,
|
||||
subnet,
|
||||
l.writeRequests,
|
||||
l.writeRequestsGauge,
|
||||
&agdnet.PrefixNetAddr{
|
||||
Prefix: subnet,
|
||||
Net: "udp",
|
||||
Port: l.port,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
err = l.conns.addPacketConn(pConn)
|
||||
if err != nil {
|
||||
|
@ -233,10 +233,10 @@ func TestManager(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lc)
|
||||
|
||||
err = m.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = m.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return m.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
return m.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
t.Run("tcp", func(t *testing.T) {
|
||||
|
@ -113,9 +113,7 @@ func SubtestListenControlTCP(
|
||||
ifaceName string,
|
||||
ifaceNet *net.IPNet,
|
||||
) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
lsnr, err := lc.Listen(ctx, "tcp", "0.0.0.0:0")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, lsnr.Close)
|
||||
@ -194,9 +192,7 @@ func SubtestListenControlUDP(
|
||||
ifaceName string,
|
||||
ifaceNet *net.IPNet,
|
||||
) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
packetConn, err := lc.ListenPacket(ctx, "udp", "0.0.0.0:0")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, packetConn.Close)
|
||||
@ -528,7 +524,7 @@ func BenchmarkReadPacketSession(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
sessSink, errSink = readPacketSession(c, body, oob)
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ type additionalInfo map[string]string
|
||||
|
||||
// validateAdditionalInfo return an error is the section is invalid.
|
||||
func (c additionalInfo) validate() (err error) {
|
||||
return mapsutil.OrderedRangeError(c, func(k, _ string) (keyErr error) {
|
||||
return mapsutil.SortedRangeError(c, func(k, _ string) (keyErr error) {
|
||||
if model.LabelName(k).IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ func setupBillStat(
|
||||
}
|
||||
|
||||
rec = billstat.NewRuntimeRecorder(&billstat.RuntimeRecorderConfig{
|
||||
ErrColl: errColl,
|
||||
Uploader: billStatUploader,
|
||||
})
|
||||
|
||||
@ -121,11 +122,9 @@ func setupBillStat(
|
||||
return context.WithTimeout(context.Background(), timeout)
|
||||
},
|
||||
Refresher: rec,
|
||||
ErrColl: errColl,
|
||||
Name: "billstat",
|
||||
Interval: refrIvl,
|
||||
RefreshOnShutdown: true,
|
||||
RoutineLogsAreDebug: true,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = billStatRefr.Start(context.Background())
|
||||
@ -157,6 +156,7 @@ func setupProfDB(
|
||||
timeout := conf.Timeout.Duration
|
||||
profDB, err = profiledb.New(&profiledb.Config{
|
||||
Storage: profStrg,
|
||||
ErrColl: errColl,
|
||||
FullSyncIvl: conf.FullRefreshIvl.Duration,
|
||||
FullSyncRetryIvl: conf.FullRefreshRetryIvl.Duration,
|
||||
InitialTimeout: timeout,
|
||||
@ -173,11 +173,9 @@ func setupProfDB(
|
||||
return context.WithTimeout(context.Background(), timeout)
|
||||
},
|
||||
Refresher: profDB,
|
||||
ErrColl: errColl,
|
||||
Name: "profiledb",
|
||||
Interval: refrIvl,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: true,
|
||||
RandomizeStart: true,
|
||||
})
|
||||
err = profDBRefr.Start(context.Background())
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||
@ -27,7 +26,6 @@ import (
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
// Main is the entry point of application.
|
||||
@ -92,9 +90,6 @@ func Main() {
|
||||
|
||||
// Safe-browsing and adult-blocking filters
|
||||
|
||||
// TODO(ameshkov): Consider making configurable.
|
||||
filteringResolver := agdnet.NewCachingResolver(agdnet.DefaultResolver{}, 1*timeutil.Day)
|
||||
|
||||
err = os.MkdirAll(envs.FilterCachePath, agd.DefaultDirPerm)
|
||||
check(err)
|
||||
|
||||
@ -105,7 +100,6 @@ func Main() {
|
||||
cloner := dnsmsg.NewCloner(metrics.ClonerStat{})
|
||||
safeBrowsingHashes, safeBrowsingFilter, err := setupHashPrefixFilter(
|
||||
c.SafeBrowsing,
|
||||
filteringResolver,
|
||||
cloner,
|
||||
agd.FilterListIDSafeBrowsing,
|
||||
envs.SafeBrowsingURL,
|
||||
@ -118,7 +112,6 @@ func Main() {
|
||||
|
||||
adultBlockingHashes, adultBlockingFilter, err := setupHashPrefixFilter(
|
||||
c.AdultBlocking,
|
||||
filteringResolver,
|
||||
cloner,
|
||||
agd.FilterListIDAdultBlocking,
|
||||
envs.AdultBlockingURL,
|
||||
@ -132,7 +125,6 @@ func Main() {
|
||||
_, newRegDomainsFilter, err := setupHashPrefixFilter(
|
||||
// Reuse general safe browsing filter configuration.
|
||||
c.SafeBrowsing,
|
||||
filteringResolver,
|
||||
cloner,
|
||||
agd.FilterListIDNewRegDomains,
|
||||
envs.NewRegDomainsURL,
|
||||
@ -147,8 +139,6 @@ func Main() {
|
||||
|
||||
fltStrgConf := c.Filters.toInternal(
|
||||
errColl,
|
||||
filteringResolver,
|
||||
cloner,
|
||||
envs,
|
||||
safeBrowsingFilter,
|
||||
adultBlockingFilter,
|
||||
@ -156,7 +146,7 @@ func Main() {
|
||||
)
|
||||
|
||||
fltRefrTimeout := c.Filters.RefreshTimeout.Duration
|
||||
fltStrg, err := setupFilterStorage(fltStrgConf, sigHdlr, errColl, fltRefrTimeout)
|
||||
fltStrg, err := setupFilterStorage(fltStrgConf, sigHdlr, fltRefrTimeout)
|
||||
check(err)
|
||||
|
||||
fltGroups, err := c.FilteringGroups.toInternal(fltStrg)
|
||||
@ -293,8 +283,6 @@ func Main() {
|
||||
UseCacheTTLOverride: c.Cache.TTLOverride.Enabled,
|
||||
UseECSCache: c.Cache.Type == cacheTypeECS,
|
||||
ProfileDBEnabled: bool(envs.ProfilesEnabled),
|
||||
ResearchMetrics: bool(envs.ResearchMetrics),
|
||||
ResearchLogs: bool(envs.ResearchLogs),
|
||||
}
|
||||
|
||||
dnsSvc, err := dnssvc.New(dnsConf)
|
||||
|
@ -101,6 +101,7 @@ func (c *configuration) buildQueryLog(envs *environments) (l querylog.Interface)
|
||||
|
||||
return querylog.NewFileSystem(&querylog.FileSystemConfig{
|
||||
Path: envs.QueryLogPath,
|
||||
RandSeed: uint64(time.Now().UnixNano()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -50,8 +50,8 @@ func (c *ddrConfig) toInternal(msgs *dnsmsg.Constructor) (conf *agd.DDR) {
|
||||
func ddrRecsToSVCBTmpls(
|
||||
msgs *dnsmsg.Constructor,
|
||||
records map[string]*ddrRecord,
|
||||
) (targets *stringutil.Set, tmpls []*dns.SVCB) {
|
||||
targets = stringutil.NewSet()
|
||||
) (targets *container.MapSet[string], tmpls []*dns.SVCB) {
|
||||
targets = container.NewMapSet[string]()
|
||||
for target, r := range records {
|
||||
target = strings.TrimPrefix(target, "*.")
|
||||
targets.Add(target)
|
||||
|
@ -60,8 +60,6 @@ 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"`
|
||||
}
|
||||
|
||||
// readEnvs reads the configuration.
|
||||
@ -117,9 +115,7 @@ func (envs *environments) buildErrColl() (errColl errcoll.Interface, err error)
|
||||
}
|
||||
|
||||
// geoIP returns an GeoIP database implementation from environment.
|
||||
func (envs *environments) geoIP(
|
||||
c *geoIPConfig,
|
||||
) (g *geoip.File, err error) {
|
||||
func (envs *environments) geoIP(c *geoIPConfig) (g *geoip.File, err error) {
|
||||
log.Debug("using geoip files %q and %q", envs.GeoIPASNPath, envs.GeoIPCountryPath)
|
||||
|
||||
g, err = geoip.NewFile(&geoip.FileConfig{
|
||||
@ -180,18 +176,17 @@ func (envs *environments) buildRuleStat(
|
||||
}
|
||||
|
||||
httpRuleStat := rulestat.NewHTTP(&rulestat.HTTPConfig{
|
||||
ErrColl: errColl,
|
||||
URL: &envs.RuleStatURL.URL,
|
||||
})
|
||||
|
||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
Context: ctxWithDefaultTimeout,
|
||||
Refresher: httpRuleStat,
|
||||
ErrColl: errColl,
|
||||
Name: "rulestat",
|
||||
// TODO(ameshkov): Consider making configurable.
|
||||
Interval: 10 * time.Minute,
|
||||
RefreshOnShutdown: true,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = refr.Start(context.Background())
|
||||
|
@ -16,24 +16,6 @@ func check(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// coalesceError returns the first non-nil error. It is named after function
|
||||
// COALESCE in SQL. If all errors are nil, it returns nil.
|
||||
//
|
||||
// TODO(a.garipov): Consider a similar helper to group errors together to show
|
||||
// as many errors as possible.
|
||||
//
|
||||
// TODO(a.garipov): Think of ways to merge with [aghalg.Coalesce] in AdGuard
|
||||
// Home.
|
||||
func coalesceError(errors ...error) (res error) {
|
||||
for _, err := range errors {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// numberOrDuration is the constraint for integer types along with
|
||||
// timeutil.Duration.
|
||||
type numberOrDuration interface {
|
||||
|
@ -5,9 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
||||
@ -17,10 +15,11 @@ import (
|
||||
"github.com/c2h5oh/datasize"
|
||||
)
|
||||
|
||||
// Filters configuration
|
||||
|
||||
// filtersConfig contains the configuration for the filter lists and filtering
|
||||
// storage to be used.
|
||||
//
|
||||
// TODO(a.garipov): Add the timeout for the blocked-service index refresh. It
|
||||
// is currently hardcoded to 3 minutes.
|
||||
type filtersConfig struct {
|
||||
// RuleListCache is the cache settings for the filtering rule-list.
|
||||
RuleListCache *fltRuleListCache `yaml:"rule_list_cache"`
|
||||
@ -41,10 +40,21 @@ type filtersConfig struct {
|
||||
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
||||
|
||||
// RefreshTimeout is the timeout for the entire filter update operation.
|
||||
// Note that each individual refresh operation also has its own hardcoded
|
||||
// 30s timeout.
|
||||
// Note that filter rule-list index and each filter rule-list update
|
||||
// operations have their own timeouts, see IndexRefreshTimeout and
|
||||
// RuleListRefreshTimeout.
|
||||
RefreshTimeout timeutil.Duration `yaml:"refresh_timeout"`
|
||||
|
||||
// IndexRefreshTimeout is the timeout for the filter rule-list index update
|
||||
// operation. See also RefreshTimeout for the entire filter update
|
||||
// operation.
|
||||
IndexRefreshTimeout timeutil.Duration `yaml:"index_refresh_timeout"`
|
||||
|
||||
// RuleListRefreshTimeout is the timeout for the filter update operation of
|
||||
// each rule-list, which includes safe-search filters. See also
|
||||
// RefreshTimeout for the entire filter update operation.
|
||||
RuleListRefreshTimeout timeutil.Duration `yaml:"rule_list_refresh_timeout"`
|
||||
|
||||
// MaxSize is the maximum size of the downloadable filtering rule-list.
|
||||
MaxSize datasize.ByteSize `yaml:"max_size"`
|
||||
}
|
||||
@ -53,8 +63,6 @@ type filtersConfig struct {
|
||||
// cacheDir must exist. c is assumed to be valid.
|
||||
func (c *filtersConfig) toInternal(
|
||||
errColl errcoll.Interface,
|
||||
resolver agdnet.Resolver,
|
||||
cloner *dnsmsg.Cloner,
|
||||
envs *environments,
|
||||
safeBrowsing *hashprefix.Filter,
|
||||
adultBlocking *hashprefix.Filter,
|
||||
@ -70,8 +78,6 @@ func (c *filtersConfig) toInternal(
|
||||
NewRegDomains: newRegDomains,
|
||||
Now: time.Now,
|
||||
ErrColl: errColl,
|
||||
Resolver: resolver,
|
||||
Cloner: cloner,
|
||||
CacheDir: envs.FilterCachePath,
|
||||
CustomFilterCacheSize: c.CustomFilterCacheSize,
|
||||
SafeSearchCacheSize: c.SafeSearchCacheSize,
|
||||
@ -79,6 +85,8 @@ func (c *filtersConfig) toInternal(
|
||||
SafeSearchCacheTTL: 1 * time.Hour,
|
||||
RuleListCacheSize: c.RuleListCache.Size,
|
||||
RefreshIvl: c.RefreshIvl.Duration,
|
||||
IndexRefreshTimeout: c.IndexRefreshTimeout.Duration,
|
||||
RuleListRefreshTimeout: c.RuleListRefreshTimeout.Duration,
|
||||
UseRuleListCache: c.RuleListCache.Enabled,
|
||||
MaxRuleListSize: c.MaxSize.Bytes(),
|
||||
}
|
||||
@ -97,6 +105,10 @@ func (c *filtersConfig) validate() (err error) {
|
||||
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
||||
case c.RefreshTimeout.Duration <= 0:
|
||||
return newMustBePositiveError("refresh_timeout", c.RefreshTimeout)
|
||||
case c.IndexRefreshTimeout.Duration <= 0:
|
||||
return newMustBePositiveError("index_refresh_timeout", c.IndexRefreshTimeout)
|
||||
case c.RuleListRefreshTimeout.Duration <= 0:
|
||||
return newMustBePositiveError("rule_list_refresh_timeout", c.RuleListRefreshTimeout)
|
||||
case c.MaxSize <= 0:
|
||||
return newMustBePositiveError("max_size", c.MaxSize)
|
||||
default:
|
||||
@ -138,7 +150,6 @@ func (c *fltRuleListCache) validate() (err error) {
|
||||
func setupFilterStorage(
|
||||
conf *filter.DefaultStorageConfig,
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
refreshTimeout time.Duration,
|
||||
) (strg *filter.DefaultStorage, err error) {
|
||||
strg, err = filter.NewDefaultStorage(conf)
|
||||
@ -151,11 +162,9 @@ func setupFilterStorage(
|
||||
return context.WithTimeout(context.Background(), refreshTimeout)
|
||||
},
|
||||
Refresher: strg,
|
||||
ErrColl: errColl,
|
||||
Name: "filters",
|
||||
Interval: conf.RefreshIvl,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = refr.Start(context.Background())
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
|
||||
// Filtering Groups Configuration
|
||||
@ -94,7 +94,7 @@ func (g *filteringGroup) validate() (err error) {
|
||||
return errors.Error("no parental")
|
||||
}
|
||||
|
||||
fltIDs := stringutil.NewSet()
|
||||
fltIDs := container.NewMapSet[string]()
|
||||
for i, fltID := range g.RuleLists.IDs {
|
||||
if fltIDs.Has(fltID) {
|
||||
return fmt.Errorf("rule_lists: at index %d: duplicate id %q", i, fltID)
|
||||
@ -160,7 +160,7 @@ func (groups filteringGroups) validate() (err error) {
|
||||
return errors.Error("no filtering_groups")
|
||||
}
|
||||
|
||||
ids := stringutil.NewSet()
|
||||
ids := container.NewMapSet[string]()
|
||||
for i, g := range groups {
|
||||
err = g.validate()
|
||||
if err != nil {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
|
||||
@ -64,12 +65,17 @@ func setupGeoIP(
|
||||
|
||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
Context: ctxWithDefaultTimeout,
|
||||
Refresher: geoIP,
|
||||
ErrColl: errColl,
|
||||
// Do not add errColl to geoip's config, as that would create an import
|
||||
// cycle.
|
||||
Refresher: agdservice.NewRefresherWithErrColl(
|
||||
geoIP,
|
||||
log.Info,
|
||||
errColl,
|
||||
"geoip_refresh",
|
||||
),
|
||||
Name: "geoip",
|
||||
Interval: conf.RefreshIvl.Duration,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = refr.Start(context.Background())
|
||||
|
@ -35,7 +35,7 @@ func (c *interfaceListenersConfig) toInternal(
|
||||
ChannelBufferSize: c.ChannelBufferSize,
|
||||
})
|
||||
|
||||
err = mapsutil.OrderedRangeError(
|
||||
err = mapsutil.SortedRangeError(
|
||||
c.List,
|
||||
func(id bindtodevice.ID, l *interfaceListener) (addErr error) {
|
||||
return errors.Annotate(m.Add(id, l.Interface, l.Port, ctrlConf), "adding listener %q: %w", id)
|
||||
@ -66,7 +66,7 @@ func (c *interfaceListenersConfig) validate() (err error) {
|
||||
// Go on.
|
||||
}
|
||||
|
||||
err = mapsutil.OrderedRangeError(
|
||||
err = mapsutil.SortedRangeError(
|
||||
c.List,
|
||||
func(id bindtodevice.ID, l *interfaceListener) (lsnrErr error) {
|
||||
return errors.Annotate(l.validate(), "interface %q: %w", id)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@ -88,7 +89,7 @@ func (o *rateLimitOptions) validate() (err error) {
|
||||
return errNilConfig
|
||||
}
|
||||
|
||||
return coalesceError(
|
||||
return cmp.Or(
|
||||
validatePositive("rps", o.RPS),
|
||||
validatePositive("subnet_key_len", o.SubnetKeyLen),
|
||||
)
|
||||
@ -120,7 +121,7 @@ func (c *rateLimitConfig) validate() (err error) {
|
||||
return fmt.Errorf("allowlist: %w", errNilConfig)
|
||||
}
|
||||
|
||||
return coalesceError(
|
||||
return cmp.Or(
|
||||
validateProp("connection_limit", c.ConnectionLimit.validate),
|
||||
validateProp("ipv4", c.IPv4.validate),
|
||||
validateProp("ipv6", c.IPv6.validate),
|
||||
@ -144,7 +145,7 @@ func setupRateLimiter(
|
||||
) (rateLimiter *ratelimit.Backoff, connLimiter *connlimiter.Limiter, err error) {
|
||||
allowSubnets := netutil.UnembedPrefixes(conf.Allowlist.List)
|
||||
allowlist := ratelimit.NewDynamicAllowlist(allowSubnets, nil)
|
||||
refresher, err := consul.NewAllowlistRefresher(allowlist, consulAllowlist)
|
||||
refresher, err := consul.NewAllowlistRefresher(allowlist, consulAllowlist, errColl)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("creating allowlist refresher: %w", err)
|
||||
}
|
||||
@ -152,11 +153,9 @@ func setupRateLimiter(
|
||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
Context: ctxWithDefaultTimeout,
|
||||
Refresher: refresher,
|
||||
ErrColl: errColl,
|
||||
Name: "allowlist",
|
||||
Interval: conf.Allowlist.RefreshIvl.Duration,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
@ -37,13 +36,15 @@ type safeBrowsingConfig struct {
|
||||
|
||||
// RefreshIvl defines how often AdGuard DNS refreshes the filter.
|
||||
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
||||
|
||||
// RefreshTimeout is the timeout for the filter update operation.
|
||||
RefreshTimeout timeutil.Duration `yaml:"refresh_timeout"`
|
||||
}
|
||||
|
||||
// toInternal converts c to the safe browsing filter configuration for the
|
||||
// filter storage of the DNS server. c is assumed to be valid.
|
||||
func (c *safeBrowsingConfig) toInternal(
|
||||
errColl errcoll.Interface,
|
||||
resolver agdnet.Resolver,
|
||||
cloner *dnsmsg.Cloner,
|
||||
id agd.FilterListID,
|
||||
url *urlutil.URL,
|
||||
@ -60,11 +61,11 @@ func (c *safeBrowsingConfig) toInternal(
|
||||
Hashes: hashes,
|
||||
URL: netutil.CloneURL(&url.URL),
|
||||
ErrColl: errColl,
|
||||
Resolver: resolver,
|
||||
ID: id,
|
||||
CachePath: filepath.Join(cacheDir, string(id)),
|
||||
ReplacementHost: c.BlockHost,
|
||||
Staleness: c.RefreshIvl.Duration,
|
||||
RefreshTimeout: c.RefreshTimeout.Duration,
|
||||
CacheTTL: c.CacheTTL.Duration,
|
||||
CacheSize: c.CacheSize,
|
||||
MaxSize: maxSize,
|
||||
@ -85,6 +86,8 @@ func (c *safeBrowsingConfig) validate() (err error) {
|
||||
return newMustBePositiveError("cache_ttl", c.CacheTTL)
|
||||
case c.RefreshIvl.Duration <= 0:
|
||||
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
||||
case c.RefreshTimeout.Duration <= 0:
|
||||
return newMustBePositiveError("refresh_timeout", c.RefreshTimeout)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -94,7 +97,6 @@ func (c *safeBrowsingConfig) validate() (err error) {
|
||||
// starts and registers its refresher in the signal handler.
|
||||
func setupHashPrefixFilter(
|
||||
conf *safeBrowsingConfig,
|
||||
resolver *agdnet.CachingResolver,
|
||||
cloner *dnsmsg.Cloner,
|
||||
id agd.FilterListID,
|
||||
url *urlutil.URL,
|
||||
@ -103,7 +105,7 @@ func setupHashPrefixFilter(
|
||||
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)
|
||||
fltConf, err := conf.toInternal(errColl, cloner, id, url, cachePath, maxSize)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("configuring hash prefix filter %s: %w", id, err)
|
||||
}
|
||||
@ -114,13 +116,15 @@ func setupHashPrefixFilter(
|
||||
}
|
||||
|
||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
Context: ctxWithDefaultTimeout,
|
||||
// Note that we also set the same timeout for the http.Client in
|
||||
// [hashprefix.NewFilter].
|
||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||
return context.WithTimeout(context.Background(), fltConf.RefreshTimeout)
|
||||
},
|
||||
Refresher: flt,
|
||||
ErrColl: errColl,
|
||||
Name: string(id),
|
||||
Interval: fltConf.Staleness,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: false,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = refr.Start(context.Background())
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
|
||||
// toInternal returns the configuration of DNS servers for a single server
|
||||
@ -95,7 +95,7 @@ func (srvs servers) validate() (needsTLS bool, err error) {
|
||||
return false, errors.Error("no servers")
|
||||
}
|
||||
|
||||
names := stringutil.NewSet()
|
||||
names := container.NewMapSet[string]()
|
||||
for i, s := range srvs {
|
||||
if s == nil {
|
||||
return false, fmt.Errorf("at index %d: no server", i)
|
||||
@ -323,19 +323,17 @@ func (c *serverBindInterface) validate() (err error) {
|
||||
// Go on.
|
||||
}
|
||||
|
||||
set := map[netip.Prefix]struct{}{}
|
||||
|
||||
set := container.NewMapSet[netip.Prefix]()
|
||||
for i, subnet := range c.Subnets {
|
||||
if !subnet.IsValid() {
|
||||
return fmt.Errorf("bad subnet at index %d", i)
|
||||
}
|
||||
|
||||
_, ok := set[subnet]
|
||||
if ok {
|
||||
if set.Has(subnet) {
|
||||
return fmt.Errorf("duplicate subnet %s at index %d", subnet, i)
|
||||
}
|
||||
|
||||
set[subnet] = struct{}{}
|
||||
set.Add(subnet)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -2,14 +2,12 @@ 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/container"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
|
||||
// serverGroups are the DNS server groups. A valid instance of serverGroups has
|
||||
@ -41,7 +39,6 @@ func (srvGrps serverGroups) toInternal(
|
||||
}
|
||||
|
||||
svcSrvGrps[i] = &agd.ServerGroup{
|
||||
BlockPageRedirect: g.BlockPageRedirect.toInternal(),
|
||||
DDR: g.DDR.toInternal(messages),
|
||||
TLS: tlsConf,
|
||||
Name: agd.ServerGroupName(g.Name),
|
||||
@ -63,7 +60,7 @@ func (srvGrps serverGroups) validate() (err error) {
|
||||
return errors.Error("no server groups")
|
||||
}
|
||||
|
||||
names := stringutil.NewSet()
|
||||
names := container.NewMapSet[string]()
|
||||
for i, g := range srvGrps {
|
||||
err = g.validate()
|
||||
if err != nil {
|
||||
@ -86,9 +83,6 @@ 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 {
|
||||
// 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"`
|
||||
@ -117,11 +111,6 @@ 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)
|
||||
@ -139,255 +128,3 @@ 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"`
|
||||
}
|
||||
|
@ -15,9 +15,10 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
@ -96,7 +97,7 @@ func (c *tlsConfig) validate(needsTLS bool) (err error) {
|
||||
// validateDeviceIDWildcards returns an error if the device ID domain wildcards
|
||||
// are invalid.
|
||||
func validateDeviceIDWildcards(wildcards []string) (err error) {
|
||||
s := stringutil.NewSet()
|
||||
s := container.NewMapSet[string]()
|
||||
for i, w := range wildcards {
|
||||
// TODO(e.burkov): Consider removing this requirement.
|
||||
if !strings.HasPrefix(w, "*.") {
|
||||
@ -185,6 +186,7 @@ func (certs tlsConfigCerts) validate() (err error) {
|
||||
|
||||
// ticketRotator is a refresh worker that rereads and resets TLS session tickets.
|
||||
type ticketRotator struct {
|
||||
errColl errcoll.Interface
|
||||
confs map[*tls.Config][]string
|
||||
}
|
||||
|
||||
@ -192,7 +194,10 @@ type ticketRotator struct {
|
||||
// tickets for the TLS configurations of all servers in grps.
|
||||
//
|
||||
// grps is assumed to be valid.
|
||||
func newTicketRotator(grps []*agd.ServerGroup) (tr *ticketRotator, err error) {
|
||||
func newTicketRotator(
|
||||
errColl errcoll.Interface,
|
||||
grps []*agd.ServerGroup,
|
||||
) (tr *ticketRotator, err error) {
|
||||
confs := map[*tls.Config][]string{}
|
||||
|
||||
for _, g := range grps {
|
||||
@ -209,6 +214,7 @@ func newTicketRotator(grps []*agd.ServerGroup) (tr *ticketRotator, err error) {
|
||||
}
|
||||
|
||||
tr = &ticketRotator{
|
||||
errColl: errColl,
|
||||
confs: confs,
|
||||
}
|
||||
|
||||
@ -231,7 +237,17 @@ const sessTickLen = 32
|
||||
var _ agdservice.Refresher = (*ticketRotator)(nil)
|
||||
|
||||
// Refresh implements the [agdservice.Refresher] interface for *ticketRotator.
|
||||
func (r *ticketRotator) Refresh(_ context.Context) (err error) {
|
||||
func (r *ticketRotator) Refresh(ctx context.Context) (err error) {
|
||||
// TODO(a.garipov): Use slog.
|
||||
log.Debug("tickrot_refresh: started")
|
||||
defer log.Debug("tickrot_refresh: finished")
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
errcoll.Collectf(ctx, r.errColl, "tickrot_refresh: %w", err)
|
||||
}
|
||||
}()
|
||||
|
||||
for conf, files := range r.confs {
|
||||
keys := make([][sessTickLen]byte, 0, len(files))
|
||||
|
||||
@ -304,7 +320,7 @@ func setupTicketRotator(
|
||||
sigHdlr *service.SignalHandler,
|
||||
errColl errcoll.Interface,
|
||||
) (err error) {
|
||||
tickRot, err := newTicketRotator(srvGrps)
|
||||
tickRot, err := newTicketRotator(errColl, srvGrps)
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting up ticket rotator: %w", err)
|
||||
}
|
||||
@ -312,12 +328,10 @@ func setupTicketRotator(
|
||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||
Context: ctxWithDefaultTimeout,
|
||||
Refresher: tickRot,
|
||||
ErrColl: errColl,
|
||||
Name: "tickrot",
|
||||
// TODO(ameshkov): Consider making configurable.
|
||||
Interval: 1 * time.Minute,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: true,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
err = refr.Start(context.Background())
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
@ -13,6 +14,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/prometheus"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
)
|
||||
@ -73,7 +75,7 @@ func (c *upstreamConfig) validate() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
return coalesceError(
|
||||
return cmp.Or(
|
||||
validateProp("fallback", c.Fallback.validate),
|
||||
validateProp("healthcheck", c.Healthcheck.validate),
|
||||
)
|
||||
@ -171,12 +173,15 @@ func newUpstreamHealthcheck(
|
||||
conf.Healthcheck.Timeout.Duration,
|
||||
)
|
||||
},
|
||||
Refresher: handler,
|
||||
ErrColl: errColl,
|
||||
Refresher: agdservice.NewRefresherWithErrColl(
|
||||
handler,
|
||||
log.Debug,
|
||||
errColl,
|
||||
"upstream_healthcheck_refresh",
|
||||
),
|
||||
Name: "upstream healthcheck",
|
||||
Interval: conf.Healthcheck.Interval.Duration,
|
||||
RefreshOnShutdown: false,
|
||||
RoutineLogsAreDebug: true,
|
||||
RandomizeStart: false,
|
||||
})
|
||||
}
|
||||
|
@ -25,12 +25,15 @@ type webConfig struct {
|
||||
// LinkedIP is the optional linked IP web server.
|
||||
LinkedIP *linkedIPServer `yaml:"linked_ip"`
|
||||
|
||||
// SafeBrowsing is the optional safe browsing block page web server.
|
||||
SafeBrowsing *blockPageServer `yaml:"safe_browsing"`
|
||||
|
||||
// AdultBlocking is the optional adult blocking block page web server.
|
||||
AdultBlocking *blockPageServer `yaml:"adult_blocking"`
|
||||
|
||||
// GeneralBlocking is the optional general block-page web server.
|
||||
GeneralBlocking *blockPageServer `yaml:"general_blocking"`
|
||||
|
||||
// SafeBrowsing is the optional safe browsing block page web server.
|
||||
SafeBrowsing *blockPageServer `yaml:"safe_browsing"`
|
||||
|
||||
// RootRedirectURL is the URL to which non-DNS and non-Debug HTTP requests
|
||||
// are redirected. If not set, a 404 page is shown.
|
||||
RootRedirectURL *urlutil.URL `yaml:"root_redirect_url"`
|
||||
@ -86,6 +89,11 @@ func (c *webConfig) toInternal(
|
||||
return nil, fmt.Errorf("converting adult_blocking: %w", err)
|
||||
}
|
||||
|
||||
conf.GeneralBlocking, err = c.GeneralBlocking.toInternal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting general_blocking: %w", err)
|
||||
}
|
||||
|
||||
conf.SafeBrowsing, err = c.SafeBrowsing.toInternal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting safe_browsing: %w", err)
|
||||
@ -146,16 +154,21 @@ func (c *webConfig) validate() (err error) {
|
||||
return fmt.Errorf("linked_ip: %w", err)
|
||||
}
|
||||
|
||||
err = c.SafeBrowsing.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("safe_browsing: %w", err)
|
||||
}
|
||||
|
||||
err = c.AdultBlocking.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("adult_blocking: %w", err)
|
||||
}
|
||||
|
||||
err = c.GeneralBlocking.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("general_blocking: %w", err)
|
||||
}
|
||||
|
||||
err = c.SafeBrowsing.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("safe_browsing: %w", err)
|
||||
}
|
||||
|
||||
err = c.StaticContent.validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("static_content: %w", err)
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
@ -23,12 +24,14 @@ type AllowlistRefresher struct {
|
||||
allowlist *ratelimit.DynamicAllowlist
|
||||
http *agdhttp.Client
|
||||
url *url.URL
|
||||
errColl errcoll.Interface
|
||||
}
|
||||
|
||||
// NewAllowlistRefresher returns a properly initialized *AllowlistRefresher.
|
||||
func NewAllowlistRefresher(
|
||||
allowlist *ratelimit.DynamicAllowlist,
|
||||
consulURL *url.URL,
|
||||
errColl errcoll.Interface,
|
||||
) (l *AllowlistRefresher, err error) {
|
||||
l = &AllowlistRefresher{
|
||||
allowlist: allowlist,
|
||||
@ -37,6 +40,7 @@ func NewAllowlistRefresher(
|
||||
Timeout: 15 * time.Second,
|
||||
}),
|
||||
url: consulURL,
|
||||
errColl: errColl,
|
||||
}
|
||||
|
||||
err = l.Refresh(context.Background())
|
||||
@ -53,6 +57,10 @@ var _ agdservice.Refresher = (*AllowlistRefresher)(nil)
|
||||
// Refresh implements the [agdservice.Refresher] interface for
|
||||
// *AllowlistRefresher.
|
||||
func (l *AllowlistRefresher) Refresh(ctx context.Context) (err error) {
|
||||
// TODO(a.garipov): Use slog.
|
||||
log.Info("allowlist_refresh: started")
|
||||
defer log.Info("allowlist_refresh: finished")
|
||||
|
||||
defer func() {
|
||||
metrics.ConsulAllowlistUpdateTime.SetToCurrentTime()
|
||||
metrics.SetStatusGauge(metrics.ConsulAllowlistUpdateStatus, err)
|
||||
@ -60,7 +68,10 @@ func (l *AllowlistRefresher) Refresh(ctx context.Context) (err error) {
|
||||
|
||||
consulNets, err := l.loadConsul(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading consul: %w", err)
|
||||
errcoll.Collectf(ctx, l.errColl, "allowlist_refresh: %w", err)
|
||||
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("allowlist: loaded %d records from %s", len(consulNets), l.url)
|
||||
|
@ -2,6 +2,7 @@ package consul_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/netip"
|
||||
@ -9,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@ -70,12 +72,18 @@ func TestNewAllowlistRefresher(t *testing.T) {
|
||||
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
||||
pt := testutil.PanicT{}
|
||||
|
||||
_, err := rw.Write([]byte(testCases[i].resp))
|
||||
_, err := io.WriteString(rw, testCases[i].resp)
|
||||
require.NoError(pt, err)
|
||||
}))
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := consul.NewAllowlistRefresher(al, u)
|
||||
errColl := &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, err error) {
|
||||
panic("not implemented")
|
||||
},
|
||||
}
|
||||
|
||||
_, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, ip := range tc.wantAllow {
|
||||
@ -104,10 +112,18 @@ func TestNewAllowlistRefresher(t *testing.T) {
|
||||
}))
|
||||
wantErr := &agdhttp.StatusError{}
|
||||
|
||||
_, err := consul.NewAllowlistRefresher(al, u)
|
||||
var gotCollErr error
|
||||
errColl := &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, err error) {
|
||||
gotCollErr = err
|
||||
},
|
||||
}
|
||||
|
||||
_, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||
require.ErrorAs(t, err, &wantErr)
|
||||
|
||||
assert.Equal(t, wantErr.Got, status)
|
||||
assert.ErrorAs(t, gotCollErr, &wantErr)
|
||||
})
|
||||
}
|
||||
|
||||
@ -116,11 +132,18 @@ func TestAllowlistRefresher_Refresh_deadline(t *testing.T) {
|
||||
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
||||
pt := testutil.PanicT{}
|
||||
|
||||
_, err := rw.Write([]byte(`[]`))
|
||||
_, err := io.WriteString(rw, `[]`)
|
||||
require.NoError(pt, err)
|
||||
}))
|
||||
|
||||
c, err := consul.NewAllowlistRefresher(al, u)
|
||||
var gotCollErr error
|
||||
errColl := &agdtest.ErrorCollector{
|
||||
OnCollect: func(_ context.Context, err error) {
|
||||
gotCollErr = err
|
||||
},
|
||||
}
|
||||
|
||||
c, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@ -128,4 +151,5 @@ func TestAllowlistRefresher_Refresh_deadline(t *testing.T) {
|
||||
|
||||
err = c.Refresh(ctx)
|
||||
assert.ErrorIs(t, err, context.Canceled)
|
||||
assert.ErrorIs(t, gotCollErr, context.Canceled)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -45,11 +44,11 @@ func TestService_Start(t *testing.T) {
|
||||
|
||||
var err error
|
||||
require.NotPanics(t, func() {
|
||||
err = svc.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
err = svc.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||
})
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return svc.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
||||
return svc.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||
})
|
||||
|
||||
client := http.Client{
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -63,7 +64,7 @@ func (b *buffer) all() (records []*record) {
|
||||
defer b.mu.Unlock()
|
||||
|
||||
for key, val := range b.entries {
|
||||
if len(val.answers) == 0 {
|
||||
if val.answers.Len() == 0 {
|
||||
records = append(records, &record{
|
||||
target: key.target,
|
||||
hits: val.hits,
|
||||
@ -73,7 +74,7 @@ func (b *buffer) all() (records []*record) {
|
||||
continue
|
||||
}
|
||||
|
||||
for a := range val.answers {
|
||||
val.answers.Range(func(a recordAnswer) (cont bool) {
|
||||
records = append(records, &record{
|
||||
target: key.target,
|
||||
answer: a.value,
|
||||
@ -81,24 +82,26 @@ func (b *buffer) all() (records []*record) {
|
||||
rrType: a.rrType,
|
||||
rcode: a.rcode,
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
||||
|
||||
// toAnswerSet converts a slice of [dns.RR] to a map that can easier be
|
||||
// toAnswerSet converts a slice of [dns.RR] to a set that can easier be
|
||||
// serialized to a csv.
|
||||
func toAnswerSet(answers []dns.RR, rc dnsmsg.RCode) (answerSet map[recordAnswer]unit) {
|
||||
answerSet = map[recordAnswer]unit{}
|
||||
func toAnswerSet(answers []dns.RR, rc dnsmsg.RCode) (answerSet *container.MapSet[recordAnswer]) {
|
||||
answerSet = container.NewMapSet[recordAnswer]()
|
||||
for _, a := range answers {
|
||||
ansStr := answerString(a)
|
||||
if ansStr != "" {
|
||||
answerSet[recordAnswer{
|
||||
answerSet.Add(recordAnswer{
|
||||
value: ansStr,
|
||||
rrType: a.Header().Rrtype,
|
||||
rcode: rc,
|
||||
}] = unit{}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,12 @@ func (db *Default) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}()
|
||||
|
||||
var rw io.Writer = w
|
||||
// TODO(a.garipov): Consider parsing the quality value.
|
||||
if strings.Contains(r.Header.Get(httphdr.AcceptEncoding), "gzip") {
|
||||
h.Set(httphdr.ContentEncoding, "gzip")
|
||||
|
||||
// TODO(a.garipov): Parse the quality value.
|
||||
//
|
||||
// TODO(a.garipov): Support other compression algorithms.
|
||||
if strings.Contains(r.Header.Get(httphdr.AcceptEncoding), agdhttp.HdrValGzip) {
|
||||
h.Set(httphdr.ContentEncoding, agdhttp.HdrValGzip)
|
||||
gw := gzip.NewWriter(w)
|
||||
defer func() { err = errors.WithDeferred(err, gw.Close()) }()
|
||||
|
||||
|
@ -31,7 +31,7 @@ func TestDefault_ServeHTTP(t *testing.T) {
|
||||
successHdr := http.Header{
|
||||
httphdr.ContentType: []string{agdhttp.HdrValTextCSV},
|
||||
httphdr.Trailer: []string{httphdr.XError},
|
||||
httphdr.ContentEncoding: []string{"gzip"},
|
||||
httphdr.ContentEncoding: []string{agdhttp.HdrValGzip},
|
||||
}
|
||||
|
||||
newMsg := func(rcode int, name string, qtype uint16) (m *dns.Msg) {
|
||||
@ -112,7 +112,7 @@ func TestDefault_ServeHTTP(t *testing.T) {
|
||||
(&url.URL{Scheme: "http", Host: "example.com"}).String(),
|
||||
nil,
|
||||
)
|
||||
r.Header.Add(httphdr.AcceptEncoding, "gzip")
|
||||
r.Header.Add(httphdr.AcceptEncoding, agdhttp.HdrValGzip)
|
||||
|
||||
for _, tc := range testCases {
|
||||
db := dnsdb.New(&dnsdb.DefaultConfig{
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -69,12 +70,9 @@ type recordKey struct {
|
||||
qt dnsmsg.RRType
|
||||
}
|
||||
|
||||
// unit is a convenient alias for struct{}.
|
||||
type unit = struct{}
|
||||
|
||||
// recordValue contains the values for a single record key.
|
||||
type recordValue struct {
|
||||
answers map[recordAnswer]unit
|
||||
answers *container.MapSet[recordAnswer]
|
||||
hits uint64
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,15 @@ type BlockingMode interface {
|
||||
|
||||
// BlockingModeCustomIP makes the [dnsmsg.Constructor] return responses with
|
||||
// custom IP addresses to A and AAAA requests. For all other types of requests,
|
||||
// as well as if one of the addresses isn't set, it returns a response with no
|
||||
// answers (aka NODATA).
|
||||
// as well as in case the address corresponding to IP version is not set, it
|
||||
// returns a response with no answers (aka NODATA).
|
||||
type BlockingModeCustomIP struct {
|
||||
IPv4 netip.Addr
|
||||
IPv6 netip.Addr
|
||||
// IPv4 is a slice of valid IPv4 addresses used in responses to A requests.
|
||||
IPv4 []netip.Addr
|
||||
|
||||
// IPv6 is a slice of valid IPv6 addresses used in responses to AAAA
|
||||
// requests.
|
||||
IPv6 []netip.Addr
|
||||
}
|
||||
|
||||
// isBlockingMode implements the BlockingMode interface for
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
// Cloner is a pool that can clone common parts of DNS messages with fewer
|
||||
// allocations.
|
||||
//
|
||||
// TODO(a.garipov): Use in filtering when cloning a [filter.ResultModified]
|
||||
// message.
|
||||
// TODO(a.garipov): Use in filtering when cloning a
|
||||
// [filter.ResultModifiedResponse] message.
|
||||
//
|
||||
// TODO(a.garipov): Use in [Constructor].
|
||||
type Cloner struct {
|
||||
|
@ -328,7 +328,7 @@ func BenchmarkClone(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
msgSink = dnsmsg.Clone(tc.msg)
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ func BenchmarkCloner_Clone(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for i := range b.N {
|
||||
msgSink = c.Clone(tc.msg)
|
||||
if i < b.N-1 {
|
||||
// Don't dispose of the last one to be sure that we can
|
||||
|
@ -33,6 +33,17 @@ func NewConstructor(cloner *Cloner, bm BlockingMode, respTTL time.Duration) (c *
|
||||
}
|
||||
}
|
||||
|
||||
// Cloner returns the constructor's Cloner.
|
||||
func (c *Constructor) Cloner() (cloner *Cloner) {
|
||||
return c.cloner
|
||||
}
|
||||
|
||||
// FilteredResponseTTL returns the TTL that the constructor uses to build
|
||||
// blocked responses.
|
||||
func (c *Constructor) FilteredResponseTTL() (ttl time.Duration) {
|
||||
return c.fltRespTTL
|
||||
}
|
||||
|
||||
// NewBlockedRespMsg returns a blocked DNS response message based on the
|
||||
// constructor's blocking mode.
|
||||
func (c *Constructor) NewBlockedRespMsg(req *dns.Msg) (msg *dns.Msg, err error) {
|
||||
@ -65,12 +76,12 @@ func (c *Constructor) newBlockedCustomIPRespMsg(
|
||||
) (msg *dns.Msg, err error) {
|
||||
switch qt := req.Question[0].Qtype; qt {
|
||||
case dns.TypeA:
|
||||
if m.IPv4.IsValid() {
|
||||
return c.NewIPRespMsg(req, m.IPv4)
|
||||
if len(m.IPv4) > 0 {
|
||||
return c.NewIPRespMsg(req, m.IPv4...)
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
if m.IPv6.IsValid() {
|
||||
return c.NewIPRespMsg(req, m.IPv6)
|
||||
if len(m.IPv6) > 0 {
|
||||
return c.NewIPRespMsg(req, m.IPv6...)
|
||||
}
|
||||
default:
|
||||
// Go on.
|
||||
@ -202,7 +213,7 @@ func (c *Constructor) AppendDebugExtra(req, resp *dns.Msg, str string) (err erro
|
||||
|
||||
// TODO(a.garipov): Use slices.Chunk in Go 1.23.
|
||||
newStr := make([]string, strNum)
|
||||
for i := 0; i < strNum; i++ {
|
||||
for i := range strNum {
|
||||
start := i * MaxTXTStringLen
|
||||
|
||||
var cutStr string
|
||||
|
@ -2,6 +2,7 @@ package dnsmsg_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -81,26 +82,34 @@ func TestConstructor_NewBlockedRespMsg_customIP(t *testing.T) {
|
||||
wantAAAA bool
|
||||
}{{
|
||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||
IPv4: testIPv4,
|
||||
IPv6: testIPv6,
|
||||
IPv4: []netip.Addr{testIPv4},
|
||||
IPv6: []netip.Addr{testIPv6},
|
||||
}, testFltRespTTL),
|
||||
name: "both",
|
||||
wantA: true,
|
||||
wantAAAA: true,
|
||||
}, {
|
||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||
IPv4: testIPv4,
|
||||
IPv4: []netip.Addr{testIPv4},
|
||||
}, testFltRespTTL),
|
||||
name: "ipv4_only",
|
||||
wantA: true,
|
||||
wantAAAA: false,
|
||||
}, {
|
||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||
IPv6: testIPv6,
|
||||
IPv6: []netip.Addr{testIPv6},
|
||||
}, testFltRespTTL),
|
||||
name: "ipv6_only",
|
||||
wantA: false,
|
||||
wantAAAA: true,
|
||||
}, {
|
||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||
IPv4: []netip.Addr{},
|
||||
IPv6: []netip.Addr{},
|
||||
}, testFltRespTTL),
|
||||
name: "empty",
|
||||
wantA: false,
|
||||
wantAAAA: false,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
2
internal/dnsserver/cache/cache_test.go
vendored
2
internal/dnsserver/cache/cache_test.go
vendored
@ -194,7 +194,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
||||
|
||||
var err error
|
||||
var nrw *dnsserver.NonWriterResponseWriter
|
||||
for i := 0; i < N; i++ {
|
||||
for range N {
|
||||
addr := &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 53}
|
||||
nrw = dnsserver.NewNonWriterResponseWriter(addr, addr)
|
||||
err = withCache.ServeDNS(context.Background(), nrw, tc.req)
|
||||
|
@ -1,9 +1,7 @@
|
||||
package dnsserver_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@ -15,16 +13,3 @@ func TestMain(m *testing.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
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func CreateTestHandler(recordsCount int) (h dnsserver.Handler) {
|
||||
}
|
||||
|
||||
ip := netutil.IPv4Localhost().Prev()
|
||||
for i := 0; i < recordsCount; i++ {
|
||||
for range recordsCount {
|
||||
// Add 1 to make sure that each IP is valid.
|
||||
ip = ip.Next()
|
||||
ans = append(ans, &dns.A{Hdr: hdr, A: ip.AsSlice()})
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/exp/rand"
|
||||
)
|
||||
@ -265,6 +266,10 @@ func (h *Handler) exchange(
|
||||
// upstreams is detected to be up again, requests are redirected back to the
|
||||
// main upstreams.
|
||||
func (h *Handler) Refresh(ctx context.Context) (err error) {
|
||||
// TODO(a.garipov): Use slog.
|
||||
log.Debug("upstream_healthcheck_refresh: started")
|
||||
defer log.Debug("upstream_healthcheck_refresh: finished")
|
||||
|
||||
return h.refresh(ctx, false)
|
||||
}
|
||||
|
||||
|
@ -21,18 +21,6 @@ func TestMain(m *testing.M) {
|
||||
// testTimeout is the timeout for tests.
|
||||
const testTimeout = 1 * time.Second
|
||||
|
||||
// newTimeoutCtx is a test helper that returns a context with a timeout of
|
||||
// [testTimeout] and its cancel function being called in the test cleanup. It
|
||||
// should not be used where cancelation is expected sooner.
|
||||
func newTimeoutCtx(tb testing.TB, parent context.Context) (ctx context.Context) {
|
||||
tb.Helper()
|
||||
|
||||
ctx, cancel := context.WithTimeout(parent, testTimeout)
|
||||
tb.Cleanup(cancel)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func TestHandler_ServeDNS(t *testing.T) {
|
||||
srv, addr := dnsservertest.RunDNSServer(t, dnsservertest.DefaultHandler())
|
||||
|
||||
@ -49,7 +37,7 @@ func TestHandler_ServeDNS(t *testing.T) {
|
||||
rw := dnsserver.NewNonWriterResponseWriter(srv.LocalUDPAddr(), srv.LocalUDPAddr())
|
||||
|
||||
// Check the handler's ServeDNS method
|
||||
err := handler.ServeDNS(newTimeoutCtx(t, context.Background()), rw, req)
|
||||
err := handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := rw.Msg()
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/dnsservertest"
|
||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/forward"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -63,32 +64,30 @@ func TestHandler_Refresh(t *testing.T) {
|
||||
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
||||
rw := dnsserver.NewNonWriterResponseWriter(fallback.LocalUDPAddr(), fallback.LocalUDPAddr())
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
err := handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
||||
err := handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, int64(2), upstreamRequestsCount.Load())
|
||||
|
||||
err = handler.Refresh(newTimeoutCtx(t, ctx))
|
||||
err = handler.Refresh(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||
|
||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
||||
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||
|
||||
// Now, set upstream up.
|
||||
upstreamIsUp.Store(true)
|
||||
|
||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
||||
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||
|
||||
err = handler.Refresh(newTimeoutCtx(t, ctx))
|
||||
err = handler.Refresh(testutil.ContextWithTimeout(t, testTimeout))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(5), upstreamRequestsCount.Load())
|
||||
|
||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
||||
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(6), upstreamRequestsCount.Load())
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func TestUpstreamPlain_Exchange(t *testing.T) {
|
||||
defer log.OnCloserError(u, log.DEBUG)
|
||||
|
||||
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
||||
res, nw, err := u.Exchange(newTimeoutCtx(t, context.Background()), req)
|
||||
res, nw, err := u.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||
@ -95,9 +95,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
||||
})
|
||||
defer log.OnCloserError(uUDP, log.DEBUG)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
res, nw, err := uUDP.Exchange(newTimeoutCtx(t, ctx), req)
|
||||
res, nw, err := uUDP.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||
require.NoError(t, err)
|
||||
dnsservertest.RequireResponse(t, req, res, 0, dns.RcodeSuccess, true)
|
||||
|
||||
@ -110,7 +108,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
||||
})
|
||||
defer log.OnCloserError(uTCP, log.DEBUG)
|
||||
|
||||
res, nw, err = uTCP.Exchange(newTimeoutCtx(t, ctx), req)
|
||||
res, nw, err = uTCP.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||
require.NoError(t, err)
|
||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||
|
||||
@ -124,7 +122,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
||||
})
|
||||
defer log.OnCloserError(uAny, log.DEBUG)
|
||||
|
||||
res, nw, err = uAny.Exchange(newTimeoutCtx(t, ctx), req)
|
||||
res, nw, err = uAny.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||
require.NoError(t, err)
|
||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||
|
||||
@ -165,7 +163,8 @@ func TestUpstreamPlain_Exchange_fallbackFail(t *testing.T) {
|
||||
var resp *dns.Msg
|
||||
var err error
|
||||
go func() {
|
||||
resp, _, err = u.Exchange(newTimeoutCtx(t, context.Background()), req)
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
resp, _, err = u.Exchange(ctx, req)
|
||||
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
||||
}()
|
||||
|
||||
@ -266,7 +265,8 @@ func TestUpstreamPlain_Exchange_fallbackSuccess(t *testing.T) {
|
||||
var actualResp *dns.Msg
|
||||
var err error
|
||||
go func() {
|
||||
actualResp, _, err = u.Exchange(newTimeoutCtx(t, context.Background()), clonedReq)
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
actualResp, _, err = u.Exchange(ctx, clonedReq)
|
||||
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
||||
}()
|
||||
|
||||
|
@ -1,44 +1,45 @@
|
||||
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
||||
|
||||
go 1.21.8
|
||||
go 1.22.4
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/golibs v0.20.1
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
||||
github.com/AdguardTeam/golibs v0.23.2
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||
github.com/ameshkov/dnsstamps v1.0.3
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/panjf2000/ants/v2 v2.9.0
|
||||
github.com/panjf2000/ants/v2 v2.9.1
|
||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||
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-20240213143201-ec583247a57a
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/quic-go/quic-go v0.42.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.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/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.46.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.52.3 // indirect
|
||||
github.com/prometheus/procfs v0.13.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.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/crypto v0.22.0 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.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
|
||||
golang.org/x/tools v0.20.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
@ -1,19 +1,19 @@
|
||||
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/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
|
||||
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
|
||||
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=
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7 h1:aEitLIR8HcxVodZ79mgRcCiC0A0I5kZPBuWGFwwulAw=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7/go.mod h1:qPWhwz6FdSmuK7W4sMyvogrez4MWdtzosdqlr0Rg3ow=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0 h1:pDXDF7eFa6Lw+04C0hoMh8kCAQM8NwUdFEllSP2zNLs=
|
||||
github.com/ameshkov/dnscrypt/v2 v2.3.0/go.mod h1:N5hDwgx2cNb4Ay7AhvOSKst+eUiOZ/vbKRO9qMpQttE=
|
||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||
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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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=
|
||||
@ -22,40 +22,40 @@ 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.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/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/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
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/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/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
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/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw=
|
||||
github.com/panjf2000/ants/v2 v2.9.1/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.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.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/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
||||
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||
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/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
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=
|
||||
@ -65,29 +65,31 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
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=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.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/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
|
||||
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
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/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.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=
|
||||
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.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.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=
|
||||
|
@ -24,7 +24,7 @@ func TestSessionPacketConn(t *testing.T) {
|
||||
|
||||
// Try the test multiple times to reduce flakiness due to UDP failures.
|
||||
var success4, success6 bool
|
||||
for i := 0; i < numTries; i++ {
|
||||
for i := range numTries {
|
||||
var isTimeout4, isTimeout6 bool
|
||||
success4 = t.Run(fmt.Sprintf("ipv4_%d", i), func(t *testing.T) {
|
||||
isTimeout4 = testSessionPacketConn(t, "udp4", "0.0.0.0:0", net.IP{127, 0, 0, 1})
|
||||
|
@ -29,7 +29,7 @@ func TestCacheMetricsListener_integration_cache(t *testing.T) {
|
||||
|
||||
// Pass 10 requests through the middleware. This way we'll increment and
|
||||
// set both hits and misses.
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
||||
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
||||
StartTime: time.Now(),
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
func TestInitSyncMap(t *testing.T) {
|
||||
numCalls := atomic.Uint32{}
|
||||
m := newInitSyncMap[int, int](func(k int) (v int) {
|
||||
m := newInitSyncMap(func(k int) (v int) {
|
||||
numCalls.Add(1)
|
||||
|
||||
return k + 1
|
||||
@ -26,13 +26,13 @@ func TestInitSyncMap(t *testing.T) {
|
||||
|
||||
results := make(chan int, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for range n {
|
||||
go func() {
|
||||
results <- m.get(key)
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for range n {
|
||||
got, _ := testutil.RequireReceive(t, results, 1*time.Second)
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func TestRateLimiterMetricsListener_integration_cache(t *testing.T) {
|
||||
)
|
||||
|
||||
// Pass 10 requests through the middleware.
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := range 10 {
|
||||
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
||||
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
||||
StartTime: time.Now(),
|
||||
@ -73,7 +73,7 @@ func BenchmarkRateLimitMetricsListener(b *testing.B) {
|
||||
b.Run("OnAllowlisted", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnAllowlisted(ctx, req, rw)
|
||||
}
|
||||
})
|
||||
@ -81,7 +81,7 @@ func BenchmarkRateLimitMetricsListener(b *testing.B) {
|
||||
b.Run("OnRateLimited", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnRateLimited(ctx, req, rw)
|
||||
}
|
||||
})
|
||||
|
@ -48,7 +48,7 @@ func TestServerMetricsListener_integration_requestLifetime(t *testing.T) {
|
||||
addr := srv.LocalUDPAddr().String()
|
||||
|
||||
// Pass 10 requests to make the test less flaky.
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
res, _, exchErr := c.Exchange(req, addr)
|
||||
require.NoError(t, exchErr)
|
||||
require.NotNil(t, res)
|
||||
@ -96,7 +96,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
||||
b.Run("OnRequest", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnRequest(ctx, info, rw)
|
||||
}
|
||||
})
|
||||
@ -104,7 +104,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
||||
b.Run("OnInvalidMsg", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnInvalidMsg(ctx)
|
||||
}
|
||||
})
|
||||
@ -112,7 +112,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
||||
b.Run("OnError", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnError(ctx, nil)
|
||||
}
|
||||
})
|
||||
@ -120,7 +120,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
||||
b.Run("OnPanic", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
l.OnPanic(ctx, nil)
|
||||
}
|
||||
})
|
||||
|
@ -12,8 +12,6 @@ import (
|
||||
cache "github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
// Backoff Rate Limiter
|
||||
|
||||
// BackoffConfig is the configuration structure for a backoff rate limiter.
|
||||
type BackoffConfig struct {
|
||||
// Allowlist defines which IP networks are excluded from rate limiting.
|
||||
@ -158,9 +156,8 @@ func validateAddr(addr netip.Addr) (err error) {
|
||||
|
||||
// CountResponses implements the Interface interface for *Backoff.
|
||||
func (l *Backoff) CountResponses(ctx context.Context, resp *dns.Msg, ip netip.Addr) {
|
||||
respLimit := l.respSzEst
|
||||
respSize := resp.Len()
|
||||
for i := 0; i < respSize/respLimit; i++ {
|
||||
estRespNum := resp.Len() / l.respSzEst
|
||||
for range estRespNum {
|
||||
_, _, _ = l.IsRateLimited(ctx, resp, ip)
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func TestRatelimitMiddleware(t *testing.T) {
|
||||
})
|
||||
|
||||
n := 0
|
||||
for i := 0; i < tc.reqsNum; i++ {
|
||||
for range tc.reqsNum {
|
||||
nrw := dnsserver.NewNonWriterResponseWriter(
|
||||
&net.UDPAddr{IP: []byte{1, 2, 3, 4}},
|
||||
tc.remoteAddr,
|
||||
|
@ -61,14 +61,13 @@ func BenchmarkServeDNS(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
_, err = conn.Write(msg)
|
||||
require.NoError(b, err)
|
||||
|
||||
err = readMsg(resBuf, tc.network, conn)
|
||||
require.NoError(b, err)
|
||||
}
|
||||
b.StopTimer()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -130,7 +129,7 @@ func BenchmarkServeTLS(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
_, err = conn.Write(msg)
|
||||
require.NoError(b, err)
|
||||
|
||||
@ -147,7 +146,6 @@ func BenchmarkServeTLS(b *testing.B) {
|
||||
|
||||
require.GreaterOrEqual(b, n, dnsserver.DNSHeaderSize)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
func BenchmarkServeDoH(b *testing.B) {
|
||||
@ -207,7 +205,7 @@ func BenchmarkServeDoH(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
var res *http.Response
|
||||
res, err = client.Do(req)
|
||||
require.NoError(b, err)
|
||||
@ -271,13 +269,12 @@ func BenchmarkServeDNSCrypt(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
var resp *dns.Msg
|
||||
resp, err = client.ExchangeConn(conn, req, ri)
|
||||
require.NoError(b, err)
|
||||
require.True(b, resp.Response)
|
||||
}
|
||||
b.StopTimer()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -312,10 +309,9 @@ func BenchmarkServeQUIC(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for range b.N {
|
||||
resp := requireSendQUICMessage(b, sess, req)
|
||||
require.NotNil(b, resp)
|
||||
require.True(b, resp.Response)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dnsserver
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
@ -108,26 +109,14 @@ 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
|
||||
}
|
||||
if conf.WriteTimeout == 0 {
|
||||
conf.WriteTimeout = DefaultWriteTimeout
|
||||
}
|
||||
if conf.TCPIdleTimeout == 0 {
|
||||
conf.TCPIdleTimeout = DefaultTCPIdleTimeout
|
||||
}
|
||||
conf.ReadTimeout = cmp.Or(conf.ReadTimeout, DefaultReadTimeout)
|
||||
conf.WriteTimeout = cmp.Or(conf.WriteTimeout, DefaultWriteTimeout)
|
||||
conf.TCPIdleTimeout = cmp.Or(conf.TCPIdleTimeout, DefaultTCPIdleTimeout)
|
||||
|
||||
// Use dns.MinMsgSize since 99% of DNS queries fit this size, so this is
|
||||
// a sensible default.
|
||||
if conf.UDPSize == 0 {
|
||||
conf.UDPSize = dns.MinMsgSize
|
||||
}
|
||||
if conf.TCPSize == 0 {
|
||||
conf.TCPSize = dns.MinMsgSize
|
||||
}
|
||||
// Use dns.MinMsgSize since 99% of DNS queries fit this size, so this is a
|
||||
// sensible default.
|
||||
conf.UDPSize = cmp.Or(conf.UDPSize, dns.MinMsgSize)
|
||||
conf.TCPSize = cmp.Or(conf.TCPSize, dns.MinMsgSize)
|
||||
|
||||
if conf.ListenConfig == nil {
|
||||
conf.ListenConfig = netext.DefaultListenConfigWithOOB(nil)
|
||||
|
@ -315,7 +315,7 @@ func TestServerDNS_integration_tcpQueriesPipelining(t *testing.T) {
|
||||
const queriesNum = 100
|
||||
|
||||
sentIDs := make(map[uint16]string, queriesNum)
|
||||
for i := 0; i < queriesNum; i++ {
|
||||
for i := range queriesNum {
|
||||
name := fmt.Sprintf("host%d.org", i)
|
||||
req := dnsservertest.CreateMessage(name, dns.TypeA)
|
||||
req.Id = uint16(i + 1)
|
||||
@ -341,7 +341,7 @@ func TestServerDNS_integration_tcpQueriesPipelining(t *testing.T) {
|
||||
|
||||
// Read the responses and check their IDs.
|
||||
receivedIDs := make(map[uint16]string, queriesNum)
|
||||
for i := 0; i < queriesNum; i++ {
|
||||
for range queriesNum {
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -466,7 +466,6 @@ func TestServerDNS_integration_tcpMsgIgnore(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -51,12 +51,22 @@ func (s *ServerDNS) acceptUDPMsg(ctx context.Context, conn net.PacketConn) (err
|
||||
|
||||
s.wg.Add(1)
|
||||
|
||||
reqCtx, reqCancel := s.requestContext()
|
||||
reqCtx = ContextWithRequestInfo(reqCtx, &RequestInfo{StartTime: time.Now()})
|
||||
// Save the start time here, but create the context inside the goroutine,
|
||||
// since s.reqCtx.New can be slow.
|
||||
//
|
||||
// TODO(a.garipov): The slowness is likely due to constant reallocation of
|
||||
// timers in [context.WithTimeout]. Consider creating an optimized reusable
|
||||
// version.
|
||||
startTime := time.Now()
|
||||
|
||||
return s.workerPool.Submit(func() {
|
||||
reqCtx, reqCancel := s.requestContext()
|
||||
defer reqCancel()
|
||||
|
||||
reqCtx = ContextWithRequestInfo(reqCtx, &RequestInfo{
|
||||
StartTime: startTime,
|
||||
})
|
||||
|
||||
s.serveUDPPacket(reqCtx, (*bufPtr)[:n], conn, sess)
|
||||
s.udpPool.Put(bufPtr)
|
||||
})
|
||||
|
@ -95,6 +95,9 @@ type ServerHTTPS struct {
|
||||
// quicListener is a listener that we use to serve DoH3 requests.
|
||||
quicListener *quic.EarlyListener
|
||||
|
||||
// quicTransport is saved here to close it later.
|
||||
quicTransport *quic.Transport
|
||||
|
||||
conf ConfigHTTPS
|
||||
}
|
||||
|
||||
@ -264,19 +267,31 @@ func (s *ServerHTTPS) shutdown(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
// Finally, shutdown the HTTP/3 server.
|
||||
if s.h3Server != nil {
|
||||
err = s.quicListener.Close()
|
||||
s.shutdownH3()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// shutdownH3 shuts down the HTTP/3 server, if enabled, and logs all errors.
|
||||
func (s *ServerHTTPS) shutdownH3() {
|
||||
if s.h3Server == nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := s.quicListener.Close()
|
||||
if err != nil {
|
||||
log.Debug("[%s]: quic listener shutdown: %v", s.Name(), err)
|
||||
log.Debug("[%s]: quic listener shutdown: %s", s.Name(), err)
|
||||
}
|
||||
|
||||
err = s.quicTransport.Close()
|
||||
if err != nil {
|
||||
log.Debug("[%s]: quic transport shutdown: %s", s.Name(), err)
|
||||
}
|
||||
|
||||
err = s.h3Server.Close()
|
||||
if err != nil {
|
||||
log.Debug("[%s]: http/3 server shutdown: %v", s.Name(), err)
|
||||
log.Debug("[%s]: http/3 server shutdown: %s", s.Name(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serveHTTPS is launched in a worker goroutine and serves HTTP/1.1 and HTTP/2
|
||||
@ -523,16 +538,23 @@ func (s *ServerHTTPS) listenQUIC(ctx context.Context) (err error) {
|
||||
|
||||
conn, err := s.listenConfig.ListenPacket(ctx, "udp", s.addr)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("listening udp for quic: %w", err)
|
||||
}
|
||||
|
||||
qConf := newServerQUICConfig(s.metrics, s.conf.QUICLimitsEnabled, s.conf.MaxStreamsPerPeer)
|
||||
ql, err := quic.ListenEarly(conn, tlsConf, qConf)
|
||||
v := newQUICAddrValidator(quicAddrValidatorCacheSize, s.metrics, quicAddrValidatorCacheTTL)
|
||||
transport := &quic.Transport{
|
||||
Conn: conn,
|
||||
VerifySourceAddress: v.requiresValidation,
|
||||
}
|
||||
|
||||
qConf := newServerQUICConfig(s.conf.QUICLimitsEnabled, s.conf.MaxStreamsPerPeer)
|
||||
ql, err := transport.ListenEarly(tlsConf, qConf)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("listening quic: %w", err)
|
||||
}
|
||||
|
||||
s.udpListener = conn
|
||||
s.quicTransport = transport
|
||||
s.quicListener = ql
|
||||
|
||||
return nil
|
||||
|
@ -104,7 +104,6 @@ func TestServerHTTPS_integration_serveRequests(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user