Compare commits
25 Commits
v0.108.0-b
...
v0.108.0-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d0a43aad6 | ||
|
|
1bc2186c2d | ||
|
|
6584c300b8 | ||
|
|
dc480ae70f | ||
|
|
e783564084 | ||
|
|
0ee34534c6 | ||
|
|
9146df5493 | ||
|
|
76fa60498e | ||
|
|
8455940b59 | ||
|
|
2d46aa7121 | ||
|
|
bf9b35b9c6 | ||
|
|
f9aa5ae86a | ||
|
|
642d68c482 | ||
|
|
5ff7cdbac8 | ||
|
|
504c54ab0e | ||
|
|
90c17c79de | ||
|
|
0b72bcc5a1 | ||
|
|
dc14f89c9f | ||
|
|
2263adbbe0 | ||
|
|
e29261516f | ||
|
|
f12eaf29a2 | ||
|
|
3e2ab87293 | ||
|
|
15956f4511 | ||
|
|
09d0ce4578 | ||
|
|
9735a35123 |
167
CHANGELOG.md
167
CHANGELOG.md
@@ -17,57 +17,132 @@ and this project adheres to
|
||||
|
||||
### Added
|
||||
|
||||
- Support for a `$dnsrewrite` modifier with an empty `NOERROR` response
|
||||
([#4133]).
|
||||
- `windows/arm64` support ([#3057]).
|
||||
|
||||
### Changed
|
||||
|
||||
- Response filtering is now performed using the record types of the answer
|
||||
section of messages as opposed to the type of the question ([#4238]).
|
||||
- Instead of adding the build time information, the build scripts now use the
|
||||
standardized environment variable [`SOURCE_DATE_EPOCH`][repr] to add the date
|
||||
of the commit from which the binary was built ([#4221]). This should simplify
|
||||
reproducible builds for package maintainers and those who compile their own
|
||||
AdGuard Home.
|
||||
- The setting `local_domain_name` is now in the `dhcp` block in the
|
||||
configuration file to avoid confusion ([#3367]).
|
||||
- The `dns.bogus_nxdomain` configuration file parameter now supports CIDR
|
||||
notation alongside IP addresses ([#1730]).
|
||||
|
||||
#### Configuration Changes
|
||||
|
||||
In this release, the schema version has changed from 12 to 13.
|
||||
|
||||
- Parameter `local_domain_name`, which in schema versions 12 and earlier used to
|
||||
be a part of the `dns` object, is now a part of the `dhcp` object:
|
||||
|
||||
```yaml
|
||||
# BEFORE:
|
||||
'dns':
|
||||
# …
|
||||
'local_domain_name': 'lan'
|
||||
|
||||
# AFTER:
|
||||
'dhcp':
|
||||
# …
|
||||
'local_domain_name': 'lan'
|
||||
```
|
||||
|
||||
To rollback this change, move the parameter back into `dns` and change the
|
||||
`schema_version` back to `12`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
<!--
|
||||
TODO(a.garipov): Remove this deprecation, if v0.108.0 is released before the Go
|
||||
1.18 release.
|
||||
-->
|
||||
- Go 1.17 support. v0.109.0 will require at least Go 1.18 to build.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Optimistic cache now responds with expired items even if those can't be
|
||||
resolved again ([#4254]).
|
||||
- Unnecessarily complex hosts-related logic leading to infinite recursion in
|
||||
some cases ([#4216]).
|
||||
|
||||
### Removed
|
||||
|
||||
- Go 1.16 support.
|
||||
|
||||
### Security
|
||||
|
||||
- Weaker cipher suites that use the CBC (cipher block chaining) mode of
|
||||
operation have been disabled ([#2993]).
|
||||
|
||||
[#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730
|
||||
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
|
||||
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
|
||||
[#3367]: https://github.com/AdguardTeam/AdGuardHome/issues/3367
|
||||
[#4216]: https://github.com/AdguardTeam/AdGuardHome/issues/4216
|
||||
[#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221
|
||||
[#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238
|
||||
[#4254]: https://github.com/AdguardTeam/AdGuardHome/issues/4254
|
||||
|
||||
[repr]: https://reproducible-builds.org/docs/source-date-epoch/
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
## [v0.107.4] - 2022-03-01 (APPROX.)
|
||||
|
||||
See also the [v0.107.4 GitHub milestone][ms-v0.107.4].
|
||||
|
||||
[ms-v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/milestone/41?closed=1
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## [v0.107.3] - 2022-01-25
|
||||
|
||||
See also the [v0.107.3 GitHub milestone][ms-v0.107.3].
|
||||
|
||||
### Added
|
||||
|
||||
- Support for a `$dnsrewrite` modifier with an empty `NOERROR` response
|
||||
([#4133]).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Wrong set of ports checked for duplicates during the initial setup ([#4095]).
|
||||
- Incorrectly invalidated service domains ([#4120]).
|
||||
- Poor testing of domain-specific upstream servers ([#4074]).
|
||||
- Omitted aliases of hosts specified by another line within the OS's hosts file
|
||||
([#4079]).
|
||||
|
||||
### Removed
|
||||
|
||||
- Go 1.16 support.
|
||||
|
||||
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
|
||||
[#4074]: https://github.com/AdguardTeam/AdGuardHome/issues/4074
|
||||
[#4079]: https://github.com/AdguardTeam/AdGuardHome/issues/4079
|
||||
[#4095]: https://github.com/AdguardTeam/AdGuardHome/issues/4095
|
||||
[#4120]: https://github.com/AdguardTeam/AdGuardHome/issues/4120
|
||||
[#4133]: https://github.com/AdguardTeam/AdGuardHome/issues/4133
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
## [v0.107.3] - 2022-02-08 (APPROX.)
|
||||
-->
|
||||
[ms-v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/40?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.2] - 2021-12-29
|
||||
|
||||
See also the [v0.107.2 GitHub milestone][ms-v0.107.2].
|
||||
|
||||
### Fixed
|
||||
|
||||
- Infinite loops when TCP connections time out ([#4042]).
|
||||
|
||||
[#4042]: https://github.com/AdguardTeam/AdGuardHome/issues/4042
|
||||
|
||||
[ms-v0.107.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/38?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.1] - 2021-12-29
|
||||
|
||||
See also the [v0.107.1 GitHub milestone][ms-v0.107.1].
|
||||
|
||||
### Changed
|
||||
|
||||
- The validation error message for duplicated allow- and blocklists in DNS
|
||||
@@ -93,10 +168,14 @@ TODO(a.garipov): Remove this deprecation, if v0.108.0 is released before the Go
|
||||
[#4016]: https://github.com/AdguardTeam/AdGuardHome/issues/4016
|
||||
[#4027]: https://github.com/AdguardTeam/AdGuardHome/issues/4027
|
||||
|
||||
[ms-v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/37?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.0] - 2021-12-21
|
||||
|
||||
See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
|
||||
|
||||
### Added
|
||||
|
||||
- Upstream server information for responses from cache ([#3772]). Note that old
|
||||
@@ -333,10 +412,14 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#3904]: https://github.com/AdguardTeam/AdGuardHome/issues/3904
|
||||
[#3933]: https://github.com/AdguardTeam/AdGuardHome/pull/3933
|
||||
|
||||
[ms-v0.107.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/23?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.106.3] - 2021-05-19
|
||||
|
||||
See also the [v0.106.3 GitHub milestone][ms-v0.106.3].
|
||||
|
||||
### Added
|
||||
|
||||
- Support for reinstall (`-r`) and uninstall (`-u`) flags in the installation
|
||||
@@ -366,20 +449,28 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#3115]: https://github.com/AdguardTeam/AdGuardHome/issues/3115
|
||||
[#3127]: https://github.com/AdguardTeam/AdGuardHome/issues/3127
|
||||
|
||||
[ms-v0.106.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/35?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.106.2] - 2021-05-06
|
||||
|
||||
See also the [v0.106.2 GitHub milestone][ms-v0.106.2].
|
||||
|
||||
### Fixed
|
||||
|
||||
- Uniqueness validation for dynamic DHCP leases ([#3056]).
|
||||
|
||||
[#3056]: https://github.com/AdguardTeam/AdGuardHome/issues/3056
|
||||
|
||||
[ms-v0.106.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/34?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.106.1] - 2021-04-30
|
||||
|
||||
See also the [v0.106.1 GitHub milestone][ms-v0.106.1].
|
||||
|
||||
### Fixed
|
||||
|
||||
- Local domain name handling when the DHCP server is disabled ([#3028]).
|
||||
@@ -390,10 +481,14 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#3027]: https://github.com/AdguardTeam/AdGuardHome/issues/3027
|
||||
[#3028]: https://github.com/AdguardTeam/AdGuardHome/issues/3028
|
||||
|
||||
[ms-v0.106.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/33?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.106.0] - 2021-04-28
|
||||
|
||||
See also the [v0.106.0 GitHub milestone][ms-v0.106.0].
|
||||
|
||||
### Added
|
||||
|
||||
- The ability to block user for login after configurable number of unsuccessful
|
||||
@@ -482,11 +577,14 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#2994]: https://github.com/AdguardTeam/AdGuardHome/issues/2994
|
||||
|
||||
[doq-draft-02]: https://tools.ietf.org/html/draft-ietf-dprive-dnsoquic-02
|
||||
[ms-v0.106.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/26?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.105.2] - 2021-03-10
|
||||
|
||||
See also the [v0.105.2 GitHub milestone][ms-v0.105.2].
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incomplete hostnames with trailing zero-bytes handling ([#2582]).
|
||||
@@ -498,6 +596,11 @@ In this release, the schema version has changed from 10 to 12.
|
||||
- Incomplete DNS upstreams validation ([#2674]).
|
||||
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
|
||||
|
||||
### Security
|
||||
|
||||
- Session token doesn't contain user's information anymore ([#2470]).
|
||||
|
||||
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
|
||||
[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582
|
||||
[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600
|
||||
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
|
||||
@@ -506,16 +609,14 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
|
||||
[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757
|
||||
|
||||
### Security
|
||||
|
||||
- Session token doesn't contain user's information anymore ([#2470]).
|
||||
|
||||
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
|
||||
[ms-v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/32?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.105.1] - 2021-02-15
|
||||
|
||||
See also the [v0.105.1 GitHub milestone][ms-v0.105.1].
|
||||
|
||||
### Changed
|
||||
|
||||
- Increased HTTP API timeouts ([#2671], [#2682]).
|
||||
@@ -555,10 +656,14 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678
|
||||
[#2682]: https://github.com/AdguardTeam/AdGuardHome/issues/2682
|
||||
|
||||
[ms-v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/31?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.105.0] - 2021-02-10
|
||||
|
||||
See also the [v0.105.0 GitHub milestone][ms-v0.105.0].
|
||||
|
||||
### Added
|
||||
|
||||
- Added more services to the "Blocked services" list ([#2224], [#2401]).
|
||||
@@ -656,18 +761,28 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#2639]: https://github.com/AdguardTeam/AdGuardHome/issues/2639
|
||||
[#2646]: https://github.com/AdguardTeam/AdGuardHome/issues/2646
|
||||
|
||||
[ms-v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/27?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.104.3] - 2020-11-19
|
||||
|
||||
See also the [v0.104.3 GitHub milestone][ms-v0.104.3].
|
||||
|
||||
### Fixed
|
||||
|
||||
- The accidentally exposed profiler HTTP API ([#2336]).
|
||||
|
||||
[#2336]: https://github.com/AdguardTeam/AdGuardHome/issues/2336
|
||||
|
||||
[ms-v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/30?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.104.2] - 2020-11-19
|
||||
|
||||
See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
|
||||
|
||||
### Added
|
||||
|
||||
- This changelog :-) ([#2294]).
|
||||
@@ -692,14 +807,18 @@ In this release, the schema version has changed from 10 to 12.
|
||||
[#2324]: https://github.com/AdguardTeam/AdGuardHome/issues/2324
|
||||
[#2325]: https://github.com/AdguardTeam/AdGuardHome/issues/2325
|
||||
|
||||
[ms-v0.104.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/28?closed=1
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...HEAD
|
||||
[v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.2...v0.107.3
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.4...HEAD
|
||||
[v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...v0.107.4
|
||||
-->
|
||||
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.2...HEAD
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...HEAD
|
||||
[v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.2...v0.107.3
|
||||
[v0.107.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.1...v0.107.2
|
||||
[v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.0...v0.107.1
|
||||
[v0.107.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.3...v0.107.0
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="google" content="notranslate">
|
||||
<meta http-equiv="x-dns-prefetch-control" content="off">
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="google" content="notranslate">
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="google" content="notranslate">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Zde je <0>seznam známých poskytovatelů DNS</0>, z nichž si můžete vybrat.",
|
||||
"update_now": "Aktualizovat nyní",
|
||||
"update_failed": "Automatická aktualizace selhala. Prosím <a>následujte tyto kroky</a> a aktualizujte ručně.",
|
||||
"manual_update": "Prosím <a>následujte tyto kroky</a> a aktualizujte ručně.",
|
||||
"processing_update": "Čekejte prosím, AdGuard Home se aktualizuje",
|
||||
"clients_title": "Klienti",
|
||||
"clients_desc": "Konfigurace zařízení připojených k AdGuard Home",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Her er en <0>liste over kendte DNS-udbydere</ 0> at vælge imellem.",
|
||||
"update_now": "Opdatér nu",
|
||||
"update_failed": "Autoopdatering mislykkedes. Følg <a>disse trin</a> for at opdatere manuelt.",
|
||||
"manual_update": "<a>Følg disse trin</a> for at opdatere manuelt.",
|
||||
"processing_update": "Vent venligst, AdGuard Home bliver opdateret",
|
||||
"clients_title": "Klienter",
|
||||
"clients_desc": "Opsæt enheder forbundet til AdGuard Home",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"parallel_requests": "Paralleles Abfragen",
|
||||
"load_balancing": "Lastverteilung",
|
||||
"load_balancing_desc": "Einen Server nach dem anderen abfragen. AdGuard Home verwendet den gewichteten Zufallsalgorithmus, um den Server so auszuwählen, dass der schnellste Server häufiger verwendet wird.",
|
||||
"bootstrap_dns": "Bootstrap DNS-Server starten",
|
||||
"bootstrap_dns": "Bootstrap DNS-Server",
|
||||
"bootstrap_dns_desc": "Bootstrap-DNS-Server werden verwendet, um IP-Adressen der DoH/DoT-Resolver aufzulösen, die Sie als Upstreams angeben.",
|
||||
"local_ptr_title": "Private inverse DNS-Server",
|
||||
"local_ptr_desc": "Die DNS-Server, die AdGuard Home für lokale PTR-Abfragen verwendet. Diese Server werden verwendet, um die Hostnamen von Clients mit privaten IP-Adressen, z. B. „192.168.12.34“, per inverse DNS-Anfragen aufzulösen. Wenn nicht festgelegt, verwendet AdGuard Home die Adressen der Standard-DNS-Auflöser Ihres Betriebssystems mit Ausnahme der Adressen von AdGuard Home selbst.",
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Ungültige IPv6-Adresse",
|
||||
"form_error_ip_format": "Ungültige IP-Adresse",
|
||||
"form_error_mac_format": "Ungültige MAC-Adresse",
|
||||
"form_error_client_id_format": "Ungültiges Client-ID",
|
||||
"form_error_client_id_format": "Client-ID muss nur Zahlen, Kleinbuchstaben und Bindestriche enthalten",
|
||||
"form_error_server_name": "Ungültiger Servername",
|
||||
"form_error_subnet": "Subnetz „{{cidr}}“ enthält nicht die IP-Adresse „{{ip}}“",
|
||||
"form_error_positive": "Muss größer als 0 (Null) sein",
|
||||
@@ -70,9 +70,9 @@
|
||||
"dhcp_error": "AdGuard Home konnte nicht ermitteln, ob es einen anderen aktiven DHCP-Server im Netzwerk gibt.",
|
||||
"dhcp_static_ip_error": "Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Es konnte nicht ermittelt werden, ob diese Netzwerkschnittstelle mit statischer IP-Adresse konfiguriert ist. Bitte legen Sie eine statische IP-Adresse manuell fest.",
|
||||
"dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}</0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}</0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP-Server aktivieren“ klicken.",
|
||||
"dhcp_lease_added": "Statischer Zuweisung „{{key}}“ erfolgreich hinzugefügt",
|
||||
"dhcp_lease_added": "Statische Zuweisung „{{key}}“ erfolgreich hinzugefügt",
|
||||
"dhcp_lease_deleted": "Statische Zuweisung „{{key}}“ erfolgreich entfernt",
|
||||
"dhcp_new_static_lease": "Neuer statischer Zuweisung",
|
||||
"dhcp_new_static_lease": "Neue statische Zuweisung",
|
||||
"dhcp_static_leases_not_found": "Keine statischen DHCP-Zuweisungen gefunden",
|
||||
"dhcp_add_static_lease": "Statische Zuweisung hinzufügen",
|
||||
"dhcp_reset_leases": "Alle Zuweisungen zurücksetzen",
|
||||
@@ -133,8 +133,8 @@
|
||||
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Sperrlisten abgelehnte DNS-Anfragen",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul „Internetsicherheit“ gesperrten DNS-Anfragen",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Anzahl der gesperrten Websites mit jugendgefährdenden Inhalten",
|
||||
"enforced_save_search": "SafeSearch erzwungen",
|
||||
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen SafeSearch für Suchanfragen erzwungen wurde",
|
||||
"enforced_save_search": "Sichere Suche erzwungen",
|
||||
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen Sichere Suche für Suchanfragen erzwungen wurde",
|
||||
"average_processing_time": "Durchschnittliche Bearbeitungsdauer",
|
||||
"average_processing_time_hint": "Durchschnittliche Zeit in Millisekunden zur Bearbeitung von DNS-Anfragen",
|
||||
"block_domain_use_filters_and_hosts": "Domains durch Filter und Host-Dateien sperren",
|
||||
@@ -143,8 +143,8 @@
|
||||
"use_adguard_browsing_sec_hint": "AdGuard Home prüft, ob die Domain durch den Webdienst für Internetsicherheit auf eine Sperrliste gesetzt wurde. Es verwendet eine datenschutzfreundliche Lookup-API, um die Prüfung durchzuführen: Nur ein kurzes Präfix des Domänennamens SHA256-Hash wird an den Server gesendet.",
|
||||
"use_adguard_parental": "AdGuard Webservice für Kindersicherung verwenden",
|
||||
"use_adguard_parental_hint": "AdGuard Home wird prüfen, ob die Domain jugendgefährdende Inhalte enthält. Zum Schutz Ihrer Privatsphäre wird die selbe API wie für den Webservice für Internetsicherheit verwendet.",
|
||||
"enforce_safe_search": "SafeSearch erzwingen",
|
||||
"enforce_save_search_hint": "AdGuard kann SafeSearch für folgende Suchmaschinen erzwingen: Google, YouTube, Bing, DuckDuckGo, Yandex und Pixabay.",
|
||||
"enforce_safe_search": "Sichere Suche verwenden",
|
||||
"enforce_save_search_hint": "AdGuard kann Sichere Suche für folgende Suchmaschinen erzwingen: Google, YouTube, Bing, DuckDuckGo, Yandex und Pixabay.",
|
||||
"no_servers_specified": "Keine Server festgelegt",
|
||||
"general_settings": "Allgemeine Einstellungen",
|
||||
"dns_settings": "DNS-Einstellungen",
|
||||
@@ -167,8 +167,8 @@
|
||||
"enabled_safe_browsing_toast": "Internetsicherheit aktiviert",
|
||||
"disabled_parental_toast": "Kindersicherung deaktiviert",
|
||||
"enabled_parental_toast": "Kindersicherung aktiviert",
|
||||
"disabled_safe_search_toast": "SafeSearch deaktiviert",
|
||||
"enabled_save_search_toast": "SafeSearch aktiviert",
|
||||
"disabled_safe_search_toast": "Sichere Suche deaktiviert",
|
||||
"enabled_save_search_toast": "Sichere Suche aktiviert",
|
||||
"enabled_table_header": "Aktiviert",
|
||||
"name_table_header": "Name",
|
||||
"list_url_table_header": "Adressliste",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Hier finden Sie eine <0>Liste der bekannten DNS-Anbieter</0> zur Auswahl.",
|
||||
"update_now": "Jetzt aktualisieren",
|
||||
"update_failed": "Das automatische Aktualisieren ist fehlgeschlagen. Bitte <a>folgen Sie den Schritten</a>, um manuell zu aktualisieren.",
|
||||
"manual_update": "Bitte <a>befolgen Sie diese Schritte</a>, um manuell zu aktualisieren.",
|
||||
"processing_update": "Bitte warten Sie, AdGuard Home wird aktualisiert …",
|
||||
"clients_title": "Clients",
|
||||
"clients_desc": "Geräte einrichten, die mit AdGuard Home verbunden sind",
|
||||
@@ -626,6 +627,6 @@
|
||||
"experimental": "Experimentell",
|
||||
"use_saved_key": "Zuvor gespeicherten Schlüssel verwenden",
|
||||
"parental_control": "Kindersicherung",
|
||||
"safe_browsing": "Sicheres Surfen",
|
||||
"safe_browsing": "Internetsicherheit",
|
||||
"served_from_cache": "{{value}} <i>(aus dem Zwischenspeicher abgerufen)</i>"
|
||||
}
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Here is a <0>list of known DNS providers</0> to choose from.",
|
||||
"update_now": "Update now",
|
||||
"update_failed": "Auto-update failed. Please <a>follow these steps</a> to update manually.",
|
||||
"manual_update": "Please <a>follow these steps</a> to update manually.",
|
||||
"processing_update": "Please wait, AdGuard Home is being updated",
|
||||
"clients_title": "Clients",
|
||||
"clients_desc": "Configure devices connected to AdGuard Home",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Aquí hay una <0>lista de proveedores DNS</0> conocidos para elegir.",
|
||||
"update_now": "Actualizar ahora",
|
||||
"update_failed": "Error en la actualización automática. Por favor <a>sigue estos pasos</a> para actualizar manualmente.",
|
||||
"manual_update": "Por favor <a>sigue estos pasos</a> para actualizar manualmente.",
|
||||
"processing_update": "Por favor espera, AdGuard Home se está actualizando",
|
||||
"clients_title": "Clientes",
|
||||
"clients_desc": "Configurar dispositivos conectados con AdGuard Home",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"fix": "تعمیر",
|
||||
"dns_providers": "در اینجا یک <0>لیست از سرویس های ارائه دهنده DNS</0> برای انتخاب هست.",
|
||||
"update_now": "حالا بروز رسانی",
|
||||
"update_failed": "بروز رسانی خودکار موفق نشد. لطفا <a href='https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update'>مراحل را دنبال کرده</a> تا بطور دستی بروز رسانی کنید.",
|
||||
"update_failed": "بروز رسانی خودکار موفق نشد. لطفا <a>مراحل را دنبال کرده</a> تا بطور دستی بروز رسانی کنید.",
|
||||
"processing_update": "منتظر بمانید،AdGuard Home در حال بروز رسانی است",
|
||||
"clients_title": "کلاینت ها",
|
||||
"clients_desc": "پیکربندی دستگاه های متصل شده به AdGuard Home",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Katso <0>luettelo tunnetuista DNS-palveluista</0>, joista valita.",
|
||||
"update_now": "Päivitä nyt",
|
||||
"update_failed": "Automaattinen päivitys epäonnistui. Seuraa <a>näitä ohjeita</a> päivittääksesi manuaalisesti.",
|
||||
"manual_update": "Seuraa <a>näitä ohjeita</a> päivittääksesi manuaalisesti.",
|
||||
"processing_update": "Odota kun AdGuard Home päivittyy",
|
||||
"clients_title": "Päätelaitteet",
|
||||
"clients_desc": "Määritä AdGuard Homeen yhdistetyt päätelaitteet",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Adresse IPv6 invalide",
|
||||
"form_error_ip_format": "Adresse IP invalide",
|
||||
"form_error_mac_format": "Adresse MAC invalide",
|
||||
"form_error_client_id_format": "Identifiant de client invalide",
|
||||
"form_error_client_id_format": "L'ID du client ne doit contenir que des chiffres, des lettres minuscules et des traits d'union.",
|
||||
"form_error_server_name": "Nom de serveur invalide",
|
||||
"form_error_subnet": "Le sous-réseau « {{cidr}} » ne contient pas l'adresse IP « {{ip}} »",
|
||||
"form_error_positive": "Doit être supérieur à 0",
|
||||
@@ -163,8 +163,8 @@
|
||||
"apply_btn": "Appliquer",
|
||||
"disabled_filtering_toast": "Filtrage désactivé",
|
||||
"enabled_filtering_toast": "Filtrage activé",
|
||||
"disabled_safe_browsing_toast": "Surfing sécurisé désactivé",
|
||||
"enabled_safe_browsing_toast": "Surfing sécurisé activé",
|
||||
"disabled_safe_browsing_toast": "Navigation sécurisée désactivée",
|
||||
"enabled_safe_browsing_toast": "Navigation sécurisée activée",
|
||||
"disabled_parental_toast": "Contrôle parental désactivé",
|
||||
"enabled_parental_toast": "Contrôle parental activé",
|
||||
"disabled_safe_search_toast": "Recherche sécurisée désactivée",
|
||||
@@ -402,7 +402,8 @@
|
||||
"fix": "Corriger",
|
||||
"dns_providers": "Voici une <0>liste de fournisseurs DNS connus</0>.",
|
||||
"update_now": "Mettre à jour maintenant",
|
||||
"update_failed": "Échec de la mise à jour automatique. Veuillez <a href='https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update'>suivre ces étapes</a> pour mettre à jour manuellement.",
|
||||
"update_failed": "Échec de la mise à jour automatique. Veuillez <a>suivre ces étapes</a> pour mettre à jour manuellement.",
|
||||
"manual_update": "Veuillez <a>suivre ces étapes</a> pour mettre à jour manuellement.",
|
||||
"processing_update": "Veuillez patienter, AdGuard Home est en cours de mise à jour",
|
||||
"clients_title": "Clients",
|
||||
"clients_desc": "Configurer les appareils connectés à AdGuard Home",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Nevažeći IPv6 format",
|
||||
"form_error_ip_format": "Nevažeći format IP adrese",
|
||||
"form_error_mac_format": "Nevažeći MAC format",
|
||||
"form_error_client_id_format": "Nevažeći format ID-a klijenta",
|
||||
"form_error_client_id_format": "ID klijenta može sadržavati samo brojeve, mala slova i crtice",
|
||||
"form_error_server_name": "Nevažeće ime poslužitelja",
|
||||
"form_error_subnet": "Podmrežu \"{{cidr}}\" ne sadrži IP adresu \"{{ip}}\"",
|
||||
"form_error_positive": "Mora biti veće od 0",
|
||||
@@ -164,7 +164,7 @@
|
||||
"disabled_filtering_toast": "Onemogućeno filtriranje",
|
||||
"enabled_filtering_toast": "Omogućeno filtriranje",
|
||||
"disabled_safe_browsing_toast": "Onemogućena Sigurna pretraga",
|
||||
"enabled_safe_browsing_toast": "Omogućena sigurna pretraga",
|
||||
"enabled_safe_browsing_toast": "Omogućena Sigurna pretraga",
|
||||
"disabled_parental_toast": "Onemogućen roditeljski nadzor",
|
||||
"enabled_parental_toast": "Omogućen roditeljski nadzor",
|
||||
"disabled_safe_search_toast": "Onemogućeno sigurno pretraživanje",
|
||||
@@ -588,7 +588,7 @@
|
||||
"show_whitelisted_responses": "Na popisu dopuštenih",
|
||||
"show_processed_responses": "Obrađeno",
|
||||
"blocked_safebrowsing": "Blokirano s Sigurnom pretragom",
|
||||
"blocked_adult_websites": "Blokirala roditeljska zaštita",
|
||||
"blocked_adult_websites": "Blokirano Roditeljskom kontrolom",
|
||||
"blocked_threats": "Blokirane prijetnje",
|
||||
"allowed": "Dopušteno",
|
||||
"filtered": "Filtrirano",
|
||||
|
||||
@@ -37,13 +37,22 @@
|
||||
"dhcp_ipv6_settings": "DHCP IPv6 Beállítások",
|
||||
"form_error_required": "Kötelező mező",
|
||||
"form_error_ip4_format": "Érvénytelen IPv4 cím",
|
||||
"form_error_ip6_format": "Érvénytelen IPv6 formátum",
|
||||
"form_error_ip4_range_start_format": "Érvénytelen IPv4-cím a tartomány kezdetéhez",
|
||||
"form_error_ip4_range_end_format": "Érvénytelen IPv4-cím a tartomány végén",
|
||||
"form_error_ip4_gateway_format": "Érvénytelen IPv4-cím az átjáró",
|
||||
"form_error_ip6_format": "Érvénytelen IPv6 cím",
|
||||
"form_error_ip_format": "Érvénytelen IP-cím",
|
||||
"form_error_mac_format": "Érvénytelen MAC formátum",
|
||||
"form_error_client_id_format": "Érvénytelen kliens ID formátum",
|
||||
"form_error_mac_format": "Érvénytelen MAC cím",
|
||||
"form_error_client_id_format": "Az ügyfél-azonosító csak számokat, kisbetűket és kötőjeleket tartalmazhat",
|
||||
"form_error_server_name": "Érvénytelen szervernév",
|
||||
"form_error_subnet": "A(z) \"{{cidr}}\" alhálózat nem tartalmazza a(z) \"{{ip}}\" IP címet",
|
||||
"form_error_positive": "0-nál nagyobbnak kell lennie",
|
||||
"out_of_range_error": "A tartományon kívül legyen \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete",
|
||||
"greater_range_start_error": "Nagyobbbb legyen, mint a tartomány kezdete",
|
||||
"greater_range_end_error": "Nagyobb legyen, mint a tartomány vége",
|
||||
"subnet_error": "A címeknek egy alhálózatban kell lenniük",
|
||||
"gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen",
|
||||
"dhcp_form_gateway_input": "Átjáró IP",
|
||||
"dhcp_form_subnet_input": "Alhálózati maszk",
|
||||
"dhcp_form_range_title": "IP-címek tartománya",
|
||||
@@ -191,6 +200,7 @@
|
||||
"form_error_url_or_path_format": "Helytelen URL vagy elérési út a listához",
|
||||
"custom_filter_rules": "Egyéni szűrési szabályok",
|
||||
"custom_filter_rules_hint": "Adjon meg egy szabályt egy sorban. Használhat egyszerű hirdetésblokkolási szabályokat vagy hosztfájl szintaxist.",
|
||||
"system_host_files": "Rendszer hosztfájlok",
|
||||
"examples_title": "Példák",
|
||||
"example_meaning_filter_block": "letiltja a hozzáférést az example.org domainhez, valamint annak az összes aldomainjéhez is",
|
||||
"example_meaning_filter_whitelist": "feloldja a hozzáférést az example.org domainhez, valamint annak az összes aldomainjéhez is",
|
||||
@@ -577,7 +587,7 @@
|
||||
"show_blocked_responses": "Blokkolva",
|
||||
"show_whitelisted_responses": "Kivételezett",
|
||||
"show_processed_responses": "Feldolgozva",
|
||||
"blocked_safebrowsing": "Blokkolva a biztonságos böngészés által",
|
||||
"blocked_safebrowsing": "Blokkolva a Biztonságos böngészés által",
|
||||
"blocked_adult_websites": "Szülői felügyelet által blokkolva",
|
||||
"blocked_threats": "Blokkolt fenyegetések",
|
||||
"allowed": "Engedve",
|
||||
@@ -611,7 +621,11 @@
|
||||
"click_to_view_queries": "Kattintson a lekérésekért",
|
||||
"port_53_faq_link": "Az 53-as portot gyakran a \"DNSStubListener\" vagy a \"systemd-resolved\" (rendszer által feloldott) szolgáltatások használják. Kérjük, olvassa el <0>ezt az útmutatót</0> a probléma megoldásához.",
|
||||
"adg_will_drop_dns_queries": "Az AdGuard Home eldobja az összes DNS kérést erről a kliensről.",
|
||||
"filter_allowlist": "FIGYELMEZTETÉS: Ez a művelet a \"{{disallowed_rule}}\" szabályt is kizárja az engedélyezett ügyfelek listájából.",
|
||||
"last_rule_in_allowlist": "Nem lehet letiltani ezt az ügyfelet, mert a \"{{disallowed_rule}}\" szabály kizárása letiltja az \"Allowed clients\" listát.",
|
||||
"experimental": "Kísérleti",
|
||||
"use_saved_key": "Előzőleg mentett kulcs használata",
|
||||
"parental_control": "Szülői felügyelet"
|
||||
"parental_control": "Szülői felügyelet",
|
||||
"safe_browsing": "Biztonságos böngészés",
|
||||
"served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>"
|
||||
}
|
||||
|
||||
@@ -36,10 +36,23 @@
|
||||
"dhcp_ipv4_settings": "Pengaturan DHCP IPv4",
|
||||
"dhcp_ipv6_settings": "Pengaturan DHCP IPv6",
|
||||
"form_error_required": "Kolom yang harus diisi",
|
||||
"form_error_ip_format": "Alamat IP salah",
|
||||
"form_error_ip4_format": "Alamat IPv4 tidak valid",
|
||||
"form_error_ip4_range_start_format": "Alamat IPv4 tidak valid dari rentang awal",
|
||||
"form_error_ip4_range_end_format": "Alamat IPv4 tidak valid dari rentang akhir",
|
||||
"form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid",
|
||||
"form_error_ip6_format": "Alamat IPv6 tidak valid",
|
||||
"form_error_ip_format": "Alamat IP tidak valid",
|
||||
"form_error_mac_format": "Alamat MAC tidak valid",
|
||||
"form_error_client_id_format": "ID Klien hanya boleh berisi angka, huruf kecil, dan tanda hubung",
|
||||
"form_error_server_name": "Nama server tidak valid",
|
||||
"form_error_subnet": "Subnet \"{{cidr}}\" tidak berisi alamat IP \"{{ip}}\"",
|
||||
"form_error_positive": "Harus lebih dari 0",
|
||||
"out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Harus lebih rendah dari rentang awal",
|
||||
"greater_range_start_error": "Harus lebih besar dari rentang awal",
|
||||
"greater_range_end_error": "Harus lebih besar dari rentang akhir",
|
||||
"subnet_error": "Alamat harus dalam satu subnet",
|
||||
"gateway_or_subnet_invalid": "Subnet mask tidak valid",
|
||||
"dhcp_form_gateway_input": "IP gateway",
|
||||
"dhcp_form_subnet_input": "Subnet mask",
|
||||
"dhcp_form_range_title": "Rentang alamat IP",
|
||||
@@ -150,8 +163,8 @@
|
||||
"apply_btn": "Terapkan",
|
||||
"disabled_filtering_toast": "Penyaringan nonaktif",
|
||||
"enabled_filtering_toast": "Penyaringan aktif",
|
||||
"disabled_safe_browsing_toast": "Penelusuran aman dinonaktifkan",
|
||||
"enabled_safe_browsing_toast": "Penelusuran aman diaktifkan",
|
||||
"disabled_safe_browsing_toast": "Penjelajahan Aman dinonaktifkan",
|
||||
"enabled_safe_browsing_toast": "Penjelajahan Aman Diaktifkan",
|
||||
"disabled_parental_toast": "Kontrol orang tua dinonaktifkan",
|
||||
"enabled_parental_toast": "Kontrol orang tua diaktifkan",
|
||||
"disabled_safe_search_toast": "Pencarian aman dinonaktifkan",
|
||||
@@ -187,6 +200,7 @@
|
||||
"form_error_url_or_path_format": "URL atau jalur absolut dari daftar tidak valid",
|
||||
"custom_filter_rules": "Aturan penyaringan khusus",
|
||||
"custom_filter_rules_hint": "Masukkan satu aturan dalam sebuah baris. Anda dapat menggunakan baik aturan adblock maupun sintaks file hosts.",
|
||||
"system_host_files": "File host sistem",
|
||||
"examples_title": "Contoh",
|
||||
"example_meaning_filter_block": "Blokir akses ke example.org dan seluruh subdomainnya",
|
||||
"example_meaning_filter_whitelist": "Buka blokir akses ke domain example.orf dan seluruh subdomainnya",
|
||||
@@ -202,6 +216,7 @@
|
||||
"example_upstream_sdns": "anda bisa menggunakan <0>Stempel DNS</0> untuk <1>DNSCrypt</1> atau pengarah <2>DNS-over-HTTPS</2>",
|
||||
"example_upstream_tcp": "DNS reguler (melalui TCP)",
|
||||
"all_lists_up_to_date_toast": "Semua daftar sudah diperbarui",
|
||||
"updated_upstream_dns_toast": "Server upstream berhasil disimpan",
|
||||
"dns_test_ok_toast": "Server DNS yang ditentukan bekerja dengan benar",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": tidak dapat digunakan, mohon cek bahwa Anda telah menulisnya dengan benar",
|
||||
"unblock": "Buka Blokir",
|
||||
@@ -299,6 +314,7 @@
|
||||
"install_settings_dns_desc": "Anda perlu mengkonfigurasi perangkat atau router anda untuk menggunakan server DNS berikut ini",
|
||||
"install_settings_all_interfaces": "Semua antarmuka",
|
||||
"install_auth_title": "Otentikasi",
|
||||
"install_auth_desc": "Otentikasi kata sandi ke antarmuka web admin AdGuard Home Anda harus dikonfigurasi. Meskipun AdGuard Home hanya dapat diakses di jaringan lokal Anda, tetap penting untuk melindunginya dari akses tak terbatas.",
|
||||
"install_auth_username": "Nama Pengguna",
|
||||
"install_auth_password": "Kata Sandi",
|
||||
"install_auth_confirm": "Konfirmasi kata sandi",
|
||||
@@ -495,6 +511,7 @@
|
||||
"statistics_clear_confirm": "Apakah Anda yakin ingin menghapus statistik?",
|
||||
"statistics_retention_confirm": "Apakah Anda yakin ingin mengubah retensi statistik? Jika Anda menurunkan nilai interval, beberapa data akan hilang",
|
||||
"statistics_cleared": "Statistik berhasil dihapus",
|
||||
"statistics_enable": "Aktifkan statistik",
|
||||
"interval_hours": "{{count}} jam",
|
||||
"interval_hours_plural": "{{count}} jam",
|
||||
"filters_configuration": "Konfigurasi filter",
|
||||
@@ -570,7 +587,7 @@
|
||||
"show_blocked_responses": "Diblokir",
|
||||
"show_whitelisted_responses": "Dalam Daftar Putih",
|
||||
"show_processed_responses": "Terproses",
|
||||
"blocked_safebrowsing": "Terblokir oleh Safebrowsing",
|
||||
"blocked_safebrowsing": "Diblokir oleh Penjelajahan Aman",
|
||||
"blocked_adult_websites": "Diblok oleh Kontrol Orang tua",
|
||||
"blocked_threats": "Blokir Ancaman",
|
||||
"allowed": "Dibolehkan",
|
||||
@@ -604,7 +621,11 @@
|
||||
"click_to_view_queries": "Klik untuk lihat permintaan",
|
||||
"port_53_faq_link": "Port 53 sering ditempati oleh layanan \"DNSStubListener\" atau \"systemd-resolved\". Silakan baca <0>instruksi ini</0> tentang cara menyelesaikan ini.",
|
||||
"adg_will_drop_dns_queries": "AdGuard Home akan menghapus semua permintaan DNS dari klien ini.",
|
||||
"filter_allowlist": "PERINGATAN: Tindakan ini juga akan mengecualikan aturan \"{{disallowed_rule}}\" dari daftar klien yang diizinkan.",
|
||||
"last_rule_in_allowlist": "Tidak dapat melarang klien ini karena mengecualikan aturan \"{{disallowed_rule}}\" akan MENONAKTIFKAN daftar \"Klien yang diizinkan\".",
|
||||
"experimental": "Eksperimental",
|
||||
"use_saved_key": "Gunakan kunci yang disimpan sebelumnya",
|
||||
"parental_control": "Kontrol Orang Tua"
|
||||
"parental_control": "Kontrol Orang Tua",
|
||||
"safe_browsing": "Penjelajahan Aman",
|
||||
"served_from_cache": "{{value}} <i>(disajikan dari cache)</i>"
|
||||
}
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Qui c'è un <0>elenco di fornitori DNS noti</0> da cui scegliere.",
|
||||
"update_now": "Aggiorna ora",
|
||||
"update_failed": "Aggiornamento automatico non riuscito. Ti suggeriamo di <a>seguire questi passaggi</a> per aggiornare manualmente.",
|
||||
"manual_update": "Ti invitiamo a <a>seguire questi passaggi</a> per aggiornare manualmente.",
|
||||
"processing_update": "Perfavore aspetta, AdGuard Home si sta aggiornando",
|
||||
"clients_title": "Client",
|
||||
"clients_desc": "Configura i dispositivi connessi ad AdGuard Home",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "IPv6アドレスが無効です",
|
||||
"form_error_ip_format": "IPアドレスが無効です",
|
||||
"form_error_mac_format": "MACアドレスが無効です",
|
||||
"form_error_client_id_format": "クライアントIDが無効です",
|
||||
"form_error_client_id_format": "クライアントIDには、数字、小文字、ハイフンのみが使われている必要があります",
|
||||
"form_error_server_name": "サーバ名が無効です",
|
||||
"form_error_subnet": "IPアドレス「{{ip}}」はサブネット「{{cidr}}」に含まれていません",
|
||||
"form_error_positive": "0より大きい必要があります",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "こちらは、選択可能な<0>既知のDNSプロバイダの一覧</0>です。",
|
||||
"update_now": "今すぐ更新する",
|
||||
"update_failed": "自動更新に失敗しました。手動で更新するには、<a>手順に従って</a>ください。",
|
||||
"manual_update": "手動でアップデートするには、<a>こちらの手順</a>を使ってください。",
|
||||
"processing_update": "AdGuard Homeを更新しています。しばらくお待ちください",
|
||||
"clients_title": "クライアント",
|
||||
"clients_desc": "AdGuard Homeに接続されているデバイスを設定します",
|
||||
@@ -587,8 +588,8 @@
|
||||
"show_blocked_responses": "ブロック済",
|
||||
"show_whitelisted_responses": "ホワイトリストにあり",
|
||||
"show_processed_responses": "処理済",
|
||||
"blocked_safebrowsing": "ブロックされたセーフブラウジング",
|
||||
"blocked_adult_websites": "ペアレンタルコントロールによってブロックされました",
|
||||
"blocked_safebrowsing": "セーフブラウジングによってブロック済み",
|
||||
"blocked_adult_websites": "ペアレンタルコントロールによってブロック済み",
|
||||
"blocked_threats": "ブロックされた脅威",
|
||||
"allowed": "許可",
|
||||
"filtered": "フィルタで処理",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "잘못된 IPv6 형식",
|
||||
"form_error_ip_format": "잘못된 IP 형식",
|
||||
"form_error_mac_format": "잘못된 MAC 형식",
|
||||
"form_error_client_id_format": "잘못된 클라이언트 ID 형식",
|
||||
"form_error_client_id_format": "클라이언트 ID는 숫자, 소문자 및 하이픈만 포함해야 합니다",
|
||||
"form_error_server_name": "유효하지 않은 서버 이름입니다",
|
||||
"form_error_subnet": "서브넷 \"{{cidr}}\"에 \"{{ip}}\" IP 주소가 없습니다",
|
||||
"form_error_positive": "0보다 커야 합니다",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "다음은 선택할 수 있는 <0>알려진 DNS 공급자 목록</0>입니다.",
|
||||
"update_now": "지금 업데이트",
|
||||
"update_failed": "자동 업데이트 실패 되었습니다. <a> 단계를 따라 수동으로 업데이트하세요</a>",
|
||||
"manual_update": "<a>절차를 따라</a> 수동으로 업데이트하십시오.",
|
||||
"processing_update": "잠시만 기다려주세요, AdGuard Home가 업데이트 중입니다.",
|
||||
"clients_title": "클라이언트",
|
||||
"clients_desc": "AdGuard Home에 연결할 기기들을 설정",
|
||||
@@ -587,8 +588,8 @@
|
||||
"show_blocked_responses": "차단됨",
|
||||
"show_whitelisted_responses": "예외 적용됨",
|
||||
"show_processed_responses": "처리됨",
|
||||
"blocked_safebrowsing": "차단된 세이프 브라우징",
|
||||
"blocked_adult_websites": "자녀 보호로 차단됨",
|
||||
"blocked_safebrowsing": "세이프 브라우징에 의해 차단됨",
|
||||
"blocked_adult_websites": "자녀 보호에 의해 차단됨",
|
||||
"blocked_threats": "차단된 위협",
|
||||
"allowed": "허용됨",
|
||||
"filtered": "필터링됨",
|
||||
@@ -626,6 +627,6 @@
|
||||
"experimental": "실험",
|
||||
"use_saved_key": "이전에 저장했던 키 사용하기",
|
||||
"parental_control": "자녀 보호",
|
||||
"safe_browsing": "안전한 브라우징",
|
||||
"safe_browsing": "세이프 브라우징",
|
||||
"served_from_cache": "{{value}} <i>(캐시에서 제공)</i>"
|
||||
}
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "hier is een <0>lijst of gekende DNS providers</0> waarvan je kan kiezen.",
|
||||
"update_now": "Update nu",
|
||||
"update_failed": "Automatisch bijwerken is mislukt. <a>Volg deze stappen</a> om handmatig bij te werken.",
|
||||
"manual_update": "<a>Volg deze stappen</a> om handmatig bij te werken.",
|
||||
"processing_update": "Even geduld, AdGuard Home wordt bijgewerkt",
|
||||
"clients_title": "Gebruikers",
|
||||
"clients_desc": "Configureer apparaten die gebruik maken van AdGuard Home",
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
{
|
||||
"client_settings": "Klientinnstillinger",
|
||||
"example_upstream_reserved": "Du kan bestemme en oppstrøms-DNS <0>for et spesifikt domene(r)</0>",
|
||||
"example_upstream_comment": "Du kan spesifisere en kommentar",
|
||||
"upstream_parallel": "Bruk parallele forespørsler for å få oppfarten på behandlinger, ved å forespørre til alle oppstrømstjenerne samtidig",
|
||||
"parallel_requests": "Parallelle forespørsler",
|
||||
"load_balancing": "Pågangstrykk-utjevning",
|
||||
"load_balancing_desc": "Forespør én tjener om gangen. AdGuard Home vil bruke en 'vektlagt tilfeldig valg'-algoritme for å velge tjener, slik at den raskeste tjeneren blir brukt oftere.",
|
||||
"bootstrap_dns": "Bootstrap-DNS-tjenere",
|
||||
"bootstrap_dns_desc": "Bootstrap-DNS-tjenere brukes til å oppklare IP-adressene til DoH/DoT-oppklarerene som du har valgt som oppstrømstjenere.",
|
||||
"local_ptr_title": "Private DNS-tjenere",
|
||||
"local_ptr_desc": "DNS-tjenerne som AdGuard Home bruker for lokale PTR-spørringer. Disse tjenerne brukes til å løse vertsnavnene til klienter med private IP-adresser, for eksempel \"192.168.12.34\", ved bruk av omvendt DNS. Hvis det ikke er angitt, bruker AdGuard Home adressene til standard-DNS-løserne til operativsystemet ditt, bortsett fra adressene til selve AdGuard Home.",
|
||||
"use_private_ptr_resolvers_title": "Bruk private omvendte DNS-løsere",
|
||||
"check_dhcp_servers": "Se etter DHCP-tjenere",
|
||||
"save_config": "Lagre oppsettet",
|
||||
"enabled_dhcp": "DHCP-tjeneren ble skrudd på",
|
||||
"disabled_dhcp": "DHCP-tjeneren ble skrudd av",
|
||||
"unavailable_dhcp": "DHCP er utilgjengelig",
|
||||
@@ -102,6 +109,7 @@
|
||||
"use_adguard_parental": "Benytt AdGuard sin foreldrekontroll-nettjeneste",
|
||||
"use_adguard_parental_hint": "AdGuard Home vil sjekke om domenet inneholder erotisk materiale. Den benytter den samme privatlivsvennlige API-en som nettlesersikkerhetstjenesten.",
|
||||
"enforce_safe_search": "Påtving barnevennlige søk",
|
||||
"enforce_save_search_hint": "AdGuard Home kan fremtvinge \"Safe Search\" i de følgende søkemotorene: Google, YouTube, Bing, DuckDuckGo, Yandex, og Pixabay.",
|
||||
"no_servers_specified": "Ingen tjenere er spesifisert",
|
||||
"general_settings": "Generelle innstillinger",
|
||||
"dns_settings": "DNS-innstillinger",
|
||||
@@ -113,6 +121,7 @@
|
||||
"encryption_settings": "Krypteringsinnstillinger",
|
||||
"dhcp_settings": "DHCP-innstillinger",
|
||||
"upstream_dns": "Oppstrøms-DNS-tjenere",
|
||||
"upstream_dns_help": "Skriv inn én tjeneradresse per linje. <a>Lær mer</a> om å konfigurere oppstrøms-DNS-tjenere.",
|
||||
"upstream_dns_configured_in_file": "Satt opp i {{path}}",
|
||||
"test_upstream_btn": "Test oppstrømstilkoblinger",
|
||||
"upstreams": "Oppstrømstjenere",
|
||||
@@ -156,6 +165,7 @@
|
||||
"form_error_url_or_path_format": "Listens URL eller fulle filbane er ugyldig",
|
||||
"custom_filter_rules": "Selvvalgte filtreringsregler",
|
||||
"custom_filter_rules_hint": "Skriv inn én oppføring per linje. Du kan bruke adblock-oppføringer, «hosts»-filsyntaks, eller rå domener.",
|
||||
"system_host_files": "System-'hosts'-filer",
|
||||
"examples_title": "Eksempler",
|
||||
"example_meaning_filter_block": "blokker tilgang til 'example.org'-domenet og alle dens underdomener",
|
||||
"example_meaning_filter_whitelist": "opphev blokkeringen av 'example.org'-domenet og alle dens underdomener",
|
||||
@@ -308,6 +318,7 @@
|
||||
"encryption_desc": "Krypteringsstøtte (HTTPS/TLS) for både DNS og admin-nettgrensesnittet",
|
||||
"encryption_server": "Tjenerens navn",
|
||||
"encryption_server_enter": "Skriv inn domenenavnet ditt",
|
||||
"encryption_server_desc": "For å kunne bruke HTTPS, må du skrive inn tjenernavnet som samsvarer med ditt SSL-sertifikat eller jokertegnsertifikat. Hvis feltet er tomt, vil den akseptere TLS-tilkoblinger til ethvert domene.",
|
||||
"encryption_redirect": "Automatisk omdiriger til HTTPS",
|
||||
"encryption_redirect_desc": "Dersom dette er valgt, vil AdGuard Home automatisk omdirigere deg fra HTTP til HTTPS-adresser.",
|
||||
"encryption_https": "HTTPS-port",
|
||||
@@ -339,6 +350,7 @@
|
||||
"form_error_password": "Passordet samsvarer ikke",
|
||||
"reset_settings": "Tilbakestill innstillinger",
|
||||
"update_announcement": "AdGuard Home {{version}} er nå tilgjengelig! <0>Klikk her</0> for mere informasjon.",
|
||||
"setup_guide": "Oppsettsveiledning",
|
||||
"dns_addresses": "DNS-adresser",
|
||||
"dns_start": "DNS-tjeneren starter opp",
|
||||
"dns_status_error": "Feil ved sjekk av DNS-tjenerstatusen",
|
||||
@@ -360,6 +372,7 @@
|
||||
"client_edit": "Rediger klienten",
|
||||
"client_identifier": "Identifikator",
|
||||
"ip_address": "IP-adresse",
|
||||
"client_identifier_desc": "Klienter kan bli identifisert gjennom IP-adressen, CIDR, MAC-adressen, eller en spesiell klient-ID (kan også brukes for DoT/DoH/DoQ). <0>Her</0> kan du lære mer om å identifisere klienter.",
|
||||
"form_enter_ip": "Skriv inn IP",
|
||||
"form_enter_mac": "Skriv inn MAC",
|
||||
"form_enter_id": "Skriv inn identifikator",
|
||||
@@ -382,6 +395,7 @@
|
||||
"access_disallowed_title": "Klienter som skal avvises",
|
||||
"access_disallowed_desc": "En liste over CIDR- eller IP-adresser. Dersom dette er satt opp, vil AdGuard Home avslå forespørsler fra disse IP-adressene.",
|
||||
"access_blocked_title": "Blokkerte domener",
|
||||
"access_blocked_desc": "Ikke forveksle dette med filtre. AdGuard Home vil nekte å behandle DNS-forespørsler som har disse domenene, og disse forespørslene dukker ikke engang opp i forespørselsloggen. Du kan spesifisere nøyaktige domene navn, jokertegn, eller URL-filterregler, f.eks. «example.org», «*.example.log» eller «||example.org^» derav.",
|
||||
"access_settings_saved": "Tilgangsinnstillingene ble vellykket lagret",
|
||||
"updates_checked": "Oppdateringene ble vellykket sett etter",
|
||||
"updates_version_equal": "AdGuard Home er fullt oppdatert",
|
||||
@@ -390,6 +404,7 @@
|
||||
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Benytt <1>{{address}}</1>-strengen.",
|
||||
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Benytt <1>{{address}}</1>-strengen.",
|
||||
"setup_dns_privacy_3": "<0>Her er en liste over programvarer du kan bruke.</0>",
|
||||
"setup_dns_privacy_4": "På en iOS 14 eller macOS Big Sur-enhet kan du laste ned en spesiell '.mobileconfig'-fil som legger til<highlight>DNS-over-HTTPS</highlight>- eller<highlight>DNS-over-TLS</highlight>-tjenere til DNS-innstillingene.",
|
||||
"setup_dns_privacy_android_1": "Android 9 har innebygd støtte for DNS-over-TLS. For å sette det opp, gå til Innstillinger → Nettverk og internett → Avansert → Privat DNS, og skriv inn domenenavnet ditt der.",
|
||||
"setup_dns_privacy_android_2": "<0>AdGuard for Android</0> støtter <1>DNS-over-HTTPS</1> og <1>DNS-over-TLS</1>.",
|
||||
"setup_dns_privacy_android_3": "<0>Intra</0> legger til <1>DNS-over-HTTPS</1>-støtte i Android.",
|
||||
@@ -449,6 +464,7 @@
|
||||
"statistics_clear_confirm": "Er du sikker på at du vil slette statistikkene?",
|
||||
"statistics_retention_confirm": "Er du sikker på at du vil endre hvor lenge statistikkene skal beholdes? Hvis du reduserer den interne verdien, vil noe av dataene gå tapt",
|
||||
"statistics_cleared": "Statistikkene ble vellykket tømt",
|
||||
"statistics_enable": "Skru på statistikker",
|
||||
"interval_hours": "{{count}} time",
|
||||
"interval_hours_plural": "{{count}} timer",
|
||||
"filters_configuration": "Oppsett av filtre",
|
||||
@@ -541,6 +557,8 @@
|
||||
"cache_ttl_min_override_desc": "Overstyr korte levetidsverdier (i sekunder) som mottas fra oppstrømstjeneren under mellomlagring av DNS-responser",
|
||||
"cache_ttl_max_override_desc": "Velg en maks-levetidsverdi (i sekunder) for oppføringer i DNS-mellomlageret",
|
||||
"ttl_cache_validation": "Minimums-mellomlagringslevetidsverdien må være mindre enn eller det samme som maksverdien",
|
||||
"cache_optimistic": "Optimistisk mellomlagring",
|
||||
"cache_optimistic_desc": "Få AdGuard Home til å svare fra hurtigbufferen selv når oppføringene er utløpt, og prøv også å oppfriske dem.",
|
||||
"filter_category_general": "Generelt",
|
||||
"filter_category_security": "Sikkerhet",
|
||||
"filter_category_regional": "Regional",
|
||||
@@ -554,5 +572,7 @@
|
||||
"port_53_faq_link": "Port 53 er ofte opptatt av «DNSStubListener»- eller «systemd-resolved»-tjenestene. Vennligst les <0>denne instruksjonen</0> om hvordan man løser dette.",
|
||||
"adg_will_drop_dns_queries": "AdGuard Home vil droppe alle DNS-forespørsler fra denne klienten.",
|
||||
"experimental": "Eksperimentell",
|
||||
"parental_control": "Foreldrekontroll"
|
||||
"use_saved_key": "Bruk den tidligere lagrede nøkkelen",
|
||||
"parental_control": "Foreldrekontroll",
|
||||
"served_from_cache": "{{value}} <i>(formidlet fra mellomlageret)</i>"
|
||||
}
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Oto lista <0>znanych dostawców DNS</0> do wyboru.",
|
||||
"update_now": "Aktualizuj teraz",
|
||||
"update_failed": "Automatyczna aktualizacja nie powiodła się. Proszę <a>wykonaj kroki</a> aby zaktualizować ręcznie.",
|
||||
"manual_update": "Proszę <a>wykonać te czynności</a>, aby zaktualizować ręcznie.",
|
||||
"processing_update": "Poczekaj, trwa aktualizacja AdGuard Home",
|
||||
"clients_title": "Klienci",
|
||||
"clients_desc": "Skonfiguruj urządzenia podłączone do AdGuard Home",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Aqui está uma <0>lista de provedores de DNS conhecidos</0> para escolher.",
|
||||
"update_now": "Atualizar agora",
|
||||
"update_failed": "A atualização automática falhou. Por favor, <a>siga estes passos</a> para atualizar manualmente.",
|
||||
"manual_update": "Por favor, <a>siga estes passos</a> para atualizar manualmente.",
|
||||
"processing_update": "Por favor, aguarde enquanto o AdGuard Home está sendo atualizado",
|
||||
"clients_title": "Clientes",
|
||||
"clients_desc": "Configure dispositivos conectados ao AdGuard",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Aqui está uma <0>lista de provedores de DNS conhecidos</0> para escolher.",
|
||||
"update_now": "Atualizar agora",
|
||||
"update_failed": "A atualização automática falhou. Por favor, <a>siga estes passos</a> para atualizar manualmente.",
|
||||
"manual_update": "Por favor, <a>siga estes passos</a> para atualizar manualmente.",
|
||||
"processing_update": "Por favor espere, o AdGuard Home está a atualizar-se",
|
||||
"clients_title": "Clientes",
|
||||
"clients_desc": "Configure os dispositivos ligados ao AdGuard",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Iată o <0>listă de furnizori DNS cunoscuți</0> ce pot fi aleși.",
|
||||
"update_now": "Actualizați acum",
|
||||
"update_failed": "Auto-actualizarea a eșuat. Vă rugăm să <a>urmați aceste etape</a> pentru a actualiza manual.",
|
||||
"manual_update": "Vă rugăm <a>să urmați etapele următoare</a> pentru a actualiza manual.",
|
||||
"processing_update": "Vă rugăm să așteptați, AdGuard Home se actualizează...",
|
||||
"clients_title": "Clienți",
|
||||
"clients_desc": "Configură aparatele conectate la AdGuard Home",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "<0>Список известных DNS-провайдеров</0> на выбор.",
|
||||
"update_now": "Обновить сейчас",
|
||||
"update_failed": "Ошибка авто-обновления. Пожалуйста, <a>следуйте инструкции</a> для обновления вручную.",
|
||||
"manual_update": "Пожалуйста, <a>следуйте инструкции</a> для обновления вручную.",
|
||||
"processing_update": "Пожалуйста, подождите, AdGuard Home обновляется",
|
||||
"clients_title": "Клиенты",
|
||||
"clients_desc": "Настройте устройства, использующие AdGuard Home",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Neplatná IPv6 adresa",
|
||||
"form_error_ip_format": "Neplatná IP adresa",
|
||||
"form_error_mac_format": "Neplatná MAC adresa",
|
||||
"form_error_client_id_format": "Neplatné ID klienta",
|
||||
"form_error_client_id_format": "ID klienta musí obsahovať iba čísla, malé písmená a spojovníky",
|
||||
"form_error_server_name": "Neplatné meno servera",
|
||||
"form_error_subnet": "Podsieť \"{{cidr}}\" neobsahuje IP adresu \"{{ip}}\"",
|
||||
"form_error_positive": "Musí byť väčšie ako 0",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Tu je <0>zoznam známych poskytovateľov DNS</0>, z ktorého si vyberiete.",
|
||||
"update_now": "Aktualizovať teraz",
|
||||
"update_failed": "Automatická aktualizácia zlyhala. Prosím <a>sledujte postup</a> pre manuálnu aktualizáciu.",
|
||||
"manual_update": "Pre manuálnu aktualizáciu prosím <a>sledujte tento postup</a>.",
|
||||
"processing_update": "Čakajte prosím, AdGuard Home sa aktualizuje",
|
||||
"clients_title": "Klienti",
|
||||
"clients_desc": "Konfigurácia zariadení pripojených k AdGuard Home",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Neveljaven naslov IPv6",
|
||||
"form_error_ip_format": "Neveljaven naslov IP",
|
||||
"form_error_mac_format": "Neveljaven naslov MAC",
|
||||
"form_error_client_id_format": "Neveljaven ID odjemalca",
|
||||
"form_error_client_id_format": "ID odjemalca mora vsebovati samo številke, male črke in vezaje",
|
||||
"form_error_server_name": "Neveljavno ime strežnika",
|
||||
"form_error_subnet": "Podomrežje \"{{cidr}}\" ne vsebuje naslova IP \"{{ip}}\"",
|
||||
"form_error_positive": "Mora biti večja od 0",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Tukaj je <0>seznam znanih ponudnikov DNS</0>, med katerimi lahko izbirate.",
|
||||
"update_now": "Posodobi zdaj",
|
||||
"update_failed": "Samodejna posodobitev ni uspela. Prosimo <a>sledite korakom</a>, da ročno posodobite.",
|
||||
"manual_update": "Za ročno posodobitev <a>sledite tem korakom</a>.",
|
||||
"processing_update": "Prosimo, počakajte. AdGuard Home se posodablja!",
|
||||
"clients_title": "Odjemalci",
|
||||
"clients_desc": "Konfigurirajte naprave, ki so povezane z AdGuard Home",
|
||||
|
||||
@@ -1,26 +1,58 @@
|
||||
{
|
||||
"client_settings": "Klientinställningar",
|
||||
"example_upstream_reserved": "Du kan specificera DNS-uppström <0>för en specifik domän</0>",
|
||||
"example_upstream_comment": "Du kan ange en kommentar",
|
||||
"upstream_parallel": "Använd parallella förfrågningar för att snabba upp dessa genom att fråga alla uppströmsservrar samtidigt.",
|
||||
"parallel_requests": "Parallella förfrågningar",
|
||||
"load_balancing": "Lastbalansering",
|
||||
"load_balancing_desc": "Fråga en uppströmsserver åt gången. AdGuard Home använder sin viktade slumpmässiga algoritm för att välja server så att den snabbaste servern används oftare.",
|
||||
"bootstrap_dns": "Bootstrap-DNS-servrar",
|
||||
"bootstrap_dns_desc": "Bootstrap-DNS-servrar används för att slå upp DoH/DoT-resolvrarnas IP-adresser som du specificerat som uppström.",
|
||||
"local_ptr_title": "Privata omvända DNS-servrar",
|
||||
"local_ptr_desc": "DNS servrarna som AdGuard Home använder för lokala PTR frågor. Dessa servrar används för att lösa värdnamnen på klienter med privata IP-adresser, till exempel \"192.168.12.34\", genom omvänd DNS. Om inga servrar angetts använder AdGuard Home adresserna till standard DNS servrar för ditt operativsystem förutom adresserna till AdGuard Home själv.",
|
||||
"local_ptr_default_resolver": "Som standard använder AdGuard Home följande omvända DNS upplösare: {{ip}}.",
|
||||
"local_ptr_no_default_resolver": "AdGuard Home kunde inte fastställa lämpliga privata omvända DNS upplösare för detta system.",
|
||||
"local_ptr_placeholder": "Ange en serveradress per rad",
|
||||
"resolve_clients_title": "Aktivera omvänd upplösning av klienters IP-adresser",
|
||||
"resolve_clients_desc": "Lös upp klienternas värdnamn med omvänt uppslag av klienternas IP-adresser genom att skicka PTR-frågor till motsvarande upplösare (privata DNS-servrar för lokala klienter, uppströmsservrar för klienter med offentliga IP-adresser).",
|
||||
"use_private_ptr_resolvers_title": "Använd privata omvända DNS upplösare",
|
||||
"use_private_ptr_resolvers_desc": "Utför omvända DNS-sökningar för lokalt betjänade adresser med dessa uppströmsservrar. Om det är inaktiverat svarar AdGuard Home med NXDOMAIN på alla sådana PTR-förfrågningar förutom klienter kända från DHCP, /etc/hosts, och så vidare.",
|
||||
"check_dhcp_servers": "Letar efter DHCP-servrar",
|
||||
"save_config": "Spara konfiguration",
|
||||
"enabled_dhcp": "DHCP-server aktiverad",
|
||||
"disabled_dhcp": "Dhcp-server avaktiverad",
|
||||
"unavailable_dhcp": "DHCP är inte tillgängligt",
|
||||
"unavailable_dhcp_desc": "AdGuard Home kan inte köra en DHCP-server på ditt operativsystem",
|
||||
"dhcp_title": "DHCP-server (experimentell)",
|
||||
"dhcp_description": "Om din router inte har inställningar för DHCP kan du använda AdGuards inbyggda server.",
|
||||
"dhcp_enable": "Aktivera DHCP.-server",
|
||||
"dhcp_disable": "Avaktivera DHCP-server",
|
||||
"dhcp_not_found": "Det är säkert att aktivera den inbyggda DHCP-servern eftersom AdGuard Home inte hittade några aktiva DHCP-servrar i nätverket. Du bör dock kontrollera det igen manuellt eftersom den automatiska sökningenn efter DHCP-servrar inte ger 100 % garanti.",
|
||||
"dhcp_found": "Några aktiva DHCP-servar upptäcktes. Det är inte säkert att aktivera inbyggda DHCP-servrar.",
|
||||
"dhcp_leases": "DHCP-lease",
|
||||
"dhcp_static_leases": "Statiska DHCP-leases",
|
||||
"dhcp_leases_not_found": "Ingen DHCP-lease hittad",
|
||||
"dhcp_config_saved": "DHCP-konfigurationen har sparats",
|
||||
"dhcp_ipv4_settings": "DHCP IPv4 inställningar",
|
||||
"dhcp_ipv6_settings": "DHCP IPv6 inställningar",
|
||||
"form_error_required": "Obligatoriskt fält",
|
||||
"form_error_ip4_format": "Ogiltig IPv4-adress",
|
||||
"form_error_ip4_range_start_format": "Ogiltig IPv4-adress för starten av intervallet",
|
||||
"form_error_ip4_range_end_format": "Ogiltig IPv4-adress för slutet av intervallet",
|
||||
"form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen",
|
||||
"form_error_ip6_format": "Ogiltig IPv6-adress",
|
||||
"form_error_ip_format": "Ogiltig IP-adress",
|
||||
"form_error_mac_format": "Ogiltig MAC-adress",
|
||||
"form_error_client_id_format": "Ogiltigt klient-ID",
|
||||
"form_error_server_name": "Ogiltigt servernamn",
|
||||
"form_error_subnet": "Subnätet \"{{cidr}}\" innehåller inte IP-adressen \"{{ip}}\"",
|
||||
"form_error_positive": "Måste vara större än noll",
|
||||
"out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Måste vara lägre än starten på intervallet",
|
||||
"greater_range_start_error": "Måste vara högre än starten på intervallet",
|
||||
"greater_range_end_error": "Måste vara större än intervallets slut",
|
||||
"subnet_error": "Adresser måste finnas i ett subnät",
|
||||
"gateway_or_subnet_invalid": "Subnätmask ogiltig",
|
||||
"dhcp_form_gateway_input": "Gateway-IP",
|
||||
"dhcp_form_subnet_input": "Subnetmask",
|
||||
"dhcp_form_range_title": "IP-adressgränser",
|
||||
@@ -31,17 +63,30 @@
|
||||
"dhcp_interface_select": "Välj DHCP-gränssnitt",
|
||||
"dhcp_hardware_address": "Hårdvaruadress",
|
||||
"dhcp_ip_addresses": "IP-adresser",
|
||||
"ip": "IP",
|
||||
"dhcp_table_hostname": "Värdnamn",
|
||||
"dhcp_table_expires": "Utgår",
|
||||
"dhcp_warning": "Om du vill använda den inbyggda DHCP servern ändå, se till att det inte finns några andra aktiva DHCP servrar. Annars kan den störa internetanslutningen för anslutna enheter!",
|
||||
"dhcp_error": "Vi kunde inte avgöra om det finns en till DHCP-server på nätverket.",
|
||||
"dhcp_static_ip_error": "För att kunna använda en DHCP-server måste det finnas en statisk IP-adress. AdGuard Home kunde inte avgöra om nätverksgränssnittet är konfigurerat med en statisk IP-adress. Ställ in en statisk IP-adress manuellt.",
|
||||
"dhcp_dynamic_ip_found": "Din enhet använder en dynamisk IP-adress för gränssnittet <0>{{interfaceName}}</0>. För att kunna använda DHCP-servern behövs en statisk IP-adress. Din nuvarande IP-adress är <0>{{ipAddress}}</0>. AdGuard Home kommer automatiskt att göra denna IP-adress statisk om du trycker på knappen \"Aktivera DHCP\".",
|
||||
"dhcp_lease_added": "Statisk lease \"{{key}}\" har lagts till",
|
||||
"dhcp_lease_deleted": "Statisk lease \"{{key}}\" har raderats",
|
||||
"dhcp_new_static_lease": "Ny statisk lease",
|
||||
"dhcp_static_leases_not_found": "Inga statiska DHCP-leases hittade",
|
||||
"dhcp_add_static_lease": "Lägg till statisk lease",
|
||||
"dhcp_reset_leases": "Återställ alla leasingavtal",
|
||||
"dhcp_reset_leases_confirm": "Är du säker på att du vill ta bort alla leasingavtal?",
|
||||
"dhcp_reset_leases_success": "DHCP-leasing har återställts",
|
||||
"dhcp_reset": "Är du säker på att du vill ta bort DHCP inställningarna?",
|
||||
"country": "Land",
|
||||
"city": "Stad",
|
||||
"delete_confirm": "Är du säker på att du vill ta bort \"{{key}}\"?",
|
||||
"form_enter_hostname": "Skriv in värdnamn",
|
||||
"error_details": "Felinformation",
|
||||
"response_details": "Svarsdetaljer",
|
||||
"request_details": "Förfrågningsdetaljer",
|
||||
"client_details": "Klient information",
|
||||
"details": "Detaljer",
|
||||
"back": "Tiilbaka",
|
||||
"dashboard": "Kontrollpanel",
|
||||
@@ -49,6 +94,8 @@
|
||||
"filters": "Filter",
|
||||
"filter": "Filter",
|
||||
"query_log": "Förfrågningslogg",
|
||||
"compact": "Komprimera",
|
||||
"nothing_found": "Inget hittades",
|
||||
"faq": "FAQ",
|
||||
"version": "version",
|
||||
"address": "Adress",
|
||||
@@ -72,52 +119,88 @@
|
||||
"for_last_24_hours": "under de senaste 24 timmarna",
|
||||
"for_last_days": "för den senaste {{count}} dagen",
|
||||
"for_last_days_plural": "för de senaste {{count}} dagarna",
|
||||
"stats_disabled": "Statistiken har inaktiverats. Du kan aktivera det från <0>inställningssidan</0>.",
|
||||
"stats_disabled_short": "Statistiken har inaktiverats",
|
||||
"no_domains_found": "Inga domäner hittade",
|
||||
"requests_count": "Förfrågningsantal",
|
||||
"top_blocked_domains": "Flest blockerade domäner",
|
||||
"top_clients": "Toppklienter",
|
||||
"no_clients_found": "Inga klienter hittade",
|
||||
"general_statistics": "Allmän statistik",
|
||||
"number_of_dns_query_days": "Antalet DNS-förfrågningar som utfördes under senaste {{count}} dagen",
|
||||
"number_of_dns_query_days_plural": "Ett antal DNS förfrågningar utfördes under de senaste {{count}} dagarna",
|
||||
"number_of_dns_query_24_hours": "Antalet DNS-förfrågningar som utfördes under de senaste 24 timmarna",
|
||||
"number_of_dns_query_blocked_24_hours": "Antalet DNS-förfrågningar som blockerades av annonsfilter och värdens blockeringsklistor",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Antalet DNS-förfrågningar som blockerades av AdGuards modul för surfsäkerhet",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Antalet vuxensajter som blockerats",
|
||||
"enforced_save_search": "Aktivering av Säker surf",
|
||||
"number_of_dns_query_to_safe_search": "Antalet DNS-förfrågningar mot sökmotorer där Säker surf tvingats",
|
||||
"average_processing_time": "Genomsnittlig processtid",
|
||||
"average_processing_time_hint": "Genomsnittlig processtid i millisekunder för DNS-förfrågning",
|
||||
"block_domain_use_filters_and_hosts": "Blockera domäner med filter- och värdfiler",
|
||||
"filters_block_toggle_hint": "Du kan ställa in egna blockerings regler i <a>Filterinställningar</a>.",
|
||||
"use_adguard_browsing_sec": "Använd AdGuards webbservice för surfsäkerhet",
|
||||
"use_adguard_browsing_sec_hint": "AdGuard Home kommer att kontrollera om en domän är svartlistad i webbservicens surfsäkerhet. Med en integritetsvänlig metod görs en API-lookup för att kontrollera : endast en kort prefix i domännamnet SHA256 hash skickas till servern.",
|
||||
"use_adguard_browsing_sec_hint": "AdGuard Home kommer att kontrollera om en domän är blockerad av webbservicen surfsäkerhet. Med en integritetsvänlig metod görs en API-lookup för att kontrollera: endast ett kort prefix i domännamnet SHA256 hash skickas till servern.",
|
||||
"use_adguard_parental": "Använda AdGuards webbservice för föräldrakontroll",
|
||||
"use_adguard_parental_hint": "AdGuard Home kommer att kontrollera domäner för innehåll av vuxenmaterial . Samma integritetsvänliga metod för API-lookup som tillämpas i webbservicens surfsäkerhet används.",
|
||||
"enforce_safe_search": "Tillämpa Säker surf",
|
||||
"enforce_safe_search": "Använd säker webbsökning",
|
||||
"enforce_save_search_hint": "AdGuard Home kommer tvinga säker surf på följande sökmotorer: Google, Youtube, Bing, DuckDuckGo, Yandex, Pixabay.",
|
||||
"no_servers_specified": "Inga servrar angivna",
|
||||
"general_settings": "Allmänna inställningar",
|
||||
"dns_settings": "DNS-inställningar",
|
||||
"dns_blocklists": "DNS blockeringslistor",
|
||||
"dns_allowlists": "DNS frilistor",
|
||||
"dns_blocklists_desc": "AdGuard Home kommer att blockera domäner som matchar blockeringslistorna.",
|
||||
"dns_allowlists_desc": "Domäner från DNS frilistor kommer att tillåtas även om de finns i någon av blockeringslistorna.",
|
||||
"custom_filtering_rules": "Egna filterregler",
|
||||
"encryption_settings": "Krypteringsinställningar",
|
||||
"dhcp_settings": "DHCP-inställningar",
|
||||
"upstream_dns": "Upstream DNS-servrar",
|
||||
"upstream_dns_help": "Ange en serveradress per rad. <a>Läs mer</a> om att konfigurera uppströms DNS-servrar.",
|
||||
"upstream_dns_configured_in_file": "Konfigurerad i {{path}}",
|
||||
"test_upstream_btn": "Testa uppströmmar",
|
||||
"upstreams": "Uppströms",
|
||||
"apply_btn": "Tillämpa",
|
||||
"disabled_filtering_toast": "Filtrering bortkopplad",
|
||||
"enabled_filtering_toast": "Filtrering inkopplad",
|
||||
"disabled_safe_browsing_toast": "Säker surfning bortkopplat",
|
||||
"enabled_safe_browsing_toast": "Säker surfning inkopplat",
|
||||
"disabled_safe_browsing_toast": "Säker surfning inaktiverad",
|
||||
"enabled_safe_browsing_toast": "Säker surfning aktiverat",
|
||||
"disabled_parental_toast": "Föräldrakontroll bortkopplat",
|
||||
"enabled_parental_toast": "Föräldrakontroll inkopplat",
|
||||
"disabled_safe_search_toast": "Säker webbsökning bortkopplat",
|
||||
"enabled_save_search_toast": "Säker webbsökning inkopplat",
|
||||
"enabled_table_header": "Inkopplat",
|
||||
"name_table_header": "Namn",
|
||||
"list_url_table_header": "Lista URL",
|
||||
"rules_count_table_header": "Regelantal",
|
||||
"last_time_updated_table_header": "Uppdaterades senast",
|
||||
"actions_table_header": "Åtgärder",
|
||||
"request_table_header": "Förfrågning",
|
||||
"edit_table_action": "Redigera",
|
||||
"delete_table_action": "Radera",
|
||||
"elapsed": "Förfluten tid",
|
||||
"filters_and_hosts_hint": "AdGuard tillämpar grundläggande annonsblockeringsregler och värdfiltersyntaxer",
|
||||
"no_blocklist_added": "Inga blocklistor har lagts till",
|
||||
"no_whitelist_added": "Inga frilistor har lagts till",
|
||||
"add_blocklist": "Lägg till blockeringslista",
|
||||
"add_allowlist": "Lägg till frilista",
|
||||
"cancel_btn": "Avbryt",
|
||||
"enter_name_hint": "Skriv in namn",
|
||||
"enter_url_or_path_hint": "Ange en URL eller en absolut sökväg till listan",
|
||||
"check_updates_btn": "Sök efter uppdateringar",
|
||||
"new_blocklist": "Ny blockeringslista",
|
||||
"new_allowlist": "Ny frilista",
|
||||
"edit_blocklist": "Redigera blockeringslista",
|
||||
"edit_allowlist": "Redigera frilista",
|
||||
"choose_blocklist": "Välj blockeringslistor",
|
||||
"choose_allowlist": "Välj frilistor",
|
||||
"enter_valid_blocklist": "Ange en giltig URL till blockeringslistan.",
|
||||
"enter_valid_allowlist": "Ange en giltig URL till frilistan.",
|
||||
"form_error_url_format": "Ogiltigt URL format",
|
||||
"form_error_url_or_path_format": "Ogiltig URL eller absolut sökväg till listan",
|
||||
"custom_filter_rules": "Egna filterregler",
|
||||
"custom_filter_rules_hint": "Skriv en regel per rad. Du kan använda antingen annonsblockeringsregler eller värdfilssyntax.",
|
||||
"system_host_files": "Systemfiler",
|
||||
"examples_title": "Exempel",
|
||||
"example_meaning_filter_block": "blockera åtkomst till domän example.org domain och alla dess subdomäner",
|
||||
"example_meaning_filter_whitelist": "avblockera åtkomst till domän example.org domain och alla dess subdomäner",
|
||||
@@ -129,17 +212,26 @@
|
||||
"example_upstream_regular": "vanlig DNS (över UDP)",
|
||||
"example_upstream_dot": "krypterat <0>DNS-over-TLS</0>",
|
||||
"example_upstream_doh": "krypterat <0>DNS-over-HTTPS</0>",
|
||||
"example_upstream_doq": "krypterat <0>DNS-over-QUIC</0>",
|
||||
"example_upstream_sdns": "Du kan använda <0>DNS-stamps</0> för <1>DNSCrypt</1> eller <2>DNS-over-HTTPS</2>-resolvers",
|
||||
"example_upstream_tcp": "vanlig DNS (över UDP)",
|
||||
"all_lists_up_to_date_toast": "Alla listor är redan uppdaterade",
|
||||
"updated_upstream_dns_toast": "Sparade uppströms dns-servrar",
|
||||
"dns_test_ok_toast": "Angivna DNS servrar fungerar korrekt",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": kunde inte användas. Var snäll och kolla att du skrivit in rätt",
|
||||
"unblock": "Avblockera",
|
||||
"block": "Blockera",
|
||||
"disallow_this_client": "Tillåt inte den här klienten",
|
||||
"allow_this_client": "Tillåt den här klienten",
|
||||
"block_for_this_client_only": "Blockera endast för denna klient",
|
||||
"unblock_for_this_client_only": "Avblockera endast för denna klient",
|
||||
"time_table_header": "Tid",
|
||||
"date": "Datum",
|
||||
"domain_name_table_header": "Domännamn",
|
||||
"domain_or_client": "Domän eller klient",
|
||||
"type_table_header": "Typ",
|
||||
"response_table_header": "Svar",
|
||||
"response_code": "Svarskod",
|
||||
"client_table_header": "Klient",
|
||||
"empty_response_status": "Tomt",
|
||||
"show_all_filter_type": "Visa alla",
|
||||
@@ -151,13 +243,14 @@
|
||||
"loading_table_status": "Läser in...",
|
||||
"page_table_footer_text": "Sida",
|
||||
"rows_table_footer_text": "rader",
|
||||
"updated_custom_filtering_toast": "Uppdaterade de egna filterreglerna",
|
||||
"updated_custom_filtering_toast": "Anpassade filterregler sparade",
|
||||
"rule_removed_from_custom_filtering_toast": "Regel borttagen från de egna filterreglerna: {{rule}}",
|
||||
"rule_added_to_custom_filtering_toast": "Regel tillagd till de egna filterreglerna: {{rule}}",
|
||||
"query_log_response_status": "Status: {{value}}",
|
||||
"query_log_filtered": "Filtrerat av {{filter}}",
|
||||
"query_log_confirm_clear": "Är du säker på att du vill rensa hela förfrågningsloggen?",
|
||||
"query_log_cleared": "Förfrågningsloggen har rensats",
|
||||
"query_log_updated": "Förfrågningsloggen har uppdaterats",
|
||||
"query_log_clear": "Rensa förfrågningsloggar",
|
||||
"query_log_retention": "Förfrågningsloggars retentionstid",
|
||||
"query_log_enable": "Aktivera logg",
|
||||
@@ -165,27 +258,63 @@
|
||||
"query_log_disabled": "Förfrågningsloggen är avaktiverad och kan konfigureras i <0>inställningar</0>",
|
||||
"query_log_strict_search": "Använd dubbla citattecken för strikt sökning",
|
||||
"query_log_retention_confirm": "Är du säker på att du vill ändra förfrågningsloggars retentionstid? Om du minskar intervallet kommer viss data att gå förlorad",
|
||||
"anonymize_client_ip": "Anonymisera klientens IP",
|
||||
"anonymize_client_ip_desc": "Spara inte klientens fullständiga IP-adress i loggar och statistik",
|
||||
"dns_config": "DNS server konfiguration",
|
||||
"dns_cache_config": "DNS cache konfiguration",
|
||||
"dns_cache_config_desc": "Här kan du konfigurera DNS cache",
|
||||
"blocking_mode": "Blockeringsläge",
|
||||
"default": "Standard",
|
||||
"nxdomain": "NXDOMÄN",
|
||||
"refused": "REFUSED",
|
||||
"null_ip": "Null IP",
|
||||
"custom_ip": "Eget IP",
|
||||
"blocking_ipv4": "Blockera IPv4",
|
||||
"blocking_ipv6": "Blockera IPv6",
|
||||
"dnscrypt": "DNSCrypt",
|
||||
"dns_over_https": "DNS-over-HTTPS",
|
||||
"dns_over_tls": "DNS-over-TLS",
|
||||
"dns_over_quic": "DNS-over-QUIC",
|
||||
"client_id": "Klient ID",
|
||||
"client_id_placeholder": "Ange klient ID",
|
||||
"client_id_desc": "Olika klienter kan identifieras med ett speciellt klient ID. <a>Här</a> kan du lära dig mer om hur du identifierar klienter.",
|
||||
"download_mobileconfig_doh": "Ladda ner .mobileconfig för DNS-over-HTTPS",
|
||||
"download_mobileconfig_dot": "Ladda ner .mobileconfig för DNS-over-TLS",
|
||||
"download_mobileconfig": "Ladda ner konfigurationsfil",
|
||||
"plain_dns": "Vanlig DNS",
|
||||
"form_enter_rate_limit": "Ange förfrågnings gräns",
|
||||
"rate_limit": "Förfrågnings gräns",
|
||||
"edns_enable": "Aktivera EDNS-klient subnät",
|
||||
"edns_cs_desc": "Skicka klienternas subnät till DNS servrarna.",
|
||||
"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.",
|
||||
"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",
|
||||
"blocking_mode_default": "Standard: Svara med noll IP-adress (0.0.0.0 för A; :: för AAAA) när det blockeras av regel i Adblock-stil; svara med IP-adressen som anges i regeln när den blockeras av regel i /etc/hosts-stil",
|
||||
"blocking_mode_refused": "REFUSED: Svara med REFUSED kod",
|
||||
"blocking_mode_nxdomain": "NXDOMAIN: Svara med NXDOMAIN kod",
|
||||
"blocking_mode_null_ip": "Null IP: Svara med noll IP adress (0.0.0.0 för A; :: för AAAA)",
|
||||
"blocking_mode_custom_ip": "Anpassad IP: Svara med en manuellt inställd IP adress",
|
||||
"upstream_dns_client_desc": "Om detta fält är tomt kommer AdGuard Home att använda de servrar som konfigurerats i <0>DNS inställningarna</0>.",
|
||||
"tracker_source": "Spårningskälla",
|
||||
"source_label": "Källa",
|
||||
"found_in_known_domain_db": "Hittad i domändatabas.",
|
||||
"category_label": "Kategori",
|
||||
"rule_label": "Regel(er)",
|
||||
"list_label": "Lista",
|
||||
"unknown_filter": "Okänt filter {{filterId}}",
|
||||
"known_tracker": "Känd spårare",
|
||||
"install_welcome_title": "Välkommen till AdGuard Home!",
|
||||
"install_welcome_desc": "AdGuard Home är en DNS-server för nätverkstäckande annons- och spårningsblockering. Dess syfte är att de dig kontroll över hela nätverket och alla dina enheter, utan behov av att använda klientbaserade program.",
|
||||
"install_settings_title": "Administratörens webbgränssnitt",
|
||||
"install_settings_listen": "Övervakningsgränssnitt",
|
||||
"install_settings_port": "Port",
|
||||
"install_settings_interface_link": "Din administratörssida för AdGuard Home finns på följande adresser:",
|
||||
"form_error_port": "Skriv in ett giltigt portnummer",
|
||||
"install_settings_dns": "DNS-server",
|
||||
"install_settings_dns_desc": "Du behöver ställa in dina enheter eller din router för att använda DNS-server på följande adresser.",
|
||||
"install_settings_all_interfaces": "Alla gränssnitt",
|
||||
"install_auth_title": "Autentisering",
|
||||
"install_auth_desc": "Det rekommenderas starkt att ställa in lösenordsskydd till webbgränssnittets administrativa del i ditt AdGuard Home. Även om den endast är åtkomlig på ditt lokala nätverk rekommenderas det ändå att skydda det mot oönskad åtkomst.",
|
||||
"install_auth_desc": "Lösenordsautentisering till ditt AdGuard Home administratörsgränssnitt måste konfigureras. Även om AdGuard Home bara är tillgängligt i ditt lokala nätverk är det fortfarande viktigt att skydda det från obegränsad åtkomst.",
|
||||
"install_auth_username": "Användarnamn",
|
||||
"install_auth_password": "Lösenord",
|
||||
"install_auth_confirm": "Bekräfta lösenord",
|
||||
@@ -195,18 +324,20 @@
|
||||
"install_devices_title": "Ställ in dina enheter",
|
||||
"install_devices_desc": "För att kunna använda AdGuard Home måste du ställa in dina enheter för att utnyttja den.",
|
||||
"install_submit_title": "Grattis!",
|
||||
"install_submit_desc": "Inställningsproceduren är klar och du kan börja använda AdGuard Home.",
|
||||
"install_submit_desc": "Installationen är klar och du kan börja använda AdGuard Home.",
|
||||
"install_devices_router": "Router",
|
||||
"install_devices_router_desc": "Den här anpassningen kommer att automatiskt täcka in alla de enheter som är anslutna till din hemmarouter och du behöver därför inte konfigurera var och en individuellt.",
|
||||
"install_devices_address": "AdGuard Home DNS-server täcker följande adresser",
|
||||
"install_devices_router_list_1": "Öppna inställningarna för din router. Vanligtvis kan du komma åt den från din webbläsare via en URL, som http://192.168.0.1/ eller http://192.168.1.1/. Du kan bli ombedd att ange ett lösenord. Om du inte kommer ihåg det kan du ofta återställa lösenordet genom att trycka på en knapp på själva routern, men var medveten om att om denna procedur väljs kommer du förmodligen att förlora hela routerkonfigurationen. Om din router kräver en app för att konfigurera den, installera appen på din telefon eller dator och använd den för att komma åt routerns inställningar.",
|
||||
"install_devices_router_list_2": "Leta upp DHCP/DNS-inställningarna. Titta efter DNS-tecken intill ett fält med två eller tre uppsättningar siffror, var och en uppdelade i grupper om fyra med en eller tre siffror.",
|
||||
"install_devices_router_list_3": "Ange serveradressen till ditt AdGuard Home.",
|
||||
"install_devices_router_list_4": "På vissa routertyper kan en anpassad DNS server inte konfigureras. I så fall kan det hjälpa att konfigurera AdGuard Home som en <0>DHCP server</0>. Annars bör du kontrollera routermanualen om hur du anpassar DNS servrar på din specifika routermodell.",
|
||||
"install_devices_windows_list_1": "Öppna Kontrollpanelen via Start eller Windows Sök.",
|
||||
"install_devices_windows_list_2": "Välj Nätverks och delningscenter, Nätverk och Internet.",
|
||||
"install_devices_windows_list_3": "Leta upp Ändra nätverkskortsalternativ",
|
||||
"install_devices_windows_list_3": "På vänster sida av skärmen hittar du \"Ändra adapterinställningar\" och klicka på den.",
|
||||
"install_devices_windows_list_4": "Markera din aktiva anslutning. Högerklicka på den och välj Egenskaper.",
|
||||
"install_devices_windows_list_5": "Markera Internet Protocol Version 4 (TCP/IP) och klicka på knappen Egenskaper.",
|
||||
"install_devices_windows_list_6": "Markera Använd följande DNS-serveradresser och skriv in adresserna till ditt AdGuard Home.",
|
||||
"install_devices_windows_list_5": "Hitta \"Internet Protocol Version 4 (TCP/IPv4)\" (eller, för IPv6, \"Internet Protocol Version 6 (TCP/IPv6)\") i listan, välj den och klicka sedan på Egenskaper igen.",
|
||||
"install_devices_windows_list_6": "Välj \"Använd följande DNS-serveradresser\" och ange dina AdGuard Home-serveradresser.",
|
||||
"install_devices_macos_list_1": "Klicka på Apple-ikonen och välj Systemalternativ.",
|
||||
"install_devices_macos_list_2": "Klicka på Nätverk.",
|
||||
"install_devices_macos_list_3": "Välj den första anslutningen i listan och klicka på Avancerat.",
|
||||
@@ -215,7 +346,7 @@
|
||||
"install_devices_android_list_2": "Tryck på Nätverk och Internet, Wi-Fi. Alla tillgängliga nätverk visas i en lista (det går inte all välja egen DNS på mobilnätverk.",
|
||||
"install_devices_android_list_3": "Håll ner på nätverksnamnet som du är ansluten till och välj Ändra nätverk.",
|
||||
"install_devices_android_list_4": "På en del enheter kan du behöva välja Avancerat för att komma åt ytterligare inställningar. För att ändra på DNS-inställningar måste du byta IP-inställning från DHCP till Statisk. På Android Pie väljs Privat DNS på Nätverk och internet.",
|
||||
"install_devices_android_list_5": "Ändra DNS 1 och DNS 2 till serveradresserna för AdGuard Home.",
|
||||
"install_devices_android_list_5": "Ändra DNS 1 och DNS 2 värdena till serveradresserna för din AdGuard Home.",
|
||||
"install_devices_ios_list_1": "Tryck Inställningar från hemskärmen.",
|
||||
"install_devices_ios_list_2": "Välj Wi_Fi på den vänstra menyn (det går inte att ställa in egen DNS för mobila nätverk).",
|
||||
"install_devices_ios_list_3": "Tryck på namnet på den aktiva anslutningen.",
|
||||
@@ -226,14 +357,18 @@
|
||||
"install_saved": "Sparat utan fel",
|
||||
"encryption_title": "Kryptering",
|
||||
"encryption_desc": "Krypteringsstöd (HTTPS/TLS) för både DNS och adminwebbgränssnitt.",
|
||||
"encryption_config_saved": "Krypteringsinställningar sparade",
|
||||
"encryption_server": "Servernamn",
|
||||
"encryption_server_enter": "Skriv in ditt domännamn",
|
||||
"encryption_server_desc": "För att kunna använda HTTPS måste du ange servernamnet som matchar ditt SSL-certifikat eller jokerteckencertifikat. Om fältet inte är inställt kommer det att acceptera TLS-anslutningar för alla domäner.",
|
||||
"encryption_redirect": "Omdirigera till HTTPS automatiskt",
|
||||
"encryption_redirect_desc": "Om bockad kommer AdGuard Home automatiskt att omdirigera dig från HTTP till HTTPS-adresser.",
|
||||
"encryption_https": "HTTPS-port",
|
||||
"encryption_https_desc": "Om en HTTPS-port är inställd kommer gränssnittet till AdGuard Home administrering att kunna nås via HTTPS och kommer också att erbjuda DNS-over-HTTPS på '/dns-query' plats.",
|
||||
"encryption_dot": "DNS-över-TLS port",
|
||||
"encryption_dot_desc": "Om den här porten ställs in kommer AdGuard Home att använda DNS-over-TLS-server på porten.",
|
||||
"encryption_doq": "DNS-over-QUIC port",
|
||||
"encryption_doq_desc": "Om denna port är konfigurerad kommer AdGuard Home att köra en DNS-over-QUIC-server på denna port. Det är experimentellt och kanske inte är tillförlitligt. Dessutom finns det inte så många klienter som stödjer det för tillfället.",
|
||||
"encryption_certificates": "Certifikat",
|
||||
"encryption_certificates_desc": "För att använda kryptering måste du ange ett giltigt SSL-certifikat för din domän. Du kan skaffa ett certifikat gratis på <0>{{link}}</0> eller köpa ett från någon av de godkända certifikatutfärdare.",
|
||||
"encryption_certificates_input": "Kopiera/klistra in dina PEM-kodade certifikat här.",
|
||||
@@ -253,16 +388,22 @@
|
||||
"encryption_reset": "Är du säker på att du vill återställa krypteringsinställningarna?",
|
||||
"topline_expiring_certificate": "Ditt SSL-certifikat håller på att gå ut. <0>Krypteringsinställningar</0>.",
|
||||
"topline_expired_certificate": "Ditt SSL-certifikat har gått ut. Uppdatera <0>Krypteringsinställningar</0>-",
|
||||
"form_error_port_range": "Ange ett portnummer inom värdena 80-65535",
|
||||
"form_error_port_unsafe": "Det här är en osäker port",
|
||||
"form_error_equal": "Får inte vara samma",
|
||||
"form_error_password": "Lösenorden överensstämmer inte",
|
||||
"reset_settings": "Återställ inställningar",
|
||||
"update_announcement": "AdGuard Home {{version}} är nu tillgänglig! <0>Klicka här</0> för mer information.",
|
||||
"setup_guide": "Installationsguide",
|
||||
"dns_addresses": "DNS-adresser",
|
||||
"dns_start": "DNS servern startar",
|
||||
"dns_status_error": "Fel vid kontroll av DNS serverns status",
|
||||
"down": "Ner",
|
||||
"fix": "Fixa",
|
||||
"dns_providers": "Här är en <0>lista över kända DNS-leverantörer</0> att välja från.",
|
||||
"update_now": "Uppdatera nu",
|
||||
"update_failed": "Automatisk uppdatering misslyckad. Var god <a>följ stegen</a> för att uppdatera manuellt.",
|
||||
"manual_update": "Vänligen <a>följ dessa steg</a> för att uppdatera manuellt.",
|
||||
"processing_update": "Vänta, AdGuard Home uppdateras",
|
||||
"clients_title": "Klienter",
|
||||
"clients_desc": "Konfigurera enheter uppkopplade mot AdGuard Home",
|
||||
@@ -276,8 +417,12 @@
|
||||
"client_edit": "Redigera klient",
|
||||
"client_identifier": "Identifikator",
|
||||
"ip_address": "IP-adress",
|
||||
"client_identifier_desc": "Klienter kan identifieras med IP-adressen, CIDR, MAC-adressen eller ett speciellt klient-ID (kan användas för DoT/DoH/DoQ). <0>Här</0> kan du lära dig mer om hur du identifierar klienter.",
|
||||
"form_enter_ip": "Skriv in IP",
|
||||
"form_enter_subnet_ip": "Ange en IP adress i subnätet \"{{cidr}}\"",
|
||||
"form_enter_mac": "Skriv in MAC",
|
||||
"form_enter_id": "Ange identifierare",
|
||||
"form_add_id": "Lägg till identifierare",
|
||||
"form_client_name": "Skriv in klientnamn",
|
||||
"name": "Namn",
|
||||
"client_global_settings": "Använda globala inställningar",
|
||||
@@ -286,15 +431,17 @@
|
||||
"client_updated": "Klient \"{{key}}\" har uppdaterats",
|
||||
"clients_not_found": "Inga klienter hittade",
|
||||
"client_confirm_delete": "Är du säker på att du vill ta bort klient \"{{key}}\"?",
|
||||
"list_confirm_delete": "Är du säker på att du vill ta bort den här listan?",
|
||||
"auto_clients_title": "Klienter (körtid)",
|
||||
"auto_clients_desc": "Data från klienter som använder AdGuard Home, men inte är sparade i konfigurationen",
|
||||
"access_title": "Åtkomstinställningar",
|
||||
"access_desc": "Här kan du konfigurera åtkomstregler för AdGuard Homes DNS-server.",
|
||||
"access_allowed_title": "Tillåtna klienter",
|
||||
"access_allowed_desc": "En lista över CIDR eller IP-adresser. Om konfigurerad kommer AdGuard Home endast acceptera förfrågningar från dessa IP-adresser.",
|
||||
"access_allowed_desc": "En lista över CIDR, IP-adresser eller klient-ID. Om det är konfigurerat accepterar AdGuard Home endast förfrågningar från dessa klienter.",
|
||||
"access_disallowed_title": "Otillåtna klienter",
|
||||
"access_disallowed_desc": "En lista över CIDR eller IP-adresser. Om konfigurerad kommer AdGuard Home inte acceptera förfrågningar från dessa IP-adresser.",
|
||||
"access_disallowed_desc": "En lista över CIDR, IP-adresser eller klient-ID. Om det är konfigurerat kommer AdGuard Home att kasta förfrågningar från dessa klienter. Om tillåtna klienter är konfigurerade ignoreras detta fält.",
|
||||
"access_blocked_title": "Blockerade domäner",
|
||||
"access_blocked_desc": "Ej att förväxla med filter. AdGuard Home kastar DNS-frågor som matchar dessa domäner, och dessa frågor visas inte ens i frågeloggen. Du kan ange exakta domännamn, jokertecken eller URL-filterregler, t.ex. \"example.org\", \"*.example.org\" eller \"||example.org^\" på motsvarande sätt.",
|
||||
"access_settings_saved": "Åtkomstinställningar sparade",
|
||||
"updates_checked": "Sökning efter uppdateringar genomförd",
|
||||
"updates_version_equal": "AdGuard Home är uppdaterat",
|
||||
@@ -302,6 +449,8 @@
|
||||
"dns_privacy": "DNS-Integritet",
|
||||
"setup_dns_privacy_1": "<0>DNS-över-TLS:</0> Använd: <1>{{address}}</1>",
|
||||
"setup_dns_privacy_2": "<0>DNS-över-HTTPS:</0> Använd: <1>{{address}}</1>",
|
||||
"setup_dns_privacy_3": "<0>Här är en lista över program du kan använda.</0>",
|
||||
"setup_dns_privacy_4": "På en iOS 14 eller macOS Big Sur enhet kan du ladda ner en speciell '.mobileconfig' fil som lägger till <highlight>DNS-over-HTTPS</highlight> eller <highlight>DNS-over-TLS</highlight>-servrar till DNS inställningarna.",
|
||||
"setup_dns_privacy_android_1": "Android 9 har inbyggt stöd för DNS-över-TLS. Konfigurera och uppge domännamn under Inställningar → Nätverk & Internet → Avancerat → Privat DNS.",
|
||||
"setup_dns_privacy_android_2": "<0>AdGuard för Android</0> stödjer <1>DNS-över-HTTPS</1> samt <1>DNS-över-TLS</1>.",
|
||||
"setup_dns_privacy_android_3": "<0>Intra</0> lägger till stöd för <1>DNS-ÖVER-HTTPS</1> till Android.",
|
||||
@@ -313,15 +462,51 @@
|
||||
"setup_dns_privacy_other_3": "<0>dnscrypt-proxy</0> stödjer <1>DNS-over-HTTPS</1>.",
|
||||
"setup_dns_privacy_other_4": "<0>Mozilla Firefox</0> stödjer <1>DNS-over-HTTPS</1>.",
|
||||
"setup_dns_privacy_other_5": "Du kan hitta fler implementeringar <0>här</0> och <1>här</1>.",
|
||||
"setup_dns_privacy_ioc_mac": "iOS och macOS konfiguration",
|
||||
"setup_dns_notice": "För att kunna använda <1>DNS-över-HTTPS</1> eller <1>DNS-över-TLS</1>, behöver du <0>konfigurera Kryptering</0> i AdGuard Home-inställningar.",
|
||||
"rewrite_added": "DNS-omskrivning för \"{{key}}\" lyckad",
|
||||
"rewrite_deleted": "DNS-omskrivning för \"{{key}}\" har tagits bort",
|
||||
"rewrite_add": "Lägg till DNS omskrivning",
|
||||
"rewrite_not_found": "Inga DNS omskrivningar hittades",
|
||||
"rewrite_confirm_delete": "Är du säker på att du vill ta bort DNS-omskrivningen för \"{{key}}\"?",
|
||||
"rewrite_desc": "Gör det enkelt att konfigurera anpassat DNS svar för ett specifikt domännamn.",
|
||||
"rewrite_applied": "Omskrivningsregeln tillämpas",
|
||||
"rewrite_hosts_applied": "Omskriven av värd fil regel",
|
||||
"dns_rewrites": "DNS omskrivningar",
|
||||
"form_domain": "Ange domännamn eller jokertecken",
|
||||
"form_answer": "Ange IP adress eller domännamn",
|
||||
"form_error_domain_format": "Ogiltigt domänformat",
|
||||
"form_error_answer_format": "Ogiltigt svarsformat",
|
||||
"configure": "Konfigurera",
|
||||
"main_settings": "Huvudinställningar",
|
||||
"block_services": "Blockera specifika tjänster",
|
||||
"blocked_services": "Blockerade tjänster",
|
||||
"blocked_services_desc": "Gör det möjligt att snabbt blockera populära webbplatser och tjänster.",
|
||||
"blocked_services_saved": "Blockerade tjänster har sparats",
|
||||
"blocked_services_global": "Använd globalt blockerade tjänster",
|
||||
"blocked_service": "Blockerad tjänst",
|
||||
"block_all": "Blockera alla",
|
||||
"unblock_all": "Avblockera alla",
|
||||
"encryption_certificate_path": "Certifikatsökväg",
|
||||
"encryption_private_key_path": "Privat nyckel sökväg",
|
||||
"encryption_certificates_source_path": "Ange sökväg för certifikatfilen",
|
||||
"encryption_certificates_source_content": "Klistra in certifikatets innehåll",
|
||||
"encryption_key_source_path": "Ställ in en privat nyckelfil",
|
||||
"encryption_key_source_content": "Klistra in den privata nyckelns innehåll",
|
||||
"stats_params": "Statistikkonfiguration",
|
||||
"config_successfully_saved": "Konfigurationen har sparats",
|
||||
"interval_6_hour": "6 timmar",
|
||||
"interval_24_hour": "24 timmar",
|
||||
"interval_days": "{{count}} dag",
|
||||
"interval_days_plural": "{{count}} dagar",
|
||||
"domain": "Domän",
|
||||
"punycode": "Punycode",
|
||||
"answer": "Svar",
|
||||
"filter_added_successfully": "Listan har lagts till",
|
||||
"filter_removed_successfully": "Listan har tagits bort",
|
||||
"filter_updated": "Listan har uppdaterats",
|
||||
"statistics_configuration": "Statistikkonfiguration",
|
||||
"statistics_retention": "Bevarande av statistik",
|
||||
"statistics_retention_desc": "Om du minskar intervallet kommer viss data att gå förlorad",
|
||||
"statistics_clear": "Rensa statistik",
|
||||
"statistics_clear_confirm": "Är du säker på att du vill radera statistiken?",
|
||||
@@ -349,17 +534,99 @@
|
||||
"descr": "Beskrivning",
|
||||
"whois": "Whois",
|
||||
"filtering_rules_learn_more": "<0>Mer info</0> om att skapa dina egna blockeringslistor för värdar.",
|
||||
"blocked_by_response": "Blockerad av CNAME eller IP i svaret",
|
||||
"blocked_by_cname_or_ip": "Blockerad av CNAME eller IP",
|
||||
"try_again": "Försök igen",
|
||||
"domain_desc": "Ange domännamnet eller jokertecken som du vill ska skrivas om.",
|
||||
"example_rewrite_domain": "skriv bara om svar för detta domännamn.",
|
||||
"example_rewrite_wildcard": "skriv om svar för alla <0>example.org</0> subdomäner.",
|
||||
"rewrite_ip_address": "IP adress: använd denna IP i ett A- eller AAAA-svar",
|
||||
"rewrite_domain_name": "Domännamn: lägg till en CNAME post",
|
||||
"rewrite_A": "<0>A</0>: specialvärde, behåll <0>A</0> poster från uppströms",
|
||||
"rewrite_AAAA": "<0>AAAA</0>: specialvärde, behåll <0>AAAA</0> poster från uppströms",
|
||||
"disable_ipv6": "Inaktivera upplösning av IPv6 adresser",
|
||||
"disable_ipv6_desc": "Kasta alla DNS-frågor för IPv6-adresser (typ AAAA).",
|
||||
"fastest_addr": "Snabbaste IP adressen",
|
||||
"fastest_addr_desc": "Fråga alla DNS servrar och returnera den snabbaste IP adressen bland alla svar. Detta saktar ner DNS-frågor eftersom AdGuard Home måste vänta på svar från alla DNS servrar, men förbättrar den övergripande anslutningen.",
|
||||
"autofix_warning_text": "Om du klickar på \"Fix\" kommer AdGuard Home att konfigurera ditt system för att använda AdGuard Home DNS server.",
|
||||
"autofix_warning_list": "Den kommer att utföra följande uppgifter: <0>Avaktivera system DNSStubListener</0> <0>Sätt DNS serveradress till 127.0.0.1</0> <0>Ersätt symboliskt länkmål för /etc/resolv.conf med /run/systemd /resolve/resolv.conf</0> <0>Stoppa DNSStubListener (ladda om systemd-resolved tjänst)</0>",
|
||||
"autofix_warning_result": "Som ett resultat kommer alla DNS-förfrågningar från ditt system att behandlas av AdGuard Home som standard.",
|
||||
"tags_title": "Taggar",
|
||||
"tags_desc": "Du kan välja de taggar som motsvarar klienten. Taggar kan inkluderas i filtreringsreglerna och låter dig tillämpa dem mer exakt. <0>Läs mer</0>",
|
||||
"form_select_tags": "Välj klienttaggar",
|
||||
"check_title": "Kontrollera filtreringen",
|
||||
"check_desc": "Kontrollera om värdnamnet är filtrerat",
|
||||
"check": "Kontrollera",
|
||||
"form_enter_host": "Ange ett värdnamn",
|
||||
"filtered_custom_rules": "Filtrerat efter anpassade filtreringsregler",
|
||||
"choose_from_list": "Välj från listan",
|
||||
"add_custom_list": "Lägg till en anpassad lista",
|
||||
"host_whitelisted": "Värden är tillåten",
|
||||
"check_ip": "IP adresser: {{ip}}",
|
||||
"check_cname": "CNAME: {{cname}}",
|
||||
"check_reason": "Anledning: {{reason}}",
|
||||
"check_service": "Service namn: {{service}}",
|
||||
"service_name": "Service namn",
|
||||
"check_not_found": "Hittades inte i dina filterlistor",
|
||||
"client_confirm_block": "Är du säker på att du vill blockera klienten \"{{ip}}\"?",
|
||||
"client_confirm_unblock": "Är du säker på att du vill avblockera klienten \"{{ip}}\"?",
|
||||
"client_blocked": "Klienten \"{{ip}}\" har blockerats",
|
||||
"client_unblocked": "Klienten \"{{ip}}\" har avblockerats",
|
||||
"static_ip": "Statisk IP adress",
|
||||
"static_ip_desc": "AdGuard Home är en server så den behöver en statisk IP-adress för att fungera korrekt. Annars kan din router vid något tillfälle tilldela en annan IP-adress till den här enheten.",
|
||||
"set_static_ip": "Ställ in en statisk IP adress",
|
||||
"install_static_ok": "Goda nyheter! Den statiska IP adressen är redan konfigurerad",
|
||||
"install_static_error": "AdGuard Home kan inte konfigurera det automatiskt för detta nätverksgränssnitt. Vänligen leta efter en instruktion om hur du gör detta manuellt.",
|
||||
"install_static_configure": "AdGuard Home har upptäckt att den dynamiska IP adressen <0>{{ip}}</0> används. Vill du att den ska ställas in som din statiska adress?",
|
||||
"confirm_static_ip": "AdGuard Home kommer att konfigurera {{ip}} för att vara din statiska IP adress. Vill du fortsätta?",
|
||||
"list_updated": "{{count}} listan uppdaterad",
|
||||
"list_updated_plural": "{{count}} listor uppdaterade",
|
||||
"dnssec_enable": "Aktivera DNSSEC",
|
||||
"dnssec_enable_desc": "Ställ in DNSSEC flagga i de utgående DNS frågorna och kontrollera resultatet (DNSSEC-aktiverad upplösare krävs).",
|
||||
"validated_with_dnssec": "Validerad med DNSSEC",
|
||||
"all_queries": "Alla förfrågningar",
|
||||
"show_blocked_responses": "Blockerade",
|
||||
"show_whitelisted_responses": "Vitlistade",
|
||||
"show_processed_responses": "Utförda",
|
||||
"blocked_safebrowsing": "Blockerad av Säker webbsökning",
|
||||
"blocked_adult_websites": "Blockerad av Föräldrakontroll",
|
||||
"blocked_threats": "Blockerade hot",
|
||||
"allowed": "Vitlistade",
|
||||
"filtered": "Filtrerad",
|
||||
"rewritten": "Omskriven",
|
||||
"safe_search": "Säker surf",
|
||||
"blocklist": "Blocklista",
|
||||
"milliseconds_abbreviation": "ms",
|
||||
"cache_size": "Cachestorlek",
|
||||
"cache_size_desc": "DNS cachestorlek (i byte)",
|
||||
"cache_ttl_min_override": "Åsidosätt minsta TTL",
|
||||
"cache_ttl_max_override": "Åsidosätt maximal TTL",
|
||||
"enter_cache_size": "Ange cachestorlek (byte)",
|
||||
"enter_cache_ttl_min_override": "Ange minsta TTL (sekunder)",
|
||||
"enter_cache_ttl_max_override": "Ange maximal TTL (sekunder)",
|
||||
"cache_ttl_min_override_desc": "Förläng värden för korta time-to-live värden (sekunder) som tas emot från uppströms server när DNS svar cachelagras",
|
||||
"cache_ttl_max_override_desc": "Ställ in ett maximalt värde för time-to-live (sekunder) för poster i DNS cachen",
|
||||
"ttl_cache_validation": "Minsta cache TTL-värde måste vara mindre än eller lika med maxvärdet",
|
||||
"cache_optimistic": "Optimistisk cachning",
|
||||
"cache_optimistic_desc": "Få AdGuard Home att svara från cachen även när posterna har gått ut och försök även uppdatera dem.",
|
||||
"filter_category_general": "General",
|
||||
"filter_category_security": "säkerhet",
|
||||
"filter_category_regional": "Regional",
|
||||
"filter_category_other": "Övrigt",
|
||||
"filter_category_general_desc": "Listor som blockerar spårning och reklam på de flesta enheterna",
|
||||
"filter_category_security_desc": "Listor utformade specifikt för att blockera skadliga domäner, nätfiske och bluffdomäner",
|
||||
"filter_category_regional_desc": "Listor som fokuserar på regionala annonser och spårningsservrar",
|
||||
"filter_category_other_desc": "Andra blockeringslistor",
|
||||
"setup_config_to_enable_dhcp_server": "Ställ in konfiguration för att aktivera DHCP-server",
|
||||
"original_response": "Ursprungligt svar",
|
||||
"click_to_view_queries": "Klicka för att se förfrågningar",
|
||||
"port_53_faq_link": "Port 53 är ofta upptagen av \"DNSStubListener\" eller \"systemd-resolved\" tjänster. Läs <0>denna instruktion</0> om hur du löser detta.",
|
||||
"adg_will_drop_dns_queries": "AdGuard Home kommer att kasta alla DNS-frågor från den här klienten.",
|
||||
"filter_allowlist": "VARNING: Denna åtgärd kommer också att utesluta regeln \"{{disallowed_rule}}\" från listan över tillåtna klienter.",
|
||||
"last_rule_in_allowlist": "Det går inte att avvisa den här klienten eftersom att utesluta regeln \"{{disallowed_rule}}\" kommer att INAKTIVERA listan \"Tillåtna klienter\".",
|
||||
"experimental": "Experimentell",
|
||||
"use_saved_key": "Använd den tidigare sparade nyckeln",
|
||||
"parental_control": "Föräldrakontroll"
|
||||
"parental_control": "Föräldrakontroll",
|
||||
"safe_browsing": "Säker surfning",
|
||||
"served_from_cache": "{{value}} <i>(levereras från cache)</i>"
|
||||
}
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "Aralarından seçim yapabileceğiniz, bilinen <0>DNS sağlayıcıların listesi</0>.",
|
||||
"update_now": "Şimdi güncelle",
|
||||
"update_failed": "Otomatik güncelleme başarısız oldu. Elle güncellemek için lütfen <a>bu adımları uygulayın</a>.",
|
||||
"manual_update": "Elle güncellemek için lütfen <a>bu adımları uygulayın</a>.",
|
||||
"processing_update": "Lütfen bekleyin, AdGuard Home güncelleniyor",
|
||||
"clients_title": "İstemciler",
|
||||
"clients_desc": "AdGuard Home'a bağlı cihazları yapılandırın",
|
||||
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "此为可从中选择的<0>已知 DNS 提供商列表</0>。",
|
||||
"update_now": "立即更新",
|
||||
"update_failed": "自动更新失败。请<a>跟随这些步骤</a>以手动更新。",
|
||||
"manual_update": "请跟随<a>此步骤</a>以进行手动更新。",
|
||||
"processing_update": "正在更新 AdGuard Home,请稍侯",
|
||||
"clients_title": "客户端",
|
||||
"clients_desc": "配置已连接到 AdGuard Home 的设备",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "無效的 IPv6 位址",
|
||||
"form_error_ip_format": "無效的 IP 位址",
|
||||
"form_error_mac_format": "無效的媒體存取控制(MAC)位址",
|
||||
"form_error_client_id_format": "用戶端 ID 必須只包含數值、小寫字母和連字號",
|
||||
"form_error_client_id_format": "用戶端 ID 必須只包含數字、小寫字母和連字號",
|
||||
"form_error_server_name": "無效的伺服器名稱",
|
||||
"form_error_subnet": "子網路 \"{{cidr}}\" 不包含該 IP 位址 \"{{ip}}\"",
|
||||
"form_error_positive": "必須大於 0",
|
||||
@@ -403,6 +403,7 @@
|
||||
"dns_providers": "這裡是一個從中選擇之<0>已知的 DNS 供應商之清單</0>。",
|
||||
"update_now": "立即更新",
|
||||
"update_failed": "自動更新已失敗。請<a>遵循這些步驟</a>以手動地更新。",
|
||||
"manual_update": "請<a>遵循這些步驟</a>以手動地更新。",
|
||||
"processing_update": "請稍候,AdGuard Home 正被更新",
|
||||
"clients_title": "用戶端",
|
||||
"clients_desc": "配置被連線到 AdGuard Home 的裝置",
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
STATUS_RESPONSE,
|
||||
SETTINGS_NAMES,
|
||||
FORM_NAME,
|
||||
GETTING_STARTED_LINK,
|
||||
MANUAL_UPDATE_LINK,
|
||||
} from '../helpers/constants';
|
||||
import { areEqualVersions } from '../helpers/version';
|
||||
import { getTlsStatus } from './encryption';
|
||||
@@ -193,7 +193,7 @@ export const getUpdate = () => async (dispatch, getState) => {
|
||||
const handleRequestError = () => {
|
||||
const options = {
|
||||
components: {
|
||||
a: <a href={GETTING_STARTED_LINK} target="_blank"
|
||||
a: <a href={MANUAL_UPDATE_LINK} target="_blank"
|
||||
rel="noopener noreferrer" />,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import Topline from './Topline';
|
||||
import { getUpdate } from '../../actions';
|
||||
import { MANUAL_UPDATE_LINK } from '../../helpers/constants';
|
||||
|
||||
const UpdateTopline = () => {
|
||||
const {
|
||||
@@ -29,16 +31,27 @@ const UpdateTopline = () => {
|
||||
>
|
||||
update_announcement
|
||||
</Trans>
|
||||
{canAutoUpdate
|
||||
&& <button
|
||||
type="button"
|
||||
className="btn btn-sm btn-primary ml-3"
|
||||
onClick={handleUpdate}
|
||||
disabled={processingUpdate}
|
||||
>
|
||||
<Trans>update_now</Trans>
|
||||
</button>
|
||||
}
|
||||
|
||||
{canAutoUpdate ? (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-primary ml-3"
|
||||
onClick={handleUpdate}
|
||||
disabled={processingUpdate}
|
||||
>
|
||||
<Trans>update_now</Trans>
|
||||
</button>
|
||||
) : (
|
||||
<Trans components={{
|
||||
a: (
|
||||
<a href={MANUAL_UPDATE_LINK} target="_blank" rel="noopener noreferrer" key="0">
|
||||
Link
|
||||
</a>
|
||||
),
|
||||
}}>
|
||||
manual_update
|
||||
</Trans>
|
||||
)}
|
||||
</>
|
||||
</Topline>;
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ export const REPOSITORY = {
|
||||
export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html';
|
||||
export const PORT_53_FAQ_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#bindinuse';
|
||||
export const UPSTREAM_CONFIGURATION_WIKI_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#upstreams';
|
||||
export const GETTING_STARTED_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update';
|
||||
export const MANUAL_UPDATE_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#manual-update';
|
||||
|
||||
export const FILTERS_RELATIVE_LINK = '#filters';
|
||||
|
||||
|
||||
@@ -28,11 +28,7 @@ const queryLogs = handleActions(
|
||||
};
|
||||
},
|
||||
|
||||
[actions.setLogsFilterRequest]: (state, { payload }) => {
|
||||
const { filter } = payload;
|
||||
|
||||
return { ...state, filter };
|
||||
},
|
||||
[actions.setLogsFilterRequest]: (state, { payload }) => ({ ...state, filter: payload }),
|
||||
|
||||
[actions.getLogsRequest]: (state) => ({ ...state, processingGetLogs: true }),
|
||||
[actions.getLogsFailure]: (state) => ({ ...state, processingGetLogs: false }),
|
||||
|
||||
5
go.mod
5
go.mod
@@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.40.5
|
||||
github.com/AdguardTeam/dnsproxy v0.41.1
|
||||
github.com/AdguardTeam/golibs v0.10.4
|
||||
github.com/AdguardTeam/urlfilter v0.15.2
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
@@ -16,7 +16,7 @@ require (
|
||||
github.com/google/renameio v1.0.1
|
||||
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489
|
||||
github.com/kardianos/service v1.2.0
|
||||
github.com/lucas-clemente/quic-go v0.24.0
|
||||
github.com/lucas-clemente/quic-go v0.25.0
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7
|
||||
github.com/mdlayher/netlink v1.5.0
|
||||
github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b
|
||||
@@ -46,6 +46,7 @@ require (
|
||||
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect
|
||||
github.com/mdlayher/socket v0.1.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
|
||||
9
go.sum
9
go.sum
@@ -7,8 +7,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AdguardTeam/dnsproxy v0.40.5 h1:727KSGRmzq2DB5dMm093g0Guhc3dzzzMbfB0C9hK0s8=
|
||||
github.com/AdguardTeam/dnsproxy v0.40.5/go.mod h1:PZ9l22h3Er+5mxFQB7oHZMTvx+aa9R6LbzA/ikXQlS0=
|
||||
github.com/AdguardTeam/dnsproxy v0.41.1 h1:sDWami83ZNp0XNdWsLECwIX/hPI5UnVrotRtPnrgDuo=
|
||||
github.com/AdguardTeam/dnsproxy v0.41.1/go.mod h1:PZ9l22h3Er+5mxFQB7oHZMTvx+aa9R6LbzA/ikXQlS0=
|
||||
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||
github.com/AdguardTeam/golibs v0.10.3/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
||||
@@ -148,8 +148,9 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucas-clemente/quic-go v0.24.0 h1:ToR7SIIEdrgOhgVTHvPgdVRJfgVy+N0wQAagH7L4d5g=
|
||||
github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0=
|
||||
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
|
||||
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
@@ -158,6 +159,8 @@ github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2i
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
|
||||
@@ -111,7 +111,7 @@ func discover4(iface *net.Interface, dstAddr *net.UDPAddr, hostname string) (ok
|
||||
// is spoiled.
|
||||
//
|
||||
// It's also known that listening on the specified interface's address
|
||||
// ignores broadcasted packets when reading.
|
||||
// ignores broadcast packets when reading.
|
||||
var c net.PacketConn
|
||||
if c, err = listenPacketReusable(iface.Name, "udp4", ":68"); err != nil {
|
||||
return false, fmt.Errorf("couldn't listen on :68: %w", err)
|
||||
|
||||
@@ -46,13 +46,8 @@ type requestMatcher struct {
|
||||
}
|
||||
|
||||
// MatchRequest processes the request rewriting hostnames and addresses read
|
||||
// from the operating system's hosts files.
|
||||
//
|
||||
// res is nil for any request having not an A/AAAA or PTR type. Results
|
||||
// containing CNAME information may be queried again with the same question type
|
||||
// and the returned CNAME for Host field of request. Results are guaranteed to
|
||||
// be direct, i.e. any returned CNAME resolves into actual address like an alias
|
||||
// in hosts does, see man hosts (5).
|
||||
// from the operating system's hosts files. res is nil for any request having
|
||||
// not an A/AAAA or PTR type, see man 5 hosts.
|
||||
//
|
||||
// It's safe for concurrent use.
|
||||
func (rm *requestMatcher) MatchRequest(
|
||||
@@ -203,7 +198,7 @@ func (hc *HostsContainer) Close() (err error) {
|
||||
}
|
||||
|
||||
// Upd returns the channel into which the updates are sent. The receivable
|
||||
// map's values are guaranteed to be of type of *aghnet.Hosts.
|
||||
// map's values are guaranteed to be of type of *stringutil.Set.
|
||||
func (hc *HostsContainer) Upd() (updates <-chan *netutil.IPMap) {
|
||||
return hc.updates
|
||||
}
|
||||
@@ -259,28 +254,14 @@ func (hc *HostsContainer) handleEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
// ipRules is the pair of generated A/AAAA and PTR rules with related IP.
|
||||
type ipRules struct {
|
||||
// rule is the A/AAAA $dnsrewrite rule.
|
||||
rule string
|
||||
// rulePtr is the PTR $dnsrewrite rule.
|
||||
rulePtr string
|
||||
// ip is the IP address related to the rules.
|
||||
ip net.IP
|
||||
}
|
||||
|
||||
// hostsParser is a helper type to parse rules from the operating system's hosts
|
||||
// file. It exists for only a single refreshing session.
|
||||
type hostsParser struct {
|
||||
// rulesBuilder builds the resulting rules list content.
|
||||
rulesBuilder *strings.Builder
|
||||
|
||||
// rules stores the rules for main hosts to generate translations.
|
||||
rules []ipRules
|
||||
|
||||
// cnameSet prevents duplicating cname rules, e.g. same hostname for
|
||||
// different IP versions.
|
||||
cnameSet *stringutil.Set
|
||||
// translations maps generated rules into actual hosts file lines.
|
||||
translations map[string]string
|
||||
|
||||
// table stores only the unique IP-hostname pairs. It's also sent to the
|
||||
// updates channel afterwards.
|
||||
@@ -290,13 +271,10 @@ type hostsParser struct {
|
||||
// newHostsParser creates a new *hostsParser with buffers of size taken from the
|
||||
// previous parse.
|
||||
func (hc *HostsContainer) newHostsParser() (hp *hostsParser) {
|
||||
lastLen := hc.last.Len()
|
||||
|
||||
return &hostsParser{
|
||||
rulesBuilder: &strings.Builder{},
|
||||
rules: make([]ipRules, 0, lastLen),
|
||||
cnameSet: stringutil.NewSet(),
|
||||
table: netutil.NewIPMap(lastLen),
|
||||
translations: map[string]string{},
|
||||
table: netutil.NewIPMap(hc.last.Len()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +320,8 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
|
||||
// Make sure that invalid hosts aren't turned into rules.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
|
||||
//
|
||||
// TODO(e.burkov): Investigate if hosts may contain DNS-SD domains.
|
||||
err := netutil.ValidateDomainName(f)
|
||||
if err != nil {
|
||||
log.Error("%s: host %q is invalid, ignoring", hostsContainerPref, f)
|
||||
@@ -355,107 +335,45 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
|
||||
return ip, hosts
|
||||
}
|
||||
|
||||
// Hosts is used to contain the main host and all it's aliases.
|
||||
type Hosts struct {
|
||||
// Aliases contains all the aliases for Main.
|
||||
Aliases *stringutil.Set
|
||||
// Main is the host itself.
|
||||
Main string
|
||||
}
|
||||
|
||||
// Equal returns true if h equals hh.
|
||||
func (h *Hosts) Equal(hh *Hosts) (ok bool) {
|
||||
if h == nil || hh == nil {
|
||||
return h == hh
|
||||
}
|
||||
|
||||
return h.Main == hh.Main && h.Aliases.Equal(hh.Aliases)
|
||||
}
|
||||
|
||||
// add tries to add the ip-host pair. It returns:
|
||||
//
|
||||
// main host if the host is not the first one added for the ip.
|
||||
// host itself if the host is the first one added for the ip.
|
||||
// "" if the ip-host pair has already been added.
|
||||
//
|
||||
func (hp *hostsParser) add(ip net.IP, host string) (mainHost string) {
|
||||
v, ok := hp.table.Get(ip)
|
||||
switch h, _ := v.(*Hosts); {
|
||||
case !ok:
|
||||
// This is the first host for the ip.
|
||||
hp.table.Set(ip, &Hosts{Main: host})
|
||||
|
||||
return host
|
||||
case h.Main == host:
|
||||
// This is a duplicate. Go on.
|
||||
case h.Aliases == nil:
|
||||
// This is the first alias.
|
||||
h.Aliases = stringutil.NewSet(host)
|
||||
|
||||
return h.Main
|
||||
case !h.Aliases.Has(host):
|
||||
// This is a new alias.
|
||||
h.Aliases.Add(host)
|
||||
|
||||
return h.Main
|
||||
default:
|
||||
// This is a duplicate. Go on.
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// addPair puts the pair of ip and host to the rules builder if needed. For
|
||||
// each ip the first member of hosts will become the main one.
|
||||
func (hp *hostsParser) addPairs(ip net.IP, hosts []string) {
|
||||
for _, host := range hosts {
|
||||
switch mainHost := hp.add(ip, host); mainHost {
|
||||
case "":
|
||||
// This host is a duplicate.
|
||||
v, ok := hp.table.Get(ip)
|
||||
if !ok {
|
||||
// This ip is added at the first time.
|
||||
v = stringutil.NewSet()
|
||||
hp.table.Set(ip, v)
|
||||
}
|
||||
|
||||
var set *stringutil.Set
|
||||
set, ok = v.(*stringutil.Set)
|
||||
if !ok {
|
||||
log.Debug("%s: adding pairs: unexpected value type %T", hostsContainerPref, v)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
processed := strings.Join(append([]string{ip.String()}, hosts...), " ")
|
||||
for _, h := range hosts {
|
||||
if set.Has(h) {
|
||||
continue
|
||||
case host:
|
||||
// This host is main.
|
||||
added, addedPtr := hp.writeMainRule(host, ip)
|
||||
hp.rules = append(hp.rules, ipRules{
|
||||
rule: added,
|
||||
rulePtr: addedPtr,
|
||||
ip: ip,
|
||||
})
|
||||
default:
|
||||
// This host is an alias.
|
||||
pair := fmt.Sprint(host, " ", mainHost)
|
||||
if hp.cnameSet.Has(pair) {
|
||||
continue
|
||||
}
|
||||
hp.writeAliasRule(host, mainHost)
|
||||
hp.cnameSet.Add(pair)
|
||||
}
|
||||
|
||||
log.Debug("%s: added ip-host pair %q-%q", hostsContainerPref, ip, host)
|
||||
set.Add(h)
|
||||
|
||||
rule, rulePtr := hp.writeRules(h, ip)
|
||||
hp.translations[rule], hp.translations[rulePtr] = processed, processed
|
||||
|
||||
log.Debug("%s: added ip-host pair %q-%q", hostsContainerPref, ip, h)
|
||||
}
|
||||
}
|
||||
|
||||
// writeAliasRule writes the CNAME rule for the alias-host pair into internal
|
||||
// builders.
|
||||
func (hp *hostsParser) writeAliasRule(alias, host string) {
|
||||
const (
|
||||
nl = "\n"
|
||||
sc = ";"
|
||||
|
||||
rwSuccess = rules.MaskSeparator + "$dnsrewrite=NOERROR" + sc + "CNAME" + sc
|
||||
constLen = len(rules.MaskPipe) + len(rwSuccess) + len(nl)
|
||||
)
|
||||
|
||||
hp.rulesBuilder.Grow(constLen + len(host) + len(alias))
|
||||
stringutil.WriteToBuilder(hp.rulesBuilder, rules.MaskPipe, alias, rwSuccess, host, nl)
|
||||
}
|
||||
|
||||
// writeMainRule writes the actual rule for the qtype and the PTR for the
|
||||
// writeRules writes the actual rule for the qtype and the PTR for the
|
||||
// host-ip pair into internal builders.
|
||||
func (hp *hostsParser) writeMainRule(host string, ip net.IP) (added, addedPtr string) {
|
||||
func (hp *hostsParser) writeRules(host string, ip net.IP) (rule, rulePtr string) {
|
||||
arpa, err := netutil.IPToReversedAddr(ip)
|
||||
if err != nil {
|
||||
return
|
||||
return "", ""
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -482,28 +400,20 @@ func (hp *hostsParser) writeMainRule(host string, ip net.IP) (added, addedPtr st
|
||||
|
||||
ruleBuilder := &strings.Builder{}
|
||||
ruleBuilder.Grow(modLen + len(host) + len(qtype) + len(ipStr))
|
||||
stringutil.WriteToBuilder(
|
||||
ruleBuilder,
|
||||
rules.MaskPipe,
|
||||
host,
|
||||
rwSuccess,
|
||||
qtype,
|
||||
";",
|
||||
ipStr,
|
||||
)
|
||||
added = ruleBuilder.String()
|
||||
stringutil.WriteToBuilder(ruleBuilder, rules.MaskPipe, host, rwSuccess, qtype, ";", ipStr)
|
||||
rule = ruleBuilder.String()
|
||||
|
||||
ruleBuilder.Reset()
|
||||
|
||||
ruleBuilder.Grow(modLenPTR + len(arpa) + len(fqdn))
|
||||
stringutil.WriteToBuilder(ruleBuilder, rules.MaskPipe, arpa, rwSuccessPTR, fqdn)
|
||||
|
||||
addedPtr = ruleBuilder.String()
|
||||
rulePtr = ruleBuilder.String()
|
||||
|
||||
hp.rulesBuilder.Grow(len(added) + len(addedPtr) + 2*len(nl))
|
||||
stringutil.WriteToBuilder(hp.rulesBuilder, added, nl, addedPtr, nl)
|
||||
hp.rulesBuilder.Grow(len(rule) + len(rulePtr) + 2*len(nl))
|
||||
stringutil.WriteToBuilder(hp.rulesBuilder, rule, nl, rulePtr, nl)
|
||||
|
||||
return added, addedPtr
|
||||
return rule, rulePtr
|
||||
}
|
||||
|
||||
// equalSet returns true if the internal hosts table just parsed equals target.
|
||||
@@ -519,12 +429,11 @@ func (hp *hostsParser) equalSet(target *netutil.IPMap) (ok bool) {
|
||||
|
||||
hp.table.Range(func(ip net.IP, b interface{}) (cont bool) {
|
||||
// ok is set to true if the target doesn't contain ip or if the
|
||||
// appropriate hosts set isn't equal to the checked one, i.e. the main
|
||||
// hosts differ or the maps have at least one discrepancy.
|
||||
// appropriate hosts set isn't equal to the checked one.
|
||||
if a, hasIP := target.Get(ip); !hasIP {
|
||||
ok = true
|
||||
} else if hosts, aok := a.(*Hosts); aok {
|
||||
ok = !hosts.Equal(b.(*Hosts))
|
||||
} else if hosts, aok := a.(*stringutil.Set); aok {
|
||||
ok = !hosts.Equal(b.(*stringutil.Set))
|
||||
}
|
||||
|
||||
// Continue only if maps has no discrepancies.
|
||||
@@ -563,35 +472,6 @@ func (hp *hostsParser) newStrg(id int) (s *filterlist.RuleStorage, err error) {
|
||||
}})
|
||||
}
|
||||
|
||||
// translations generates the map to translate $dnsrewrite rules to
|
||||
// hosts-syntax ones.
|
||||
func (hp *hostsParser) translations() (trans map[string]string) {
|
||||
l := len(hp.rules)
|
||||
if l == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
trans = make(map[string]string, l*2)
|
||||
for _, r := range hp.rules {
|
||||
v, ok := hp.table.Get(r.ip)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var hosts *Hosts
|
||||
hosts, ok = v.(*Hosts)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
strs := append([]string{r.ip.String(), hosts.Main}, hosts.Aliases.Values()...)
|
||||
hostsLine := strings.Join(strs, " ")
|
||||
trans[r.rule], trans[r.rulePtr] = hostsLine, hostsLine
|
||||
}
|
||||
|
||||
return trans
|
||||
}
|
||||
|
||||
// refresh gets the data from specified files and propagates the updates if
|
||||
// needed.
|
||||
//
|
||||
@@ -618,7 +498,7 @@ func (hc *HostsContainer) refresh() (err error) {
|
||||
return fmt.Errorf("initializing rules storage: %w", err)
|
||||
}
|
||||
|
||||
hc.resetEng(rulesStrg, hp.translations())
|
||||
hc.resetEng(rulesStrg, hp.translations)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/urlfilter"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
"github.com/miekg/dns"
|
||||
@@ -86,6 +87,7 @@ func TestNewHostsContainer(t *testing.T) {
|
||||
|
||||
return
|
||||
}
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hc)
|
||||
@@ -156,8 +158,9 @@ func TestHostsContainer_refresh(t *testing.T) {
|
||||
|
||||
hc, err := NewHostsContainer(0, testFS, w, "dir")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
checkRefresh := func(t *testing.T, wantHosts Hosts) {
|
||||
checkRefresh := func(t *testing.T, wantHosts *stringutil.Set) {
|
||||
upd, ok := <-hc.Upd()
|
||||
require.True(t, ok)
|
||||
require.NotNil(t, upd)
|
||||
@@ -167,22 +170,21 @@ func TestHostsContainer_refresh(t *testing.T) {
|
||||
v, ok := upd.Get(ip)
|
||||
require.True(t, ok)
|
||||
|
||||
var hosts *Hosts
|
||||
hosts, ok = v.(*Hosts)
|
||||
var set *stringutil.Set
|
||||
set, ok = v.(*stringutil.Set)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, wantHosts.Main, hosts.Main)
|
||||
assert.True(t, hosts.Aliases.Equal(wantHosts.Aliases))
|
||||
assert.True(t, set.Equal(wantHosts))
|
||||
}
|
||||
|
||||
t.Run("initial_refresh", func(t *testing.T) {
|
||||
checkRefresh(t, Hosts{Main: "hostname"})
|
||||
checkRefresh(t, stringutil.NewSet("hostname"))
|
||||
})
|
||||
|
||||
t.Run("second_refresh", func(t *testing.T) {
|
||||
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + ` alias` + nl)}
|
||||
eventsCh <- event{}
|
||||
checkRefresh(t, Hosts{Main: "hostname", Aliases: stringutil.NewSet("alias")})
|
||||
checkRefresh(t, stringutil.NewSet("hostname", "alias"))
|
||||
})
|
||||
|
||||
t.Run("double_refresh", func(t *testing.T) {
|
||||
@@ -288,6 +290,7 @@ func TestHostsContainer_Translate(t *testing.T) {
|
||||
|
||||
hc, err := NewHostsContainer(0, testdata, &stubWatcher, "etc_hosts")
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, hc.Close)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -300,7 +303,11 @@ func TestHostsContainer_Translate(t *testing.T) {
|
||||
}, {
|
||||
name: "hello",
|
||||
rule: "|hello^$dnsrewrite=NOERROR;A;1.0.0.0",
|
||||
wantTrans: []string{"1.0.0.0", "hello", "hello.world", "hello.world.again"},
|
||||
wantTrans: []string{"1.0.0.0", "hello", "hello.world"},
|
||||
}, {
|
||||
name: "hello-alias",
|
||||
rule: "|hello.world.again^$dnsrewrite=NOERROR;A;1.0.0.0",
|
||||
wantTrans: []string{"1.0.0.0", "hello.world.again"},
|
||||
}, {
|
||||
name: "simplehost_v6",
|
||||
rule: "|simplehost^$dnsrewrite=NOERROR;AAAA;::1",
|
||||
@@ -308,7 +315,11 @@ func TestHostsContainer_Translate(t *testing.T) {
|
||||
}, {
|
||||
name: "hello_v6",
|
||||
rule: "|hello^$dnsrewrite=NOERROR;AAAA;::",
|
||||
wantTrans: []string{"::", "hello", "hello.world", "hello.world.again"},
|
||||
wantTrans: []string{"::", "hello", "hello.world"},
|
||||
}, {
|
||||
name: "hello_v6-alias",
|
||||
rule: "|hello.world.again^$dnsrewrite=NOERROR;AAAA;::",
|
||||
wantTrans: []string{"::", "hello.world.again"},
|
||||
}, {
|
||||
name: "simplehost_ptr",
|
||||
rule: "|1.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;simplehost.",
|
||||
@@ -316,7 +327,11 @@ func TestHostsContainer_Translate(t *testing.T) {
|
||||
}, {
|
||||
name: "hello_ptr",
|
||||
rule: "|0.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;hello.",
|
||||
wantTrans: []string{"1.0.0.0", "hello", "hello.world", "hello.world.again"},
|
||||
wantTrans: []string{"1.0.0.0", "hello", "hello.world"},
|
||||
}, {
|
||||
name: "hello_ptr-alias",
|
||||
rule: "|0.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;hello.world.again.",
|
||||
wantTrans: []string{"1.0.0.0", "hello.world.again"},
|
||||
}, {
|
||||
name: "simplehost_ptr_v6",
|
||||
rule: "|1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
|
||||
@@ -326,14 +341,18 @@ func TestHostsContainer_Translate(t *testing.T) {
|
||||
name: "hello_ptr_v6",
|
||||
rule: "|0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
|
||||
"^$dnsrewrite=NOERROR;PTR;hello.",
|
||||
wantTrans: []string{"::", "hello", "hello.world", "hello.world.again"},
|
||||
wantTrans: []string{"::", "hello", "hello.world"},
|
||||
}, {
|
||||
name: "hello_ptr_v6-alias",
|
||||
rule: "|0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
|
||||
"^$dnsrewrite=NOERROR;PTR;hello.world.again.",
|
||||
wantTrans: []string{"::", "hello.world.again"},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
want := stringutil.NewSet(tc.wantTrans...)
|
||||
got := stringutil.NewSet(strings.Fields(hc.Translate(tc.rule))...)
|
||||
assert.True(t, want.Equal(got))
|
||||
assert.True(t, stringutil.NewSet(tc.wantTrans...).Equal(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -354,7 +373,7 @@ func TestHostsContainer(t *testing.T) {
|
||||
RRType: dns.TypeA,
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
Value: net.IP(append((&[15]byte{})[:], byte(1))),
|
||||
Value: net.ParseIP("::1"),
|
||||
RRType: dns.TypeAAAA,
|
||||
}},
|
||||
name: "simple",
|
||||
@@ -364,8 +383,13 @@ func TestHostsContainer(t *testing.T) {
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
NewCNAME: "hello",
|
||||
RCode: dns.RcodeSuccess,
|
||||
Value: net.IPv4(1, 0, 0, 0),
|
||||
RRType: dns.TypeA,
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
Value: net.ParseIP("::"),
|
||||
RRType: dns.TypeAAAA,
|
||||
}},
|
||||
name: "hello_alias",
|
||||
req: urlfilter.DNSRequest{
|
||||
@@ -374,8 +398,13 @@ func TestHostsContainer(t *testing.T) {
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
NewCNAME: "hello",
|
||||
RCode: dns.RcodeSuccess,
|
||||
Value: net.IPv4(1, 0, 0, 0),
|
||||
RRType: dns.TypeA,
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
Value: net.ParseIP("::"),
|
||||
RRType: dns.TypeAAAA,
|
||||
}},
|
||||
name: "other_line_alias",
|
||||
req: urlfilter.DNSRequest{
|
||||
@@ -398,8 +427,13 @@ func TestHostsContainer(t *testing.T) {
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
NewCNAME: "a.whole",
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeA,
|
||||
Value: net.IPv4(1, 0, 0, 2),
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeAAAA,
|
||||
Value: net.ParseIP("::2"),
|
||||
}},
|
||||
name: "lots_of_aliases",
|
||||
req: urlfilter.DNSRequest{
|
||||
@@ -431,6 +465,51 @@ func TestHostsContainer(t *testing.T) {
|
||||
Hostname: "1.0.0.1.in-addr.arpa",
|
||||
DNSType: dns.TypeSRV,
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeA,
|
||||
Value: net.IPv4(4, 2, 1, 6),
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeAAAA,
|
||||
Value: net.ParseIP("::42"),
|
||||
}},
|
||||
name: "issue_4216_4_6",
|
||||
req: urlfilter.DNSRequest{
|
||||
Hostname: "domain",
|
||||
DNSType: dns.TypeA,
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeA,
|
||||
Value: net.IPv4(7, 5, 3, 1),
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeA,
|
||||
Value: net.IPv4(1, 3, 5, 7),
|
||||
}},
|
||||
name: "issue_4216_4",
|
||||
req: urlfilter.DNSRequest{
|
||||
Hostname: "domain4",
|
||||
DNSType: dns.TypeA,
|
||||
},
|
||||
}, {
|
||||
want: []*rules.DNSRewrite{{
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeAAAA,
|
||||
Value: net.ParseIP("::13"),
|
||||
}, {
|
||||
RCode: dns.RcodeSuccess,
|
||||
RRType: dns.TypeAAAA,
|
||||
Value: net.ParseIP("::31"),
|
||||
}},
|
||||
name: "issue_4216_6",
|
||||
req: urlfilter.DNSRequest{
|
||||
Hostname: "domain6",
|
||||
DNSType: dns.TypeAAAA,
|
||||
},
|
||||
}}
|
||||
|
||||
stubWatcher := aghtest.FSWatcher{
|
||||
@@ -441,6 +520,7 @@ func TestHostsContainer(t *testing.T) {
|
||||
|
||||
hc, err := NewHostsContainer(listID, 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) {
|
||||
|
||||
10
internal/aghnet/testdata/etc_hosts
vendored
10
internal/aghnet/testdata/etc_hosts
vendored
@@ -27,4 +27,12 @@
|
||||
::4 *.com
|
||||
:: hello.world.again
|
||||
::1 simplehost
|
||||
:: hello.world
|
||||
:: 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
|
||||
@@ -20,17 +20,19 @@ func DiscardLogOutput(m *testing.M) {
|
||||
|
||||
// ReplaceLogWriter moves logger output to w and uses Cleanup method of t to
|
||||
// revert changes.
|
||||
func ReplaceLogWriter(t *testing.T, w io.Writer) {
|
||||
stdWriter := log.Writer()
|
||||
t.Cleanup(func() {
|
||||
log.SetOutput(stdWriter)
|
||||
})
|
||||
func ReplaceLogWriter(t testing.TB, w io.Writer) {
|
||||
t.Helper()
|
||||
|
||||
prev := log.Writer()
|
||||
t.Cleanup(func() { log.SetOutput(prev) })
|
||||
log.SetOutput(w)
|
||||
}
|
||||
|
||||
// ReplaceLogLevel sets logging level to l and uses Cleanup method of t to
|
||||
// revert changes.
|
||||
func ReplaceLogLevel(t *testing.T, l log.Level) {
|
||||
func ReplaceLogLevel(t testing.TB, l log.Level) {
|
||||
t.Helper()
|
||||
|
||||
switch l {
|
||||
case log.INFO, log.DEBUG, log.ERROR:
|
||||
// Go on.
|
||||
@@ -38,9 +40,7 @@ func ReplaceLogLevel(t *testing.T, l log.Level) {
|
||||
t.Fatalf("wrong l value (must be one of %v, %v, %v)", log.INFO, log.DEBUG, log.ERROR)
|
||||
}
|
||||
|
||||
stdLevel := log.GetLevel()
|
||||
t.Cleanup(func() {
|
||||
log.SetLevel(stdLevel)
|
||||
})
|
||||
prev := log.GetLevel()
|
||||
t.Cleanup(func() { log.SetLevel(prev) })
|
||||
log.SetLevel(l)
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// TestUpstream is a mock of real upstream.
|
||||
type TestUpstream struct {
|
||||
// Upstream is a mock implementation of upstream.Upstream.
|
||||
type Upstream struct {
|
||||
// CName is a map of hostname to canonical name.
|
||||
CName map[string]string
|
||||
CName map[string][]string
|
||||
// IPv4 is a map of hostname to IPv4.
|
||||
IPv4 map[string][]net.IP
|
||||
// IPv6 is a map of hostname to IPv6.
|
||||
@@ -25,78 +25,45 @@ type TestUpstream struct {
|
||||
Addr string
|
||||
}
|
||||
|
||||
// Exchange implements upstream.Upstream interface for *TestUpstream.
|
||||
// Exchange implements the upstream.Upstream interface for *Upstream.
|
||||
//
|
||||
// TODO(a.garipov): Split further into handlers.
|
||||
func (u *TestUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = &dns.Msg{}
|
||||
resp.SetReply(m)
|
||||
func (u *Upstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = new(dns.Msg).SetReply(m)
|
||||
|
||||
if len(m.Question) == 0 {
|
||||
return nil, fmt.Errorf("question should not be empty")
|
||||
}
|
||||
|
||||
name := m.Question[0].Name
|
||||
|
||||
if cname, ok := u.CName[name]; ok {
|
||||
ans := &dns.CNAME{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: name,
|
||||
Rrtype: dns.TypeCNAME,
|
||||
},
|
||||
q := m.Question[0]
|
||||
name := q.Name
|
||||
for _, cname := range u.CName[name] {
|
||||
resp.Answer = append(resp.Answer, &dns.CNAME{
|
||||
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME},
|
||||
Target: cname,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
})
|
||||
}
|
||||
|
||||
rrType := m.Question[0].Qtype
|
||||
qtype := q.Qtype
|
||||
hdr := dns.RR_Header{
|
||||
Name: name,
|
||||
Rrtype: rrType,
|
||||
Rrtype: qtype,
|
||||
}
|
||||
|
||||
var names []string
|
||||
var ips []net.IP
|
||||
switch m.Question[0].Qtype {
|
||||
switch qtype {
|
||||
case dns.TypeA:
|
||||
ips = u.IPv4[name]
|
||||
for _, ip := range u.IPv4[name] {
|
||||
resp.Answer = append(resp.Answer, &dns.A{Hdr: hdr, A: ip})
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
ips = u.IPv6[name]
|
||||
for _, ip := range u.IPv6[name] {
|
||||
resp.Answer = append(resp.Answer, &dns.AAAA{Hdr: hdr, AAAA: ip})
|
||||
}
|
||||
case dns.TypePTR:
|
||||
names = u.Reverse[name]
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
var ans dns.RR
|
||||
if rrType == dns.TypeA {
|
||||
ans = &dns.A{
|
||||
Hdr: hdr,
|
||||
A: ip,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
|
||||
continue
|
||||
for _, name := range u.Reverse[name] {
|
||||
resp.Answer = append(resp.Answer, &dns.PTR{Hdr: hdr, Ptr: name})
|
||||
}
|
||||
|
||||
ans = &dns.AAAA{
|
||||
Hdr: hdr,
|
||||
AAAA: ip,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
}
|
||||
|
||||
for _, n := range names {
|
||||
ans := &dns.PTR{
|
||||
Hdr: hdr,
|
||||
Ptr: n,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
}
|
||||
|
||||
if len(resp.Answer) == 0 {
|
||||
resp.SetRcode(m, dns.RcodeNameError)
|
||||
}
|
||||
@@ -104,8 +71,8 @@ func (u *TestUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Address implements upstream.Upstream interface for *TestUpstream.
|
||||
func (u *TestUpstream) Address() string {
|
||||
// Address implements upstream.Upstream interface for *Upstream.
|
||||
func (u *Upstream) Address() string {
|
||||
return u.Addr
|
||||
}
|
||||
|
||||
|
||||
30
internal/aghtls/aghtls.go
Normal file
30
internal/aghtls/aghtls.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Package aghtls contains utilities for work with TLS.
|
||||
package aghtls
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// SaferCipherSuites returns a set of default cipher suites with vulnerable and
|
||||
// weak cipher suites removed.
|
||||
func SaferCipherSuites() (safe []uint16) {
|
||||
for _, s := range tls.CipherSuites() {
|
||||
switch s.ID {
|
||||
case
|
||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
|
||||
// Less safe 3DES and CBC suites, go on.
|
||||
default:
|
||||
safe = append(safe, s.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return safe
|
||||
}
|
||||
@@ -119,23 +119,28 @@ func (l *Lease) UnmarshalJSON(data []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServerConfig - DHCP server configuration
|
||||
// field ordering is important -- yaml fields will mirror ordering from here
|
||||
// ServerConfig is the configuration for the DHCP server. The order of YAML
|
||||
// fields is important, since the YAML configuration file follows it.
|
||||
type ServerConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
InterfaceName string `yaml:"interface_name"`
|
||||
|
||||
Conf4 V4ServerConf `yaml:"dhcpv4"`
|
||||
Conf6 V6ServerConf `yaml:"dhcpv6"`
|
||||
|
||||
WorkDir string `yaml:"-"`
|
||||
DBFilePath string `yaml:"-"` // path to DB file
|
||||
|
||||
// Called when the configuration is changed by HTTP request
|
||||
ConfigModified func() `yaml:"-"`
|
||||
|
||||
// Register an HTTP handler
|
||||
HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request)) `yaml:"-"`
|
||||
|
||||
Enabled bool `yaml:"enabled"`
|
||||
InterfaceName string `yaml:"interface_name"`
|
||||
|
||||
// LocalDomainName is the domain name used for DHCP hosts. For example,
|
||||
// a DHCP client with the hostname "myhost" can be addressed as "myhost.lan"
|
||||
// when LocalDomainName is "lan".
|
||||
LocalDomainName string `yaml:"local_domain_name"`
|
||||
|
||||
Conf4 V4ServerConf `yaml:"dhcpv4"`
|
||||
Conf6 V6ServerConf `yaml:"dhcpv6"`
|
||||
|
||||
WorkDir string `yaml:"-"`
|
||||
DBFilePath string `yaml:"-"`
|
||||
}
|
||||
|
||||
// OnLeaseChangedT is a callback for lease changes.
|
||||
@@ -156,7 +161,9 @@ type Server struct {
|
||||
srv4 DHCPServer
|
||||
srv6 DHCPServer
|
||||
|
||||
conf ServerConfig
|
||||
// TODO(a.garipov): Either create a separate type for the internal config or
|
||||
// just put the config values into Server.
|
||||
conf *ServerConfig
|
||||
|
||||
// Called when the leases DB is modified
|
||||
onLeaseChanged []OnLeaseChangedT
|
||||
@@ -181,14 +188,21 @@ type ServerInterface interface {
|
||||
}
|
||||
|
||||
// Create - create object
|
||||
func Create(conf ServerConfig) (s *Server, err error) {
|
||||
s = &Server{}
|
||||
func Create(conf *ServerConfig) (s *Server, err error) {
|
||||
s = &Server{
|
||||
conf: &ServerConfig{
|
||||
ConfigModified: conf.ConfigModified,
|
||||
|
||||
s.conf.Enabled = conf.Enabled
|
||||
s.conf.InterfaceName = conf.InterfaceName
|
||||
s.conf.HTTPRegister = conf.HTTPRegister
|
||||
s.conf.ConfigModified = conf.ConfigModified
|
||||
s.conf.DBFilePath = filepath.Join(conf.WorkDir, dbFilename)
|
||||
HTTPRegister: conf.HTTPRegister,
|
||||
|
||||
Enabled: conf.Enabled,
|
||||
InterfaceName: conf.InterfaceName,
|
||||
|
||||
LocalDomainName: conf.LocalDomainName,
|
||||
|
||||
DBFilePath: filepath.Join(conf.WorkDir, dbFilename),
|
||||
},
|
||||
}
|
||||
|
||||
if !webHandlersRegistered && s.conf.HTTPRegister != nil {
|
||||
if runtime.GOOS == "windows" {
|
||||
@@ -305,6 +319,7 @@ func (s *Server) notify(flags int) {
|
||||
func (s *Server) WriteDiskConfig(c *ServerConfig) {
|
||||
c.Enabled = s.conf.Enabled
|
||||
c.InterfaceName = s.conf.InterfaceName
|
||||
c.LocalDomainName = s.conf.LocalDomainName
|
||||
s.srv4.WriteDiskConfig4(&c.Conf4)
|
||||
s.srv6.WriteDiskConfig6(&c.Conf6)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func testNotify(flags uint32) {
|
||||
func TestDB(t *testing.T) {
|
||||
var err error
|
||||
s := Server{
|
||||
conf: ServerConfig{
|
||||
conf: &ServerConfig{
|
||||
DBFilePath: dbFilename,
|
||||
},
|
||||
}
|
||||
@@ -140,27 +140,27 @@ func TestNormalizeLeases(t *testing.T) {
|
||||
func TestV4Server_badRange(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
wantErrMsg string
|
||||
gatewayIP net.IP
|
||||
subnetMask net.IP
|
||||
wantErrMsg string
|
||||
}{{
|
||||
name: "gateway_in_range",
|
||||
gatewayIP: net.IP{192, 168, 10, 120},
|
||||
subnetMask: net.IP{255, 255, 255, 0},
|
||||
name: "gateway_in_range",
|
||||
wantErrMsg: "dhcpv4: gateway ip 192.168.10.120 in the ip range: " +
|
||||
"192.168.10.20-192.168.10.200",
|
||||
gatewayIP: net.IP{192, 168, 10, 120},
|
||||
subnetMask: net.IP{255, 255, 255, 0},
|
||||
}, {
|
||||
name: "outside_range_start",
|
||||
gatewayIP: net.IP{192, 168, 10, 1},
|
||||
subnetMask: net.IP{255, 255, 255, 240},
|
||||
name: "outside_range_start",
|
||||
wantErrMsg: "dhcpv4: range start 192.168.10.20 is outside network " +
|
||||
"192.168.10.1/28",
|
||||
}, {
|
||||
name: "outside_range_end",
|
||||
gatewayIP: net.IP{192, 168, 10, 1},
|
||||
subnetMask: net.IP{255, 255, 255, 224},
|
||||
subnetMask: net.IP{255, 255, 255, 240},
|
||||
}, {
|
||||
name: "outside_range_end",
|
||||
wantErrMsg: "dhcpv4: range end 192.168.10.200 is outside network " +
|
||||
"192.168.10.1/27",
|
||||
gatewayIP: net.IP{192, 168, 10, 1},
|
||||
subnetMask: net.IP{255, 255, 255, 224},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -575,12 +575,15 @@ func (s *Server) handleReset(w http.ResponseWriter, r *http.Request) {
|
||||
log.Error("dhcp: removing db: %s", err)
|
||||
}
|
||||
|
||||
oldconf := s.conf
|
||||
s.conf = ServerConfig{
|
||||
WorkDir: oldconf.WorkDir,
|
||||
HTTPRegister: oldconf.HTTPRegister,
|
||||
ConfigModified: oldconf.ConfigModified,
|
||||
DBFilePath: oldconf.DBFilePath,
|
||||
s.conf = &ServerConfig{
|
||||
ConfigModified: s.conf.ConfigModified,
|
||||
|
||||
HTTPRegister: s.conf.HTTPRegister,
|
||||
|
||||
LocalDomainName: s.conf.LocalDomainName,
|
||||
|
||||
WorkDir: s.conf.WorkDir,
|
||||
DBFilePath: s.conf.DBFilePath,
|
||||
}
|
||||
|
||||
v4conf := V4ServerConf{
|
||||
|
||||
@@ -12,33 +12,33 @@ import (
|
||||
func TestNullBool_UnmarshalJSON(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data []byte
|
||||
wantErrMsg string
|
||||
data []byte
|
||||
want nullBool
|
||||
}{{
|
||||
name: "empty",
|
||||
data: []byte{},
|
||||
wantErrMsg: "",
|
||||
data: []byte{},
|
||||
want: nbNull,
|
||||
}, {
|
||||
name: "null",
|
||||
data: []byte("null"),
|
||||
wantErrMsg: "",
|
||||
data: []byte("null"),
|
||||
want: nbNull,
|
||||
}, {
|
||||
name: "true",
|
||||
data: []byte("true"),
|
||||
wantErrMsg: "",
|
||||
data: []byte("true"),
|
||||
want: nbTrue,
|
||||
}, {
|
||||
name: "false",
|
||||
data: []byte("false"),
|
||||
wantErrMsg: "",
|
||||
data: []byte("false"),
|
||||
want: nbFalse,
|
||||
}, {
|
||||
name: "invalid",
|
||||
data: []byte("flase"),
|
||||
wantErrMsg: `invalid nullBool value "flase"`,
|
||||
wantErrMsg: `invalid nullBool value "invalid"`,
|
||||
data: []byte("invalid"),
|
||||
want: nbNull,
|
||||
}}
|
||||
|
||||
|
||||
@@ -969,11 +969,10 @@ func (s *v4Server) send(peer net.Addr, conn net.PacketConn, req, resp *dhcpv4.DH
|
||||
Port: dhcpv4.ServerPort,
|
||||
}
|
||||
if mtype == dhcpv4.MessageTypeNak {
|
||||
// Set the broadcast bit in the DHCPNAK, so that the
|
||||
// relay agent broadcasted it to the client, because the
|
||||
// client may not have a correct network address or
|
||||
// subnet mask, and the client may not be answering ARP
|
||||
// requests.
|
||||
// Set the broadcast bit in the DHCPNAK, so that the relay agent
|
||||
// broadcasts it to the client, because the client may not have
|
||||
// a correct network address or subnet mask, and the client may not
|
||||
// be answering ARP requests.
|
||||
resp.SetBroadcast()
|
||||
}
|
||||
case mtype == dhcpv4.MessageTypeNak:
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
@@ -243,15 +244,15 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
|
||||
proxyConfig.FastestPingTimeout = s.conf.FastestTimeout.Duration
|
||||
}
|
||||
|
||||
if len(s.conf.BogusNXDomain) > 0 {
|
||||
for _, s := range s.conf.BogusNXDomain {
|
||||
ip := net.ParseIP(s)
|
||||
if ip == nil {
|
||||
log.Error("Invalid bogus IP: %s", s)
|
||||
} else {
|
||||
proxyConfig.BogusNXDomain = append(proxyConfig.BogusNXDomain, ip)
|
||||
}
|
||||
for i, s := range s.conf.BogusNXDomain {
|
||||
subnet, err := netutil.ParseSubnet(s)
|
||||
if err != nil {
|
||||
log.Error("subnet at index %d: %s", i, err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
proxyConfig.BogusNXDomain = append(proxyConfig.BogusNXDomain, subnet)
|
||||
}
|
||||
|
||||
// TLS settings
|
||||
@@ -426,6 +427,7 @@ func (s *Server) prepareTLS(proxyConfig *proxy.Config) error {
|
||||
|
||||
proxyConfig.TLSConfig = &tls.Config{
|
||||
GetCertificate: s.onGetCertificate,
|
||||
CipherSuites: aghtls.SaferCipherSuites(),
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
|
||||
|
||||
@@ -215,9 +215,8 @@ func (s *Server) onDHCPLeaseChanged(flags int) {
|
||||
ipToHost = netutil.NewIPMap(len(ll))
|
||||
|
||||
for _, l := range ll {
|
||||
// TODO(a.garipov): Remove this after we're finished
|
||||
// with the client hostname validations in the DHCP
|
||||
// server code.
|
||||
// TODO(a.garipov): Remove this after we're finished with the client
|
||||
// hostname validations in the DHCP server code.
|
||||
err = netutil.ValidateDomainName(l.Hostname)
|
||||
if err != nil {
|
||||
log.Debug(
|
||||
@@ -301,6 +300,8 @@ func (s *Server) processInternalHosts(dctx *dnsContext) (rc resultCode) {
|
||||
}
|
||||
|
||||
reqHost := strings.ToLower(q.Name)
|
||||
// TODO(a.garipov): Move everything related to DHCP local domain to the DHCP
|
||||
// server.
|
||||
host := strings.TrimSuffix(reqHost, s.localDomainSuffix)
|
||||
if host == reqHost {
|
||||
return resultCodeSuccess
|
||||
@@ -612,9 +613,9 @@ func (s *Server) processFilteringAfterResponse(ctx *dnsContext) (rc resultCode)
|
||||
d.Res.Answer = answer
|
||||
}
|
||||
default:
|
||||
// Check the response only if the it's from an upstream. Don't check
|
||||
// the response if the protection is disabled since dnsrewrite rules
|
||||
// aren't applied to it anyway.
|
||||
// Check the response only if it's from an upstream. Don't check the
|
||||
// response if the protection is disabled since dnsrewrite rules aren't
|
||||
// applied to it anyway.
|
||||
if !ctx.protectionEnabled || !ctx.responseFromUpstream || s.dnsFilter == nil {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ func TestServer_ProcessInternalHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_ProcessRestrictLocal(t *testing.T) {
|
||||
ups := &aghtest.TestUpstream{
|
||||
ups := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"251.252.253.254.in-addr.arpa.": {"host1.example.net."},
|
||||
"1.1.168.192.in-addr.arpa.": {"some.local-client."},
|
||||
@@ -339,7 +339,7 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
|
||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
}, &aghtest.TestUpstream{
|
||||
}, &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
reqAddr: {locDomain},
|
||||
},
|
||||
|
||||
@@ -89,7 +89,7 @@ func createTestServer(
|
||||
defer s.serverLock.Unlock()
|
||||
|
||||
if localUps != nil {
|
||||
s.localResolvers.Config.UpstreamConfig.Upstreams = []upstream.Upstream{localUps}
|
||||
s.localResolvers.UpstreamConfig.Upstreams = []upstream.Upstream{localUps}
|
||||
s.conf.UsePrivateRDNS = true
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ func TestServer(t *testing.T) {
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
}, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
|
||||
},
|
||||
@@ -316,7 +316,7 @@ func TestServerWithProtectionDisabled(t *testing.T) {
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
}, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
|
||||
},
|
||||
@@ -339,7 +339,7 @@ func TestDoTServer(t *testing.T) {
|
||||
TLSListenAddrs: []*net.TCPAddr{{}},
|
||||
})
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
|
||||
},
|
||||
@@ -369,7 +369,7 @@ func TestDoQServer(t *testing.T) {
|
||||
QUICListenAddrs: []*net.UDPAddr{{IP: net.IP{127, 0, 0, 1}}},
|
||||
})
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
|
||||
},
|
||||
@@ -413,7 +413,7 @@ func TestServerRace(t *testing.T) {
|
||||
}
|
||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
|
||||
},
|
||||
@@ -552,7 +552,7 @@ func TestServerCustomClientUpstream(t *testing.T) {
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
s.conf.GetCustomUpstreamByClient = func(_ string) (conf *proxy.UpstreamConfig, err error) {
|
||||
ups := &aghtest.TestUpstream{
|
||||
ups := &aghtest.Upstream{
|
||||
IPv4: map[string][]net.IP{
|
||||
"host.": {{192, 168, 0, 1}},
|
||||
},
|
||||
@@ -580,9 +580,9 @@ func TestServerCustomClientUpstream(t *testing.T) {
|
||||
}
|
||||
|
||||
// testCNAMEs is a map of names and CNAMEs necessary for the TestUpstream work.
|
||||
var testCNAMEs = map[string]string{
|
||||
"badhost.": "NULL.example.org.",
|
||||
"whitelist.example.org.": "NULL.example.org.",
|
||||
var testCNAMEs = map[string][]string{
|
||||
"badhost.": {"NULL.example.org."},
|
||||
"whitelist.example.org.": {"NULL.example.org."},
|
||||
}
|
||||
|
||||
// testIPv4 is a map of names and IPv4s necessary for the TestUpstream work.
|
||||
@@ -596,7 +596,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
}, nil)
|
||||
testUpstm := &aghtest.TestUpstream{
|
||||
testUpstm := &aghtest.Upstream{
|
||||
CName: testCNAMEs,
|
||||
IPv4: testIPv4,
|
||||
IPv6: nil,
|
||||
@@ -630,7 +630,7 @@ func TestBlockCNAME(t *testing.T) {
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
CName: testCNAMEs,
|
||||
IPv4: testIPv4,
|
||||
},
|
||||
@@ -640,14 +640,17 @@ func TestBlockCNAME(t *testing.T) {
|
||||
addr := s.dnsProxy.Addr(proxy.ProtoUDP).String()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
host string
|
||||
want bool
|
||||
}{{
|
||||
name: "block_request",
|
||||
host: "badhost.",
|
||||
// 'badhost' has a canonical name 'NULL.example.org' which is
|
||||
// blocked by filters: response is blocked.
|
||||
want: true,
|
||||
}, {
|
||||
name: "allowed",
|
||||
host: "whitelist.example.org.",
|
||||
// 'whitelist.example.org' has a canonical name
|
||||
// 'NULL.example.org' which is blocked by filters
|
||||
@@ -655,6 +658,7 @@ func TestBlockCNAME(t *testing.T) {
|
||||
// response isn't blocked.
|
||||
want: false,
|
||||
}, {
|
||||
name: "block_response",
|
||||
host: "example.org.",
|
||||
// 'example.org' has a canonical name 'cname1' with IP
|
||||
// 127.0.0.255 which is blocked by filters: response is blocked.
|
||||
@@ -662,9 +666,9 @@ func TestBlockCNAME(t *testing.T) {
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run("block_cname_"+tc.host, func(t *testing.T) {
|
||||
req := createTestMessage(tc.host)
|
||||
req := createTestMessage(tc.host)
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
reply, err := dns.Exchange(req, addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -674,7 +678,7 @@ func TestBlockCNAME(t *testing.T) {
|
||||
|
||||
ans := reply.Answer[0]
|
||||
a, ok := ans.(*dns.A)
|
||||
require.Truef(t, ok, "got %T", ans)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.True(t, a.A.IsUnspecified())
|
||||
}
|
||||
@@ -695,7 +699,7 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
&aghtest.Upstream{
|
||||
CName: testCNAMEs,
|
||||
IPv4: testIPv4,
|
||||
},
|
||||
@@ -931,9 +935,9 @@ func TestRewrite(t *testing.T) {
|
||||
}))
|
||||
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.TestUpstream{
|
||||
CName: map[string]string{
|
||||
"example.org": "somename",
|
||||
&aghtest.Upstream{
|
||||
CName: map[string][]string{
|
||||
"example.org": {"somename"},
|
||||
},
|
||||
IPv4: map[string][]net.IP{
|
||||
"example.org.": {{4, 3, 2, 1}},
|
||||
@@ -1193,12 +1197,12 @@ func TestNewServer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_Exchange(t *testing.T) {
|
||||
extUpstream := &aghtest.TestUpstream{
|
||||
extUpstream := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"1.1.1.1.in-addr.arpa.": {"one.one.one.one"},
|
||||
},
|
||||
}
|
||||
locUpstream := &aghtest.TestUpstream{
|
||||
locUpstream := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"1.1.168.192.in-addr.arpa.": {"local.domain"},
|
||||
"2.1.168.192.in-addr.arpa.": {},
|
||||
|
||||
@@ -116,7 +116,7 @@ func (s *Server) filterDNSRequest(ctx *dnsContext) (*filtering.Result, error) {
|
||||
|
||||
// checkHostRules checks the host against filters. It is safe for concurrent
|
||||
// use.
|
||||
func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Settings) (
|
||||
func (s *Server) checkHostRules(host string, rrtype uint16, setts *filtering.Settings) (
|
||||
r *filtering.Result,
|
||||
err error,
|
||||
) {
|
||||
@@ -128,7 +128,7 @@ func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Sett
|
||||
}
|
||||
|
||||
var res filtering.Result
|
||||
res, err = s.dnsFilter.CheckHostRules(host, qtype, setts)
|
||||
res, err = s.dnsFilter.CheckHostRules(host, rrtype, setts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -136,33 +136,36 @@ func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Sett
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// If response contains CNAME, A or AAAA records, we apply filtering to each
|
||||
// canonical host name or IP address. If this is a match, we set a new response
|
||||
// in d.Res and return.
|
||||
func (s *Server) filterDNSResponse(ctx *dnsContext) (*filtering.Result, error) {
|
||||
// filterDNSResponse checks each resource record of the response's answer
|
||||
// section from ctx and returns a non-nil res if at least one of canonnical
|
||||
// names or IP addresses in it matches the filtering rules.
|
||||
func (s *Server) filterDNSResponse(ctx *dnsContext) (res *filtering.Result, err error) {
|
||||
d := ctx.proxyCtx
|
||||
setts := ctx.setts
|
||||
if !setts.FilteringEnabled {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, a := range d.Res.Answer {
|
||||
host := ""
|
||||
|
||||
switch v := a.(type) {
|
||||
var rrtype uint16
|
||||
switch a := a.(type) {
|
||||
case *dns.CNAME:
|
||||
log.Debug("DNSFwd: Checking CNAME %s for %s", v.Target, v.Hdr.Name)
|
||||
host = strings.TrimSuffix(v.Target, ".")
|
||||
|
||||
host = strings.TrimSuffix(a.Target, ".")
|
||||
rrtype = dns.TypeCNAME
|
||||
case *dns.A:
|
||||
host = v.A.String()
|
||||
log.Debug("DNSFwd: Checking record A (%s) for %s", host, v.Hdr.Name)
|
||||
|
||||
host = a.A.String()
|
||||
rrtype = dns.TypeA
|
||||
case *dns.AAAA:
|
||||
host = v.AAAA.String()
|
||||
log.Debug("DNSFwd: Checking record AAAA (%s) for %s", host, v.Hdr.Name)
|
||||
|
||||
host = a.AAAA.String()
|
||||
rrtype = dns.TypeAAAA
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
host = strings.TrimSuffix(host, ".")
|
||||
res, err := s.checkHostRules(host, d.Req.Question[0].Qtype, ctx.setts)
|
||||
log.Debug("dnsforward: checking %s %s for %s", dns.Type(rrtype), host, a.Header().Name)
|
||||
|
||||
res, err = s.checkHostRules(host, rrtype, setts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if res == nil {
|
||||
|
||||
159
internal/dnsforward/filter_test.go
Normal file
159
internal/dnsforward/filter_test.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package dnsforward
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHandleDNSRequest_filterDNSResponse(t *testing.T) {
|
||||
rules := `
|
||||
||blocked.domain^
|
||||
@@||allowed.domain^
|
||||
||cname.specific^$dnstype=~CNAME
|
||||
||0.0.0.1^$dnstype=~A
|
||||
||::1^$dnstype=~AAAA
|
||||
`
|
||||
|
||||
forwardConf := ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
},
|
||||
}
|
||||
filters := []filtering.Filter{{
|
||||
ID: 0, Data: []byte(rules),
|
||||
}}
|
||||
|
||||
f := filtering.New(&filtering.Config{}, filters)
|
||||
f.SetEnabled(true)
|
||||
|
||||
snd, err := aghnet.NewSubnetDetector()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, snd)
|
||||
|
||||
s, err := NewServer(DNSCreateParams{
|
||||
DHCPServer: &testDHCP{},
|
||||
DNSFilter: f,
|
||||
SubnetDetector: snd,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
s.conf = forwardConf
|
||||
err = s.Prepare(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||
&aghtest.Upstream{
|
||||
CName: map[string][]string{
|
||||
"cname.exception.": {"cname.specific."},
|
||||
"should.block.": {"blocked.domain."},
|
||||
"allowed.first.": {"allowed.domain.", "blocked.domain."},
|
||||
"blocked.first.": {"blocked.domain.", "allowed.domain."},
|
||||
},
|
||||
IPv4: map[string][]net.IP{
|
||||
"a.exception.": {{0, 0, 0, 1}},
|
||||
},
|
||||
IPv6: map[string][]net.IP{
|
||||
"aaaa.exception.": {net.ParseIP("::1")},
|
||||
},
|
||||
},
|
||||
}
|
||||
startDeferStop(t, s)
|
||||
|
||||
testCases := []struct {
|
||||
req *dns.Msg
|
||||
name string
|
||||
wantAns []dns.RR
|
||||
}{{
|
||||
req: createTestMessage("cname.exception."),
|
||||
name: "cname_exception",
|
||||
wantAns: []dns.RR{&dns.CNAME{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "cname.exception.",
|
||||
Rrtype: dns.TypeCNAME,
|
||||
},
|
||||
Target: "cname.specific.",
|
||||
}},
|
||||
}, {
|
||||
req: createTestMessage("should.block."),
|
||||
name: "blocked_by_cname",
|
||||
wantAns: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "should.block.",
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
},
|
||||
A: netutil.IPv4Zero(),
|
||||
}},
|
||||
}, {
|
||||
req: createTestMessage("a.exception."),
|
||||
name: "a_exception",
|
||||
wantAns: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "a.exception.",
|
||||
Rrtype: dns.TypeA,
|
||||
},
|
||||
A: net.IP{0, 0, 0, 1},
|
||||
}},
|
||||
}, {
|
||||
req: createTestMessageWithType("aaaa.exception.", dns.TypeAAAA),
|
||||
name: "aaaa_exception",
|
||||
wantAns: []dns.RR{&dns.AAAA{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "aaaa.exception.",
|
||||
Rrtype: dns.TypeAAAA,
|
||||
},
|
||||
AAAA: net.ParseIP("::1"),
|
||||
}},
|
||||
}, {
|
||||
req: createTestMessage("allowed.first."),
|
||||
name: "allowed_first",
|
||||
wantAns: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "allowed.first.",
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
},
|
||||
A: netutil.IPv4Zero(),
|
||||
}},
|
||||
}, {
|
||||
req: createTestMessage("blocked.first."),
|
||||
name: "blocked_first",
|
||||
wantAns: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "blocked.first.",
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
},
|
||||
A: netutil.IPv4Zero(),
|
||||
}},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
dctx := &proxy.DNSContext{
|
||||
Proto: proxy.ProtoUDP,
|
||||
Req: tc.req,
|
||||
Addr: &net.UDPAddr{IP: net.IP{127, 0, 0, 1}, Port: 1},
|
||||
}
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err = s.handleDNSRequest(nil, dctx)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dctx.Res)
|
||||
|
||||
assert.Equal(t, tc.wantAns, dctx.Res.Answer)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -420,14 +420,8 @@ func (r Reason) Matched() bool {
|
||||
}
|
||||
|
||||
// CheckHostRules tries to match the host against filtering rules only.
|
||||
func (d *DNSFilter) CheckHostRules(host string, qtype uint16, setts *Settings) (Result, error) {
|
||||
if !setts.FilteringEnabled {
|
||||
return Result{}, nil
|
||||
}
|
||||
|
||||
host = strings.ToLower(host)
|
||||
|
||||
return d.matchHost(host, qtype, setts)
|
||||
func (d *DNSFilter) CheckHostRules(host string, rrtype uint16, setts *Settings) (Result, error) {
|
||||
return d.matchHost(strings.ToLower(host), rrtype, setts)
|
||||
}
|
||||
|
||||
// CheckHost tries to match the host against filtering rules, then safebrowsing
|
||||
@@ -477,7 +471,7 @@ func (d *DNSFilter) matchSysHosts(
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return d.matchSysHostsIntl(&urlfilter.DNSRequest{
|
||||
dnsres, _ := d.EtcHosts.MatchRequest(urlfilter.DNSRequest{
|
||||
Hostname: host,
|
||||
SortedClientTags: setts.ClientTags,
|
||||
// TODO(e.burkov): Wait for urlfilter update to pass net.IP.
|
||||
@@ -485,12 +479,6 @@ func (d *DNSFilter) matchSysHosts(
|
||||
ClientName: setts.ClientName,
|
||||
DNSType: qtype,
|
||||
})
|
||||
}
|
||||
|
||||
// matchSysHostsIntl actually matches the request. It's separated to avoid
|
||||
// performing checks twice.
|
||||
func (d *DNSFilter) matchSysHostsIntl(req *urlfilter.DNSRequest) (res Result, err error) {
|
||||
dnsres, _ := d.EtcHosts.MatchRequest(*req)
|
||||
if dnsres == nil {
|
||||
return res, nil
|
||||
}
|
||||
@@ -501,13 +489,6 @@ func (d *DNSFilter) matchSysHostsIntl(req *urlfilter.DNSRequest) (res Result, er
|
||||
}
|
||||
|
||||
res = d.processDNSRewrites(dnsr)
|
||||
if cn := res.CanonName; cn != "" {
|
||||
// Probably an alias.
|
||||
req.Hostname = cn
|
||||
|
||||
return d.matchSysHostsIntl(req)
|
||||
}
|
||||
|
||||
res.Reason = RewrittenAutoHosts
|
||||
for _, r := range res.Rules {
|
||||
r.Text = stringutil.Coalesce(d.EtcHosts.Translate(r.Text), r.Text)
|
||||
@@ -739,8 +720,7 @@ func hostRulesToRules(netRules []*rules.HostRule) (res []rules.Rule) {
|
||||
return res
|
||||
}
|
||||
|
||||
// matchHostProcessAllowList processes the allowlist logic of host
|
||||
// matching.
|
||||
// matchHostProcessAllowList processes the allowlist logic of host matching.
|
||||
func (d *DNSFilter) matchHostProcessAllowList(
|
||||
host string,
|
||||
dnsres *urlfilter.DNSResult,
|
||||
@@ -811,11 +791,11 @@ func (d *DNSFilter) matchHostProcessDNSResult(
|
||||
return Result{}
|
||||
}
|
||||
|
||||
// matchHost is a low-level way to check only if hostname is filtered by rules,
|
||||
// matchHost is a low-level way to check only if host is filtered by rules,
|
||||
// skipping expensive safebrowsing and parental lookups.
|
||||
func (d *DNSFilter) matchHost(
|
||||
host string,
|
||||
qtype uint16,
|
||||
rrtype uint16,
|
||||
setts *Settings,
|
||||
) (res Result, err error) {
|
||||
if !setts.FilteringEnabled {
|
||||
@@ -828,7 +808,7 @@ func (d *DNSFilter) matchHost(
|
||||
// TODO(e.burkov): Wait for urlfilter update to pass net.IP.
|
||||
ClientIP: setts.ClientIP.String(),
|
||||
ClientName: setts.ClientName,
|
||||
DNSType: qtype,
|
||||
DNSType: rrtype,
|
||||
}
|
||||
|
||||
d.engineLock.RLock()
|
||||
@@ -868,7 +848,7 @@ func (d *DNSFilter) matchHost(
|
||||
return Result{}, nil
|
||||
}
|
||||
|
||||
res = d.matchHostProcessDNSResult(qtype, dnsres)
|
||||
res = d.matchHostProcessDNSResult(rrtype, dnsres)
|
||||
for _, r := range res.Rules {
|
||||
log.Debug(
|
||||
"filtering: found rule %q for host %q, filter list id: %d",
|
||||
|
||||
@@ -783,17 +783,14 @@ func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
|
||||
|
||||
n := 0
|
||||
hosts.Range(func(ip net.IP, v interface{}) (cont bool) {
|
||||
hosts, ok := v.(*aghnet.Hosts)
|
||||
hosts, ok := v.(*stringutil.Set)
|
||||
if !ok {
|
||||
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if clients.addHostLocked(ip, hosts.Main, ClientSourceHostsFile) {
|
||||
n++
|
||||
}
|
||||
hosts.Aliases.Range(func(name string) (cont bool) {
|
||||
hosts.Range(func(name string) (cont bool) {
|
||||
if clients.addHostLocked(ip, name, ClientSourceHostsFile) {
|
||||
n++
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ package home
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -271,12 +273,18 @@ func TestClientsAddExisting(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("complicated", func(t *testing.T) {
|
||||
// TODO(a.garipov): Properly decouple the DHCP server from the client
|
||||
// storage.
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("skipping dhcp test on windows")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
ip := net.IP{1, 2, 3, 4}
|
||||
|
||||
// First, init a DHCP server with a single static lease.
|
||||
config := dhcpd.ServerConfig{
|
||||
config := &dhcpd.ServerConfig{
|
||||
Enabled: true,
|
||||
DBFilePath: "leases.db",
|
||||
Conf4: dhcpd.V4ServerConf{
|
||||
@@ -290,10 +298,9 @@ func TestClientsAddExisting(t *testing.T) {
|
||||
|
||||
clients.dhcpServer, err = dhcpd.Create(config)
|
||||
require.NoError(t, err)
|
||||
// TODO(e.burkov): leases.db isn't created on Windows so removing it
|
||||
// causes an error. Split the test to make it run properly on different
|
||||
// operating systems.
|
||||
t.Cleanup(func() { _ = os.Remove("leases.db") })
|
||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||
return os.Remove("leases.db")
|
||||
})
|
||||
|
||||
err = clients.dhcpServer.AddStaticLease(&dhcpd.Lease{
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
|
||||
@@ -83,7 +83,7 @@ type configuration struct {
|
||||
WhitelistFilters []filter `yaml:"whitelist_filters"`
|
||||
UserRules []string `yaml:"user_rules"`
|
||||
|
||||
DHCP dhcpd.ServerConfig `yaml:"dhcp"`
|
||||
DHCP *dhcpd.ServerConfig `yaml:"dhcp"`
|
||||
|
||||
// Clients contains the YAML representations of the persistent clients.
|
||||
// This field is only used for reading and writing persistent client data.
|
||||
@@ -123,11 +123,6 @@ type dnsConfig struct {
|
||||
// UpstreamTimeout is the timeout for querying upstream servers.
|
||||
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
|
||||
|
||||
// LocalDomainName is the domain name used for known internal hosts.
|
||||
// For example, a machine called "myhost" can be addressed as
|
||||
// "myhost.lan" when LocalDomainName is "lan".
|
||||
LocalDomainName string `yaml:"local_domain_name"`
|
||||
|
||||
// ResolveClients enables and disables resolving clients with RDNS.
|
||||
ResolveClients bool `yaml:"resolve_clients"`
|
||||
|
||||
@@ -199,7 +194,6 @@ var config = &configuration{
|
||||
FilteringEnabled: true, // whether or not use filter lists
|
||||
FiltersUpdateIntervalHours: 24,
|
||||
UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout},
|
||||
LocalDomainName: "lan",
|
||||
ResolveClients: true,
|
||||
UsePrivateRDNS: true,
|
||||
},
|
||||
@@ -208,6 +202,9 @@ var config = &configuration{
|
||||
PortDNSOverTLS: defaultPortTLS, // needs to be passed through to dnsproxy
|
||||
PortDNSOverQUIC: defaultPortQUIC,
|
||||
},
|
||||
DHCP: &dhcpd.ServerConfig{
|
||||
LocalDomainName: "lan",
|
||||
},
|
||||
logSettings: logSettings{
|
||||
LogCompress: false,
|
||||
LogLocalTime: false,
|
||||
@@ -389,8 +386,8 @@ func (c *configuration) write() error {
|
||||
}
|
||||
|
||||
if Context.dhcpServer != nil {
|
||||
c := dhcpd.ServerConfig{}
|
||||
Context.dhcpServer.WriteDiskConfig(&c)
|
||||
c := &dhcpd.ServerConfig{}
|
||||
Context.dhcpServer.WriteDiskConfig(c)
|
||||
config.DHCP = c
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func initDNSServer() (err error) {
|
||||
QueryLog: Context.queryLog,
|
||||
SubnetDetector: Context.subnetDetector,
|
||||
Anonymizer: anonymizer,
|
||||
LocalDomain: config.DNS.LocalDomainName,
|
||||
LocalDomain: config.DHCP.LocalDomainName,
|
||||
}
|
||||
if Context.dhcpServer != nil {
|
||||
p.DHCPServer = Context.dhcpServer
|
||||
@@ -211,7 +211,6 @@ func generateServerConfig() (newConf dnsforward.ServerConfig, err error) {
|
||||
}
|
||||
|
||||
newConf.TLSv12Roots = Context.tlsRoots
|
||||
newConf.TLSCiphers = Context.tlsCiphers
|
||||
newConf.TLSAllowUnencryptedDoH = tlsConf.AllowUnencryptedDoH
|
||||
|
||||
newConf.FilterHandler = applyAdditionalFiltering
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
@@ -80,7 +81,6 @@ type homeContext struct {
|
||||
disableUpdate bool // If set, don't check for updates
|
||||
controlLock sync.Mutex
|
||||
tlsRoots *x509.CertPool // list of root CAs for TLSv1.2
|
||||
tlsCiphers []uint16 // list of TLS ciphers to use
|
||||
transport *http.Transport
|
||||
client *http.Client
|
||||
appSignalChannel chan os.Signal // Channel for receiving OS signals by the console app
|
||||
@@ -145,13 +145,13 @@ func setupContext(args options) {
|
||||
initConfig()
|
||||
|
||||
Context.tlsRoots = LoadSystemRootCAs()
|
||||
Context.tlsCiphers = InitTLSCiphers()
|
||||
Context.transport = &http.Transport{
|
||||
DialContext: customDialContext,
|
||||
Proxy: getHTTPProxy,
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: Context.tlsRoots,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
RootCAs: Context.tlsRoots,
|
||||
CipherSuites: aghtls.SaferCipherSuites(),
|
||||
MinVersion: tls.VersionTLS12,
|
||||
},
|
||||
}
|
||||
Context.client = &http.Client{
|
||||
@@ -182,7 +182,7 @@ func setupContext(args options) {
|
||||
|
||||
// logIfUnsupported logs a formatted warning if the error is one of the
|
||||
// unsupported errors and returns nil. If err is nil, logIfUnsupported returns
|
||||
// nil. Otherise, it returns err.
|
||||
// nil. Otherwise, it returns err.
|
||||
func logIfUnsupported(msg string, err error) (outErr error) {
|
||||
if errors.As(err, new(*aghos.UnsupportedError)) {
|
||||
log.Debug(msg, err)
|
||||
|
||||
@@ -167,7 +167,7 @@ func TestRDNS_WorkerLoop(t *testing.T) {
|
||||
w := &bytes.Buffer{}
|
||||
aghtest.ReplaceLogWriter(t, w)
|
||||
|
||||
locUpstream := &aghtest.TestUpstream{
|
||||
locUpstream := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"192.168.1.1": {"local.domain"},
|
||||
"2a00:1450:400c:c06::93": {"ipv6.domain"},
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"golang.org/x/sys/cpu"
|
||||
)
|
||||
|
||||
var tlsWebHandlersRegistered = false
|
||||
@@ -731,52 +730,3 @@ func LoadSystemRootCAs() (roots *x509.CertPool) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitTLSCiphers performs the same work as initDefaultCipherSuites() from
|
||||
// crypto/tls/common.go but don't uses lots of other default ciphers.
|
||||
func InitTLSCiphers() (ciphers []uint16) {
|
||||
// Check the cpu flags for each platform that has optimized GCM
|
||||
// implementations. The worst case is when all these variables are
|
||||
// false.
|
||||
var (
|
||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
|
||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
||||
// Keep in sync with crypto/aes/cipher_s390x.go.
|
||||
hasGCMAsmS390X = cpu.S390X.HasAES &&
|
||||
cpu.S390X.HasAESCBC &&
|
||||
cpu.S390X.HasAESCTR &&
|
||||
(cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
|
||||
|
||||
hasGCMAsm = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
|
||||
)
|
||||
|
||||
if hasGCMAsm {
|
||||
// If AES-GCM hardware is provided then prioritize AES-GCM
|
||||
// cipher suites.
|
||||
ciphers = []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
} else {
|
||||
// Without AES-GCM hardware, we put the ChaCha20-Poly1305 cipher
|
||||
// suites first.
|
||||
ciphers = []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
}
|
||||
}
|
||||
|
||||
return append(
|
||||
ciphers,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
// currentSchemaVersion is the current schema version.
|
||||
const currentSchemaVersion = 12
|
||||
const currentSchemaVersion = 13
|
||||
|
||||
// These aliases are provided for convenience.
|
||||
type (
|
||||
@@ -85,6 +85,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
||||
upgradeSchema9to10,
|
||||
upgradeSchema10to11,
|
||||
upgradeSchema11to12,
|
||||
upgradeSchema12to13,
|
||||
}
|
||||
|
||||
n := 0
|
||||
@@ -690,6 +691,52 @@ func upgradeSchema11to12(diskConf yobj) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeSchema12to13 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'dns':
|
||||
// # …
|
||||
// 'local_domain_name': 'lan'
|
||||
//
|
||||
// # AFTER:
|
||||
// 'dhcp':
|
||||
// # …
|
||||
// 'local_domain_name': 'lan'
|
||||
//
|
||||
func upgradeSchema12to13(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 12 to 13")
|
||||
diskConf["schema_version"] = 13
|
||||
|
||||
dnsVal, ok := diskConf["dns"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var dns yobj
|
||||
dns, ok = dnsVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||
}
|
||||
|
||||
dhcpVal, ok := diskConf["dhcp"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var dhcp yobj
|
||||
dhcp, ok = dhcpVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of dhcp: %T", dnsVal)
|
||||
}
|
||||
|
||||
const field = "local_domain_name"
|
||||
|
||||
dhcp[field] = dns[field]
|
||||
delete(dns, field)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(a.garipov): Replace with log.Output when we port it to our logging
|
||||
// package.
|
||||
func funcName() string {
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestUpgradeSchema2to3(t *testing.T) {
|
||||
require.Len(t, v, 1)
|
||||
require.Equal(t, "8.8.8.8:53", v[0])
|
||||
default:
|
||||
t.Fatalf("wrong type for bootsrap dns: %T", v)
|
||||
t.Fatalf("wrong type for bootstrap dns: %T", v)
|
||||
}
|
||||
|
||||
excludedEntries := []string{"bootstrap_dns"}
|
||||
@@ -511,3 +511,48 @@ func TestUpgradeSchema11to12(t *testing.T) {
|
||||
assert.Equal(t, 90*24*time.Hour, ivlVal.Duration)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpgradeSchema12to13(t *testing.T) {
|
||||
t.Run("no_dns", func(t *testing.T) {
|
||||
conf := yobj{}
|
||||
|
||||
err := upgradeSchema12to13(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, conf["schema_version"], 13)
|
||||
})
|
||||
|
||||
t.Run("no_dhcp", func(t *testing.T) {
|
||||
conf := yobj{
|
||||
"dns": yobj{},
|
||||
}
|
||||
|
||||
err := upgradeSchema12to13(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, conf["schema_version"], 13)
|
||||
})
|
||||
|
||||
t.Run("good", func(t *testing.T) {
|
||||
conf := yobj{
|
||||
"dns": yobj{
|
||||
"local_domain_name": "lan",
|
||||
},
|
||||
"dhcp": yobj{},
|
||||
"schema_version": 12,
|
||||
}
|
||||
|
||||
wantConf := yobj{
|
||||
"dns": yobj{},
|
||||
"dhcp": yobj{
|
||||
"local_domain_name": "lan",
|
||||
},
|
||||
"schema_version": 13,
|
||||
}
|
||||
|
||||
err := upgradeSchema12to13(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, wantConf, conf)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
@@ -34,14 +35,13 @@ const (
|
||||
)
|
||||
|
||||
type webConfig struct {
|
||||
clientFS fs.FS
|
||||
clientBetaFS fs.FS
|
||||
|
||||
BindHost net.IP
|
||||
BindPort int
|
||||
BetaBindPort int
|
||||
PortHTTPS int
|
||||
firstRun bool
|
||||
|
||||
clientFS fs.FS
|
||||
clientBetaFS fs.FS
|
||||
|
||||
// ReadTimeout is an option to pass to http.Server for setting an
|
||||
// appropriate field.
|
||||
@@ -54,6 +54,8 @@ type webConfig struct {
|
||||
// WriteTimeout is an option to pass to http.Server for setting an
|
||||
// appropriate field.
|
||||
WriteTimeout time.Duration
|
||||
|
||||
firstRun bool
|
||||
}
|
||||
|
||||
// HTTPSServer - HTTPS Server
|
||||
@@ -263,9 +265,9 @@ func (web *Web) tlsServerLoop() {
|
||||
Addr: address,
|
||||
TLSConfig: &tls.Config{
|
||||
Certificates: []tls.Certificate{web.httpsServer.cert},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
RootCAs: Context.tlsRoots,
|
||||
CipherSuites: Context.tlsCiphers,
|
||||
CipherSuites: aghtls.SaferCipherSuites(),
|
||||
MinVersion: tls.VersionTLS12,
|
||||
},
|
||||
Handler: withMiddlewares(Context.mux, limitRequestBody),
|
||||
ReadTimeout: web.conf.ReadTimeout,
|
||||
|
||||
@@ -306,7 +306,7 @@ func assertLogEntry(t *testing.T, entry *logEntry, host string, answer, client n
|
||||
require.NoError(t, msg.Unpack(entry.Answer))
|
||||
require.Len(t, msg.Answer, 1)
|
||||
|
||||
ip := proxyutil.GetIPFromDNSRecord(msg.Answer[0]).To16()
|
||||
ip := proxyutil.IPFromRR(msg.Answer[0]).To16()
|
||||
assert.Equal(t, answer, ip)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
@@ -26,11 +27,11 @@ const (
|
||||
// TODO(a.garipov): Find out if we can get GOARM and GOMIPS values the same way
|
||||
// we can GOARCH and GOOS.
|
||||
var (
|
||||
channel string = ChannelDevelopment
|
||||
goarm string
|
||||
gomips string
|
||||
version string
|
||||
buildtime string
|
||||
channel string = ChannelDevelopment
|
||||
goarm string
|
||||
gomips string
|
||||
version string
|
||||
committime string
|
||||
)
|
||||
|
||||
// Channel returns the current AdGuard Home release channel.
|
||||
@@ -106,7 +107,7 @@ const (
|
||||
vFmtVerHdr = "Version: "
|
||||
vFmtChanHdr = "Channel: "
|
||||
vFmtGoHdr = "Go version: "
|
||||
vFmtTimeHdr = "Build time: "
|
||||
vFmtTimeHdr = "Commit time: "
|
||||
vFmtRaceHdr = "Race: "
|
||||
vFmtGOOSHdr = "GOOS: " + runtime.GOOS
|
||||
vFmtGOARCHHdr = "GOARCH: " + runtime.GOARCH
|
||||
@@ -148,15 +149,23 @@ func Verbose() (v string) {
|
||||
vFmtGoHdr,
|
||||
runtime.Version(),
|
||||
)
|
||||
if buildtime != "" {
|
||||
stringutil.WriteToBuilder(b, nl, vFmtTimeHdr, buildtime)
|
||||
|
||||
if committime != "" {
|
||||
commitTimeUnix, err := strconv.ParseInt(committime, 10, 64)
|
||||
if err != nil {
|
||||
stringutil.WriteToBuilder(b, nl, vFmtTimeHdr, fmt.Sprintf("parse error: %s", err))
|
||||
} else {
|
||||
stringutil.WriteToBuilder(b, nl, vFmtTimeHdr, time.Unix(commitTimeUnix, 0).String())
|
||||
}
|
||||
}
|
||||
|
||||
stringutil.WriteToBuilder(b, nl, vFmtGOOSHdr, nl, vFmtGOARCHHdr)
|
||||
if goarm != "" {
|
||||
stringutil.WriteToBuilder(b, nl, vFmtGOARMHdr, "v", goarm)
|
||||
} else if gomips != "" {
|
||||
stringutil.WriteToBuilder(b, nl, vFmtGOMIPSHdr, gomips)
|
||||
}
|
||||
|
||||
stringutil.WriteToBuilder(b, nl, vFmtRaceHdr, strconv.FormatBool(isRace))
|
||||
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
|
||||
@@ -90,14 +90,15 @@ Required environment:
|
||||
### `go-build.sh`: Build The Backend
|
||||
|
||||
Optional environment:
|
||||
* `BUILD_TIME`: If set, overrides the build time information. Useful for
|
||||
reproducible builds.
|
||||
* `GOARM`: ARM processor options for the Go compiler.
|
||||
* `GOMIPS`: ARM processor options for the Go compiler.
|
||||
* `GO`: set an alternative name for the Go compiler.
|
||||
* `OUT`: output binary name.
|
||||
* `PARALLELISM`: set the maximum number of concurrently run build commands
|
||||
(that is, compiler, linker, etc.).
|
||||
* `SOURCE_DATE_EPOCH`: the [standardized][repr] environment variable for the
|
||||
Unix epoch time of the latest commit in the repository. If set, overrides
|
||||
the default obtained from Git. Useful for reproducible builds.
|
||||
* `VERBOSE`: verbosity level. `1` shows every command that is run and every
|
||||
Go package that is processed. `2` also shows subcommands and environment.
|
||||
The default value is `0`, don't be verbose.
|
||||
@@ -107,6 +108,8 @@ Optional environment:
|
||||
Required environment:
|
||||
* `CHANNEL`: release channel, see above.
|
||||
|
||||
[repr]: https://reproducible-builds.org/docs/source-date-epoch/
|
||||
|
||||
|
||||
|
||||
### `go-deps.sh`: Install Backend Dependencies
|
||||
|
||||
@@ -384,16 +384,15 @@ rerun_with_root() {
|
||||
|
||||
log 'restarting with root privileges'
|
||||
|
||||
# Group curl together with an echo, so that if curl fails before
|
||||
# producing any output, the echo prints an exit command for the
|
||||
# following shell to execute to prevent it from getting an empty input
|
||||
# and exiting with a zero code in that case.
|
||||
# Group curl together with an echo, so that if curl fails before producing
|
||||
# any output, the echo prints an exit command for the following shell to
|
||||
# execute to prevent it from getting an empty input and exiting with a zero
|
||||
# code in that case.
|
||||
{ curl -L -S -s "$script_url" || echo 'exit 1'; }\
|
||||
| $sudo_cmd sh -s -- -c "$channel" -C "$cpu" -O "$os" -o "$out_dir" "$r" "$u" "$v"
|
||||
|
||||
# Exit the script. Since if the code of the previous pipeline is
|
||||
# non-zero, the execution won't reach this point thanks to set -e, exit
|
||||
# with zero.
|
||||
# Exit the script. Since if the code of the previous pipeline is non-zero,
|
||||
# the execution won't reach this point thanks to set -e, exit with zero.
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -483,11 +482,7 @@ handle_existing() {
|
||||
|
||||
# Function install_service tries to install AGH as service.
|
||||
install_service() {
|
||||
# Installing as root is required at least on FreeBSD.
|
||||
#
|
||||
# TODO(e.burkov): Think about AGH's output suppressing with no verbose
|
||||
# flag.
|
||||
if ( cd "$agh_dir" && $sudo_cmd ./AdGuardHome -s install )
|
||||
if ( cd "$agh_dir" && ./AdGuardHome -s install )
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -5,22 +5,26 @@ FROM alpine:3.13
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION
|
||||
ARG VCS_REF
|
||||
LABEL maintainer="AdGuard Team <devteam@adguard.com>" \
|
||||
org.opencontainers.image.created=$BUILD_DATE \
|
||||
org.opencontainers.image.url="https://adguard.com/adguard-home.html" \
|
||||
org.opencontainers.image.source="https://github.com/AdguardTeam/AdGuardHome" \
|
||||
org.opencontainers.image.version=$VERSION \
|
||||
org.opencontainers.image.revision=$VCS_REF \
|
||||
org.opencontainers.image.vendor="AdGuard" \
|
||||
org.opencontainers.image.title="AdGuard Home" \
|
||||
org.opencontainers.image.description="Network-wide ads & trackers blocking DNS server" \
|
||||
org.opencontainers.image.licenses="GPL-3.0"
|
||||
|
||||
LABEL\
|
||||
maintainer="AdGuard Team <devteam@adguard.com>" \
|
||||
org.opencontainers.image.authors="AdGuard Team <devteam@adguard.com>" \
|
||||
org.opencontainers.image.created=$BUILD_DATE \
|
||||
org.opencontainers.image.description="Network-wide ads & trackers blocking DNS server" \
|
||||
org.opencontainers.image.documentation="https://github.com/AdguardTeam/AdGuardHome/wiki/" \
|
||||
org.opencontainers.image.licenses="GPL-3.0" \
|
||||
org.opencontainers.image.revision=$VCS_REF \
|
||||
org.opencontainers.image.source="https://github.com/AdguardTeam/AdGuardHome" \
|
||||
org.opencontainers.image.title="AdGuard Home" \
|
||||
org.opencontainers.image.url="https://adguard.com/en/adguard-home/overview.html" \
|
||||
org.opencontainers.image.vendor="AdGuard" \
|
||||
org.opencontainers.image.version=$VERSION
|
||||
|
||||
# Update certificates.
|
||||
RUN apk --no-cache --update add ca-certificates libcap tzdata && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
mkdir -p /opt/adguardhome/conf /opt/adguardhome/work && \
|
||||
chown -R nobody: /opt/adguardhome
|
||||
rm -rf /var/cache/apk/* && \
|
||||
mkdir -p /opt/adguardhome/conf /opt/adguardhome/work && \
|
||||
chown -R nobody: /opt/adguardhome
|
||||
|
||||
ARG DIST_DIR
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Experienced readers may find it overly verbose.
|
||||
|
||||
# The default verbosity level is 0. Show log messages if the caller requested
|
||||
# verbosity level greather than 0. Show every command that is run if the
|
||||
# verbosity level greater than 0. Show every command that is run if the
|
||||
# verbosity level is greater than 1. Show the environment if the verbosity
|
||||
# level is greater than 2. Otherwise, print nothing.
|
||||
#
|
||||
@@ -370,26 +370,27 @@ log "writing versions"
|
||||
|
||||
echo "version=$version" > "./${dist}/version.txt"
|
||||
|
||||
# Create the verison.json file.
|
||||
# Create the version.json file.
|
||||
|
||||
version_download_url="https://static.adguard.com/adguardhome/${channel}"
|
||||
version_json="./${dist}/version.json"
|
||||
readonly version_download_url version_json
|
||||
|
||||
# Point users to the master branch if the channel is edge.
|
||||
# If the channel is edge, point users to the "Platforms" page on the Wiki,
|
||||
# because the direct links to the edge packages are listed there.
|
||||
if [ "$channel" = 'edge' ]
|
||||
then
|
||||
version_history_url='https://github.com/AdguardTeam/AdGuardHome/commits/master'
|
||||
announcement_url='https://github.com/AdguardTeam/AdGuardHome/wiki/Platforms'
|
||||
else
|
||||
version_history_url='https://github.com/AdguardTeam/AdGuardHome/releases'
|
||||
announcement_url="https://github.com/AdguardTeam/AdGuardHome/releases/tag/${version}"
|
||||
fi
|
||||
readonly version_history_url
|
||||
readonly announcement_url
|
||||
|
||||
rm -f "$version_json"
|
||||
echo "{
|
||||
\"version\": \"${version}\",
|
||||
\"announcement\": \"AdGuard Home ${version} is now available!\",
|
||||
\"announcement_url\": \"${version_history_url}\",
|
||||
\"announcement_url\": \"${announcement_url}\",
|
||||
\"selfupdate_min_version\": \"0.0\",
|
||||
" >> "$version_json"
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ then
|
||||
fi
|
||||
readonly version
|
||||
|
||||
# Set date and time of the current build unless already set.
|
||||
buildtime="${BUILD_TIME:-$( date -u +%FT%TZ%z )}"
|
||||
readonly buildtime
|
||||
# Set date and time of the latest commit unless already set.
|
||||
committime="${SOURCE_DATE_EPOCH:-$( git log -1 --pretty=%ct )}"
|
||||
readonly committime
|
||||
|
||||
# Set the linker flags accordingly: set the release channel and the current
|
||||
# version as well as goarm and gomips variable values, if the variables are set
|
||||
@@ -78,7 +78,7 @@ readonly version_pkg
|
||||
ldflags="-s -w"
|
||||
ldflags="${ldflags} -X ${version_pkg}.version=${version}"
|
||||
ldflags="${ldflags} -X ${version_pkg}.channel=${channel}"
|
||||
ldflags="${ldflags} -X ${version_pkg}.buildtime=${buildtime}"
|
||||
ldflags="${ldflags} -X ${version_pkg}.committime=${committime}"
|
||||
if [ "${GOARM:-}" != '' ]
|
||||
then
|
||||
ldflags="${ldflags} -X ${version_pkg}.goarm=${GOARM}"
|
||||
|
||||
@@ -86,6 +86,7 @@ in
|
||||
# minor release. If the current commit is the new minor release,
|
||||
# num_commits_since_minor is zero.
|
||||
num_commits_since_minor="$( git rev-list "${last_minor_zero}..HEAD" | wc -l )"
|
||||
|
||||
# The output of darwin's implementation of wc needs to be trimmed from
|
||||
# redundant spaces.
|
||||
num_commits_since_minor="$( echo "$num_commits_since_minor" | tr -d '[:space:]' )"
|
||||
|
||||
Reference in New Issue
Block a user