Compare commits
12 Commits
v0.108.0-b
...
6263-custo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b704fb58 | ||
|
|
780d001cef | ||
|
|
820bcf0e23 | ||
|
|
e7ca515630 | ||
|
|
23392d08b1 | ||
|
|
a09cd190c0 | ||
|
|
feb15745d2 | ||
|
|
789060e4d4 | ||
|
|
a700bfb42e | ||
|
|
7669419b59 | ||
|
|
4a9dc1d6c1 | ||
|
|
944e0d7a4b |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'build'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.20.12'
|
||||
'GO_VERSION': '1.20.11'
|
||||
'NODE_VERSION': '16'
|
||||
|
||||
'on':
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'lint'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.20.12'
|
||||
'GO_VERSION': '1.20.11'
|
||||
|
||||
'on':
|
||||
'push':
|
||||
|
||||
135
CHANGELOG.md
135
CHANGELOG.md
@@ -14,128 +14,20 @@ and this project adheres to
|
||||
<!--
|
||||
## [v0.108.0] - TBA
|
||||
|
||||
## [v0.107.44] - 2023-12-20 (APPROX.)
|
||||
## [v0.107.42] - 2023-12-06 (APPROX.)
|
||||
|
||||
See also the [v0.107.44 GitHub milestone][ms-v0.107.44].
|
||||
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
|
||||
|
||||
[ms-v0.107.44]: https://github.com/AdguardTeam/AdGuardHome/milestone/79?closed=1
|
||||
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
|
||||
|
||||
NOTE: Add new changes BELOW THIS COMMENT.
|
||||
-->
|
||||
|
||||
### Added
|
||||
|
||||
- Etc timezones to the timezone list ([#6568]).
|
||||
- The schema version of the configuration file to the output of running
|
||||
`AdGuardHome` (or `AdGuardHome.exe) with `-v --version` command-line options
|
||||
([#6545]).
|
||||
- Ability to disable plain-DNS serving via UI if an encrypted protocol is
|
||||
already used ([#1660]).
|
||||
|
||||
### Changed
|
||||
|
||||
- The bootstrapped upstream addresses now updated according to the TTL of the
|
||||
bootstrap DNS response ([#6321]).
|
||||
- Logging level of timeout errors is now `error` instead of `debug` ([#6574]).
|
||||
- The field `"upstream_mode"` in `POST /control/dns_config` and
|
||||
`GET /control/dns_info` HTTP APIs now accepts `load_balance` value. Check
|
||||
`openapi/CHANGELOG.md` for more details.
|
||||
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 27 to 28.
|
||||
|
||||
- The new property `clients.persistent.*.uid`, which is unique identifier of the
|
||||
persistent client.
|
||||
- The properties `dns.all_servers` and `dns.fastest_addr` were removed, their
|
||||
values migrated to newly added field `dns.upstream_mode` that describes the
|
||||
logic through which upstreams will be used. See also a [Wiki
|
||||
page][wiki-config].
|
||||
|
||||
```yaml
|
||||
# BEFORE:
|
||||
'dns':
|
||||
# …
|
||||
'all_servers': true
|
||||
'fastest_addr': true
|
||||
|
||||
# AFTER:
|
||||
'dns':
|
||||
# …
|
||||
'upstream_mode': 'parallel'
|
||||
```
|
||||
|
||||
To rollback this change, remove the new field `upstream_mode`, set back
|
||||
`dns.all_servers` and `dns.fastest_addr` properties in `dns` section, and
|
||||
change the `schema_version` back to `27`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Panic on using `--no-etc-hosts` flag ([#6644]).
|
||||
- Schedule display in the client settings after creating or updating.
|
||||
- Zero value in `querylog.size_memory` disables logging ([#6570]).
|
||||
- Non-anonymized IP addresses on the dashboard ([#6584]).
|
||||
- Maximum cache TTL requirement when editing minimum cache TTL in the Web UI
|
||||
([#6409]).
|
||||
- Load balancing algorithm stuck on a single server ([#6480]).
|
||||
- Statistics for 7 days displayed as 168 hours on the dashboard.
|
||||
- Pre-filling the Edit static lease window with data ([#6534]).
|
||||
- Names defined in the `/etc/hosts` for a single address family wrongly
|
||||
considered undefined for another family ([#6541]).
|
||||
- Omitted CNAME records in safe search results, which can cause YouTube to not
|
||||
work on iOS ([#6352]).
|
||||
|
||||
[#6321]: https://github.com/AdguardTeam/AdGuardHome/issues/6321
|
||||
[#6352]: https://github.com/AdguardTeam/AdGuardHome/issues/6352
|
||||
[#6409]: https://github.com/AdguardTeam/AdGuardHome/issues/6409
|
||||
[#6480]: https://github.com/AdguardTeam/AdGuardHome/issues/6480
|
||||
[#6534]: https://github.com/AdguardTeam/AdGuardHome/issues/6534
|
||||
[#6541]: https://github.com/AdguardTeam/AdGuardHome/issues/6541
|
||||
[#6545]: https://github.com/AdguardTeam/AdGuardHome/issues/6545
|
||||
[#6568]: https://github.com/AdguardTeam/AdGuardHome/issues/6568
|
||||
[#6570]: https://github.com/AdguardTeam/AdGuardHome/issues/6570
|
||||
[#6574]: https://github.com/AdguardTeam/AdGuardHome/issues/6574
|
||||
[#6584]: https://github.com/AdguardTeam/AdGuardHome/issues/6584
|
||||
[#6644]: https://github.com/AdguardTeam/AdGuardHome/issues/6644
|
||||
|
||||
[wiki-config]: https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration
|
||||
|
||||
<!--
|
||||
NOTE: Add new changes ABOVE THIS COMMENT.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## [v0.107.43] - 2023-12-11
|
||||
|
||||
See also the [v0.107.43 GitHub milestone][ms-v0.107.43].
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incorrect handling of IPv4-in-IPv6 addresses when binding to an unspecified
|
||||
address on some machines ([#6510]).
|
||||
|
||||
[#6510]: https://github.com/AdguardTeam/AdGuardHome/issues/6510
|
||||
|
||||
[ms-v0.107.43]: https://github.com/AdguardTeam/AdGuardHome/milestone/78?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.42] - 2023-12-07
|
||||
|
||||
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
|
||||
|
||||
### Security
|
||||
|
||||
- Go version has been updated to prevent the possibility of exploiting the
|
||||
CVE-2023-39326, CVE-2023-45283, and CVE-2023-45285 Go vulnerabilities fixed in
|
||||
[Go 1.20.12][go-1.20.12].
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to set client's custom DNS cache ([#6263]).
|
||||
- Ability to set client's custom DNS cache ([#6362], [dnsproxy#169]).
|
||||
- Ability to disable plain-DNS serving through configuration file if an
|
||||
encrypted protocol is already enabled ([#1660]).
|
||||
encrypted protocol is already used ([#1660]).
|
||||
- Ability to specify rate limiting settings in the Web UI ([#6369]).
|
||||
|
||||
### Changed
|
||||
@@ -157,13 +49,16 @@ See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
|
||||
|
||||
[#1660]: https://github.com/AdguardTeam/AdGuardHome/issues/1660
|
||||
[#5759]: https://github.com/AdguardTeam/AdGuardHome/issues/5759
|
||||
[#6263]: https://github.com/AdguardTeam/AdGuardHome/issues/6263
|
||||
[#6362]: https://github.com/AdguardTeam/AdGuardHome/issues/6362
|
||||
[#6369]: https://github.com/AdguardTeam/AdGuardHome/issues/6369
|
||||
[#6402]: https://github.com/AdguardTeam/AdGuardHome/issues/6402
|
||||
[#6420]: https://github.com/AdguardTeam/AdGuardHome/issues/6420
|
||||
|
||||
[go-1.20.12]: https://groups.google.com/g/golang-announce/c/iLGK3x6yuNo/m/z6MJ-eB0AQAJ
|
||||
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
|
||||
[dnsproxy#169] https://github.com/AdguardTeam/dnsproxy/issues/169
|
||||
|
||||
<!--
|
||||
NOTE: Add new changes ABOVE THIS COMMENT.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
@@ -2750,13 +2645,11 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
|
||||
|
||||
|
||||
<!--
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.44...HEAD
|
||||
[v0.107.44]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.43...v0.107.44
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.42...HEAD
|
||||
[v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...v0.107.42
|
||||
-->
|
||||
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.43...HEAD
|
||||
[v0.107.43]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.42...v0.107.43
|
||||
[v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...v0.107.42
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...HEAD
|
||||
[v0.107.41]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.40...v0.107.41
|
||||
[v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.39...v0.107.40
|
||||
[v0.107.39]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.38...v0.107.39
|
||||
|
||||
14
README.md
14
README.md
@@ -276,15 +276,6 @@ Open your terminal and execute these commands:
|
||||
git clone https://github.com/AdguardTeam/AdGuardHome
|
||||
cd AdGuardHome
|
||||
make
|
||||
```
|
||||
|
||||
#### <a href="#building-node" id="building-node" name="building-node">Building with Node.js 17 and later</a>
|
||||
|
||||
In order to build AdGuard Home with Node.js 17 and later, specify
|
||||
`--openssl-legacy-provider` option.
|
||||
|
||||
```sh
|
||||
export NODE_OPTIONS=--openssl-legacy-provider
|
||||
```
|
||||
|
||||
**NOTE:** The non-standard `-j` flag is currently not supported, so building
|
||||
@@ -418,7 +409,6 @@ There are three options how you can install an unstable version:
|
||||
```sh
|
||||
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -c edge
|
||||
```
|
||||
|
||||
[wiki-platf]: https://github.com/AdguardTeam/AdGuardHome/wiki/Platforms
|
||||
|
||||
|
||||
@@ -473,6 +463,10 @@ bug or implementing the feature.
|
||||
[@kongfl888](https://github.com/kongfl888) (originally by
|
||||
[@rufengsuixing](https://github.com/rufengsuixing)).
|
||||
|
||||
* [Prometheus exporter for AdGuard
|
||||
Home](https://github.com/ebrianne/adguard-exporter) by
|
||||
[@ebrianne](https://github.com/ebrianne).
|
||||
|
||||
* [Terminal-based, real-time traffic monitoring and statistics for your AdGuard Home
|
||||
instance](https://github.com/Lissy93/AdGuardian-Term) by
|
||||
[@Lissy93](https://github.com/Lissy93)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Make sure to sync any changes with the branch overrides below.
|
||||
'variables':
|
||||
'channel': 'edge'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
|
||||
'stages':
|
||||
- 'Build frontend':
|
||||
@@ -272,7 +272,7 @@
|
||||
# need to build a few of these.
|
||||
'variables':
|
||||
'channel': 'beta'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
# release-vX.Y.Z branches are the branches from which the actual final
|
||||
# release is built.
|
||||
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
|
||||
@@ -287,4 +287,4 @@
|
||||
# are the ones that actually get released.
|
||||
'variables':
|
||||
'channel': 'release'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Make sure to sync any changes with the branch overrides below.
|
||||
'variables':
|
||||
'channel': 'edge'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
'snapcraftChannel': 'edge'
|
||||
|
||||
'stages':
|
||||
@@ -191,7 +191,7 @@
|
||||
# need to build a few of these.
|
||||
'variables':
|
||||
'channel': 'beta'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
'snapcraftChannel': 'beta'
|
||||
# release-vX.Y.Z branches are the branches from which the actual final
|
||||
# release is built.
|
||||
@@ -207,5 +207,5 @@
|
||||
# are the ones that actually get released.
|
||||
'variables':
|
||||
'channel': 'release'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
'snapcraftChannel': 'candidate'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'key': 'AHBRTSPECS'
|
||||
'name': 'AdGuard Home - Build and run tests'
|
||||
'variables':
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.6'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
|
||||
'stages':
|
||||
- 'Tests':
|
||||
|
||||
26
client/package-lock.json
generated
vendored
26
client/package-lock.json
generated
vendored
@@ -11,7 +11,6 @@
|
||||
"@nivo/line": "^0.64.0",
|
||||
"axios": "^0.19.2",
|
||||
"classnames": "^2.2.6",
|
||||
"countries-and-timezones": "^3.6.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"i18next": "^19.6.2",
|
||||
"i18next-browser-languagedetector": "^4.2.0",
|
||||
@@ -38,6 +37,7 @@
|
||||
"redux-actions": "^2.6.5",
|
||||
"redux-form": "^8.3.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"timezones-list": "^3.0.2",
|
||||
"url-polyfill": "^1.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -5596,15 +5596,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/countries-and-timezones": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.6.0.tgz",
|
||||
"integrity": "sha512-8/nHBCs1eKeQ1jnsZVGdqrLYxS8nPcfJn8PnmxdJXWRLZdXsGFR8gnVhRjatGDBjqmPm7H+FtYpBYTPWd0Eiqg==",
|
||||
"engines": {
|
||||
"node": ">=8.x",
|
||||
"npm": ">=5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/create-ecdh": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
|
||||
@@ -18890,6 +18881,11 @@
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/timezones-list": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/timezones-list/-/timezones-list-3.0.2.tgz",
|
||||
"integrity": "sha512-I698hm6Jp/xxkwyTSOr39pZkYKETL8LDJeSIhjxXBfPUAHM5oZNuQ4o9UK3PSkDBOkjATecSOBb3pR1IkIBUsg=="
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
|
||||
@@ -25272,11 +25268,6 @@
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"countries-and-timezones": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.6.0.tgz",
|
||||
"integrity": "sha512-8/nHBCs1eKeQ1jnsZVGdqrLYxS8nPcfJn8PnmxdJXWRLZdXsGFR8gnVhRjatGDBjqmPm7H+FtYpBYTPWd0Eiqg=="
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
|
||||
@@ -35683,6 +35674,11 @@
|
||||
"setimmediate": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"timezones-list": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/timezones-list/-/timezones-list-3.0.2.tgz",
|
||||
"integrity": "sha512-I698hm6Jp/xxkwyTSOr39pZkYKETL8LDJeSIhjxXBfPUAHM5oZNuQ4o9UK3PSkDBOkjATecSOBb3pR1IkIBUsg=="
|
||||
},
|
||||
"tiny-invariant": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
|
||||
|
||||
2
client/package.json
vendored
2
client/package.json
vendored
@@ -16,7 +16,6 @@
|
||||
"@nivo/line": "^0.64.0",
|
||||
"axios": "^0.19.2",
|
||||
"classnames": "^2.2.6",
|
||||
"countries-and-timezones": "^3.6.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"i18next": "^19.6.2",
|
||||
"i18next-browser-languagedetector": "^4.2.0",
|
||||
@@ -43,6 +42,7 @@
|
||||
"redux-actions": "^2.6.5",
|
||||
"redux-form": "^8.3.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"timezones-list": "^3.0.2",
|
||||
"url-polyfill": "^1.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"client_settings": "Налады кліентаў",
|
||||
"example_upstream_reserved": "upstream <0>для канкрэтных даменаў</0>;",
|
||||
"example_multiple_upstreams_reserved": "некалькі DNS-сервераў <0>для канкрэтных даменаў</0>;",
|
||||
"example_upstream_comment": "каментар.",
|
||||
"upstream_parallel": "Ужыць адначасныя запыты да ўсіх сервераў для паскарэння апрацоўкі запыту",
|
||||
"parallel_requests": "Паралельныя запыты",
|
||||
@@ -144,8 +143,6 @@
|
||||
"enforced_save_search": "Ужыты бяспечны пошук",
|
||||
"number_of_dns_query_to_safe_search": "Колькасць запытаў DNS для пошукавых сістэм, для якіх быў ужыты Бяспечны пошук",
|
||||
"average_processing_time": "Сярэдні час апрацоўкі запыту",
|
||||
"average_upstream_response_time": "Сярэдні час водгуку upstream-сервера",
|
||||
"response_time": "Час водгуку",
|
||||
"average_processing_time_hint": "Сярэдні час для апрацоўкі запыту DNS у мілісекундах",
|
||||
"block_domain_use_filters_and_hosts": "Блакаваць дамены з выкарыстаннем фільтраў і файлаў хастоў",
|
||||
"filters_block_toggle_hint": "Вы можаце наладзіць правілы блакавання ў «<a>Фільтрах</a>».",
|
||||
@@ -310,15 +307,6 @@
|
||||
"edns_use_custom_ip": "Выкарыстоўваць указаны IP для DNS",
|
||||
"edns_use_custom_ip_desc": "Дазволіць выкарыстоўваць уласны IP для DNS",
|
||||
"rate_limit_desc": "Абмежаванне на колькасць запытаў у секунду для кожнага кліента (0 — неабмежавана)",
|
||||
"rate_limit_subnet_len_ipv4": "Даўжыня прэфікса падсеткі для адрасоў IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Даўжыня прэфікса падсеткі для адрасоў IPv4, якія выкарыстоўваюцца для абмежавання хуткасці. Значэнне па змаўчанні 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Даўжыня прэфікса падсеткі IPv4 павінна быць ад 0 да 32",
|
||||
"rate_limit_subnet_len_ipv6": "Даўжыня прэфікса падсеткі для адрасоў IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Даўжыня прэфікса падсеткі для адрасоў IPv6, якія выкарыстоўваюцца для абмежавання хуткасці. Значэнне па змаўчанні 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Даўжыня прэфікса падсеткі IPv6 павінна быць ад 0 да 128",
|
||||
"form_enter_rate_limit_subnet_len": "Увядзіце даўжыню прэфікса падсеткі для абмежавання хуткасці",
|
||||
"rate_limit_whitelist": "Белы спіс з абмежаваннем хуткасці",
|
||||
"rate_limit_whitelist_desc": "IP-адрасы выключаны з абмежавання хуткасці",
|
||||
"rate_limit_whitelist_placeholder": "Увядзіце па адным адрасе на радок",
|
||||
"blocking_ipv4_desc": "IP-адрас, што вяртаецца пры блакаванню A-запыту",
|
||||
"blocking_ipv6_desc": "IP-адрас, што вяртаецца пры блакаванню AAAA-запыту",
|
||||
@@ -734,8 +722,5 @@
|
||||
"wednesday_short": "Ср.",
|
||||
"thursday_short": "Чц.",
|
||||
"friday_short": "Пт.",
|
||||
"saturday_short": "Сб.",
|
||||
"upstream_dns_cache_configuration": "Канфігурацыя кэша upstream DNS-сервераў",
|
||||
"enable_upstream_dns_cache": "Ўключыць кэшаванне для карыстацкай канфігурацыі upstream-сервераў гэтага кліента",
|
||||
"dns_cache_size": "Памер кэша DNS, у байтах"
|
||||
"saturday_short": "Сб."
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Středa",
|
||||
"thursday_short": "Čtvrtek",
|
||||
"friday_short": "Pátek",
|
||||
"saturday_short": "Sobota",
|
||||
"upstream_dns_cache_configuration": "Konfigurace mezipaměti odchozího DNS",
|
||||
"enable_upstream_dns_cache": "Povolit ukládání do mezipaměti DNS pro vlastní konfiguraci odchozího připojení tohoto klienta",
|
||||
"dns_cache_size": "Velikost mezipaměti DNS v bajtech"
|
||||
"saturday_short": "Sobota"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Ons",
|
||||
"thursday_short": "Tors",
|
||||
"friday_short": "Fre",
|
||||
"saturday_short": "Lør",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS-cacheopsætning",
|
||||
"enable_upstream_dns_cache": "Aktivér DNS-cachelagring for denne klients tilpassede upstream-opsætning",
|
||||
"dns_cache_size": "DNS-cachestørrelse i bytes"
|
||||
"saturday_short": "Lør"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Mi",
|
||||
"thursday_short": "Do",
|
||||
"friday_short": "Fr",
|
||||
"saturday_short": "Sa",
|
||||
"upstream_dns_cache_configuration": "Konfiguration des Upstream-DNS-Cache",
|
||||
"enable_upstream_dns_cache": "Caching für die benutzerdefinierte Upstream-Server-Konfiguration dieses Clients aktivieren",
|
||||
"dns_cache_size": "Größe des DNS-Cache, in Bytes"
|
||||
"saturday_short": "Sa"
|
||||
}
|
||||
|
||||
@@ -423,9 +423,6 @@
|
||||
"encryption_hostnames": "Hostnames",
|
||||
"encryption_reset": "Are you sure you want to reset encryption settings?",
|
||||
"encryption_warning": "Warning",
|
||||
"encryption_plain_dns_enable": "Enable plain DNS",
|
||||
"encryption_plain_dns_desc": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol",
|
||||
"encryption_plain_dns_error": "To disable plain DNS, enable at least one encrypted DNS protocol",
|
||||
"topline_expiring_certificate": "Your SSL certificate is about to expire. Update <0>Encryption settings</0>.",
|
||||
"topline_expired_certificate": "Your SSL certificate is expired. Update <0>Encryption settings</0>.",
|
||||
"form_error_port_range": "Enter port number in the range of 80-65535",
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Mié.",
|
||||
"thursday_short": "Jue.",
|
||||
"friday_short": "Vie.",
|
||||
"saturday_short": "Sáb.",
|
||||
"upstream_dns_cache_configuration": "Configuración de la caché DNS upstream",
|
||||
"enable_upstream_dns_cache": "Habilitar el almacenamiento en caché de DNS para la configuración personalizada de este cliente",
|
||||
"dns_cache_size": "Tamaño de la caché DNS, en bytes"
|
||||
"saturday_short": "Sáb."
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Ke",
|
||||
"thursday_short": "To",
|
||||
"friday_short": "Pe",
|
||||
"saturday_short": "La",
|
||||
"upstream_dns_cache_configuration": "Ylävirran DNS-välimuistin määritykset",
|
||||
"enable_upstream_dns_cache": "Käytä DNS-välimuistia tämän päätelaitteen mukautetuissa ylävirtamäärityksissä",
|
||||
"dns_cache_size": "DNS-välimuistin koko tavuina"
|
||||
"saturday_short": "La"
|
||||
}
|
||||
|
||||
@@ -310,15 +310,6 @@
|
||||
"edns_use_custom_ip": "Utiliser une IP personnalisée pour EDNS",
|
||||
"edns_use_custom_ip_desc": "Autoriser l'utilisation d'une adresse IP personnalisée pour EDNS",
|
||||
"rate_limit_desc": "Le nombre de requêtes par seconde qu’un seul client est autorisé à faire. Le réglage 0 fait illimité.",
|
||||
"rate_limit_subnet_len_ipv4": "Longueur du préfixe de sous-réseau pour les adresses IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Longueur du préfixe de sous-réseau pour les adresses IPv4 utilisé pour la limitation de vitesse. La valeur par défaut est 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "La longueur du préfixe du sous-réseau IPv4 doit être entre 0 et 32",
|
||||
"rate_limit_subnet_len_ipv6": "Longueur du préfixe de sous-réseau pour les adresses IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Longueur du préfixe de sous-réseau pour les adresses IPv6 utilisé pour la limitation de débit. La valeur par défaut est 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "La longueur du préfixe du sous-réseau IPv6 doit être entre 0 et 128",
|
||||
"form_enter_rate_limit_subnet_len": "Saisissez la longueur du préfixe de sous-réseau pour la limitation de débit",
|
||||
"rate_limit_whitelist": "Liste d'autorisation de limitation de débit",
|
||||
"rate_limit_whitelist_desc": "Adresses IP exclues de la limitation du débit",
|
||||
"rate_limit_whitelist_placeholder": "Saisissez une adresse IP par ligne",
|
||||
"blocking_ipv4_desc": "Adresse IP à renvoyer pour une demande A bloquée",
|
||||
"blocking_ipv6_desc": "Adresse IP à renvoyer pour une demande AAAA bloquée",
|
||||
@@ -734,8 +725,5 @@
|
||||
"wednesday_short": "Mer.",
|
||||
"thursday_short": "Jeu.",
|
||||
"friday_short": "Ven.",
|
||||
"saturday_short": "Sam.",
|
||||
"upstream_dns_cache_configuration": "Configuration du cache DNS en amont",
|
||||
"enable_upstream_dns_cache": "Activer la mise en cache pour la configuration personnalisée du serveur en amont de ce client",
|
||||
"dns_cache_size": "Taille du cache DNS, en bytes"
|
||||
"saturday_short": "Sam."
|
||||
}
|
||||
|
||||
@@ -310,15 +310,6 @@
|
||||
"edns_use_custom_ip": "Koristi prilagođeni IP za EDNS",
|
||||
"edns_use_custom_ip_desc": "Dopusti korištenje prilagođenog IP-a za EDNS",
|
||||
"rate_limit_desc": "Broj zahtjeva u sekundi koji su dopušteni po jednom klijentu. Postavljanje na 0 znači neograničeno.",
|
||||
"rate_limit_subnet_len_ipv4": "Duljina prefiksa podmreže za IPv4 adrese",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Duljina prefiksa podmreže za IPv4 adrese koje se koriste za ograničavanje brzine. Zadana vrijednost je 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Dužina IPv4 prefiksa podmreže trebala bi biti između 0 i 32",
|
||||
"rate_limit_subnet_len_ipv6": "Duljina prefiksa podmreže za IPv6 adrese",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Duljina prefiksa podmreže za IPv6 adrese koje se koriste za ograničavanje brzine. Zadana vrijednost je 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Dužina IPv6 prefiksa podmreže trebala bi biti između 0 i 128",
|
||||
"form_enter_rate_limit_subnet_len": "Unesite duljinu prefiksa podmreže za ograničenje brzine",
|
||||
"rate_limit_whitelist": "Popis dopuštenih za ograničavanje brzine",
|
||||
"rate_limit_whitelist_desc": "IP adrese isključene iz ograničenja brzine",
|
||||
"rate_limit_whitelist_placeholder": "Unesite jednu adresu poslužitelja po retku",
|
||||
"blocking_ipv4_desc": "Povratna IP adresa za blokirane A zahtjeve",
|
||||
"blocking_ipv6_desc": "Povratna IP adresa za blokirane AAAA zahtjeve",
|
||||
@@ -734,8 +725,5 @@
|
||||
"wednesday_short": "Sri",
|
||||
"thursday_short": "Čet",
|
||||
"friday_short": "Pet",
|
||||
"saturday_short": "Sub",
|
||||
"upstream_dns_cache_configuration": "Konfiguracija predmemoriranja upstream DNS poslužitelja",
|
||||
"enable_upstream_dns_cache": "Uključite keširanje za korisničku konfiguraciju upstream servera ovog klijenta",
|
||||
"dns_cache_size": "Veličina DNS predmemorije, u bajtovima"
|
||||
"saturday_short": "Sub"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Szer",
|
||||
"thursday_short": "Csüt",
|
||||
"friday_short": "Pén",
|
||||
"saturday_short": "Szom",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS gyorsítótár konfigurációja",
|
||||
"enable_upstream_dns_cache": "A DNS gyorsítótárazásának engedélyezése az ügyfél egyéni upstream konfigurációjához",
|
||||
"dns_cache_size": "DNS gyorsítótár mérete, bájtokban"
|
||||
"saturday_short": "Szom"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Rab",
|
||||
"thursday_short": "Kam",
|
||||
"friday_short": "Jum",
|
||||
"saturday_short": "Sab",
|
||||
"upstream_dns_cache_configuration": "Konfigurasi cache DNS upstream",
|
||||
"enable_upstream_dns_cache": "Aktifkan cache DNS untuk konfigurasi upstream kustom klien ini",
|
||||
"dns_cache_size": "Ukuran cache DNS, dalam byte"
|
||||
"saturday_short": "Sab"
|
||||
}
|
||||
|
||||
@@ -310,15 +310,6 @@
|
||||
"edns_use_custom_ip": "Usa IP personalizzato per EDNS",
|
||||
"edns_use_custom_ip_desc": "Consentire l'uso di un IP personalizzato per EDNS",
|
||||
"rate_limit_desc": "Il numero di richieste al secondo consentite da un singolo client. Impostare questo valore a 0 rimuove le limitazioni.",
|
||||
"rate_limit_subnet_len_ipv4": "Lunghezza prefisso di sottorete per indirizzi IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Lunghezza prefisso sottorete per indirizzi IPv4 usati per la limitazione della velocità. Valore predefinito 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "La lunghezza del prefisso di sottorete IPv4 deve essere compresa tra 0 e 32",
|
||||
"rate_limit_subnet_len_ipv6": "Lunghezza prefisso di sottorete per indirizzi IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Lunghezza prefisso di sottorete per indirizzi IPv6 usati per la limitazione della velocità. Valore predefinito 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "La lunghezza del prefisso di sottorete IPv6 deve essere compresa tra 0 e 128",
|
||||
"form_enter_rate_limit_subnet_len": "Inserisci lunghezza prefisso di sottorete per limitazione velocità",
|
||||
"rate_limit_whitelist": "Lista consentita per limitazione velocità",
|
||||
"rate_limit_whitelist_desc": "Indirizzi IP esclusi dalla limitazione della velocità",
|
||||
"rate_limit_whitelist_placeholder": "Inserisci un indirizzo IP per riga",
|
||||
"blocking_ipv4_desc": "Indirizzo IP per una richiesta DNS IPv4 bloccata",
|
||||
"blocking_ipv6_desc": "Indirizzo IP restituito per una richiesta DNS IPv6 bloccata",
|
||||
@@ -734,8 +725,5 @@
|
||||
"wednesday_short": "Mer",
|
||||
"thursday_short": "Gio",
|
||||
"friday_short": "Ven",
|
||||
"saturday_short": "Sab",
|
||||
"upstream_dns_cache_configuration": "Configurazione cache DNS upstream",
|
||||
"enable_upstream_dns_cache": "Abilita cache DNS per la configurazione upstream personalizzata del client",
|
||||
"dns_cache_size": "Dimensioni cache DNS (in byte)"
|
||||
"saturday_short": "Sab"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "水",
|
||||
"thursday_short": "木",
|
||||
"friday_short": "金",
|
||||
"saturday_short": "土",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS cache configuration(アップストリームDNSキャッシュの構成)",
|
||||
"enable_upstream_dns_cache": "このクライアントのカスタムアップストリーム構成に対してDNSキャッシュを有効にする",
|
||||
"dns_cache_size": "DNSキャッシュサイズ(バイト単位)"
|
||||
"saturday_short": "土"
|
||||
}
|
||||
|
||||
@@ -310,15 +310,6 @@
|
||||
"edns_use_custom_ip": "EDNS에 사용자 지정 IP 사용",
|
||||
"edns_use_custom_ip_desc": "EDNS에 사용자 지정 IP 사용하도록 허용합니다.",
|
||||
"rate_limit_desc": "단일 클라이언트에서 허용 가능한 초 당 요청 생성 숫자 (0: 무제한)",
|
||||
"rate_limit_subnet_len_ipv4": "IPv4 주소의 서브넷 접두사 길이",
|
||||
"rate_limit_subnet_len_ipv4_desc": "속도 제한에 사용되는 IPv4 주소의 서브넷 접두사 길이입니다. 기본값은 24입니다.",
|
||||
"rate_limit_subnet_len_ipv4_error": "IPv4 서브넷 접두사 길이는 0에서 32 사이여야 합니다.",
|
||||
"rate_limit_subnet_len_ipv6": "IPv6 주소의 서브넷 접두사 길이",
|
||||
"rate_limit_subnet_len_ipv6_desc": "속도 제한에 사용되는 IPv6 주소의 서브넷 접두사 길이입니다. 기본값은 56입니다.",
|
||||
"rate_limit_subnet_len_ipv6_error": "IPv6 서브넷 접두사 길이는 0에서 128 사이여야 합니다.",
|
||||
"form_enter_rate_limit_subnet_len": "속도 제한을 위한 서브넷 접두사 길이를 입력하세요",
|
||||
"rate_limit_whitelist": "속도 제한 허용 목록",
|
||||
"rate_limit_whitelist_desc": "속도 제한에서 제외되는 IP 주소",
|
||||
"rate_limit_whitelist_placeholder": "한 줄에 하나씩 IP 주소를 입력하세요.",
|
||||
"blocking_ipv4_desc": "차단된 A 요청에 대해서 반환할 IP 주소",
|
||||
"blocking_ipv6_desc": "차단된 AAAA 요청에 대해서 반환할 IP 주소",
|
||||
@@ -734,8 +725,5 @@
|
||||
"wednesday_short": "수",
|
||||
"thursday_short": "목",
|
||||
"friday_short": "금",
|
||||
"saturday_short": "토",
|
||||
"upstream_dns_cache_configuration": "업스트림 DNS 캐시 설정",
|
||||
"enable_upstream_dns_cache": "이 클라이언트의 사용자 지정 업스트림 설정에서 DNS 캐싱 사용",
|
||||
"dns_cache_size": "DNS 캐시 크기(바이트)"
|
||||
"saturday_short": "토"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "wo",
|
||||
"thursday_short": "do",
|
||||
"friday_short": "vr",
|
||||
"saturday_short": "za",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS-cacheconfiguratie",
|
||||
"enable_upstream_dns_cache": "DNS-caching inschakelen voor de aangepaste upstream-configuratie van deze client",
|
||||
"dns_cache_size": "DNS-cachegrootte, in bytes"
|
||||
"saturday_short": "za"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Śro",
|
||||
"thursday_short": "Czw",
|
||||
"friday_short": "Pt",
|
||||
"saturday_short": "Sob",
|
||||
"upstream_dns_cache_configuration": "Konfiguracja pamięci podręcznej upstream serwerów DNS",
|
||||
"enable_upstream_dns_cache": "Włącz pamięć podręczną dla niestandardowej konfiguracji serwera upstream tego klienta",
|
||||
"dns_cache_size": "Rozmiar pamięci podręcznej DNS, w bajtach"
|
||||
"saturday_short": "Sob"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Quar",
|
||||
"thursday_short": "Qui",
|
||||
"friday_short": "Sex",
|
||||
"saturday_short": "Sab",
|
||||
"upstream_dns_cache_configuration": "Configuração do cache de DNS upstream",
|
||||
"enable_upstream_dns_cache": "Ativar o armazenamento em cache do DNS para a configuração de upstream personalizada deste cliente",
|
||||
"dns_cache_size": "Tamanho do cache do DNS, em bytes"
|
||||
"saturday_short": "Sab"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Quarta",
|
||||
"thursday_short": "Quinta",
|
||||
"friday_short": "Sexta",
|
||||
"saturday_short": "Sábado",
|
||||
"upstream_dns_cache_configuration": "Configuração da cache do DNS upstream",
|
||||
"enable_upstream_dns_cache": "Ativar o armazenamento em cache do DNS para a configuração de upstream personalizada deste cliente",
|
||||
"dns_cache_size": "Tamanho da cache DNS, em bytes"
|
||||
"saturday_short": "Sábado"
|
||||
}
|
||||
|
||||
@@ -310,15 +310,6 @@
|
||||
"edns_use_custom_ip": "Utilizați IP personalizat pentru EDNS",
|
||||
"edns_use_custom_ip_desc": "Permiteți utilizarea IP-ului personalizat pentru EDNS",
|
||||
"rate_limit_desc": "Numărul de interogări pe secundă permise pe client. Setarea la 0 înseamnă că nu există limită.",
|
||||
"rate_limit_subnet_len_ipv4": "Lungimea prefixului de subrețea pentru adrese IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Lungimea prefixului de subrețea pentru adresele IPv4 utilizate pentru limitarea ratei. Valoarea implicită este 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Lungimea prefixului de subrețea IPv4 ar trebui să fie între 0 și 32",
|
||||
"rate_limit_subnet_len_ipv6": "Lungimea prefixului de subrețea pentru adrese IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Lungimea prefixului de subrețea pentru adresele IPv6 utilizate pentru limitarea ratei. Valoarea implicită este 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Lungimea prefixului de subrețea IPv6 ar trebui să fie între 0 și 128",
|
||||
"form_enter_rate_limit_subnet_len": "Introduceți lungimea prefixului de subrețea pentru limitarea ratei",
|
||||
"rate_limit_whitelist": "Lista permisă pentru limitarea ratei",
|
||||
"rate_limit_whitelist_desc": "Adresele IP excluse de la limitarea ratei",
|
||||
"rate_limit_whitelist_placeholder": "Introduceți o adresă IP per linie",
|
||||
"blocking_ipv4_desc": "Adresa IP de returnat pentru o cerere A de blocare",
|
||||
"blocking_ipv6_desc": "Adresa IP de returnat pentru o cerere AAAA de blocare",
|
||||
@@ -734,8 +725,5 @@
|
||||
"wednesday_short": "mi",
|
||||
"thursday_short": "jo",
|
||||
"friday_short": "vi",
|
||||
"saturday_short": "sa",
|
||||
"upstream_dns_cache_configuration": "Configurarea cache-ului DNS în amonte",
|
||||
"enable_upstream_dns_cache": "Activați memoria cache DNS pentru configurația personalizată în amonte a acestui client",
|
||||
"dns_cache_size": "Dimensiunea cache-ului DNS, în octeți"
|
||||
"saturday_short": "sa"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Ср",
|
||||
"thursday_short": "Чт",
|
||||
"friday_short": "Пт",
|
||||
"saturday_short": "Сб",
|
||||
"upstream_dns_cache_configuration": "Конфигурация кеша upstream DNS-серверов",
|
||||
"enable_upstream_dns_cache": "Включить кеширование для пользовательской конфигурации upstream-серверов этого клиента",
|
||||
"dns_cache_size": "Размер DNS-кеша в байтах"
|
||||
"saturday_short": "Сб"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Str",
|
||||
"thursday_short": "Štr",
|
||||
"friday_short": "Pia",
|
||||
"saturday_short": "Sob",
|
||||
"upstream_dns_cache_configuration": "Konfigurácia cache pamäte DNS pre upstream",
|
||||
"enable_upstream_dns_cache": "Zapnúť ukladanie DNS do cache pamäte pre vlastnú konfiguráciu odosielania tohto klienta",
|
||||
"dns_cache_size": "Veľkosť cache pamäte DNS v bajtoch"
|
||||
"saturday_short": "Sob"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Sre",
|
||||
"thursday_short": "Čet",
|
||||
"friday_short": "Pet",
|
||||
"saturday_short": "Sob",
|
||||
"upstream_dns_cache_configuration": "Nastavitve predpomnilnika gorvodnega DNS",
|
||||
"enable_upstream_dns_cache": "Omogoči predpomnjenje nastavitev gorvodnega DNS po meri tega odjemalca",
|
||||
"dns_cache_size": "Velikost predpomnilnika DNS, v bajtih"
|
||||
"saturday_short": "Sob"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Sre",
|
||||
"thursday_short": "Čet",
|
||||
"friday_short": "Pet",
|
||||
"saturday_short": "Sub",
|
||||
"upstream_dns_cache_configuration": "Konfiguracija keša upstream DNS servera",
|
||||
"enable_upstream_dns_cache": "Uključite keširanje za korisničku konfiguraciju upstream servera ovog klijenta",
|
||||
"dns_cache_size": "Veličina DNS keša, u bajtovima"
|
||||
"saturday_short": "Sub"
|
||||
}
|
||||
|
||||
@@ -310,14 +310,6 @@
|
||||
"edns_use_custom_ip": "Använd anpassad IP för EDNS",
|
||||
"edns_use_custom_ip_desc": "Tillåt att använda anpassad IP för EDNS",
|
||||
"rate_limit_desc": "Antalet förfrågningar per sekund som tillåts per klient. Att sätta den till 0 innebär ingen gräns.",
|
||||
"rate_limit_subnet_len_ipv4": "Prefixlängd för subnät för IPv4-adresser",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Subnätprefixlängd för IPv4-adresser som används för hastighetsbegränsning. Standard är 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "IPv4-subnätets prefixlängd ska vara mellan 0 och 32",
|
||||
"rate_limit_subnet_len_ipv6": "Prefixlängd för subnät för IPv6-adresser",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Subnätprefixlängd för IPv6-adresser som används för hastighetsbegränsning. Standard är 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "IPv6-subnätets prefixlängd ska vara mellan 0 och 128",
|
||||
"form_enter_rate_limit_subnet_len": "Ange subnätprefixlängd för hastighetsbegränsning",
|
||||
"rate_limit_whitelist_desc": "IP-adresser uteslutna från hastighetsbegränsning",
|
||||
"rate_limit_whitelist_placeholder": "Ange en IP-adress per rad",
|
||||
"blocking_ipv4_desc": "IP adress som ska returneras för en blockerad A förfrågan",
|
||||
"blocking_ipv6_desc": "IP adress som ska returneras för en blockerad AAAA förfrågan",
|
||||
@@ -733,8 +725,5 @@
|
||||
"wednesday_short": "Ons",
|
||||
"thursday_short": "Tor",
|
||||
"friday_short": "Fre",
|
||||
"saturday_short": "Lör",
|
||||
"upstream_dns_cache_configuration": "Konfiguration av uppströms DNS-cache",
|
||||
"enable_upstream_dns_cache": "Aktivera DNS-cachelagring för den här klientens anpassade uppströmskonfiguration",
|
||||
"dns_cache_size": "DNS-cachestorlek, i byte"
|
||||
"saturday_short": "Lör"
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
"rate_limit_whitelist_placeholder": "Her satıra bir IP adresi girin",
|
||||
"blocking_ipv4_desc": "Engellenen bir A isteği için geri döndürülecek IP adresi",
|
||||
"blocking_ipv6_desc": "Engellenen bir AAAA isteği için geri döndürülecek IP adresi",
|
||||
"blocking_mode_default": "Varsayılan: Reklam engelleme stili kuralı tarafından engellendiğinde sıfır IP adresiyle (A için 0.0.0.0; :: AAAA için) yanıt verin; /etc/hosts-tarzı kural tarafından engellendiğinde, kuralda belirtilen IP adresiyle yanıt verin",
|
||||
"blocking_mode_default": "Varsayılan: Reklam engelleme tarzı kural tarafından engellendiğinde sıfır IP adresiyle (A için 0.0.0.0; :: AAAA için) yanıt verin; /etc/hosts-tarzı kural tarafından engellendiğinde, kuralda belirtilen IP adresiyle yanıt verin",
|
||||
"blocking_mode_refused": "REFUSED: REFUSED koduyla yanıt verin",
|
||||
"blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN koduyla yanıt verin",
|
||||
"blocking_mode_null_ip": "Boş IP: Sıfır IP adresiyle yanıt verin (A için 0.0.0.0; :: AAAA için)",
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Çar",
|
||||
"thursday_short": "Per",
|
||||
"friday_short": "Cum",
|
||||
"saturday_short": "Cmt",
|
||||
"upstream_dns_cache_configuration": "Üst kaynak DNS önbellek yapılandırması",
|
||||
"enable_upstream_dns_cache": "Bu istemcinin özel üst kaynak yapılandırması için DNS önbelleğe almayı etkinleştir",
|
||||
"dns_cache_size": "DNS önbellek boyutu, bayt cinsinden"
|
||||
"saturday_short": "Cmt"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "СР",
|
||||
"thursday_short": "ЧТ",
|
||||
"friday_short": "ПТ",
|
||||
"saturday_short": "СБ",
|
||||
"upstream_dns_cache_configuration": "Конфігурація кешу upstream DNS-серверів",
|
||||
"enable_upstream_dns_cache": "Увімкнути кешування для користувацької конфігурації upstream-серверів цього клієнта",
|
||||
"dns_cache_size": "Розмір кешу DNS, у байтах"
|
||||
"saturday_short": "СБ"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "Thứ 4",
|
||||
"thursday_short": "Thứ 5",
|
||||
"friday_short": "Thứ 6",
|
||||
"saturday_short": "Thứ 7",
|
||||
"upstream_dns_cache_configuration": "Cấu hình bộ nhớ đệm upstream của các máy chủ DNS",
|
||||
"enable_upstream_dns_cache": "Bật bộ nhớ cache cho cấu hình ngược dòng của máy chủ upstream của khách hàng này",
|
||||
"dns_cache_size": "Kích thước bộ nhớ cache DNS, tính bằng byte"
|
||||
"saturday_short": "Thứ 7"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "周三",
|
||||
"thursday_short": "周四",
|
||||
"friday_short": "周五",
|
||||
"saturday_short": "周六",
|
||||
"upstream_dns_cache_configuration": "上游 DNS 缓存配置",
|
||||
"enable_upstream_dns_cache": "为该客户端的自定义上游配置启用 DNS 缓存",
|
||||
"dns_cache_size": "DNS 缓存大小,单位:字节"
|
||||
"saturday_short": "周六"
|
||||
}
|
||||
|
||||
@@ -734,8 +734,5 @@
|
||||
"wednesday_short": "週三",
|
||||
"thursday_short": "週四",
|
||||
"friday_short": "週五",
|
||||
"saturday_short": "週六",
|
||||
"upstream_dns_cache_configuration": "上游 DNS 快取設定",
|
||||
"enable_upstream_dns_cache": "啟用本用戶端自訂上游配置的 DNS 快取",
|
||||
"dns_cache_size": "DNS 快取大小,單位:位元"
|
||||
"saturday_short": "週六"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import ct from 'countries-and-timezones';
|
||||
import timezones from 'timezones-list';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
@@ -15,8 +15,6 @@ export const Timezone = ({
|
||||
setTimezone(event.target.value);
|
||||
};
|
||||
|
||||
const timezones = ct.getAllTimezones();
|
||||
|
||||
return (
|
||||
<div className="schedule__timezone">
|
||||
<label className="form__label form__label--with-desc mb-2">
|
||||
@@ -32,9 +30,9 @@ export const Timezone = ({
|
||||
{t('schedule_timezone')}
|
||||
</option>
|
||||
{/* TODO: get timezones from backend method when the method is ready */}
|
||||
{Object.keys(timezones).map((zone) => (
|
||||
<option key={zone} value={zone}>
|
||||
{zone} (GMT{timezones[zone].utcOffsetStr})
|
||||
{timezones.map((zone) => (
|
||||
<option key={zone.name} value={zone.tzCode}>
|
||||
{zone.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
import cn from 'classnames';
|
||||
@@ -21,7 +21,10 @@ export const ScheduleForm = ({
|
||||
const onModalOpen = () => setModalOpen(true);
|
||||
const onModalClose = () => setModalOpen(false);
|
||||
|
||||
const filteredScheduleKeys = schedule ? Object.keys(schedule).filter((v) => v !== 'time_zone') : [];
|
||||
const filteredScheduleKeys = useMemo(() => (
|
||||
schedule ? Object.keys(schedule).filter((v) => v !== 'time_zone') : []
|
||||
), [schedule]);
|
||||
|
||||
const scheduleMap = new Map();
|
||||
filteredScheduleKeys.forEach((day) => scheduleMap.set(day, schedule[day]));
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ let Form = (props) => {
|
||||
const [activeTabLabel, setActiveTabLabel] = useState('settings');
|
||||
|
||||
const handleScheduleSubmit = (values) => {
|
||||
change('blocked_services_schedule', { ...values });
|
||||
change('blocked_services_schedule', values);
|
||||
};
|
||||
|
||||
const tabs = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ReactTable from 'react-table';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import { LEASES_TABLE_DEFAULT_PAGE_SIZE, MODAL_TYPE } from '../../../helpers/constants';
|
||||
import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../helpers/constants';
|
||||
import { sortIp } from '../../../helpers/helpers';
|
||||
import { toggleLeaseModal } from '../../../actions';
|
||||
|
||||
@@ -18,10 +18,7 @@ class Leases extends Component {
|
||||
|
||||
convertToStatic = (data) => () => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(toggleLeaseModal({
|
||||
type: MODAL_TYPE.ADD_LEASE,
|
||||
config: data,
|
||||
}));
|
||||
dispatch(toggleLeaseModal(data));
|
||||
}
|
||||
|
||||
makeStatic = ({ row }) => {
|
||||
|
||||
@@ -41,7 +41,7 @@ const Form = ({
|
||||
cache_ttl_max, cache_ttl_min,
|
||||
} = useSelector((state) => state.form[FORM_NAME.CACHE].values, shallowEqual);
|
||||
|
||||
const minExceedsMax = cache_ttl_min > 0 && cache_ttl_max > 0 && cache_ttl_min > cache_ttl_max;
|
||||
const minExceedsMax = cache_ttl_min > cache_ttl_max;
|
||||
|
||||
const handleClearCache = () => {
|
||||
if (window.confirm(t('confirm_dns_cache_clear'))) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
toNumber,
|
||||
} from '../../../helpers/form';
|
||||
import {
|
||||
validateServerName, validateIsSafePort, validatePort, validatePortQuic, validatePortTLS, validatePlainDns,
|
||||
validateServerName, validateIsSafePort, validatePort, validatePortQuic, validatePortTLS,
|
||||
} from '../../../helpers/validators';
|
||||
import i18n from '../../../i18n';
|
||||
import KeyStatus from './KeyStatus';
|
||||
@@ -47,7 +47,6 @@ const clearFields = (change, setTlsConfig, validateTlsConfig, t) => {
|
||||
force_https: false,
|
||||
enabled: false,
|
||||
private_key_saved: false,
|
||||
serve_plain_dns: true,
|
||||
};
|
||||
// eslint-disable-next-line no-alert
|
||||
if (window.confirm(t('encryption_reset'))) {
|
||||
@@ -84,7 +83,6 @@ let Form = (props) => {
|
||||
handleSubmit,
|
||||
handleChange,
|
||||
isEnabled,
|
||||
servePlainDns,
|
||||
certificateChain,
|
||||
privateKey,
|
||||
certificatePath,
|
||||
@@ -111,24 +109,21 @@ let Form = (props) => {
|
||||
privateKeySaved,
|
||||
} = props;
|
||||
|
||||
const isSavingDisabled = () => {
|
||||
const processing = submitting || processingConfig || processingValidate;
|
||||
const isSavingDisabled = invalid
|
||||
|| submitting
|
||||
|| processingConfig
|
||||
|| processingValidate
|
||||
|| !valid_key
|
||||
|| !valid_cert
|
||||
|| !valid_pair;
|
||||
|
||||
if (servePlainDns && !isEnabled) {
|
||||
return invalid || processing;
|
||||
}
|
||||
|
||||
return invalid || processing || !valid_key || !valid_cert || !valid_pair;
|
||||
};
|
||||
|
||||
const isDisabled = isSavingDisabled();
|
||||
const isWarning = valid_key && valid_cert && valid_pair;
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="form__group form__group--settings mb-3">
|
||||
<div className="form__group form__group--settings">
|
||||
<Field
|
||||
name="enabled"
|
||||
type="checkbox"
|
||||
@@ -140,19 +135,6 @@ let Form = (props) => {
|
||||
<div className="form__desc">
|
||||
<Trans>encryption_enable_desc</Trans>
|
||||
</div>
|
||||
<div className="form__group mb-3 mt-5">
|
||||
<Field
|
||||
name="serve_plain_dns"
|
||||
type="checkbox"
|
||||
component={CheckboxField}
|
||||
placeholder={t('encryption_plain_dns_enable')}
|
||||
onChange={handleChange}
|
||||
validate={validatePlainDns}
|
||||
/>
|
||||
</div>
|
||||
<div className="form__desc">
|
||||
<Trans>encryption_plain_dns_desc</Trans>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
<div className="col-12">
|
||||
@@ -245,16 +227,16 @@ let Form = (props) => {
|
||||
<Trans>encryption_doq</Trans>
|
||||
</label>
|
||||
<Field
|
||||
id="port_dns_over_quic"
|
||||
name="port_dns_over_quic"
|
||||
component={renderInputField}
|
||||
type="number"
|
||||
className="form-control"
|
||||
placeholder={t('encryption_doq')}
|
||||
validate={[validatePortQuic]}
|
||||
normalize={toNumber}
|
||||
onChange={handleChange}
|
||||
disabled={!isEnabled}
|
||||
id="port_dns_over_quic"
|
||||
name="port_dns_over_quic"
|
||||
component={renderInputField}
|
||||
type="number"
|
||||
className="form-control"
|
||||
placeholder={t('encryption_doq')}
|
||||
validate={[validatePortQuic]}
|
||||
normalize={toNumber}
|
||||
onChange={handleChange}
|
||||
disabled={!isEnabled}
|
||||
/>
|
||||
<div className="form__desc">
|
||||
<Trans>encryption_doq_desc</Trans>
|
||||
@@ -430,8 +412,8 @@ let Form = (props) => {
|
||||
<div className="btn-list mt-2">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isDisabled}
|
||||
className="btn btn-success btn-standart"
|
||||
disabled={isSavingDisabled}
|
||||
>
|
||||
<Trans>save_config</Trans>
|
||||
</button>
|
||||
@@ -452,7 +434,6 @@ Form.propTypes = {
|
||||
handleSubmit: PropTypes.func.isRequired,
|
||||
handleChange: PropTypes.func,
|
||||
isEnabled: PropTypes.bool.isRequired,
|
||||
servePlainDns: PropTypes.bool.isRequired,
|
||||
certificateChain: PropTypes.string.isRequired,
|
||||
privateKey: PropTypes.string.isRequired,
|
||||
certificatePath: PropTypes.string.isRequired,
|
||||
@@ -486,7 +467,6 @@ const selector = formValueSelector(FORM_NAME.ENCRYPTION);
|
||||
|
||||
Form = connect((state) => {
|
||||
const isEnabled = selector(state, 'enabled');
|
||||
const servePlainDns = selector(state, 'serve_plain_dns');
|
||||
const certificateChain = selector(state, 'certificate_chain');
|
||||
const privateKey = selector(state, 'private_key');
|
||||
const certificatePath = selector(state, 'certificate_path');
|
||||
@@ -496,7 +476,6 @@ Form = connect((state) => {
|
||||
const privateKeySaved = selector(state, 'private_key_saved');
|
||||
return {
|
||||
isEnabled,
|
||||
servePlainDns,
|
||||
certificateChain,
|
||||
privateKey,
|
||||
certificatePath,
|
||||
|
||||
@@ -25,8 +25,7 @@ class Encryption extends Component {
|
||||
|
||||
handleFormChange = debounce((values) => {
|
||||
const submitValues = this.getSubmitValues(values);
|
||||
|
||||
if (submitValues.enabled || submitValues.serve_plain_dns) {
|
||||
if (submitValues.enabled) {
|
||||
this.props.validateTlsConfig(submitValues);
|
||||
}
|
||||
}, DEBOUNCE_TIMEOUT);
|
||||
@@ -86,7 +85,6 @@ class Encryption extends Component {
|
||||
certificate_path,
|
||||
private_key_path,
|
||||
private_key_saved,
|
||||
serve_plain_dns,
|
||||
} = encryption;
|
||||
|
||||
const initialValues = this.getInitialValues({
|
||||
@@ -101,7 +99,6 @@ class Encryption extends Component {
|
||||
certificate_path,
|
||||
private_key_path,
|
||||
private_key_saved,
|
||||
serve_plain_dns,
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -181,7 +181,6 @@ export const MODAL_TYPE = {
|
||||
ADD_REWRITE: 'ADD_REWRITE',
|
||||
EDIT_REWRITE: 'EDIT_REWRITE',
|
||||
EDIT_LEASE: 'EDIT_LEASE',
|
||||
ADD_LEASE: 'ADD_LEASE',
|
||||
};
|
||||
|
||||
export const CLIENT_ID = {
|
||||
@@ -436,7 +435,7 @@ export const SCHEME_TO_PROTOCOL_MAP = {
|
||||
export const DNS_REQUEST_OPTIONS = {
|
||||
PARALLEL: 'parallel',
|
||||
FASTEST_ADDR: 'fastest_addr',
|
||||
LOAD_BALANCING: 'load_balance',
|
||||
LOAD_BALANCING: '',
|
||||
};
|
||||
|
||||
export const DHCP_FORM_NAMES = {
|
||||
|
||||
@@ -142,11 +142,11 @@ export default {
|
||||
"homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"
|
||||
},
|
||||
"awavenue_ads_rule": {
|
||||
"name": "AWAvenue Ads Rule",
|
||||
"adway_default_blocklist": {
|
||||
"name": "AdAway Default Blocklist",
|
||||
"categoryId": "general",
|
||||
"homepage": "https://awavenue.top/",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_53.txt"
|
||||
"homepage": "https://github.com/AdAway/adaway.github.io/",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt"
|
||||
},
|
||||
"curben_phishing_filter": {
|
||||
"name": "Phishing URL Blocklist (PhishTank and OpenPhish)",
|
||||
@@ -190,12 +190,6 @@ export default {
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists#piracy",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_46.txt"
|
||||
},
|
||||
"hagezi_dyndns_blocklist": {
|
||||
"name": "HaGeZi's DynDNS Blocklist",
|
||||
"categoryId": "security",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_54.txt"
|
||||
},
|
||||
"hagezi_encrypted_dns_vpn_tor_proxy_bypass": {
|
||||
"name": "HaGeZi's Encrypted DNS/VPN/TOR/Proxy Bypass",
|
||||
"categoryId": "security",
|
||||
|
||||
@@ -180,7 +180,7 @@ export const CheckboxField = ({
|
||||
{!disabled
|
||||
&& touched
|
||||
&& error
|
||||
&& <div className="form__message form__message--error mt-1"><Trans>{error}</Trans></div>}
|
||||
&& <span className="form__message form__message--error"><Trans>{error}</Trans></span>}
|
||||
</>;
|
||||
|
||||
CheckboxField.propTypes = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"timeUpdated": "2024-01-22T00:10:10.554Z",
|
||||
"timeUpdated": "2023-11-10T12:55:56.663Z",
|
||||
"categories": {
|
||||
"0": "audio_video_player",
|
||||
"1": "comments",
|
||||
@@ -640,8 +640,7 @@
|
||||
"name": "AdChina",
|
||||
"categoryId": 4,
|
||||
"url": "http://www.adchina.com/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
"companyId": "alibaba"
|
||||
},
|
||||
"adcito": {
|
||||
"name": "Adcito",
|
||||
@@ -1322,13 +1321,6 @@
|
||||
"companyId": "adobe",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adobe_experience_league": {
|
||||
"name": "Adobe Experience League",
|
||||
"categoryId": 6,
|
||||
"url": "https://experienceleague.adobe.com/",
|
||||
"companyId": "adobe",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adobe_login": {
|
||||
"name": "Adobe Login",
|
||||
"categoryId": 2,
|
||||
@@ -2289,29 +2281,27 @@
|
||||
"name": "Alibaba",
|
||||
"categoryId": 8,
|
||||
"url": "http://www.alibaba.com/",
|
||||
"companyId": "softbank",
|
||||
"source": "AdGuard"
|
||||
"companyId": "alibaba"
|
||||
},
|
||||
"alibaba_cloud": {
|
||||
"name": "Alibaba Cloud",
|
||||
"categoryId": 10,
|
||||
"url": "https://www.alibabacloud.com/",
|
||||
"companyId": "softbank",
|
||||
"companyId": "alibaba",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"alibaba_ucbrowser": {
|
||||
"name": "UC Browser",
|
||||
"categoryId": 8,
|
||||
"url": "https://ucweb.com/",
|
||||
"companyId": "softbank",
|
||||
"companyId": "alibaba",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"alipay.com": {
|
||||
"name": "Alipay",
|
||||
"categoryId": 2,
|
||||
"url": "https://global.alipay.com/",
|
||||
"companyId": "softbank",
|
||||
"source": "AdGuard"
|
||||
"url": "https://www.alipay.com/",
|
||||
"companyId": "alibaba"
|
||||
},
|
||||
"alivechat": {
|
||||
"name": "AliveChat",
|
||||
@@ -3777,11 +3767,10 @@
|
||||
"companyId": "branica"
|
||||
},
|
||||
"braze": {
|
||||
"name": "Braze, Inc.",
|
||||
"name": "Braze",
|
||||
"categoryId": 6,
|
||||
"url": "https://www.braze.com/",
|
||||
"companyId": "braze",
|
||||
"source": "AdGuard"
|
||||
"companyId": "braze_inc"
|
||||
},
|
||||
"brealtime": {
|
||||
"name": "EMX Digital",
|
||||
@@ -10758,10 +10747,9 @@
|
||||
},
|
||||
"localytics": {
|
||||
"name": "Localytics",
|
||||
"categoryId": 101,
|
||||
"url": "https://uplandsoftware.com/localytics/",
|
||||
"companyId": "upland",
|
||||
"source": "AdGuard"
|
||||
"categoryId": 6,
|
||||
"url": "http://www.localytics.com/",
|
||||
"companyId": "localytics"
|
||||
},
|
||||
"lockerdome": {
|
||||
"name": "LockerDome",
|
||||
@@ -12546,7 +12534,7 @@
|
||||
"name": "Network Time Protocol",
|
||||
"categoryId": 5,
|
||||
"url": "https://ntp.org/",
|
||||
"companyId": "network_time_foundation",
|
||||
"companyId": "ntppool",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"nttcom_online_marketing_solutions": {
|
||||
@@ -15614,11 +15602,10 @@
|
||||
"companyId": "sharecompany"
|
||||
},
|
||||
"sharepoint": {
|
||||
"name": "SharePoint",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.microsoft.com/microsoft-365/sharepoint/collaboration",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
"name": "Microsoft SharePoint",
|
||||
"categoryId": 2,
|
||||
"url": "https://products.office.com/en-us/sharepoint/sharepoint-online-collaboration-software",
|
||||
"companyId": "microsoft"
|
||||
},
|
||||
"sharethis": {
|
||||
"name": "ShareThis",
|
||||
@@ -17075,8 +17062,7 @@
|
||||
"name": "Taobao",
|
||||
"categoryId": 4,
|
||||
"url": "https://world.taobao.com/",
|
||||
"companyId": "softbank",
|
||||
"source": "AdGuard"
|
||||
"companyId": "alibaba"
|
||||
},
|
||||
"tapad": {
|
||||
"name": "Tapad",
|
||||
@@ -20445,7 +20431,6 @@
|
||||
"nedstat.com": "adobe_experience_cloud",
|
||||
"omtrdc.net": "adobe_experience_cloud",
|
||||
"sitestat.com": "adobe_experience_cloud",
|
||||
"adobedc.net": "adobe_experience_league",
|
||||
"adobelogin.com": "adobe_login",
|
||||
"adobetag.com": "adobe_tagmanager",
|
||||
"typekit.com": "adobe_typekit",
|
||||
@@ -21061,7 +21046,6 @@
|
||||
"brandwire.tv": "brandwire.tv",
|
||||
"branica.com": "branica",
|
||||
"appboycdn.com": "braze",
|
||||
"braze.com": "braze",
|
||||
"brealtime.com": "brealtime",
|
||||
"bridgetrack.com": "bridgetrack",
|
||||
"brightcove.com": "brightcove",
|
||||
@@ -22960,7 +22944,6 @@
|
||||
"loadercdn.com": "loadercdn.com",
|
||||
"loadsource.org": "loadsource.org",
|
||||
"web.localytics.com": "localytics",
|
||||
"localytics.com": "localytics",
|
||||
"cdn2.lockerdome.com": "lockerdome",
|
||||
"addtoany.com": "lockerz_share",
|
||||
"pixel.loganmedia.mobi": "logan_media",
|
||||
@@ -23157,11 +23140,8 @@
|
||||
"s-microsoft.com": "microsoft",
|
||||
"trouter.io": "microsoft",
|
||||
"windows.net": "microsoft",
|
||||
"aka.ms": "microsoft",
|
||||
"microsoftazuread-sso.com": "microsoft",
|
||||
"bingapis.com": "microsoft",
|
||||
"msauth.net": "microsoft",
|
||||
"msauthimages.net": "microsoft",
|
||||
"msftauth.net": "microsoft",
|
||||
"msftstatic.com": "microsoft",
|
||||
"msidentity.com": "microsoft",
|
||||
@@ -23252,14 +23232,10 @@
|
||||
"mrpdata.net": "mrpdata",
|
||||
"mrskincash.com": "mrskincash",
|
||||
"a-msedge.net": "msedge",
|
||||
"b-msedge.net": "msedge",
|
||||
"e-msedge.net": "msedge",
|
||||
"k-msedge.net": "msedge",
|
||||
"l-msedge.net": "msedge",
|
||||
"s-msedge.net": "msedge",
|
||||
"spo-msedge.net": "msedge",
|
||||
"t-msedge.net": "msedge",
|
||||
"wac-msedge.net": "msedge",
|
||||
"msn.com": "msn",
|
||||
"s-msn.com": "msn",
|
||||
"musculahq.appspot.com": "muscula",
|
||||
@@ -23525,10 +23501,8 @@
|
||||
"outbrain.com": "outbrain",
|
||||
"outbrainimg.com": "outbrain",
|
||||
"live.com": "outlook",
|
||||
"cloud.microsoft": "outlook",
|
||||
"hotmail.com": "outlook",
|
||||
"outlook.com": "outlook",
|
||||
"svc.ms": "outlook",
|
||||
"overheat.it": "overheat.it",
|
||||
"oewabox.at": "owa",
|
||||
"owneriq.net": "owneriq",
|
||||
@@ -23796,7 +23770,6 @@
|
||||
"rcsmediagroup.it": "rcs.it",
|
||||
"d335luupugsy2.cloudfront.net": "rd_station",
|
||||
"rea-group.com": "rea_group",
|
||||
"reagroupdata.com.au": "rea_group",
|
||||
"reastatic.net": "rea_group",
|
||||
"d12ulf131zb0yj.cloudfront.net": "reachforce",
|
||||
"reachforce.com": "reachforce",
|
||||
@@ -24116,8 +24089,6 @@
|
||||
"quintrics.nl": "sharecompany",
|
||||
"sharecompany.nl": "sharecompany",
|
||||
"sharepointonline.com": "sharepoint",
|
||||
"onmicrosoft.com": "sharepoint",
|
||||
"sharepoint.com": "sharepoint",
|
||||
"sharethis.com": "sharethis",
|
||||
"shareth.ru": "sharethrough",
|
||||
"sharethrough.com": "sharethrough",
|
||||
|
||||
@@ -389,18 +389,3 @@ export const validateIPv6Subnet = (value) => {
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {undefined|string}
|
||||
* @param value
|
||||
* @param allValues
|
||||
*/
|
||||
export const validatePlainDns = (value, allValues) => {
|
||||
const { enabled } = allValues;
|
||||
|
||||
if (!enabled && !value) {
|
||||
return 'encryption_plain_dns_error';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -128,8 +128,7 @@ const dhcp = handleActions(
|
||||
const newState = {
|
||||
...state,
|
||||
isModalOpen: !state.isModalOpen,
|
||||
modalType: payload?.type || '',
|
||||
leaseModalConfig: payload?.config,
|
||||
leaseModalConfig: payload,
|
||||
};
|
||||
return newState;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { handleActions } from 'redux-actions';
|
||||
|
||||
import * as actions from '../actions/dnsConfig';
|
||||
import { ALL_INTERFACES_IP, BLOCKING_MODES, DNS_REQUEST_OPTIONS } from '../helpers/constants';
|
||||
import { ALL_INTERFACES_IP, BLOCKING_MODES } from '../helpers/constants';
|
||||
|
||||
const DEFAULT_BLOCKING_IPV4 = ALL_INTERFACES_IP;
|
||||
const DEFAULT_BLOCKING_IPV6 = '::';
|
||||
@@ -15,7 +15,6 @@ const dnsConfig = handleActions(
|
||||
blocking_ipv4,
|
||||
blocking_ipv6,
|
||||
upstream_dns,
|
||||
upstream_mode,
|
||||
fallback_dns,
|
||||
bootstrap_dns,
|
||||
local_ptr_upstreams,
|
||||
@@ -34,7 +33,6 @@ const dnsConfig = handleActions(
|
||||
local_ptr_upstreams: (local_ptr_upstreams && local_ptr_upstreams.join('\n')) || '',
|
||||
ratelimit_whitelist: (ratelimit_whitelist && ratelimit_whitelist.join('\n')) || '',
|
||||
processingGetConfig: false,
|
||||
upstream_mode: upstream_mode === '' ? DNS_REQUEST_OPTIONS.LOAD_BALANCING : upstream_mode,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ const encryption = handleActions({
|
||||
processingConfig: false,
|
||||
processingValidate: false,
|
||||
enabled: false,
|
||||
serve_plain_dns: false,
|
||||
dns_names: null,
|
||||
force_https: false,
|
||||
issuer: '',
|
||||
|
||||
38
go.mod
38
go.mod
@@ -3,13 +3,12 @@ module github.com/AdguardTeam/AdGuardHome
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.63.1
|
||||
github.com/AdguardTeam/golibs v0.19.0
|
||||
github.com/AdguardTeam/dnsproxy v0.59.1
|
||||
github.com/AdguardTeam/golibs v0.17.2
|
||||
github.com/AdguardTeam/urlfilter v0.17.3
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
|
||||
github.com/digineo/go-ipset/v2 v2.2.1
|
||||
github.com/dimfeld/httptreemux/v5 v5.5.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
@@ -17,8 +16,8 @@ require (
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/renameio/v2 v2.0.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||
github.com/google/uuid v1.4.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c
|
||||
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86
|
||||
github.com/kardianos/service v1.2.2
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
||||
@@ -27,18 +26,18 @@ require (
|
||||
// TODO(a.garipov): This package is deprecated; find a new one or use our
|
||||
// own code for that. Perhaps, use gopacket.
|
||||
github.com/mdlayher/raw v0.1.0
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/miekg/dns v1.1.56
|
||||
github.com/quic-go/quic-go v0.40.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/ti-mo/netfilter v0.5.1
|
||||
go.etcd.io/bbolt v1.3.8
|
||||
golang.org/x/crypto v0.18.0
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/sys v0.16.0
|
||||
golang.org/x/crypto v0.15.0
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
||||
golang.org/x/net v0.18.0
|
||||
golang.org/x/sys v0.14.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
howett.net/plist v1.0.1
|
||||
howett.net/plist v1.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -48,21 +47,20 @@ require (
|
||||
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 // indirect
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||
// TODO(a.garipov): Upgrade to v0.5.0 once we switch to Go 1.21+.
|
||||
github.com/mdlayher/socket v0.5.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.1 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.18 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
gonum.org/v1/gonum v0.14.0 // indirect
|
||||
golang.org/x/tools v0.15.0 // indirect
|
||||
)
|
||||
|
||||
78
go.sum
78
go.sum
@@ -1,7 +1,7 @@
|
||||
github.com/AdguardTeam/dnsproxy v0.63.1 h1:CilxSuLYcuYpbPCGB7w41UUqWRMu3dvj4c9TvkIrpBg=
|
||||
github.com/AdguardTeam/dnsproxy v0.63.1/go.mod h1:dRRAFOjrq4QYM92jGs4lt4BoY0Dm3EY3HkaleoM2Feo=
|
||||
github.com/AdguardTeam/golibs v0.19.0 h1:y/x+Xn3pDg1ZfQ+QEZapPJqaeVYUIMp/EODMtVhn7PM=
|
||||
github.com/AdguardTeam/golibs v0.19.0/go.mod h1:3WunclLLfrVAq7fYQRhd6f168FHOEMssnipVXCxDL/w=
|
||||
github.com/AdguardTeam/dnsproxy v0.59.1 h1:G/6T32EuPF0rhRkACkLFwD0pajI9351a1LACpuA2UcE=
|
||||
github.com/AdguardTeam/dnsproxy v0.59.1/go.mod h1:ZvkbM71HwpilgkCnTubDiR4Ba6x5Qvnhy2iasMWaTDM=
|
||||
github.com/AdguardTeam/golibs v0.17.2 h1:vg6wHMjUKscnyPGRvxS5kAt7Uw4YxcJiITZliZ476W8=
|
||||
github.com/AdguardTeam/golibs v0.17.2/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
|
||||
github.com/AdguardTeam/urlfilter v0.17.3 h1:fg/ObbnO0Cv6aw0tW6N/ETDMhhNvmcUUOZ7HlmKC3rw=
|
||||
github.com/AdguardTeam/urlfilter v0.17.3/go.mod h1:Jru7jFfeH2CoDf150uDs+rRYcZBzHHBz05r9REyDKyE=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
@@ -18,8 +18,6 @@ github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 h1:0b2vaepXIfMsG+
|
||||
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4=
|
||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -43,16 +41,16 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8=
|
||||
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c h1:PgxFEySCI41sH0mB7/2XswdXbUykQsRUGod8Rn+NubM=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
@@ -73,19 +71,19 @@ github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU
|
||||
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
|
||||
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
|
||||
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||
github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI=
|
||||
github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
|
||||
github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
|
||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
||||
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/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -111,19 +109,19 @@ github.com/ti-mo/netfilter v0.5.1 h1:cqamEd1c1zmpfpqvInLOro0Znq/RAfw2QL5wL2rAR/8
|
||||
github.com/ti-mo/netfilter v0.5.1/go.mod h1:h9UPQ3ZrTZGBitay+LETMxZvNgWGK/efTUcqES2YiLw=
|
||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e h1:BA9O3BmlTmpjbvajAwzWx4Wo2TRVdpPXZEeemGQcajw=
|
||||
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.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.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
@@ -134,12 +132,12 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -151,8 +149,8 @@ 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-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -160,12 +158,10 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
|
||||
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
|
||||
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=
|
||||
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
|
||||
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
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=
|
||||
@@ -175,5 +171,5 @@ gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa
|
||||
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
package aghalg
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
)
|
||||
|
||||
// RingBuffer is the implementation of ring buffer data structure.
|
||||
type RingBuffer[T any] struct {
|
||||
buf []T
|
||||
cur uint
|
||||
cur int
|
||||
full bool
|
||||
}
|
||||
|
||||
// NewRingBuffer initializes the new instance of ring buffer. size must be
|
||||
// greater or equal to zero.
|
||||
func NewRingBuffer[T any](size uint) (rb *RingBuffer[T]) {
|
||||
func NewRingBuffer[T any](size int) (rb *RingBuffer[T]) {
|
||||
if size < 0 {
|
||||
panic(errors.Error("ring buffer: size must be greater or equal to zero"))
|
||||
}
|
||||
|
||||
return &RingBuffer[T]{
|
||||
buf: make([]T, size),
|
||||
}
|
||||
@@ -22,7 +30,7 @@ func (rb *RingBuffer[T]) Append(e T) {
|
||||
}
|
||||
|
||||
rb.buf[rb.cur] = e
|
||||
rb.cur = (rb.cur + 1) % uint(cap(rb.buf))
|
||||
rb.cur = (rb.cur + 1) % cap(rb.buf)
|
||||
if rb.cur == 0 {
|
||||
rb.full = true
|
||||
}
|
||||
@@ -79,12 +87,12 @@ func (rb *RingBuffer[T]) splitCur() (before, after []T) {
|
||||
}
|
||||
|
||||
// Len returns a length of the buffer.
|
||||
func (rb *RingBuffer[T]) Len() (l uint) {
|
||||
func (rb *RingBuffer[T]) Len() (l int) {
|
||||
if !rb.full {
|
||||
return rb.cur
|
||||
}
|
||||
|
||||
return uint(cap(rb.buf))
|
||||
return cap(rb.buf)
|
||||
}
|
||||
|
||||
// Clear clears the buffer.
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
)
|
||||
|
||||
// elements is a helper function that returns n elements of the buffer.
|
||||
func elements(b *aghalg.RingBuffer[int], n uint, reverse bool) (es []int) {
|
||||
func elements(b *aghalg.RingBuffer[int], n int, reverse bool) (es []int) {
|
||||
fn := b.Range
|
||||
if reverse {
|
||||
fn = b.ReverseRange
|
||||
}
|
||||
|
||||
var i uint
|
||||
i := 0
|
||||
fn(func(e int) (cont bool) {
|
||||
if i >= n {
|
||||
return false
|
||||
@@ -42,14 +42,19 @@ func TestNewRingBuffer(t *testing.T) {
|
||||
assert.Zero(t, b.Len())
|
||||
})
|
||||
|
||||
t.Run("negative_size", func(t *testing.T) {
|
||||
assert.PanicsWithError(t, "ring buffer: size must be greater or equal to zero", func() {
|
||||
aghalg.NewRingBuffer[int](-5)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("zero", func(t *testing.T) {
|
||||
b := aghalg.NewRingBuffer[int](0)
|
||||
for i := 0; i < 10; i++ {
|
||||
b.Append(i)
|
||||
bufLen := b.Len()
|
||||
assert.EqualValues(t, 0, bufLen)
|
||||
assert.Empty(t, elements(b, bufLen, false))
|
||||
assert.Empty(t, elements(b, bufLen, true))
|
||||
assert.Equal(t, 0, b.Len())
|
||||
assert.Empty(t, elements(b, b.Len(), false))
|
||||
assert.Empty(t, elements(b, b.Len(), true))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -57,10 +62,9 @@ func TestNewRingBuffer(t *testing.T) {
|
||||
b := aghalg.NewRingBuffer[int](1)
|
||||
for i := 0; i < 10; i++ {
|
||||
b.Append(i)
|
||||
bufLen := b.Len()
|
||||
assert.EqualValues(t, 1, bufLen)
|
||||
assert.Equal(t, []int{i}, elements(b, bufLen, false))
|
||||
assert.Equal(t, []int{i}, elements(b, bufLen, true))
|
||||
assert.Equal(t, 1, b.Len())
|
||||
assert.Equal(t, []int{i}, elements(b, b.Len(), false))
|
||||
assert.Equal(t, []int{i}, elements(b, b.Len(), true))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -74,7 +78,7 @@ func TestRingBuffer_Range(t *testing.T) {
|
||||
name string
|
||||
want []int
|
||||
count int
|
||||
length uint
|
||||
length int
|
||||
}{{
|
||||
name: "three",
|
||||
count: 3,
|
||||
@@ -159,11 +163,11 @@ func TestRingBuffer_Range_increment(t *testing.T) {
|
||||
for i, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
b.Append(i)
|
||||
bufLen := b.Len()
|
||||
assert.Equal(t, tc.want, elements(b, bufLen, false))
|
||||
|
||||
assert.Equal(t, tc.want, elements(b, b.Len(), false))
|
||||
|
||||
slices.Reverse(tc.want)
|
||||
assert.Equal(t, tc.want, elements(b, bufLen, true))
|
||||
assert.Equal(t, tc.want, elements(b, b.Len(), true))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
33
internal/aghchan/aghchan.go
Normal file
33
internal/aghchan/aghchan.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Package aghchan contains channel utilities.
|
||||
package aghchan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Receive returns an error if it cannot receive a value form c before timeout
|
||||
// runs out.
|
||||
func Receive[T any](c <-chan T, timeout time.Duration) (v T, ok bool, err error) {
|
||||
var zero T
|
||||
timeoutCh := time.After(timeout)
|
||||
select {
|
||||
case <-timeoutCh:
|
||||
// TODO(a.garipov): Consider implementing [errors.Aser] for
|
||||
// os.ErrTimeout.
|
||||
return zero, false, fmt.Errorf("did not receive after %s", timeout)
|
||||
case v, ok = <-c:
|
||||
return v, ok, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MustReceive panics if it cannot receive a value form c before timeout runs
|
||||
// out.
|
||||
func MustReceive[T any](c <-chan T, timeout time.Duration) (v T, ok bool) {
|
||||
v, ok, err := Receive(c, timeout)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return v, ok
|
||||
}
|
||||
@@ -1,23 +1,65 @@
|
||||
package aghnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/netip"
|
||||
"path"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/hostsfile"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// DefaultHostsPaths returns the slice of paths default for the operating system
|
||||
// to files and directories which are containing the hosts database. The result
|
||||
// is intended to be used within fs.FS so the initial slash is omitted.
|
||||
func DefaultHostsPaths() (paths []string) {
|
||||
return defaultHostsPaths()
|
||||
}
|
||||
|
||||
// MatchAddr returns the records for the IP address.
|
||||
func (hc *HostsContainer) MatchAddr(ip netip.Addr) (recs []*hostsfile.Record) {
|
||||
cur := hc.current.Load()
|
||||
if cur == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cur.addrs[ip]
|
||||
}
|
||||
|
||||
// MatchName returns the records for the hostname.
|
||||
func (hc *HostsContainer) MatchName(name string) (recs []*hostsfile.Record) {
|
||||
cur := hc.current.Load()
|
||||
if cur != nil {
|
||||
recs = cur.names[name]
|
||||
}
|
||||
|
||||
return recs
|
||||
}
|
||||
|
||||
// hostsContainerPrefix is a prefix for logging and wrapping errors in
|
||||
// HostsContainer's methods.
|
||||
const hostsContainerPrefix = "hosts container"
|
||||
|
||||
// Hosts is a map of IP addresses to the records, as it primarily stored in the
|
||||
// [HostsContainer]. It should not be accessed for writing since it may be read
|
||||
// concurrently, users should clone it before modifying.
|
||||
//
|
||||
// The order of records for each address is preserved from original files, but
|
||||
// the order of the addresses, being a map key, is not.
|
||||
//
|
||||
// TODO(e.burkov): Probably, this should be a sorted slice of records.
|
||||
type Hosts map[netip.Addr][]*hostsfile.Record
|
||||
|
||||
// HostsContainer stores the relevant hosts database provided by the OS and
|
||||
// processes both A/AAAA and PTR DNS requests for those.
|
||||
type HostsContainer struct {
|
||||
@@ -25,10 +67,10 @@ type HostsContainer struct {
|
||||
done chan struct{}
|
||||
|
||||
// updates is the channel for receiving updated hosts.
|
||||
updates chan *hostsfile.DefaultStorage
|
||||
updates chan Hosts
|
||||
|
||||
// current is the last set of hosts parsed.
|
||||
current atomic.Pointer[hostsfile.DefaultStorage]
|
||||
current atomic.Pointer[hostsIndex]
|
||||
|
||||
// fsys is the working file system to read hosts files from.
|
||||
fsys fs.FS
|
||||
@@ -69,7 +111,7 @@ func NewHostsContainer(
|
||||
|
||||
hc = &HostsContainer{
|
||||
done: make(chan struct{}, 1),
|
||||
updates: make(chan *hostsfile.DefaultStorage, 1),
|
||||
updates: make(chan Hosts, 1),
|
||||
fsys: fsys,
|
||||
watcher: w,
|
||||
patterns: patterns,
|
||||
@@ -110,25 +152,11 @@ func (hc *HostsContainer) Close() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Upd returns the channel into which the updates are sent. The updates
|
||||
// themselves must not be modified.
|
||||
func (hc *HostsContainer) Upd() (updates <-chan *hostsfile.DefaultStorage) {
|
||||
// Upd returns the channel into which the updates are sent.
|
||||
func (hc *HostsContainer) Upd() (updates <-chan Hosts) {
|
||||
return hc.updates
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ hostsfile.Storage = (*HostsContainer)(nil)
|
||||
|
||||
// ByAddr implements the [hostsfile.Storage] interface for *HostsContainer.
|
||||
func (hc *HostsContainer) ByAddr(addr netip.Addr) (names []string) {
|
||||
return hc.current.Load().ByAddr(addr)
|
||||
}
|
||||
|
||||
// ByName implements the [hostsfile.Storage] interface for *HostsContainer.
|
||||
func (hc *HostsContainer) ByName(name string) (addrs []netip.Addr) {
|
||||
return hc.current.Load().ByName(name)
|
||||
}
|
||||
|
||||
// pathsToPatterns converts paths into patterns compatible with fs.Glob.
|
||||
func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error) {
|
||||
for i, p := range paths {
|
||||
@@ -139,7 +167,7 @@ func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error)
|
||||
continue
|
||||
}
|
||||
|
||||
// Don't put a filename here since it's already added by [fs.Stat].
|
||||
// Don't put a filename here since it's already added by fs.Stat.
|
||||
return nil, fmt.Errorf("path at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
@@ -181,7 +209,7 @@ func (hc *HostsContainer) handleEvents() {
|
||||
}
|
||||
|
||||
// sendUpd tries to send the parsed data to the ch.
|
||||
func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
|
||||
func (hc *HostsContainer) sendUpd(recs Hosts) {
|
||||
log.Debug("%s: sending upd", hostsContainerPrefix)
|
||||
|
||||
ch := hc.updates
|
||||
@@ -198,6 +226,67 @@ func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
|
||||
}
|
||||
}
|
||||
|
||||
// hostsIndex is a [hostsfile.Set] to enumerate all the records.
|
||||
type hostsIndex struct {
|
||||
// addrs maps IP addresses to the records.
|
||||
addrs Hosts
|
||||
|
||||
// names maps hostnames to the records.
|
||||
names map[string][]*hostsfile.Record
|
||||
}
|
||||
|
||||
// walk is a file walking function for hostsIndex.
|
||||
func (idx *hostsIndex) walk(r io.Reader) (patterns []string, cont bool, err error) {
|
||||
return nil, true, hostsfile.Parse(idx, r, nil)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ hostsfile.Set = (*hostsIndex)(nil)
|
||||
|
||||
// Add implements the [hostsfile.Set] interface for *hostsIndex.
|
||||
func (idx *hostsIndex) Add(rec *hostsfile.Record) {
|
||||
idx.addrs[rec.Addr] = append(idx.addrs[rec.Addr], rec)
|
||||
for _, name := range rec.Names {
|
||||
idx.names[name] = append(idx.names[name], rec)
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ hostsfile.HandleSet = (*hostsIndex)(nil)
|
||||
|
||||
// HandleInvalid implements the [hostsfile.HandleSet] interface for *hostsIndex.
|
||||
func (idx *hostsIndex) HandleInvalid(src string, _ []byte, err error) {
|
||||
lineErr := &hostsfile.LineError{}
|
||||
if !errors.As(err, &lineErr) {
|
||||
// Must not happen if idx passed to [hostsfile.Parse].
|
||||
return
|
||||
} else if errors.Is(lineErr, hostsfile.ErrEmptyLine) {
|
||||
// Ignore empty lines.
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("%s: warning: parsing %q: %s", hostsContainerPrefix, src, lineErr)
|
||||
}
|
||||
|
||||
// equalRecs is an equality function for [*hostsfile.Record].
|
||||
func equalRecs(a, b *hostsfile.Record) (ok bool) {
|
||||
return a.Addr == b.Addr && a.Source == b.Source && slices.Equal(a.Names, b.Names)
|
||||
}
|
||||
|
||||
// equalRecSlices is an equality function for slices of [*hostsfile.Record].
|
||||
func equalRecSlices(a, b []*hostsfile.Record) (ok bool) { return slices.EqualFunc(a, b, equalRecs) }
|
||||
|
||||
// Equal returns true if indexes are equal.
|
||||
func (idx *hostsIndex) Equal(other *hostsIndex) (ok bool) {
|
||||
if idx == nil {
|
||||
return other == nil
|
||||
} else if other == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return maps.EqualFunc(idx.addrs, other.addrs, equalRecSlices)
|
||||
}
|
||||
|
||||
// refresh gets the data from specified files and propagates the updates if
|
||||
// needed.
|
||||
//
|
||||
@@ -205,22 +294,63 @@ func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
|
||||
func (hc *HostsContainer) refresh() (err error) {
|
||||
log.Debug("%s: refreshing", hostsContainerPrefix)
|
||||
|
||||
// The error is always nil here since no readers passed.
|
||||
strg, _ := hostsfile.NewDefaultStorage()
|
||||
_, err = aghos.FileWalker(func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||
// Don't wrap the error since it's already informative enough as is.
|
||||
return nil, true, hostsfile.Parse(strg, r, nil)
|
||||
}).Walk(hc.fsys, hc.patterns...)
|
||||
var addrLen, nameLen int
|
||||
last := hc.current.Load()
|
||||
if last != nil {
|
||||
addrLen, nameLen = len(last.addrs), len(last.names)
|
||||
}
|
||||
idx := &hostsIndex{
|
||||
addrs: make(Hosts, addrLen),
|
||||
names: make(map[string][]*hostsfile.Record, nameLen),
|
||||
}
|
||||
|
||||
_, err = aghos.FileWalker(idx.walk).Walk(hc.fsys, hc.patterns...)
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(e.burkov): Serialize updates using [time.Time].
|
||||
if !hc.current.Load().Equal(strg) {
|
||||
hc.current.Store(strg)
|
||||
hc.sendUpd(strg)
|
||||
// TODO(e.burkov): Serialize updates using time.
|
||||
if !last.Equal(idx) {
|
||||
hc.current.Store(idx)
|
||||
hc.sendUpd(idx.addrs)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ upstream.Resolver = (*HostsContainer)(nil)
|
||||
|
||||
// LookupNetIP implements the [upstream.Resolver] interface for *HostsContainer.
|
||||
func (hc *HostsContainer) LookupNetIP(
|
||||
ctx context.Context,
|
||||
network string,
|
||||
hostname string,
|
||||
) (addrs []netip.Addr, err error) {
|
||||
// TODO(e.burkov): Think of extracting this logic to a golibs function if
|
||||
// needed anywhere else.
|
||||
var isDesiredProto func(ip netip.Addr) (ok bool)
|
||||
switch network {
|
||||
case "ip4":
|
||||
isDesiredProto = (netip.Addr).Is4
|
||||
case "ip6":
|
||||
isDesiredProto = (netip.Addr).Is6
|
||||
case "ip":
|
||||
isDesiredProto = func(ip netip.Addr) (ok bool) { return true }
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported network: %q", network)
|
||||
}
|
||||
|
||||
idx := hc.current.Load()
|
||||
recs := idx.names[strings.ToLower(hostname)]
|
||||
|
||||
addrs = make([]netip.Addr, 0, len(recs))
|
||||
for _, rec := range recs {
|
||||
if isDesiredProto(rec.Addr) {
|
||||
addrs = append(addrs, rec.Addr)
|
||||
}
|
||||
}
|
||||
|
||||
return slices.Clip(addrs), nil
|
||||
}
|
||||
|
||||
17
internal/aghnet/hostscontainer_linux.go
Normal file
17
internal/aghnet/hostscontainer_linux.go
Normal file
@@ -0,0 +1,17 @@
|
||||
//go:build linux
|
||||
|
||||
package aghnet
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
)
|
||||
|
||||
func defaultHostsPaths() (paths []string) {
|
||||
paths = []string{"etc/hosts"}
|
||||
|
||||
if aghos.IsOpenWrt() {
|
||||
paths = append(paths, "tmp/hosts")
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
7
internal/aghnet/hostscontainer_others.go
Normal file
7
internal/aghnet/hostscontainer_others.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build !(windows || linux)
|
||||
|
||||
package aghnet
|
||||
|
||||
func defaultHostsPaths() (paths []string) {
|
||||
return []string{"etc/hosts"}
|
||||
}
|
||||
@@ -3,11 +3,13 @@ package aghnet_test
|
||||
import (
|
||||
"net/netip"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghchan"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
@@ -18,6 +20,139 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// nl is a newline character.
|
||||
const nl = "\n"
|
||||
|
||||
// Variables mirroring the etc_hosts file from testdata.
|
||||
var (
|
||||
addr1000 = netip.MustParseAddr("1.0.0.0")
|
||||
addr1001 = netip.MustParseAddr("1.0.0.1")
|
||||
addr1002 = netip.MustParseAddr("1.0.0.2")
|
||||
addr1003 = netip.MustParseAddr("1.0.0.3")
|
||||
addr1004 = netip.MustParseAddr("1.0.0.4")
|
||||
addr1357 = netip.MustParseAddr("1.3.5.7")
|
||||
addr4216 = netip.MustParseAddr("4.2.1.6")
|
||||
addr7531 = netip.MustParseAddr("7.5.3.1")
|
||||
|
||||
addr0 = netip.MustParseAddr("::")
|
||||
addr1 = netip.MustParseAddr("::1")
|
||||
addr2 = netip.MustParseAddr("::2")
|
||||
addr3 = netip.MustParseAddr("::3")
|
||||
addr4 = netip.MustParseAddr("::4")
|
||||
addr42 = netip.MustParseAddr("::42")
|
||||
addr13 = netip.MustParseAddr("::13")
|
||||
addr31 = netip.MustParseAddr("::31")
|
||||
|
||||
hostsSrc = "./" + filepath.Join("./testdata", "etc_hosts")
|
||||
|
||||
testHosts = map[netip.Addr][]*hostsfile.Record{
|
||||
addr1000: {{
|
||||
Addr: addr1000,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello", "hello.world"},
|
||||
}, {
|
||||
Addr: addr1000,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello.world.again"},
|
||||
}, {
|
||||
Addr: addr1000,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello.world"},
|
||||
}},
|
||||
addr1001: {{
|
||||
Addr: addr1001,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"simplehost"},
|
||||
}, {
|
||||
Addr: addr1001,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"simplehost"},
|
||||
}},
|
||||
addr1002: {{
|
||||
Addr: addr1002,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"a.whole", "lot.of", "aliases", "for.testing"},
|
||||
}},
|
||||
addr1003: {{
|
||||
Addr: addr1003,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"*"},
|
||||
}},
|
||||
addr1004: {{
|
||||
Addr: addr1004,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"*.com"},
|
||||
}},
|
||||
addr1357: {{
|
||||
Addr: addr1357,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain4", "domain4.alias"},
|
||||
}},
|
||||
addr7531: {{
|
||||
Addr: addr7531,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain4.alias", "domain4"},
|
||||
}},
|
||||
addr4216: {{
|
||||
Addr: addr4216,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain", "domain.alias"},
|
||||
}},
|
||||
addr0: {{
|
||||
Addr: addr0,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello", "hello.world"},
|
||||
}, {
|
||||
Addr: addr0,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello.world.again"},
|
||||
}, {
|
||||
Addr: addr0,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"hello.world"},
|
||||
}},
|
||||
addr1: {{
|
||||
Addr: addr1,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"simplehost"},
|
||||
}, {
|
||||
Addr: addr1,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"simplehost"},
|
||||
}},
|
||||
addr2: {{
|
||||
Addr: addr2,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"a.whole", "lot.of", "aliases", "for.testing"},
|
||||
}},
|
||||
addr3: {{
|
||||
Addr: addr3,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"*"},
|
||||
}},
|
||||
addr4: {{
|
||||
Addr: addr4,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"*.com"},
|
||||
}},
|
||||
addr42: {{
|
||||
Addr: addr42,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain.alias", "domain"},
|
||||
}},
|
||||
addr13: {{
|
||||
Addr: addr13,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain6", "domain6.alias"},
|
||||
}},
|
||||
addr31: {{
|
||||
Addr: addr31,
|
||||
Source: hostsSrc,
|
||||
Names: []string{"domain6.alias", "domain6"},
|
||||
}},
|
||||
}
|
||||
)
|
||||
|
||||
func TestNewHostsContainer(t *testing.T) {
|
||||
const dirname = "dir"
|
||||
const filename = "file1"
|
||||
@@ -132,21 +267,7 @@ func TestHostsContainer_refresh(t *testing.T) {
|
||||
anotherIPStr := "1.2.3.4"
|
||||
anotherIP := netip.MustParseAddr(anotherIPStr)
|
||||
|
||||
r1 := &hostsfile.Record{
|
||||
Addr: ip,
|
||||
Source: "file1",
|
||||
Names: []string{"hostname"},
|
||||
}
|
||||
r2 := &hostsfile.Record{
|
||||
Addr: anotherIP,
|
||||
Source: "file2",
|
||||
Names: []string{"alias"},
|
||||
}
|
||||
|
||||
r1Data, _ := r1.MarshalText()
|
||||
r2Data, _ := r2.MarshalText()
|
||||
|
||||
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: r1Data}}
|
||||
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}}
|
||||
|
||||
// event is a convenient alias for an empty struct{} to emit test events.
|
||||
type event = struct{}
|
||||
@@ -168,47 +289,172 @@ func TestHostsContainer_refresh(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
strg, _ := hostsfile.NewDefaultStorage()
|
||||
strg.Add(r1)
|
||||
checkRefresh := func(t *testing.T, want aghnet.Hosts) {
|
||||
t.Helper()
|
||||
|
||||
upd, ok := aghchan.MustReceive(hc.Upd(), 1*time.Second)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, want, upd)
|
||||
}
|
||||
|
||||
t.Run("initial_refresh", func(t *testing.T) {
|
||||
upd, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.True(t, strg.Equal(upd))
|
||||
checkRefresh(t, aghnet.Hosts{
|
||||
ip: {{
|
||||
Addr: ip,
|
||||
Source: "file1",
|
||||
Names: []string{"hostname"},
|
||||
}},
|
||||
})
|
||||
})
|
||||
|
||||
strg.Add(r2)
|
||||
|
||||
t.Run("second_refresh", func(t *testing.T) {
|
||||
testFS["dir/file2"] = &fstest.MapFile{Data: r2Data}
|
||||
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(anotherIPStr + ` alias` + nl)}
|
||||
eventsCh <- event{}
|
||||
|
||||
upd, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.True(t, strg.Equal(upd))
|
||||
checkRefresh(t, aghnet.Hosts{
|
||||
ip: {{
|
||||
Addr: ip,
|
||||
Source: "file1",
|
||||
Names: []string{"hostname"},
|
||||
}},
|
||||
anotherIP: {{
|
||||
Addr: anotherIP,
|
||||
Source: "file2",
|
||||
Names: []string{"alias"},
|
||||
}},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("double_refresh", func(t *testing.T) {
|
||||
// Make a change once.
|
||||
testFS["dir/file1"] = &fstest.MapFile{Data: []byte(ipStr + " alias\n")}
|
||||
testFS["dir/file1"] = &fstest.MapFile{Data: []byte(ipStr + ` alias` + nl)}
|
||||
eventsCh <- event{}
|
||||
|
||||
// Require the changes are written.
|
||||
current, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
|
||||
require.True(t, ok)
|
||||
require.Eventually(t, func() bool {
|
||||
ips := hc.MatchName("hostname")
|
||||
|
||||
require.Empty(t, current.ByName("hostname"))
|
||||
return len(ips) == 0
|
||||
}, 5*time.Second, time.Second/2)
|
||||
|
||||
// Make a change again.
|
||||
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + " hostname\n")}
|
||||
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}
|
||||
eventsCh <- event{}
|
||||
|
||||
// Require the changes are written.
|
||||
current, ok = testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
|
||||
require.True(t, ok)
|
||||
require.Eventually(t, func() bool {
|
||||
ips := hc.MatchName("hostname")
|
||||
|
||||
require.NotEmpty(t, current.ByName("hostname"))
|
||||
return len(ips) > 0
|
||||
}, 5*time.Second, time.Second/2)
|
||||
|
||||
assert.Len(t, hc.Upd(), 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestHostsContainer_MatchName(t *testing.T) {
|
||||
require.NoError(t, fstest.TestFS(testdata, "etc_hosts"))
|
||||
|
||||
stubWatcher := aghtest.FSWatcher{
|
||||
OnEvents: func() (e <-chan struct{}) { return nil },
|
||||
OnAdd: func(name string) (err error) { return nil },
|
||||
OnClose: func() (err error) { return nil },
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
req string
|
||||
name string
|
||||
want []*hostsfile.Record
|
||||
}{{
|
||||
req: "simplehost",
|
||||
name: "simple",
|
||||
want: append(testHosts[addr1001], testHosts[addr1]...),
|
||||
}, {
|
||||
req: "hello.world",
|
||||
name: "hello_alias",
|
||||
want: []*hostsfile.Record{
|
||||
testHosts[addr1000][0],
|
||||
testHosts[addr1000][2],
|
||||
testHosts[addr0][0],
|
||||
testHosts[addr0][2],
|
||||
},
|
||||
}, {
|
||||
req: "hello.world.again",
|
||||
name: "other_line_alias",
|
||||
want: []*hostsfile.Record{
|
||||
testHosts[addr1000][1],
|
||||
testHosts[addr0][1],
|
||||
},
|
||||
}, {
|
||||
req: "say.hello",
|
||||
name: "hello_subdomain",
|
||||
want: nil,
|
||||
}, {
|
||||
req: "say.hello.world",
|
||||
name: "hello_alias_subdomain",
|
||||
want: nil,
|
||||
}, {
|
||||
req: "for.testing",
|
||||
name: "lots_of_aliases",
|
||||
want: append(testHosts[addr1002], testHosts[addr2]...),
|
||||
}, {
|
||||
req: "nonexistent.example",
|
||||
name: "non-existing",
|
||||
want: nil,
|
||||
}, {
|
||||
req: "domain",
|
||||
name: "issue_4216_4_6",
|
||||
want: append(testHosts[addr4216], testHosts[addr42]...),
|
||||
}, {
|
||||
req: "domain4",
|
||||
name: "issue_4216_4",
|
||||
want: append(testHosts[addr1357], testHosts[addr7531]...),
|
||||
}, {
|
||||
req: "domain6",
|
||||
name: "issue_4216_6",
|
||||
want: append(testHosts[addr13], testHosts[addr31]...),
|
||||
}}
|
||||
|
||||
hc, err := aghnet.NewHostsContainer(testdata, &stubWatcher, "etc_hosts")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recs := hc.MatchName(tc.req)
|
||||
assert.Equal(t, tc.want, recs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostsContainer_MatchAddr(t *testing.T) {
|
||||
require.NoError(t, fstest.TestFS(testdata, "etc_hosts"))
|
||||
|
||||
stubWatcher := aghtest.FSWatcher{
|
||||
OnEvents: func() (e <-chan struct{}) { return nil },
|
||||
OnAdd: func(name string) (err error) { return nil },
|
||||
OnClose: func() (err error) { return nil },
|
||||
}
|
||||
|
||||
hc, err := aghnet.NewHostsContainer(testdata, &stubWatcher, "etc_hosts")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
testCases := []struct {
|
||||
req netip.Addr
|
||||
name string
|
||||
want []*hostsfile.Record
|
||||
}{{
|
||||
req: netip.AddrFrom4([4]byte{1, 0, 0, 1}),
|
||||
name: "reverse",
|
||||
want: testHosts[addr1001],
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recs := hc.MatchAddr(tc.req)
|
||||
assert.Equal(t, tc.want, recs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
32
internal/aghnet/hostscontainer_windows.go
Normal file
32
internal/aghnet/hostscontainer_windows.go
Normal file
@@ -0,0 +1,32 @@
|
||||
//go:build windows
|
||||
|
||||
package aghnet
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func defaultHostsPaths() (paths []string) {
|
||||
sysDir, err := windows.GetSystemDirectory()
|
||||
if err != nil {
|
||||
log.Error("aghnet: getting system directory: %s", err)
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Split all the elements of the path to join them afterwards. This is
|
||||
// needed to make the Windows-specific path string returned by
|
||||
// windows.GetSystemDirectory to be compatible with fs.FS.
|
||||
pathElems := strings.Split(sysDir, string(os.PathSeparator))
|
||||
if len(pathElems) > 0 && pathElems[0] == filepath.VolumeName(sysDir) {
|
||||
pathElems = pathElems[1:]
|
||||
}
|
||||
|
||||
return []string{path.Join(append(pathElems, "drivers/etc/hosts")...)}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package aghnet_test
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
@@ -16,6 +18,9 @@ func TestMain(m *testing.M) {
|
||||
testutil.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
// testdata is the filesystem containing data for testing the package.
|
||||
var testdata fs.FS = os.DirFS("./testdata")
|
||||
|
||||
func TestParseAddrPort(t *testing.T) {
|
||||
const defaultPort = 1
|
||||
|
||||
|
||||
38
internal/aghnet/testdata/etc_hosts
vendored
Normal file
38
internal/aghnet/testdata/etc_hosts
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Test /etc/hosts file
|
||||
#
|
||||
|
||||
1.0.0.1 simplehost
|
||||
1.0.0.0 hello hello.world
|
||||
|
||||
# See https://github.com/AdguardTeam/AdGuardHome/issues/3846.
|
||||
1.0.0.2 a.whole lot.of aliases for.testing
|
||||
|
||||
# See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
|
||||
1.0.0.3 *
|
||||
1.0.0.4 *.com
|
||||
|
||||
# See https://github.com/AdguardTeam/AdGuardHome/issues/4079.
|
||||
1.0.0.0 hello.world.again
|
||||
|
||||
# Duplicates of a main host and an alias.
|
||||
1.0.0.1 simplehost
|
||||
1.0.0.0 hello.world
|
||||
|
||||
# Same for IPv6.
|
||||
::1 simplehost
|
||||
:: hello hello.world
|
||||
::2 a.whole lot.of aliases for.testing
|
||||
::3 *
|
||||
::4 *.com
|
||||
:: hello.world.again
|
||||
::1 simplehost
|
||||
:: hello.world
|
||||
|
||||
# See https://github.com/AdguardTeam/AdGuardHome/issues/4216.
|
||||
4.2.1.6 domain domain.alias
|
||||
::42 domain.alias domain
|
||||
1.3.5.7 domain4 domain4.alias
|
||||
7.5.3.1 domain4.alias domain4
|
||||
::13 domain6 domain6.alias
|
||||
::31 domain6.alias domain6
|
||||
1
internal/aghnet/testdata/ifaces
vendored
Normal file
1
internal/aghnet/testdata/ifaces
vendored
Normal file
@@ -0,0 +1 @@
|
||||
iface sample_name inet static
|
||||
5
internal/aghnet/testdata/include-subsources
vendored
Normal file
5
internal/aghnet/testdata/include-subsources
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# The "testdata" part is added here because the test is actually run from the
|
||||
# parent directory. Real interface files usually contain only absolute paths.
|
||||
|
||||
source ./testdata/ifaces
|
||||
source ./testdata/*
|
||||
@@ -262,7 +262,8 @@ func (p *DefaultAddrProc) processRDNS(ip netip.Addr) (host string) {
|
||||
// shouldResolve returns false if ip is a loopback address, or ip is private and
|
||||
// resolving of private addresses is disabled.
|
||||
func (p *DefaultAddrProc) shouldResolve(ip netip.Addr) (ok bool) {
|
||||
return !ip.IsLoopback() && (p.usePrivateRDNS || !p.privateSubnets.Contains(ip))
|
||||
return !ip.IsLoopback() &&
|
||||
(p.usePrivateRDNS || !p.privateSubnets.Contains(ip.AsSlice()))
|
||||
}
|
||||
|
||||
// processWHOIS looks up the information about clients' IP addresses in the
|
||||
|
||||
@@ -7,8 +7,6 @@ package client
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
)
|
||||
|
||||
// Source represents the source from which the information about the client has
|
||||
@@ -17,7 +15,8 @@ type Source uint8
|
||||
|
||||
// Clients information sources. The order determines the priority.
|
||||
const (
|
||||
SourceWHOIS Source = iota + 1
|
||||
SourceNone Source = iota
|
||||
SourceWHOIS
|
||||
SourceARP
|
||||
SourceRDNS
|
||||
SourceDHCP
|
||||
@@ -53,107 +52,3 @@ var _ encoding.TextMarshaler = Source(0)
|
||||
func (cs Source) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
||||
// Runtime is a client information from different sources.
|
||||
type Runtime struct {
|
||||
// whois is the filtered WHOIS information of a client.
|
||||
whois *whois.Info
|
||||
|
||||
// arp is the ARP information of a client. nil indicates that there is no
|
||||
// information from the source. Empty non-nil slice indicates that the data
|
||||
// from the source is present, but empty.
|
||||
arp []string
|
||||
|
||||
// rdns is the RDNS information of a client. nil indicates that there is no
|
||||
// information from the source. Empty non-nil slice indicates that the data
|
||||
// from the source is present, but empty.
|
||||
rdns []string
|
||||
|
||||
// dhcp is the DHCP information of a client. nil indicates that there is no
|
||||
// information from the source. Empty non-nil slice indicates that the data
|
||||
// from the source is present, but empty.
|
||||
dhcp []string
|
||||
|
||||
// hostsFile is the information from the hosts file. nil indicates that
|
||||
// there is no information from the source. Empty non-nil slice indicates
|
||||
// that the data from the source is present, but empty.
|
||||
hostsFile []string
|
||||
}
|
||||
|
||||
// Info returns a client information from the highest-priority source.
|
||||
func (r *Runtime) Info() (cs Source, host string) {
|
||||
info := []string{}
|
||||
|
||||
switch {
|
||||
case r.hostsFile != nil:
|
||||
cs, info = SourceHostsFile, r.hostsFile
|
||||
case r.dhcp != nil:
|
||||
cs, info = SourceDHCP, r.dhcp
|
||||
case r.rdns != nil:
|
||||
cs, info = SourceRDNS, r.rdns
|
||||
case r.arp != nil:
|
||||
cs, info = SourceARP, r.arp
|
||||
case r.whois != nil:
|
||||
cs = SourceWHOIS
|
||||
}
|
||||
|
||||
if len(info) == 0 {
|
||||
return cs, ""
|
||||
}
|
||||
|
||||
// TODO(s.chzhen): Return the full information.
|
||||
return cs, info[0]
|
||||
}
|
||||
|
||||
// SetInfo sets a host as a client information from the cs.
|
||||
func (r *Runtime) SetInfo(cs Source, hosts []string) {
|
||||
if len(hosts) == 1 && hosts[0] == "" {
|
||||
hosts = []string{}
|
||||
}
|
||||
|
||||
switch cs {
|
||||
case SourceARP:
|
||||
r.arp = hosts
|
||||
case SourceRDNS:
|
||||
r.rdns = hosts
|
||||
case SourceDHCP:
|
||||
r.dhcp = hosts
|
||||
case SourceHostsFile:
|
||||
r.hostsFile = hosts
|
||||
}
|
||||
}
|
||||
|
||||
// WHOIS returns a WHOIS client information.
|
||||
func (r *Runtime) WHOIS() (info *whois.Info) {
|
||||
return r.whois
|
||||
}
|
||||
|
||||
// SetWHOIS sets a WHOIS client information. info must be non-nil.
|
||||
func (r *Runtime) SetWHOIS(info *whois.Info) {
|
||||
r.whois = info
|
||||
}
|
||||
|
||||
// Unset clears a cs information.
|
||||
func (r *Runtime) Unset(cs Source) {
|
||||
switch cs {
|
||||
case SourceWHOIS:
|
||||
r.whois = nil
|
||||
case SourceARP:
|
||||
r.arp = nil
|
||||
case SourceRDNS:
|
||||
r.rdns = nil
|
||||
case SourceDHCP:
|
||||
r.dhcp = nil
|
||||
case SourceHostsFile:
|
||||
r.hostsFile = nil
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty returns true if there is no information from any source.
|
||||
func (r *Runtime) IsEmpty() (ok bool) {
|
||||
return r.whois == nil &&
|
||||
r.arp == nil &&
|
||||
r.rdns == nil &&
|
||||
r.dhcp == nil &&
|
||||
r.hostsFile == nil
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
// Package configmigrate provides a way to upgrade the YAML configuration file.
|
||||
package configmigrate
|
||||
|
||||
// LastSchemaVersion is the most recent schema version.
|
||||
const LastSchemaVersion uint = 28
|
||||
@@ -1,47 +0,0 @@
|
||||
package configmigrate
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
)
|
||||
|
||||
// migrateTo28 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'dns':
|
||||
// 'all_servers': true
|
||||
// 'fastest_addr': true
|
||||
// # …
|
||||
// # …
|
||||
//
|
||||
// # AFTER:
|
||||
// 'dns':
|
||||
// 'upstream_mode': 'parallel'
|
||||
// # …
|
||||
// # …
|
||||
func migrateTo28(diskConf yobj) (err error) {
|
||||
diskConf["schema_version"] = 28
|
||||
|
||||
dns, ok, err := fieldVal[yobj](diskConf, "dns")
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
|
||||
allServers, _, _ := fieldVal[bool](dns, "all_servers")
|
||||
fastestAddr, _, _ := fieldVal[bool](dns, "fastest_addr")
|
||||
|
||||
var upstreamModeType dnsforward.UpstreamMode
|
||||
if allServers {
|
||||
upstreamModeType = dnsforward.UpstreamModeParallel
|
||||
} else if fastestAddr {
|
||||
upstreamModeType = dnsforward.UpstreamModeFastestAddr
|
||||
} else {
|
||||
upstreamModeType = dnsforward.UpstreamModeLoadBalance
|
||||
}
|
||||
|
||||
dns["upstream_mode"] = upstreamModeType
|
||||
|
||||
delete(dns, "all_servers")
|
||||
delete(dns, "fastest_addr")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package configmigrate
|
||||
package confmigrate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
@@ -1647,84 +1646,3 @@ func TestUpgradeSchema26to27(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpgradeSchema27to28(t *testing.T) {
|
||||
const newSchemaVer = 28
|
||||
|
||||
testCases := []struct {
|
||||
in yobj
|
||||
want yobj
|
||||
name string
|
||||
}{{
|
||||
name: "empty",
|
||||
in: yobj{},
|
||||
want: yobj{
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
}, {
|
||||
name: "load_balance",
|
||||
in: yobj{
|
||||
"dns": yobj{
|
||||
"all_servers": false,
|
||||
"fastest_addr": false,
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"dns": yobj{
|
||||
"upstream_mode": dnsforward.UpstreamModeLoadBalance,
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
}, {
|
||||
name: "parallel",
|
||||
in: yobj{
|
||||
"dns": yobj{
|
||||
"all_servers": true,
|
||||
"fastest_addr": false,
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"dns": yobj{
|
||||
"upstream_mode": dnsforward.UpstreamModeParallel,
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
}, {
|
||||
name: "parallel_fastest",
|
||||
in: yobj{
|
||||
"dns": yobj{
|
||||
"all_servers": true,
|
||||
"fastest_addr": true,
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"dns": yobj{
|
||||
"upstream_mode": dnsforward.UpstreamModeParallel,
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
}, {
|
||||
name: "load_balance",
|
||||
in: yobj{
|
||||
"dns": yobj{
|
||||
"all_servers": false,
|
||||
"fastest_addr": true,
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"dns": yobj{
|
||||
"upstream_mode": dnsforward.UpstreamModeFastestAddr,
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := migrateTo28(tc.in)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, tc.in)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
package configmigrate
|
||||
// Package confmigrate provides a way to upgrade the YAML configuration file.
|
||||
package confmigrate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,6 +9,9 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// LastSchemaVersion is the most recent schema version.
|
||||
const LastSchemaVersion uint = 27
|
||||
|
||||
// Config is a the configuration for initializing a [Migrator].
|
||||
type Config struct {
|
||||
// WorkingDir is an absolute path to the working directory of AdGuardHome.
|
||||
@@ -119,7 +123,6 @@ func (m *Migrator) upgradeConfigSchema(current, target uint, diskConf yobj) (err
|
||||
24: migrateTo25,
|
||||
25: migrateTo26,
|
||||
26: migrateTo27,
|
||||
27: migrateTo28,
|
||||
}
|
||||
|
||||
for i, migrate := range upgrades[current:target] {
|
||||
@@ -1,4 +1,4 @@
|
||||
package configmigrate_test
|
||||
package confmigrate_test
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/configmigrate"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/confmigrate"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -200,7 +200,7 @@ func TestMigrateConfig_Migrate(t *testing.T) {
|
||||
wantBody, err := fs.ReadFile(testdata, path.Join(t.Name(), outputFileName))
|
||||
require.NoError(t, err)
|
||||
|
||||
migrator := configmigrate.New(&configmigrate.Config{
|
||||
migrator := confmigrate.New(&confmigrate.Config{
|
||||
WorkingDir: t.Name(),
|
||||
})
|
||||
newBody, upgraded, err := migrator.Migrate(body, tc.targetVersion)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user