Compare commits

..

3 Commits

Author SHA1 Message Date
Eugene Burkov
3918789ca7 aghnet: imp permissions logic 2023-02-06 16:11:55 +03:00
Eugene Burkov
da1b53a3b4 Merge branch 'master' into 4728-cap-check 2023-02-06 15:45:10 +03:00
yscialom
b82c67405f Fix #4714: correctly check thread can bind to privileged ports 2022-07-09 17:21:56 +02:00
64 changed files with 1074 additions and 1364 deletions

View File

@@ -1,7 +1,7 @@
'name': 'build' 'name': 'build'
'env': 'env':
'GO_VERSION': '1.19.6' 'GO_VERSION': '1.18.9'
'NODE_VERSION': '14' 'NODE_VERSION': '14'
'on': 'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint' 'name': 'lint'
'env': 'env':
'GO_VERSION': '1.19.6' 'GO_VERSION': '1.18.9'
'on': 'on':
'push': 'push':

View File

@@ -14,20 +14,20 @@ and this project adheres to
<!-- <!--
## [v0.108.0] - TBA ## [v0.108.0] - TBA
## [v0.107.25] - 2023-03-09 (APPROX.) ## [v0.107.24] - 2023-02-22 (APPROX.)
See also the [v0.107.25 GitHub milestone][ms-v0.107.25]. See also the [v0.107.24 GitHub milestone][ms-v0.107.24].
[ms-v0.107.25]: https://github.com/AdguardTeam/AdGuardHome/milestone/61?closed=1 [ms-v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/milestone/60?closed=1
NOTE: Add new changes BELOW THIS COMMENT. NOTE: Add new changes BELOW THIS COMMENT.
--> -->
### Fixed ### Fixed
- Failing service installation via script on FreeBSD ([#5431]). - The icon for League Of Legends on the Blocked services page ([#5433]).
[#5431]: https://github.com/AdguardTeam/AdGuardHome/issues/5431 [#5433]: https://github.com/AdguardTeam/AdGuardHome/issues/5433
<!-- <!--
NOTE: Add new changes ABOVE THIS COMMENT. NOTE: Add new changes ABOVE THIS COMMENT.
@@ -35,98 +35,6 @@ NOTE: Add new changes ABOVE THIS COMMENT.
## [v0.107.24] - 2023-02-15
See also the [v0.107.24 GitHub milestone][ms-v0.107.24].
### Security
- Go version has been updated, both because Go 1.18 has reached end of life an
to prevent the possibility of exploiting the Go vulnerabilities fixed in [Go
1.19.6][go-1.19.6].
### Added
- The ability to disable statistics by using the new `statistics.enabled`
field. Previously it was necessary to set the `statistics_interval` to 0,
losing the previous value ([#1717], [#4299]).
- The ability to exclude domain names from the query log or statistics by using
the new `querylog.ignored` or `statistics.ignored` fields ([#1717], [#4299]).
The UI changes are coming in the upcoming releases.
### Changed
#### Configuration Changes
In this release, the schema version has changed from 14 to 16.
- Property `statistics_interval`, which in schema versions 15 and earlier used
to be a part of the `dns` object, is now a part of the `statistics` object:
```yaml
# BEFORE:
'dns':
# …
'statistics_interval': 1
# AFTER:
'statistics':
# …
'interval': 1
```
To rollback this change, move the property back into the `dns` object and
change the `schema_version` back to `15`.
- The fields `dns.querylog_enabled`, `dns.querylog_file_enabled`,
`dns.querylog_interval`, and `dns.querylog_size_memory` have been moved to the
new `querylog` object.
```yaml
# BEFORE:
'dns':
'querylog_enabled': true
'querylog_file_enabled': true
'querylog_interval': '2160h'
'querylog_size_memory': 1000
# AFTER:
'querylog':
'enabled': true
'file_enabled': true
'interval': '2160h'
'size_memory': 1000
```
To rollback this change, rename and move properties back into the `dns`
object, remove `querylog` object and `querylog.ignored` property, and change
the `schema_version` back to `14`.
### Deprecated
- Go 1.19 support. Future versions will require at least Go 1.20 to build.
### Fixed
- Setting the AD (Authenticated Data) flag on responses that have the DO (DNSSEC
OK) flag set but not the AD flag ([#5479]).
- Client names resolved via reverse DNS not being updated ([#4939]).
- The icon for League Of Legends on the Blocked services page ([#5433]).
### Removed
- Go 1.18 support, as it has reached end of life.
[#1717]: https://github.com/AdguardTeam/AdGuardHome/issues/1717
[#4299]: https://github.com/AdguardTeam/AdGuardHome/issues/4299
[#4939]: https://github.com/AdguardTeam/AdGuardHome/issues/4939
[#5433]: https://github.com/AdguardTeam/AdGuardHome/issues/5433
[#5479]: https://github.com/AdguardTeam/AdGuardHome/issues/5479
[go-1.19.6]: https://groups.google.com/g/golang-announce/c/V0aBFqaFs_E
[ms-v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/milestone/60?closed=1
## [v0.107.23] - 2023-02-01 ## [v0.107.23] - 2023-02-01
See also the [v0.107.23 GitHub milestone][ms-v0.107.23]. See also the [v0.107.23 GitHub milestone][ms-v0.107.23].
@@ -1129,6 +1037,7 @@ In this release, the schema version has changed from 10 to 12.
To rollback this change, convert the property back into days and change the To rollback this change, convert the property back into days and change the
`schema_version` back to `11`. `schema_version` back to `11`.
- Property `rlimit_nofile`, which in schema versions 10 and earlier used to be - Property `rlimit_nofile`, which in schema versions 10 and earlier used to be
on the top level, is now moved to the new `os` object: on the top level, is now moved to the new `os` object:
@@ -1675,12 +1584,11 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
<!-- <!--
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.25...HEAD
[v0.107.25]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.24...v0.107.25
-->
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.24...HEAD [Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.24...HEAD
[v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.23...v0.107.24 [v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.23...v0.107.24
-->
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.23...HEAD
[v0.107.23]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.22...v0.107.23 [v0.107.23]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.22...v0.107.23
[v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.21...v0.107.22 [v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.21...v0.107.22
[v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.20...v0.107.21 [v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.20...v0.107.21

View File

@@ -81,24 +81,12 @@ code.
### <a href="#automated-install-linux-and-mac" id="automated-install-linux-and-mac" name="automated-install-linux-and-mac">Automated install (Unix)</a> ### <a href="#automated-install-linux-and-mac" id="automated-install-linux-and-mac" name="automated-install-linux-and-mac">Automated install (Unix)</a>
To install with `curl` run the following command: Run the following command in your terminal:
```sh ```sh
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
``` ```
To install with `wget` run the following command:
```sh
wget --no-verbose -O - https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
```
To install with `fetch` run the following command:
```sh
fetch -o - https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
```
The script also accepts some options: The script also accepts some options:
* `-c <channel>` to use specified channel; * `-c <channel>` to use specified channel;
@@ -261,7 +249,7 @@ Run `make init` to prepare the development environment.
You will need this to build AdGuard Home: You will need this to build AdGuard Home:
* [Go](https://golang.org/dl/) v1.19 or later; * [Go](https://golang.org/dl/) v1.18 or later;
* [Node.js](https://nodejs.org/en/download/) v10.16.2 or later; * [Node.js](https://nodejs.org/en/download/) v10.16.2 or later;
* [npm](https://www.npmjs.com/) v6.14 or later; * [npm](https://www.npmjs.com/) v6.14 or later;
* [yarn](https://yarnpkg.com/) v1.22.5 or later. * [yarn](https://yarnpkg.com/) v1.22.5 or later.

View File

@@ -7,7 +7,7 @@
# Make sure to sync any changes with the branch overrides below. # Make sure to sync any changes with the branch overrides below.
'variables': 'variables':
'channel': 'edge' 'channel': 'edge'
'dockerGo': 'adguard/golang-ubuntu:6.1' 'dockerGo': 'adguard/golang-ubuntu:5.4'
'stages': 'stages':
- 'Build frontend': - 'Build frontend':
@@ -136,12 +136,8 @@
set -e -f -u -x set -e -f -u -x
COMMIT="${bamboo.repository.revision.number}"
export COMMIT
readonly COMMIT
# Explicitly checkout the revision that we need. # Explicitly checkout the revision that we need.
git checkout "$COMMIT" git checkout "${bamboo.repository.revision.number}"
# Install Qemu, create builder. # Install Qemu, create builder.
docker version -f '{{ .Server.Experimental }}' docker version -f '{{ .Server.Experimental }}'
@@ -161,13 +157,12 @@
docker info docker info
# Prepare and push the build. # Prepare and push the build.
env\ make\
CHANNEL="${bamboo.channel}"\ CHANNEL="${bamboo.channel}"\
DIST_DIR='dist'\
DOCKER_IMAGE_NAME='adguard/adguardhome'\ DOCKER_IMAGE_NAME='adguard/adguardhome'\
DOCKER_OUTPUT="type=image,name=adguard/adguardhome,push=true"\ DOCKER_OUTPUT="type=image,name=adguard/adguardhome,push=true"\
VERBOSE='1'\ VERBOSE='1'\
sh ./scripts/make/build-docker.sh build-docker
'environment': 'environment':
DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_CLI_EXPERIMENTAL=enabled
'final-tasks': 'final-tasks':
@@ -228,7 +223,6 @@
channel="${bamboo.channel}" channel="${bamboo.channel}"
readonly channel readonly channel
case "$channel" case "$channel"
in in
('release') ('release')
@@ -275,10 +269,8 @@
set -e -f -u -x set -e -f -u -x
channel="${bamboo.channel}" export CHANNEL="${bamboo.channel}"
readonly channel if [ "$CHANNEL" != 'release' ] && [ "${CHANNEL}" != 'beta' ]
if [ "$channel" != 'release' ] && [ "${channel}" != 'beta' ]
then then
echo "don't publish to GitHub Releases for this channel" echo "don't publish to GitHub Releases for this channel"
@@ -331,7 +323,7 @@
# need to build a few of these. # need to build a few of these.
'variables': 'variables':
'channel': 'beta' 'channel': 'beta'
'dockerGo': 'adguard/golang-ubuntu:6.1' 'dockerGo': 'adguard/golang-ubuntu:5.4'
# release-vX.Y.Z branches are the branches from which the actual final release # release-vX.Y.Z branches are the branches from which the actual final release
# is built. # is built.
- '^release-v[0-9]+\.[0-9]+\.[0-9]+': - '^release-v[0-9]+\.[0-9]+\.[0-9]+':
@@ -346,4 +338,4 @@
# are the ones that actually get released. # are the ones that actually get released.
'variables': 'variables':
'channel': 'release' 'channel': 'release'
'dockerGo': 'adguard/golang-ubuntu:6.1' 'dockerGo': 'adguard/golang-ubuntu:5.4'

View File

@@ -5,7 +5,7 @@
'key': 'AHBRTSPECS' 'key': 'AHBRTSPECS'
'name': 'AdGuard Home - Build and run tests' 'name': 'AdGuard Home - Build and run tests'
'variables': 'variables':
'dockerGo': 'adguard/golang-ubuntu:6.1' 'dockerGo': 'adguard/golang-ubuntu:5.4'
'stages': 'stages':
- 'Tests': - 'Tests':

View File

@@ -261,7 +261,7 @@
"query_log_configuration": "Налада часопіса", "query_log_configuration": "Налада часопіса",
"query_log_disabled": "Часопіс запытаў выключаны, яго можна ўключыць у <0>наладах</0>", "query_log_disabled": "Часопіс запытаў выключаны, яго можна ўключыць у <0>наладах</0>",
"query_log_strict_search": "Ужывайце падвойныя двукоссі для строгага пошуку", "query_log_strict_search": "Ужывайце падвойныя двукоссі для строгага пошуку",
"query_log_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання запытаў? Пры памяншэнні інтэрвалу, некаторыя даныя могуць быць страчаны", "query_log_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання запытаў? Пры скарачэнні інтэрвалу дадзеныя могуць быць згублены",
"anonymize_client_ip": "Ананімізацыя IP-адрасы кліента", "anonymize_client_ip": "Ананімізацыя IP-адрасы кліента",
"anonymize_client_ip_desc": "Не захоўвайце поўныя IP-адрасы гэтых удзельнікаў у часопісах або статыстыцы", "anonymize_client_ip_desc": "Не захоўвайце поўныя IP-адрасы гэтых удзельнікаў у часопісах або статыстыцы",
"dns_config": "Налады DNS-сервера", "dns_config": "Налады DNS-сервера",
@@ -356,7 +356,7 @@
"install_devices_android_list_5": "Зараз можна змяніць палі «DNS 1» і «DNS 2». Увядзіце ў іх адрасы AdGuard Home.", "install_devices_android_list_5": "Зараз можна змяніць палі «DNS 1» і «DNS 2». Увядзіце ў іх адрасы AdGuard Home.",
"install_devices_ios_list_1": "Увайдзіце ў меню налад прылады.", "install_devices_ios_list_1": "Увайдзіце ў меню налад прылады.",
"install_devices_ios_list_2": "Абярыце пункт «Wi-Fi» (для мабільных сетак ручная наладка DNS немагчыма).", "install_devices_ios_list_2": "Абярыце пункт «Wi-Fi» (для мабільных сетак ручная наладка DNS немагчыма).",
"install_devices_ios_list_3": "Націсніце на назву актыўнай у дадзены момант сеткі.", "install_devices_ios_list_3": "Націсніце на назву сетцы, да якой прылада падлучана ў дадзены момант.",
"install_devices_ios_list_4": "У поле «DNS» увядзіце ўвядзіце адрасы AdGuard Home.", "install_devices_ios_list_4": "У поле «DNS» увядзіце ўвядзіце адрасы AdGuard Home.",
"get_started": "Паехалі", "get_started": "Паехалі",
"next": "Далей", "next": "Далей",
@@ -517,10 +517,10 @@
"filter_updated": "Спіс паспяхова абноўлены", "filter_updated": "Спіс паспяхова абноўлены",
"statistics_configuration": "Канфігурацыя статыстыкі", "statistics_configuration": "Канфігурацыя статыстыкі",
"statistics_retention": "Захаванне статыстыкі", "statistics_retention": "Захаванне статыстыкі",
"statistics_retention_desc": "Калі вы паменшыце значэнне інтэрвалу, некаторыя даныя могуць быць страчаны", "statistics_retention_desc": "Калі вы зменшыце значэнне інтэрвалу, некаторыя дадзеныя могуць быць згублены",
"statistics_clear": "Ачысціць статыстыку", "statistics_clear": "Ачысціць статыстыку",
"statistics_clear_confirm": "Вы ўпэўнены, што хочаце ачысціць статыстыку?", "statistics_clear_confirm": "Вы ўпэўнены, што хочаце ачысціць статыстыку?",
"statistics_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання статыстыкі? Пры памяншэнні інтэрвалу, некаторыя даныя могуць быць страчаны", "statistics_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання статыстыкі? Пры скарачэнні інтэрвалу дадзеныя могуць быць згублены",
"statistics_cleared": "Статыстыка паспяхова вычышчана", "statistics_cleared": "Статыстыка паспяхова вычышчана",
"statistics_enable": "Уключыць статыстыку", "statistics_enable": "Уключыць статыстыку",
"interval_hours": "{{count}} гадзіна", "interval_hours": "{{count}} гадзіна",
@@ -598,7 +598,7 @@
"show_blocked_responses": "Заблакавана", "show_blocked_responses": "Заблакавана",
"show_whitelisted_responses": "Белы спіс", "show_whitelisted_responses": "Белы спіс",
"show_processed_responses": "Апрацавана", "show_processed_responses": "Апрацавана",
"blocked_safebrowsing": "Заблакіравана згодна з базай даных Safe Browsing", "blocked_safebrowsing": "Заблакавана згодна базе дадзеных Safe Browsing",
"blocked_adult_websites": "Заблакавана Бацькоўскім кантролем", "blocked_adult_websites": "Заблакавана Бацькоўскім кантролем",
"blocked_threats": "Заблакавана пагроз", "blocked_threats": "Заблакавана пагроз",
"allowed": "Дазволены", "allowed": "Дазволены",
@@ -639,7 +639,7 @@
"safe_browsing": "Бяспечны інтэрнэт", "safe_browsing": "Бяспечны інтэрнэт",
"served_from_cache": "{{value}} <i>(атрымана з кэша)</i>", "served_from_cache": "{{value}} <i>(атрымана з кэша)</i>",
"form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў", "form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў",
"anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яе ў <1>Агульных наладах</1>.", "anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яго ў <1>Агульных наладах</1> .",
"confirm_dns_cache_clear": "Вы ўпэўнены, што хочаце ачысціць кэш DNS?", "confirm_dns_cache_clear": "Вы ўпэўнены, што хочаце ачысціць кэш DNS?",
"cache_cleared": "Кэш DNS паспяхова ачышчаны", "cache_cleared": "Кэш DNS паспяхова ачышчаны",
"clear_cache": "Ачысціць кэш" "clear_cache": "Ачысціць кэш"

View File

@@ -454,7 +454,7 @@
"updates_checked": "La nueva versión de AdGuard Home está disponible", "updates_checked": "La nueva versión de AdGuard Home está disponible",
"updates_version_equal": "AdGuard Home está actualizado", "updates_version_equal": "AdGuard Home está actualizado",
"check_updates_now": "Buscar actualizaciones ahora", "check_updates_now": "Buscar actualizaciones ahora",
"version_request_error": "Error buscar la actualización. Comprueba tu conexión a Internet.", "version_request_error": "La búsqueda de actualizaciones falló. Por favor revisa tu conexión a Internet.",
"dns_privacy": "DNS cifrado", "dns_privacy": "DNS cifrado",
"setup_dns_privacy_1": "<0>DNS mediante TLS:</0> Utiliza la cadena <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS mediante TLS:</0> Utiliza la cadena <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS mediante HTTPS:</0> Utiliza la cadena <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS mediante HTTPS:</0> Utiliza la cadena <1>{{address}}</1>.",
@@ -640,7 +640,7 @@
"served_from_cache": "{{value}} <i>(servido desde la caché)</i>", "served_from_cache": "{{value}} <i>(servido desde la caché)</i>",
"form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres", "form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres",
"anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>.", "anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>.",
"confirm_dns_cache_clear": "¿Estás seguro de que deseas borrar la caché DNS?", "confirm_dns_cache_clear": "¿Estás seguro de que deseas borrar la caché de DNS?",
"cache_cleared": "Caché DNS borrado correctamente", "cache_cleared": "Caché DNS borrado con éxito",
"clear_cache": "Borrar caché" "clear_cache": "Borrar caché"
} }

View File

@@ -24,7 +24,7 @@
"unavailable_dhcp": "DHCP ei ole käytettävissä", "unavailable_dhcp": "DHCP ei ole käytettävissä",
"unavailable_dhcp_desc": "AdGuard Home ei voi suorittaa DHCP-palvelinta käyttöjärjestelmässäsi", "unavailable_dhcp_desc": "AdGuard Home ei voi suorittaa DHCP-palvelinta käyttöjärjestelmässäsi",
"dhcp_title": "DHCP-palvelin (kokeellinen!)", "dhcp_title": "DHCP-palvelin (kokeellinen!)",
"dhcp_description": "Jollei reitittimesi tarjoa DHCP-asetuksia, voit käyttää AdGuard Homen omaa sisäänrakennettua DHCP-palvelinta.", "dhcp_description": "Jos reitittimessäsi ei ole DHCP-asetuksia, voit käyttää AdGuard Homen omaa sisäänrakennettua DHCP-palvelinta.",
"dhcp_enable": "Ota DHCP-palvelin käyttöön", "dhcp_enable": "Ota DHCP-palvelin käyttöön",
"dhcp_disable": "Poista DHCP-palvelin käytöstä", "dhcp_disable": "Poista DHCP-palvelin käytöstä",
"dhcp_not_found": "On turvallista ottaa sisäänrakennettu DHCP-palvelin käyttöön, koska AdGuard Home ei havainnut verkossa muita aktiivisia DHCP-palvelimia. Suosittelemme, että varmistat tämän vielä itse, koska automaattinen tunnistus ei ole 100% varma.", "dhcp_not_found": "On turvallista ottaa sisäänrakennettu DHCP-palvelin käyttöön, koska AdGuard Home ei havainnut verkossa muita aktiivisia DHCP-palvelimia. Suosittelemme, että varmistat tämän vielä itse, koska automaattinen tunnistus ei ole 100% varma.",

View File

@@ -16,7 +16,7 @@
"resolve_clients_title": "启用客户端的 IP 地址的反向解析", "resolve_clients_title": "启用客户端的 IP 地址的反向解析",
"resolve_clients_desc": "通过发送 PTR 查询到对应的解析器 (本地客户端的私人 DNS 服务器,公共 IP 客户端的上游服务器) 将 IP 地址反向解析成其客户端主机名。", "resolve_clients_desc": "通过发送 PTR 查询到对应的解析器 (本地客户端的私人 DNS 服务器,公共 IP 客户端的上游服务器) 将 IP 地址反向解析成其客户端主机名。",
"use_private_ptr_resolvers_title": "使用私人反向 DNS 解析器", "use_private_ptr_resolvers_title": "使用私人反向 DNS 解析器",
"use_private_ptr_resolvers_desc": "使用这些上游服务器对本地服务的地址执行反向 DNS 查找。 如果禁用,则 AdGuard Home 会以 NXDOMAIN 响应所有此类 PTR 请求,从 DHCP、/etc/hosts 等获知的客户端除外。", "use_private_ptr_resolvers_desc": "使用这些上游服务器对本地服务的地址执行反向 DNS 查找。 如果禁用,则 AdGuard Home会以 NXDOMAIN 响应所有此类PTR请求从 DHCP、/ etc / hosts 等获知的客户端除外。",
"check_dhcp_servers": "检查 DHCP 服务器", "check_dhcp_servers": "检查 DHCP 服务器",
"save_config": "保存配置", "save_config": "保存配置",
"enabled_dhcp": "DHCP 服务器已启用", "enabled_dhcp": "DHCP 服务器已启用",
@@ -128,7 +128,7 @@
"number_of_dns_query_days": "过去 {{count}} 天内处理的 DNS 查询总数", "number_of_dns_query_days": "过去 {{count}} 天内处理的 DNS 查询总数",
"number_of_dns_query_days_plural": "在过去的 {{count}} 天内处理了多少个 DNS 查询", "number_of_dns_query_days_plural": "在过去的 {{count}} 天内处理了多少个 DNS 查询",
"number_of_dns_query_24_hours": "过去 24 小时内处理的 DNS 请求总数", "number_of_dns_query_24_hours": "过去 24 小时内处理的 DNS 请求总数",
"number_of_dns_query_blocked_24_hours": "被广告过滤器和 Hosts 黑名单阻止的 DNS 请求总数", "number_of_dns_query_blocked_24_hours": "被广告过滤器和 Hosts 拦截清单阻止的 DNS 请求总数",
"number_of_dns_query_blocked_24_hours_by_sec": "被 AdGuard 安全浏览模块阻止的 DNS 请求总数", "number_of_dns_query_blocked_24_hours_by_sec": "被 AdGuard 安全浏览模块阻止的 DNS 请求总数",
"number_of_dns_query_blocked_24_hours_adult": "被阻止的成人网站总数", "number_of_dns_query_blocked_24_hours_adult": "被阻止的成人网站总数",
"enforced_save_search": "强制安全搜索", "enforced_save_search": "强制安全搜索",
@@ -146,10 +146,10 @@
"no_servers_specified": "未找到指定的服务器", "no_servers_specified": "未找到指定的服务器",
"general_settings": "常规设置", "general_settings": "常规设置",
"dns_settings": "DNS 设置", "dns_settings": "DNS 设置",
"dns_blocklists": "DNS 黑名单", "dns_blocklists": "DNS 拦截列表",
"dns_allowlists": "DNS 白名单", "dns_allowlists": "DNS 允许列表",
"dns_blocklists_desc": "AdGuard Home将阻止匹配DNS拦截清单的域名", "dns_blocklists_desc": "AdGuard Home将阻止匹配DNS拦截清单的域名",
"dns_allowlists_desc": "来自 DNS 白名单的域将被允许,即使它们位于任意黑名单中也是如此", "dns_allowlists_desc": "来自DNS允许列表的域将被允许,即使它们位于任意阻止列表中也是如此",
"custom_filtering_rules": "自定义过滤规则", "custom_filtering_rules": "自定义过滤规则",
"encryption_settings": "加密设置", "encryption_settings": "加密设置",
"dhcp_settings": "DHCP 设置", "dhcp_settings": "DHCP 设置",
@@ -178,22 +178,22 @@
"delete_table_action": "删除", "delete_table_action": "删除",
"elapsed": "耗时", "elapsed": "耗时",
"filters_and_hosts_hint": "AdGuard Home 可以解析基础的 adblock 规则和 Hosts 语法。", "filters_and_hosts_hint": "AdGuard Home 可以解析基础的 adblock 规则和 Hosts 语法。",
"no_blocklist_added": "未添加黑名单", "no_blocklist_added": "未添加阻止列表",
"no_whitelist_added": "未添加白名单", "no_whitelist_added": "未添加允许列表",
"add_blocklist": "添加黑名单", "add_blocklist": "添加阻止列表",
"add_allowlist": "添加白名单", "add_allowlist": "添加允许列表",
"cancel_btn": "取消", "cancel_btn": "取消",
"enter_name_hint": "输入名称", "enter_name_hint": "输入名称",
"enter_url_or_path_hint": "请输入URL或列表的绝对路径", "enter_url_or_path_hint": "请输入URL或列表的绝对路径",
"check_updates_btn": "检查更新", "check_updates_btn": "检查更新",
"new_blocklist": "新封锁清单", "new_blocklist": "新封锁清单",
"new_allowlist": "新增白名单", "new_allowlist": "新的允许清单",
"edit_blocklist": "编辑黑名单", "edit_blocklist": "编辑阻止列表",
"edit_allowlist": "编辑白名单", "edit_allowlist": "编辑允许列表",
"choose_blocklist": "选择黑名单", "choose_blocklist": "选择拦截列表",
"choose_allowlist": "选择白名单", "choose_allowlist": "选择允许列表",
"enter_valid_blocklist": "输入有效的黑名单 URL", "enter_valid_blocklist": "输入有效的阻止列表URL",
"enter_valid_allowlist": "输入有效的白名单 URL", "enter_valid_allowlist": "输入有效的允许列表URL",
"form_error_url_format": "无效的 URL 格式", "form_error_url_format": "无效的 URL 格式",
"form_error_url_or_path_format": "无效的 URL 或列表的绝对路径", "form_error_url_or_path_format": "无效的 URL 或列表的绝对路径",
"custom_filter_rules": "自定义过滤器规则", "custom_filter_rules": "自定义过滤器规则",
@@ -269,9 +269,9 @@
"dns_cache_config_desc": "您可以在此处配置 DNS 缓存", "dns_cache_config_desc": "您可以在此处配置 DNS 缓存",
"blocking_mode": "拦截模式", "blocking_mode": "拦截模式",
"default": "默认", "default": "默认",
"nxdomain": "NXDOMAIN", "nxdomain": "无效域名",
"refused": "REFUSED", "refused": "REFUSED",
"null_ip": " IP", "null_ip": "无效 IP",
"custom_ip": "自定义 IP", "custom_ip": "自定义 IP",
"blocking_ipv4": "拦截 IPv4", "blocking_ipv4": "拦截 IPv4",
"blocking_ipv6": "拦截 IPv6", "blocking_ipv6": "拦截 IPv6",
@@ -296,7 +296,7 @@
"blocking_mode_default": "默认:被 Adblock 规则拦截时反应为零 IP 地址A记录0.0.0.0AAAA记录::);被/etc/hosts 规则拦截时反应为规则中指定 IP 地址", "blocking_mode_default": "默认:被 Adblock 规则拦截时反应为零 IP 地址A记录0.0.0.0AAAA记录::);被/etc/hosts 规则拦截时反应为规则中指定 IP 地址",
"blocking_mode_refused": "REFUSED以 REFUSED 码响应请求", "blocking_mode_refused": "REFUSED以 REFUSED 码响应请求",
"blocking_mode_nxdomain": "NXDOMAIN以NXDOMAIN码响应", "blocking_mode_nxdomain": "NXDOMAIN以NXDOMAIN码响应",
"blocking_mode_null_ip": "空 IP以零 IP 地址响应A 记录 0.0.0.0AAAA 记录 ::", "blocking_mode_null_ip": "空IP以零IP地址响应(A记录 0.0.0.0AAAA记录 ::)",
"blocking_mode_custom_ip": "自定IP以手动设置的IP地址响应", "blocking_mode_custom_ip": "自定IP以手动设置的IP地址响应",
"theme_auto": "自动", "theme_auto": "自动",
"theme_light": "浅色主题", "theme_light": "浅色主题",
@@ -605,7 +605,7 @@
"filtered": "已过滤", "filtered": "已过滤",
"rewritten": "重写项", "rewritten": "重写项",
"safe_search": "安全搜索", "safe_search": "安全搜索",
"blocklist": "黑名单", "blocklist": "拦截列表",
"milliseconds_abbreviation": "毫秒", "milliseconds_abbreviation": "毫秒",
"cache_size": "缓存大小", "cache_size": "缓存大小",
"cache_size_desc": "DNS 缓存大小(单位:字节)。要关闭缓存,请留空。", "cache_size_desc": "DNS 缓存大小(单位:字节)。要关闭缓存,请留空。",
@@ -626,7 +626,7 @@
"filter_category_general_desc": "在大多数设备上阻止跟踪和广告的列表", "filter_category_general_desc": "在大多数设备上阻止跟踪和广告的列表",
"filter_category_security_desc": "专用于拦截恶意软件、钓鱼或欺诈域名的列表", "filter_category_security_desc": "专用于拦截恶意软件、钓鱼或欺诈域名的列表",
"filter_category_regional_desc": "专注于区域广告和跟踪服务器的列表", "filter_category_regional_desc": "专注于区域广告和跟踪服务器的列表",
"filter_category_other_desc": "其他黑名单", "filter_category_other_desc": "其他阻止列表",
"setup_config_to_enable_dhcp_server": "设置配置以启用 DHCP 服务器", "setup_config_to_enable_dhcp_server": "设置配置以启用 DHCP 服务器",
"original_response": "原始响应", "original_response": "原始响应",
"click_to_view_queries": "点击查看查询", "click_to_view_queries": "点击查看查询",

View File

@@ -53,7 +53,7 @@ export const STATUS_COLORS = {
export const REPOSITORY = { export const REPOSITORY = {
URL: 'https://github.com/AdguardTeam/AdGuardHome', URL: 'https://github.com/AdguardTeam/AdGuardHome',
TRACKERS_DB: TRACKERS_DB:
'https://github.com/AdguardTeam/AdGuardHome/tree/master/client/src/helpers/trackers/trackers.json', 'https://github.com/AdguardTeam/AdGuardHome/tree/master/client/src/helpers/trackers/adguard.json',
ISSUES: 'https://github.com/AdguardTeam/AdGuardHome/issues/new/choose', ISSUES: 'https://github.com/AdguardTeam/AdGuardHome/issues/new/choose',
}; };

View File

@@ -160,6 +160,12 @@ export default {
"homepage": "https://github.com/DandelionSprout/adfilt", "homepage": "https://github.com/DandelionSprout/adfilt",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_6.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_6.txt"
}, },
"energized_spark": {
"name": "Energized Spark",
"categoryId": "general",
"homepage": "https://energized.pro/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_28.txt"
},
"hagezi_personal": { "hagezi_personal": {
"name": "HaGeZi Personal Black \u0026 White", "name": "HaGeZi Personal Black \u0026 White",
"categoryId": "general", "categoryId": "general",

View File

@@ -0,0 +1,175 @@
{
"timeUpdated": "2021-12-15",
"categories": {
"0": "audio_video_player",
"1": "comments",
"2": "customer_interaction",
"3": "pornvertising",
"4": "advertising",
"5": "essential",
"6": "site_analytics",
"7": "social_media",
"8": "misc",
"9": "cdn",
"10": "hosting",
"11": "unknown",
"12": "extensions",
"13": "email",
"14": "consent",
"15": "telemetry",
"101": "mobile_analytics"
},
"trackers": {
"akamai_technologies": {
"name": "Akamai Technologies",
"categoryId": 9,
"url": "https://www.akamai.com/",
"companyId": "akamai"
},
"apple": {
"name": "Apple",
"categoryId": 8,
"url": "https://www.apple.com/",
"companyId": "apple"
},
"apple_ads": {
"name": "Apple Search Ads",
"categoryId": 4,
"url": "https://searchads.apple.com/",
"companyId": "apple"
},
"facebook_audience": {
"name": "Facebook Audience Network",
"categoryId": 4,
"url": "https://www.facebook.com/business/products/audience-network",
"companyId": "facebook"
},
"crashlytics": {
"name": "Crashlytics",
"categoryId": 101,
"url": "https://crashlytics.com/",
"companyId": null
},
"flurry": {
"name": "Flurry",
"categoryId": 101,
"url": "http://www.flurry.com/",
"companyId": "verizon"
},
"hockeyapp": {
"name": "HockeyApp",
"categoryId": 101,
"url": "https://hockeyapp.net/",
"companyId": null
},
"firebase": {
"name": "Firebase",
"categoryId": 101,
"url": "https://firebase.google.com/",
"companyId": "google"
},
"appsflyer": {
"name": "AppsFlyer",
"categoryId": 101,
"url": "https://www.appsflyer.com/",
"companyId": "appsflyer"
},
"yandex_appmetrica": {
"name": "Yandex AppMetrica",
"categoryId": 101,
"url": "https://appmetrica.yandex.com/",
"companyId": "yandex"
},
"adjust": {
"name": "Adjust",
"categoryId": 101,
"url": "https://www.adjust.com/",
"companyId": "adjust"
},
"branch": {
"name": "Branch.io",
"categoryId": 101,
"url": "https://branch.io/",
"companyId": "branch_metrics_inc"
},
"markmonitor": {
"name": "MarkMonitor",
"categoryId": 4,
"url": "https://www.markmonitor.com/",
"companyId": "markmonitor"
},
"appcenter": {
"name": "Microsoft App Center",
"categoryId": 5,
"url": "https://appcenter.ms/",
"companyId": null
},
"unity_ads": {
"name": "Unity Ads",
"categoryId": 4,
"url": "https://unity.com/solutions/mobile-business/monetize-your-game",
"companyId": null
},
"azure": {
"name": "Microsoft Azure",
"categoryId": 10,
"url": "https://azure.microsoft.com/",
"companyId": "microsoft"
},
"button": {
"name": "Button",
"categoryId": 4,
"url": "https://www.usebutton.com/",
"companyId": null
},
"netflix": {
"name": "Netflix",
"categoryId": 8,
"url": "https://www.netflix.com/",
"companyId": null
},
"mail.ru_banner": {
"name": "Mail.Ru Banner Network",
"categoryId": 4,
"url": "http://mail.ru/",
"companyId": "vk"
},
"mail.ru_counter": {
"name": "Mail.Ru Counter",
"categoryId": 2,
"url": "http://mail.ru/",
"companyId": "vk"
},
"mail.ru_group": {
"name": "Mail.Ru Group",
"categoryId": 7,
"url": "http://mail.ru/",
"companyId": "vk"
}
},
"trackerDomains": {
"akadns.net": "akamai_technologies",
"akamaiedge.net": "akamai_technologies",
"apple.com": "apple",
"apple.news": "apple",
"apple-dns.net": "apple",
"aaplimg.com": "apple",
"icloud.com": "apple",
"mzstatic.com": "apple",
"iadsdk.apple.com": "apple_ads",
"graph.facebook.com": "facebook_audience",
"crashlytics.com": "crashlytics",
"flurry.com": "flurry",
"hockeyapp.net": "hockeyapp",
"app-measurement.com": "firebase",
"appsflyer.com": "appsflyer",
"appmetrica.yandex.com": "yandex_appmetrica",
"adjust.com": "adjust",
"mobileapptracking.com": "branch",
"edgecastcdn.net": "markmonitor",
"appcenter.ms": "appcenter",
"unityads.unity3d.com": "unity_ads",
"azure.com": "azure",
"bttn.io": "button"
}
}

View File

@@ -1,5 +1,6 @@
import whotracksmeDb from './whotracksme.json';
import whotracksmeWebsites from './whotracksme_web.json'; import whotracksmeWebsites from './whotracksme_web.json';
import trackersDb from './trackers.json'; import adguardDb from './adguard.json';
import { REPOSITORY } from '../constants'; import { REPOSITORY } from '../constants';
/** /**
@@ -38,7 +39,6 @@ const getWhotracksmeUrl = (trackerId) => {
/** /**
* Gets the source metadata for the specified tracker * Gets the source metadata for the specified tracker
*
* @param {TrackerData} trackerData tracker data * @param {TrackerData} trackerData tracker data
* @returns {source} source metadata or null if no matching tracker found * @returns {source} source metadata or null if no matching tracker found
*/ */
@@ -64,26 +64,14 @@ export const getSourceData = (trackerData) => {
}; };
/** /**
* Converts the JSON string source into numeric source for AdGuard Home * Gets tracker data in the specified database
*
* @param {TrackerData} trackerData tracker data
* @returns {number} source number
*/
const convertSource = (sourceStr) => {
if (!sourceStr || sourceStr !== 'AdGuard') {
return sources.WHOTRACKSME;
}
return sources.ADGUARD;
};
/**
* Gets tracker data from the trackers database
* *
* @param {String} domainName domain name to check * @param {String} domainName domain name to check
* @param {*} trackersDb trackers database
* @param {number} source source ID
* @returns {TrackerData} tracker data or null if no matching tracker found * @returns {TrackerData} tracker data or null if no matching tracker found
*/ */
export const getTrackerData = (domainName) => { const getTrackerDataFromDb = (domainName, trackersDb, source) => {
if (!domainName) { if (!domainName) {
return null; return null;
} }
@@ -100,7 +88,7 @@ export const getTrackerData = (domainName) => {
if (trackerId) { if (trackerId) {
const trackerData = trackersDb.trackers[trackerId]; const trackerData = trackersDb.trackers[trackerId];
const categoryName = trackersDb.categories[trackerData.categoryId]; const categoryName = trackersDb.categories[trackerData.categoryId];
const source = convertSource(trackerData.source); trackerData.source = source;
const sourceData = getSourceData(trackerData); const sourceData = getSourceData(trackerData);
return { return {
@@ -117,3 +105,22 @@ export const getTrackerData = (domainName) => {
// No tracker found for the specified domain // No tracker found for the specified domain
return null; return null;
}; };
/**
* Gets tracker data from the trackers database
*
* @param {String} domainName domain name to check
* @returns {TrackerData} tracker data or null if no matching tracker found
*/
export const getTrackerData = (domainName) => {
if (!domainName) {
return null;
}
let data = getTrackerDataFromDb(domainName, adguardDb, sources.ADGUARD);
if (!data) {
data = getTrackerDataFromDb(domainName, whotracksmeDb, sources.WHOTRACKSME);
}
return data;
};

View File

@@ -1,5 +1,5 @@
{ {
"timeUpdated": "2023-02-09T12:31:34.007Z", "timeUpdated": "2022-10-15T00:14:03.765Z",
"categories": { "categories": {
"0": "audio_video_player", "0": "audio_video_player",
"1": "comments", "1": "comments",
@@ -16,8 +16,7 @@
"12": "extensions", "12": "extensions",
"13": "email", "13": "email",
"14": "consent", "14": "consent",
"15": "telemetry", "15": "telemetry"
"101": "mobile_analytics"
}, },
"trackers": { "trackers": {
"163": { "163": {
@@ -873,11 +872,10 @@
"companyId": "adgoto" "companyId": "adgoto"
}, },
"adguard": { "adguard": {
"name": "AdGuard", "name": "Adguard",
"categoryId": 8, "categoryId": 12,
"url": "https://adguard.com/", "url": "https://adguard.com/",
"companyId": "adguard", "companyId": null
"source": "AdGuard"
}, },
"adhands": { "adhands": {
"name": "AdHands", "name": "AdHands",
@@ -953,10 +951,9 @@
}, },
"adjust": { "adjust": {
"name": "Adjust", "name": "Adjust",
"categoryId": 101, "categoryId": 6,
"url": "https://www.adjust.com/", "url": "https://www.adjust.com/",
"companyId": "adjust", "companyId": "adjust"
"source": "AdGuard"
}, },
"adk2": { "adk2": {
"name": "adk2", "name": "adk2",
@@ -2144,8 +2141,7 @@
"name": "Akamai Technologies", "name": "Akamai Technologies",
"categoryId": 9, "categoryId": 9,
"url": "https://www.akamai.com/", "url": "https://www.akamai.com/",
"companyId": "akamai", "companyId": "akamai"
"source": "AdGuard"
}, },
"akamoihd.net": { "akamoihd.net": {
"name": "akamoihd.net", "name": "akamoihd.net",
@@ -2545,10 +2541,9 @@
}, },
"appsflyer": { "appsflyer": {
"name": "AppsFlyer", "name": "AppsFlyer",
"categoryId": 101, "categoryId": 6,
"url": "https://www.appsflyer.com/", "url": "https://www.appsflyer.com/",
"companyId": "appsflyer", "companyId": "appsflyer"
"source": "AdGuard"
}, },
"apptv": { "apptv": {
"name": "appTV", "name": "appTV",
@@ -7100,10 +7095,9 @@
}, },
"flurry": { "flurry": {
"name": "Flurry", "name": "Flurry",
"categoryId": 101, "categoryId": 6,
"url": "http://www.flurry.com/", "url": "http://www.flurry.com/",
"companyId": "verizon", "companyId": "verizon"
"source": "AdGuard"
}, },
"flxone": { "flxone": {
"name": "FLXONE", "name": "FLXONE",
@@ -10499,22 +10493,19 @@
"name": "Mail.Ru Banner Network", "name": "Mail.Ru Banner Network",
"categoryId": 4, "categoryId": 4,
"url": "http://mail.ru/", "url": "http://mail.ru/",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"mail.ru_counter": { "mail.ru_counter": {
"name": "Mail.Ru Counter", "name": "Mail.Ru Counter",
"categoryId": 2, "categoryId": 2,
"url": "http://mail.ru/", "url": "https://corp.megafon.com/",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"mail.ru_group": { "mail.ru_group": {
"name": "Mail.Ru Group", "name": "Mail.Ru Group",
"categoryId": 7, "categoryId": 7,
"url": "http://mail.ru/", "url": "http://mail.ru/",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"mailchimp_tracking": { "mailchimp_tracking": {
"name": "MailChimp Tracking", "name": "MailChimp Tracking",
@@ -10640,8 +10631,7 @@
"name": "MarkMonitor", "name": "MarkMonitor",
"categoryId": 4, "categoryId": 4,
"url": "https://www.markmonitor.com/", "url": "https://www.markmonitor.com/",
"companyId": "markmonitor", "companyId": "markmonitor"
"source": "AdGuard"
}, },
"marktest": { "marktest": {
"name": "Marktest", "name": "Marktest",
@@ -11701,10 +11691,9 @@
}, },
"netflix": { "netflix": {
"name": "Netflix", "name": "Netflix",
"categoryId": 0, "categoryId": 8,
"url": "https://www.netflix.com/", "url": null,
"companyId": "netflix", "companyId": null
"source": "AdGuard"
}, },
"netletix": { "netletix": {
"name": "Netletix", "name": "Netletix",
@@ -17980,22 +17969,19 @@
"name": "Vk.com", "name": "Vk.com",
"categoryId": 7, "categoryId": 7,
"url": "https://vk.com/", "url": "https://vk.com/",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"vkontakte": { "vkontakte": {
"name": "VKontakte", "name": "VKontakte",
"categoryId": 7, "categoryId": 7,
"url": "https://vk.com/", "url": "https://vk.com/",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"vkontakte_widgets": { "vkontakte_widgets": {
"name": "VKontakte Widgets", "name": "VKontakte Widgets",
"categoryId": 7, "categoryId": 7,
"url": "https://dev.vk.com/", "url": "http://vk.com/developers.php",
"companyId": "vk", "companyId": "megafon"
"source": "AdGuard"
}, },
"vntsm.com": { "vntsm.com": {
"name": "Venatus Media", "name": "Venatus Media",
@@ -19214,160 +19200,6 @@
"categoryId": 4, "categoryId": 4,
"url": "http://www.zypmedia.com/", "url": "http://www.zypmedia.com/",
"companyId": "zypmedia" "companyId": "zypmedia"
},
"slack": {
"name": "Slack",
"categoryId": 8,
"url": "https://www.slack.com/",
"companyId": "salesforce",
"source": "AdGuard"
},
"apple": {
"name": "Apple",
"categoryId": 8,
"url": "https://www.apple.com/",
"companyId": "apple",
"source": "AdGuard"
},
"apple_ads": {
"name": "Apple Search Ads",
"categoryId": 4,
"url": "https://searchads.apple.com/",
"companyId": "apple",
"source": "AdGuard"
},
"facebook_audience": {
"name": "Facebook Audience Network",
"categoryId": 4,
"url": "https://www.facebook.com/business/products/audience-network",
"companyId": "facebook",
"source": "AdGuard"
},
"crashlytics": {
"name": "Crashlytics",
"categoryId": 101,
"url": "https://crashlytics.com/",
"companyId": null,
"source": "AdGuard"
},
"showrss": {
"name": "showRSS",
"categoryId": 8,
"url": "https://showrss.info/",
"companyId": "showrss",
"source": "AdGuard"
},
"hockeyapp": {
"name": "HockeyApp",
"categoryId": 101,
"url": "https://hockeyapp.net/",
"companyId": null,
"source": "AdGuard"
},
"google_trust_services": {
"name": "Google Trust Services",
"categoryId": 5,
"url": "https://pki.goog/",
"companyId": "google",
"source": "AdGuard"
},
"firebase": {
"name": "Firebase",
"categoryId": 101,
"url": "https://firebase.google.com/",
"companyId": "google",
"source": "AdGuard"
},
"yandex_appmetrica": {
"name": "Yandex AppMetrica",
"categoryId": 101,
"url": "https://appmetrica.yandex.com/",
"companyId": "yandex",
"source": "AdGuard"
},
"branch": {
"name": "Branch.io",
"categoryId": 101,
"url": "https://branch.io/",
"companyId": "branch_metrics_inc",
"source": "AdGuard"
},
"qualcomm": {
"name": "Qualcomm",
"categoryId": 8,
"url": "https://www.qualcomm.com/",
"companyId": "qualcomm",
"source": "AdGuard"
},
"solaredge": {
"name": "SolarEdge Technologies, Inc.",
"categoryId": 8,
"url": "https://www.solaredge.com/",
"companyId": "solaredge",
"source": "AdGuard"
},
"element": {
"name": "Element",
"categoryId": 7,
"url": "https://element.io/",
"companyId": "element",
"source": "AdGuard"
},
"outlook": {
"name": "Microsoft Outlook",
"categoryId": 13,
"url": "https://outlook.live.com/",
"companyId": "microsoft",
"source": "AdGuard"
},
"appcenter": {
"name": "Microsoft App Center",
"categoryId": 5,
"url": "https://appcenter.ms/",
"companyId": null,
"source": "AdGuard"
},
"unity_ads": {
"name": "Unity Ads",
"categoryId": 4,
"url": "https://unity.com/solutions/mobile-business/monetize-your-game",
"companyId": null,
"source": "AdGuard"
},
"azure": {
"name": "Microsoft Azure",
"categoryId": 10,
"url": "https://azure.microsoft.com/",
"companyId": "microsoft",
"source": "AdGuard"
},
"button": {
"name": "Button",
"categoryId": 4,
"url": "https://www.usebutton.com/",
"companyId": null,
"source": "AdGuard"
},
"lets_encrypt": {
"name": "Let's Encrypt",
"categoryId": 5,
"url": "https://letsencrypt.org/",
"companyId": "lets_encrypt",
"source": "AdGuard"
},
"plex": {
"name": "Plex",
"categoryId": 0,
"url": "https://www.plex.tv/",
"companyId": "plex",
"source": "AdGuard"
},
"matrix": {
"name": "Matrix",
"categoryId": 5,
"url": "https://matrix.org/",
"companyId": "matrix",
"source": "AdGuard"
} }
}, },
"trackerDomains": { "trackerDomains": {
@@ -20908,7 +20740,7 @@
"facebook.net": "facebook", "facebook.net": "facebook",
"fbcdn.net": "facebook_cdn", "fbcdn.net": "facebook_cdn",
"fbsbx.com": "facebook_cdn", "fbsbx.com": "facebook_cdn",
"graph.facebook.com": "facebook_audience", "graph.facebook.com": "facebook_graph",
"facetz.net": "facetz.dca", "facetz.net": "facetz.dca",
"adsfac.eu": "facilitate_digital", "adsfac.eu": "facilitate_digital",
"adsfac.net": "facilitate_digital", "adsfac.net": "facilitate_digital",
@@ -21441,7 +21273,7 @@
"isocket.com": "isocket", "isocket.com": "isocket",
"ispot.tv": "ispot.tv", "ispot.tv": "ispot.tv",
"itineraire.info": "itineraire.info", "itineraire.info": "itineraire.info",
"apple.com": "apple", "apple.com": "itunes_link_maker",
"autolinkmaker.itunes.apple.com": "itunes_link_maker", "autolinkmaker.itunes.apple.com": "itunes_link_maker",
"ity.im": "ity.im", "ity.im": "ity.im",
"iubenda.com": "iubenda.com", "iubenda.com": "iubenda.com",
@@ -21895,7 +21727,7 @@
"azurewebsites.net": "microsoft", "azurewebsites.net": "microsoft",
"cloudapp.net": "microsoft", "cloudapp.net": "microsoft",
"gfx.ms": "microsoft", "gfx.ms": "microsoft",
"live.com": "outlook", "live.com": "microsoft",
"microsoft.com": "microsoft", "microsoft.com": "microsoft",
"microsoftonline-p.com": "microsoft", "microsoftonline-p.com": "microsoft",
"microsoftonline.com": "microsoft", "microsoftonline.com": "microsoft",
@@ -23697,54 +23529,6 @@
"zukxd6fkxqn.com": "zukxd6fkxqn.com", "zukxd6fkxqn.com": "zukxd6fkxqn.com",
"zwaar.net": "zwaar", "zwaar.net": "zwaar",
"zwaar.org": "zwaar", "zwaar.org": "zwaar",
"extend.tv": "zypmedia", "extend.tv": "zypmedia"
"slack.com": "slack",
"slackb.com": "slack",
"slack-edge.com": "slack",
"slack-imgs.com": "slack",
"adguard.app": "adguard",
"adguard.io": "adguard",
"adguard.org": "adguard",
"adguard-dns.com": "adguard",
"adguard-dns.io": "adguard",
"adguard-vpn.com": "adguard",
"adguardvpn.com": "adguard",
"adguard-vpn.online": "adguard",
"nflximg.com": "netflix",
"element.io": "element",
"riot.im": "element",
"akadns.net": "akamai_technologies",
"akamaiedge.net": "akamai_technologies",
"apple.news": "apple",
"apple-dns.net": "apple",
"aaplimg.com": "apple",
"icloud.com": "apple",
"icloud-content.com": "apple",
"mzstatic.com": "apple",
"matrix.org": "matrix",
"l-msedge.net": "microsoft",
"iadsdk.apple.com": "apple_ads",
"showrss.info": "showrss",
"solaredge.com": "solaredge",
"crashlytics.com": "crashlytics",
"flurry.com": "flurry",
"hockeyapp.net": "hockeyapp",
"app-measurement.com": "firebase",
"appmetrica.yandex.com": "yandex_appmetrica",
"letsencrypt.org": "lets_encrypt",
"lencr.org": "lets_encrypt",
"mobileapptracking.com": "branch",
"plex.tv": "plex",
"plex.direct": "plex",
"edgecastcdn.net": "markmonitor",
"appcenter.ms": "appcenter",
"unityads.unity3d.com": "unity_ads",
"azure.com": "azure",
"trafficmanager.net": "azure",
"hotmail.com": "outlook",
"bttn.io": "button",
"pki.goog": "google_trust_services",
"xtracloud.net": "qualcomm",
"qualcomm.com": "qualcomm"
} }
} }

39
go.mod
View File

@@ -1,10 +1,10 @@
module github.com/AdguardTeam/AdGuardHome module github.com/AdguardTeam/AdGuardHome
go 1.19 go 1.18
require ( require (
// TODO(a.garipov): Use v0.48.0 when it's released. // TODO(a.garipov): Return to a tagged version once DNS64 is in.
github.com/AdguardTeam/dnsproxy v0.47.1-0.20230207130636-533058b17239 github.com/AdguardTeam/dnsproxy v0.46.6-0.20230125113741-98cb8a899e49
github.com/AdguardTeam/golibs v0.11.4 github.com/AdguardTeam/golibs v0.11.4
github.com/AdguardTeam/urlfilter v0.16.1 github.com/AdguardTeam/urlfilter v0.16.1
github.com/NYTimes/gziphandler v1.1.1 github.com/NYTimes/gziphandler v1.1.1
@@ -19,26 +19,27 @@ require (
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8 github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8
github.com/kardianos/service v1.2.2 github.com/kardianos/service v1.2.2
github.com/lucas-clemente/quic-go v0.31.1
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
github.com/mdlayher/netlink v1.7.1 github.com/mdlayher/netlink v1.7.1
// TODO(a.garipov): This package is deprecated; find a new one or use // TODO(a.garipov): This package is deprecated; find a new one or use
// our own code for that. Perhaps, use gopacket. // our own code for that. Perhaps, use gopacket.
github.com/mdlayher/raw v0.1.0 github.com/mdlayher/raw v0.1.0
github.com/miekg/dns v1.1.50 github.com/miekg/dns v1.1.50
github.com/quic-go/quic-go v0.32.0
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.1
github.com/ti-mo/netfilter v0.5.0 github.com/ti-mo/netfilter v0.5.0
go.etcd.io/bbolt v1.3.7 go.etcd.io/bbolt v1.3.7
golang.org/x/crypto v0.6.0 golang.org/x/crypto v0.5.0
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb golang.org/x/exp v0.0.0-20230131160201-f062dba9d201
golang.org/x/net v0.7.0 golang.org/x/net v0.5.0
golang.org/x/sys v0.5.0 golang.org/x/sys v0.4.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
howett.net/plist v1.0.0 howett.net/plist v1.0.0
) )
require ( require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
github.com/ameshkov/dnsstamps v1.0.3 // indirect github.com/ameshkov/dnsstamps v1.0.3 // indirect
@@ -47,22 +48,20 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f // indirect
github.com/josharian/native v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/marten-seemann/qpack v0.3.0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.4 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.2 // indirect
github.com/mdlayher/packet v1.1.1 // indirect github.com/mdlayher/packet v1.1.1 // indirect
github.com/mdlayher/socket v0.4.0 // indirect github.com/mdlayher/socket v0.4.0 // indirect
github.com/onsi/ginkgo/v2 v2.8.1 // indirect github.com/onsi/ginkgo/v2 v2.8.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/u-root/uio v0.0.0-20221213070652-c3537552635f // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect golang.org/x/mod v0.7.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/u-root/uio v0.0.0-20230215032506-9aa6f7e2d72c // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/text v0.6.0 // indirect
golang.org/x/tools v0.6.0 // indirect golang.org/x/tools v0.5.0 // indirect
) )

73
go.sum
View File

@@ -1,5 +1,5 @@
github.com/AdguardTeam/dnsproxy v0.47.1-0.20230207130636-533058b17239 h1:n1oOiywOvdeqWLto809bK1rK1EPDkpaSfT/r1OiCVaQ= github.com/AdguardTeam/dnsproxy v0.46.6-0.20230125113741-98cb8a899e49 h1:TDZsKB8BrKA2na6p5l20BvEu3MmgOWhIfTANz5laFuE=
github.com/AdguardTeam/dnsproxy v0.47.1-0.20230207130636-533058b17239/go.mod h1:+Sdi5ISrjDFbeCsKNqzcC1Ag7pJ5Hh9y+UBNb3dfqJ4= github.com/AdguardTeam/dnsproxy v0.46.6-0.20230125113741-98cb8a899e49/go.mod h1:ZEkTmTJ2XInT3aVy0mHtEnSWSclpHHj/9hfNXDuAk5k=
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw= github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
github.com/AdguardTeam/golibs v0.11.4 h1:IltyvxwCTN+xxJF5sh6VadF8Zfbf8elgCm9dgijSVzM= github.com/AdguardTeam/golibs v0.11.4 h1:IltyvxwCTN+xxJF5sh6VadF8Zfbf8elgCm9dgijSVzM=
@@ -7,6 +7,8 @@ github.com/AdguardTeam/golibs v0.11.4/go.mod h1:87bN2x4VsTritptE3XZg9l8T6gznWsIx
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU= github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
github.com/AdguardTeam/urlfilter v0.16.1 h1:ZPi0rjqo8cQf2FVdzo6cqumNoHZx2KPXj2yZa1A5BBw= github.com/AdguardTeam/urlfilter v0.16.1 h1:ZPi0rjqo8cQf2FVdzo6cqumNoHZx2KPXj2yZa1A5BBw=
github.com/AdguardTeam/urlfilter v0.16.1/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI= github.com/AdguardTeam/urlfilter v0.16.1/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
@@ -55,8 +57,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f h1:gl1DCiSk+mrXXBGPm6CEeS2MkJuMVzAOrXg34oVj1QI=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU= github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk= github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -83,6 +85,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4=
github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
github.com/marten-seemann/qtls-go1-18 v0.1.4 h1:ogomB+lWV3Vmwiu6RTwDVTMGx+9j7SEi98e8QB35Its=
github.com/marten-seemann/qtls-go1-18 v0.1.4/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/marten-seemann/qtls-go1-19 v0.1.2 h1:ZevAEqKXH0bZmoOBPiqX2h5rhQ7cbZi+X+rlq2JUbCE=
github.com/marten-seemann/qtls-go1-19 v0.1.2/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE= github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE=
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118/go.mod h1:ZFUnHIVchZ9lJoWoEGUg8Q3M4U8aNNWA3CVSUTkW4og= github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118/go.mod h1:ZFUnHIVchZ9lJoWoEGUg8Q3M4U8aNNWA3CVSUTkW4og=
@@ -108,29 +118,16 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU= github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU=
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
github.com/shirou/gopsutil/v3 v3.21.8 h1:nKct+uP0TV8DjjNiHanKf8SAuub+GNsbrOtM9Nl9biA= github.com/shirou/gopsutil/v3 v3.21.8 h1:nKct+uP0TV8DjjNiHanKf8SAuub+GNsbrOtM9Nl9biA=
github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ= github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -154,24 +151,23 @@ github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f h1:dpx1PHxYqAnXzbryJrWP1NQLzEjwcVgFLhkknuFQ7ww=
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f/go.mod h1:IogEAUBXDEwX7oR/BMmCctShYs80ql4hF0ySdzGxf7E= github.com/u-root/uio v0.0.0-20221213070652-c3537552635f/go.mod h1:IogEAUBXDEwX7oR/BMmCctShYs80ql4hF0ySdzGxf7E=
github.com/u-root/uio v0.0.0-20230215032506-9aa6f7e2d72c h1:PHoGTnweZP+KIg/8Zc6+iOesrIF5yHkpb4GBDxHm7yE=
github.com/u-root/uio v0.0.0-20230215032506-9aa6f7e2d72c/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 h1:BEABXpNXLEz0WxtA+6CQIz2xkg80e+1zrhWyMcq8VzE=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -188,8 +184,8 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
@@ -222,24 +218,24 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -248,11 +244,12 @@ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscL
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -80,6 +80,11 @@ func CanBindPrivilegedPorts() (can bool, err error) {
return canBindPrivilegedPorts() return canBindPrivilegedPorts()
} }
// AcquirePermissions tries to acquire permissions to bind to privileged ports.
func AcquirePermissions() (err error) {
return acquirePermissions()
}
// NetInterface represents an entry of network interfaces map. // NetInterface represents an entry of network interfaces map.
type NetInterface struct { type NetInterface struct {
// Addresses are the network interface addresses. // Addresses are the network interface addresses.

View File

@@ -7,3 +7,7 @@ import "github.com/AdguardTeam/AdGuardHome/internal/aghos"
func canBindPrivilegedPorts() (can bool, err error) { func canBindPrivilegedPorts() (can bool, err error) {
return aghos.HaveAdminRights() return aghos.HaveAdminRights()
} }
func acquirePermissions() (err error) {
return nil
}

View File

@@ -23,17 +23,17 @@ const dhcpcdConf = "etc/dhcpcd.conf"
func canBindPrivilegedPorts() (can bool, err error) { func canBindPrivilegedPorts() (can bool, err error) {
res, err := unix.PrctlRetInt( res, err := unix.PrctlRetInt(
unix.PR_CAP_AMBIENT, unix.PR_CAPBSET_READ,
unix.PR_CAP_AMBIENT_IS_SET,
unix.CAP_NET_BIND_SERVICE, unix.CAP_NET_BIND_SERVICE,
0, 0,
0, 0,
0,
) )
if err != nil { if err != nil {
if errors.Is(err, unix.EINVAL) { if errors.Is(err, unix.EINVAL) {
// Older versions of Linux kernel do not support this. Print a // Older versions of Linux kernel do not support this. Print a
// warning and check admin rights. // warning and check admin rights.
log.Info("warning: cannot check capability cap_net_bind_service: %s", err) log.Info("warning: cannot check cap_net_bind_service: %s", err)
} else { } else {
return false, err return false, err
} }
@@ -45,6 +45,21 @@ func canBindPrivilegedPorts() (can bool, err error) {
return res == 1 || adm, nil return res == 1 || adm, nil
} }
func acquirePermissions() (err error) {
_, err = unix.PrctlRetInt(
unix.PR_CAP_AMBIENT,
unix.PR_CAP_AMBIENT_RAISE,
unix.CAP_NET_BIND_SERVICE,
0,
0,
)
if err != nil {
return fmt.Errorf("raising cap_net_bind_service: %w", err)
}
return nil
}
// dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to // dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to
// have a static IP. // have a static IP.
func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) { func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) {

View File

@@ -43,3 +43,7 @@ func closePortChecker(c io.Closer) (err error) {
func isAddrInUse(err syscall.Errno) (ok bool) { func isAddrInUse(err syscall.Errno) (ok bool) {
return errors.Is(err, windows.WSAEADDRINUSE) return errors.Is(err, windows.WSAEADDRINUSE)
} }
func acquirePermissions() (err error) {
return nil
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/netutil"
"github.com/quic-go/quic-go" "github.com/lucas-clemente/quic-go"
) )
// ValidateClientID returns an error if id is not a valid ClientID. // ValidateClientID returns an error if id is not a valid ClientID.
@@ -151,7 +151,25 @@ func (s *Server) clientIDFromDNSContext(pctx *proxy.DNSContext) (clientID string
func clientServerName(pctx *proxy.DNSContext, proto proxy.Proto) (srvName string, err error) { func clientServerName(pctx *proxy.DNSContext, proto proxy.Proto) (srvName string, err error) {
switch proto { switch proto {
case proxy.ProtoHTTPS: case proxy.ProtoHTTPS:
srvName = pctx.HTTPRequest.TLS.ServerName // github.com/lucas-clemente/quic-go seems to not populate the TLS
// field. So, if the request comes over HTTP/3, use the Host header
// value as the server name.
//
// See https://github.com/lucas-clemente/quic-go/issues/2879.
//
// TODO(a.garipov): Remove this crutch once they fix it.
r := pctx.HTTPRequest
if r.ProtoAtLeast(3, 0) {
var host string
host, err = netutil.SplitHost(r.Host)
if err != nil {
return "", fmt.Errorf("parsing host: %w", err)
}
srvName = host
} else if connState := r.TLS; connState != nil {
srvName = r.TLS.ServerName
}
case proxy.ProtoQUIC: case proxy.ProtoQUIC:
qConn := pctx.QUICConnection qConn := pctx.QUICConnection
conn, ok := qConn.(quicConnection) conn, ok := qConn.(quicConnection)

View File

@@ -9,7 +9,7 @@ import (
"github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/testutil" "github.com/AdguardTeam/golibs/testutil"
"github.com/quic-go/quic-go" "github.com/lucas-clemente/quic-go"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -55,6 +55,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID string wantClientID string
wantErrMsg string wantErrMsg string
strictSNI bool strictSNI bool
useHTTP3 bool
}{{ }{{
name: "udp", name: "udp",
proto: proxy.ProtoUDP, proto: proxy.ProtoUDP,
@@ -63,6 +64,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "", wantClientID: "",
wantErrMsg: "", wantErrMsg: "",
strictSNI: false, strictSNI: false,
useHTTP3: false,
}, { }, {
name: "tls_no_clientid", name: "tls_no_clientid",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -71,6 +73,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "", wantClientID: "",
wantErrMsg: "", wantErrMsg: "",
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_no_client_server_name", name: "tls_no_client_server_name",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -80,6 +83,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantErrMsg: `clientid check: client server name "" ` + wantErrMsg: `clientid check: client server name "" ` +
`doesn't match host server name "example.com"`, `doesn't match host server name "example.com"`,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_no_client_server_name_no_strict", name: "tls_no_client_server_name_no_strict",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -88,6 +92,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "", wantClientID: "",
wantErrMsg: "", wantErrMsg: "",
strictSNI: false, strictSNI: false,
useHTTP3: false,
}, { }, {
name: "tls_clientid", name: "tls_clientid",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -96,6 +101,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "cli", wantClientID: "cli",
wantErrMsg: "", wantErrMsg: "",
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_clientid_hostname_error", name: "tls_clientid_hostname_error",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -105,6 +111,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantErrMsg: `clientid check: client server name "cli.example.net" ` + wantErrMsg: `clientid check: client server name "cli.example.net" ` +
`doesn't match host server name "example.com"`, `doesn't match host server name "example.com"`,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_invalid_clientid", name: "tls_invalid_clientid",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -114,6 +121,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantErrMsg: `clientid check: invalid clientid "!!!": ` + wantErrMsg: `clientid check: invalid clientid "!!!": ` +
`bad domain name label rune '!'`, `bad domain name label rune '!'`,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_clientid_too_long", name: "tls_clientid_too_long",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -125,6 +133,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
`pqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789": ` + `pqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789": ` +
`domain name label is too long: got 72, max 63`, `domain name label is too long: got 72, max 63`,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "quic_clientid", name: "quic_clientid",
proto: proxy.ProtoQUIC, proto: proxy.ProtoQUIC,
@@ -133,6 +142,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "cli", wantClientID: "cli",
wantErrMsg: "", wantErrMsg: "",
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_clientid_issue3437", name: "tls_clientid_issue3437",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -142,6 +152,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantErrMsg: `clientid check: client server name "cli.myexample.com" ` + wantErrMsg: `clientid check: client server name "cli.myexample.com" ` +
`doesn't match host server name "example.com"`, `doesn't match host server name "example.com"`,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "tls_case", name: "tls_case",
proto: proxy.ProtoTLS, proto: proxy.ProtoTLS,
@@ -150,6 +161,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "insensitive", wantClientID: "insensitive",
wantErrMsg: ``, wantErrMsg: ``,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "quic_case", name: "quic_case",
proto: proxy.ProtoQUIC, proto: proxy.ProtoQUIC,
@@ -158,6 +170,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "insensitive", wantClientID: "insensitive",
wantErrMsg: ``, wantErrMsg: ``,
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "https_no_clientid", name: "https_no_clientid",
proto: proxy.ProtoHTTPS, proto: proxy.ProtoHTTPS,
@@ -166,6 +179,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "", wantClientID: "",
wantErrMsg: "", wantErrMsg: "",
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, { }, {
name: "https_clientid", name: "https_clientid",
proto: proxy.ProtoHTTPS, proto: proxy.ProtoHTTPS,
@@ -174,6 +188,16 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
wantClientID: "cli", wantClientID: "cli",
wantErrMsg: "", wantErrMsg: "",
strictSNI: true, strictSNI: true,
useHTTP3: false,
}, {
name: "https_clientid_quic",
proto: proxy.ProtoHTTPS,
hostSrvName: "example.com",
cliSrvName: "cli.example.com",
wantClientID: "cli",
wantErrMsg: "",
strictSNI: true,
useHTTP3: true,
}} }}
for _, tc := range testCases { for _, tc := range testCases {
@@ -195,7 +219,7 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
switch tc.proto { switch tc.proto {
case proxy.ProtoHTTPS: case proxy.ProtoHTTPS:
httpReq = newHTTPReq(tc.cliSrvName) httpReq = newHTTPReq(tc.cliSrvName, tc.useHTTP3)
case proxy.ProtoQUIC: case proxy.ProtoQUIC:
qconn = testQUICConnection{ qconn = testQUICConnection{
serverName: tc.cliSrvName, serverName: tc.cliSrvName,
@@ -222,11 +246,21 @@ func TestServer_clientIDFromDNSContext(t *testing.T) {
} }
// newHTTPReq is a helper to create HTTP requests for tests. // newHTTPReq is a helper to create HTTP requests for tests.
func newHTTPReq(cliSrvName string) (r *http.Request) { func newHTTPReq(cliSrvName string, useHTTP3 bool) (r *http.Request) {
u := &url.URL{ u := &url.URL{
Path: "/dns-query", Path: "/dns-query",
} }
if useHTTP3 {
return &http.Request{
ProtoMajor: 3,
ProtoMinor: 0,
URL: u,
Host: cliSrvName,
TLS: &tls.ConnectionState{},
}
}
return &http.Request{ return &http.Request{
ProtoMajor: 1, ProtoMajor: 1,
ProtoMinor: 1, ProtoMinor: 1,

View File

@@ -5,7 +5,6 @@ import (
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"net" "net"
"net/netip"
"os" "os"
"sort" "sort"
"strings" "strings"
@@ -226,7 +225,7 @@ type ServerConfig struct {
LocalPTRResolvers []string LocalPTRResolvers []string
// DNS64Prefixes is a slice of NAT64 prefixes to be used for DNS64. // DNS64Prefixes is a slice of NAT64 prefixes to be used for DNS64.
DNS64Prefixes []netip.Prefix DNS64Prefixes []string
// ResolveClients signals if the RDNS should resolve clients' addresses. // ResolveClients signals if the RDNS should resolve clients' addresses.
ResolveClients bool ResolveClients bool
@@ -272,8 +271,6 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
RequestHandler: s.handleDNSRequest, RequestHandler: s.handleDNSRequest,
EnableEDNSClientSubnet: srvConf.EnableEDNSClientSubnet, EnableEDNSClientSubnet: srvConf.EnableEDNSClientSubnet,
MaxGoroutines: int(srvConf.MaxGoroutines), MaxGoroutines: int(srvConf.MaxGoroutines),
UseDNS64: srvConf.UseDNS64,
DNS64Prefs: srvConf.DNS64Prefixes,
} }
if srvConf.CacheSize != 0 { if srvConf.CacheSize != 0 {

View File

@@ -10,8 +10,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd" "github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
"github.com/AdguardTeam/AdGuardHome/internal/filtering" "github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil" "github.com/AdguardTeam/golibs/stringutil"
@@ -19,9 +17,6 @@ import (
) )
// To transfer information between modules // To transfer information between modules
//
// TODO(s.chzhen): Add lowercased, non-FQDN version of the hostname from the
// question of the request.
type dnsContext struct { type dnsContext struct {
proxyCtx *proxy.DNSContext proxyCtx *proxy.DNSContext
@@ -424,7 +419,7 @@ func (s *Server) processDHCPHosts(dctx *dnsContext) (rc resultCode) {
} }
resp.Answer = append(resp.Answer, a) resp.Answer = append(resp.Answer, a)
case dns.TypeAAAA: case dns.TypeAAAA:
if s.dns64Pref != (netip.Prefix{}) { if len(s.dns64Prefs) > 0 {
// Respond with DNS64-mapped address for IPv4 host if DNS64 is // Respond with DNS64-mapped address for IPv4 host if DNS64 is
// enabled. // enabled.
aaaa := &dns.AAAA{ aaaa := &dns.AAAA{
@@ -473,6 +468,15 @@ func (s *Server) processRestrictLocal(dctx *dnsContext) (rc resultCode) {
return resultCodeSuccess return resultCodeSuccess
} }
if s.shouldStripDNS64(ip) {
// Strip the prefix from the address to get the original IPv4.
ip = ip[nat64PrefixLen:]
// Treat a DNS64-prefixed address as a locally served one since those
// queries should never be sent to the global DNS.
dctx.unreversedReqIP = ip
}
// Restrict an access to local addresses for external clients. We also // Restrict an access to local addresses for external clients. We also
// assume that all the DHCP leases we give are locally served or at least // assume that all the DHCP leases we give are locally served or at least
// shouldn't be accessible externally. // shouldn't be accessible externally.
@@ -651,7 +655,13 @@ func (s *Server) processUpstream(dctx *dnsContext) (rc resultCode) {
s.setCustomUpstream(pctx, dctx.clientID) s.setCustomUpstream(pctx, dctx.clientID)
reqWantsDNSSEC := s.setReqAD(req) origReqAD := false
if s.conf.EnableDNSSEC {
origReqAD = req.AuthenticatedData
if !req.AuthenticatedData {
req.AuthenticatedData = true
}
}
// Process the request further since it wasn't filtered. // Process the request further since it wasn't filtered.
prx := s.proxy() prx := s.proxy()
@@ -661,73 +671,23 @@ func (s *Server) processUpstream(dctx *dnsContext) (rc resultCode) {
return resultCodeError return resultCodeError
} }
if err := prx.Resolve(pctx); err != nil { if dctx.err = prx.Resolve(pctx); dctx.err != nil {
if errors.Is(err, upstream.ErrNoUpstreams) { return resultCodeError
// Do not even put into querylog. Currently this happens either }
// when the private resolvers enabled and the request is DNS64 PTR,
// or when the client isn't considered local by prx.
//
// TODO(e.burkov): Make proxy detect local client the same way as
// AGH does.
pctx.Res = s.genNXDomain(req)
return resultCodeFinish
}
dctx.err = err
if s.performDNS64(prx, dctx) == resultCodeError {
return resultCodeError return resultCodeError
} }
dctx.responseFromUpstream = true dctx.responseFromUpstream = true
dctx.responseAD = pctx.Res.AuthenticatedData dctx.responseAD = pctx.Res.AuthenticatedData
s.setRespAD(pctx, reqWantsDNSSEC) if s.conf.EnableDNSSEC && !origReqAD {
return resultCodeSuccess
}
// setReqAD changes the request based on the server settings. wantsDNSSEC is
// false if the response should be cleared of the AD bit.
//
// TODO(a.garipov, e.burkov): This should probably be done in module dnsproxy.
func (s *Server) setReqAD(req *dns.Msg) (wantsDNSSEC bool) {
if !s.conf.EnableDNSSEC {
return false
}
origReqAD := req.AuthenticatedData
req.AuthenticatedData = true
// Per [RFC 6840] says, validating resolvers should only set the AD bit when
// the response has the AD bit set and the request contained either a set DO
// bit or a set AD bit. So, if neither of these is true, clear the AD bits
// in [Server.setRespAD].
//
// [RFC 6840]: https://datatracker.ietf.org/doc/html/rfc6840#section-5.8
return origReqAD || hasDO(req)
}
// hasDO returns true if msg has EDNS(0) options and the DNSSEC OK flag is set
// in there.
//
// TODO(a.garipov): Move to golibs/dnsmsg when it's there.
func hasDO(msg *dns.Msg) (do bool) {
o := msg.IsEdns0()
if o == nil {
return false
}
return o.Do()
}
// setRespAD changes the request and response based on the server settings and
// the original request data.
func (s *Server) setRespAD(pctx *proxy.DNSContext, reqWantsDNSSEC bool) {
if s.conf.EnableDNSSEC && !reqWantsDNSSEC {
pctx.Req.AuthenticatedData = false pctx.Req.AuthenticatedData = false
pctx.Res.AuthenticatedData = false pctx.Res.AuthenticatedData = false
} }
return resultCodeSuccess
} }
// isDHCPClientHostQ returns true if q is from a request for a DHCP client // isDHCPClientHostQ returns true if q is from a request for a DHCP client

View File

@@ -1,10 +1,34 @@
package dnsforward package dnsforward
import ( import (
"fmt"
"net" "net"
"net/netip" "net/netip"
"github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/mathutil"
"github.com/AdguardTeam/golibs/netutil"
"github.com/miekg/dns"
)
const (
// maxNAT64PrefixBitLen is the maximum length of a NAT64 prefix in bits.
// See https://datatracker.ietf.org/doc/html/rfc6147#section-5.2.
maxNAT64PrefixBitLen = 96
// nat64PrefixLen is the length of a NAT64 prefix in bytes.
nat64PrefixLen = net.IPv6len - net.IPv4len
// maxDNS64SynTTL is the maximum TTL for synthesized DNS64 responses with no
// SOA records in seconds.
//
// If the SOA RR was not delivered with the negative response to the AAAA
// query, then the DNS64 SHOULD use the TTL of the original A RR or 600
// seconds, whichever is shorter.
//
// See https://datatracker.ietf.org/doc/html/rfc6147#section-5.1.7.
maxDNS64SynTTL uint32 = 600
) )
// setupDNS64 initializes DNS64 settings, the NAT64 prefixes in particular. If // setupDNS64 initializes DNS64 settings, the NAT64 prefixes in particular. If
@@ -14,22 +38,227 @@ import (
// is specified explicitly. Each prefix also validated to be a valid IPv6 // is specified explicitly. Each prefix also validated to be a valid IPv6
// CIDR with a maximum length of 96 bits. The first specified prefix is then // CIDR with a maximum length of 96 bits. The first specified prefix is then
// used to synthesize AAAA records. // used to synthesize AAAA records.
func (s *Server) setupDNS64() { func (s *Server) setupDNS64() (err error) {
if !s.conf.UseDNS64 { if !s.conf.UseDNS64 {
return return nil
} }
if len(s.conf.DNS64Prefixes) == 0 { l := len(s.conf.DNS64Prefixes)
// dns64WellKnownPref is the default prefix to use in an algorithmic if l == 0 {
// mapping for DNS64. s.dns64Prefs = []netip.Prefix{dns64WellKnownPref}
//
// See https://datatracker.ietf.org/doc/html/rfc6052#section-2.1.
dns64WellKnownPref := netip.MustParsePrefix("64:ff9b::/96")
s.dns64Pref = dns64WellKnownPref return nil
} else {
s.dns64Pref = s.conf.DNS64Prefixes[0]
} }
prefs := make([]netip.Prefix, 0, l)
for i, pref := range s.conf.DNS64Prefixes {
var p netip.Prefix
p, err = netip.ParsePrefix(pref)
if err != nil {
return fmt.Errorf("prefix at index %d: %w", i, err)
}
addr := p.Addr()
if !addr.Is6() {
return fmt.Errorf("prefix at index %d: %q is not an IPv6 prefix", i, pref)
}
if p.Bits() > maxNAT64PrefixBitLen {
return fmt.Errorf("prefix at index %d: %q is too long for DNS64", i, pref)
}
prefs = append(prefs, p.Masked())
}
s.dns64Prefs = prefs
return nil
}
// checkDNS64 checks if DNS64 should be performed. It returns a DNS64 request
// to resolve or nil if DNS64 is not desired. It also filters resp to not
// contain any NAT64 excluded addresses in the answer section, if needed. Both
// req and resp must not be nil.
//
// See https://datatracker.ietf.org/doc/html/rfc6147.
func (s *Server) checkDNS64(req, resp *dns.Msg) (dns64Req *dns.Msg) {
if len(s.dns64Prefs) == 0 {
return nil
}
q := req.Question[0]
if q.Qtype != dns.TypeAAAA || q.Qclass != dns.ClassINET {
// DNS64 operation for classes other than IN is undefined, and a DNS64
// MUST behave as though no DNS64 function is configured.
return nil
}
rcode := resp.Rcode
if rcode == dns.RcodeNameError {
// A result with RCODE=3 (Name Error) is handled according to normal DNS
// operation (which is normally to return the error to the client).
return nil
}
if rcode == dns.RcodeSuccess {
// If resolver receives an answer with at least one AAAA record
// containing an address outside any of the excluded range(s), then it
// by default SHOULD build an answer section for a response including
// only the AAAA record(s) that do not contain any of the addresses
// inside the excluded ranges.
var hasAnswers bool
if resp.Answer, hasAnswers = s.filterNAT64Answers(resp.Answer); hasAnswers {
return nil
}
// Any other RCODE is treated as though the RCODE were 0 and the answer
// section were empty.
}
return &dns.Msg{
MsgHdr: dns.MsgHdr{
Id: dns.Id(),
RecursionDesired: req.RecursionDesired,
AuthenticatedData: req.AuthenticatedData,
CheckingDisabled: req.CheckingDisabled,
},
Question: []dns.Question{{
Name: req.Question[0].Name,
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
}},
}
}
// filterNAT64Answers filters out AAAA records that are within one of NAT64
// exclusion prefixes. hasAnswers is true if the filtered slice contains at
// least a single AAAA answer not within the prefixes or a CNAME.
func (s *Server) filterNAT64Answers(rrs []dns.RR) (filtered []dns.RR, hasAnswers bool) {
filtered = make([]dns.RR, 0, len(rrs))
for _, ans := range rrs {
switch ans := ans.(type) {
case *dns.AAAA:
addr, err := netutil.IPToAddrNoMapped(ans.AAAA)
if err != nil {
log.Error("dnsforward: bad AAAA record: %s", err)
continue
}
if s.withinDNS64(addr) {
// Filter the record.
continue
}
filtered, hasAnswers = append(filtered, ans), true
case *dns.CNAME, *dns.DNAME:
// If the response contains a CNAME or a DNAME, then the CNAME or
// DNAME chain is followed until the first terminating A or AAAA
// record is reached.
//
// Just treat CNAME and DNAME responses as passable answers since
// AdGuard Home doesn't follow any of these chains except the
// dnsrewrite-defined ones.
filtered, hasAnswers = append(filtered, ans), true
default:
filtered = append(filtered, ans)
}
}
return filtered, hasAnswers
}
// synthDNS64 synthesizes a DNS64 response using the original response as a
// basis and modifying it with data from resp. It returns true if the response
// was actually modified.
func (s *Server) synthDNS64(origReq, origResp, resp *dns.Msg) (ok bool) {
if len(resp.Answer) == 0 {
// If there is an empty answer, then the DNS64 responds to the original
// querying client with the answer the DNS64 received to the original
// (initiator's) query.
return false
}
// The Time to Live (TTL) field is set to the minimum of the TTL of the
// original A RR and the SOA RR for the queried domain. If the original
// response contains no SOA records, the minimum of the TTL of the original
// A RR and [maxDNS64SynTTL] should be used. See [maxDNS64SynTTL].
soaTTL := maxDNS64SynTTL
for _, rr := range origResp.Ns {
if hdr := rr.Header(); hdr.Rrtype == dns.TypeSOA && hdr.Name == origReq.Question[0].Name {
soaTTL = hdr.Ttl
break
}
}
newAns := make([]dns.RR, 0, len(resp.Answer))
for _, ans := range resp.Answer {
rr := s.synthRR(ans, soaTTL)
if rr == nil {
// The error should have already been logged.
return false
}
newAns = append(newAns, rr)
}
origResp.Answer = newAns
origResp.Ns = resp.Ns
origResp.Extra = resp.Extra
return true
}
// dns64WellKnownPref is the default prefix to use in an algorithmic mapping for
// DNS64. See https://datatracker.ietf.org/doc/html/rfc6052#section-2.1.
var dns64WellKnownPref = netip.MustParsePrefix("64:ff9b::/96")
// withinDNS64 checks if ip is within one of the configured DNS64 prefixes.
//
// TODO(e.burkov): We actually using bytes of only the first prefix from the
// set to construct the answer, so consider using some implementation of a
// prefix set for the rest.
func (s *Server) withinDNS64(ip netip.Addr) (ok bool) {
for _, n := range s.dns64Prefs {
if n.Contains(ip) {
return true
}
}
return false
}
// shouldStripDNS64 returns true if DNS64 is enabled and ip has either one of
// custom DNS64 prefixes or the Well-Known one. This is intended to be used
// with PTR requests.
//
// The requirement is to match any Pref64::/n used at the site, and not merely
// the locally configured Pref64::/n. This is because end clients could ask for
// a PTR record matching an address received through a different (site-provided)
// DNS64.
//
// See https://datatracker.ietf.org/doc/html/rfc6147#section-5.3.1.
func (s *Server) shouldStripDNS64(ip net.IP) (ok bool) {
if len(s.dns64Prefs) == 0 {
return false
}
addr, err := netutil.IPToAddr(ip, netutil.AddrFamilyIPv6)
if err != nil {
return false
}
switch {
case s.withinDNS64(addr):
log.Debug("dnsforward: %s is within DNS64 custom prefix set", ip)
case dns64WellKnownPref.Contains(addr):
log.Debug("dnsforward: %s is within DNS64 well-known prefix", ip)
default:
return false
}
return true
} }
// mapDNS64 maps ip to IPv6 address using configured DNS64 prefix. ip must be a // mapDNS64 maps ip to IPv6 address using configured DNS64 prefix. ip must be a
@@ -38,12 +267,79 @@ func (s *Server) setupDNS64() {
func (s *Server) mapDNS64(ip netip.Addr) (mapped net.IP) { func (s *Server) mapDNS64(ip netip.Addr) (mapped net.IP) {
// Don't mask the address here since it should have already been masked on // Don't mask the address here since it should have already been masked on
// initialization stage. // initialization stage.
pref := s.dns64Pref.Masked().Addr().As16() pref := s.dns64Prefs[0].Addr().As16()
ipData := ip.As4() ipData := ip.As4()
mapped = make(net.IP, net.IPv6len) mapped = make(net.IP, net.IPv6len)
copy(mapped[:proxy.NAT64PrefixLength], pref[:]) copy(mapped[:nat64PrefixLen], pref[:])
copy(mapped[proxy.NAT64PrefixLength:], ipData[:]) copy(mapped[nat64PrefixLen:], ipData[:])
return mapped return mapped
} }
// performDNS64 processes the current state of dctx assuming that it has already
// been tried to resolve, checks if it contains any acceptable response, and if
// it doesn't, performs DNS64 request and the following synthesis. It returns
// the [resultCodeError] if there was an error set to dctx.
func (s *Server) performDNS64(prx *proxy.Proxy, dctx *dnsContext) (rc resultCode) {
pctx := dctx.proxyCtx
req := pctx.Req
dns64Req := s.checkDNS64(req, pctx.Res)
if dns64Req == nil {
return resultCodeSuccess
}
log.Debug("dnsforward: received an empty AAAA response, checking DNS64")
origReq := pctx.Req
origResp := pctx.Res
origUps := pctx.Upstream
pctx.Req = dns64Req
defer func() { pctx.Req = origReq }()
if dctx.err = prx.Resolve(pctx); dctx.err != nil {
return resultCodeError
}
dns64Resp := pctx.Res
pctx.Res = origResp
if dns64Resp != nil && s.synthDNS64(origReq, pctx.Res, dns64Resp) {
log.Debug("dnsforward: synthesized AAAA response for %q", origReq.Question[0].Name)
} else {
pctx.Upstream = origUps
}
return resultCodeSuccess
}
// synthRR synthesizes a DNS64 resource record in compliance with RFC 6147. If
// rr is not an A record, it's returned as is. A records are modified to become
// a DNS64-synthesized AAAA records, and the TTL is set according to the
// original TTL of a record and soaTTL. It returns nil on invalid A records.
func (s *Server) synthRR(rr dns.RR, soaTTL uint32) (result dns.RR) {
aResp, ok := rr.(*dns.A)
if !ok {
return rr
}
addr, err := netutil.IPToAddr(aResp.A, netutil.AddrFamilyIPv4)
if err != nil {
log.Error("dnsforward: bad A record: %s", err)
return nil
}
aaaa := &dns.AAAA{
Hdr: dns.RR_Header{
Name: aResp.Hdr.Name,
Rrtype: dns.TypeAAAA,
Class: aResp.Hdr.Class,
Ttl: mathutil.Min(aResp.Hdr.Ttl, soaTTL),
},
AAAA: s.mapDNS64(addr),
}
return aaaa
}

View File

@@ -15,16 +15,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// maxDNS64SynTTL is the maximum TTL for synthesized DNS64 responses with no SOA
// records in seconds.
//
// If the SOA RR was not delivered with the negative response to the AAAA query,
// then the DNS64 SHOULD use the TTL of the original A RR or 600 seconds,
// whichever is shorter.
//
// See https://datatracker.ietf.org/doc/html/rfc6147#section-5.1.7.
const maxDNS64SynTTL uint32 = 600
// newRR is a helper that creates a new dns.RR with the given name, qtype, ttl // newRR is a helper that creates a new dns.RR with the given name, qtype, ttl
// and value. It fails the test if the qtype is not supported or the type of // and value. It fails the test if the qtype is not supported or the type of
// value doesn't match the qtype. // value doesn't match the qtype.
@@ -273,22 +263,18 @@ func TestServer_HandleDNSRequest_dns64(t *testing.T) {
return resp, nil return resp, nil
}) })
s := createTestServer(t, &filtering.Config{}, ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
UseDNS64: true,
}, localUps)
client := &dns.Client{ client := &dns.Client{
Net: "tcp", Net: "tcp",
Timeout: 1 * time.Second, Timeout: 1 * time.Second,
} }
for _, tc := range testCases { for _, tc := range testCases {
// TODO(e.burkov): It seems [proxy.Proxy] isn't intended to be reused
// right after stop, due to a data race in [proxy.Proxy.Init] method
// when setting an OOB size. As a temporary workaround, recreate the
// whole server for each test case.
s := createTestServer(t, &filtering.Config{}, ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
UseDNS64: true,
}, localUps)
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{newUps(tc.upsAns)} s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{newUps(tc.upsAns)}
startDeferStop(t, s) startDeferStop(t, s)

View File

@@ -80,17 +80,10 @@ type Server struct {
privateNets netutil.SubnetSet privateNets netutil.SubnetSet
localResolvers *proxy.Proxy localResolvers *proxy.Proxy
sysResolvers aghnet.SystemResolvers sysResolvers aghnet.SystemResolvers
recDetector *recursionDetector
// recDetector is a cache for recursive requests. It is used to detect // dns64Prefix is the set of NAT64 prefixes used for DNS64 handling.
// and prevent recursive requests only for private upstreams. dns64Prefs []netip.Prefix
//
// See https://github.com/adguardTeam/adGuardHome/issues/3185#issuecomment-851048135.
recDetector *recursionDetector
// dns64Pref is the NAT64 prefix used for DNS64 response mapping. The major
// part of DNS64 happens inside the [proxy] package, but there still are
// some places where response mapping is needed (e.g. DHCP).
dns64Pref netip.Prefix
// anonymizer masks the client's IP addresses if needed. // anonymizer masks the client's IP addresses if needed.
anonymizer *aghnet.IPMut anonymizer *aghnet.IPMut
@@ -253,8 +246,8 @@ func (s *Server) Resolve(host string) ([]net.IPAddr, error) {
// RDNSExchanger is a resolver for clients' addresses. // RDNSExchanger is a resolver for clients' addresses.
type RDNSExchanger interface { type RDNSExchanger interface {
// Exchange tries to resolve the ip in a suitable way, i.e. either as local // Exchange tries to resolve the ip in a suitable way, e.g. either as
// or as external. // local or as external.
Exchange(ip net.IP) (host string, err error) Exchange(ip net.IP) (host string, err error)
// ResolvesPrivatePTR returns true if the RDNSExchanger is able to // ResolvesPrivatePTR returns true if the RDNSExchanger is able to
@@ -263,13 +256,13 @@ type RDNSExchanger interface {
} }
const ( const (
// ErrRDNSNoData is returned by [RDNSExchanger.Exchange] when the answer // rDNSEmptyAnswerErr is returned by Exchange method when the answer
// section of response is either NODATA or has no PTR records. // section of respond is empty.
ErrRDNSNoData errors.Error = "no ptr data in response" rDNSEmptyAnswerErr errors.Error = "the answer section is empty"
// ErrRDNSFailed is returned by [RDNSExchanger.Exchange] if the received // rDNSNotPTRErr is returned by Exchange method when the response is not
// response is not a NOERROR or NXDOMAIN. // of PTR type.
ErrRDNSFailed errors.Error = "failed to resolve ptr" rDNSNotPTRErr errors.Error = "the response is not a ptr"
) )
// type check // type check
@@ -324,24 +317,17 @@ func (s *Server) Exchange(ip net.IP) (host string, err error) {
return "", err return "", err
} }
// Distinguish between NODATA response and a failed request.
resp := ctx.Res resp := ctx.Res
if resp.Rcode != dns.RcodeSuccess && resp.Rcode != dns.RcodeNameError { if len(resp.Answer) == 0 {
return "", fmt.Errorf( return "", fmt.Errorf("lookup for %q: %w", arpa, rDNSEmptyAnswerErr)
"received %s response: %w",
dns.RcodeToString[resp.Rcode],
ErrRDNSFailed,
)
} }
for _, ans := range resp.Answer { ptr, ok := resp.Answer[0].(*dns.PTR)
ptr, ok := ans.(*dns.PTR) if !ok {
if ok { return "", fmt.Errorf("type checking: %w", rDNSNotPTRErr)
return strings.TrimSuffix(ptr.Ptr, "."), nil
}
} }
return "", ErrRDNSNoData return strings.TrimSuffix(ptr.Ptr, "."), nil
} }
// ResolvesPrivatePTR implements the RDNSExchanger interface for *Server. // ResolvesPrivatePTR implements the RDNSExchanger interface for *Server.
@@ -491,8 +477,6 @@ func (s *Server) Prepare(conf *ServerConfig) (err error) {
return fmt.Errorf("preparing proxy: %w", err) return fmt.Errorf("preparing proxy: %w", err)
} }
s.setupDNS64()
err = s.prepareInternalProxy() err = s.prepareInternalProxy()
if err != nil { if err != nil {
return fmt.Errorf("preparing internal proxy: %w", err) return fmt.Errorf("preparing internal proxy: %w", err)
@@ -509,18 +493,18 @@ func (s *Server) Prepare(conf *ServerConfig) (err error) {
s.registerHandlers() s.registerHandlers()
// TODO(e.burkov): Remove once the local resolvers logic moved to dnsproxy. err = s.setupDNS64()
if err != nil {
return fmt.Errorf("preparing DNS64: %w", err)
}
s.dnsProxy = &proxy.Proxy{Config: proxyConfig}
err = s.setupResolvers(s.conf.LocalPTRResolvers) err = s.setupResolvers(s.conf.LocalPTRResolvers)
if err != nil { if err != nil {
return fmt.Errorf("setting up resolvers: %w", err) return fmt.Errorf("setting up resolvers: %w", err)
} }
if s.conf.UsePrivateRDNS {
proxyConfig.PrivateRDNSUpstreamConfig = s.localResolvers.UpstreamConfig
}
s.dnsProxy = &proxy.Proxy{Config: proxyConfig}
s.recDetector.clear() s.recDetector.clear()
return nil return nil

View File

@@ -89,14 +89,9 @@ func createTestServer(
s.serverLock.Lock() s.serverLock.Lock()
defer s.serverLock.Unlock() defer s.serverLock.Unlock()
// TODO(e.burkov): Try to move it higher.
if localUps != nil { if localUps != nil {
ups := []upstream.Upstream{localUps} s.localResolvers.UpstreamConfig.Upstreams = []upstream.Upstream{localUps}
s.localResolvers.UpstreamConfig.Upstreams = ups
s.conf.UsePrivateRDNS = true s.conf.UsePrivateRDNS = true
s.dnsProxy.PrivateRDNSUpstreamConfig = &proxy.UpstreamConfig{
Upstreams: ups,
}
} }
return s return s
@@ -1221,9 +1216,6 @@ func TestServer_Exchange(t *testing.T) {
errUpstream := aghtest.NewErrorUpstream() errUpstream := aghtest.NewErrorUpstream()
nonPtrUpstream := aghtest.NewBlockUpstream("some-host", true) nonPtrUpstream := aghtest.NewBlockUpstream("some-host", true)
refusingUpstream := aghtest.NewUpstreamMock(func(req *dns.Msg) (resp *dns.Msg, err error) {
return new(dns.Msg).SetRcode(req, dns.RcodeRefused), nil
})
srv := &Server{ srv := &Server{
recDetector: newRecursionDetector(0, 1), recDetector: newRecursionDetector(0, 1),
@@ -1268,21 +1260,15 @@ func TestServer_Exchange(t *testing.T) {
}, { }, {
name: "empty_answer_error", name: "empty_answer_error",
want: "", want: "",
wantErr: ErrRDNSNoData, wantErr: rDNSEmptyAnswerErr,
locUpstream: locUpstream, locUpstream: locUpstream,
req: net.IP{192, 168, 1, 2}, req: net.IP{192, 168, 1, 2},
}, { }, {
name: "invalid_answer", name: "not_ptr_error",
want: "", want: "",
wantErr: ErrRDNSNoData, wantErr: rDNSNotPTRErr,
locUpstream: nonPtrUpstream, locUpstream: nonPtrUpstream,
req: localIP, req: localIP,
}, {
name: "refused",
want: "",
wantErr: ErrRDNSFailed,
locUpstream: refusingUpstream,
req: localIP,
}} }}
for _, tc := range testCases { for _, tc := range testCases {

View File

@@ -22,11 +22,9 @@ func (s *Server) processQueryLogsAndStats(dctx *dnsContext) (rc resultCode) {
shouldLog := true shouldLog := true
msg := pctx.Req msg := pctx.Req
q := msg.Question[0]
host := strings.ToLower(strings.TrimSuffix(q.Name, "."))
// don't log ANY request if refuseAny is enabled // don't log ANY request if refuseAny is enabled
if q.Qtype == dns.TypeANY && s.conf.RefuseAny { if len(msg.Question) >= 1 && msg.Question[0].Qtype == dns.TypeANY && s.conf.RefuseAny {
shouldLog = false shouldLog = false
} }
@@ -43,20 +41,11 @@ func (s *Server) processQueryLogsAndStats(dctx *dnsContext) (rc resultCode) {
// Synchronize access to s.queryLog and s.stats so they won't be suddenly // Synchronize access to s.queryLog and s.stats so they won't be suddenly
// uninitialized while in use. This can happen after proxy server has been // uninitialized while in use. This can happen after proxy server has been
// stopped, but its workers haven't yet exited. // stopped, but its workers haven't yet exited.
if shouldLog && if shouldLog && s.queryLog != nil {
s.queryLog != nil &&
s.queryLog.ShouldLog(host, q.Qtype, q.Qclass) {
s.logQuery(dctx, pctx, elapsed, ip) s.logQuery(dctx, pctx, elapsed, ip)
} else {
log.Debug(
"dnsforward: request %s %s from %s ignored; not logging",
dns.Type(q.Qtype),
host,
ip,
)
} }
if s.stats != nil && s.stats.ShouldCount(host, q.Qtype, q.Qclass) { if s.stats != nil {
s.updateStats(dctx, elapsed, *dctx.result, ip) s.updateStats(dctx, elapsed, *dctx.result, ip)
} }

View File

@@ -16,44 +16,34 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// testQueryLog is a simple [querylog.QueryLog] implementation for tests. // testQueryLog is a simple querylog.QueryLog implementation for tests.
type testQueryLog struct { type testQueryLog struct {
// QueryLog is embedded here simply to make testQueryLog // QueryLog is embedded here simply to make testQueryLog
// a [querylog.QueryLog] without actually implementing all methods. // a querylog.QueryLog without actually implementing all methods.
querylog.QueryLog querylog.QueryLog
lastParams *querylog.AddParams lastParams *querylog.AddParams
} }
// Add implements the [querylog.QueryLog] interface for *testQueryLog. // Add implements the querylog.QueryLog interface for *testQueryLog.
func (l *testQueryLog) Add(p *querylog.AddParams) { func (l *testQueryLog) Add(p *querylog.AddParams) {
l.lastParams = p l.lastParams = p
} }
// ShouldLog implements the [querylog.QueryLog] interface for *testQueryLog. // testStats is a simple stats.Stats implementation for tests.
func (l *testQueryLog) ShouldLog(string, uint16, uint16) bool {
return true
}
// testStats is a simple [stats.Interface] implementation for tests.
type testStats struct { type testStats struct {
// Stats is embedded here simply to make testStats a [stats.Interface] // Stats is embedded here simply to make testStats a stats.Stats without
// without actually implementing all methods. // actually implementing all methods.
stats.Interface stats.Interface
lastEntry stats.Entry lastEntry stats.Entry
} }
// Update implements the [stats.Interface] interface for *testStats. // Update implements the stats.Stats interface for *testStats.
func (l *testStats) Update(e stats.Entry) { func (l *testStats) Update(e stats.Entry) {
l.lastEntry = e l.lastEntry = e
} }
// ShouldCount implements the [stats.Interface] interface for *testStats.
func (l *testStats) ShouldCount(string, uint16, uint16) bool {
return true
}
func TestProcessQueryLogsAndStats(t *testing.T) { func TestProcessQueryLogsAndStats(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string

View File

@@ -1307,7 +1307,9 @@ var blockedServices = []blockedService{{
Rules: []string{ Rules: []string{
"||aus.social^", "||aus.social^",
"||awscommunity.social^", "||awscommunity.social^",
"||cupoftea.social^",
"||cyberplace.social^", "||cyberplace.social^",
"||defcon.social^",
"||det.social^", "||det.social^",
"||fosstodon.org^", "||fosstodon.org^",
"||glasgow.social^", "||glasgow.social^",
@@ -1333,6 +1335,7 @@ var blockedServices = []blockedService{{
"||mastodon.au^", "||mastodon.au^",
"||mastodon.bida.im^", "||mastodon.bida.im^",
"||mastodon.com.tr^", "||mastodon.com.tr^",
"||mastodon.eus^",
"||mastodon.green^", "||mastodon.green^",
"||mastodon.ie^", "||mastodon.ie^",
"||mastodon.iriseden.eu^", "||mastodon.iriseden.eu^",
@@ -1340,15 +1343,13 @@ var blockedServices = []blockedService{{
"||mastodon.nu^", "||mastodon.nu^",
"||mastodon.nz^", "||mastodon.nz^",
"||mastodon.online^", "||mastodon.online^",
"||mastodon.online^",
"||mastodon.scot^", "||mastodon.scot^",
"||mastodon.sdf.org^", "||mastodon.sdf.org^",
"||mastodon.social^", "||mastodon.social^",
"||mastodon.social^",
"||mastodon.top^", "||mastodon.top^",
"||mastodon.uno^", "||mastodon.uno^",
"||mastodon.world^", "||mastodon.world^",
"||mastodon.xyz^", "||mastodon.zaclys.com^",
"||mastodonapp.uk^", "||mastodonapp.uk^",
"||mastodonners.nl^", "||mastodonners.nl^",
"||mastodont.cat^", "||mastodont.cat^",
@@ -1360,10 +1361,9 @@ var blockedServices = []blockedService{{
"||mindly.social^", "||mindly.social^",
"||mstdn.ca^", "||mstdn.ca^",
"||mstdn.jp^", "||mstdn.jp^",
"||mstdn.party^",
"||mstdn.social^", "||mstdn.social^",
"||muenchen.social^", "||muenchen.social^",
"||nerdculture.de^", "||muenster.im^",
"||newsie.social^", "||newsie.social^",
"||noc.social^", "||noc.social^",
"||norden.social^", "||norden.social^",

View File

@@ -67,18 +67,15 @@ func (c *Client) closeUpstreams() (err error) {
type clientSource uint type clientSource uint
// Clients information sources. The order determines the priority. // Client sources. The order determines the priority.
const ( const (
ClientSourceNone clientSource = iota ClientSourceWHOIS clientSource = iota
ClientSourceWHOIS
ClientSourceARP ClientSourceARP
ClientSourceRDNS ClientSourceRDNS
ClientSourceDHCP ClientSourceDHCP
ClientSourceHostsFile ClientSourceHostsFile
ClientSourcePersistent
) )
// type check
var _ fmt.Stringer = clientSource(0) var _ fmt.Stringer = clientSource(0)
// String returns a human-readable name of cs. // String returns a human-readable name of cs.
@@ -99,7 +96,6 @@ func (cs clientSource) String() (s string) {
} }
} }
// type check
var _ encoding.TextMarshaler = clientSource(0) var _ encoding.TextMarshaler = clientSource(0)
// MarshalText implements encoding.TextMarshaler for the clientSource. // MarshalText implements encoding.TextMarshaler for the clientSource.
@@ -336,24 +332,23 @@ func (clients *clientsContainer) onDHCPLeaseChanged(flags int) {
} }
} }
// clientSource checks if client with this IP address already exists and returns // exists checks if client with this IP address already exists.
// the source which updated it last. It returns [ClientSourceNone] if the func (clients *clientsContainer) exists(ip netip.Addr, source clientSource) (ok bool) {
// client doesn't exist.
func (clients *clientsContainer) clientSource(ip netip.Addr) (src clientSource) {
clients.lock.Lock() clients.lock.Lock()
defer clients.lock.Unlock() defer clients.lock.Unlock()
_, ok := clients.findLocked(ip.String()) _, ok = clients.findLocked(ip.String())
if ok { if ok {
return ClientSourcePersistent return true
} }
rc, ok := clients.ipToRC[ip] rc, ok := clients.ipToRC[ip]
if !ok { if !ok {
return ClientSourceNone return false
} }
return rc.Source // Return false if the new source has higher priority.
return source <= rc.Source
} }
func toQueryLogWHOIS(wi *RuntimeClientWHOISInfo) (cw *querylog.ClientWHOIS) { func toQueryLogWHOIS(wi *RuntimeClientWHOISInfo) (cw *querylog.ClientWHOIS) {

View File

@@ -67,9 +67,9 @@ func TestClients(t *testing.T) {
assert.Equal(t, "client2", c.Name) assert.Equal(t, "client2", c.Name)
assert.Equal(t, clients.clientSource(cliNoneIP), ClientSourceNone) assert.False(t, clients.exists(cliNoneIP, ClientSourceHostsFile))
assert.Equal(t, clients.clientSource(cli1IP), ClientSourcePersistent) assert.True(t, clients.exists(cli1IP, ClientSourceHostsFile))
assert.Equal(t, clients.clientSource(cli2IP), ClientSourcePersistent) assert.True(t, clients.exists(cli2IP, ClientSourceHostsFile))
}) })
t.Run("add_fail_name", func(t *testing.T) { t.Run("add_fail_name", func(t *testing.T) {
@@ -127,8 +127,8 @@ func TestClients(t *testing.T) {
}) })
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, clients.clientSource(cliOldIP), ClientSourceNone) assert.False(t, clients.exists(cliOldIP, ClientSourceHostsFile))
assert.Equal(t, clients.clientSource(cliNewIP), ClientSourcePersistent) assert.True(t, clients.exists(cliNewIP, ClientSourceHostsFile))
err = clients.Update("client1", &Client{ err = clients.Update("client1", &Client{
IDs: []string{cliNew}, IDs: []string{cliNew},
@@ -157,7 +157,7 @@ func TestClients(t *testing.T) {
ok := clients.Del("client1-renamed") ok := clients.Del("client1-renamed")
require.True(t, ok) require.True(t, ok)
assert.Equal(t, clients.clientSource(netip.MustParseAddr("1.1.1.2")), ClientSourceNone) assert.False(t, clients.exists(netip.MustParseAddr("1.1.1.2"), ClientSourceHostsFile))
}) })
t.Run("del_fail", func(t *testing.T) { t.Run("del_fail", func(t *testing.T) {
@@ -176,18 +176,18 @@ func TestClients(t *testing.T) {
ok = clients.AddHost(ip, "host3", ClientSourceHostsFile) ok = clients.AddHost(ip, "host3", ClientSourceHostsFile)
assert.True(t, ok) assert.True(t, ok)
assert.Equal(t, clients.clientSource(ip), ClientSourceHostsFile) assert.True(t, clients.exists(ip, ClientSourceHostsFile))
}) })
t.Run("dhcp_replaces_arp", func(t *testing.T) { t.Run("dhcp_replaces_arp", func(t *testing.T) {
ip := netip.MustParseAddr("1.2.3.4") ip := netip.MustParseAddr("1.2.3.4")
ok := clients.AddHost(ip, "from_arp", ClientSourceARP) ok := clients.AddHost(ip, "from_arp", ClientSourceARP)
assert.True(t, ok) assert.True(t, ok)
assert.Equal(t, clients.clientSource(ip), ClientSourceARP) assert.True(t, clients.exists(ip, ClientSourceARP))
ok = clients.AddHost(ip, "from_dhcp", ClientSourceDHCP) ok = clients.AddHost(ip, "from_dhcp", ClientSourceDHCP)
assert.True(t, ok) assert.True(t, ok)
assert.Equal(t, clients.clientSource(ip), ClientSourceDHCP) assert.True(t, clients.exists(ip, ClientSourceDHCP))
}) })
t.Run("addhost_fail", func(t *testing.T) { t.Run("addhost_fail", func(t *testing.T) {

View File

@@ -6,7 +6,6 @@ import (
"net/netip" "net/netip"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"sync" "sync"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghalg"
@@ -113,10 +112,8 @@ type configuration struct {
// An active session is automatically refreshed once a day. // An active session is automatically refreshed once a day.
WebSessionTTLHours uint32 `yaml:"web_session_ttl"` WebSessionTTLHours uint32 `yaml:"web_session_ttl"`
DNS dnsConfig `yaml:"dns"` DNS dnsConfig `yaml:"dns"`
TLS tlsConfigSettings `yaml:"tls"` TLS tlsConfigSettings `yaml:"tls"`
QueryLog queryLogConfig `yaml:"querylog"`
Stats statsConfig `yaml:"statistics"`
// Filters reflects the filters from [filtering.Config]. It's cloned to the // Filters reflects the filters from [filtering.Config]. It's cloned to the
// config used in the filtering module at the startup. Afterwards it's // config used in the filtering module at the startup. Afterwards it's
@@ -150,6 +147,20 @@ type dnsConfig struct {
BindHosts []netip.Addr `yaml:"bind_hosts"` BindHosts []netip.Addr `yaml:"bind_hosts"`
Port int `yaml:"port"` Port int `yaml:"port"`
// StatsInterval is the time interval for flushing statistics to the disk in
// days.
StatsInterval uint32 `yaml:"statistics_interval"`
// QueryLogEnabled defines if the query log is enabled.
QueryLogEnabled bool `yaml:"querylog_enabled"`
// QueryLogFileEnabled defines, if the query log is written to the file.
QueryLogFileEnabled bool `yaml:"querylog_file_enabled"`
// QueryLogInterval is the interval for query log's files rotation.
QueryLogInterval timeutil.Duration `yaml:"querylog_interval"`
// QueryLogMemSize is the number of entries kept in memory before they are
// flushed to disk.
QueryLogMemSize uint32 `yaml:"querylog_size_memory"`
// AnonymizeClientIP defines if clients' IP addresses should be anonymized // AnonymizeClientIP defines if clients' IP addresses should be anonymized
// in query log and statistics. // in query log and statistics.
AnonymizeClientIP bool `yaml:"anonymize_client_ip"` AnonymizeClientIP bool `yaml:"anonymize_client_ip"`
@@ -177,7 +188,7 @@ type dnsConfig struct {
UseDNS64 bool `yaml:"use_dns64"` UseDNS64 bool `yaml:"use_dns64"`
// DNS64Prefixes is the list of NAT64 prefixes to be used for DNS64. // DNS64Prefixes is the list of NAT64 prefixes to be used for DNS64.
DNS64Prefixes []netip.Prefix `yaml:"dns64_prefixes"` DNS64Prefixes []string `yaml:"dns64_prefixes"`
// ServeHTTP3 defines if HTTP/3 is be allowed for incoming requests. // ServeHTTP3 defines if HTTP/3 is be allowed for incoming requests.
// //
@@ -217,37 +228,6 @@ type tlsConfigSettings struct {
dnsforward.TLSConfig `yaml:",inline" json:",inline"` dnsforward.TLSConfig `yaml:",inline" json:",inline"`
} }
type queryLogConfig struct {
// Enabled defines if the query log is enabled.
Enabled bool `yaml:"enabled"`
// FileEnabled defines, if the query log is written to the file.
FileEnabled bool `yaml:"file_enabled"`
// Interval is the interval for query log's files rotation.
Interval timeutil.Duration `yaml:"interval"`
// MemSize is the number of entries kept in memory before they are
// flushed to disk.
MemSize uint32 `yaml:"size_memory"`
// Ignored is the list of host names, which should not be written to
// log.
Ignored []string `yaml:"ignored"`
}
type statsConfig struct {
// Enabled defines if the statistics are enabled.
Enabled bool `yaml:"enabled"`
// Interval is the time interval for flushing statistics to the disk in
// days.
Interval uint32 `yaml:"interval"`
// Ignored is the list of host names, which should not be counted.
Ignored []string `yaml:"ignored"`
}
// config is the global configuration structure. // config is the global configuration structure.
// //
// TODO(a.garipov, e.burkov): This global is awful and must be removed. // TODO(a.garipov, e.burkov): This global is awful and must be removed.
@@ -258,8 +238,13 @@ var config = &configuration{
AuthBlockMin: 15, AuthBlockMin: 15,
WebSessionTTLHours: 30 * 24, WebSessionTTLHours: 30 * 24,
DNS: dnsConfig{ DNS: dnsConfig{
BindHosts: []netip.Addr{netip.IPv4Unspecified()}, BindHosts: []netip.Addr{netip.IPv4Unspecified()},
Port: defaultPortDNS, Port: defaultPortDNS,
StatsInterval: 1,
QueryLogEnabled: true,
QueryLogFileEnabled: true,
QueryLogInterval: timeutil.Duration{Duration: 90 * timeutil.Day},
QueryLogMemSize: 1000,
FilteringConfig: dnsforward.FilteringConfig{ FilteringConfig: dnsforward.FilteringConfig{
ProtectionEnabled: true, // whether or not use any of filtering features ProtectionEnabled: true, // whether or not use any of filtering features
BlockingMode: dnsforward.BlockingModeDefault, BlockingMode: dnsforward.BlockingModeDefault,
@@ -297,18 +282,6 @@ var config = &configuration{
PortDNSOverTLS: defaultPortTLS, // needs to be passed through to dnsproxy PortDNSOverTLS: defaultPortTLS, // needs to be passed through to dnsproxy
PortDNSOverQUIC: defaultPortQUIC, PortDNSOverQUIC: defaultPortQUIC,
}, },
QueryLog: queryLogConfig{
Enabled: true,
FileEnabled: true,
Interval: timeutil.Duration{Duration: 90 * timeutil.Day},
MemSize: 1000,
Ignored: []string{},
},
Stats: statsConfig{
Enabled: true,
Interval: 1,
Ignored: []string{},
},
// NOTE: Keep these parameters in sync with the one put into // NOTE: Keep these parameters in sync with the one put into
// client/src/helpers/filters/filters.js by scripts/vetted-filters. // client/src/helpers/filters/filters.js by scripts/vetted-filters.
// //
@@ -485,24 +458,19 @@ func (c *configuration) write() (err error) {
} }
if Context.stats != nil { if Context.stats != nil {
statsConf := stats.Config{} sdc := stats.DiskConfig{}
Context.stats.WriteDiskConfig(&statsConf) Context.stats.WriteDiskConfig(&sdc)
config.Stats.Interval = statsConf.LimitDays config.DNS.StatsInterval = sdc.Interval
config.Stats.Enabled = statsConf.Enabled
config.Stats.Ignored = statsConf.Ignored.Values()
sort.Strings(config.Stats.Ignored)
} }
if Context.queryLog != nil { if Context.queryLog != nil {
dc := querylog.Config{} dc := querylog.Config{}
Context.queryLog.WriteDiskConfig(&dc) Context.queryLog.WriteDiskConfig(&dc)
config.DNS.QueryLogEnabled = dc.Enabled
config.DNS.QueryLogFileEnabled = dc.FileEnabled
config.DNS.QueryLogInterval = timeutil.Duration{Duration: dc.RotationIvl}
config.DNS.QueryLogMemSize = dc.MemSize
config.DNS.AnonymizeClientIP = dc.AnonymizeClientIP config.DNS.AnonymizeClientIP = dc.AnonymizeClientIP
config.QueryLog.Enabled = dc.Enabled
config.QueryLog.FileEnabled = dc.FileEnabled
config.QueryLog.Interval = timeutil.Duration{Duration: dc.RotationIvl}
config.QueryLog.MemSize = dc.MemSize
config.QueryLog.Ignored = dc.Ignored.Values()
sort.Strings(config.QueryLog.Ignored)
} }
if Context.filters != nil { if Context.filters != nil {

View File

@@ -20,7 +20,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/version" "github.com/AdguardTeam/AdGuardHome/internal/version"
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/quic-go/quic-go/http3" "github.com/lucas-clemente/quic-go/http3"
) )
// getAddrsResponse is the response for /install/get_addresses endpoint. // getAddrsResponse is the response for /install/get_addresses endpoint.

View File

@@ -7,7 +7,6 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg" "github.com/AdguardTeam/AdGuardHome/internal/aghalg"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
@@ -21,7 +20,6 @@ import (
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/ameshkov/dnscrypt/v2" "github.com/ameshkov/dnscrypt/v2"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
) )
@@ -53,18 +51,10 @@ func initDNS() (err error) {
statsConf := stats.Config{ statsConf := stats.Config{
Filename: filepath.Join(baseDir, "stats.db"), Filename: filepath.Join(baseDir, "stats.db"),
LimitDays: config.Stats.Interval, LimitDays: config.DNS.StatsInterval,
ConfigModified: onConfigModified, ConfigModified: onConfigModified,
HTTPRegister: httpRegister, HTTPRegister: httpRegister,
Enabled: config.Stats.Enabled,
} }
set, err := nonDupEmptyHostNames(config.Stats.Ignored)
if err != nil {
return fmt.Errorf("statistics: ignored list: %w", err)
}
statsConf.Ignored = set
Context.stats, err = stats.New(statsConf) Context.stats, err = stats.New(statsConf)
if err != nil { if err != nil {
return fmt.Errorf("init stats: %w", err) return fmt.Errorf("init stats: %w", err)
@@ -76,19 +66,12 @@ func initDNS() (err error) {
HTTPRegister: httpRegister, HTTPRegister: httpRegister,
FindClient: Context.clients.findMultiple, FindClient: Context.clients.findMultiple,
BaseDir: baseDir, BaseDir: baseDir,
RotationIvl: config.DNS.QueryLogInterval.Duration,
MemSize: config.DNS.QueryLogMemSize,
Enabled: config.DNS.QueryLogEnabled,
FileEnabled: config.DNS.QueryLogFileEnabled,
AnonymizeClientIP: config.DNS.AnonymizeClientIP, AnonymizeClientIP: config.DNS.AnonymizeClientIP,
RotationIvl: config.QueryLog.Interval.Duration,
MemSize: config.QueryLog.MemSize,
Enabled: config.QueryLog.Enabled,
FileEnabled: config.QueryLog.FileEnabled,
} }
set, err = nonDupEmptyHostNames(config.QueryLog.Ignored)
if err != nil {
return fmt.Errorf("querylog: ignored list: %w", err)
}
conf.Ignored = set
Context.queryLog = querylog.New(conf) Context.queryLog = querylog.New(conf)
Context.filters, err = filtering.New(config.DNS.DnsfilterConf, nil) Context.filters, err = filtering.New(config.DNS.DnsfilterConf, nil)
@@ -532,27 +515,3 @@ func closeDNSServer() {
log.Debug("all dns modules are closed") log.Debug("all dns modules are closed")
} }
// nonDupEmptyHostNames returns nil and error, if list has duplicate or empty
// host name. Otherwise returns a set, which contains lowercase host names
// without dot at the end, and nil error.
func nonDupEmptyHostNames(list []string) (set *stringutil.Set, err error) {
set = stringutil.NewSet()
for _, v := range list {
host := strings.ToLower(strings.TrimSuffix(v, "."))
// TODO(a.garipov): Think about ignoring empty (".") names in
// the future.
if host == "" {
return nil, errors.Error("host name is empty")
}
if set.Has(host) {
return nil, fmt.Errorf("duplicate host name %q", host)
}
set.Add(host)
}
return set, nil
}

View File

@@ -570,14 +570,21 @@ func startMods() (err error) {
func checkPermissions() { func checkPermissions() {
log.Info("Checking if AdGuard Home has necessary permissions") log.Info("Checking if AdGuard Home has necessary permissions")
if ok, err := aghnet.CanBindPrivilegedPorts(); !ok || err != nil { err := aghnet.AcquirePermissions()
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.") if err != nil {
log.Debug("acquiring necessary permissions: %s", err)
var ok bool
if ok, err = aghnet.CanBindPrivilegedPorts(); !ok || err != nil {
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.")
}
} }
// We should check if AdGuard Home is able to bind to port 53 // We should check if AdGuard Home is able to bind to port 53
err := aghnet.CheckPort("tcp", netip.AddrPortFrom(netutil.IPv4Localhost(), defaultPortDNS)) err = aghnet.CheckPort("tcp", netip.AddrPortFrom(netutil.IPv4Localhost(), defaultPortDNS))
if err != nil { if err != nil {
if errors.Is(err, os.ErrPermission) { if errors.Is(err, os.ErrPermission) {
log.Debug("checking permissions via binding: %v", err)
log.Fatal(`Permission check failed. log.Fatal(`Permission check failed.
AdGuard Home is not allowed to bind to privileged ports (for instance, port 53). AdGuard Home is not allowed to bind to privileged ports (for instance, port 53).

View File

@@ -8,7 +8,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/golibs/cache" "github.com/AdguardTeam/golibs/cache"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
) )
@@ -17,6 +16,10 @@ type RDNS struct {
exchanger dnsforward.RDNSExchanger exchanger dnsforward.RDNSExchanger
clients *clientsContainer clients *clientsContainer
// usePrivate is used to store the state of current private RDNS resolving
// settings and to react to it's changes.
usePrivate uint32
// ipCh used to pass client's IP to rDNS workerLoop. // ipCh used to pass client's IP to rDNS workerLoop.
ipCh chan netip.Addr ipCh chan netip.Addr
@@ -25,21 +28,13 @@ type RDNS struct {
// address will be resolved once again. If the address couldn't be // address will be resolved once again. If the address couldn't be
// resolved, cache prevents further attempts to resolve it for some time. // resolved, cache prevents further attempts to resolve it for some time.
ipCache cache.Cache ipCache cache.Cache
// usePrivate stores the state of current private reverse-DNS resolving
// settings.
usePrivate atomic.Bool
} }
// Default AdGuard Home reverse DNS values. // Default rDNS values.
const ( const (
revDNSCacheSize = 10000 defaultRDNSCacheSize = 10000
defaultRDNSCacheTTL = 1 * 60 * 60
// TODO(e.burkov): Make these values configurable. defaultRDNSIPChSize = 256
revDNSCacheTTL = 24 * 60 * 60
revDNSFailureCacheTTL = 1 * 60 * 60
revDNSQueueSize = 256
) )
// NewRDNS creates and returns initialized RDNS. // NewRDNS creates and returns initialized RDNS.
@@ -53,12 +48,13 @@ func NewRDNS(
clients: clients, clients: clients,
ipCache: cache.New(cache.Config{ ipCache: cache.New(cache.Config{
EnableLRU: true, EnableLRU: true,
MaxCount: revDNSCacheSize, MaxCount: defaultRDNSCacheSize,
}), }),
ipCh: make(chan netip.Addr, revDNSQueueSize), ipCh: make(chan netip.Addr, defaultRDNSIPChSize),
}
if usePrivate {
rDNS.usePrivate = 1
} }
rDNS.usePrivate.Store(usePrivate)
go rDNS.workerLoop() go rDNS.workerLoop()
@@ -72,8 +68,12 @@ func NewRDNS(
// approach since only unresolved locally-served addresses should be removed. // approach since only unresolved locally-served addresses should be removed.
// Implement when improving the cache. // Implement when improving the cache.
func (r *RDNS) ensurePrivateCache() { func (r *RDNS) ensurePrivateCache() {
usePrivate := r.exchanger.ResolvesPrivatePTR() var usePrivate uint32
if r.usePrivate.CompareAndSwap(!usePrivate, usePrivate) { if r.exchanger.ResolvesPrivatePTR() {
usePrivate = 1
}
if atomic.CompareAndSwapUint32(&r.usePrivate, 1-usePrivate, usePrivate) {
r.ipCache.Clear() r.ipCache.Clear()
} }
} }
@@ -84,28 +84,25 @@ func (r *RDNS) isCached(ip netip.Addr) (ok bool) {
ipBytes := ip.AsSlice() ipBytes := ip.AsSlice()
now := uint64(time.Now().Unix()) now := uint64(time.Now().Unix())
if expire := r.ipCache.Get(ipBytes); len(expire) != 0 { if expire := r.ipCache.Get(ipBytes); len(expire) != 0 {
return binary.BigEndian.Uint64(expire) > now if binary.BigEndian.Uint64(expire) > now {
return true
}
} }
// The cache entry either expired or doesn't exist.
ttl := make([]byte, 8)
binary.BigEndian.PutUint64(ttl, now+defaultRDNSCacheTTL)
r.ipCache.Set(ipBytes, ttl)
return false return false
} }
// cache caches the ip address for ttl seconds.
func (r *RDNS) cache(ip netip.Addr, ttl uint64) {
ipData := ip.AsSlice()
ttlData := [8]byte{}
binary.BigEndian.PutUint64(ttlData[:], uint64(time.Now().Unix())+ttl)
r.ipCache.Set(ipData, ttlData[:])
}
// Begin adds the ip to the resolving queue if it is not cached or already // Begin adds the ip to the resolving queue if it is not cached or already
// resolved. // resolved.
func (r *RDNS) Begin(ip netip.Addr) { func (r *RDNS) Begin(ip netip.Addr) {
r.ensurePrivateCache() r.ensurePrivateCache()
if r.isCached(ip) || r.clients.clientSource(ip) > ClientSourceRDNS { if r.isCached(ip) || r.clients.exists(ip, ClientSourceRDNS) {
return return
} }
@@ -123,21 +120,15 @@ func (r *RDNS) workerLoop() {
defer log.OnPanic("rdns") defer log.OnPanic("rdns")
for ip := range r.ipCh { for ip := range r.ipCh {
ttl := uint64(revDNSCacheTTL)
host, err := r.exchanger.Exchange(ip.AsSlice()) host, err := r.exchanger.Exchange(ip.AsSlice())
if err != nil { if err != nil {
log.Debug("rdns: resolving %q: %s", ip, err) log.Debug("rdns: resolving %q: %s", ip, err)
if errors.Is(err, dnsforward.ErrRDNSFailed) {
// Cache failure for a less time. continue
ttl = revDNSFailureCacheTTL } else if host == "" {
} continue
} }
r.cache(ip, ttl) _ = r.clients.AddHost(ip, host, ClientSourceRDNS)
if host != "" {
_ = r.clients.AddHost(ip, host, ClientSourceRDNS)
}
} }
} }

View File

@@ -76,7 +76,7 @@ func TestRDNS_Begin(t *testing.T) {
ipCache := cache.New(cache.Config{ ipCache := cache.New(cache.Config{
EnableLRU: true, EnableLRU: true,
MaxCount: revDNSCacheSize, MaxCount: defaultRDNSCacheSize,
}) })
ttl := make([]byte, binary.Size(uint64(0))) ttl := make([]byte, binary.Size(uint64(0)))
binary.BigEndian.PutUint64(ttl, uint64(time.Now().Add(100*time.Hour).Unix())) binary.BigEndian.PutUint64(ttl, uint64(time.Now().Add(100*time.Hour).Unix()))
@@ -153,7 +153,7 @@ func TestRDNS_ensurePrivateCache(t *testing.T) {
ipCache := cache.New(cache.Config{ ipCache := cache.New(cache.Config{
EnableLRU: true, EnableLRU: true,
MaxCount: revDNSCacheSize, MaxCount: defaultRDNSCacheSize,
}) })
ex := &rDNSExchanger{ ex := &rDNSExchanger{
@@ -200,29 +200,25 @@ func TestRDNS_WorkerLoop(t *testing.T) {
errUpstream := aghtest.NewErrorUpstream() errUpstream := aghtest.NewErrorUpstream()
testCases := []struct { testCases := []struct {
ups upstream.Upstream ups upstream.Upstream
cliIP netip.Addr cliIP netip.Addr
wantLog string wantLog string
name string name string
wantClientSource clientSource
}{{ }{{
ups: locUpstream, ups: locUpstream,
cliIP: localIP, cliIP: localIP,
wantLog: "", wantLog: "",
name: "all_good", name: "all_good",
wantClientSource: ClientSourceRDNS,
}, { }, {
ups: errUpstream, ups: errUpstream,
cliIP: netip.MustParseAddr("192.168.1.2"), cliIP: netip.MustParseAddr("192.168.1.2"),
wantLog: `rdns: resolving "192.168.1.2": test upstream error`, wantLog: `rdns: resolving "192.168.1.2": test upstream error`,
name: "resolve_error", name: "resolve_error",
wantClientSource: ClientSourceNone,
}, { }, {
ups: locUpstream, ups: locUpstream,
cliIP: netip.MustParseAddr("2a00:1450:400c:c06::93"), cliIP: netip.MustParseAddr("2a00:1450:400c:c06::93"),
wantLog: "", wantLog: "",
name: "ipv6_good", name: "ipv6_good",
wantClientSource: ClientSourceRDNS,
}} }}
for _, tc := range testCases { for _, tc := range testCases {
@@ -241,10 +237,6 @@ func TestRDNS_WorkerLoop(t *testing.T) {
}, },
clients: cc, clients: cc,
ipCh: ch, ipCh: ch,
ipCache: cache.New(cache.Config{
EnableLRU: true,
MaxCount: revDNSCacheSize,
}),
} }
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
@@ -261,9 +253,11 @@ func TestRDNS_WorkerLoop(t *testing.T) {
if tc.wantLog != "" { if tc.wantLog != "" {
assert.Contains(t, w.String(), tc.wantLog) assert.Contains(t, w.String(), tc.wantLog)
return
} }
assert.Equal(t, tc.wantClientSource, cc.clientSource(tc.cliIP)) assert.True(t, cc.exists(tc.cliIP, ClientSourceRDNS))
}) })
} }
} }

View File

@@ -22,7 +22,7 @@ import (
) )
// currentSchemaVersion is the current schema version. // currentSchemaVersion is the current schema version.
const currentSchemaVersion = 16 const currentSchemaVersion = 14
// These aliases are provided for convenience. // These aliases are provided for convenience.
type ( type (
@@ -87,8 +87,6 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
upgradeSchema11to12, upgradeSchema11to12,
upgradeSchema12to13, upgradeSchema12to13,
upgradeSchema13to14, upgradeSchema13to14,
upgradeSchema14to15,
upgradeSchema15to16,
} }
n := 0 n := 0
@@ -804,107 +802,6 @@ func upgradeSchema13to14(diskConf yobj) (err error) {
return nil return nil
} }
// upgradeSchema14to15 performs the following changes:
//
// # BEFORE:
// 'dns':
// 'querylog_enabled': true
// 'querylog_file_enabled': true
// 'querylog_interval': '2160h'
// 'querylog_size_memory': 1000
//
// # AFTER:
// 'querylog':
// 'enabled': true
// 'file_enabled': true
// 'interval': '2160h'
// 'size_memory': 1000
// 'ignored': []
func upgradeSchema14to15(diskConf yobj) (err error) {
log.Printf("Upgrade yaml: 14 to 15")
diskConf["schema_version"] = 15
dnsVal, ok := diskConf["dns"]
if !ok {
return nil
}
dns, ok := dnsVal.(yobj)
if !ok {
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
}
type temp struct {
from string
to string
val any
}
replaces := []temp{
{from: "querylog_enabled", to: "enabled", val: true},
{from: "querylog_file_enabled", to: "file_enabled", val: true},
{from: "querylog_interval", to: "interval", val: "2160h"},
{from: "querylog_size_memory", to: "size_memory", val: 1000},
}
qlog := map[string]any{
"ignored": []any{},
}
for _, r := range replaces {
v, has := dns[r.from]
if !has {
v = r.val
}
delete(dns, r.from)
qlog[r.to] = v
}
diskConf["querylog"] = qlog
return nil
}
// upgradeSchema15to16 performs the following changes:
//
// # BEFORE:
// 'dns':
// 'statistics_interval': 1
//
// # AFTER:
// 'statistics':
// 'enabled': true
// 'interval': 1
// 'ignored': []
func upgradeSchema15to16(diskConf yobj) (err error) {
log.Printf("Upgrade yaml: 15 to 16")
diskConf["schema_version"] = 16
dnsVal, ok := diskConf["dns"]
if !ok {
return nil
}
dns, ok := dnsVal.(yobj)
if !ok {
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
}
stats := map[string]any{
"enabled": true,
"interval": 1,
"ignored": []any{},
}
k := "statistics_interval"
v, has := dns[k]
if has {
stats["enabled"] = v != 0
stats["interval"] = v
}
delete(dns, k)
diskConf["statistics"] = stats
return nil
}
// TODO(a.garipov): Replace with log.Output when we port it to our logging // TODO(a.garipov): Replace with log.Output when we port it to our logging
// package. // package.
func funcName() string { func funcName() string {

View File

@@ -640,110 +640,3 @@ func TestUpgradeSchema13to14(t *testing.T) {
}) })
} }
} }
func TestUpgradeSchema14to15(t *testing.T) {
const newSchemaVer = 15
defaultWantObj := yobj{
"querylog": map[string]any{
"enabled": true,
"file_enabled": true,
"interval": "2160h",
"size_memory": 1000,
"ignored": []any{},
},
"dns": map[string]any{},
"schema_version": newSchemaVer,
}
testCases := []struct {
in yobj
want yobj
name string
}{{
in: yobj{
"dns": map[string]any{
"querylog_enabled": true,
"querylog_file_enabled": true,
"querylog_interval": "2160h",
"querylog_size_memory": 1000,
},
},
want: defaultWantObj,
name: "basic",
}, {
in: yobj{
"dns": map[string]any{},
},
want: defaultWantObj,
name: "default_values",
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := upgradeSchema14to15(tc.in)
require.NoError(t, err)
assert.Equal(t, tc.want, tc.in)
})
}
}
func TestUpgradeSchema15to16(t *testing.T) {
const newSchemaVer = 16
defaultWantObj := yobj{
"statistics": map[string]any{
"enabled": true,
"interval": 1,
"ignored": []any{},
},
"dns": map[string]any{},
"schema_version": newSchemaVer,
}
testCases := []struct {
in yobj
want yobj
name string
}{{
in: yobj{
"dns": map[string]any{
"statistics_interval": 1,
},
},
want: defaultWantObj,
name: "basic",
}, {
in: yobj{
"dns": map[string]any{},
},
want: defaultWantObj,
name: "default_values",
}, {
in: yobj{
"dns": map[string]any{
"statistics_interval": 0,
},
},
want: yobj{
"statistics": map[string]any{
"enabled": false,
"interval": 0,
"ignored": []any{},
},
"dns": map[string]any{},
"schema_version": newSchemaVer,
},
name: "stats_disabled",
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := upgradeSchema15to16(tc.in)
require.NoError(t, err)
assert.Equal(t, tc.want, tc.in)
})
}
}

View File

@@ -15,8 +15,8 @@ import (
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil" "github.com/AdguardTeam/golibs/netutil"
"github.com/NYTimes/gziphandler" "github.com/NYTimes/gziphandler"
"github.com/quic-go/quic-go" "github.com/lucas-clemente/quic-go"
"github.com/quic-go/quic-go/http3" "github.com/lucas-clemente/quic-go/http3"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/h2c" "golang.org/x/net/http2/h2c"
) )

View File

@@ -48,11 +48,18 @@ type Config struct {
// Service is the AdGuard Home DNS service. A nil *Service is a valid // Service is the AdGuard Home DNS service. A nil *Service is a valid
// [agh.Service] that does nothing. // [agh.Service] that does nothing.
type Service struct { type Service struct {
// running is an atomic boolean value. Keep it the first value in the
// struct to ensure atomic alignment. 0 means that the service is not
// running, 1 means that it is running.
//
// TODO(a.garipov): Use [atomic.Bool] in Go 1.19 or get rid of it
// completely.
running uint64
proxy *proxy.Proxy proxy *proxy.Proxy
bootstraps []string bootstraps []string
upstreams []string upstreams []string
upsTimeout time.Duration upsTimeout time.Duration
running atomic.Bool
} }
// New returns a new properly initialized *Service. If c is nil, svc is a nil // New returns a new properly initialized *Service. If c is nil, svc is a nil
@@ -166,7 +173,11 @@ func (svc *Service) Start() (err error) {
// TODO(a.garipov): [proxy.Proxy.Start] doesn't actually have any way to // TODO(a.garipov): [proxy.Proxy.Start] doesn't actually have any way to
// tell when all servers are actually up, so at best this is merely an // tell when all servers are actually up, so at best this is merely an
// assumption. // assumption.
svc.running.Store(err == nil) if err != nil {
atomic.StoreUint64(&svc.running, 0)
} else {
atomic.StoreUint64(&svc.running, 1)
}
}() }()
return svc.proxy.Start() return svc.proxy.Start()
@@ -190,7 +201,7 @@ func (svc *Service) Config() (c *Config) {
// TODO(a.garipov): Do we need to get the TCP addresses separately? // TODO(a.garipov): Do we need to get the TCP addresses separately?
var addrs []netip.AddrPort var addrs []netip.AddrPort
if svc.running.Load() { if atomic.LoadUint64(&svc.running) == 1 {
udpAddrs := svc.proxy.Addrs(proxy.ProtoUDP) udpAddrs := svc.proxy.Addrs(proxy.ProtoUDP)
addrs = make([]netip.AddrPort, len(udpAddrs)) addrs = make([]netip.AddrPort, len(udpAddrs))
for i, a := range udpAddrs { for i, a := range udpAddrs {

View File

@@ -26,12 +26,13 @@ func TestService_HandlePatchSettingsDNS(t *testing.T) {
UpstreamTimeout: websvc.JSONDuration(2 * time.Second), UpstreamTimeout: websvc.JSONDuration(2 * time.Second),
} }
var started atomic.Bool // TODO(a.garipov): Use [atomic.Bool] in Go 1.19.
var numStarted uint64
confMgr := newConfigManager() confMgr := newConfigManager()
confMgr.onDNS = func() (s agh.ServiceWithConfig[*dnssvc.Config]) { confMgr.onDNS = func() (s agh.ServiceWithConfig[*dnssvc.Config]) {
return &aghtest.ServiceWithConfig[*dnssvc.Config]{ return &aghtest.ServiceWithConfig[*dnssvc.Config]{
OnStart: func() (err error) { OnStart: func() (err error) {
started.Store(true) atomic.AddUint64(&numStarted, 1)
return nil return nil
}, },
@@ -62,7 +63,7 @@ func TestService_HandlePatchSettingsDNS(t *testing.T) {
err := json.Unmarshal(respBody, resp) err := json.Unmarshal(respBody, resp)
require.NoError(t, err) require.NoError(t, err)
assert.True(t, started.Load()) assert.Equal(t, uint64(1), numStarted)
assert.Equal(t, wantDNS, resp) assert.Equal(t, wantDNS, resp)
assert.Equal(t, wantDNS, resp) assert.Equal(t, wantDNS, resp)
} }

View File

@@ -12,10 +12,11 @@ import (
) )
func TestWaitListener_Accept(t *testing.T) { func TestWaitListener_Accept(t *testing.T) {
var accepted atomic.Bool // TODO(a.garipov): use atomic.Bool in Go 1.19.
var numAcceptCalls uint32
var l net.Listener = &aghtest.Listener{ var l net.Listener = &aghtest.Listener{
OnAccept: func() (conn net.Conn, err error) { OnAccept: func() (conn net.Conn, err error) {
accepted.Store(true) atomic.AddUint32(&numAcceptCalls, 1)
return nil, nil return nil, nil
}, },
@@ -41,5 +42,5 @@ func TestWaitListener_Accept(t *testing.T) {
wg.Wait() wg.Wait()
close(done) close(done)
assert.True(t, accepted.Load()) assert.Equal(t, uint32(1), atomic.LoadUint32(&numAcceptCalls))
} }

View File

@@ -44,9 +44,6 @@ func (l *queryLog) initWeb() {
} }
func (l *queryLog) handleQueryLog(w http.ResponseWriter, r *http.Request) { func (l *queryLog) handleQueryLog(w http.ResponseWriter, r *http.Request) {
l.lock.Lock()
defer l.lock.Unlock()
params, err := l.parseSearchParams(r) params, err := l.parseSearchParams(r)
if err != nil { if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "failed to parse params: %s", err) aghhttp.Error(r, w, http.StatusBadRequest, "failed to parse params: %s", err)

View File

@@ -247,13 +247,3 @@ func (l *queryLog) Add(params *AddParams) {
}() }()
} }
} }
// ShouldLog returns true if request for the host should be logged.
func (l *queryLog) ShouldLog(host string, _, _ uint16) bool {
return !l.isIgnored(host)
}
// isIgnored returns true if the host is in the Ignored list.
func (l *queryLog) isIgnored(host string) bool {
return l.conf.Ignored.Has(host)
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/filtering" "github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxyutil" "github.com/AdguardTeam/dnsproxy/proxyutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/golibs/testutil" "github.com/AdguardTeam/golibs/testutil"
"github.com/AdguardTeam/golibs/timeutil" "github.com/AdguardTeam/golibs/timeutil"
"github.com/miekg/dns" "github.com/miekg/dns"
@@ -250,48 +249,6 @@ func TestQueryLogFileDisabled(t *testing.T) {
assert.Equal(t, "example2.org", ll[1].QHost) assert.Equal(t, "example2.org", ll[1].QHost)
} }
func TestQueryLogShouldLog(t *testing.T) {
const (
ignored1 = "ignor.ed"
ignored2 = "ignored.to"
)
set := stringutil.NewSet(ignored1, ignored2)
l := newQueryLog(Config{
Enabled: true,
RotationIvl: timeutil.Day,
MemSize: 100,
BaseDir: t.TempDir(),
Ignored: set,
})
testCases := []struct {
name string
host string
wantLog bool
}{{
name: "log",
host: "example.com",
wantLog: true,
}, {
name: "no_log_ignored_1",
host: ignored1,
wantLog: false,
}, {
name: "no_log_ignored_2",
host: ignored2,
wantLog: false,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
res := l.ShouldLog(tc.host, dns.TypeA, dns.ClassINET)
assert.Equal(t, tc.wantLog, res)
})
}
}
func addEntry(l *queryLog, host string, answerStr, client net.IP) { func addEntry(l *queryLog, host string, answerStr, client net.IP) {
q := dns.Msg{ q := dns.Msg{
Question: []dns.Question{{ Question: []dns.Question{{

View File

@@ -10,7 +10,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/filtering" "github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/golibs/timeutil" "github.com/AdguardTeam/golibs/timeutil"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@@ -27,9 +26,6 @@ type QueryLog interface {
// WriteDiskConfig - write configuration // WriteDiskConfig - write configuration
WriteDiskConfig(c *Config) WriteDiskConfig(c *Config)
// ShouldLog returns true if request for the host should be logged.
ShouldLog(host string, qType, qClass uint16) bool
} }
// Config is the query log configuration structure. // Config is the query log configuration structure.
@@ -75,10 +71,6 @@ type Config struct {
// AnonymizeClientIP tells if the query log should anonymize clients' IP // AnonymizeClientIP tells if the query log should anonymize clients' IP
// addresses. // addresses.
AnonymizeClientIP bool AnonymizeClientIP bool
// Ignored is the list of host names, which should not be written to
// log.
Ignored *stringutil.Set
} }
// AddParams is the parameters for adding an entry. // AddParams is the parameters for adding an entry.

View File

@@ -155,9 +155,6 @@ func (l *queryLog) periodicRotate() {
// checkAndRotate rotates log files if those are older than the specified // checkAndRotate rotates log files if those are older than the specified
// rotation interval. // rotation interval.
func (l *queryLog) checkAndRotate() { func (l *queryLog) checkAndRotate() {
l.lock.Lock()
defer l.lock.Unlock()
oldest, err := l.readFileFirstTimeValue() oldest, err := l.readFileFirstTimeValue()
if err != nil && !errors.Is(err, os.ErrNotExist) { if err != nil && !errors.Is(err, os.ErrNotExist) {
log.Error("querylog: reading oldest record for rotation: %s", err) log.Error("querylog: reading oldest record for rotation: %s", err)

View File

@@ -263,10 +263,6 @@ func (l *queryLog) readNextEntry(
e = &logEntry{} e = &logEntry{}
decodeLogEntry(e, line) decodeLogEntry(e, line)
if l.isIgnored(e.QHost) {
return nil, ts, nil
}
e.client, err = l.client(e.ClientID, e.IP.String(), cache) e.client, err = l.client(e.ClientID, e.IP.String(), cache)
if err != nil { if err != nil {
log.Error( log.Error(

View File

@@ -5,6 +5,7 @@ package stats
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"sync/atomic"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
@@ -40,11 +41,10 @@ type StatsResp struct {
// handleStats handles requests to the GET /control/stats endpoint. // handleStats handles requests to the GET /control/stats endpoint.
func (s *StatsCtx) handleStats(w http.ResponseWriter, r *http.Request) { func (s *StatsCtx) handleStats(w http.ResponseWriter, r *http.Request) {
s.lock.Lock() limit := atomic.LoadUint32(&s.limitHours)
defer s.lock.Unlock()
start := time.Now() start := time.Now()
resp, ok := s.getData(s.limitHours) resp, ok := s.getData(limit)
log.Debug("stats: prepared data in %v", time.Since(start)) log.Debug("stats: prepared data in %v", time.Since(start))
if !ok { if !ok {
@@ -65,13 +65,7 @@ type configResp struct {
// handleStatsInfo handles requests to the GET /control/stats_info endpoint. // handleStatsInfo handles requests to the GET /control/stats_info endpoint.
func (s *StatsCtx) handleStatsInfo(w http.ResponseWriter, r *http.Request) { func (s *StatsCtx) handleStatsInfo(w http.ResponseWriter, r *http.Request) {
s.lock.Lock() resp := configResp{IntervalDays: atomic.LoadUint32(&s.limitHours) / 24}
defer s.lock.Unlock()
resp := configResp{IntervalDays: s.limitHours / 24}
if !s.enabled {
resp.IntervalDays = 0
}
_ = aghhttp.WriteJSONResponse(w, r, resp) _ = aghhttp.WriteJSONResponse(w, r, resp)
} }

View File

@@ -15,10 +15,16 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/stringutil"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
) )
// DiskConfig is the configuration structure that is stored in file.
type DiskConfig struct {
// Interval is the number of days for which the statistics are collected
// before flushing to the database.
Interval uint32 `yaml:"statistics_interval"`
}
// checkInterval returns true if days is valid to be used as statistics // checkInterval returns true if days is valid to be used as statistics
// retention interval. The valid values are 0, 1, 7, 30 and 90. // retention interval. The valid values are 0, 1, 7, 30 and 90.
func checkInterval(days uint32) (ok bool) { func checkInterval(days uint32) (ok bool) {
@@ -45,12 +51,6 @@ type Config struct {
// LimitDays is the maximum number of days to collect statistics into the // LimitDays is the maximum number of days to collect statistics into the
// current unit. // current unit.
LimitDays uint32 LimitDays uint32
// Enabled tells if the statistics are enabled.
Enabled bool
// Ignored is the list of host names, which should not be counted.
Ignored *stringutil.Set
} }
// Interface is the statistics interface to be used by other packages. // Interface is the statistics interface to be used by other packages.
@@ -68,22 +68,30 @@ type Interface interface {
TopClientsIP(limit uint) []netip.Addr TopClientsIP(limit uint) []netip.Addr
// WriteDiskConfig puts the Interface's configuration to the dc. // WriteDiskConfig puts the Interface's configuration to the dc.
WriteDiskConfig(dc *Config) WriteDiskConfig(dc *DiskConfig)
// ShouldCount returns true if request for the host should be counted.
ShouldCount(host string, qType, qClass uint16) bool
} }
// StatsCtx collects the statistics and flushes it to the database. Its default // StatsCtx collects the statistics and flushes it to the database. Its default
// flushing interval is one hour. // flushing interval is one hour.
//
// TODO(e.burkov): Use atomic.Pointer for accessing db in go1.19.
type StatsCtx struct { type StatsCtx struct {
// limitHours is the maximum number of hours to collect statistics into the
// current unit.
//
// It is of type uint32 to be accessed by atomic. It's arranged at the
// beginning of the structure to keep 64-bit alignment.
limitHours uint32
// currMu protects curr. // currMu protects curr.
currMu *sync.RWMutex currMu *sync.RWMutex
// curr is the actual statistics collection result. // curr is the actual statistics collection result.
curr *unit curr *unit
// dbMu protects db.
dbMu *sync.Mutex
// db is the opened statistics database, if any. // db is the opened statistics database, if any.
db atomic.Pointer[bbolt.DB] db *bbolt.DB
// unitIDGen is the function that generates an identifier for the current // unitIDGen is the function that generates an identifier for the current
// unit. It's here for only testing purposes. // unit. It's here for only testing purposes.
@@ -98,21 +106,6 @@ type StatsCtx struct {
// filename is the name of database file. // filename is the name of database file.
filename string filename string
// lock protects all the fields below.
lock sync.Mutex
// enabled tells if the statistics are enabled.
enabled bool
// limitHours is the maximum number of hours to collect statistics into the
// current unit.
//
// TODO(s.chzhen): Rewrite to use time.Duration.
limitHours uint32
// ignored is the list of host names, which should not be counted.
ignored *stringutil.Set
} }
// New creates s from conf and properly initializes it. Don't use s before // New creates s from conf and properly initializes it. Don't use s before
@@ -121,12 +114,11 @@ func New(conf Config) (s *StatsCtx, err error) {
defer withRecovered(&err) defer withRecovered(&err)
s = &StatsCtx{ s = &StatsCtx{
enabled: conf.Enabled,
currMu: &sync.RWMutex{}, currMu: &sync.RWMutex{},
dbMu: &sync.Mutex{},
filename: conf.Filename, filename: conf.Filename,
configModified: conf.ConfigModified, configModified: conf.ConfigModified,
httpRegister: conf.HTTPRegister, httpRegister: conf.HTTPRegister,
ignored: conf.Ignored,
} }
if s.limitHours = conf.LimitDays * 24; !checkInterval(conf.LimitDays) { if s.limitHours = conf.LimitDays * 24; !checkInterval(conf.LimitDays) {
s.limitHours = 24 s.limitHours = 24
@@ -145,7 +137,7 @@ func New(conf Config) (s *StatsCtx, err error) {
var udb *unitDB var udb *unitDB
id := s.unitIDGen() id := s.unitIDGen()
tx, err := s.db.Load().Begin(true) tx, err := s.db.Begin(true)
if err != nil { if err != nil {
return nil, fmt.Errorf("stats: opening a transaction: %w", err) return nil, fmt.Errorf("stats: opening a transaction: %w", err)
} }
@@ -199,7 +191,7 @@ func (s *StatsCtx) Start() {
func (s *StatsCtx) Close() (err error) { func (s *StatsCtx) Close() (err error) {
defer func() { err = errors.Annotate(err, "stats: closing: %w") }() defer func() { err = errors.Annotate(err, "stats: closing: %w") }()
db := s.db.Swap(nil) db := s.swapDatabase(nil)
if db == nil { if db == nil {
return nil return nil
} }
@@ -228,10 +220,7 @@ func (s *StatsCtx) Close() (err error) {
// Update implements the Interface interface for *StatsCtx. // Update implements the Interface interface for *StatsCtx.
func (s *StatsCtx) Update(e Entry) { func (s *StatsCtx) Update(e Entry) {
s.lock.Lock() if atomic.LoadUint32(&s.limitHours) == 0 {
defer s.lock.Unlock()
if !s.enabled || s.limitHours == 0 {
return return
} }
@@ -259,22 +248,14 @@ func (s *StatsCtx) Update(e Entry) {
} }
// WriteDiskConfig implements the Interface interface for *StatsCtx. // WriteDiskConfig implements the Interface interface for *StatsCtx.
func (s *StatsCtx) WriteDiskConfig(dc *Config) { func (s *StatsCtx) WriteDiskConfig(dc *DiskConfig) {
s.lock.Lock() dc.Interval = atomic.LoadUint32(&s.limitHours) / 24
defer s.lock.Unlock()
dc.LimitDays = s.limitHours / 24
dc.Enabled = s.enabled
dc.Ignored = s.ignored
} }
// TopClientsIP implements the [Interface] interface for *StatsCtx. // TopClientsIP implements the [Interface] interface for *StatsCtx.
func (s *StatsCtx) TopClientsIP(maxCount uint) (ips []netip.Addr) { func (s *StatsCtx) TopClientsIP(maxCount uint) (ips []netip.Addr) {
s.lock.Lock() limit := atomic.LoadUint32(&s.limitHours)
defer s.lock.Unlock() if limit == 0 {
limit := s.limitHours
if !s.enabled || limit == 0 {
return nil return nil
} }
@@ -303,6 +284,25 @@ func (s *StatsCtx) TopClientsIP(maxCount uint) (ips []netip.Addr) {
return ips return ips
} }
// database returns the database if it's opened. It's safe for concurrent use.
func (s *StatsCtx) database() (db *bbolt.DB) {
s.dbMu.Lock()
defer s.dbMu.Unlock()
return s.db
}
// swapDatabase swaps the database with another one and returns it. It's safe
// for concurrent use.
func (s *StatsCtx) swapDatabase(with *bbolt.DB) (old *bbolt.DB) {
s.dbMu.Lock()
defer s.dbMu.Unlock()
old, s.db = s.db, with
return old
}
// deleteOldUnits walks the buckets available to tx and deletes old units. It // deleteOldUnits walks the buckets available to tx and deletes old units. It
// returns the number of deletions performed. // returns the number of deletions performed.
func deleteOldUnits(tx *bbolt.Tx, firstID uint32) (deleted int) { func deleteOldUnits(tx *bbolt.Tx, firstID uint32) (deleted int) {
@@ -358,7 +358,10 @@ func (s *StatsCtx) openDB() (err error) {
// Use defer to unlock the mutex as soon as possible. // Use defer to unlock the mutex as soon as possible.
defer log.Debug("stats: database opened") defer log.Debug("stats: database opened")
s.db.Store(db) s.dbMu.Lock()
defer s.dbMu.Unlock()
s.db = db
return nil return nil
} }
@@ -366,9 +369,6 @@ func (s *StatsCtx) openDB() (err error) {
func (s *StatsCtx) flush() (cont bool, sleepFor time.Duration) { func (s *StatsCtx) flush() (cont bool, sleepFor time.Duration) {
id := s.unitIDGen() id := s.unitIDGen()
s.lock.Lock()
defer s.lock.Unlock()
s.currMu.Lock() s.currMu.Lock()
defer s.currMu.Unlock() defer s.currMu.Unlock()
@@ -377,12 +377,12 @@ func (s *StatsCtx) flush() (cont bool, sleepFor time.Duration) {
return false, 0 return false, 0
} }
limit := s.limitHours limit := atomic.LoadUint32(&s.limitHours)
if limit == 0 || ptr.id == id { if limit == 0 || ptr.id == id {
return true, time.Second return true, time.Second
} }
db := s.db.Load() db := s.database()
if db == nil { if db == nil {
return true, 0 return true, 0
} }
@@ -437,30 +437,21 @@ func (s *StatsCtx) periodicFlush() {
} }
func (s *StatsCtx) setLimit(limitDays int) { func (s *StatsCtx) setLimit(limitDays int) {
s.lock.Lock() atomic.StoreUint32(&s.limitHours, uint32(24*limitDays))
defer s.lock.Unlock() if limitDays == 0 {
if err := s.clear(); err != nil {
if limitDays != 0 { log.Error("stats: %s", err)
s.enabled = true }
s.limitHours = uint32(24 * limitDays)
log.Debug("stats: set limit: %d days", limitDays)
return
} }
s.enabled = false log.Debug("stats: set limit: %d days", limitDays)
log.Debug("stats: disabled")
if err := s.clear(); err != nil {
log.Error("stats: %s", err)
}
} }
// Reset counters and clear database // Reset counters and clear database
func (s *StatsCtx) clear() (err error) { func (s *StatsCtx) clear() (err error) {
defer func() { err = errors.Annotate(err, "clearing: %w") }() defer func() { err = errors.Annotate(err, "clearing: %w") }()
db := s.db.Swap(nil) db := s.swapDatabase(nil)
if db != nil { if db != nil {
var tx *bbolt.Tx var tx *bbolt.Tx
tx, err = db.Begin(true) tx, err = db.Begin(true)
@@ -504,7 +495,7 @@ func (s *StatsCtx) clear() (err error) {
} }
func (s *StatsCtx) loadUnits(limit uint32) (units []*unitDB, firstID uint32) { func (s *StatsCtx) loadUnits(limit uint32) (units []*unitDB, firstID uint32) {
db := s.db.Load() db := s.database()
if db == nil { if db == nil {
return nil, 0 return nil, 0
} }
@@ -556,13 +547,3 @@ func (s *StatsCtx) loadUnits(limit uint32) (units []*unitDB, firstID uint32) {
return units, firstID return units, firstID
} }
// ShouldCount returns true if request for the host should be counted.
func (s *StatsCtx) ShouldCount(host string, _, _ uint16) bool {
return !s.isIgnored(host)
}
// isIgnored returns true if the host is in the Ignored list.
func (s *StatsCtx) isIgnored(host string) bool {
return s.ignored.Has(host)
}

View File

@@ -47,6 +47,8 @@ func TestStats_races(t *testing.T) {
startTime := time.Now() startTime := time.Now()
testutil.CleanupAndRequireSuccess(t, s.Close) testutil.CleanupAndRequireSuccess(t, s.Close)
type signal = struct{}
writeFunc := func(start, fin *sync.WaitGroup, waitCh <-chan unit, i int) { writeFunc := func(start, fin *sync.WaitGroup, waitCh <-chan unit, i int) {
e := Entry{ e := Entry{
Domain: fmt.Sprintf("example-%d.org", i), Domain: fmt.Sprintf("example-%d.org", i),

View File

@@ -53,7 +53,6 @@ func TestStats(t *testing.T) {
conf := stats.Config{ conf := stats.Config{
Filename: filepath.Join(t.TempDir(), "stats.db"), Filename: filepath.Join(t.TempDir(), "stats.db"),
LimitDays: 1, LimitDays: 1,
Enabled: true,
UnitID: constUnitID, UnitID: constUnitID,
HTTPRegister: func(_, url string, handler http.HandlerFunc) { HTTPRegister: func(_, url string, handler http.HandlerFunc) {
handlers[url] = handler handlers[url] = handler
@@ -159,7 +158,6 @@ func TestLargeNumbers(t *testing.T) {
conf := stats.Config{ conf := stats.Config{
Filename: filepath.Join(t.TempDir(), "stats.db"), Filename: filepath.Join(t.TempDir(), "stats.db"),
LimitDays: 1, LimitDays: 1,
Enabled: true,
UnitID: func() (id uint32) { return atomic.LoadUint32(&curHour) }, UnitID: func() (id uint32) { return atomic.LoadUint32(&curHour) },
HTTPRegister: func(_, url string, handler http.HandlerFunc) { handlers[url] = handler }, HTTPRegister: func(_, url string, handler http.HandlerFunc) { handlers[url] = handler },
} }

View File

@@ -10,7 +10,6 @@ import (
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/stringutil"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
) )
@@ -342,13 +341,11 @@ type pairsGetter func(u *unitDB) (pairs []countPair)
// topsCollector collects statistics about highest values from the given *unitDB // topsCollector collects statistics about highest values from the given *unitDB
// slice using pg to retrieve data. // slice using pg to retrieve data.
func topsCollector(units []*unitDB, max int, ignored *stringutil.Set, pg pairsGetter) []map[string]uint64 { func topsCollector(units []*unitDB, max int, pg pairsGetter) []map[string]uint64 {
m := map[string]uint64{} m := map[string]uint64{}
for _, u := range units { for _, u := range units {
for _, cp := range pg(u) { for _, cp := range pg(u) {
if !ignored.Has(cp.Name) { m[cp.Name] += cp.Count
m[cp.Name] += cp.Count
}
} }
} }
a2 := convertMapToSlice(m, max) a2 := convertMapToSlice(m, max)
@@ -411,9 +408,9 @@ func (s *StatsCtx) getData(limit uint32) (StatsResp, bool) {
BlockedFiltering: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RFiltered] }), BlockedFiltering: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RFiltered] }),
ReplacedSafebrowsing: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RSafeBrowsing] }), ReplacedSafebrowsing: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RSafeBrowsing] }),
ReplacedParental: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RParental] }), ReplacedParental: statsCollector(units, firstID, timeUnit, func(u *unitDB) (num uint64) { return u.NResult[RParental] }),
TopQueried: topsCollector(units, maxDomains, s.ignored, func(u *unitDB) (pairs []countPair) { return u.Domains }), TopQueried: topsCollector(units, maxDomains, func(u *unitDB) (pairs []countPair) { return u.Domains }),
TopBlocked: topsCollector(units, maxDomains, s.ignored, func(u *unitDB) (pairs []countPair) { return u.BlockedDomains }), TopBlocked: topsCollector(units, maxDomains, func(u *unitDB) (pairs []countPair) { return u.BlockedDomains }),
TopClients: topsCollector(units, maxClients, nil, func(u *unitDB) (pairs []countPair) { return u.Clients }), TopClients: topsCollector(units, maxClients, func(u *unitDB) (pairs []countPair) { return u.Clients }),
} }
// Total counters: // Total counters:

View File

@@ -1,6 +1,6 @@
module github.com/AdguardTeam/AdGuardHome/internal/tools module github.com/AdguardTeam/AdGuardHome/internal/tools
go 1.19 go 1.18
require ( require (
github.com/fzipp/gocyclo v0.6.0 github.com/fzipp/gocyclo v0.6.0
@@ -8,10 +8,10 @@ require (
github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28
github.com/kisielk/errcheck v1.6.3 github.com/kisielk/errcheck v1.6.3
github.com/kyoh86/looppointer v0.2.1 github.com/kyoh86/looppointer v0.2.1
github.com/securego/gosec/v2 v2.15.0 github.com/securego/gosec/v2 v2.14.0
golang.org/x/tools v0.6.0 golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2
golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30 golang.org/x/vuln v0.0.0-20230130175424-dd534eeddf33
honnef.co/go/tools v0.4.1 honnef.co/go/tools v0.3.3
mvdan.cc/gofumpt v0.4.0 mvdan.cc/gofumpt v0.4.0
mvdan.cc/unparam v0.0.0-20230125043941-70a0ce6e7b95 mvdan.cc/unparam v0.0.0-20230125043941-70a0ce6e7b95
) )
@@ -24,10 +24,10 @@ require (
github.com/kyoh86/nolint v0.0.1 // indirect github.com/kyoh86/nolint v0.0.1 // indirect
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 // indirect
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb // indirect golang.org/x/exp/typeparams v0.0.0-20230131160201-f062dba9d201 // indirect
golang.org/x/mod v0.8.0 // indirect golang.org/x/mod v0.7.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.5.0 // indirect golang.org/x/sys v0.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

View File

@@ -7,7 +7,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0=
github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
@@ -30,14 +29,14 @@ github.com/kyoh86/nolint v0.0.1 h1:GjNxDEkVn2wAxKHtP7iNTrRxytRZ1wXxLV5j4XzGfRU=
github.com/kyoh86/nolint v0.0.1/go.mod h1:1ZiZZ7qqrZ9dZegU96phwVcdQOMKIqRzFJL3ewq9gtI= github.com/kyoh86/nolint v0.0.1/go.mod h1:1ZiZZ7qqrZ9dZegU96phwVcdQOMKIqRzFJL3ewq9gtI=
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA=
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= github.com/onsi/ginkgo/v2 v2.3.1 h1:8SbseP7qM32WcvE6VaN6vfXxv698izmsJ1UQX9ve7T8=
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= github.com/securego/gosec/v2 v2.14.0 h1:U1hfs0oBackChXA72plCYVA4cOlQ4gO+209dHiSNZbI=
github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/securego/gosec/v2 v2.14.0/go.mod h1:Ff03zEi5NwSOfXj9nFpBfhbWTtROCkg9N+9goggrYn4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -54,22 +53,22 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 h1:BEABXpNXLEz0WxtA+6CQIz2xkg80e+1zrhWyMcq8VzE=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb h1:WGs/bGIWYyAY5PVgGGMXqGGCxSJz4fpoUExb/vgqNCU= golang.org/x/exp/typeparams v0.0.0-20230131160201-f062dba9d201 h1:O1QcdQUR9htWjzzsXVFPX+RJ3n1P/u/5bsQR8dbs5BY=
golang.org/x/exp/typeparams v0.0.0-20230213192124-5e25df0256eb/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230131160201-f062dba9d201/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -84,33 +83,35 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 h1:v0FhRDmSCNH/0EurAT6T8KRY4aNuUhz6/WwBMxG+gvQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30 h1:Q4B8LhSjZGto/+P5REBb4N51ec2H4efRqjBIeJ6nv/Y= golang.org/x/vuln v0.0.0-20230130175424-dd534eeddf33 h1:je2aB5nnlseeGvJy5clg6EyC3jjbbCNsRDroC3qQJsA=
golang.org/x/vuln v0.0.0-20230213165600-1a019b0c7f30/go.mod h1:cBP4HMKv0X+x96j8IJWCKk0eqpakBmmHjKGSSC0NaYE= golang.org/x/vuln v0.0.0-20230130175424-dd534eeddf33/go.mod h1:cBP4HMKv0X+x96j8IJWCKk0eqpakBmmHjKGSSC0NaYE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.4.1 h1:HPeloSr0mLOEMOkhT9Au5aeki44kvP6ka3v1xIsM6Zo= honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA=
honnef.co/go/tools v0.4.1/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM=
mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ=
mvdan.cc/unparam v0.0.0-20230125043941-70a0ce6e7b95 h1:n/xhncJPSt0YzfOhnyn41XxUdrWQNgmLBG72FE27Fqw= mvdan.cc/unparam v0.0.0-20230125043941-70a0ce6e7b95 h1:n/xhncJPSt0YzfOhnyn41XxUdrWQNgmLBG72FE27Fqw=

View File

@@ -205,7 +205,7 @@ code from [the repo][companiesrepo].
### Usage ### Usage
```sh ```sh
sh ./scripts/companiesdb/download.sh ( cd scripts/companiesdb && sh ./download.sh )
``` ```
[companiesrepo]: https://github.com/AdguardTeam/companiesdb [companiesrepo]: https://github.com/AdguardTeam/companiesdb

View File

@@ -4,9 +4,11 @@ set -e -f -u -x
# This script syncs companies DB that we bundle with AdGuard Home. The source # This script syncs companies DB that we bundle with AdGuard Home. The source
# for this database is https://github.com/AdguardTeam/companiesdb. # for this database is https://github.com/AdguardTeam/companiesdb.
#
trackers_url='https://raw.githubusercontent.com/AdguardTeam/companiesdb/main/dist/trackers.json'
output='./client/src/helpers/trackers/trackers.json'
readonly trackers_url output
curl -o "$output" -v "$trackers_url" whotracksme='https://raw.githubusercontent.com/AdguardTeam/companiesdb/main/dist/whotracksme.json'
adguard='https://raw.githubusercontent.com/AdguardTeam/companiesdb/main/dist/adguard.json'
base_path='../../client/src/helpers/trackers'
readonly whotracksme adguard base_path
curl -o "${base_path}/whotracksme.json" -v "$whotracksme"
curl -o "${base_path}/adguard.json" -v "$adguard"

View File

@@ -33,19 +33,6 @@ usage() {
exit 2 exit 2
} }
# Function maybe_sudo runs passed command with root privileges if use_sudo isn't
# equal to 0.
#
# TODO(e.burkov): Use everywhere the sudo_cmd isn't quoted.
maybe_sudo() {
if [ "$use_sudo" -eq 0 ]
then
"$@"
else
"$sudo_cmd" "$@"
fi
}
# Function is_command checks if the command exists on the machine. # Function is_command checks if the command exists on the machine.
is_command() { is_command() {
command -v "$1" >/dev/null 2>&1 command -v "$1" >/dev/null 2>&1
@@ -351,18 +338,6 @@ download_wget() {
wget --no-verbose -O "$wget_output" "$1" wget --no-verbose -O "$wget_output" "$1"
} }
# download_fetch uses fetch(1) to download a file. The first argument is the
# URL. The second argument is optional and is the output file.
download_fetch() {
fetch_output="${2:-}"
if [ "$fetch_output" = '' ]
then
fetch -o '-' "$1"
else
fetch -o "$fetch_output" "$1"
fi
}
# Function set_download_func sets the appropriate function for downloading # Function set_download_func sets the appropriate function for downloading
# files. # files.
set_download_func() { set_download_func() {
@@ -373,9 +348,6 @@ set_download_func() {
elif is_command 'wget' elif is_command 'wget'
then then
download_func='download_wget' download_func='download_wget'
elif is_command 'fetch'
then
download_func='download_fetch'
else else
error_exit "either curl or wget is required to install AdGuard Home via this script" error_exit "either curl or wget is required to install AdGuard Home via this script"
fi fi
@@ -567,14 +539,7 @@ handle_existing() {
# Function install_service tries to install AGH as service. # Function install_service tries to install AGH as service.
install_service() { install_service() {
# Installing the service as root is required at least on FreeBSD. if ( cd "$agh_dir" && ./AdGuardHome -s install )
use_sudo='0'
if [ "$os" = 'freebsd' ]
then
use_sudo='1'
fi
if ( cd "$agh_dir" && maybe_sudo ./AdGuardHome -s install )
then then
return 0 return 0
fi fi

View File

@@ -52,7 +52,7 @@ trap not_found EXIT
go_version="$( "${GO:-go}" version )" go_version="$( "${GO:-go}" version )"
readonly go_version readonly go_version
go_min_version='go1.19' go_min_version='go1.18'
go_version_msg=" go_version_msg="
warning: your go version (${go_version}) is different from the recommended minimal one (${go_min_version}). warning: your go version (${go_version}) is different from the recommended minimal one (${go_min_version}).
if you have the version installed, please set the GO environment variable. if you have the version installed, please set the GO environment variable.

View File

@@ -40,7 +40,7 @@ readonly go
count_flags='--count=1' count_flags='--count=1'
cover_flags='--coverprofile=./coverage.txt' cover_flags='--coverprofile=./coverage.txt'
shuffle_flags='--shuffle=on' shuffle_flags='--shuffle=on'
timeout_flags="${TIMEOUT_FLAGS:---timeout=90s}" timeout_flags="${TIMEOUT_FLAGS:---timeout=30s}"
readonly count_flags cover_flags shuffle_flags timeout_flags readonly count_flags cover_flags shuffle_flags timeout_flags
"$go" test "$count_flags" "$cover_flags" "$race_flags" "$shuffle_flags" "$timeout_flags"\ "$go" test "$count_flags" "$cover_flags" "$race_flags" "$shuffle_flags" "$timeout_flags"\