Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9200163f85 | ||
|
|
3c17853344 | ||
|
|
993a3fc42c | ||
|
|
7bb9b2416b | ||
|
|
2de321ce24 | ||
|
|
30b2b85ff1 | ||
|
|
6ea4788f56 | ||
|
|
3c52a021b9 | ||
|
|
0ceea9af5f | ||
|
|
39b404be19 | ||
|
|
56dc3eab02 | ||
|
|
554a38eeb1 | ||
|
|
c8d3afe869 | ||
|
|
44222c604c | ||
|
|
cbf221585e | ||
|
|
48322f6d0d | ||
|
|
d5a213c639 | ||
|
|
8166c4bc33 | ||
|
|
133cd9ef6b | ||
|
|
11146f73ed | ||
|
|
1beb18db47 | ||
|
|
f7bc2273a7 | ||
|
|
d1e735a003 | ||
|
|
af4ff5c748 | ||
|
|
fc951c1226 | ||
|
|
f81fd42472 | ||
|
|
1029ea5966 | ||
|
|
c0abdb4bc7 | ||
|
|
6681178ad3 |
49
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
49
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,49 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report to help us improve AdGuard Home
|
||||
---
|
||||
|
||||
Have a question or an idea? Please search it [on our forum](https://github.com/AdguardTeam/AdGuardHome/discussions) to make sure it was not yet asked. If you cannot find what you had in mind, please [submit it here](https://github.com/AdguardTeam/AdGuardHome/discussions/new).
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Please answer the following questions for yourself before submitting an issue. **YOU MAY DELETE THE PREREQUISITES SECTION.**
|
||||
|
||||
- [ ] I am running the latest version
|
||||
- [ ] I checked the documentation and found no answer
|
||||
- [ ] I checked to make sure that this issue has not already been filed
|
||||
|
||||
### Issue Details
|
||||
|
||||
<!-- Please include all relevant details about the environment you experienced the bug in. If possible, include the result of running `./AdGuardHome -v --version` from the installation directory. -->
|
||||
|
||||
* **Version of AdGuard Home server:**
|
||||
* <!-- (e.g. v0.123.4) -->
|
||||
* **How did you install AdGuard Home:**
|
||||
* <!-- (e.g. Built from source, Snapcraft, Docker, GitHub releases, etc.) -->
|
||||
* **How did you setup DNS configuration:**
|
||||
* <!-- (System/Router/IoT) -->
|
||||
* **If it's a router or IoT, please write device model:**
|
||||
* <!-- (e.g. Raspberry Pi 3 Model B) -->
|
||||
* **CPU architecture:**
|
||||
* <!-- (e.g. AMD64, MIPS, etc.) -->
|
||||
* **Operating system and version:**
|
||||
* <!-- (e.g. Ubuntu 18.04.1) -->
|
||||
|
||||
### Expected Behavior
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
### Actual Behavior
|
||||
<!-- A clear and concise description of what actually happened. -->
|
||||
|
||||
### Screenshots
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
<details><summary>Screenshot:</summary>
|
||||
|
||||
<!--- drag and drop, upload or paste your screenshot to this area-->
|
||||
|
||||
</details>
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
26
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a feature request for AdGuard Home
|
||||
---
|
||||
|
||||
Have a question or an idea? Please search it [on our forum](https://github.com/AdguardTeam/AdGuardHome/discussions) to make sure it was not yet asked. If you cannot find what you had in mind, please [submit it here](https://github.com/AdguardTeam/AdGuardHome/discussions/new).
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Please answer the following questions for yourself before submitting an issue. **YOU MAY DELETE THE PREREQUISITES SECTION.**
|
||||
|
||||
- [ ] I am running the latest version
|
||||
- [ ] I checked the documentation and found no answer
|
||||
- [ ] I checked to make sure that this issue has not already been filed
|
||||
|
||||
### Problem Description
|
||||
<!-- Is your feature request related to a problem? Please add a clear and concise description of what the problem is. -->
|
||||
|
||||
### Proposed Solution
|
||||
<!-- Describe the solution you'd like in a clear and concise manner -->
|
||||
|
||||
### Alternatives Considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
109
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
109
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
'body':
|
||||
- 'attributes':
|
||||
'description': >
|
||||
Please make sure that the issue is not a duplicate or a question.
|
||||
If it's a duplicate, please react to the original issue with a
|
||||
thumbs up. If it's a question, please post it to the GitHub
|
||||
Discussions page.
|
||||
'label': 'Prerequisites'
|
||||
'options':
|
||||
- 'label': >
|
||||
I have checked the
|
||||
[Wiki](https://github.com/AdguardTeam/AdGuardHome/wiki) and
|
||||
[Discussions](https://github.com/AdguardTeam/AdGuardHome/discussions)
|
||||
and found no answer
|
||||
'required': true
|
||||
- 'label': >
|
||||
I have searched other issues and found no duplicates
|
||||
'required': true
|
||||
- 'label': >
|
||||
I want to report a bug and not ask a question
|
||||
'required': true
|
||||
'id': 'prerequisites'
|
||||
'type': 'checkboxes'
|
||||
- 'attributes':
|
||||
'description': 'On which operating system type does the issue occur?'
|
||||
'label': 'Operating system type'
|
||||
'options':
|
||||
- 'FreeBSD'
|
||||
- 'Linux, OpenWrt'
|
||||
- 'Linux, Other (please mention the version in the description)'
|
||||
- 'macOS (aka Darwin)'
|
||||
- 'OpenBSD'
|
||||
- 'Windows'
|
||||
- 'Other (please mention in the description)'
|
||||
'id': 'os'
|
||||
'type': 'dropdown'
|
||||
'validations':
|
||||
'required': true
|
||||
- 'attributes':
|
||||
'description': 'On which CPU architecture does the issue occur?'
|
||||
'label': 'CPU architecture'
|
||||
'options':
|
||||
- 'AMD64'
|
||||
- 'x86'
|
||||
- '64-bit ARM'
|
||||
- 'ARMv5'
|
||||
- 'ARMv6'
|
||||
- 'ARMv7'
|
||||
- '64-bit MIPS'
|
||||
- '64-bit MIPS LE'
|
||||
- '32-bit MIPS'
|
||||
- '32-bit MIPS LE'
|
||||
- '64-bit PowerPC LE'
|
||||
- 'Other (please mention in the description)'
|
||||
'id': 'arch'
|
||||
'type': 'dropdown'
|
||||
'validations':
|
||||
'required': true
|
||||
- 'attributes':
|
||||
'description': 'How did you install AdGuard Home?'
|
||||
'label': 'Installation'
|
||||
'options':
|
||||
- 'GitHub releases or script from README'
|
||||
- 'Docker'
|
||||
- 'Snapcraft'
|
||||
- 'Custom port'
|
||||
- 'Other (please mention in the description)'
|
||||
'id': 'install'
|
||||
'type': 'dropdown'
|
||||
'validations':
|
||||
'required': true
|
||||
- 'attributes':
|
||||
'description': 'How did you setup AdGuard Home?'
|
||||
'label': 'Setup'
|
||||
'options':
|
||||
- 'On one machine'
|
||||
- 'On a router, DHCP is handled by the router'
|
||||
- 'On a router, DHCP is handled by AdGuard Home'
|
||||
- 'Other (please mention in the description)'
|
||||
'id': 'setup'
|
||||
'type': 'dropdown'
|
||||
'validations':
|
||||
'required': true
|
||||
- 'attributes':
|
||||
'description': 'What version of AdGuard Home are you using?'
|
||||
'label': 'AdGuard Home version'
|
||||
'id': 'version'
|
||||
'type': 'input'
|
||||
'validations':
|
||||
'required': true
|
||||
- 'attributes':
|
||||
'description': 'Please describe the bug'
|
||||
'label': 'Description'
|
||||
'value': |
|
||||
#### What did you do?
|
||||
|
||||
#### Expected result
|
||||
|
||||
#### Actual result
|
||||
|
||||
#### Screenshots (if applicable)
|
||||
|
||||
#### Additional information
|
||||
'id': 'description'
|
||||
'type': 'textarea'
|
||||
'validations':
|
||||
'required': true
|
||||
'description': 'File a bug report'
|
||||
'name': 'Bug'
|
||||
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'blank_issues_enabled': false
|
||||
'contact_links':
|
||||
- 'about': >
|
||||
Please report filtering issues, for example advertising filters
|
||||
misfiring or safe browsing false positives, using the form on our
|
||||
website
|
||||
'name': 'AdGuard filters issues'
|
||||
'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github'
|
||||
- 'about': >
|
||||
Please use GitHub Discussions for questions
|
||||
'name': 'Q&A Discussions'
|
||||
'url': 'https://github.com/AdguardTeam/AdGuardHome/discussions'
|
||||
- 'about': >
|
||||
Please check our Wiki for configuration file description, frequently
|
||||
asked questions, and other documentation
|
||||
'name': 'Wiki'
|
||||
'url': 'https://github.com/AdguardTeam/AdGuardHome/wiki'
|
||||
41
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
41
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
'body':
|
||||
- 'attributes':
|
||||
'description': >
|
||||
Please make sure that the issue is not a duplicate or a question.
|
||||
If it's a duplicate, please react to the original issue with a
|
||||
thumbs up. If it's a question, please post it to the GitHub
|
||||
Discussions page.
|
||||
'label': 'Prerequisites'
|
||||
'options':
|
||||
- 'label': >
|
||||
I have checked the
|
||||
[Wiki](https://github.com/AdguardTeam/AdGuardHome/wiki) and
|
||||
[Discussions](https://github.com/AdguardTeam/AdGuardHome/discussions)
|
||||
and found no answer
|
||||
'required': true
|
||||
- 'label': >
|
||||
I have searched other issues and found no duplicates
|
||||
'required': true
|
||||
- 'label': >
|
||||
I want to request a feature or enhancement and not ask a
|
||||
question
|
||||
'required': true
|
||||
'id': 'prerequisites'
|
||||
'type': 'checkboxes'
|
||||
- 'attributes':
|
||||
'description': 'Please describe the request'
|
||||
'label': 'Description'
|
||||
'value': |
|
||||
#### What problem are you trying to solve?
|
||||
|
||||
#### Proposed solution
|
||||
|
||||
#### Alternatives considered
|
||||
|
||||
#### Additional information
|
||||
'id': 'description'
|
||||
'type': 'textarea'
|
||||
'validations':
|
||||
'required': true
|
||||
'description': 'Suggest a feature or an enhancement for AdGuard Home'
|
||||
'name': 'Feature request or enhancement'
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'build'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.17'
|
||||
'GO_VERSION': '1.18'
|
||||
'NODE_VERSION': '14'
|
||||
|
||||
'on':
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'lint'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.17'
|
||||
'GO_VERSION': '1.18'
|
||||
|
||||
'on':
|
||||
'push':
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
{
|
||||
"project_id": "home",
|
||||
"base_locale": "en",
|
||||
"localizable_files": ["client/src/__locales/en.json"],
|
||||
"localizable_files": [
|
||||
"client/src/__locales/en.json"
|
||||
],
|
||||
"languages": {
|
||||
"ar": "العربية",
|
||||
"be": "Беларуская",
|
||||
"bg": "Български",
|
||||
"cs": "Český",
|
||||
|
||||
103
CHANGELOG.md
103
CHANGELOG.md
@@ -20,26 +20,97 @@ and this project adheres to
|
||||
- Weaker cipher suites that use the CBC (cipher block chaining) mode of
|
||||
operation have been disabled ([#2993]).
|
||||
|
||||
### Added
|
||||
|
||||
- Support for Discovery of Designated Resolvers (DDR) according to the [RFC
|
||||
draft][ddr-draft] ([#4463]).
|
||||
- `windows/arm64` support ([#3057]).
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Go 1.17 support. v0.109.0 will require at least Go 1.18 to build.
|
||||
- Go 1.18 support. v0.109.0 will require at least Go 1.19 to build.
|
||||
|
||||
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
|
||||
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
## [v0.107.11] - 2022-09-28 (APPROX.)
|
||||
|
||||
See also the [v0.107.11 GitHub milestone][ms-v0.107.11].
|
||||
|
||||
[ms-v0.107.11]: https://github.com/AdguardTeam/AdGuardHome/milestone/47?closed=1
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## [v0.107.10] - 2022-08-17
|
||||
|
||||
See also the [v0.107.10 GitHub milestone][ms-v0.107.10].
|
||||
|
||||
[ms-v0.107.10]: https://github.com/AdguardTeam/AdGuardHome/milestone/46?closed=1
|
||||
|
||||
### Added
|
||||
|
||||
- Arabic localization.
|
||||
- Support for Discovery of Designated Resolvers (DDR) according to the [RFC
|
||||
draft][ddr-draft] ([#4463]).
|
||||
|
||||
### Changed
|
||||
|
||||
- Our snap package now uses the `core22` image as its base ([#4843]).
|
||||
|
||||
### Fixed
|
||||
|
||||
- DHCP not working on most OSes ([#4836]).
|
||||
- `invalid argument` errors during update checks on older Linux kernels
|
||||
([#4670]).
|
||||
- Data races and concurrent map access in statistics module ([#4358], [#4342]).
|
||||
|
||||
[#4342]: https://github.com/AdguardTeam/AdGuardHome/issues/4342
|
||||
[#4358]: https://github.com/AdguardTeam/AdGuardHome/issues/4358
|
||||
[#4670]: https://github.com/AdguardTeam/AdGuardHome/issues/4670
|
||||
[#4836]: https://github.com/AdguardTeam/AdGuardHome/issues/4836
|
||||
[#4843]: https://github.com/AdguardTeam/AdGuardHome/issues/4843
|
||||
|
||||
[ddr-draft]: https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-08
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
## [v0.107.9] - 2022-08-23 (APPROX.)
|
||||
-->
|
||||
## [v0.107.9] - 2022-08-03
|
||||
|
||||
See also the [v0.107.9 GitHub milestone][ms-v0.107.9].
|
||||
|
||||
### Security
|
||||
|
||||
- Go version was updated to prevent the possibility of exploiting the
|
||||
CVE-2022-32189 Go vulnerability fixed in [Go 1.18.5][go-1.18.5]. Go 1.17
|
||||
support has also been removed, as it has reached end of life and will not
|
||||
receive security updates.
|
||||
|
||||
### Added
|
||||
|
||||
- Domain-specific upstream servers test. If such test fails, a warning message
|
||||
is shown ([#4517]).
|
||||
- `windows/arm64` support ([#3057]).
|
||||
|
||||
### Changed
|
||||
|
||||
- UI and update links have been changed to make them more resistant to DNS
|
||||
blocking.
|
||||
|
||||
### Fixed
|
||||
|
||||
- DHCP not working on most OSes ([#4836]).
|
||||
- Several UI issues ([#4775], [#4776], [#4782]).
|
||||
|
||||
### Removed
|
||||
|
||||
- Go 1.17 support, as it has reached end of life.
|
||||
|
||||
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
|
||||
[#4517]: https://github.com/AdguardTeam/AdGuardHome/issues/4517
|
||||
[#4775]: https://github.com/AdguardTeam/AdGuardHome/issues/4775
|
||||
[#4776]: https://github.com/AdguardTeam/AdGuardHome/issues/4776
|
||||
[#4782]: https://github.com/AdguardTeam/AdGuardHome/issues/4782
|
||||
[#4836]: https://github.com/AdguardTeam/AdGuardHome/issues/4836
|
||||
|
||||
[go-1.18.5]: https://groups.google.com/g/golang-announce/c/YqYYG87xB10
|
||||
[ms-v0.107.9]: https://github.com/AdguardTeam/AdGuardHome/milestone/45?closed=1
|
||||
|
||||
|
||||
|
||||
@@ -411,7 +482,7 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
|
||||
|
||||
- Upstream server information for responses from cache ([#3772]). Note that old
|
||||
log entries concerning cached responses won't include that information.
|
||||
- Finnish and Ukrainian translations.
|
||||
- Finnish and Ukrainian localizations.
|
||||
- Setting the timeout for IP address pinging in the "Fastest IP address" mode
|
||||
through the new `fastest_timeout` field in the configuration file ([#1992]).
|
||||
- Static IP address detection on FreeBSD ([#3289]).
|
||||
@@ -1046,11 +1117,13 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
|
||||
|
||||
|
||||
<!--
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.9...HEAD
|
||||
[v0.107.9]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.8...v0.107.9
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.11...HEAD
|
||||
[v0.107.11]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.10...v0.107.11
|
||||
-->
|
||||
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.8...HEAD
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.10...HEAD
|
||||
[v0.107.10]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.9...v0.107.10
|
||||
[v0.107.9]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.8...v0.107.9
|
||||
[v0.107.8]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.7...v0.107.8
|
||||
[v0.107.7]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.6...v0.107.7
|
||||
[v0.107.6]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.5...v0.107.6
|
||||
|
||||
2
Makefile
2
Makefile
@@ -39,7 +39,7 @@ YARN_INSTALL_FLAGS = $(YARN_FLAGS) --network-timeout 120000 --silent\
|
||||
# into BUILD_RELEASE_DEPS_0, and so both frontend and backend
|
||||
# dependencies are fetched and the frontend is built. Otherwise, if
|
||||
# FRONTEND_PREBUILT is 1, only backend dependencies are fetched and the
|
||||
# frontend isn't reuilt.
|
||||
# frontend isn't rebuilt.
|
||||
#
|
||||
# TODO(a.garipov): We could probably do that from .../build-release.sh,
|
||||
# but that would mean either calling make from inside make or
|
||||
|
||||
81
README.md
81
README.md
@@ -1,6 +1,6 @@
|
||||
|
||||
<p align="center">
|
||||
<img src="https://cdn.adguard.com/public/Adguard/Common/adguard_home.svg" width="300px" alt="AdGuard Home" />
|
||||
<img src="https://cdn.adtidy.org/public/Adguard/Common/adguard_home.svg" width="300px" alt="AdGuard Home" />
|
||||
</p>
|
||||
<h3 align="center">Privacy protection center for you and your devices</h3>
|
||||
<p align="center">
|
||||
@@ -23,9 +23,6 @@
|
||||
<a href="https://hub.docker.com/r/adguard/adguardhome">
|
||||
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/adguard/adguardhome.svg?maxAge=604800" />
|
||||
</a>
|
||||
<a href="https://hub.docker.com/r/adguard/adguardhome">
|
||||
<img alt="Docker Stars" src="https://img.shields.io/docker/stars/adguard/adguardhome.svg?maxAge=604800" />
|
||||
</a>
|
||||
<br />
|
||||
<a href="https://github.com/AdguardTeam/AdGuardHome/releases">
|
||||
<img src="https://img.shields.io/github/release/AdguardTeam/AdGuardHome/all.svg" alt="Latest release" />
|
||||
@@ -38,14 +35,19 @@
|
||||
<br />
|
||||
|
||||
<p align="center">
|
||||
<img src="https://cdn.adguard.com/public/Adguard/Common/adguard_home.gif" width="800" />
|
||||
<img src="https://cdn.adtidy.org/public/Adguard/Common/adguard_home.gif" width="800" />
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
|
||||
AdGuard Home is a network-wide software for blocking ads & tracking. After you set it up, it'll cover ALL your home devices, and you don't need any client-side software for that.
|
||||
|
||||
It operates as a DNS server that re-routes tracking domains to a "black hole", thus preventing your devices from connecting to those servers. It's based on software we use for our public [AdGuard DNS](https://adguard.com/en/adguard-dns/overview.html) servers -- both share a lot of common code.
|
||||
It operates as a DNS server that re-routes tracking domains to a “black hole”,
|
||||
thus preventing your devices from connecting to those servers. It's based on
|
||||
software we use for our public [AdGuard DNS](https://adguard-dns.io/) servers,
|
||||
and both share a lot of code.
|
||||
|
||||
|
||||
|
||||
* [Getting Started](#getting-started)
|
||||
* [Comparing AdGuard Home to other solutions](#comparison)
|
||||
@@ -114,7 +116,7 @@ If you're running **Linux**, there's a secure and easy way to install AdGuard Ho
|
||||
### API
|
||||
|
||||
If you want to integrate with AdGuard Home, you can use our [REST API](https://github.com/AdguardTeam/AdGuardHome/tree/master/openapi).
|
||||
Alternatively, you can use this [python client](https://pypi.org/project/adguardhome/), which is used to build the [AdGuard Home Hass.io Add-on](https://community.home-assistant.io/t/community-hass-io-add-on-adguard-home).
|
||||
Alternatively, you can use this [python client](https://pypi.org/project/adguardhome/), which is used to build the [AdGuard Home Hass.io Add-on](https://www.home-assistant.io/integrations/adguard/).
|
||||
|
||||
<a id="comparison"></a>
|
||||
## Comparing AdGuard Home to other solutions
|
||||
@@ -161,7 +163,15 @@ AdGuard Home provides a lot of features out-of-the-box with no need to install a
|
||||
|
||||
It depends.
|
||||
|
||||
"DNS sinkholing" is capable of blocking a big percentage of ads, but it lacks flexibility and power of traditional ad blockers. You can get a good impression about the difference between these methods by reading [this article](https://adguard.com/en/blog/adguard-vs-adaway-dns66/). It compares AdGuard for Android (a traditional ad blocker) to hosts-level ad blockers (which are almost identical to DNS-based blockers in their capabilities). This level of protection is enough for some users.
|
||||
“DNS sinkholing” is capable of blocking a big percentage of ads, but it lacks
|
||||
flexibility and power of traditional ad blockers. You can get a good impression
|
||||
about the difference between these methods by reading
|
||||
[this article](https://adguard.com/en/blog/adguard-vs-adaway-dns66/). It
|
||||
compares AdGuard for Android (a traditional ad blocker) to hosts-level ad
|
||||
blockers (which are almost identical to DNS-based blockers in their
|
||||
capabilities). This level of protection is enough for some users.
|
||||
|
||||
|
||||
|
||||
Additionally, using a DNS-based blocker can help to block ads, tracking and analytics requests on other types of devices, such as SmartTVs, smart speakers or other kinds of IoT devices (on which you can't install traditional ad blockers).
|
||||
|
||||
@@ -185,7 +195,7 @@ Run `make init` to prepare the development environment.
|
||||
|
||||
You will need this to build AdGuard Home:
|
||||
|
||||
* [go](https://golang.org/dl/) v1.17 or later.
|
||||
* [go](https://golang.org/dl/) v1.18 or later.
|
||||
* [node.js](https://nodejs.org/en/download/) v10.16.2 or later.
|
||||
* [npm](https://www.npmjs.com/) v6.14 or later (temporary requirement, TODO: remove when redesign is finished).
|
||||
* [yarn](https://yarnpkg.com/) v1.22.5 or later.
|
||||
@@ -281,28 +291,28 @@ curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/s
|
||||
```
|
||||
|
||||
* Beta channel builds
|
||||
* Linux: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_amd64.tar.gz), [32-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_386.tar.gz)
|
||||
* Linux ARM: [32-bit ARMv6](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_armv6.tar.gz) (recommended for Raspberry Pi OS stable), [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_arm64.tar.gz), [32-bit ARMv5](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_armv5.tar.gz), [32-bit ARMv7](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_armv7.tar.gz)
|
||||
* Linux MIPS: [32-bit MIPS](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_mips_softfloat.tar.gz), [32-bit MIPSLE](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_mipsle_softfloat.tar.gz), [64-bit MIPS](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_mips64_softfloat.tar.gz), [64-bit MIPSLE](https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_mips64le_softfloat.tar.gz)
|
||||
* Windows: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_windows_amd64.zip), [32-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_windows_386.zip)
|
||||
* macOS: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_darwin_amd64.zip), [32-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_darwin_386.zip)
|
||||
* macOS ARM: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_darwin_arm64.zip)
|
||||
* FreeBSD: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_amd64.tar.gz), [32-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_386.tar.gz)
|
||||
* FreeBSD ARM: [64-bit](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_arm64.tar.gz), [32-bit ARMv5](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_armv5.tar.gz), [32-bit ARMv6](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_armv6.tar.gz), [32-bit ARMv7](https://static.adguard.com/adguardhome/beta/AdGuardHome_freebsd_armv7.tar.gz)
|
||||
* Linux: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_amd64.tar.gz), [32-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_386.tar.gz)
|
||||
* Linux ARM: [32-bit ARMv6](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_armv6.tar.gz) (recommended for Raspberry Pi OS stable), [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_arm64.tar.gz), [32-bit ARMv5](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_armv5.tar.gz), [32-bit ARMv7](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_armv7.tar.gz)
|
||||
* Linux MIPS: [32-bit MIPS](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_mips_softfloat.tar.gz), [32-bit MIPSLE](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_mipsle_softfloat.tar.gz), [64-bit MIPS](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_mips64_softfloat.tar.gz), [64-bit MIPSLE](https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_mips64le_softfloat.tar.gz)
|
||||
* Windows: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_windows_amd64.zip), [32-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_windows_386.zip)
|
||||
* macOS: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_darwin_amd64.zip), [32-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_darwin_386.zip)
|
||||
* macOS ARM: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_darwin_arm64.zip)
|
||||
* FreeBSD: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_amd64.tar.gz), [32-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_386.tar.gz)
|
||||
* FreeBSD ARM: [64-bit](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_arm64.tar.gz), [32-bit ARMv5](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_armv5.tar.gz), [32-bit ARMv6](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_armv6.tar.gz), [32-bit ARMv7](https://static.adtidy.org/adguardhome/beta/AdGuardHome_freebsd_armv7.tar.gz)
|
||||
* OpenBSD: (coming soon)
|
||||
* OpenBSD ARM: (coming soon)
|
||||
|
||||
* Edge channel builds
|
||||
* Linux: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_amd64.tar.gz), [32-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_386.tar.gz)
|
||||
* Linux ARM: [32-bit ARMv6](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_armv6.tar.gz) (recommended for Raspberry Pi OS stable), [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_arm64.tar.gz), [32-bit ARMv5](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_armv5.tar.gz), [32-bit ARMv7](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_armv7.tar.gz)
|
||||
* Linux MIPS: [32-bit MIPS](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_mips_softfloat.tar.gz), [32-bit MIPSLE](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_mipsle_softfloat.tar.gz), [64-bit MIPS](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_mips64_softfloat.tar.gz), [64-bit MIPSLE](https://static.adguard.com/adguardhome/edge/AdGuardHome_linux_mips64le_softfloat.tar.gz)
|
||||
* Windows: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_windows_amd64.zip), [32-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_windows_386.zip)
|
||||
* macOS: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_darwin_amd64.zip), [32-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_darwin_386.zip)
|
||||
* macOS ARM: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_darwin_arm64.zip)
|
||||
* FreeBSD: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_amd64.tar.gz), [32-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_386.tar.gz)
|
||||
* FreeBSD ARM: [64-bit](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_arm64.tar.gz), [32-bit ARMv5](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_armv5.tar.gz), [32-bit ARMv6](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_armv6.tar.gz), [32-bit ARMv7](https://static.adguard.com/adguardhome/edge/AdGuardHome_freebsd_armv7.tar.gz)
|
||||
* OpenBSD: [64-bit (experimental)](https://static.adguard.com/adguardhome/edge/AdGuardHome_openbsd_amd64.tar.gz)
|
||||
* OpenBSD ARM: [64-bit (experimental)](https://static.adguard.com/adguardhome/edge/AdGuardHome_openbsd_arm64.tar.gz)
|
||||
* Linux: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_amd64.tar.gz), [32-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_386.tar.gz)
|
||||
* Linux ARM: [32-bit ARMv6](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_armv6.tar.gz) (recommended for Raspberry Pi OS stable), [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_arm64.tar.gz), [32-bit ARMv5](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_armv5.tar.gz), [32-bit ARMv7](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_armv7.tar.gz)
|
||||
* Linux MIPS: [32-bit MIPS](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_mips_softfloat.tar.gz), [32-bit MIPSLE](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_mipsle_softfloat.tar.gz), [64-bit MIPS](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_mips64_softfloat.tar.gz), [64-bit MIPSLE](https://static.adtidy.org/adguardhome/edge/AdGuardHome_linux_mips64le_softfloat.tar.gz)
|
||||
* Windows: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_windows_amd64.zip), [32-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_windows_386.zip)
|
||||
* macOS: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_darwin_amd64.zip), [32-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_darwin_386.zip)
|
||||
* macOS ARM: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_darwin_arm64.zip)
|
||||
* FreeBSD: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_amd64.tar.gz), [32-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_386.tar.gz)
|
||||
* FreeBSD ARM: [64-bit](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_arm64.tar.gz), [32-bit ARMv5](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_armv5.tar.gz), [32-bit ARMv6](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_armv6.tar.gz), [32-bit ARMv7](https://static.adtidy.org/adguardhome/edge/AdGuardHome_freebsd_armv7.tar.gz)
|
||||
* OpenBSD: [64-bit (experimental)](https://static.adtidy.org/adguardhome/edge/AdGuardHome_openbsd_amd64.tar.gz)
|
||||
* OpenBSD ARM: [64-bit (experimental)](https://static.adtidy.org/adguardhome/edge/AdGuardHome_openbsd_arm64.tar.gz)
|
||||
|
||||
|
||||
<a id="reporting-issues"></a>
|
||||
@@ -313,9 +323,12 @@ If you run into any problem or have a suggestion, head to [this page](https://gi
|
||||
<a id="translate"></a>
|
||||
### Help with translations
|
||||
|
||||
If you want to help with AdGuard Home translations, please learn more about translating AdGuard products here: https://kb.adguard.com/en/general/adguard-translations
|
||||
If you want to help with AdGuard Home translations, please learn more about
|
||||
translating AdGuard products
|
||||
[in our Knowledge Base](https://kb.adguard.com/en/general/adguard-translations).
|
||||
|
||||
Here is a link to AdGuard Home project: https://crowdin.com/project/adguard-applications/en#/adguard-home
|
||||
Here is a link to AdGuard Home project:
|
||||
<https://crowdin.com/project/adguard-applications/en#/adguard-home>
|
||||
|
||||
<a id="help-other"></a>
|
||||
### Other
|
||||
@@ -364,11 +377,17 @@ This software wouldn't have been possible without:
|
||||
* And many more node.js packages.
|
||||
* [whotracks.me data](https://github.com/cliqz-oss/whotracks.me)
|
||||
|
||||
You might have seen that [CoreDNS](https://coredns.io) was mentioned here before — we've stopped using it in AdGuard Home. While we still use it on our servers for [AdGuard DNS](https://adguard.com/adguard-dns/overview.html) service, it seemed like an overkill for Home as it impeded Home features that we plan to implement.
|
||||
You might have seen that [CoreDNS](https://coredns.io) was mentioned here
|
||||
before, but we've stopped using it in AdGuard Home.
|
||||
|
||||
For a full list of all node.js packages in use, please take a look at [client/package.json](https://github.com/AdguardTeam/AdGuardHome/blob/master/client/package.json) file.
|
||||
|
||||
<a id="privacy"></a>
|
||||
## Privacy
|
||||
|
||||
Our main idea is that you are the one, who should be in control of your data. So it is only natural, that AdGuard Home does not collect any usage statistics, and does not use any web services unless you configure it to do so. Full policy with every bit that _could in theory be_ sent by AdGuard Home is available [here](https://adguard.com/en/privacy/home.html).
|
||||
|
||||
Our main idea is that you are the one, who should be in control of your data.
|
||||
So it is only natural, that AdGuard Home does not collect any usage statistics,
|
||||
and does not use any web services unless you configure it to do so. Full policy
|
||||
with every bit that *could in theory be* sent by AdGuard Home is available
|
||||
[here](https://adguard.com/en/privacy/home.html)
|
||||
|
||||
@@ -7,9 +7,15 @@
|
||||
# Make sure to sync any changes with the branch overrides below.
|
||||
'variables':
|
||||
'channel': 'edge'
|
||||
'dockerGo': 'adguard/golang-ubuntu:4.5'
|
||||
'dockerGo': 'adguard/golang-ubuntu:5.0'
|
||||
|
||||
'stages':
|
||||
- 'Build frontend':
|
||||
'manual': false
|
||||
'final': false
|
||||
'jobs':
|
||||
- 'Build frontend'
|
||||
|
||||
- 'Make release':
|
||||
'manual': false
|
||||
'final': false
|
||||
@@ -22,11 +28,11 @@
|
||||
'jobs':
|
||||
- 'Make and publish docker'
|
||||
|
||||
- 'Publish to static.adguard.com':
|
||||
- 'Publish to static storage':
|
||||
'manual': false
|
||||
'final': false
|
||||
'jobs':
|
||||
- 'Publish to static.adguard.com'
|
||||
- 'Publish to static storage'
|
||||
|
||||
- 'Publish to Snapstore':
|
||||
'manual': false
|
||||
@@ -40,11 +46,41 @@
|
||||
'jobs':
|
||||
- 'Publish to GitHub Releases'
|
||||
|
||||
'Make release':
|
||||
'Build frontend':
|
||||
'docker':
|
||||
'image': '${bamboo.dockerGo}'
|
||||
'volumes':
|
||||
'${system.YARN_DIR}': '${bamboo.cacheYarn}'
|
||||
'key': 'BF'
|
||||
'other':
|
||||
'clean-working-dir': true
|
||||
'tasks':
|
||||
- 'checkout':
|
||||
'force-clean-build': true
|
||||
- 'script':
|
||||
'interpreter': 'SHELL'
|
||||
'scripts':
|
||||
- |
|
||||
#!/bin/sh
|
||||
|
||||
set -e -f -u -x
|
||||
|
||||
# Explicitly checkout the revision that we need.
|
||||
git checkout "${bamboo.repository.revision.number}"
|
||||
|
||||
make js-deps js-build
|
||||
'artifacts':
|
||||
- 'name': 'AdGuardHome frontend'
|
||||
'pattern': 'build*/**'
|
||||
'shared': true
|
||||
'required': true
|
||||
'requirements':
|
||||
- 'adg-docker': 'true'
|
||||
|
||||
'Make release':
|
||||
'docker':
|
||||
'image': '${bamboo.dockerGo}'
|
||||
'volumes':
|
||||
'${system.GO_CACHE_DIR}': '${bamboo.cacheGo}'
|
||||
'${system.GO_PKG_CACHE_DIR}': '${bamboo.cacheGoPkg}'
|
||||
'key': 'MR'
|
||||
@@ -65,13 +101,14 @@
|
||||
git checkout "${bamboo.repository.revision.number}"
|
||||
|
||||
# Run the build with the specified channel.
|
||||
echo "${bamboo.gpgSecretKey}"\
|
||||
echo "${bamboo.gpgSecretKeyPart1}${bamboo.gpgSecretKeyPart2}"\
|
||||
| awk '{ gsub(/\\n/, "\n"); print; }'\
|
||||
| gpg --import --batch --yes
|
||||
|
||||
make\
|
||||
CHANNEL=${bamboo.channel}\
|
||||
GPG_KEY_PASSPHRASE=${bamboo.gpgPassword}\
|
||||
FRONTEND_PREBUILT=1\
|
||||
VERBOSE=1\
|
||||
build-release
|
||||
# TODO(a.garipov): Use more fine-grained artifact rules.
|
||||
@@ -132,7 +169,7 @@
|
||||
'requirements':
|
||||
- 'adg-docker': 'true'
|
||||
|
||||
'Publish to static.adguard.com':
|
||||
'Publish to static storage':
|
||||
'key': 'PUB'
|
||||
'other':
|
||||
'clean-working-dir': true
|
||||
@@ -285,7 +322,7 @@
|
||||
# need to build a few of these.
|
||||
'variables':
|
||||
'channel': 'beta'
|
||||
'dockerGo': 'adguard/golang-ubuntu:4.5'
|
||||
'dockerGo': 'adguard/golang-ubuntu:5.0'
|
||||
# release-vX.Y.Z branches are the branches from which the actual final release
|
||||
# is built.
|
||||
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
|
||||
@@ -300,4 +337,4 @@
|
||||
# are the ones that actually get released.
|
||||
'variables':
|
||||
'channel': 'release'
|
||||
'dockerGo': 'adguard/golang-ubuntu:4.5'
|
||||
'dockerGo': 'adguard/golang-ubuntu:5.0'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'key': 'AHBRTSPECS'
|
||||
'name': 'AdGuard Home - Build and run tests'
|
||||
'variables':
|
||||
'dockerGo': 'adguard/golang-ubuntu:4.5'
|
||||
'dockerGo': 'adguard/golang-ubuntu:5.0'
|
||||
|
||||
'stages':
|
||||
- 'Tests':
|
||||
|
||||
634
client/src/__locales/ar.json
Normal file
634
client/src/__locales/ar.json
Normal file
@@ -0,0 +1,634 @@
|
||||
{
|
||||
"client_settings": "الإعدادات",
|
||||
"example_upstream_reserved": "يمكنك تحديد <0> DNS upstream لنطاق معين (نطاقات) </0>",
|
||||
"example_upstream_comment": "يمكنك تحديد تعليق",
|
||||
"upstream_parallel": "استخدام الاستعلامات المتوازية لتسريع الحل عن طريق الاستعلام في وقت واحد عن جميع خوادم المنبع",
|
||||
"parallel_requests": "طلبات موازية",
|
||||
"load_balancing": "توزيع الحمل",
|
||||
"load_balancing_desc": "الاستعلام عن خادم واحد في كل مرة سيستخدم AdGuard الرئيسية الخوارزمية العشوائية الموزونة لاختيار الخادم بحيث يتم استخدام أسرع خادم في كثير من الأحيان",
|
||||
"bootstrap_dns": "خوادم Bootstrap DNS",
|
||||
"bootstrap_dns_desc": "يتم استخدام خوادم Bootstrap DNS لحل عناوين IP الخاصة بمحللات DoH / DoT التي تحددها على هيئة تدفقات.",
|
||||
"local_ptr_title": "خوادم DNS العكسية الخاصة",
|
||||
"local_ptr_desc": "خوادم DNS التي يستخدمها AdGuard Home لاستعلامات PTR المحلية. تُستخدم هذه الخوادم لحل أسماء المضيفين للعملاء بعناوين IP خاصة ، على سبيل المثال \"192.168.12.34\" ، باستخدام DNS العكسي. في حالة عدم التعيين ، يستخدم AdGuard Home عناوين محللات DNS الافتراضية لنظام التشغيل الخاص بك باستثناء عناوين AdGuard Home نفسها.",
|
||||
"local_ptr_default_resolver": "بشكل افتراضي ، يستخدم AdGuard Home محللات DNS العكسية التالية: {{ip}}.",
|
||||
"local_ptr_no_default_resolver": "لم يتمكن AdGuard Home من تحديد محللات DNS العكسية المناسبة لهذا النظام.",
|
||||
"local_ptr_placeholder": "أدخل عنوان خادم واحد لكل سطر",
|
||||
"resolve_clients_title": "تفعيل التحليل العكسي لعناوين IP للعملاء",
|
||||
"resolve_clients_desc": "حل عكسيًا لعناوين IP للعملاء في أسماء مضيفيهم عن طريق إرسال استعلامات PTR إلى أدوات الحل المقابلة (خوادم DNS الخاصة للعملاء المحليين ، والخوادم الأولية للعملاء الذين لديهم عناوين IP عامة).",
|
||||
"use_private_ptr_resolvers_title": "استخدم محللات DNS العكسية الخاصة",
|
||||
"use_private_ptr_resolvers_desc": "قم بإجراء عمليات بحث DNS عكسية عن العناوين التي يتم تقديمها محليًا باستخدام هذه الخوادم الأولية. في حالة التعطيل ، يستجيب AdGuard Home مع NXDOMAIN لجميع طلبات PTR هذه باستثناء العملاء المعروفين من DHCP و / etc / hosts وما إلى ذلك.",
|
||||
"check_dhcp_servers": "تحقق من خوادم DHCP",
|
||||
"save_config": "حفظ الإعدادات",
|
||||
"enabled_dhcp": "خادم DHCP مفعل",
|
||||
"disabled_dhcp": "خادم DHCP غير مفعل",
|
||||
"unavailable_dhcp": "DHCP غير متوفر",
|
||||
"unavailable_dhcp_desc": "لا يمكن لـ AdGuard Home تشغيل خادم DHCP على نظام التشغيل الخاص بك",
|
||||
"dhcp_title": "خادم DHCP (تجريبي!)",
|
||||
"dhcp_description": "إذا كان جهاز الراوتر الخاص بك لا يوفر إعدادات DHCP ، يمكنك استخدام خادم DHCP المدمج في AdGuard.",
|
||||
"dhcp_enable": "فعل خادم DHCP",
|
||||
"dhcp_disable": "عطل خادم DHCP",
|
||||
"dhcp_not_found": "من الآمن تمكين خادم DHCP المدمج - لم نعثر على أي خوادم DHCP نشطة على الشبكة. ومع ذلك ، نشجعك على إعادة التحقق يدويًا لأن اختبارنا التلقائي في الوقت الحالي لا يوفر ضمانًا بنسبة 100٪.",
|
||||
"dhcp_found": "تم العثور على خادم DHCP نشط على الشبكة. وبالتالي لا ينصح بتفعيل خادم DHCP المدمج.",
|
||||
"dhcp_leases": "عقود إيجار DHCP",
|
||||
"dhcp_static_leases": "إيجارات DHCP الثابتة",
|
||||
"dhcp_leases_not_found": "لم يتم العثور على عقود إيجار DHCP",
|
||||
"dhcp_config_saved": "الإعدادات محفوظة لخادم DHCP",
|
||||
"dhcp_ipv4_settings": "DHCP IPv4 إعدادات",
|
||||
"dhcp_ipv6_settings": "DHCP IPv6 إعدادات",
|
||||
"form_error_required": "الحقل مطلوب",
|
||||
"form_error_ip4_format": "عنوان IPv4 غير صالح",
|
||||
"form_error_ip4_range_start_format": "عناوين البداية لـIPv4 غير صالحة للنطاق",
|
||||
"form_error_ip4_range_end_format": "عناوين IPv4 غير صالحة لنطاق النهاية",
|
||||
"form_error_ip4_gateway_format": "عنوان IPv4 غير صالح للبوابة",
|
||||
"form_error_ip6_format": "عنوان IPv6 غير صالح",
|
||||
"form_error_ip_format": "عنوان IP غير صحيح",
|
||||
"form_error_mac_format": "عنوان MAC غير صالح",
|
||||
"form_error_client_id_format": "يجب أن يحتوي معرف العميل على الأرقام والأحرف الصغيرة والواصلات فقط",
|
||||
"form_error_server_name": "اسم الخادم غير صالح",
|
||||
"form_error_subnet": "لا تحتوي الشبكة الفرعية \"{{cidr}}\" على عنوان IP \"{{ip}}\"",
|
||||
"form_error_positive": "يجب أن يكون أكبر من 0",
|
||||
"out_of_range_error": "يجب أن يكون خارج النطاق \"{{start}}\" - \"{{end}}\"",
|
||||
"lower_range_start_error": "يجب أن يكون أقل من نطاق البداية",
|
||||
"greater_range_start_error": "يجب أن يكون أكبر من نطاق البداية",
|
||||
"greater_range_end_error": "يجب أن يكون أكبر من نطاق النهاية",
|
||||
"subnet_error": "يجب أن تكون العناوين في شبكة فرعية واحدة",
|
||||
"gateway_or_subnet_invalid": "قناع الشبكة الفرعية غير صالح",
|
||||
"dhcp_form_gateway_input": "IP البوابة",
|
||||
"dhcp_form_subnet_input": "قناع الشبكة الفرعية",
|
||||
"dhcp_form_range_title": "مجموعة عناوين IP",
|
||||
"dhcp_form_range_start": "نطاق البداية",
|
||||
"dhcp_form_range_end": "نطاق النهاية",
|
||||
"dhcp_form_lease_title": "مدة تأجير DHCP (بالثواني)",
|
||||
"dhcp_form_lease_input": "مدة الإيجار",
|
||||
"dhcp_interface_select": "حدد واجهة DHCP",
|
||||
"dhcp_hardware_address": "عناوين الأجهزة",
|
||||
"dhcp_ip_addresses": "عناوين الـIP",
|
||||
"ip": "IP",
|
||||
"dhcp_table_hostname": "اسم المضيف",
|
||||
"dhcp_table_expires": "يتنهي في",
|
||||
"dhcp_warning": "إذا كنت تريد تمكين خادم DHCP على أي حال ، فتأكد من عدم وجود خادم DHCP نشط آخر في شبكتك. خلاف ذلك ، يمكن أن يعطل خدمة الإنترنت للأجهزة المتصلة!",
|
||||
"dhcp_error": "لم نتمكن من تحديد ما إذا كان هناك خادم DHCP آخر في الشبكة.",
|
||||
"dhcp_static_ip_error": "من أجل استخدام خادم DHCP ، يجب تعيين عنوان IP ثابت. فشلنا في تحديد ما إذا تم تكوين واجهة الشبكة هذه باستخدام عنوان IP ثابت. يرجى تعيين عنوان IP ثابت يدويًا.",
|
||||
"dhcp_dynamic_ip_found": "يستخدم نظامك عنوان IP الديناميكي للواجهة <0>{{interfaceName}}</0>. من أجل استعمال خادم DHCP ، يجب تعيين عنوان IP ثابت. عنوان IP الحالي الخاص بك هو <0>{{ipAddress}}</0>. إذا ضغطت على زر تفعيل DHCP سنقوم تلقائيًا بتعيين عنوان الIP هذا على أنه ثابت.",
|
||||
"dhcp_lease_added": "تمت أضافة مدة الايجار \"{{key}}\" بنجاح",
|
||||
"dhcp_lease_deleted": "تمت ازالة مدة الايجار \"{{key}}\" بنجاح",
|
||||
"dhcp_new_static_lease": "عقد إيجار ثابت جديد",
|
||||
"dhcp_static_leases_not_found": "لم يتم العثور على عقود إيجار ثابتة DHCP",
|
||||
"dhcp_add_static_lease": "إضافة عقد إيجار ثابت",
|
||||
"dhcp_reset_leases": "إعادة تعيين كافة عقود الإيجار",
|
||||
"dhcp_reset_leases_confirm": "هل أنت متأكد أنك تريد إعادة تعيين كافة عقود الإيجار؟",
|
||||
"dhcp_reset_leases_success": "إعادة تعيين تأجير DHCP بنجاح",
|
||||
"dhcp_reset": "هل أنت متأكد من أنك تريد إعادة تعيين تكوين DHCP؟",
|
||||
"country": "الدولة",
|
||||
"city": "المدينة",
|
||||
"delete_confirm": "هل أنت متأكد من أنك تريد حذف \"{{key}}\"؟",
|
||||
"form_enter_hostname": "أدخل اسم الhostname",
|
||||
"error_details": "مزيد من التفاصيل حول الخطأ",
|
||||
"response_details": "تفاصيل الاستجابة",
|
||||
"request_details": "تفاصيل الطلب",
|
||||
"client_details": "تفاصيل العميل",
|
||||
"details": "التفاصيل",
|
||||
"back": "رجوع",
|
||||
"dashboard": "لوحة القيادة",
|
||||
"settings": "الإعدادات",
|
||||
"filters": "الفلاتر",
|
||||
"filter": "فلتر",
|
||||
"query_log": "سجل الQuery",
|
||||
"compact": "المدمج",
|
||||
"nothing_found": "لم يتم العثور علي شيء...",
|
||||
"faq": "أسئلة مكررة",
|
||||
"version": "الإصدار",
|
||||
"address": "العناوين",
|
||||
"protocol": "البروتوكول",
|
||||
"on": "ON",
|
||||
"off": "OFF",
|
||||
"copyright": "حقوق النشر",
|
||||
"homepage": "الصفحة الرئيسية",
|
||||
"report_an_issue": "الإبلاغ عن مشكلة",
|
||||
"privacy_policy": "سياسة الخصوصية",
|
||||
"enable_protection": "تفعيل الحماية",
|
||||
"enabled_protection": "الحماية مفعلة",
|
||||
"disable_protection": "تعطيل الحماية",
|
||||
"disabled_protection": "الحماية غير مفعلة",
|
||||
"refresh_statics": "تحيين الإحصائيات",
|
||||
"dns_query": "DNS Queries",
|
||||
"blocked_by": "<0>تم حظره بواسطة الفلاتر</0>",
|
||||
"stats_malware_phishing": "حسر البرامج الضارة / والتصيّد",
|
||||
"stats_adult": "حظر مواقع الويب الخاصة بالبالغين",
|
||||
"stats_query_domain": "اعلى النطاقات التي تم الاستعلام عنها",
|
||||
"for_last_24_hours": "لأخر 24 ساعة",
|
||||
"for_last_days": "لآخر {{value}} يوم",
|
||||
"for_last_days_plural": "لآخر {{count}} ايام",
|
||||
"stats_disabled": "تم تعطيل الإحصائيات. يمكنك تشغيله من <0> صفحة الإعدادات </0>.",
|
||||
"stats_disabled_short": "تم تعطيل الإحصائيات",
|
||||
"no_domains_found": "لم يتم العثور على النطاق",
|
||||
"requests_count": "عدد الطلبات",
|
||||
"top_blocked_domains": "اعلى الدومينات المحظورة",
|
||||
"top_clients": "كبار العملاء",
|
||||
"no_clients_found": "لم يتم العثور على عملاء",
|
||||
"general_statistics": "الإحصاءات العامة",
|
||||
"number_of_dns_query_days": "عدد استعلامات DNS التي تمت معالجتها لآخر {{count}} يوم",
|
||||
"number_of_dns_query_days_plural": "عدد استعلامات DNS التي تمت معالجتها لآخر {{count}} أيام",
|
||||
"number_of_dns_query_24_hours": "عدد استعلامات DNS التي تمت معالجتها لآخر 24 ساعة",
|
||||
"number_of_dns_query_blocked_24_hours": "عدد طلبات DNS المحظورة بواسطة فلاتر adblock وقوائم حظر المضيفين",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "عدد طلبات DNS التي تم حظرها من قبل وحدة أمان التصفح AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "عدد من المواقع (الإباحية) للبالغين تم حجبها",
|
||||
"enforced_save_search": "فرض البحث الآمن",
|
||||
"number_of_dns_query_to_safe_search": "عدد طلبات DNS لمحركات البحث التي تم فرض البحث الآمن عنها",
|
||||
"average_processing_time": "متوسط وقت المعالجة",
|
||||
"average_processing_time_hint": "متوسط الوقت بالمللي ثانية عند معالجة طلب DNS",
|
||||
"block_domain_use_filters_and_hosts": "حظر النطاقات باستخدام عوامل التصفية وملفات المضيفين",
|
||||
"filters_block_toggle_hint": "يمكنك إعداد قواعد حظر في <a>المرشحات</a> اعدادات.",
|
||||
"use_adguard_browsing_sec": "استخدم خدمة الويب الأمنية لتصفح AdGuard",
|
||||
"use_adguard_browsing_sec_hint": "سيتحقق AdGuard Home مما إذا كان النطاق محظورًا بواسطة خدمة الويب الخاصة بأمان التصفح. سيستخدم واجهة برمجة تطبيقات بحث صديقة للخصوصية لإجراء الفحص: يتم إرسال بادئة قصيرة فقط من تجزئة اسم المجال SHA256 إلى الخادم.",
|
||||
"use_adguard_parental": "استخدام خدمة AdGuard للرقابة الأبوية على الويب",
|
||||
"use_adguard_parental_hint": "سيتحقق AdGuard Home مما إذا كان النطاق يحتوي على محتوى للبالغين. إنه يستخدم نفس واجهة برمجة التطبيقات الصديقة للخصوصية مثل خدمة الويب الأمنية للتصفح.",
|
||||
"enforce_safe_search": "استخدم البحث الآمن",
|
||||
"enforce_save_search_hint": "سيفرض AdGuard Home البحث الآمن في محركات البحث التالية: Google وYouTube وBing وDuckDuckGo وYandex وPixabay.",
|
||||
"no_servers_specified": "لم يتم تحديد خوادم",
|
||||
"general_settings": "الإعدادات العامة",
|
||||
"dns_settings": "إعدادات الـ DNS",
|
||||
"dns_blocklists": "قوائم حظر DNS",
|
||||
"dns_allowlists": "قوائم السماح لـ DNS",
|
||||
"dns_blocklists_desc": "سيقوم AdGuard Home بحظر النطاقات المطابقة لقوائم الحظر",
|
||||
"dns_allowlists_desc": "سيتم السماح بالنطاقات من قوائم DNS المسموحة حتى لو كانت في أي من قوائم الحظر",
|
||||
"custom_filtering_rules": "قواعد التصفية المخصصة",
|
||||
"encryption_settings": "إعدادات التعمية",
|
||||
"dhcp_settings": "إعدادات DHCP",
|
||||
"upstream_dns": "خادم DNS لـ Upstream",
|
||||
"upstream_dns_help": "أدخل عنوان خادم واحد في كل سطر. <a>تعرف على المزيد</a> حول تكوين خوادم DNS الأولية.",
|
||||
"upstream_dns_configured_in_file": "تم اعداده في {{path}}",
|
||||
"test_upstream_btn": "اختبار upstream",
|
||||
"upstreams": "Upstreams",
|
||||
"apply_btn": "تطبيق",
|
||||
"disabled_filtering_toast": "تم تعطيل الفلترة",
|
||||
"enabled_filtering_toast": "تم تمكين الفلترة",
|
||||
"disabled_safe_browsing_toast": "تم تعطيل التصفح الآمن",
|
||||
"enabled_safe_browsing_toast": "تم تمكين التصفح الآمن",
|
||||
"disabled_parental_toast": "تعطيل الرقابة الأبوية",
|
||||
"enabled_parental_toast": "تفعيل الرقابة الأبوية",
|
||||
"disabled_safe_search_toast": "تعطيل البحث الآمن",
|
||||
"enabled_save_search_toast": "تفعيل البحث الآمن",
|
||||
"enabled_table_header": "تمكين",
|
||||
"name_table_header": "الاسم",
|
||||
"list_url_table_header": "قائمة الروابط",
|
||||
"rules_count_table_header": "عدد القواعد",
|
||||
"last_time_updated_table_header": "آخر تحديث",
|
||||
"actions_table_header": "الإجراءات",
|
||||
"request_table_header": "طلب",
|
||||
"edit_table_action": "تحرير",
|
||||
"delete_table_action": "حذف",
|
||||
"elapsed": "المنقضي",
|
||||
"filters_and_hosts_hint": "يفهم AdGuard Home قواعد حظر الإعلانات الاساسية وملفات الهوست.",
|
||||
"no_blocklist_added": "لم يتم إضافة قوائم الحظر",
|
||||
"no_whitelist_added": "لم تتم إضافة قوائم السماح",
|
||||
"add_blocklist": "إضافة قائمة الحظر",
|
||||
"add_allowlist": "إضافة قائمة السماح",
|
||||
"cancel_btn": "إلغاء",
|
||||
"enter_name_hint": "أدخل الاسم",
|
||||
"enter_url_or_path_hint": "إدخال عنوان URL أو مسار مطلق للقائمة",
|
||||
"check_updates_btn": "تحقق من وجود تحديثات",
|
||||
"new_blocklist": "قائمة حظر جديدة",
|
||||
"new_allowlist": "قائمة السماح الجديدة",
|
||||
"edit_blocklist": "تحرير قائمة الحظر",
|
||||
"edit_allowlist": "تحرير قائمة السماح",
|
||||
"choose_blocklist": "اختر قوائم الحظر",
|
||||
"choose_allowlist": "اختر قوائم السماح",
|
||||
"enter_valid_blocklist": "إدخال عنوان URL صالح إلى قائمة الحظر",
|
||||
"enter_valid_allowlist": "أدخل عنوان URL صالحًا لقائمة السماح",
|
||||
"form_error_url_format": "تنسيق رابط غير صالح",
|
||||
"form_error_url_or_path_format": "عنوان URL أو المسار المطلق للقائمة غير صالح",
|
||||
"custom_filter_rules": "قواعد التصفية المخصصة",
|
||||
"custom_filter_rules_hint": "أدخل قاعدة واحدة على السطر يمكنك استخدام قواعد adblock أو بناء جملة ملفات المضيفين",
|
||||
"system_host_files": "ملفات الهوست للنظام",
|
||||
"examples_title": "أمثلة",
|
||||
"example_meaning_filter_block": "منع الوصول إلى نطاق example.org وجميع نطاقاته الفرعية",
|
||||
"example_meaning_filter_whitelist": "إلغاء حظر الوصول إلى نطاق example.org وجميع نطاقاته الفرعية",
|
||||
"example_meaning_host_block": "الرد ب 127.0.0.1 على example.org (ولكن ليس لنطاقاته الفرعية);",
|
||||
"example_comment": "! ها هو التعليق.",
|
||||
"example_comment_meaning": "فقط تعليق;",
|
||||
"example_comment_hash": "# تعليق أيضًا",
|
||||
"example_regex_meaning": "منع الوصول إلى النطاقات المطابقة للتعبير العادي المحدد.",
|
||||
"example_upstream_regular": "regular DNS (over UDP);",
|
||||
"example_upstream_udp": "regular DNS (over UDP, hostname);",
|
||||
"example_upstream_dot": "مشفر<0>DNS-over-TLS</0>;",
|
||||
"example_upstream_doh": "مشفر <0>DNS-over-HTTPS</0>;",
|
||||
"example_upstream_doq": "encrypted <0>DNS-over-QUIC</0>;",
|
||||
"example_upstream_sdns": "<0>DNS Stamps</0> for <1>DNSCrypt</1> or <2>DNS-over-HTTPS</2> resolvers;",
|
||||
"example_upstream_tcp": "regular DNS (over TCP);",
|
||||
"example_upstream_tcp_hostname": "regular DNS (over TCP, hostname);",
|
||||
"all_lists_up_to_date_toast": "جميع القوائم محدثة بالفعل",
|
||||
"updated_upstream_dns_toast": "تم حفظ خوادم Upstream بنجاح",
|
||||
"dns_test_ok_toast": "تعمل خوادم DNS المحددة بشكل صحيح",
|
||||
"dns_test_not_ok_toast": "خادم \"{{key}}\": لا يمكن استخدامه يرجى التحقق من كتابته بشكل صحيح",
|
||||
"unblock": "إلغاء الحظر",
|
||||
"block": "حظر",
|
||||
"disallow_this_client": "منع هذا العميل",
|
||||
"allow_this_client": "السماح لهذا العميل",
|
||||
"block_for_this_client_only": "احجب هذا العميل فقط",
|
||||
"unblock_for_this_client_only": "إلغاء حجب هذا العميل فقط",
|
||||
"time_table_header": "وقت",
|
||||
"date": "التاريخ",
|
||||
"domain_name_table_header": "اسم النطاق",
|
||||
"domain_or_client": "الدومين أو العميل",
|
||||
"type_table_header": "النوع",
|
||||
"response_table_header": "استجابة",
|
||||
"response_code": "كود الاستجابة",
|
||||
"client_table_header": "عميل",
|
||||
"empty_response_status": "فارغ",
|
||||
"show_all_filter_type": "إظهار الكل",
|
||||
"show_filtered_type": "إظهار ماتمت تصفيته",
|
||||
"no_logs_found": "لم يتم العثور على سجلات",
|
||||
"refresh_btn": "تحديث",
|
||||
"previous_btn": "السابق",
|
||||
"next_btn": "التالي",
|
||||
"loading_table_status": "جار التحميل...",
|
||||
"page_table_footer_text": "الصفحة",
|
||||
"rows_table_footer_text": "صفوف",
|
||||
"updated_custom_filtering_toast": "تحديث قواعد الفلترة المخصصة",
|
||||
"rule_removed_from_custom_filtering_toast": "تم إزالة قاعدة من قواعد الفلترة المخصصة: {{rule}}",
|
||||
"rule_added_to_custom_filtering_toast": "تم إضافة إلى قواعد الفلترة المخصصة: {{rule}}",
|
||||
"query_log_response_status": "الحالات: {{value}}",
|
||||
"query_log_filtered": "تم الفلترة بواسطة {{filter}}",
|
||||
"query_log_confirm_clear": "هل أنت متأكد من أنك تريد محو كامل سجل التصفية؟",
|
||||
"query_log_cleared": "تم مسح سجل الاستعلام بنجاح",
|
||||
"query_log_updated": "تم تحديث سجل الاستعلام بنجاح",
|
||||
"query_log_clear": "مسح سجلات الاستعلام",
|
||||
"query_log_retention": "الاحتفاظ بسجلات الاستعلام",
|
||||
"query_log_enable": "تمكين السجل",
|
||||
"query_log_configuration": "تكوين السجلات",
|
||||
"query_log_disabled": "سجل الاستعلام معطل ويمكن تهيئته من<0>الاعدادات</0>",
|
||||
"query_log_strict_search": "استخدم علامات الاقتباس المزدوجة للبحث الدقيق",
|
||||
"query_log_retention_confirm": "هل أنت متأكد من أنك تريد تغيير الاحتفاظ بسجل الاستعلام؟ إذا قمت بتقليل قيمة الفاصل الزمني سيتم فقدان بعض البيانات",
|
||||
"anonymize_client_ip": "إخفاء عنوان IP العميل",
|
||||
"anonymize_client_ip_desc": "لا تقم بحفظ كامل عنوان IP العميل في السجلات والإحصائيات",
|
||||
"dns_config": "إعداد خادم DNS",
|
||||
"dns_cache_config": "ضبط الملفات المؤقتة لـ DNS",
|
||||
"dns_cache_config_desc": "هنا تستطيع ضبط اعدادات الـ DNS وملفاته",
|
||||
"blocking_mode": "وضع الحجب",
|
||||
"default": "إفتراضي",
|
||||
"nxdomain": "NXDOMAIN",
|
||||
"refused": "مرفوض",
|
||||
"null_ip": "عنوان IP فارغ",
|
||||
"custom_ip": "عنوان IP مخصص",
|
||||
"blocking_ipv4": "حجب عنوان IPv4",
|
||||
"blocking_ipv6": "حجب عنوان IPv6",
|
||||
"dnscrypt": "DNSCrypt",
|
||||
"dns_over_https": "DNS-over-HTTPS",
|
||||
"dns_over_tls": "DNS-over-TLS",
|
||||
"dns_over_quic": "DNS-over-QUIC",
|
||||
"client_id": "عنوان العميل الشخصي",
|
||||
"client_id_placeholder": "ادخل عنوان العميل الشخصي",
|
||||
"client_id_desc": "يمكن تحديد هوية العميل. اعرف المزيد عن كيفية تحديد هوية العملاء <a> هنا</a>.",
|
||||
"download_mobileconfig_doh": "حمّل .mobileconfig for DNS-over-HTTPS",
|
||||
"download_mobileconfig_dot": "حمل .mobileconfig for DNS-over-TLS",
|
||||
"download_mobileconfig": "حمّل ملف الإعدادات",
|
||||
"plain_dns": "عنوان DNS العادي",
|
||||
"form_enter_rate_limit": "ادخل حد التقييم",
|
||||
"rate_limit": "حدود التقييم",
|
||||
"edns_enable": "فعل EDNS client subnet",
|
||||
"edns_cs_desc": "أضف EDNS الشبكة الفرعية للعميل (ECS) إلى الطلبات الأولية وقم بتسجيل القيم المرسلة من قبل العملاء في سجل الاستعلام.",
|
||||
"rate_limit_desc": "عدد الطلبات في الثانية المسموح بها لكل عميل. جعله على 0 يعني عدم وجود حد.",
|
||||
"blocking_ipv4_desc": "سيتم إرجاع عنوان IP لطلب محظور",
|
||||
"blocking_ipv6_desc": "سيتم إرجاع عنوان IP لطلب AAAA محظور",
|
||||
"blocking_mode_default": "الافتراضي: الرد بعنوان IP صفري (0.0.0.0 لـ A ؛ :: لـ AAAA) عند حظره بواسطة قاعدة نمط Adblock ؛ الرد بعنوان IP المحدد في القاعدة عند حظره بواسطة / etc / hosts-style rule",
|
||||
"blocking_mode_refused": "مرفوض: رد برمز مرفوض",
|
||||
"blocking_mode_nxdomain": "NXDOMAIN: الرد باستخدام رمز NXDOMAIN",
|
||||
"blocking_mode_null_ip": "IP Null: الاستجابة بعنوان IP صفري (0.0.0.0 لـ A ؛ :: لـ AAAA)",
|
||||
"blocking_mode_custom_ip": "استجابة IP مخصصة بعنوان IP تم تعيينه يدويًا",
|
||||
"upstream_dns_client_desc": "إذا احتفظت بهذا الحقل فارغًا ، فسيستخدم AdGuard Home الخوادم التي تم تكوينها في<0>DNS إعدادات</0>.",
|
||||
"tracker_source": "مصدر المتعقب",
|
||||
"source_label": "المصدر",
|
||||
"found_in_known_domain_db": "تم العثور عليه في قاعدة بيانات دومينات معروفة.",
|
||||
"category_label": "الفئة",
|
||||
"rule_label": "قواعد",
|
||||
"list_label": "قائمه",
|
||||
"unknown_filter": "فلتر غير معروف {{filterId}}",
|
||||
"known_tracker": "متعقب معروف",
|
||||
"install_welcome_title": "مرحبًا بك في AdGuard Home!",
|
||||
"install_welcome_desc": "AdGuard Home هو إعلان ومتتبع على مستوى الشبكة يمنع خادم DNS. الغرض منه هو السماح لك بالتحكم في شبكتك بأكملها وجميع أجهزتك، ولا يتطلب استخدام برنامج من جانب العميل.",
|
||||
"install_settings_title": "واجهة ويب المسؤول",
|
||||
"install_settings_listen": "واجهة الاستماع",
|
||||
"install_settings_port": "المنفذ",
|
||||
"install_settings_interface_link": "ستكون واجهة الويب الخاصة بمسؤول AdGuard Home متاحة على العناوين التالية:",
|
||||
"form_error_port": "أدخل رقم منفذ صالح",
|
||||
"install_settings_dns": "خادم DNS",
|
||||
"install_settings_dns_desc": "ستحتاج إلى ضبط أجهزتك أو جهاز التوجيه الخاص بك لاستخدام خادم DNS على العناوين التالية:",
|
||||
"install_settings_all_interfaces": "جميع الواجهات",
|
||||
"install_auth_title": "المصادقة",
|
||||
"install_auth_desc": "يجب إعداد مصادقة كلمة المرور لواجهة ويب مسؤول AdGuard Home. في حال كان AdGuard Home لا يمكن الوصول إليه إلا في شبكتك المحلية ، فلا يزال من المهم حمايته من الوصول غير المقيد.",
|
||||
"install_auth_username": "اسم المستخدم",
|
||||
"install_auth_password": "الكلمة السرية",
|
||||
"install_auth_confirm": "تاكيد كلمه المرور",
|
||||
"install_auth_username_enter": "أدخل اسم المستخدم",
|
||||
"install_auth_password_enter": "أدخل كلمة المرور",
|
||||
"install_step": "خطوة",
|
||||
"install_devices_title": "قم بإعداد أجهزتك",
|
||||
"install_devices_desc": "لبدء استخدام AdGuard Home، تحتاج إلى إعداد أجهزتك لاستخدامها.",
|
||||
"install_submit_title": "تهانينا!",
|
||||
"install_submit_desc": "انتهى إجراء الإعداد وأنت على استعداد لبدء استخدام AdGuard Home",
|
||||
"install_devices_router": "راوتر",
|
||||
"install_devices_router_desc": "يغطي هذا الإعداد تلقائيا جميع الأجهزة المتصلة بجهاز التوجيه المنزلي، دون الحاجة إلى تكوين كل منها يدويا.",
|
||||
"install_devices_address": "يستمع خادم AdGuard Home DNS إلى العناوين التالية",
|
||||
"install_devices_router_list_1": "افتح تفضيلات جهاز التوجيه الخاص بك. عادة، يمكنك الوصول إليه من متصفحك عبر عنوان URL، مثل http://192.168.0.1/ أو http://192.168.1.1/. قد يطلب منك إدخال كلمة مرور. إذا كنت لا تتذكر ذلك، يمكنك في كثير من الأحيان إعادة تعيين كلمة المرور عن طريق الضغط على زر في جهاز التوجيه نفسه، ولكن كن على علم بأنه إذا تم اختيار هذا الإجراء، فمن المحتمل أن تفقد إعدادات جهاز التوجيه بأكمله. إذا كان جهاز التوجيه الخاص بك يتطلب تطبيقا لإعداده، فيرجى تثبيت التطبيق على هاتفك أو الكمبيوتر الشخصي واستخدامه للوصول إلى إعدادات جهاز التوجيه.",
|
||||
"install_devices_router_list_2": "ابحث عن إعدادات DHCP / DNS. ابحث عن أحرف DNS بجوار الحقل الذي يسمح بمجموعتين أو ثلاث مجموعات من الأرقام ، كل واحدة مقسمة إلى أربع مجموعات من واحد إلى ثلاثة أرقام.",
|
||||
"install_devices_router_list_3": "أدخل عناوين خادم AdGuard Home هناك.",
|
||||
"install_devices_router_list_4": "في بعض أنواع أجهزة التوجيه ، لا يمكن إعداد خادم DNS مخصص. في هذه الحالة ، قد يساعد إعداد AdGuard Home باعتباره <0>خادم DHCP</0>. بخلاف ذلك ، يجب عليك التحقق من دليل جهاز التوجيه حول كيفية تخصيص خوادم DNS على طراز جهاز التوجيه المحدد الخاص بك.",
|
||||
"install_devices_windows_list_1": "افتح لوحة التحكم من خلال قائمة ابدأ أو بحث Windows.",
|
||||
"install_devices_windows_list_2": "انتقل إلى فئة الشبكة والإنترنت ثم إلى مركز الشبكة والمشاركة.",
|
||||
"install_devices_windows_list_3": "على الجانب الأيسر من الشاشة ، ابحث عن \"تغيير إعدادات المحول\" وانقر عليها.",
|
||||
"install_devices_windows_list_4": "حدد اتصالك النشط ، وانقر فوقه بزر الماوس الأيمن واختر خصائص.",
|
||||
"install_devices_windows_list_5": "ابحث عن \"Internet Protocol Version 4 (TCP / IPv4)\" (أو ، لـ IPv6 ، \"Internet Protocol Version 6 (TCP / IPv6)\") في القائمة ، حدده ثم انقر فوق خصائص مرة أخرى.",
|
||||
"install_devices_windows_list_6": "اختر \"استخدام عناوين خادم DNS التالية\" وأدخل عناوين خادم AdGuard Home.",
|
||||
"install_devices_macos_list_1": "انقر فوق أيقونة Apple وانتقل إلى تفضيلات النظام.",
|
||||
"install_devices_macos_list_2": "اضغط على الشبكة.",
|
||||
"install_devices_macos_list_3": "حدد الاتصال الأول في قائمتك وانقر فوق خيارات متقدمة.",
|
||||
"install_devices_macos_list_4": "حدد علامة التبويب DNS وأدخل عناوين خادم AdGuard Home.",
|
||||
"install_devices_android_list_1": "من الشاشة الرئيسية لقائمة Android ، انقر فوق الإعدادات.",
|
||||
"install_devices_android_list_2": "اضغط على Wi-Fi في القائمة. ستظهر الشاشة التي تسرد جميع الشبكات المتاحة (من المستحيل تعيين DNS مخصص لاتصال المحمول).",
|
||||
"install_devices_android_list_3": "اضغط لفترة طويلة على الشبكة التي تتصل بها ثم اضغط على تعديل الشبكة",
|
||||
"install_devices_android_list_4": "في بعض الأجهزة قد تحتاج إلى تحديد المربع المتقدم لرؤية المزيد من الإعدادات لضبط إعدادات DNS لنظام اندرويد ستحتاج إلى تبديل إعدادات IP من DHCP إلى ثابت.",
|
||||
"install_devices_android_list_5": "قم بتغيير قيم DNS 1 و DNS 2 المعينة لعناوين خادم AdGuard Home",
|
||||
"install_devices_ios_list_1": "من الشاشة الرئيسية انقر فوق الإعدادات",
|
||||
"install_devices_ios_list_2": "اختر Wi-Fi في القائمة اليسرى (من المستحيل ضبط الـ DNS لشبكات الجوال).",
|
||||
"install_devices_ios_list_3": "اضغط على اسم الشبكة النشطة حاليًا.",
|
||||
"install_devices_ios_list_4": "في حقل DNS ، أدخل عناوين خادم AdGuard Home.",
|
||||
"get_started": "أبدأ",
|
||||
"next": "التالي",
|
||||
"open_dashboard": "افتح لوحة التحكم",
|
||||
"install_saved": "تم الحفظ بنجاح",
|
||||
"encryption_title": "التعمية",
|
||||
"encryption_desc": "دعم التشفير (HTTPS / TLS) لكل من DNS وواجهة ويب المسؤول",
|
||||
"encryption_config_saved": "تم حفظ اعدادات التشفير",
|
||||
"encryption_server": "اسم الخادم",
|
||||
"encryption_server_enter": "ادخل عنوان النطاق الخاص بك",
|
||||
"encryption_redirect": "إعادة التوجيه إلى HTTPS تلقائيًا",
|
||||
"encryption_redirect_desc": "إذا تم تحديده ، فسيقوم AdGuard Home بإعادة توجيهك تلقائيًا من عناوين HTTP إلى عناوين HTTPS.",
|
||||
"encryption_https": "منفذ HTTPS",
|
||||
"encryption_https_desc": "إذا تم تكوين منفذ HTTPS ، فسيتم الوصول إلى واجهة مشرف AdGuard Home عبر HTTPS ، وستوفر أيضًا DNS-over-HTTPS على موقع '/dns-query'.",
|
||||
"encryption_dot": "منفذ DNS-over-TLS",
|
||||
"encryption_dot_desc": "إذا تم ضبط هذا المنفذ ، فسيقوم AdGuard Home بتشغيل خادم DNS-over-TLS على هذا المنفذ.",
|
||||
"encryption_doq": "DNS-over-QUIC port",
|
||||
"encryption_doq_desc": "إذا تم ضبط هذا المنفذ، فسيقوم AdGuard Home بتشغيل خادم DNS-over-QUIC على هذا المنفذ.",
|
||||
"encryption_certificates": "الشهادات",
|
||||
"encryption_certificates_desc": "من أجل استخدام التشفير ، تحتاج إلى تقديم سلسلة شهادات SSL صالحة لنطاقك. يمكنك الحصول على شهادة مجانية على <0>{{link}}</0> أو يمكنك شرائها من أحد المراجع المصدقة الموثوقة.",
|
||||
"encryption_certificates_input": "انسخ / الصق الشهادات المشفرة PEM هنا.",
|
||||
"encryption_status": "الحالة",
|
||||
"encryption_expire": "يتنهي في",
|
||||
"encryption_key": "مفتاح خاص",
|
||||
"encryption_key_input": "انسخ / الصق مفتاحك الخاص المشفر بـ PEM لشهادتك هنا",
|
||||
"encryption_enable": "تمكين التشفير (HTTPS و DNS-over-HTTPS و DNS-over-TLS)",
|
||||
"encryption_enable_desc": "إذا تم تمكين التشفير فستعمل واجهة مسؤول AdGuard Home عبر HTTPS وسيستمع خادم DNS للطلبات عبر DNS-over-HTTPS و DNS-over-TLS.",
|
||||
"encryption_chain_valid": "سلسلة الشهادات صالحة",
|
||||
"encryption_chain_invalid": "سلسلة الشهادات غير صالحة",
|
||||
"encryption_key_valid": "هذا مفتاح خاص {{type}} صالح",
|
||||
"encryption_key_invalid": "هذا مفتاح خاص {{type}} غير صالح",
|
||||
"encryption_subject": "الموضوع",
|
||||
"encryption_issuer": "المصدر",
|
||||
"encryption_hostnames": "اسم المستضيف",
|
||||
"encryption_reset": "هل أنت متأكد أنك تريد إعادة تعيين إعدادات التشفير؟",
|
||||
"topline_expiring_certificate": "شهادة SSL الخاصة بك على وشك الانتهاء. قم بتحديث <0>إعدادات التشفير</0>.",
|
||||
"topline_expired_certificate": "انتهت صلاحية شهادة SSL الخاصة بك. قم بتحديث <0>إعدادات التشفير</0>.",
|
||||
"form_error_port_range": "أدخل رقم المنفذ في النطاق 80-65535",
|
||||
"form_error_port_unsafe": "منفذ غير آمن",
|
||||
"form_error_equal": "يجب ألا تكون متساوية",
|
||||
"form_error_password": "كلمة السر غير مطابقة",
|
||||
"reset_settings": "إعادة ضبط الإعدادات",
|
||||
"update_announcement": "AdGuard Home {{version}} متوفر الآن! <0>انقر هنا</0> لمزيد من المعلومات.",
|
||||
"setup_guide": "دليل الإعداد",
|
||||
"dns_addresses": "عناوين DNS",
|
||||
"dns_start": "خادم DNS قيد التشغيل",
|
||||
"dns_status_error": "خطأ في التحقق من حالة خادم الـ DNS",
|
||||
"down": "تحت",
|
||||
"fix": "يصلح",
|
||||
"dns_providers": "فيما يلي قائمة <0> بموفري DNS المعروفين </0> للاختيار من بينها.",
|
||||
"update_now": "تحديث الآن",
|
||||
"update_failed": "فشل التحديث التلقائي. الرجاء <a> اتباع هذه الخطوات </a> للتحديث يدويًا.",
|
||||
"manual_update": "الرجاء <a> اتباع هذه الخطوات </a> للتحديث يدويًا.",
|
||||
"processing_update": "يُرجى الانتظار ، يتم تحديث صفحة AdGuard الرئيسية",
|
||||
"clients_title": "العملاء الدائمين",
|
||||
"clients_desc": "قم بضبط سجلات العميل الدائمة للأجهزة المتصلة بـ AdGuard Home",
|
||||
"settings_global": "عالمي",
|
||||
"settings_custom": "مخصص",
|
||||
"table_client": "العميل",
|
||||
"table_name": "الاسم",
|
||||
"save_btn": "حفظ",
|
||||
"client_add": "إضافة عميل",
|
||||
"client_new": "عميل جديد",
|
||||
"client_edit": "تعديل العميل",
|
||||
"client_identifier": "المعّرف",
|
||||
"ip_address": "عنوان IP",
|
||||
"client_identifier_desc": "يمكن التعرف على العملاء من خلال عنوان IP أو CIDR أو عنوان MAC أو ClientID (يمكن استخدامه في DoT / DoH / DoQ). تعرف على المزيد حول كيفية تحديد العملاء <0> هنا </0>.",
|
||||
"form_enter_ip": "ادخل عنوان IP",
|
||||
"form_enter_subnet_ip": "أدخل عنوان IP في الشبكة الفرعية \"{{cidr}}\"",
|
||||
"form_enter_mac": "ادخل MAC",
|
||||
"form_enter_id": "ادخل المعّرف",
|
||||
"form_add_id": "أضافة معّرف",
|
||||
"form_client_name": "ادخل اسم العميل",
|
||||
"name": "اسم",
|
||||
"client_global_settings": "استخدم إعدادات عالمية",
|
||||
"client_deleted": "تم حذف العميل \"{{key}}\" بنجاح",
|
||||
"client_added": "تم اضافة العميل \"{{key}}\" بنجاح",
|
||||
"client_updated": "تم تحديث العميل \"{{key}}\" بنجاح",
|
||||
"clients_not_found": "لم يتم العثور على عملاء",
|
||||
"client_confirm_delete": "هل أنت متأكد من أنك تريد حذف العميل \"{{key}}\"?",
|
||||
"list_confirm_delete": "هل أنت متأكد أنك تريد حذف هذه القائمة؟",
|
||||
"auto_clients_title": "Runtime clients",
|
||||
"auto_clients_desc": "الأجهزة غير المدرجة في قائمة العملاء الدائمين الذين قد لا يزالون يستخدمون AdGuard Home",
|
||||
"access_title": "إعدادات الوصول",
|
||||
"access_desc": "هنا يمكنك ضبط قواعد الوصول لخادم AdGuard Home DNS",
|
||||
"access_allowed_title": "العملاء المسموحين",
|
||||
"access_allowed_desc": "قائمة CIDRs أو عناوين IP أو <a> ClientIDs </a>. إذا كانت هذه القائمة تحتوي على إدخالات ، فسيقبل AdGuard Home الطلبات من هؤلاء العملاء فقط.",
|
||||
"access_disallowed_title": "العملاء غير المسموحين",
|
||||
"access_disallowed_desc": "قائمة CIDRs أو عناوين IP أو <a> ClientIDs </a>. إذا كانت هذه القائمة تحتوي على إدخالات ، فسيقوم AdGuard Home بإسقاط الطلبات من هؤلاء العملاء. يتم تجاهل هذا الحقل إذا كانت هناك إدخالات في العملاء المسموح لهم.",
|
||||
"access_blocked_title": "النطاقات غير المسموح بها",
|
||||
"access_blocked_desc": "لا ينبغي الخلط بينه وبين المرشحات. يسقط AdGuard Home استعلامات DNS المطابقة لهذه المجالات ، ولا تظهر هذه الاستعلامات حتى في سجل الاستعلام. يمكنك تحديد أسماء النطاقات الدقيقة أو أحرف البدل أو قواعد تصفية عناوين URL ، على سبيل المثال \"example.org\" أو \"*.example.org\" أو \"|| example.org ^\" في المقابل.",
|
||||
"access_settings_saved": "تم حفظ إعدادات الوصول بنجاح",
|
||||
"updates_checked": "يتوفر إصدار جديد من AdGuard Home",
|
||||
"updates_version_equal": "AdGuard Home محدث",
|
||||
"check_updates_now": "تحقق من وجود تحديثات الآن",
|
||||
"dns_privacy": "خصوصية DNS",
|
||||
"setup_dns_privacy_1": "<0> DNS-over-TLS: </0> استخدم سلسلة <1> {{address}} </1>.",
|
||||
"setup_dns_privacy_2": "<0> DNS-over-HTTPS: </0> استخدم سلسلة <1> {{address}} </1>.",
|
||||
"setup_dns_privacy_3": "<0> فيما يلي قائمة بالبرامج التي يمكنك استخدامها. </0>",
|
||||
"setup_dns_privacy_4": "على جهاز iOS 14 أو macOS Big Sur ، يمكنك تنزيل ملف \".mobileconfig\" خاص يضيف خوادم <highlight> DNS-over-HTTPS </highlight> أو <highlight> DNS-over-TLS </highlight> إلى إعدادات DNS.",
|
||||
"setup_dns_privacy_android_1": "يدعم Android 9 DNS-over-TLS أصلاً. لتكوينه ، انتقل إلى الإعدادات → الشبكة والإنترنت → متقدم → DNS الخاص وأدخل اسم المجال الخاص بك هناك.",
|
||||
"setup_dns_privacy_android_2": "<0> AdGuard لنظام Android </0> يدعم <1> DNS-over-HTTPS </1> و <1> DNS-over-TLS </1>.",
|
||||
"setup_dns_privacy_android_3": "<0> Intra </0> يضيف دعم <1> DNS-over-HTTPS </1> إلى Android.",
|
||||
"setup_dns_privacy_ios_1": "<0> DNSCloak </0> يدعم <1> DNS-over-HTTPS </1> ، ولكن من أجل تكوينه لاستخدام الخادم الخاص بك ، ستحتاج إلى إنشاء <2> DNS Stamp </2> لذلك.",
|
||||
"setup_dns_privacy_ios_2": "<0> AdGuard لنظام iOS </0> يدعم إعداد <1> DNS-over-HTTPS </1> و <1> DNS-over-TLS </1> الإعداد.",
|
||||
"setup_dns_privacy_other_title": "تطبيقات أخرى",
|
||||
"setup_dns_privacy_other_1": "يمكن أن يكون AdGuard Home نفسه عميل DNS آمنًا على أي نظام أساسي.",
|
||||
"setup_dns_privacy_other_2": "يدعم <0> dnsproxy </0> جميع بروتوكولات DNS الآمنة المعروفة.",
|
||||
"setup_dns_privacy_other_3": "<0> dnscrypt-proxy </0> يدعم <1> DNS-over-HTTPS </1>.",
|
||||
"setup_dns_privacy_other_4": "يدعم <0> Mozilla Firefox </0> <1> DNS-over-HTTPS </1>.",
|
||||
"setup_dns_privacy_other_5": "ستجد المزيد من التطبيقات <0> هنا </0> و <1> هنا </1>.",
|
||||
"setup_dns_privacy_ioc_mac": "اعدادات iOS و macOS",
|
||||
"setup_dns_notice": "من أجل استخدام <0> DNS-over-HTTPS </0> أو <1> DNS-over-TLS </1> ، تحتاج إلى <1> تكوين التشفير </1> في إعدادات AdGuard Home.",
|
||||
"rewrite_added": "تمت إضافة إعادة كتابة DNS لـ \"{{key}}\" بنجاح",
|
||||
"rewrite_deleted": "تم حذف إعادة كتابة DNS لـ \"{{key}}\" بنجاح",
|
||||
"rewrite_add": "إضافة إعادة كتابة DNS",
|
||||
"rewrite_not_found": "لم يتم العثور على إعادة كتابة DNS",
|
||||
"rewrite_confirm_delete": "هل أنت متأكد من أنك تريد حذف إعادة كتابة DNS لـ \"{{key}}\"؟",
|
||||
"rewrite_desc": "يسمح بتكوين استجابة DNS المخصصة بسهولة لاسم نطاق معين.",
|
||||
"rewrite_applied": "يتم تطبيق قاعدة إعادة الكتابة",
|
||||
"rewrite_hosts_applied": "أعيد كتابتها بواسطة قاعدة ملف المضيفين",
|
||||
"dns_rewrites": "إعادة كتابة DNS",
|
||||
"form_domain": "أدخل اسم النطاق أو حرف البدل",
|
||||
"form_answer": "أدخل عنوان IP أو اسم النطاق",
|
||||
"form_error_domain_format": "تنسيق النطاق غير صالح",
|
||||
"form_error_answer_format": "تنسيق إجابة غير صالح",
|
||||
"configure": "ضبط",
|
||||
"main_settings": "الاعدادات الرئيسية",
|
||||
"block_services": "حظر خدمات معينة",
|
||||
"blocked_services": "الخوادم المحجوبة",
|
||||
"blocked_services_desc": "يسمح بحجب المواقع والخدمات الشعبية بسرعة.",
|
||||
"blocked_services_saved": "تم حفظ الخوادم المحجوبة بنجاح",
|
||||
"blocked_services_global": "استخدام خدمات الحظر العالمية",
|
||||
"blocked_service": "الخدمات المحجوبة",
|
||||
"block_all": "حجب الكل",
|
||||
"unblock_all": "إلغاء حجب الكل",
|
||||
"encryption_certificate_path": "مسار الشهادة",
|
||||
"encryption_private_key_path": "مسار المفتاح الخاص",
|
||||
"encryption_certificates_source_path": "قم بتعيين مسار ملف الشهادات",
|
||||
"encryption_certificates_source_content": "الصق محتويات الشهادات",
|
||||
"encryption_key_source_path": "قم بتعيين ملف مفتاح خاص",
|
||||
"encryption_key_source_content": "الصق محتويات المفتاح الخاص",
|
||||
"stats_params": "ضبط الاحصائيات",
|
||||
"config_successfully_saved": "تم حفظ الاعدادات بنجاح",
|
||||
"interval_6_hour": "ساعات6",
|
||||
"interval_24_hour": "24 ساعة",
|
||||
"interval_days": "{{count}} يوم",
|
||||
"interval_days_plural": "{{count}} الأيام",
|
||||
"domain": "النطاق",
|
||||
"ecs": "ECS",
|
||||
"punycode": "Punycode",
|
||||
"answer": "الإجابة",
|
||||
"filter_added_successfully": "تم إضافة القائمة بنجاح",
|
||||
"filter_removed_successfully": "تم ازالته من القائمة بنجاح",
|
||||
"filter_updated": "تم تحديث القائمة بنجاح",
|
||||
"statistics_configuration": "ضبط الاحصائيات",
|
||||
"statistics_retention": "الاحتفاظ بالإحصاءات",
|
||||
"statistics_retention_desc": "إذا قمت بتقليل قيمة الفاصل الزمني ، فستفقد بعض البيانات",
|
||||
"statistics_clear": "إعادة تعيين الإحصائيات",
|
||||
"statistics_clear_confirm": "هل أنت متأكد من أنك تريد مسح الإحصاءات؟",
|
||||
"statistics_retention_confirm": "هل أنت متأكد أنك تريد تغيير الاحتفاظ بالإحصاءات؟ إذا قمت بتقليل قيمة الفاصل الزمني ، فستفقد بعض البيانات",
|
||||
"statistics_cleared": "تم مسح الإحصائيات بنجاح",
|
||||
"statistics_enable": "تفعيل الاحصائيات",
|
||||
"interval_hours": "{{count}} ساعة",
|
||||
"interval_hours_plural": "{{count}} ساعات",
|
||||
"filters_configuration": "اضبط الفلاتر",
|
||||
"filters_enable": "تفعيل الفلاتر",
|
||||
"filters_interval": "الفاصل الزمني لتحديث الفلاتر",
|
||||
"disabled": "معطلة",
|
||||
"username_label": "اسم المستخدم",
|
||||
"username_placeholder": "ادخل اسم المستخدم",
|
||||
"password_label": "كلمة المرور",
|
||||
"password_placeholder": "ادخل كلمة المرور",
|
||||
"sign_in": "تسجيل الدخول",
|
||||
"sign_out": "تسجيل الخروج",
|
||||
"forgot_password": "نسيت كلمة المرور؟",
|
||||
"forgot_password_desc": "يرجى اتباع <0> هذه الخطوات </0> لإنشاء كلمة مرور جديدة لحساب المستخدم الخاص بك.",
|
||||
"location": "الموقع",
|
||||
"orgname": "اسم المنظمة",
|
||||
"netname": "اسم الشبكة",
|
||||
"network": "الشبكة",
|
||||
"descr": "الوصف",
|
||||
"whois": "WHOIS",
|
||||
"filtering_rules_learn_more": "<0> اعرف المزيد </0> حول إنشاء قوائم المضيفين الخاصة بك.",
|
||||
"blocked_by_response": "حظر بواسطة CNAME or IP in response",
|
||||
"blocked_by_cname_or_ip": "حظر بواسطة CNAME or IP",
|
||||
"try_again": "حاول مرة أخرى",
|
||||
"domain_desc": "أدخل اسم النطاق أو حرف البدل الذي تريد إعادة كتابته.",
|
||||
"example_rewrite_domain": "أعد كتابة الردود لاسم النطاق هذا فقط.",
|
||||
"example_rewrite_wildcard": "أعد كتابة الردود لجميع النطاقات الفرعية <0> example.org </0>.",
|
||||
"rewrite_ip_address": "عنوان IP: استخدم عنوان IP هذا في استجابة A أو AAAA",
|
||||
"rewrite_domain_name": "اسم النطاق: أضف سجل CNAME",
|
||||
"rewrite_A": "<0> A </0>: قيمة خاصة ، احتفظ بسجلات <0> A </0> من upstream",
|
||||
"rewrite_AAAA": "<0> AAAA </0>: قيمة خاصة ، احتفظ بسجلات <0> AAAA </0> من upstream",
|
||||
"disable_ipv6": "قم بتعطيل تحليل عناوين IPv6",
|
||||
"disable_ipv6_desc": "قم بإسقاط جميع استعلامات DNS لعناوين IPv6 (اكتب AAAA).",
|
||||
"fastest_addr": "أسرع عنوان IP",
|
||||
"fastest_addr_desc": "استعلم عن جميع خوادم DNS وأعد عنوان IP الأسرع بين جميع الاستجابات. يؤدي هذا إلى إبطاء استعلامات DNS حيث يتعين على AdGuard Home انتظار الاستجابات من جميع خوادم DNS ، ولكنه يحسن الاتصال الكلي.",
|
||||
"autofix_warning_text": "إذا قمت بالنقر فوق \"إصلاح\" ، فسيقوم AdGuard Home بتهيئة نظامك لاستخدام خادم AdGuard Home DNS.",
|
||||
"autofix_warning_list": "سيقوم بتنفيذ هذه المهام: <0> إلغاء تنشيط نظام DNSStubListener </0> <0> تعيين عنوان خادم DNS إلى 127.0.0.1 </0> <0> استبدال هدف الارتباط الرمزي لـ /etc/resolv.conf بـ / run / systemd /resolve/resolv.conf </0> <0> إيقاف DNSStubListener (إعادة تحميل خدمة حل نظام d) </0>",
|
||||
"autofix_warning_result": "نتيجة لذلك ، ستتم معالجة جميع طلبات DNS من نظامك بواسطة AdGuard Home افتراضيًا.",
|
||||
"tags_title": "وسوم",
|
||||
"tags_desc": "يمكنك تحديد العلامات التي تتوافق مع العميل. قم بتضمين العلامات في قواعد التصفية لتطبيقها بدقة أكبر. <0> معرفة المزيد </0>.",
|
||||
"form_select_tags": "حدد علامات العميل",
|
||||
"check_title": "تحقق من الفلترة",
|
||||
"check_desc": "تحقق مما إذا تم فلترة اسم المضيف.",
|
||||
"check": "تحقق",
|
||||
"form_enter_host": "ادخل اسم المضيف",
|
||||
"filtered_custom_rules": "تمت تصفيتها حسب قواعد التصفية المخصصة",
|
||||
"choose_from_list": "اختر من القائمة",
|
||||
"add_custom_list": "أضف قائمة مخصصة",
|
||||
"host_whitelisted": "المضيف مسموح به",
|
||||
"check_ip": "عناوين الـ IP: {{ip}}",
|
||||
"check_cname": "CNAME: {{cname}}",
|
||||
"check_reason": "سبب: {{reason}}",
|
||||
"check_service": "أسم الخدمة: {{service}}",
|
||||
"service_name": "أسم الخدمة",
|
||||
"check_not_found": "غير موجود في قوائم التصفية الخاصة بك",
|
||||
"client_confirm_block": "هل أنت متأكد من أنك تريد منع العميل \"{{ip}}\"؟",
|
||||
"client_confirm_unblock": "هل تريد بالتأكيد إلغاء حظر العميل \"{{ip}}\"؟",
|
||||
"client_blocked": "تم حظر العميل \"{{ip}}\" بنجاح",
|
||||
"client_unblocked": "تم إلغاء حظر العميل \"{{ip}}\" بنجاح",
|
||||
"static_ip": "عنوان IP ثابت",
|
||||
"static_ip_desc": "AdGuard Home هو خادم لذلك يحتاج إلى عنوان IP ثابت ليعمل بشكل صحيح. خلاف ذلك ، في مرحلة ما ، قد يقوم جهاز التوجيه الخاص بك بتعيين عنوان IP مختلف لهذا الجهاز.",
|
||||
"set_static_ip": "قم بتعيين عنوان IP ثابت",
|
||||
"install_static_ok": "أخبار جيدة! تم ضبط عنوان IP الثابت بالفعل",
|
||||
"install_static_error": "لا يمكن لـ AdGuard Home تكوينه تلقائيًا لواجهة الشبكة هذه. الرجاء البحث عن تعليمات حول كيفية القيام بذلك يدويًا.",
|
||||
"install_static_configure": "اكتشف AdGuard Home استخدام عنوان IP الديناميكي <0> {{ip}} </0>. هل تريد تعيينه كعنوان ثابت؟",
|
||||
"confirm_static_ip": "سيقوم AdGuard Home بتهيئة {{ip}} ليكون عنوان IP الثابت الخاص بك. هل تريد المتابعة؟",
|
||||
"list_updated": "قائمة {{count}} محدثة",
|
||||
"list_updated_plural": "قوائم {{count}} محدثة",
|
||||
"dnssec_enable": "تفعيل DNSSEC",
|
||||
"dnssec_enable_desc": "قم بتعيين علامة DNSSEC في استعلامات DNS الواردة وتحقق من النتيجة (مطلوب محلل يدعم DNSSEC).",
|
||||
"validated_with_dnssec": "تم التحقق من صحتها باستخدام DNSSEC",
|
||||
"all_queries": "كافة الاستفسارات",
|
||||
"show_blocked_responses": "حظر",
|
||||
"show_whitelisted_responses": "القائمة البيضاء",
|
||||
"show_processed_responses": "المعالجة",
|
||||
"blocked_safebrowsing": "محظور بواسطة التصفح الآمن",
|
||||
"blocked_adult_websites": "محظور بواسطة الرقابة الأبوية",
|
||||
"blocked_threats": "التهديدات المحظورة",
|
||||
"allowed": "القائمة البيضاء",
|
||||
"filtered": "تمت الفلترة",
|
||||
"rewritten": "أعيدت كتابته",
|
||||
"safe_search": "البحث الأمن",
|
||||
"blocklist": "قائمة الحظر",
|
||||
"milliseconds_abbreviation": "ms",
|
||||
"cache_size": "حجم ذاكرة التخزين المؤقت",
|
||||
"cache_size_desc": "حجم ذاكرة التخزين المؤقت لنظام أسماء النطاقات (بالبايت).",
|
||||
"cache_ttl_min_override": "تجاوز الحد الأدنى من مدة البقاء TTL",
|
||||
"cache_ttl_max_override": "تجاوز الحد الاقصى من مدة البقاء TTL",
|
||||
"enter_cache_size": "أدخل حجم ذاكرة التخزين المؤقت (بايت)",
|
||||
"enter_cache_ttl_min_override": "أدخل الحد الأدنى من مدة البقاء (بالثواني)",
|
||||
"enter_cache_ttl_max_override": "أدخل الحد الاقصى من مدة البقاء (بالثواني)",
|
||||
"cache_ttl_min_override_desc": "قم بتمديد قيم فترة البقاء القصيرة (بالثواني) المستلمة من الخادم الرئيسي عند تخزين استجابات DNS مؤقتًا.",
|
||||
"cache_ttl_max_override_desc": "قم بتعيين الحد الأقصى لقيمة الوقت للعيش (بالثواني) للإدخالات في ذاكرة التخزين المؤقت لنظام أسماء النطاقات.",
|
||||
"ttl_cache_validation": "يجب أن يكون الحد الأدنى لتجاوز TTL لذاكرة التخزين المؤقت أقل من أو يساوي الحد الأقصى",
|
||||
"cache_optimistic": "متفائل التخزين المؤقت",
|
||||
"cache_optimistic_desc": "اجعل AdGuard Home يستجيب من ذاكرة التخزين المؤقت حتى عندما تنتهي صلاحية الإدخالات وحاول أيضًا تحديثها.",
|
||||
"filter_category_general": "General",
|
||||
"filter_category_security": "الامان",
|
||||
"filter_category_regional": "إقليمي",
|
||||
"filter_category_other": "أخرى",
|
||||
"filter_category_general_desc": "القوائم التي تمنع التتبع والإعلان على معظم الأجهزة",
|
||||
"filter_category_security_desc": "القوائم المصممة خصيصًا لحظر النطاقات الخبيثة والتصيد الاحتيالي والخداع",
|
||||
"filter_category_regional_desc": "القوائم التي تركز على الإعلانات الإقليمية وخوادم التتبع",
|
||||
"filter_category_other_desc": "قوائم حظر أخرى",
|
||||
"setup_config_to_enable_dhcp_server": "أضبط الاعدادات لتمكين خادم DHCP",
|
||||
"original_response": "الرد الأصلي",
|
||||
"click_to_view_queries": "انقر لعرض الـ queries",
|
||||
"port_53_faq_link": "غالبًا ما يتم احتلال المنفذ 53 بواسطة خدمات \"DNSStubListener\" أو \"حل النظام\". يرجى قراءة <0> هذه التعليمات </0> حول كيفية حل هذه المشكلة.",
|
||||
"adg_will_drop_dns_queries": "سيقوم AdGuard Home بإسقاط جميع استعلامات DNS من هذا العميل.",
|
||||
"filter_allowlist": "تحذير: سيؤدي هذا الإجراء أيضًا إلى استبعاد القاعدة \"{{disallowed_rule}}\" من قائمة العملاء المسموح لهم.",
|
||||
"last_rule_in_allowlist": "لا يمكن منع هذا العميل لأن استبعاد القاعدة \"{{disallowed_rule}}\" سيؤدي إلى تعطيل قائمة \"العملاء المسموح لهم\".",
|
||||
"use_saved_key": "استخدم المفتاح المحفوظ مسبقًا",
|
||||
"parental_control": "الرقابة الابويه",
|
||||
"safe_browsing": "تصفح آمن",
|
||||
"served_from_cache": "{{value}} <i>(يتم تقديمه من ذاكرة التخزين المؤقت)</i>",
|
||||
"form_error_password_length": "يجب أن تتكون كلمة المرور من {{value}} من الأحرف على الأقل"
|
||||
}
|
||||
@@ -71,8 +71,8 @@
|
||||
"dhcp_error": "AdGuard Home не можа вызначыць, ці ёсць у сетцы іншы актыўны DHCP-сервер",
|
||||
"dhcp_static_ip_error": "Для таго, каб выкарыстоўваць DHCP-сервер, павінен быць усталяваны статычны IP-адрас. Мы не змаглі вызначыць, ці выкарыстоўвае гэты інтэрфейс сеціва статычны IP-адрас. Калі ласка, усталюйце яго ручна.",
|
||||
"dhcp_dynamic_ip_found": "Ваша сістэма выкарыстоўвае дынамічны IP-адрас для інтэрфейсу <0>{{interfaceName}}</0>. Каб выкарыстоўваць DHCP-сервер трэба ўсталяваць статычны IP-адрас. Ваш бягучы IP-адрас – <0>{{ipAddress}}</0>. Мы аўтаматычна ўсталюем яго як статычны, калі вы націснеце кнопку Ўключыць DHCP.",
|
||||
"dhcp_lease_added": "Статычная арэнда \"{{key}}\" паспяхова дададзена",
|
||||
"dhcp_lease_deleted": "Статычная арэнда \"{{key}}\" паспяхова выдалена",
|
||||
"dhcp_lease_added": "Статычная арэнда «{{key}}» паспяхова дададзена",
|
||||
"dhcp_lease_deleted": "Статычная арэнда «{{key}}» паспяхова выдалена",
|
||||
"dhcp_new_static_lease": "Новая статычная арэнда",
|
||||
"dhcp_static_leases_not_found": "Не знойдзена статычных арэнд DHCP",
|
||||
"dhcp_add_static_lease": "Дадаць статычную арэнду",
|
||||
@@ -82,7 +82,7 @@
|
||||
"dhcp_reset": "Вы ўпэўнены, што хочаце скінуць налады DHCP?",
|
||||
"country": "Краіна",
|
||||
"city": "Горад",
|
||||
"delete_confirm": "Вы ўпэўнены, што хочаце выдаліць \"{{key}}\"?",
|
||||
"delete_confirm": "Вы ўпэўнены, што хочаце выдаліць «{{key}}»?",
|
||||
"form_enter_hostname": "Увядзіце імя хаста",
|
||||
"error_details": "Дэталізацыя памылкі",
|
||||
"response_details": "Дэталі адказу",
|
||||
@@ -115,7 +115,7 @@
|
||||
"dns_query": "DNS-запыты",
|
||||
"blocked_by": "<0>Заблакавана фільтрамі</0>",
|
||||
"stats_malware_phishing": "Заблакаваныя шкодныя і фішынгавыя сайты",
|
||||
"stats_adult": "Заблакаваныя \"дарослыя\" сайты",
|
||||
"stats_adult": "Заблакаваныя «дарослыя» сайты",
|
||||
"stats_query_domain": "Часта запытаныя дамены",
|
||||
"for_last_24_hours": "за 24 гадзіны",
|
||||
"for_last_days": "за апошні {{count}} дзень",
|
||||
@@ -133,13 +133,13 @@
|
||||
"number_of_dns_query_24_hours": "Колькасць DNS-запытаў за 24 гадзіны",
|
||||
"number_of_dns_query_blocked_24_hours": "Колькасць DNS-запытаў, заблакаваных фільтрамі і блок-спісамі",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Колькасць DNS-запытаў, заблакаваных модулем Антыфішынгу AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Колькасць заблакаваных \"сайтаў для дарослых\"",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Колькасць заблакаваных «сайтаў для дарослых»",
|
||||
"enforced_save_search": "Ужыты бяспечны пошук",
|
||||
"number_of_dns_query_to_safe_search": "Колькасць запытаў DNS для пошукавых сістэм, для якіх быў ужыты Бяспечны пошук",
|
||||
"average_processing_time": "Сярэдні час апрацоўкі запыту",
|
||||
"average_processing_time_hint": "Сярэдні час для апрацоўкі запыту DNS у мілісекундах",
|
||||
"block_domain_use_filters_and_hosts": "Блакаваць дамены з выкарыстаннем фільтраў і файлаў хастоў",
|
||||
"filters_block_toggle_hint": "Вы можаце наладзіць правілы блакавання ў <a> \"Фільтрах\"</a>.",
|
||||
"filters_block_toggle_hint": "Вы можаце наладзіць правілы блакавання ў <a> «Фільтрах»</a>.",
|
||||
"use_adguard_browsing_sec": "Выкарыстаць Бяспечную навігацыю AdGuard",
|
||||
"use_adguard_browsing_sec_hint": "AdGuard Home праверыць, ці ўлучаны дамен у ўэб-службу бяспекі браўзара. Ён будзе выкарыстоўваць API, каб выканаць праверку: на сервер адсылаецца толькі кароткі прэфікс імя дамена SHA256.",
|
||||
"use_adguard_parental": "Ужывайце модуль Бацькоўскага кантролю AdGuard ",
|
||||
@@ -221,7 +221,8 @@
|
||||
"all_lists_up_to_date_toast": "Усе спісы ўжо абноўлены",
|
||||
"updated_upstream_dns_toast": "Upstream DNS-серверы абноўлены",
|
||||
"dns_test_ok_toast": "Паказаныя серверы DNS працуюць карэктна",
|
||||
"dns_test_not_ok_toast": "Сервер \"{{key}}\": немагчыма выкарыстоўваць, праверце слушнасць напісання",
|
||||
"dns_test_not_ok_toast": "Сервер «{{key}}»: немагчыма выкарыстоўваць, праверце слушнасць напісання",
|
||||
"dns_test_warning_toast": "Upstream «{{key}}» не адказвае на тэставыя запыты і можа не працаваць належным чынам",
|
||||
"unblock": "Адблакаваць",
|
||||
"block": "Заблакаваць",
|
||||
"disallow_this_client": "Забараніць доступ гэтаму кліенту",
|
||||
@@ -332,15 +333,15 @@
|
||||
"install_devices_router_desc": "Такая наладка аўтаматычна пакрые ўсе прылады, што выкарыстоўваюць ваш хатні роўтар, і вам не трэба будзе наладжваць кожнае з іх у асобнасці.",
|
||||
"install_devices_address": "DNS-сервер AdGuard Home даступны па наступных адрасах",
|
||||
"install_devices_router_list_1": "Адкрыйце налады вашага роўтара. Звычайна вы можаце адкрыць іх у вашым браўзары, напрыклад, http://192.168.0.1/ ці http://192.168.1.1/. Вас могуць папрасіць увесці пароль. Калі вы не помніце яго, пароль часта можна скінуць, націснуўшы на кнопку на самым роўтары. Некаторыя роўтары патрабуюць адмысловага дадатку, які ў гэтым выпадку павінен быць ужо ўсталявана на ваш кампутар ці тэлефон.",
|
||||
"install_devices_router_list_2": "Знайдзіце налады DHCP ці DNS. Знайдзіце літары \"DNS\" поруч з тэкставым полем, у якое можна ўвесці два ці тры шэрагі лічбаў, падзеленых на 4 групы ад адной до трох лічбаў.",
|
||||
"install_devices_router_list_2": "Знайдзіце налады DHCP ці DNS. Знайдзіце літары «DNS» поруч з тэкставым полем, у якое можна ўвесці два ці тры шэрагі лічбаў, падзеленых на 4 групы ад адной до трох лічбаў.",
|
||||
"install_devices_router_list_3": "Увядзіце туды адрас вашага AdGuard Home.",
|
||||
"install_devices_router_list_4": "Вы не можаце ўсталяваць уласны DNS-сервер на некаторых тыпах маршрутызатараў. У гэтым выпадку можа дапамагчы налада AdGuard Home у якасці <a href='#dhcp'>DHCP-сервера</a>. У адваротным выпадку вам трэба звярнуцца да кіраўніцтва па наладзе DNS-сервераў для вашай пэўнай мадэлі маршрутызатара.",
|
||||
"install_devices_windows_list_1": "Адкрыйце Панэль кіравання праз меню \"Пуск\" ці праз пошук Windows.",
|
||||
"install_devices_windows_list_2": "Перайдзіце ў \"Сеціва і інтэрнэт\", а потым у \"Цэнтр кіравання сеціва і агульным доступам\"",
|
||||
"install_devices_windows_list_1": "Адкрыйце Панэль кіравання праз меню «Пуск» ці праз пошук Windows.",
|
||||
"install_devices_windows_list_2": "Перайдзіце ў «Сеціва і інтэрнэт», а потым у «Цэнтр кіравання сеціва і агульным доступам»",
|
||||
"install_devices_windows_list_3": "У левым боку экрана клікніце «Змена параметраў адаптара».",
|
||||
"install_devices_windows_list_4": "Пстрыкніце правай кнопкай мышы ваша актыўнае злучэнне і абярыце Уласцівасці.",
|
||||
"install_devices_windows_list_5": "Знайдзіце ў спісе пункт \"IP версіі 4 (TCP/IPv4)\", вылучыце яго і потым ізноў націсніце \"Уласцівасці\".",
|
||||
"install_devices_windows_list_6": "Абярыце \"Выкарыстаць наступныя адрасы DNS-сервераў\" і ўвядзіце адрас AdGuard Home.",
|
||||
"install_devices_windows_list_5": "Знайдзіце ў спісе пункт «IP версіі 4 (TCP/IPv4)», вылучыце яго і потым ізноў націсніце «Уласцівасці».",
|
||||
"install_devices_windows_list_6": "Абярыце «Выкарыстаць наступныя адрасы DNS-сервераў» і ўвядзіце адрас AdGuard Home.",
|
||||
"install_devices_macos_list_1": "Клікніце па абразку Apple і перайдзіце ў Сістэмныя налады.",
|
||||
"install_devices_macos_list_2": "Клікніце па іконцы Сеціва.",
|
||||
"install_devices_macos_list_3": "Абярыце першае падлучэнне ў спісе і націсніце кнопку «Дадаткова».",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Налады шыфравання захаваны",
|
||||
"encryption_server": "Імя сервера",
|
||||
"encryption_server_enter": "Увядзіце ваша даменавае імя",
|
||||
"encryption_server_desc": "Для выкарыстання HTTPS вам трэба ўвесці імя сервера, якое падыходзіць вашаму SSL-сертыфікату.",
|
||||
"encryption_server_desc": "Калі ўстаноўлена, AdGuard Home вызначае ClientID, адказвае на запыты DDR і выконвае дадатковыя праверкі злучэння. Калі не ўстаноўлена, гэтыя функцыі адключаны. Павінна адпавядаць аднаму з імёнаў DNS у сертыфікаце.",
|
||||
"encryption_redirect": "Аўтаматычна перанакіроўваць на HTTPS",
|
||||
"encryption_redirect_desc": "Калі ўлучана, AdGuard Home будзе аўтаматычна перанакіроўваць вас з HTTP на HTTPS адрас.",
|
||||
"encryption_https": "Порт HTTPS",
|
||||
@@ -429,11 +430,11 @@
|
||||
"form_client_name": "Увядзіце імя кліента",
|
||||
"name": "Назва",
|
||||
"client_global_settings": "Выкарыстаць глабальныя налады",
|
||||
"client_deleted": "Кліент \"{{key}}\" паспяхова выдалены",
|
||||
"client_added": "Кліент \"{{key}}\" паспяхова дададзены",
|
||||
"client_updated": "Кліент \"{{key}}\" паспяхова абноўлены",
|
||||
"client_deleted": "Кліент «{{key}}» паспяхова выдалены",
|
||||
"client_added": "Кліент «{{key}}» паспяхова дададзены",
|
||||
"client_updated": "Кліент «{{key}}» паспяхова абноўлены",
|
||||
"clients_not_found": "Кліентаў не знойдзена",
|
||||
"client_confirm_delete": "Вы ўпэўнены, што хочаце выдаліць кліента \"{{key}}\"?",
|
||||
"client_confirm_delete": "Вы ўпэўнены, што хочаце выдаліць кліента «{{key}}»?",
|
||||
"list_confirm_delete": "Вы ўпэўнены, што хочаце выдаліць гэты спіс?",
|
||||
"auto_clients_title": "Кліенты (runtime)",
|
||||
"auto_clients_desc": "Прылады, якіх няма ў спісе пастаянных кліентаў, якія ўсё яшчэ могуць выкарыстоўваць AdGuard Home",
|
||||
@@ -467,11 +468,11 @@
|
||||
"setup_dns_privacy_other_5": "Вы можаце знайсці яшчэ варыянты <0>тут</0> і <1>тут</1>.",
|
||||
"setup_dns_privacy_ioc_mac": "Канфігурацыя для iOS і macOS",
|
||||
"setup_dns_notice": "Каб выкарыстоўваць <1>DNS-over-HTTPS</1> ці <1>DNS-over-TLS</1>, вам патрэбна <0>наладзіць шыфраванне</0> у наладах AdGuard Home.",
|
||||
"rewrite_added": "Правіла перанакіравання DNS для \"{{key}}\" паспяхова дададзена",
|
||||
"rewrite_deleted": "Правіла перанакіравання DNS для \"{{key}}\" паспяхова выдалена",
|
||||
"rewrite_added": "Правіла перанакіравання DNS для «{{key}}» паспяхова дададзена",
|
||||
"rewrite_deleted": "Правіла перанакіравання DNS для «{{key}}» паспяхова выдалена",
|
||||
"rewrite_add": "Дадаць правіла перанакіравання DNS",
|
||||
"rewrite_not_found": "Не знойдзена правілаў перанакіравання DNS",
|
||||
"rewrite_confirm_delete": "Вы ўпэўнены, што хочаце выдаліць правіла перанакіравання DNS для \"{{key}}\"?",
|
||||
"rewrite_confirm_delete": "Вы ўпэўнены, што хочаце выдаліць правіла перанакіравання DNS для «{{key}}»?",
|
||||
"rewrite_desc": "Дазваляе лёгка наладзіць карыстацкі DNS-адказ для пэўнага дамена.",
|
||||
"rewrite_applied": "Ужыта правіла перанакіравання",
|
||||
"rewrite_hosts_applied": "Перапісана па правіле файла hosts",
|
||||
@@ -552,7 +553,7 @@
|
||||
"disable_ipv6_desc": "Калі гэта опцыя ўлучана, усе DNS-запыты адрасоў IPv6 (тып AAAA) будуць ігнаравацца.",
|
||||
"fastest_addr": "Найхуткі IP-адрас",
|
||||
"fastest_addr_desc": "Апытайце ўсе DNS-серверы і вярніце самы хуткі IP-адрас сярод усіх адказаў. Гэта замарудзіць выкананне DNS-запытаў, бо нам давядзецца чакаць адказаў ад усіх DNS-сервераў, але палепшыць агульную ўзаемасувязь.",
|
||||
"autofix_warning_text": "Пры націску \"Выправіць\" AdGuard Home наладзіць вашу сістэму на выкарыстанне DNS-сервера AdGuard Home.",
|
||||
"autofix_warning_text": "Пры націску «Выправіць» AdGuard Home наладзіць вашу сістэму на выкарыстанне DNS-сервера AdGuard Home.",
|
||||
"autofix_warning_list": "Будуць выконвацца наступныя заданні: <0>Дэактываваць сістэмны DNSStubListener</0> <0>Усталяваць адрас сервера DNS на 127.0.0.1</0> <0>Стварыць сімвалічную спасылку /etc/resolv.conf на /run/systemd/resolve/resolv.conf</0> <0>Спыніць DNSStubListener (перазагрузіць сістэмную службу)</0>.",
|
||||
"autofix_warning_result": "У выніку ўсе DNS-запыты ад вашай сістэмы будуць па змаўчанні апрацоўвацца AdGuard Home.\n",
|
||||
"tags_title": "Тэгі",
|
||||
@@ -572,10 +573,10 @@
|
||||
"check_service": "Назва сэрвісу: {{service}}",
|
||||
"service_name": "Назва сэрвіса",
|
||||
"check_not_found": "Не знойдзена ў вашым спісе фільтраў",
|
||||
"client_confirm_block": "Вы ўпэўнены, што хочаце заблакаваць кліента \"{{ip}}\"?",
|
||||
"client_confirm_unblock": "Вы ўпэўнены, што хочаце адблакаваць кліента \"{{ip}}\"?",
|
||||
"client_blocked": "Кліент \"{{ip}}\" паспяхова заблакаваны",
|
||||
"client_unblocked": "Кліент \"{{ip}}\" паспяхова адблакаваны",
|
||||
"client_confirm_block": "Вы ўпэўнены, што хочаце заблакаваць кліента «{{ip}}»?",
|
||||
"client_confirm_unblock": "Вы ўпэўнены, што хочаце адблакаваць кліента «{{ip}}»?",
|
||||
"client_blocked": "Кліент «{{ip}}» паспяхова заблакаваны",
|
||||
"client_unblocked": "Кліент «{{ip}}» паспяхова адблакаваны",
|
||||
"static_ip": "Статычны IP-адрас",
|
||||
"static_ip_desc": "AdGuard Home з'яўляецца серверам, таму для карэктнай працы яму патрэбен статычны IP-адрас. У адваротным выпадку, у нейкі момант ваш роўтар можа прысвоіць гэтай прыладзе іншы IP-адрас.",
|
||||
"set_static_ip": "Усталяваць статычны IP-адрас",
|
||||
@@ -624,7 +625,7 @@
|
||||
"setup_config_to_enable_dhcp_server": "Наладзіць канфігурацыю для ўключэння DHCP-сервера",
|
||||
"original_response": "Першапачатковы адказ",
|
||||
"click_to_view_queries": "Націсніце, каб прагледзець запыты",
|
||||
"port_53_faq_link": "Порт 53 часта заняты службамі \"DNSStubListener\" ці \"systemd-resolved\". Азнаёмцеся з <0>інструкцыяй</0> пра тое, як гэта дазволіць.",
|
||||
"port_53_faq_link": "Порт 53 часта заняты службамі «DNSStubListener» ці «systemd-resolved». Азнаёмцеся з <0>інструкцыяй</0> пра тое, як гэта дазволіць.",
|
||||
"adg_will_drop_dns_queries": "AdGuard Home скіне ўсе DNS-запыты ад гэтага кліента.",
|
||||
"filter_allowlist": "УВАГА: Гэта дзеянне таксама выключыць правіла «{{disallowed_rule}}» са спіса дазволеных кліентаў.",
|
||||
"last_rule_in_allowlist": "Няможна заблакаваць гэтага кліента, бо вынятак правіла «{{disallowed_rule}}» АДКЛЮЧЫЦЬ рэжым белага спіса.",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Odchozí servery byly úspěšně uloženy",
|
||||
"dns_test_ok_toast": "Specifikované DNS servery pracují správně",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohl být použit, zkontrolujte, zda jste ho správně napsali",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" neodpovídá na testovací požadavky a nemusí fungovat správně",
|
||||
"unblock": "Odblokovat",
|
||||
"block": "Blokovat",
|
||||
"disallow_this_client": "Blokovat tohoto klienta",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Konfigurace šifrování byla uložena",
|
||||
"encryption_server": "Název serveru",
|
||||
"encryption_server_enter": "Zadejte název domény",
|
||||
"encryption_server_desc": "Abyste mohli používat HTTPS, musíte zadat název serveru, který odpovídá vašemu certifikátu SSL nebo zástupnému certifikátu. Pokud není pole nastaveno, bude přijímat připojení TLS pro libovolnou doménu.",
|
||||
"encryption_server_desc": "Pokud je nastaveno, AdGuard Home detekuje ClientID, odpovídá na dotazy DDR a provádí další ověření připojení. Pokud není nastaveno, jsou tyto funkce vypnuty. Musí odpovídat jednomu z názvů DNS v certifikátu.",
|
||||
"encryption_redirect": "Automaticky přesměrovat na HTTPS",
|
||||
"encryption_redirect_desc": "Pokud je zaškrtnuto, AdGuard Home vás automaticky přesměruje z adres HTTP na HTTPS.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"form_error_server_name": "Ugyldigt servernavn",
|
||||
"form_error_subnet": "Undernet \"{{cidr}}\" indeholder ikke IP-adressen \"{{ip}}\"",
|
||||
"form_error_positive": "Skal være større end 0",
|
||||
"form_error_gateway_ip": "Lease kan ikke have gatewayens IP-adresse",
|
||||
"out_of_range_error": "Skal være uden for området \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Skal være mindre end starten på området",
|
||||
"greater_range_start_error": "Skal være større end starten på området",
|
||||
@@ -221,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream-servere er gemt",
|
||||
"dns_test_ok_toast": "Angivne DNS-servere fungerer korrekt",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": Kunne ikke bruges. Tjek, at du har angivet den korrekt",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" svarer ikke på testforespørgsler og fungerer muligvis ikke korrekt",
|
||||
"unblock": "Afblokering",
|
||||
"block": "Blokering",
|
||||
"disallow_this_client": "Afvis denne klient",
|
||||
@@ -362,7 +364,7 @@
|
||||
"encryption_config_saved": "Krypteringsopsætning gemt",
|
||||
"encryption_server": "Servernavn",
|
||||
"encryption_server_enter": "Angiv dit domænenavn",
|
||||
"encryption_server_desc": "For at kunne bruge HTTPS skal du angive det servernavn, der matcher dit SSL-certifikat eller wildcard-certifikat. Er feltet ikke er opsat, accepterer det TLS-forbindelser til ethvert domæne.",
|
||||
"encryption_server_desc": "Hvis indstillet, registrerer AdGuard Home ClientID'er, svarer på DDR-forespørgsler og udfører yderligere forbindelsesvalideringer. Hvis ikke er indstillet, er disse funktioner deaktiveret. Skal matche et af DNS-navnene i certifikatet.",
|
||||
"encryption_redirect": "Omdirigér automatisk til HTTPS",
|
||||
"encryption_redirect_desc": "Hvis afkrydset, omdirigerer AdGuard Home dig automatisk fra HTTP- til HTTPS-adresser.",
|
||||
"encryption_https": "HTTPS-port",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream-Server erfolgreich gespeichert",
|
||||
"dns_test_ok_toast": "Angegebene DNS-Server arbeiten ordnungsgemäß",
|
||||
"dns_test_not_ok_toast": "Server „{{key}}“: konnte nicht verwendet werden, bitte überprüfen Sie die korrekte Schreibweise",
|
||||
"dns_test_warning_toast": "Upstream „{{key}}“ reagiert nicht auf Testanfragen und funktioniert möglicherweise nicht fehlerfrei",
|
||||
"unblock": "Entsperren",
|
||||
"block": "Sperren",
|
||||
"disallow_this_client": "Diesen Client sperren",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Verschlüsselungskonfiguration gespeichert",
|
||||
"encryption_server": "Servername",
|
||||
"encryption_server_enter": "Domain-Namen eingeben",
|
||||
"encryption_server_desc": "Um HTTPS verwenden zu können, müssen Sie den Servernamen eingeben, der zu Ihrem SSL-Zertifikat passt.",
|
||||
"encryption_server_desc": "Wenn diese Option aktiviert ist, erkennt AdGuard Home ClientIDs, antwortet auf DDR-Anfragen und führt zusätzliche Verbindungsüberprüfungen durch. Wenn sie nicht gesetzt ist, sind diese Funktionen deaktiviert. Muss mit einem der DNS-Namen im Zertifikat übereinstimmen.",
|
||||
"encryption_redirect": "Automatisch auf HTTPS umleiten",
|
||||
"encryption_redirect_desc": "Wenn aktiviert, leitet AdGuard Home Sie automatisch von HTTP- auf HTTPS-Adressen um.",
|
||||
"encryption_https": "HTTPS-Port",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream servers successfully saved",
|
||||
"dns_test_ok_toast": "Specified DNS servers are working correctly",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": could not be used, please check that you've written it correctly",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" does not respond to test requests and may not work properly",
|
||||
"unblock": "Unblock",
|
||||
"block": "Block",
|
||||
"disallow_this_client": "Disallow this client",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Encryption configuration saved",
|
||||
"encryption_server": "Server name",
|
||||
"encryption_server_enter": "Enter your domain name",
|
||||
"encryption_server_desc": "In order to use HTTPS, you need to enter the server name that matches your SSL certificate or wildcard certificate. If the field is not set, it will accept TLS connections for any domain.",
|
||||
"encryption_server_desc": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.",
|
||||
"encryption_redirect": "Redirect to HTTPS automatically",
|
||||
"encryption_redirect_desc": "If checked, AdGuard Home will automatically redirect you from HTTP to HTTPS addresses.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"form_error_server_name": "Nombre de servidor no válido",
|
||||
"form_error_subnet": "La subred \"{{cidr}}\" no contiene la dirección IP \"{{ip}}\"",
|
||||
"form_error_positive": "Debe ser mayor que 0",
|
||||
"form_error_gateway_ip": "Asignación no puede tener la dirección IP de la puerta de enlace",
|
||||
"form_error_gateway_ip": "La asignación no puede tener la dirección IP de la puerta de enlace",
|
||||
"out_of_range_error": "Debe estar fuera del rango \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Debe ser inferior que el inicio de rango",
|
||||
"greater_range_start_error": "Debe ser mayor que el inicio de rango",
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Servidores DNS de subida guardados correctamente",
|
||||
"dns_test_ok_toast": "Los servidores DNS especificados funcionan correctamente",
|
||||
"dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revisa si lo has escrito correctamente",
|
||||
"dns_test_warning_toast": "DNS de subida \"{{key}}\" no responde a las peticiones de prueba y es posible que no funcione correctamente",
|
||||
"unblock": "Desbloquear",
|
||||
"block": "Bloquear",
|
||||
"disallow_this_client": "No permitir a este cliente",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Configuración de cifrado guardado",
|
||||
"encryption_server": "Nombre del servidor",
|
||||
"encryption_server_enter": "Ingresa el nombre del dominio",
|
||||
"encryption_server_desc": "Para utilizar HTTPS, debes ingresar el nombre del servidor que coincida con tu certificado SSL o certificado comodín. Si el campo no está establecido, el servidor aceptará conexiones TLS para cualquier dominio.",
|
||||
"encryption_server_desc": "Si se configura, AdGuard Home detecta los ID de clientes, responde a las consultas DDR y realiza validaciones de conexión adicionales. Si no se configura, estas funciones se deshabilitarán. Debe coincidir con uno de los nombres DNS del certificado.",
|
||||
"encryption_redirect": "Redireccionar a HTTPS automáticamente",
|
||||
"encryption_redirect_desc": "Si está marcado, AdGuard Home redireccionará automáticamente de HTTP a las direcciones HTTPS.",
|
||||
"encryption_https": "Puerto HTTPS",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"form_error_ip6_format": "Virheellinen IPv6-osoite",
|
||||
"form_error_ip_format": "Virheellinen IP-osoite",
|
||||
"form_error_mac_format": "Virheellinen MAC-osoite",
|
||||
"form_error_client_id_format": "Päätelaitteen ID voi sisältää ainoastaan numeroita, pieniä kirjaimia sekä yhdysviivoja",
|
||||
"form_error_client_id_format": "ClientID-tunniste voi sisältää ainoastaan numeroita, pieniä kirjaimia sekä yhdysviivoja",
|
||||
"form_error_server_name": "Virheellinen palvelimen nimi",
|
||||
"form_error_subnet": "Aliverkko \"{{cidr}}\" ei sisällä IP-osoitetta \"{{ip}}\"",
|
||||
"form_error_positive": "Oltava suurempi kuin 0",
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Ylävirtojen palvelimet tallennettiin",
|
||||
"dns_test_ok_toast": "Määritetyt DNS-palvelimet toimivat oikein",
|
||||
"dns_test_not_ok_toast": "Palvelin \"{{key}}\": ei voitu käyttää, tarkista sen oikeinkirjoitus",
|
||||
"dns_test_warning_toast": "Datavuon \"{{key}}\" ei vastaa testipyyntöihin eikä välttämättä toimi kunnolla",
|
||||
"unblock": "Salli",
|
||||
"block": "Estä",
|
||||
"disallow_this_client": "Estä tämä päätelaite",
|
||||
@@ -278,9 +279,9 @@
|
||||
"dns_over_https": "DNS-over-HTTPS",
|
||||
"dns_over_tls": "DNS-over-TLS",
|
||||
"dns_over_quic": "DNS-over-QUIC",
|
||||
"client_id": "Päätelaitteen ID",
|
||||
"client_id_placeholder": "Syötä päätelaitteen ID",
|
||||
"client_id_desc": "Päätelaitteet voidaan tunnistaa erityisillä ID-tunnisteilla. Lue lisää päätelaitteiden tunnistuksesta <a>täältä</a>.",
|
||||
"client_id": "ClientID",
|
||||
"client_id_placeholder": "Syötä ClientID",
|
||||
"client_id_desc": "Päätelaitteet voidaan tunnistaa erityisillä ClientID-tunnisteilla. Lue lisää päätelaitteiden tunnistuksesta <a>täältä</a>.",
|
||||
"download_mobileconfig_doh": "Lataa .mobileconfig-tiedosto DNS-over-HTTPS -käytölle",
|
||||
"download_mobileconfig_dot": "Lataa .mobileconfig-tiedosto DNS-over-TLS -käytölle",
|
||||
"download_mobileconfig": "Lataa asetustiedosto",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Salausasetukset tallennettiin",
|
||||
"encryption_server": "Palvelimen nimi",
|
||||
"encryption_server_enter": "Syötä verkkotunnuksesi",
|
||||
"encryption_server_desc": "HTTPS-yhteyden käyttöä varten, on syötettävä SSL- tai jokerivarmennetta vastaava palvelimen nimi. Jos kenttä on tyhjä, sallitaan kaikkien verkkotunnusten TLS-yhteydet.",
|
||||
"encryption_server_desc": "Jos määritetty, AdGuard Home tunnistaa ClientID-tunnisteet, vastaa DDR-kyselyihin ja suorittaa yhteyden lisätarkistuksia. Jos ei määritetty, nämä ominaisuudet eivät ole käytössä. On vastattava yhtä varmenteen DNS-nimistä.",
|
||||
"encryption_redirect": "Automaattinen HTTPS-ohjaus",
|
||||
"encryption_redirect_desc": "Jos käytössä, AdGuard Home ohjaa HTTP-osoitteet automaattisesti HTTPS-osoitteisiin.",
|
||||
"encryption_https": "HTTPS-portti",
|
||||
@@ -420,7 +421,7 @@
|
||||
"client_edit": "Muokkaa päätelaitetta",
|
||||
"client_identifier": "Tunniste",
|
||||
"ip_address": "IP-osoite",
|
||||
"client_identifier_desc": "Päätelaitteet voidaan tunnistaa IP- tai MAC-osoitteista, CIDR-merkinnöistä tai erityisistä päätelaite ID -tunnisteista (voidaan käyttää DoT/DoH/DoQ yhteydessä). Lue lisää päätelaitteiden tunnistuksesta <0>täältä</0>.",
|
||||
"client_identifier_desc": "Päätelaitteet voidaan tunnistaa IP- tai MAC-osoitteista, CIDR-merkinnöistä tai erityisistä ClientID-tunnisteista (voidaan käyttää DoT/DoH/DoQ yhteydessä). Lue lisää päätelaitteiden tunnistuksesta <0>täältä</0>.",
|
||||
"form_enter_ip": "Syötä IP-osoite",
|
||||
"form_enter_subnet_ip": "Syötä aliverkossa \"{{cidr}}\" oleva IP-osoite",
|
||||
"form_enter_mac": "Syötä MAC-osoite",
|
||||
@@ -440,9 +441,9 @@
|
||||
"access_title": "Käytön asetukset",
|
||||
"access_desc": "Tässä voidaan määrittää AdGuard Homen DNS-palvelimen käyttöoikeussääntöjä.",
|
||||
"access_allowed_title": "Sallitut päätelaitteet",
|
||||
"access_allowed_desc": "Lista CIDR-merkinnöistä, IP-osoitteista tai <a>päätelaite ID</a> -tunnisteista. Jos listalla on kohteita, hyväksyy AdGuard Home pyyntöjä vain näiltä päätelaitteilta.",
|
||||
"access_allowed_desc": "Lista CIDR-merkinnöistä, IP-osoitteista tai <a>ClientID</a>-tunnisteista. Jos listalla on kohteita, hyväksyy AdGuard Home pyyntöjä vain näiltä päätelaitteilta.",
|
||||
"access_disallowed_title": "Kielletyt päätelaitteet",
|
||||
"access_disallowed_desc": "Lista CIDR-merkinnöistä, IP-osoitteista tai <a>päätelaite ID</a> -tunnisteista. Jos listalla on kohteita, hylkää AdGuard Home näiden päätelaitteiden pyynnöt. Tätä kenttää ei huomioida, jos sallittuja päätelaitteita on määritetty.",
|
||||
"access_disallowed_desc": "Lista CIDR-merkinnöistä, IP-osoitteista tai <a>ClientID</a>-tunnisteista. Jos listalla on kohteita, hylkää AdGuard Home näiden päätelaitteiden pyynnöt. Tätä kenttää ei huomioida, jos sallittuja päätelaitteita on määritetty.",
|
||||
"access_blocked_title": "Kielletyt verkkotunnukset",
|
||||
"access_blocked_desc": "Ei pidä sekoittaa suodattimiin. AdGuard Home hylkää näiden verkkotunnusten DNS-pyynnöt, eivätkä nämä pyynnöt näy edes pyyntöhistoriassa. Tähän voidaan syöttää tarkkoja verkkotunnuksia, jokerimerkkejä tai URL-suodatussääntöjä, kuten \"example.org\", \"*.example.org\" tai \"||example.org^\".",
|
||||
"access_settings_saved": "Käytön asetukset tallennettiin",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Serveurs en amont enregistrés",
|
||||
"dns_test_ok_toast": "Les serveurs DNS spécifiés fonctionnent correctement",
|
||||
"dns_test_not_ok_toast": "Impossible d'utiliser le serveur « {{key}} »: veuillez vérifier si le nom saisi est bien correct",
|
||||
"dns_test_warning_toast": "L'amont « {{key}} » ne répond pas aux demandes de test et peut ne pas fonctionner correctement.",
|
||||
"unblock": "Débloquer",
|
||||
"block": "Bloquer",
|
||||
"disallow_this_client": "Interdire ce client",
|
||||
@@ -337,7 +338,7 @@
|
||||
"install_devices_router_list_4": "Vous ne pouvez pas définir un serveur DNS personnalisé sur certains types de routeurs. Dans ce cas, la configuration de AdGuard Home en tant que <0>serveur DHCP</0> peut aider. Sinon, vous devez rechercher le manuel sur la façon de personnaliser les serveurs DNS pour votre modèle de routeur particulier.",
|
||||
"install_devices_windows_list_1": "Ouvrez votre Panneau de configuration depuis le menu Démarrer ou la recherche Windows.",
|
||||
"install_devices_windows_list_2": "Allez dans la catégorie Réseau et Internet et ensuite dans le Centre Réseau et Partage.",
|
||||
"install_devices_windows_list_3": "Dans le panneau de gauche, cliquez sur \"Modifier les paramètres de l'adaptateur\".",
|
||||
"install_devices_windows_list_3": "Dans le panneau de gauche, cliquez sur « Modifier les paramètres de l'adaptateur ».",
|
||||
"install_devices_windows_list_4": "Cliquez avec le bouton droit de la souris sur votre connexion active et sélectionnez Propriétés.",
|
||||
"install_devices_windows_list_5": "Recherchez « Protocole Internet Version 4 (TCP/IPv4) » (soit, pour IPv6, « Protocole Internet Version 6 (TCP/IPv6) ») dans la liste, sélectionnez-la puis cliquez à nouveau sur Propriétés.",
|
||||
"install_devices_windows_list_6": "Sélectionnez « Utiliser l’adresse de serveur DNS suivante » et saisissez votre adresse de serveur AdGuard Home.",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Configuration de chiffrement enregistrée",
|
||||
"encryption_server": "Nom du serveur",
|
||||
"encryption_server_enter": "Entrez votre nom de domaine",
|
||||
"encryption_server_desc": "Pour utiliser HTTPS, vous devez saisir le nom du serveur qui correspond à votre certificat SSL ou wildcard. Si le champ n'est pas configuré, les connexions TLS pour tous les domaines seront acceptées.",
|
||||
"encryption_server_desc": "Si cette option est définie, AdGuard Home détecte les ClientID, répond aux requêtes DDR et effectue des validations de connexion supplémentaires. Si elle n'est pas définie, ces fonctions sont désactivées. Doit correspondre à l'un des noms DNS du certificat.",
|
||||
"encryption_redirect": "Redirection automatiquement vers HTTPS",
|
||||
"encryption_redirect_desc": "Si coché, AdGuard Home vous redirigera automatiquement d'adresses HTTP vers HTTPS.",
|
||||
"encryption_https": "Port HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Uzvodni poslužitelji uspješno su spremljeni",
|
||||
"dns_test_ok_toast": "Odabrani DNS poslužitelji su trenutno aktivni",
|
||||
"dns_test_not_ok_toast": "\"{{key}}\" poslužitelja: ne može se upotrijebiti, provjerite jeste li to ispravno napisali",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" ne odgovara na zahtjeve za testiranje i možda neće raditi ispravno",
|
||||
"unblock": "Odblokiraj",
|
||||
"block": "Blokiraj",
|
||||
"disallow_this_client": "Onemogući ovog klijenta",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Konfiguracija šifriranja spremljena",
|
||||
"encryption_server": "Naziv poslužitelja",
|
||||
"encryption_server_enter": "Unesite naziv domene",
|
||||
"encryption_server_desc": "Da biste koristili HTTPS, morate unijeti ime poslužitelja koje odgovara vašem SSL certifikatu ili wildcard certifikatu. Ako polje nije postavljeno, prihvatit će TLS veze za bilo koju domenu.",
|
||||
"encryption_server_desc": "Ako je postavljeno, AdGuard Home otkriva ClientID-ove, odgovara na DDR upite i provodi dodatne provjere valjanosti veze. Ako nije postavljeno, ove značajke su onemogućene. Mora odgovarati jednom od DNS naziva u certifikatu.",
|
||||
"encryption_redirect": "Automatski preusmjeri na HTTPS",
|
||||
"encryption_redirect_desc": "Ako je omogućeno, AdGuard Home će vas automatski preusmjeravati s HTTP na HTTPS adrese.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream szerverek sikeresen mentve",
|
||||
"dns_test_ok_toast": "A megadott DNS-kiszolgálók megfelelően működnek",
|
||||
"dns_test_not_ok_toast": "Szerver \"{{key}}\": nem használható, ellenőrizze, hogy helyesen írta-e be",
|
||||
"dns_test_warning_toast": "A \"{{key}}\" feltöltés nem válaszol a tesztkérelmekre, és lehet, hogy nem működik megfelelően",
|
||||
"unblock": "Feloldás",
|
||||
"block": "Blokkolás",
|
||||
"disallow_this_client": "Tiltás ennek a kliensnek",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Titkosítási beállítások mentve",
|
||||
"encryption_server": "Szerver neve",
|
||||
"encryption_server_enter": "Adja meg az Ön domain címét",
|
||||
"encryption_server_desc": "A HTTPS használatához meg kell adnia a szerver nevét, amely megegyezik az SSL tanúsítvánnyal vagy a helyettesítő tanúsítvánnyal. Ha a mező nincs beállítva, akkor bármely tartományhoz elfogadja a TLS kapcsolatokat.",
|
||||
"encryption_server_desc": "Ha be van állítva, az AdGuard Home észleli az ClientID-ket, válaszol a DDR-lekérdezésekre, és további kapcsolatellenőrzéseket végez. Ha nincs beállítva, ezek a funkciók le vannak tiltva. Meg kell egyeznie a tanúsítványban szereplő DNS-nevek egyikével.",
|
||||
"encryption_redirect": "Automatikus átirányítás HTTPS kapcsolatra",
|
||||
"encryption_redirect_desc": "Ha be van jelölve, az AdGuard Home automatikusan átirányítja a HTTP kapcsolatokat a biztonságos HTTPS protokollra.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"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",
|
||||
"form_error_gateway_ip": "Sewa tidak dapat memiliki alamat IP gateway",
|
||||
"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",
|
||||
@@ -221,6 +222,7 @@
|
||||
"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",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" tidak menanggapi permintaan pengujian dan mungkin tidak berfungsi dengan baik",
|
||||
"unblock": "Buka Blokir",
|
||||
"block": "Blok",
|
||||
"disallow_this_client": "Cabut ijin untuk klien ini",
|
||||
@@ -362,7 +364,7 @@
|
||||
"encryption_config_saved": "Pengaturan enkripsi telah tersimpan",
|
||||
"encryption_server": "Nama server",
|
||||
"encryption_server_enter": "Masukkan nama domain anda",
|
||||
"encryption_server_desc": "Untuk menggunakan HTTPS, Anda harus memasukkan nama server yang cocok dengan sertifikat SSL Anda. Bila ruas tak ditata, akan menerima koneksi TLS bagi domain manapun.",
|
||||
"encryption_server_desc": "Jika disetel, AdGuard Home mendeteksi ClientID, merespons kueri DDR, dan melakukan validasi koneksi tambahan. Jika tidak disetel, fitur-fitur ini dinonaktifkan. Harus cocok dengan salah satu Nama DNS dalam sertifikat.",
|
||||
"encryption_redirect": "Alihkan ke HTTPS secara otomatis",
|
||||
"encryption_redirect_desc": "Jika dicentang, AdGuard Home akan secara otomatis mengarahkan anda dari HTTP ke alamat HTTPS.",
|
||||
"encryption_https": "Port HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "I server upstream sono stati salvati correttamente",
|
||||
"dns_test_ok_toast": "I server DNS specificati funzionano correttamente",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": non può essere utilizzato, assicurati di averlo digitato correttamente",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" non risponde alle richieste di test e potrebbe non funzionare correttamente",
|
||||
"unblock": "Sblocca",
|
||||
"block": "Blocca",
|
||||
"disallow_this_client": "Blocca questo client",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Configurazione crittografia salvata",
|
||||
"encryption_server": "Nome server",
|
||||
"encryption_server_enter": "Inserisci il tuo nome di dominio",
|
||||
"encryption_server_desc": "Per utilizzare HTTPS, è necessario immettere il nome del server che corrisponde al certificato SSL o al certificato wildcard. Se il campo risulterà vuoto, accetterà connessioni TLS per qualsiasi dominio.",
|
||||
"encryption_server_desc": "Se impostato, AdGuard Home rileva i ClientID, risponde alle query DDR ed esegue ulteriori convalide della connessione. Se non sono impostate, queste funzioni sono disabilitate. Deve corrispondere a uno dei nomi DNS nel certificato.",
|
||||
"encryption_redirect": "Reindirizza automaticamente a HTTPS",
|
||||
"encryption_redirect_desc": "Se selezionato, AdGuard Home ti reindirizzerà automaticamente da indirizzi HTTP a HTTPS.",
|
||||
"encryption_https": "Porta HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "上流DNSサーバを保存しました。",
|
||||
"dns_test_ok_toast": "指定されたDNSサーバは正しく動作しています",
|
||||
"dns_test_not_ok_toast": "サーバ \"{{key}}\": 使用できませんでした。正しく入力されているかどうかを確認してください",
|
||||
"dns_test_warning_toast": "アップストリーム\"{{key}}\"はテストリクエストに応答せず、正しく動作しない可能性があります。",
|
||||
"unblock": "ブロック解除",
|
||||
"block": "ブロック",
|
||||
"disallow_this_client": "このクライアントを拒否する",
|
||||
@@ -361,9 +362,9 @@
|
||||
"encryption_title": "暗号化",
|
||||
"encryption_desc": "DNSと管理者ウェブインターフェースの両方に対する暗号化(HTTPS/QUIC/TLS)サポート。",
|
||||
"encryption_config_saved": "暗号化構成が保存されました。",
|
||||
"encryption_server": "サーバ名",
|
||||
"encryption_server": "サーバー名",
|
||||
"encryption_server_enter": "ドメイン名を入力してください",
|
||||
"encryption_server_desc": "HTTPSを使用するには、SSL証明書またはワイルドカード証明書と一致するサーバー名を入力する必要があります。このフィールドが設定されていない場合は、任意のドメインのTLS接続を受け入れます。",
|
||||
"encryption_server_desc": "こちらでサーバー名を設定すると、AdGuard HomeはClientIDを検出し、DDRクエリに応答し、追加の接続検証を実行します。設定されていない場合、これらの機能は無効になります。※証明書のDNS名のいずれかに一致する必要があります。",
|
||||
"encryption_redirect": "HTTPSに自動的にリダイレクト",
|
||||
"encryption_redirect_desc": "チェックすると、AdGuard Homeは自動的にHTTPからHTTPSアドレスへリダイレクトします。",
|
||||
"encryption_https": "HTTPS ポート",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "업스트림 서버가 성공적으로 저장되었습니다",
|
||||
"dns_test_ok_toast": "특정 DNS 서버들은 정상적으로 동작 중입니다",
|
||||
"dns_test_not_ok_toast": "서버 \"{{key}}\": 사용할 수 없습니다, 제대로 작성했는지 확인하세요.",
|
||||
"dns_test_warning_toast": "업스트림 '{{key}}'이(가) 테스트 요청에 응답하지 않으며 제대로 작동하지 않을 수 있습니다",
|
||||
"unblock": "차단 해제",
|
||||
"block": "차단",
|
||||
"disallow_this_client": "클라이언트 거부",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "암호화 구성이 저장되었습니다",
|
||||
"encryption_server": "서버 이름",
|
||||
"encryption_server_enter": "도메인 이름을 입력하세요.",
|
||||
"encryption_server_desc": "HTTPS를 사용하려면 SSL 인증서와 일치하는 서버 이름을 입력해야 합니다.",
|
||||
"encryption_server_desc": "설정된 경우 AdGuard Home은 ClientID를 감지하고 DDR 쿼리에 응답하고 추가 연결 유효성 검사를 수행합니다. 설정하지 않으면 이러한 기능이 비활성화됩니다. 인증서의 DNS 이름 중 하나와 일치해야 합니다.",
|
||||
"encryption_redirect": "HTTPS로 자동 리디렉션",
|
||||
"encryption_redirect_desc": "상자를 체크하면 AdGuard Home 자동으로 사용자를 HTTP에서 HTTPS 주소로 리디렉션합니다.",
|
||||
"encryption_https": "HTTP 포트",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream-servers succesvol opgeslagen",
|
||||
"dns_test_ok_toast": "Opgegeven DNS-servers werken correct",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": kon niet worden gebruikt, controleer of je het correct hebt geschreven",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" reageert niet op testverzoeken en werkt mogelijk niet goed",
|
||||
"unblock": "Deblokkeren",
|
||||
"block": "Blokkeren",
|
||||
"disallow_this_client": "Toepassing/systeem niet toelaten",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Versleuteling configuratie opgeslagen",
|
||||
"encryption_server": "Server naam",
|
||||
"encryption_server_enter": "Voer domein naam in",
|
||||
"encryption_server_desc": "Om HTTPS te gebruiken, moet je de servernaam invoeren die overeenkomt met je SSL-certificaat of jokerteken-certificaat. Als het veld niet is ingesteld, accepteert het TLS-verbindingen voor elk domein.",
|
||||
"encryption_server_desc": "Indien ingesteld, detecteert AdGuard Home Client-ID's, reageert op DDR-zoekopdrachten en voert aanvullende verbindingsvalidaties uit. Indien niet ingesteld, zijn deze functies uitgeschakeld. Moet overeenkomen met een van de DNS-namen in het certificaat.",
|
||||
"encryption_redirect": "Herleid automatisch naar HTTPS",
|
||||
"encryption_redirect_desc": "Indien ingeschakeld, zal AdGuard Home je automatisch herleiden van HTTP naar HTTPS.",
|
||||
"encryption_https": "HTTPS poort",
|
||||
|
||||
@@ -347,7 +347,7 @@
|
||||
"encryption_config_saved": "Krypteringsoppsettet ble lagret",
|
||||
"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_server_desc": "Hvis angitt, oppdager AdGuard Home klient-IDer, svarer på DDR-spørringer og utfører ytterligere tilkoblingsvalideringer. Hvis ikke angitt, er disse funksjonene deaktivert. Må samsvare med ett av DNS-navnene i sertifikatet.",
|
||||
"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",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Serwery nadrzędne zostały pomyślnie zapisane",
|
||||
"dns_test_ok_toast": "Określone serwery DNS działają poprawnie",
|
||||
"dns_test_not_ok_toast": "Serwer \"{{key}}\": nie można go użyć, sprawdź, czy napisałeś go poprawnie",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" nie odpowiada na zapytania testowe i może nie działać prawidłowo",
|
||||
"unblock": "Odblokuj",
|
||||
"block": "Zablokuj",
|
||||
"disallow_this_client": "Odrzuć tego klienta",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Konfiguracja szyfrowania została zapisana",
|
||||
"encryption_server": "Nazwa serwera",
|
||||
"encryption_server_enter": "Wpisz swoją nazwę domeny",
|
||||
"encryption_server_desc": "Aby korzystać z protokołu HTTPS, musisz wprowadzić nazwę serwera, która jest zgodna z certyfikatem SSL lub certyfikatem typu wildcard. Jeśli pole nie jest ustawione, będzie akceptować połączenia TLS dla dowolnej domeny.",
|
||||
"encryption_server_desc": "Jeśli jest ustawiony, AdGuard Home wykrywa ClientID, odpowiada na zapytania DDR i wykonuje dodatkowe walidacje połączeń. Jeśli nie jest ustawiony, funkcje te są wyłączone. Musi odpowiadać jednej z nazw DNS w certyfikacie.",
|
||||
"encryption_redirect": "Przekieruj automatycznie do HTTPS",
|
||||
"encryption_redirect_desc": "Jeśli zaznaczone, AdGuard Home automatycznie przekieruje Cię z adresów HTTP na HTTPS.",
|
||||
"encryption_https": "Port HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Servidores DNS primário salvos com sucesso",
|
||||
"dns_test_ok_toast": "Os servidores DNS especificados estão funcionando corretamente",
|
||||
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se você escreveu corretamente",
|
||||
"dns_test_warning_toast": "Servidor DNS primário \"{{key}}\" não responde aos Solicitações de teste e pode não funcionar corretamente",
|
||||
"unblock": "Desbloquear",
|
||||
"block": "Bloquear",
|
||||
"disallow_this_client": "Não permitir este cliente",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Configuração de criptografia salva",
|
||||
"encryption_server": "Nome do servidor",
|
||||
"encryption_server_enter": "Digite seu nome de domínio",
|
||||
"encryption_server_desc": "Para usar HTTPS, você precisa inserir o nome do servidor que corresponda ao seu certificado SSL ou certificado curinga. Se o campo não estiver definido, ele aceitará conexões TLS para qualquer domínio.",
|
||||
"encryption_server_desc": "Se definido, AdGuard Home detecta ClientIDs, responde a consultas DDR, e executa validações de ligações adicionais. Se não estiver definido, estas características são desactivadas. Devem corresponder a um dos Nomes DNS no certificado.",
|
||||
"encryption_redirect": "Redirecionar automaticamente para HTTPS",
|
||||
"encryption_redirect_desc": "Se marcado, o AdGuard Home irá redirecionar automaticamente os endereços HTTP para HTTPS.",
|
||||
"encryption_https": "Porta HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Servidores DNS primário guardados com sucesso",
|
||||
"dns_test_ok_toast": "Os servidores DNS especificados estão a funcionar corretamente",
|
||||
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se o escreveu corretamente",
|
||||
"dns_test_warning_toast": "Servidor DNS primário \"{{key}}\" não responde aos solicitações de teste e pode não funcionar corretamente",
|
||||
"unblock": "Desbloquear",
|
||||
"block": "Bloquear",
|
||||
"disallow_this_client": "Não permitir este cliente",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Definição de criptografia guardada",
|
||||
"encryption_server": "Nome do servidor",
|
||||
"encryption_server_enter": "Insira o seu nome de domínio",
|
||||
"encryption_server_desc": "Para usar HTTPS, você precisa inserir o nome do servidor que corresponda ao seu certificado SSL ou certificado curinga. Se o campo não estiver definido, ele aceitará conexões TLS para qualquer domínio.",
|
||||
"encryption_server_desc": "Se definido, AdGuard Home detecta ClientIDs, responde a consultas DDR, e executa validações de ligações adicionais. Se não estiver definido, estas características são desactivadas. Devem corresponder a um dos Nomes DNS no certificado.",
|
||||
"encryption_redirect": "Redirecionar automaticamente para HTTPS",
|
||||
"encryption_redirect_desc": "Se marcado, o AdGuard Home irá redirecionar automaticamente os endereços HTTP para HTTPS.",
|
||||
"encryption_https": "Porta HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Serverele din amonte au fost salvate cu succes",
|
||||
"dns_test_ok_toast": "Serverele DNS specificate funcționează corect",
|
||||
"dns_test_not_ok_toast": "Serverul \"{{key}}\": nu a putut fi utilizat, verificați dacă l-ați scris corect",
|
||||
"dns_test_warning_toast": "„{{key}}” în amonte nu răspunde la solicitările de testare și s-ar putea să nu funcționeze corect",
|
||||
"unblock": "Deblocați",
|
||||
"block": "Blocați",
|
||||
"disallow_this_client": "Nu permiteți acest client",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Configurația de criptare salvată",
|
||||
"encryption_server": "Nume de server",
|
||||
"encryption_server_enter": "Introduceți numele domeniului",
|
||||
"encryption_server_desc": "Pentru a utiliza HTTPS, trebuie să introduceți numele serverului care se potrivește cu certificatul SSL sau certificatul wildcard al dvs. În cazul în care câmpul nu este setat, va accepta conexiuni TLS pentru orice domeniu.",
|
||||
"encryption_server_desc": "Dacă este setat, AdGuard Home detectează ID-urile de client, răspunde la interogările DDR și efectuează validări suplimentare ale conexiunii. Dacă nu este setat, aceste caracteristici sunt dezactivate. Trebuie să corespundă cu unul dintre numele DNS din certificat.",
|
||||
"encryption_redirect": "Redirecționați automat la HTTPS",
|
||||
"encryption_redirect_desc": "Dacă este bifat, AdGuard Home vă va redirecționa automat de la adrese HTTP la HTTPS.",
|
||||
"encryption_https": "Port HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "DNS-серверы успешно обновлены",
|
||||
"dns_test_ok_toast": "Указанные серверы DNS работают корректно",
|
||||
"dns_test_not_ok_toast": "Сервер «{{key}}»: невозможно использовать, проверьте правильность написания",
|
||||
"dns_test_warning_toast": "Upstream «{{key}}» не отвечает на тестовые запросы и может работать некорректно",
|
||||
"unblock": "Разблокировать",
|
||||
"block": "Заблокировать",
|
||||
"disallow_this_client": "Запретить доступ клиенту",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Настройки шифрования сохранены",
|
||||
"encryption_server": "Имя сервера",
|
||||
"encryption_server_enter": "Введите ваше доменное имя",
|
||||
"encryption_server_desc": "Для использования HTTPS вам необходимо ввести имя сервера, которое подходит вашему SSL-сертификату или сертификату с поддержкой поддоменов. Если это поле не задано, сервер будет принимать TLS-соединения для любого домена.",
|
||||
"encryption_server_desc": "Если задано, AdGuard Home распознаёт ClientID, отвечает на DDR-запросы, и дополнительно проверяет соединения. Если не задано, этот функционал отключён. Должно соответствовать одному из параметров DNS Names в сертификате.",
|
||||
"encryption_redirect": "Автоматически перенаправлять на HTTPS",
|
||||
"encryption_redirect_desc": "Если включено, AdGuard Home будет автоматически перенаправлять вас с HTTP на HTTPS адрес.",
|
||||
"encryption_https": "Порт HTTPS",
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
"load_balancing": "ධාරිතාව තුලනය",
|
||||
"local_ptr_title": "පෞද්ගලික ප්රතිවර්ත ව.නා.ප. සේවාදායක",
|
||||
"local_ptr_desc": "ස්ථානීය PTR විමසුම් සඳහා ඇඩ්ගාර්ඩ් හෝම් භාවිතා කරන ව.නා.ප. සේවාදායක. මෙම සේවාදායක පුද්ගලික අ.ජා.කෙ. ලිපින සහිත අනුග්රාහකවල සත්කාරක නාම විසඳීමට භාවිතා කරයි, උදාහරණයක් ලෙස ප්රතිවර්ත ව.නා.ප. භාවිතයෙන් \"192.168.12.34\". නැති නම්, ඇඩ්ගාර්ඩ් හෝම් හි ලිපින සඳහා හැරුනු විට ඔබගේ මෙහෙයුම් පද්ධතියේ පෙරනිමි ව.නා.ප. විසදුම්වල ලිපින භාවිතා කරයි.",
|
||||
"local_ptr_default_resolver": "පෙරනිමි ලෙස, ඇඩ්ගාර්ඩ් හෝම් පහත ප්රතිවර්තත ව.නා.ප. විසඳුම් භාවිතා කරයි: {{ip}}.",
|
||||
"local_ptr_no_default_resolver": "ඇඩ්ගාර්ඩ් හෝම් හට මෙම පද්ධතිය සඳහා සුදුසු පුද්ගලික ප්රතිවර්ත ව.නා.ප. විසඳුම් නිශ්චය කරගත නොහැකි විය.",
|
||||
"local_ptr_default_resolver": "පෙරනිමි ලෙස, ඇඩ්ගාර්ඩ් හෝම් පහත ප්රතිවර්තත ව.නා.ප. පිළිවිසඳු භාවිතා කරයි: {{ip}}.",
|
||||
"local_ptr_no_default_resolver": "ඇඩ්ගාර්ඩ් හෝම් හට මෙම පද්ධතිය සඳහා සුදුසු පුද්ගලික ප්රතිවර්ත ව.නා.ප. පිළිවිසඳු නිශ්චය කරගත නොහැකි විය.",
|
||||
"local_ptr_placeholder": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් යොදන්න",
|
||||
"resolve_clients_title": "අනුග්රාහකවල අ.ජා.කෙ. ලිපින ප්රතිවර්ත විසඳීම සබල කරන්න",
|
||||
"use_private_ptr_resolvers_title": "පෞද්. ප්රතිවර්ත ව.නා.ප. පිළිවිසඳු භාවිතය",
|
||||
"check_dhcp_servers": "ග.ධා.වි.කෙ. සේවාදායක සඳහා පරීක්ෂා කරන්න",
|
||||
"save_config": "වින්යාසය සුරකින්න",
|
||||
"enabled_dhcp": "ග.ධා.වි.කෙ. සේවාදායකය සබල කෙරිණි",
|
||||
@@ -16,9 +17,14 @@
|
||||
"unavailable_dhcp": "ග.ධා.වි.කෙ. නැත",
|
||||
"unavailable_dhcp_desc": "ඇඩ්ගාර්ඩ් හෝම් හට ඔබගේ මෙහෙයුම් පද්ධතියේ ග.ධා.වි.කෙ. සේවාදායකයක් ධාවනය කිරීමට නොහැකිය",
|
||||
"dhcp_title": "ග.ධා.වි.කෙ. සේවාදායකය (පර්යේෂණාත්මක!)",
|
||||
"dhcp_description": "ඔබගේ මාර්ගකාරකය ග.ධා.වි.කෙ. (DHCP) සැකසුම් ලබා නොදෙන්නේ නම්, ඔබට ඇඩ්ගාර්ඩ් හි ඇති ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කළ හැකිය.",
|
||||
"dhcp_description": "ඔබගේ මාර්ගකාරකය ග.ධා.වි.කෙ. (DHCP) සැකසුම් ලබා නොදෙන්නේ නම්, ඔබට ඇඩ්ගාර්ඩ් හි තිළෑලි ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කළ හැකිය.",
|
||||
"dhcp_enable": "ග.ධා.වි.කෙ. සේවාදායකය සබල කරන්න",
|
||||
"dhcp_disable": "ග.ධා.වි.කෙ. සේවාදායකය අබල කරන්න",
|
||||
"dhcp_not_found": "ඇඩ්ගාර්ඩ් හෝම් සඳහා ජාලයෙහි කිසිදු ක්රියාත්මක ග.ධා.වි.කෙ. සේවාදායකයක් හමු නොවූ නිසා තිළෑලි සේවාදායකය සබල කිරීම ආරක්ෂිත වේ. කෙසේ වෙතත්, ස්වයංක්රීය ඒෂණය ඉතා නිවැරදි නොවිය හැකි බැවින් ඔබ එය අතින් නැවත පරීක්ෂා කළ යුතුය.",
|
||||
"dhcp_found": "ක්රියාත්මක ග.ධා.වි.කෙ සේවාදායකයක් ජාලය තුළ හමු විය. තිළෑලි ග.ධා.වි.කෙ සේවාදායකය සබල කිරීම ආරක්ෂිත නොවේ.",
|
||||
"dhcp_leases": "ග.ධා.වි.කෙ. කල්පැවරීම",
|
||||
"dhcp_static_leases": "ස්ථිර ග.ධා.වි.කෙ. කල්පැවරීම",
|
||||
"dhcp_leases_not_found": "ග.ධා.වි.කෙ. කල්පැවරීම් නැත",
|
||||
"dhcp_config_saved": "ග.ධා.වි.කෙ. වින්යාසය සාර්ථකව සුරකින ලදි",
|
||||
"dhcp_ipv4_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 4 සැකසුම්",
|
||||
"dhcp_ipv6_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 6 සැකසුම්",
|
||||
@@ -31,6 +37,7 @@
|
||||
"form_error_mac_format": "මා.ප්ර.පා. ලිපිනය වලංගු නොවේ",
|
||||
"form_error_client_id_format": "අනුග්රාහකයේ හැඳු. වලංගු නොවේ",
|
||||
"form_error_server_name": "සේවාදායකයේ නම වලංගු නොවේ",
|
||||
"form_error_subnet": "\"{{cidr}}\" අනුජාලය හි \"{{ip}}\" අ.ජා.කෙ. ලිපිනය අඩංගු නොවේ",
|
||||
"form_error_positive": "0 ට වඩා වැඩි විය යුතුය",
|
||||
"out_of_range_error": "\"{{start}}\"-\"{{end}}\" පරාසයෙන් පිට විය යුතුය",
|
||||
"lower_range_start_error": "පරාසය ආරම්භයට වඩා අඩු විය යුතුය",
|
||||
@@ -40,6 +47,8 @@
|
||||
"dhcp_form_range_title": "අ.ජා. කෙ. (IP) ලිපින පරාසය",
|
||||
"dhcp_form_range_start": "පරාසය ආරම්භය",
|
||||
"dhcp_form_range_end": "පරාසය අවසානය",
|
||||
"dhcp_form_lease_title": "ග.ධා.වි.කෙ. කල්පැවරීම (තත්. වලින්)",
|
||||
"dhcp_form_lease_input": "කල්පැවරීමේ පරාසය",
|
||||
"dhcp_interface_select": "ග.ධා.වි.කෙ. අතුරුමුහුණත තෝරන්න",
|
||||
"dhcp_hardware_address": "දෘඩාංග ලිපිනය",
|
||||
"dhcp_ip_addresses": "අ.ජා.කෙ. (IP) ලිපින",
|
||||
@@ -50,6 +59,14 @@
|
||||
"dhcp_error": "ජාලයේ තවත් ක්රියාත්මක ග.ධා.වි.කෙ. සේවාදායකයක් තිබේද යන්න නිශ්චය කළ නොහැකි විය",
|
||||
"dhcp_static_ip_error": "ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කිරීම සඳහා ස්ථිතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනයක් සැකසිය යුතුය. මෙම ජාල අතුරුමුහුණත ස්ථිතික අ.ජා. කෙ. ලිපිනයක් භාවිතයෙන් වින්යාසගත කර තිබේද යන්න තීරණය කිරීමට ඇඩ්ගාර්ඩ් හෝම් අසමත් විය. කරුණාකර ස්ථිතික අ.ජා. කෙ. ලිපිනයක් අතින් සකසන්න.",
|
||||
"dhcp_dynamic_ip_found": "ඔබගේ පද්ධතිය <0>{{interfaceName}}</0> අතුරු මුහුණත සඳහා ගතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපින වින්යාසය භාවිතා කරයි. ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කිරීම සඳහා ස්ථිතික අ.ජා. කෙ. ලිපිනයක් සැකසිය යුතුය. ඔබගේ වර්තමාන අ.ජා. කෙ. ලිපිනය <0>{{ipAddress}}</0> වේ. ඔබ \"ග.ධා.වි.කෙ. සබල කරන්න\" බොත්තම එබුවහොත් ඇඩ්ගාර්ඩ් හෝම් ස්වයංක්රීයව මෙම අ.ජා. කෙ. ලිපිනය ස්ථිතික ලෙස සකසනු ඇත.",
|
||||
"dhcp_lease_added": "\"{{key}}\" ස්ථිර කල්පැවරීම එකතු කෙරිණි",
|
||||
"dhcp_lease_deleted": "\"{{key}}\" ස්ථිර කල්පැවරීම මකා දැමිණි",
|
||||
"dhcp_new_static_lease": "නව ස්ථිර කල්පැවරීම",
|
||||
"dhcp_static_leases_not_found": "ග.ධා.වි.කෙ. ස්ථිර කල්පැවරීම් නැත",
|
||||
"dhcp_add_static_lease": "ස්ථිර කල්පැවරීමක් යොදන්න",
|
||||
"dhcp_reset_leases": "කල්පැවරීම් යළි සකසන්න",
|
||||
"dhcp_reset_leases_confirm": "සියළු කල්පැවරීම් යළි සැකසීමට වුවමනා ද?",
|
||||
"dhcp_reset_leases_success": "ග.ධා.වි.කෙ. කල්පැවරීම් යළි සැකසිණි",
|
||||
"dhcp_reset": "ග.ධා.වි.කෙ. වින්යාසය යළි පිහිටුවීමට අවශ්ය බව ඔබට විශ්වාස ද?",
|
||||
"country": "රට",
|
||||
"city": "නගරය",
|
||||
@@ -112,6 +129,7 @@
|
||||
"block_domain_use_filters_and_hosts": "පෙරහන් සහ ධාරක ගොනු භාවිතා කරමින් වසම් අවහිර කරන්න",
|
||||
"filters_block_toggle_hint": "ඔබට අවහිර කිරීමේ නීති <a>පෙරහන්</a> තුළ පිහිටුවිය හැකිය.",
|
||||
"use_adguard_browsing_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ වියමන සේවාව භාවිතා කරන්න",
|
||||
"use_adguard_browsing_sec_hint": "ඇඩ්ගාර්ඩ් හෝම් විසින් පිරික්සුම් ආරක්ෂණ වියමන සේවාව මගින් වසම අවහිර කර ඇත්දැයි පරීක්ෂා කරයි. එය සිදු කිරීමට රහස්යතා-හිතකාමී බැලීමේ යෙ.ක්ර.මු. භාවිතා කෙරේ: වසමේ කෙටි උපසර්ගයක SHA256 පූරකයක් පමණක් සේවාදායකය වෙත යවනු ලැබේ.",
|
||||
"use_adguard_parental": "ඇඩ්ගාර්ඩ් දෙමාපිය පාලන වියමන සේවාව භාවිතා කරන්න",
|
||||
"use_adguard_parental_hint": "වසමේ වැඩිහිටියන්ට අදාල කරුණු අඩංගු දැයි ඇඩ්ගාර්ඩ් හෝම් විසින් පරීක්ෂා කරනු ඇත. එය පිරික්සුම් ආරක්ෂණ වියමන සේවාව මෙන් රහස්යතා හිතකාමී යෙ.ක්ර. අ.මු. (API) භාවිතා කරයි.",
|
||||
"enforce_safe_search": "ආරක්ෂිත සෙවුම භාවිතා කරන්න",
|
||||
@@ -179,13 +197,13 @@
|
||||
"example_comment_hash": "# එසේම අදහස් දැක්වීමක්.",
|
||||
"example_regex_meaning": "නිශ්චිතව දක්වා ඇති නිත්ය වාක්යවිධියට ගැළපෙන වසම් වෙත ප්රවේශය අවහිර කරයි.",
|
||||
"example_upstream_regular": "සාමාන්ය ව.නා.ප. (UDP හරහා);",
|
||||
"example_upstream_udp": "සාමාන්ය ව.නා.ප. (UDP, සත්කාරක නම හරහා);",
|
||||
"example_upstream_dot": "සංකේතිත <0>DNS-over-TLS</0>",
|
||||
"example_upstream_doh": "සංකේතිත <0>DNS-over-HTTPS</0>",
|
||||
"example_upstream_doq": "සංකේතිත <0>DNS-over-QUIC</0>;",
|
||||
"example_upstream_sdns": "<1>DNSCrypt</1> හෝ <2>HTTPS-හරහා-ව.නා.ප.</2> විසඳුම් සඳහා <0>ව.නා.ප. මුද්දර</0>;",
|
||||
"example_upstream_udp": "සාමාන්ය ව.නා.ප. (UDP, සත්කාරක-නම හරහා);",
|
||||
"example_upstream_dot": "සංකේතිත <0>TLS-මගින්-ව.නා.ප.</0>;",
|
||||
"example_upstream_doh": "සංකේතිත <0>HTTPS-මගින්-ව.නා.ප.</0>;",
|
||||
"example_upstream_doq": "සංකේතිත <0>QUIC-මගින්-ව.නා.ප.</0>;",
|
||||
"example_upstream_sdns": "<1>DNSCrypt</1> හෝ <2>HTTPS-මගින්-ව.නා.ප.</2> පිළිවිසඳු සඳහා <0>ව.නා.ප. මුද්දර</0>;",
|
||||
"example_upstream_tcp": "සාමාන්ය ව.නා.ප. (TCP/ස.පා.කෙ. හරහා);",
|
||||
"example_upstream_tcp_hostname": "සාමාන්ය ව.නා.ප. (ස.පා.කෙ., සත්කාරක නම හරහා);",
|
||||
"example_upstream_tcp_hostname": "සාමාන්ය ව.නා.ප. (ස.පා.කෙ., සත්කාරක-නම හරහා);",
|
||||
"all_lists_up_to_date_toast": "සියළුම ලැයිස්තු දැනටමත් යාවත්කාලීනයි",
|
||||
"dns_test_ok_toast": "සඳහන් කළ ව.නා.ප. සේවාදායක නිවැරදිව ක්රියා කරයි",
|
||||
"dns_test_not_ok_toast": "\"{{key}}\" සේවාදායක(ය): භාවිතා කිරීමට නොහැකි විය, ඔබ එය නිවැරදිව ලියා ඇතිදැයි පරීක්ෂා කරන්න",
|
||||
@@ -242,14 +260,14 @@
|
||||
"blocking_ipv4": "අ.ජා.කෙ.4 අවහිර කිරීම",
|
||||
"blocking_ipv6": "අ.ජා.කෙ.6 අවහිර කිරීම",
|
||||
"dnscrypt": "DNSCrypt",
|
||||
"dns_over_https": "HTTPS-හරහා-ව.නා.ප.",
|
||||
"dns_over_tls": "TLS-හරහා-ව.නා.ප.",
|
||||
"dns_over_quic": "QUIC-හරහා-ව.නා.ප.",
|
||||
"dns_over_https": "HTTPS-මගින්-ව.නා.ප.",
|
||||
"dns_over_tls": "TLS-මගින්-ව.නා.ප.",
|
||||
"dns_over_quic": "QUIC-මගින්-ව.නා.ප.",
|
||||
"client_id": "අනුග්රාහකයේ හැඳු.",
|
||||
"client_id_placeholder": "අනුග්රාහකයක හැඳු. යොදන්න",
|
||||
"client_id_desc": "අනුග්රාහක හැඳු. මගින් අනුග්රාහක හඳුනාගත හැකිය. කෙසේදැයි <a>මෙතැනින්</a> දැන ගන්න.",
|
||||
"download_mobileconfig_doh": "HTTPS-හරහා-ව.නා.ප. සඳහා .ජංගමවින්යාසය බාගන්න",
|
||||
"download_mobileconfig_dot": "TLS-හරහා-ව.නා.ප. සඳහා .ජංගමවින්යාසය බාගන්න",
|
||||
"download_mobileconfig_doh": "HTTPS-මගින්-ව.නා.ප. සඳහා .ජංගමවින්යාසය බාගන්න",
|
||||
"download_mobileconfig_dot": "TLS-මගින්-ව.නා.ප. සඳහා .ජංගමවින්යාසය බාගන්න",
|
||||
"download_mobileconfig": "වින්යාසගත ගොනුව බාගන්න",
|
||||
"plain_dns": "සරල ව.නා.ප.",
|
||||
"form_enter_rate_limit": "අනුපාත සීමාව ඇතුල් කරන්න",
|
||||
@@ -295,12 +313,13 @@
|
||||
"install_submit_title": "සුභ පැතුම්!",
|
||||
"install_submit_desc": "පිහිටුවීමේ ක්රියා පටිපාටිය අවසන් වී ඇති අතර ඔබ දැන් ඇඩ්ගාර්ඩ් හෝම් භාවිතය ආරම්භ කිරීමට සූදානම්ය.",
|
||||
"install_devices_router": "මාර්ගකාරකය",
|
||||
"install_devices_router_desc": "මෙම පිහිටුම ඔබගේ නිවසේ මාර්ගකාරකයට සම්බන්ධ සියළුම උපාංග ස්වයංක්රීයව ආවරණය කරන අතර ඔබට ඒ සෑම එකක්ම අතින් වින්යාසගත කිරීමට අවශ්ය නොවේ.",
|
||||
"install_devices_router_desc": "මෙම පිහිටුම ඔබගේ නිවසේ මාර්ගකාරකයට සම්බන්ධිත සියළුම උපාංග ස්වයංක්රීයව ආවරණය කරන අතර ඔබට ඒ සෑම එකක්ම අතින් වින්යාසගත කිරීමට අවශ්ය නොවේ.",
|
||||
"install_devices_address": "ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය පහත ලිපිනයන්ට සවන් දෙමින් පවතී",
|
||||
"install_devices_router_list_1": "ඔබගේ මාර්ගකාරකය සඳහා වූ මනාපයන් විවෘත කරන්න. සාමාන්යයෙන්, එය ඔබගේ අතිරික්සුවෙන් ඒ.ස.නි.(URL) ක් හරහා (http://192.168.0.1/ හෝ http://192.168.1.1/ වැනි) ප්රවේශ විය හැකිය. මුරපදය ඇතුල් කිරීමට සිදු විය හැකි නමුත් එය මතක නැතිනම් බොහෝ විට මාර්ගකාරකයේ බොත්තමක් එබීමෙන් මුරපදය නැවත සැකසිය හැකිය. නමුත් මෙම ක්රියා පටිපාටිය තෝරා ගන්නේ නම්, බොහෝ විට ඔබගේ මාර්ගකාරකයේ සමස්ථ වින්යාසය අහිමි වනු ඇති බව මතක තබා ගන්න.එය පිහිටුවීමට ඔබගේ මාර්ගකාරකයට යෙදුමක් ඇවැසි නම්, කරුණාකර එය ඔබගේ පරිගණකයේ හෝ දුරකථනයේ ස්ථාපනය කර මාර්ගකාරකයේ සැකසුම් වෙත ප්රවේශ වීමට භාවිතා කරන්න.",
|
||||
"install_devices_router_list_2": "ග.ධා.වි.කෙ. (DHCP)/ ව.නා.ප. (DNS) සැකසුම් සොයා ගන්න. අංක කට්ටල දෙකකට හෝ තුනකට ඉඩ දෙන ක්ෂේත්රයක් අසල ඇති ව.නා.ප. අකුරු බලන්න, සෑම එකක්ම ඉලක්කම් එකේ සිට තුන දක්වා කාණ්ඩ හතරකට බෙදා ඇත.",
|
||||
"install_devices_router_list_3": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින එහි ඇතුල් කරන්න.",
|
||||
"install_devices_router_list_4": "සමහර වර්ගයේ මාර්ගකාරක වල අභිරුචි ව.නා.ප. සේවාදායකයක් සැකසීමට නොහැකිය. මෙම අවස්ථාවේදී ඇඩ්ගාර්ඩ් හෝම් <0>ග.ධා.වි.කෙ. සේවාදායකයක්</0> ලෙස පිහිටුවන්නේ නම් එය උපකාර වනු ඇත. එසේ නැතිනම්, ඔබගේ විශේෂිත මාර්ගකාරකය සඳහා වූ ව.නා.ප. සේවාදායක රිසිකරණය කරන්නේ කෙසේද යන්න පිළිබඳ අත්පොත පරීක්ෂා කළ යුතුය.",
|
||||
"install_devices_windows_list_1": "පාලන වට්ටෝරුව හෝ වින්ඩෝස් සෙවුම හරහා පාලන මඬල අරින්න.",
|
||||
"install_devices_windows_list_2": "ජාල සහ අන්තර්ජාල ප්රවර්ගයට ගොස් පසුව ජාල සහ බෙදාගැනීමේ මධ්යස්ථානය වෙත යන්න.",
|
||||
"install_devices_windows_list_3": "වම් තීරුවෙහි \"උපයුක්තකයෙහි සැකසුම් වෙනස් කිරීම\" ඔබන්න.",
|
||||
"install_devices_windows_list_4": "ඔබගේ ක්රියාකාරී සම්බන්ධතාවය මත දකුණු-ක්ලික් කර ගුණාංග තෝරන්න.",
|
||||
@@ -310,8 +329,8 @@
|
||||
"install_devices_macos_list_2": "ජාලය මත ඔබන්න.",
|
||||
"install_devices_macos_list_3": "ඔබගේ ලැයිස්තුවේ පළමු සම්බන්ධතාවය තෝරා වැඩිදුර යන්න ඔබන්න.",
|
||||
"install_devices_macos_list_4": "ව.නා.ප. (DNS) තීරුව තෝරා ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුල් කරන්න.",
|
||||
"install_devices_android_list_1": "ඇන්ඩ්රොයිඩ් මෙනුවෙහි මුල් තිරයෙන්, සැකසීම් මත තට්ටු කරන්න.",
|
||||
"install_devices_android_list_2": "මෙනුවේ වයි-ෆයි මත තට්ටු කරන්න. පවතින සියලුම ජාල ලැයිස්තුගත කර ඇති තිරය පෙන්වනු ඇත (ජංගම සම්බන්ධතාවය සඳහා අභිරුචි ව.නා.ප. සැකසිය නොහැක).",
|
||||
"install_devices_android_list_1": "ඇන්ඩ්රොයිඩ් මුල් තිරයෙන්, සැකසුම් මත තට්ටු කරන්න.",
|
||||
"install_devices_android_list_2": "වට්ටෝරුවෙහි වයි-ෆයි මත තට්ටු කරන්න. පවතින සියළුම ජාල ලේඛන ගතවී තිබෙන තිරය පෙන්වනු ඇත (ජංගම සම්බන්ධතාවය සඳහා අභිරුචි ව.නා.ප. සැකසීමට නොහැකිය).",
|
||||
"install_devices_android_list_3": "සම්බන්ධිත ජාලය මත දිගු වේලාවක් ඔබන්න, ඉන්පසුව ජාලය වෙනස් කිරීම මත තට්ටු කරන්න.",
|
||||
"install_devices_android_list_4": "ඔබට සමහර උපාංගවල සියළු සැකසුම් බැලීමට \"වැඩිදුර\" සඳහා වූ කොටුව සලකුණු කිරීමට අවශ්ය විය හැකිය. එමෙන්ම ඔබගේ ඇන්ඩ්රොයිඩ් ව.නා.ප. (DNS) සැකසුම් වෙනස් කිරීමට අ.ජා.කෙ. (IP) සැකසුම්, ග.ධා.වි.කෙ. (DHCP) සිට ස්ථිතික වෙත මාරු කළ යුතුය.",
|
||||
"install_devices_android_list_5": "ව.නා.ප. 1 සහ ව.නා.ප. 2 පිහිටුවීම් අගයන් ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින වලට වෙනස් කරන්න.",
|
||||
@@ -328,22 +347,24 @@
|
||||
"encryption_config_saved": "සංකේතන වින්යාසය සුරකින ලදි",
|
||||
"encryption_server": "සේවාදායකයේ නම",
|
||||
"encryption_server_enter": "ඔබගේ වසම් නාමය ඇතුල් කරන්න",
|
||||
"encryption_server_desc": "සැකසා ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් අනුග්රාහක හැඳුනුම් හඳුනා ගැනෙයි, සෘ.ද.ඉ. (DDR) විමසුම්වලට ප්රතිචාර දක්වයි, සහ අතිරේක සම්බන්ධතා වලංගුකරණය සිදු කරයි. නොඑසේ නම්, මෙම විශේෂාංග අබලව ඇත. සහතිකයේ තිබෙන ව.නා.ප. නම් වලින් එකකට ගැළපිය යුතුය.",
|
||||
"encryption_redirect": "ස්වයංක්රීයව HTTPS වෙත හරවා යවන්න",
|
||||
"encryption_redirect_desc": "සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් ඔබව ස්වයංක්රීයව HTTP සිට HTTPS ලිපින වෙත හරවා යවනු ඇත.",
|
||||
"encryption_https": "HTTPS තොට",
|
||||
"encryption_https_desc": "HTTPS තොට වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ප්රවේශ විය හැකි අතර එය '/dns-query' ස්ථානයේ HTTPS-හරහා-ව.නා.ප. ද ලබා දෙනු ඇත.",
|
||||
"encryption_dot": "TLS-හරහා-ව.නා.ප. තොට",
|
||||
"encryption_dot_desc": "මෙම තොට වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කවුළුව හරහා TLS-හරහා-ව.නා.ප. සේවාදායකයක් ධාවනය කරනු ඇත.",
|
||||
"encryption_doq": "QUIC-හරහා-ව.නා.ප. තොට",
|
||||
"encryption_doq_desc": "මෙම තොට වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම තොට හරහා QUIC-හරහා-ව.නා.ප. සේවාදායකයක් ධාවනය කරනු ඇත.",
|
||||
"encryption_https_desc": "HTTPS තොට වින්යාසගත නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ප්රවේශ විය හැකි අතර එය '/dns-query' ස්ථානයේ HTTPS-මගින්-ව.නා.ප. ද ලබා දෙනු ඇත.",
|
||||
"encryption_dot": "TLS-මගින්-ව.නා.ප. තොට",
|
||||
"encryption_dot_desc": "මෙම තොට වින්යාසගත නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කවුළුව හරහා TLS-මගින්-ව.නා.ප. සේවාදායකයක් ධාවනය කෙරේ.",
|
||||
"encryption_doq": "QUIC-මගින්-ව.නා.ප. තොට",
|
||||
"encryption_doq_desc": "මෙම තොට වින්යාසගත නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම තොට හරහා QUIC-මගින්-ව.නා.ප. සේවාදායකයක් ධාවනය කෙරේ.",
|
||||
"encryption_certificates": "සහතික",
|
||||
"encryption_certificates_desc": "සංකේතනය භාවිතයට, ඔබගේ වසම සඳහා වලංගු SSL සහතික දාමයක් සැපයිය යුතුය. <0>{{link}}</0> වෙතින් නොමිලේ සහතිකයක් ලබා ගැනීමට හැකිය හෝ විශ්වාසදායක සහතික අධිකාරියකින් මිලදී ගන්න.",
|
||||
"encryption_certificates_input": "ඔබගේ PEM-කේතනය කළ සහතික පිටපත් කර මෙහි අලවන්න.",
|
||||
"encryption_status": "තත්වය",
|
||||
"encryption_expire": "කල් ඉකුත් වීම",
|
||||
"encryption_key": "පුද්ගලික යතුර",
|
||||
"encryption_key_input": "ඔබගේ සහතිකය සඳහා PEM-කේතනය කළ පුද්ගලික යතුර පිටපත් කර මෙහි අලවන්න.",
|
||||
"encryption_enable": "සංකේතනය සබල කරන්න (HTTPS, DNS-over-HTTPS සහ DNS-over-TLS)",
|
||||
"encryption_enable_desc": "සංකේතනය සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ක්රියා කරනු ඇති අතර ව.නා.ප. සේවාදායකය DNS-over-HTTPS සහ DNS-over-TLS හරහා ලැබෙන ඉල්ලීම් සඳහා සවන් දෙනු ඇත.",
|
||||
"encryption_enable": "සංකේතනය සබල කරන්න (HTTPS, HTTPS-මගින්-ව.නා.ප. සහ TLS-මගින්-ව.නා.ප.)",
|
||||
"encryption_enable_desc": "සංකේතනය සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ක්රියා කරනු ඇති අතර ව.නා.ප. සේවාදායකය HTTPS-මගින්-ව.නා.ප. සහ TLS-මගින්-ව.නා.ප. හරහා ලැබෙන ඉල්ලීම් සඳහා සවන් දෙනු ඇත.",
|
||||
"encryption_chain_valid": "සහතික දාමය වලංගු ය",
|
||||
"encryption_chain_invalid": "සහතික දාමය වලංගු නොවේ",
|
||||
"encryption_key_valid": "මෙය වලංගු {{type}} පුද්ගලික යතුරකි",
|
||||
@@ -383,6 +404,7 @@
|
||||
"client_edit": "අනුග්රාහකය සංස්කරණය",
|
||||
"client_identifier": "හඳුන්වනය",
|
||||
"ip_address": "අ.ජා.කෙ. ලිපිනය",
|
||||
"client_identifier_desc": "අ.ජා.කෙ. (IP) ලිපින, අන.ජා. (CIDR), මා.ප්ර.පා. (MAC) ලිපින හෝ අනුග්රාහක හැඳුනුමක් (DoT/DoH/DoQ සඳහා භාවිතා කළ හැකිය) මගින් අනුග්රාහක හඳුනාගත හැකිය. අනුග්රාහක හඳුනා ගන්නේ කෙසේද යන්න පිළිබඳව <0>මෙතැනින්</0> තව දැනගන්න.",
|
||||
"form_enter_ip": "අ.ජා.කෙ. (IP) ඇතුල් කරන්න",
|
||||
"form_enter_subnet_ip": "\"{{cidr}}\" අනුජාලයෙහි අ.ජා.කෙ. ලිපිනයක් යොදන්න.",
|
||||
"form_enter_mac": "මා.ප්ර.පා. (MAC) යොදන්න",
|
||||
@@ -401,25 +423,32 @@
|
||||
"access_title": "ප්රවේශවීමට සැකසුම්",
|
||||
"access_desc": "මෙහිදී ඔබට ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකයට ප්රවේශ වීමේ නීති වින්යාසගත කළ හැකිය",
|
||||
"access_allowed_title": "ඉඩ ලත් අනුග්රාහකයින්",
|
||||
"access_allowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් පමණක් ඉල්ලීම් පිළිගනු ඇත.",
|
||||
"access_allowed_desc": "අන.ජා.(CIDR), අ.ජා.කෙ. ලිපින හෝ <a>අනුග්රාහක හැඳු.</a> ලේඛනයකි. මෙහි නිවේශිත ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අනුග්රාහක වලින් පමණක් ඉල්ලීම් පිළිගනු ඇත.",
|
||||
"access_disallowed_title": "නොඉඩ ලත් අනුග්රාහකයින්",
|
||||
"access_disallowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් ඉල්ලීම් අත්හරිනු ඇත.",
|
||||
"access_disallowed_desc": "අන.ජා.(CIDR), අ.ජා.කෙ. ලිපින හෝ <a>අනුග්රාහක හැඳු.</a> ලේඛනයකි. මෙහි නිවේශිත ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අනුග්රාහක වලින් ඉල්ලීම් අත්හරිනු ඇත. ඉඩ ලත් අනුග්රාහකවල නිවේශිත තිබේ නම්, මෙම ක්ෂේත්රය නොසලකා හරිනු ඇත.",
|
||||
"access_blocked_title": "නොඉඩ ලත් වසම්",
|
||||
"access_settings_saved": "ප්රවේශ වීමේ සැකසුම් සාර්ථකව සුරකින ලදි",
|
||||
"updates_checked": "ඇඩ්ගාර්ඩ් හෝම් හි නව අනුවාදයක් තිබේ",
|
||||
"updates_version_equal": "ඇඩ්ගාර්ඩ් හෝම් යාවත්කාලීනයි",
|
||||
"check_updates_now": "දැන් යාවත්කාල පරීක්ෂා කරන්න",
|
||||
"dns_privacy": "ව.නා.ප. රහස්යතා",
|
||||
"setup_dns_privacy_1": "<0>TLS-මගින්-ව.නා.ප.</0> සඳහා <1>{{address}}</1>.",
|
||||
"setup_dns_privacy_2": "<0>HTTPS-මගින්-ව.නා.ප.</0> සඳහා <1>{{address}}</1>.",
|
||||
"setup_dns_privacy_3": "<0>මෙහි ඔබට භාවිතා කළ හැකි මෘදුකාංග ලැයිස්තුවක් ඇත.</0>",
|
||||
"setup_dns_privacy_android_2": "<1>HTTPS-හරහා-ව.නා.ප.</1> සහ <1>TLS-හරහා-ව.නා.ප.</1> සඳහා <0>ඇන්ඩ්රොයිඩ් සඳහා ඇඩ්ගාර්ඩ්</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_android_1": "TLS-මගින්-ව.නා.ප සහාය සමගම ඇන්ඩ්රොයිඩ් 9 පැමිණේ. එය වින්යාස කිරීමට, සැකසුම් → ජාලය හා අන්තර්ජාලය → වැඩිදුර → පෞද්. ව.නා.ප. වෙත ගොස් එහි ඔබගේ වසමේ නම යොදන්න.",
|
||||
"setup_dns_privacy_android_2": "<1>HTTPS-මගින්-ව.නා.ප.</1> හා <1>TLS-මගින්-ව.නා.ප.</1> සඳහා <0>ඇන්ඩ්රොයිඩ් සඳහා ඇඩ්ගාර්ඩ්</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_android_3": "<0>ඉන්ට්රා</0> විසින් <1>HTTPS-මගින්-ව.නා.ප</1> සහාය ඇන්ඩ්රොයිඩ් සඳහා එකතු කරයි.",
|
||||
"setup_dns_privacy_ios_2": "<1>HTTPS-මගින්-ව.නා.ප.</1> හා <1>TLS-මගින්-ව.නා.ප.</1> සඳහා <0>අයිඕඑස් සඳහා ඇඩ්ගාර්ඩ්</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_title": "වෙනත් ක්රියාවට නැංවූ දෑ",
|
||||
"setup_dns_privacy_other_2": "<0>ඩීඑන්එස්ප්රොක්සි</0> දන්නා සියලුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_4": "<1>DNS-over-HTTPS</1> සඳහා <0>මොසිල්ලා ෆයර්ෆොක්ස්</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_1": "ඇඩ්ගාර්ඩ් හෝම් මෘදුකාංගයට ඕනෑම වේදිකාවක ආරක්ෂිත ව.නා.ප. අනුග්රාහකයක් ලෙස ක්රියාත්මක වීමට ද හැකිය.",
|
||||
"setup_dns_privacy_other_2": "<0>ව.නා.ප. ප්රතියුක්තය</0> දන්නා සියළුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_3": "<1>HTTPS-මගින්-ව.නා.ප.</1> සඳහා <0>dnscrypt-ප්රතියුක්තය</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_4": "<1>HTTPS-මගින්-ව.නා.ප.</1> සඳහා <0>මොසිල්ලා ෆයර්ෆොක්ස්</0> සහාය දක්වයි.",
|
||||
"setup_dns_privacy_other_5": "<0>මෙහි</0> සහ <1>මෙහි</1> තවත් ක්රියාවට නැංවූ දෑ ඔබට හමුවනු ඇත.",
|
||||
"setup_dns_privacy_ioc_mac": "අයිඕඑස් සහ මැක්ඕඑස් වින්යාසය",
|
||||
"setup_dns_notice": "ඔබට <1>DNS-over-HTTPS</1> හෝ <1>DNS-over-TLS</1> භාවිතයට ඇඩ්ගාර්ඩ් හෝම් සැකසුම් තුළ <0>සංකේතනය වින්යාසගත</0> කිරීමට ඇවැසිය.",
|
||||
"setup_dns_notice": "ඔබට <1>HTTPS-මගින්-ව.නා.ප.</1> හෝ <1>DNS-මගින්-ව.නා.ප.</1> භාවිතයට ඇඩ්ගාර්ඩ් හෝම් සැකසුම් තුළ <0>සංකේතනය වින්යාසගත</0> කළ යුතුය.",
|
||||
"rewrite_added": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම සාර්ථකව එකතු කෙරිණි",
|
||||
"rewrite_deleted": "\"{{key}}\" සඳහා ව. නා. ප. නැවත ලිවීම සාර්ථකව ඉවත් කෙරිණි",
|
||||
"rewrite_deleted": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම ඉවත් කෙරිණි",
|
||||
"rewrite_add": "ව.නා.ප. නැවත ලිවීමක් එකතු කරන්න",
|
||||
"rewrite_not_found": "ව.නා.ප. නැවත ලිවීම් හමු නොවිණි",
|
||||
"rewrite_confirm_delete": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම ඉවත් කිරීමට අවශ්ය බව ඔබට විශ්වාසද?",
|
||||
@@ -462,7 +491,7 @@
|
||||
"statistics_retention": "සංඛ්යාලේඛන රඳවා තබා ගැනීම",
|
||||
"statistics_retention_desc": "ඔබ කාල පරතරය අඩු කළහොත් සමහර දත්ත නැති වනු ඇත",
|
||||
"statistics_clear": "සංඛ්යාලේඛන හිස් කරන්න",
|
||||
"statistics_clear_confirm": "සංඛ්යාලේඛන ඉවත් කිරීමට අවශ්ය බව ඔබට විශ්වාස ද?",
|
||||
"statistics_clear_confirm": "සංඛ්යාලේඛන ඉවත් කිරීමට වුවමනා ද?",
|
||||
"statistics_retention_confirm": "සංඛ්යාලේඛන රඳවා තබා ගැනීම වෙනස් කිරීමට අවශ්ය බව ඔබට විශ්වාසද? ඔබ කාල පරතරයෙහි අගය අඩු කළහොත් සමහර දත්ත නැති වී යනු ඇත",
|
||||
"statistics_cleared": "සංඛ්යාලේඛන සාර්ථකව ඉවත් කෙරිණි",
|
||||
"statistics_enable": "සංඛ්යාලේඛන සබල කරන්න",
|
||||
@@ -531,6 +560,7 @@
|
||||
"list_updated": "ලැයිස්තු {{count}} ක් යාවත්කාල කෙරිණි",
|
||||
"list_updated_plural": "ලැයිස්තු {{count}} ක් යාවත්කාල කෙරිණි",
|
||||
"dnssec_enable": "DNSSEC සබල කරන්න",
|
||||
"validated_with_dnssec": "DNSSEC සමඟ වලංගු කෙරිණි",
|
||||
"all_queries": "සියළුම විමසුම්",
|
||||
"show_blocked_responses": "අවහිර කර ඇත",
|
||||
"show_whitelisted_responses": "ඉඩ දී ඇත",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream servery boli úspešne uložené",
|
||||
"dns_test_ok_toast": "Špecifikované DNS servery pracujú korektne",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohol byť použitý, skontrolujte, či ste ho správne napísali",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" neodpovedá na testovacie dopyty a nemusí fungovať správne",
|
||||
"unblock": "Odblokovať",
|
||||
"block": "Blokovať",
|
||||
"disallow_this_client": "Zablokovať tohto klienta",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Konfigurácia šifrovania uložená",
|
||||
"encryption_server": "Meno servera",
|
||||
"encryption_server_enter": "Zadajte meno Vašej domény",
|
||||
"encryption_server_desc": "Ak chcete používať protokol HTTPS, musíte zadať názov servera, ktorý zodpovedá Vášmu certifikátu SSL alebo certifikátu so zástupnými znakmi. Ak pole nie je nastavené, bude akceptovať TLS pripojenia pre ľubovoľnú doménu.",
|
||||
"encryption_server_desc": "Ak je nastavené, AdGuard Home zisťuje ClientID, odpovedá na dotazy DDR a vykonáva ďalšie overenia pripojenia. Ak nie je nastavená, tieto funkcie sú vypnuté. Musí sa zhodovať s jedným z názvov DNS v certifikáte.",
|
||||
"encryption_redirect": "Automaticky presmerovať na HTTPS",
|
||||
"encryption_redirect_desc": "Ak je táto možnosť začiarknutá, služba AdGuard Home Vás automaticky presmeruje z adresy HTTP na adresy HTTPS.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Gorvodni trežniki so uspešno shranjeni",
|
||||
"dns_test_ok_toast": "Navedeni strežniki DNS delujejo pravilno",
|
||||
"dns_test_not_ok_toast": "Ni mogoče uporabiti: strežnika \"{{key}}\". Preverite, ali ste ga pravilno napisali",
|
||||
"dns_test_warning_toast": "Upstream \"{{key}}\" se ne odziva na testne zahteve in morda ne deluje pravilno",
|
||||
"unblock": "Omogoči",
|
||||
"block": "Onemogoči",
|
||||
"disallow_this_client": "Onemogoči tega odjemalca",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Nastavitve šifriranja so shranjene",
|
||||
"encryption_server": "Ime strežnika",
|
||||
"encryption_server_enter": "Vnesite ime vaše domene",
|
||||
"encryption_server_desc": "Za uporabo HTTPS morate vnesti ime strežnika, ki se ujema z vašim digitalnim certifikatom SSL.\n",
|
||||
"encryption_server_desc": "Če je nastavljeno, AdGuard Home zazna ClientID-je, odgovori na poizvedbe DDR in izvede dodatna preverjanja povezave. Če ni nastavljeno, so te funkcije onemogočene. Ujemati se mora z enim od imen DNS v potrdilu.",
|
||||
"encryption_redirect": "Samodejno preusmeri na HTTPS",
|
||||
"encryption_redirect_desc": "Če je označeno, vas bo AdGuard Home samodejno preusmeril iz naslovov HTTP na naslove HTTPS.",
|
||||
"encryption_https": "Vrata HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Upstream serveri su uspešno sačuvani",
|
||||
"dns_test_ok_toast": "Dati DNS serveri rade ispravno",
|
||||
"dns_test_not_ok_toast": "Server \"{{key}}\": se ne može koristiti. Proverite da li ste ga ispravno uneli",
|
||||
"dns_test_warning_toast": "Apstrim \"{{key}}\" ne odgovara na zahteve za testiranje i možda neće raditi kako treba",
|
||||
"unblock": "Odblokiraj",
|
||||
"block": "Blokiraj",
|
||||
"disallow_this_client": "Zabrani ovaj klijent",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Konfiguracija šifrovanja je sačuvana",
|
||||
"encryption_server": "Ime servera",
|
||||
"encryption_server_enter": "Unesite vaše ime domena",
|
||||
"encryption_server_desc": "Da biste koristili HTTPS, potrebno je da unesete ime servera koje se podudara sa SSL certifikatom ili džoker certifikatom. Ako polje nije postavljeno, prihvatiće TLS veze za bilo koji domen.",
|
||||
"encryption_server_desc": "Ako je podešen, AdGuard Home otkriva ID-ove klijenta, odgovara na DDR upite i izvršava dodatne provere valjanosti veze. Ako se ne postave, ove funkcije su onemogućene. Mora se podudarati sa DNS imenima u certifikatu.",
|
||||
"encryption_redirect": "Automatski preusmeri na HTTPS",
|
||||
"encryption_redirect_desc": "Ako je označeno, AdGuard Home će vas automatski preusmeravati sa HTTP na HTTPS adrese.",
|
||||
"encryption_https": "HTTPS port",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"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",
|
||||
"dns_test_warning_toast": "Uppströms \"{{key}}\" svarar inte på testförfrågningar och kanske inte fungerar korrekt",
|
||||
"unblock": "Avblockera",
|
||||
"block": "Blockera",
|
||||
"disallow_this_client": "Tillåt inte den här klienten",
|
||||
@@ -363,7 +364,7 @@
|
||||
"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_server_desc": "För att använda HTTPS behöver du skriva in servernamnet som stämmer överens med ditt SSL-certifikat.",
|
||||
"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",
|
||||
@@ -613,7 +614,7 @@
|
||||
"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_general": "Allmänt",
|
||||
"filter_category_security": "säkerhet",
|
||||
"filter_category_regional": "Regional",
|
||||
"filter_category_other": "Övrigt",
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
"disabled_safe_search_toast": "Güvenli Arama devre dışı bırakıldı",
|
||||
"enabled_save_search_toast": "Güvenli Arama etkinleştirildi",
|
||||
"enabled_table_header": "Etkin",
|
||||
"name_table_header": "İsim",
|
||||
"name_table_header": "Ad",
|
||||
"list_url_table_header": "Liste URL'si",
|
||||
"rules_count_table_header": "Kural sayısı",
|
||||
"last_time_updated_table_header": "Son güncelleme zamanı",
|
||||
@@ -186,7 +186,7 @@
|
||||
"add_blocklist": "Engel listesi ekle",
|
||||
"add_allowlist": "İzin listesi ekle",
|
||||
"cancel_btn": "İptal",
|
||||
"enter_name_hint": "İsim girin",
|
||||
"enter_name_hint": "Ad girin",
|
||||
"enter_url_or_path_hint": "Listenin URL adresini veya dosya yolunu girin",
|
||||
"check_updates_btn": "Güncellemeleri denetle",
|
||||
"new_blocklist": "Yeni engel listesi",
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Üst sunucular başarıyla kaydedildi",
|
||||
"dns_test_ok_toast": "Belirtilen DNS sunucuları düzgün çalışıyor",
|
||||
"dns_test_not_ok_toast": "Sunucu \"{{key}}\": kullanılamıyor, lütfen doğru yazdığınızdan emin olun",
|
||||
"dns_test_warning_toast": "Üst kaynak \"{{key}}\", test isteklerine yanıt vermiyor ve düzgün çalışmayabilir",
|
||||
"unblock": "Engeli kaldır",
|
||||
"block": "Engelle",
|
||||
"disallow_this_client": "Bu istemciye izin verme",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Şifreleme yapılandırması kaydedildi",
|
||||
"encryption_server": "Sunucu adı",
|
||||
"encryption_server_enter": "Alan adınızı girin",
|
||||
"encryption_server_desc": "HTTPS kullanmak için SSL sertifikanızla veya joker sertifikanızla eşleşen sunucu adını girmeniz gerekir. Bu alan ayarlanmazsa, herhangi bir alan adının TLS bağlantılarını kabul eder.",
|
||||
"encryption_server_desc": "Ayarlanırsa, AdGuard Home ClientID'leri algılar, DDR sorgularına yanıt verir ve ek bağlantı doğrulamaları gerçekleştirir. Ayarlanmazsa, bu özellikler devre dışı bırakılır. Sertifikadaki DNS Adlarından biriyle eşleşmelidir.",
|
||||
"encryption_redirect": "Otomatik olarak HTTPS'e yönlendir",
|
||||
"encryption_redirect_desc": "Etkinleştirirseniz, AdGuard Home sizi HTTP adresi yerine HTTPS adresine yönlendirir.",
|
||||
"encryption_https": "HTTPS bağlantı noktası",
|
||||
@@ -396,7 +397,7 @@
|
||||
"form_error_equal": "Aynı olmamalıdır",
|
||||
"form_error_password": "Parolalar uyuşmuyor",
|
||||
"reset_settings": "Ayarları sıfırla",
|
||||
"update_announcement": "AdGuard Home {{version}} sürümü mevcut! Daha fazla bilgi için <0>buraya tıklayın.</0>",
|
||||
"update_announcement": "AdGuard Home {{version}} sürümü artık mevcut! Daha fazla bilgi için <0>buraya tıklayın</0>.",
|
||||
"setup_guide": "Kurulum Rehberi",
|
||||
"dns_addresses": "DNS adresleri",
|
||||
"dns_start": "DNS sunucusu başlatılıyor",
|
||||
@@ -413,7 +414,7 @@
|
||||
"settings_global": "Genel",
|
||||
"settings_custom": "Özel",
|
||||
"table_client": "İstemci",
|
||||
"table_name": "İsim",
|
||||
"table_name": "Ad",
|
||||
"save_btn": "Kaydet",
|
||||
"client_add": "İstemci Ekle",
|
||||
"client_new": "Yeni İstemci",
|
||||
@@ -427,7 +428,7 @@
|
||||
"form_enter_id": "Tanımlayıcı girin",
|
||||
"form_add_id": "Tanımlayıcı ekle",
|
||||
"form_client_name": "İstemci ismi girin",
|
||||
"name": "İsim",
|
||||
"name": "Ad",
|
||||
"client_global_settings": "Genel ayarları kullan",
|
||||
"client_deleted": "\"{{key}}\" istemcisi başarıyla silindi",
|
||||
"client_added": "\"{{key}}\" istemcisi başarıyla eklendi",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "DNS-сервери успішно збережено",
|
||||
"dns_test_ok_toast": "Вказані DNS сервери працюють правильно",
|
||||
"dns_test_not_ok_toast": "Сервер «{{key}}»: неможливо використати. Перевірте правильність введення",
|
||||
"dns_test_warning_toast": "Upstream «{{key}}» не відповідає на тестові запити та може працювати не правильно",
|
||||
"unblock": "Дозволити",
|
||||
"block": "Заборонити",
|
||||
"disallow_this_client": "Заборонити цього клієнта",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "Конфігурацію шифрування збережено",
|
||||
"encryption_server": "Назва сервера",
|
||||
"encryption_server_enter": "Введіть ваше доменне ім'я",
|
||||
"encryption_server_desc": "Для використання HTTPS вам потрібно ввести назву сервера, який відповідає вашому SSL-сертифікату або сертифікату з підтримкою піддоменів. Якщо значення не вказано, то сервер буде приймати TLS-з'єднання для будь-якого домену.",
|
||||
"encryption_server_desc": "Якщо встановлено, AdGuard Home розпізнає ClientID, відповідає на DDR-запити та додатково перевіряє з'єднання. Якщо не встановлено, то цей функціонал вимкнено. Мусить відповідати одному з параметрів DNS Names в сертифікаті.",
|
||||
"encryption_redirect": "Автоматично перенаправляти на HTTPS",
|
||||
"encryption_redirect_desc": "Якщо встановлено, AdGuard Home автоматично перенаправить вас з HTTP на адреси HTTPS.",
|
||||
"encryption_https": "Порт HTTPS",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"form_error_server_name": "Tên máy chủ không hợp lệ",
|
||||
"form_error_subnet": "Mạng con \"{{cidr}}\" không chứa địa chỉ IP \"{{ip}}\"",
|
||||
"form_error_positive": "Phải lớn hơn 0",
|
||||
"form_error_gateway_ip": "Cho thuê không thể có địa chỉ IP của cổng",
|
||||
"out_of_range_error": "Phải nằm ngoài phạm vi \"{{start}}\"-\"{{end}}\"",
|
||||
"lower_range_start_error": "Phải thấp hơn khởi động phạm vi",
|
||||
"greater_range_start_error": "Phải lớn hơn khoảng bắt đầu",
|
||||
@@ -221,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "Các máy chủ thượng nguồn đã được lưu thành công",
|
||||
"dns_test_ok_toast": "Máy chủ DNS có thể sử dụng",
|
||||
"dns_test_not_ok_toast": "Máy chủ \"{{key}}\"': không thể sử dụng, vui lòng kiểm tra lại",
|
||||
"dns_test_warning_toast": "Ngược lại \"{{key}}\" không phản hồi các yêu cầu kiểm tra và có thể không hoạt động bình thường",
|
||||
"unblock": "Bỏ chặn",
|
||||
"block": "Chặn",
|
||||
"disallow_this_client": "Không cho phép client này",
|
||||
@@ -362,7 +364,7 @@
|
||||
"encryption_config_saved": "Đã lưu cấu hình mã hóa",
|
||||
"encryption_server": "Tên máy chủ",
|
||||
"encryption_server_enter": "Nhập tên miền của bạn",
|
||||
"encryption_server_desc": "Để sử dụng HTTPS, bạn cần nhập tên máy chủ phù hợp với chứng chỉ SSL của bạn. Nếu trường này bị bỏ trống, nó sẽ chấp nhận kết nối TLS với tất cả tên miền.",
|
||||
"encryption_server_desc": "Nếu được đặt, AdGuard Home sẽ phát hiện ClientID, phản hồi các truy vấn DDR và thực hiện xác thực kết nối bổ sung. Nếu không được đặt, các tính năng này sẽ bị vô hiệu hóa. Phải khớp với một trong các Tên DNS trong chứng chỉ.",
|
||||
"encryption_redirect": "Tự động chuyển hướng đến HTTPS",
|
||||
"encryption_redirect_desc": "Nếu được chọn, AdGuard Home sẽ tự động chuyển hướng bạn từ địa chỉ HTTP sang địa chỉ HTTPS.",
|
||||
"encryption_https": "Cổng HTTPS",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "上游服务器保存成功",
|
||||
"dns_test_ok_toast": "指定的 DNS 服务器现已正常运行",
|
||||
"dns_test_not_ok_toast": "服务器 \"{{key}}\":无法使用,请检查你输入的是否正确",
|
||||
"dns_test_warning_toast": "上游 “{{key}}” 不响应测试请求,可能无法正常工作",
|
||||
"unblock": "放行",
|
||||
"block": "拦截",
|
||||
"disallow_this_client": "不允许这个客户端",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "加密配置已保存",
|
||||
"encryption_server": "服务器名称",
|
||||
"encryption_server_enter": "输入您的域名",
|
||||
"encryption_server_desc": "为了使用 HTTPS,请您输入与 SSL 证书或通配证书相匹配的服务器名称。如此字段未设置,服务器将要为所有域名接受 TLS 连接。",
|
||||
"encryption_server_desc": "设置后,AdGuard Home 检测客户端标识号,对 DDR 查询作出反应,以及进一步检查连接。在没有设置的情况下,该功能被禁用。必须与证书里的一个 DNS 名称相匹配。",
|
||||
"encryption_redirect": "HTTPS 自动重定向",
|
||||
"encryption_redirect_desc": "如果勾选此选项,AdGuard Home 将自动将您从 HTTP 重定向到 HTTPS 地址。",
|
||||
"encryption_https": "HTTPS 端口",
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
"updated_upstream_dns_toast": "上游的伺服器被成功地儲存",
|
||||
"dns_test_ok_toast": "已明確指定的 DNS 伺服器正在正確地運作",
|
||||
"dns_test_not_ok_toast": "伺服器 \"{{key}}\":無法被使用,請檢查您已正確地填寫它",
|
||||
"dns_test_warning_toast": "上游 “{{key}}” 不回應測試請求,可能無法正常工作",
|
||||
"unblock": "解除封鎖",
|
||||
"block": "封鎖",
|
||||
"disallow_this_client": "不允許此用戶端",
|
||||
@@ -363,7 +364,7 @@
|
||||
"encryption_config_saved": "加密配置被儲存",
|
||||
"encryption_server": "伺服器名稱",
|
||||
"encryption_server_enter": "輸入您的域名",
|
||||
"encryption_server_desc": "為了使用 HTTPS,您需要輸入與您的安全通訊端層(SSL)憑證或萬用字元憑證相符的伺服器名稱。如果此欄位未被設定,它將接受向任何網域的傳輸層安全性協定(TLS)連線。",
|
||||
"encryption_server_desc": "如果被設定,AdGuard Home 檢測用戶端 IDs,回覆 DDR 查詢,並執行額外的連線驗證。如果未被設定,這些功能被禁用。必須與在該憑證裡的 DNS 名稱其中之一相符。",
|
||||
"encryption_redirect": "自動地重新導向到 HTTPS",
|
||||
"encryption_redirect_desc": "如果被勾選,AdGuard Home 將自動地重新導向您從 HTTP 到 HTTPS 位址。",
|
||||
"encryption_https": "HTTPS 連接埠",
|
||||
|
||||
@@ -314,13 +314,15 @@ export const testUpstream = (
|
||||
const testMessages = Object.keys(upstreamResponse)
|
||||
.map((key) => {
|
||||
const message = upstreamResponse[key];
|
||||
if (message !== 'OK') {
|
||||
if (message.startsWith('WARNING:')) {
|
||||
dispatch(addErrorToast({ error: i18next.t('dns_test_warning_toast', { key }) }));
|
||||
} else if (message !== 'OK') {
|
||||
dispatch(addErrorToast({ error: i18next.t('dns_test_not_ok_toast', { key }) }));
|
||||
}
|
||||
return message;
|
||||
});
|
||||
|
||||
if (testMessages.every((message) => message === 'OK')) {
|
||||
if (testMessages.every((message) => message === 'OK' || message.startsWith('WARNING:'))) {
|
||||
dispatch(addSuccessToast('dns_test_ok_toast'));
|
||||
}
|
||||
|
||||
|
||||
@@ -147,11 +147,11 @@ const DomainCell = ({
|
||||
/>
|
||||
<div className={valueClass}>
|
||||
{unicodeName ? (
|
||||
<div className="text-truncate" title={unicodeName}>
|
||||
<div className="text-truncate overflow-break-mobile" title={unicodeName}>
|
||||
{unicodeName}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-truncate" title={domain}>
|
||||
<div className="text-truncate overflow-break-mobile" title={domain}>
|
||||
{domain}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@media (max-width: 991.98px) {
|
||||
.overflow-break-mobile {
|
||||
white-space: normal !important;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, min-content);
|
||||
|
||||
@@ -139,11 +139,23 @@ const Row = memo(({
|
||||
}
|
||||
};
|
||||
|
||||
const blockButton = <button
|
||||
className={classNames('title--border text-center button-action--arrow-option', { 'bg--danger': !isBlocked })}
|
||||
onClick={onToggleBlock}>
|
||||
{t(buttonType)}
|
||||
</button>;
|
||||
const blockButton = (
|
||||
<>
|
||||
<div className="title--border" />
|
||||
<button
|
||||
type="button"
|
||||
className={
|
||||
classNames(
|
||||
'button-action--arrow-option',
|
||||
{ 'bg--danger': !isBlocked },
|
||||
{ 'bg--green': isFiltered },
|
||||
)}
|
||||
onClick={onToggleBlock}
|
||||
>
|
||||
{t(buttonType)}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
|
||||
const blockForClientButton = <button
|
||||
className='text-center font-weight-bold py-2 button-action--arrow-option'
|
||||
|
||||
@@ -102,10 +102,6 @@
|
||||
padding: 0.5rem 0.75rem 0.5rem 2rem !important;
|
||||
}
|
||||
|
||||
.bg--danger {
|
||||
color: var(--danger) !important;
|
||||
}
|
||||
|
||||
.form-control--search {
|
||||
box-shadow: 0 1px 0 #ddd;
|
||||
padding: 0 2.5rem;
|
||||
@@ -230,6 +226,12 @@
|
||||
height: 1.6rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.button-action__container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.button-action__container--detailed {
|
||||
bottom: 1.3rem;
|
||||
}
|
||||
@@ -310,16 +312,34 @@
|
||||
border: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button-action--arrow-option:hover,
|
||||
.button-action--arrow-option:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.button-action--arrow-option:focus-visible {
|
||||
outline: 2px solid #295a9f;
|
||||
}
|
||||
|
||||
.button-action--arrow-option:disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tooltip-custom__container .button-action--arrow-option {
|
||||
padding-bottom: 0;
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tooltip-custom__container .button-action--arrow-option:not(:disabled):hover {
|
||||
cursor: pointer;
|
||||
background: var(--gray-f3);
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -457,3 +477,11 @@
|
||||
font-weight: normal;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.bg--danger {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.bg--green {
|
||||
color: var(--green79);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import queryString from 'query-string';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
BLOCK_ACTIONS,
|
||||
SMALL_SCREEN_SIZE,
|
||||
MEDIUM_SCREEN_SIZE,
|
||||
} from '../../helpers/constants';
|
||||
import Loading from '../ui/Loading';
|
||||
import Filters from './Filters';
|
||||
@@ -80,7 +80,7 @@ const Logs = () => {
|
||||
const search = search_url_param || filter?.search || '';
|
||||
const response_status = response_status_url_param || filter?.response_status || '';
|
||||
|
||||
const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth < SMALL_SCREEN_SIZE);
|
||||
const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth <= MEDIUM_SCREEN_SIZE);
|
||||
const [detailedDataCurrent, setDetailedDataCurrent] = useState({});
|
||||
const [buttonType, setButtonType] = useState(BLOCK_ACTIONS.BLOCK);
|
||||
const [isModalOpened, setModalOpened] = useState(false);
|
||||
@@ -99,7 +99,7 @@ const Logs = () => {
|
||||
})();
|
||||
}, [response_status, search]);
|
||||
|
||||
const mediaQuery = window.matchMedia(`(max-width: ${SMALL_SCREEN_SIZE}px)`);
|
||||
const mediaQuery = window.matchMedia(`(max-width: ${MEDIUM_SCREEN_SIZE}px)`);
|
||||
const mediaQueryHandler = (e) => {
|
||||
setIsSmallScreen(e.matches);
|
||||
if (e.matches) {
|
||||
|
||||
@@ -11,16 +11,16 @@ const Examples = (props) => (
|
||||
<code>94.140.14.140</code>: {props.t('example_upstream_regular')}
|
||||
</li>
|
||||
<li>
|
||||
<code>udp://dns-unfiltered.adguard.com</code>: <Trans>example_upstream_udp</Trans>
|
||||
<code>udp://unfiltered.adguard-dns.com</code>: <Trans>example_upstream_udp</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<code>tcp://94.140.14.140</code>: <Trans>example_upstream_tcp</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<code>tcp://dns-unfiltered.adguard.com</code>: <Trans>example_upstream_tcp_hostname</Trans>
|
||||
<code>tcp://unfiltered.adguard-dns.com</code>: <Trans>example_upstream_tcp_hostname</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<code>tls://dns-unfiltered.adguard.com</code>:
|
||||
<code>tls://unfiltered.adguard-dns.com</code>:
|
||||
<span>
|
||||
<Trans
|
||||
components={[
|
||||
@@ -39,7 +39,7 @@ const Examples = (props) => (
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<code>https://dns-unfiltered.adguard.com/dns-query</code>:
|
||||
<code>https://unfiltered.adguard-dns.com/dns-query</code>:
|
||||
<span>
|
||||
<Trans
|
||||
components={[
|
||||
@@ -58,12 +58,12 @@ const Examples = (props) => (
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<code>quic://dns-unfiltered.adguard.com:784</code>:
|
||||
<code>quic://unfiltered.adguard-dns.com:784</code>:
|
||||
<span>
|
||||
<Trans
|
||||
components={[
|
||||
<a
|
||||
href="https://tools.ietf.org/html/draft-huitema-quic-dnsoquic-07"
|
||||
href="https://datatracker.ietf.org/doc/html/rfc9250"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="0"
|
||||
|
||||
@@ -149,7 +149,7 @@ const Form = ({
|
||||
{' '}
|
||||
<Trans components={[
|
||||
<a
|
||||
href="https://kb.adguard.com/general/dns-providers"
|
||||
href="https://link.adtidy.org/forward.html?action=dns_kb_providers&from=ui&app=home"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="0"
|
||||
|
||||
@@ -44,7 +44,7 @@ const Footer = () => {
|
||||
const renderCopyright = () => <div className="footer__column">
|
||||
<div className="footer__copyright">
|
||||
{t('copyright')} © {getYear()}{' '}
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://adguard.com/">AdGuard</a>
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://link.adtidy.org/forward.html?action=home&from=ui&app=home">AdGuard</a>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ const getDnsPrivacyList = () => [
|
||||
components: [
|
||||
{
|
||||
key: 0,
|
||||
href: 'https://adguard.com/adguard-android/overview.html',
|
||||
href: 'https://link.adtidy.org/forward.html?action=android&from=ui&app=home',
|
||||
},
|
||||
<code key="1">text</code>,
|
||||
],
|
||||
@@ -63,7 +63,7 @@ const getDnsPrivacyList = () => [
|
||||
components: [
|
||||
{
|
||||
key: 0,
|
||||
href: 'https://adguard.com/adguard-ios/overview.html',
|
||||
href: 'https://link.adtidy.org/forward.html?action=ios&from=ui&app=home',
|
||||
},
|
||||
<code key="1">text</code>,
|
||||
],
|
||||
|
||||
@@ -60,7 +60,7 @@ export const REPOSITORY = {
|
||||
export const CLIENT_ID_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#clientid';
|
||||
export const MANUAL_UPDATE_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#manual-update';
|
||||
export const PORT_53_FAQ_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#bindinuse';
|
||||
export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html';
|
||||
export const PRIVACY_POLICY_LINK = 'https://link.adtidy.org/forward.html?action=privacy&from=ui&app=home';
|
||||
export const UPSTREAM_CONFIGURATION_WIKI_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#upstreams';
|
||||
|
||||
export const FILTERS_RELATIVE_LINK = '#filters';
|
||||
@@ -588,7 +588,7 @@ export const FORM_NAME = {
|
||||
};
|
||||
|
||||
export const SMALL_SCREEN_SIZE = 767;
|
||||
export const MEDIUM_SCREEN_SIZE = 1023;
|
||||
export const MEDIUM_SCREEN_SIZE = 1024;
|
||||
|
||||
export const SECONDS_IN_DAY = 60 * 60 * 24;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import langDetect from 'i18next-browser-languagedetector';
|
||||
|
||||
import { LANGUAGES, BASE_LOCALE } from './helpers/twosky';
|
||||
|
||||
import ar from './__locales/ar.json';
|
||||
import be from './__locales/be.json';
|
||||
import bg from './__locales/bg.json';
|
||||
import cs from './__locales/cs.json';
|
||||
@@ -42,6 +43,7 @@ import zhTW from './__locales/zh-tw.json';
|
||||
import { setHtmlLangAttr } from './helpers/helpers';
|
||||
|
||||
const resources = {
|
||||
ar: { translation: ar },
|
||||
be: { translation: be },
|
||||
bg: { translation: bg },
|
||||
cs: { translation: cs },
|
||||
|
||||
41
go.mod
41
go.mod
@@ -1,38 +1,39 @@
|
||||
module github.com/AdguardTeam/AdGuardHome
|
||||
|
||||
go 1.17
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.43.1
|
||||
github.com/AdguardTeam/golibs v0.10.8
|
||||
github.com/AdguardTeam/golibs v0.10.9
|
||||
github.com/AdguardTeam/urlfilter v0.16.0
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/ameshkov/dnscrypt/v2 v2.2.3
|
||||
github.com/digineo/go-ipset/v2 v2.2.1
|
||||
github.com/dimfeld/httptreemux/v5 v5.4.0
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/go-ping/ping v1.1.0
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/renameio v1.0.1
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f
|
||||
github.com/kardianos/service v1.2.1
|
||||
github.com/lucas-clemente/quic-go v0.27.1
|
||||
github.com/lucas-clemente/quic-go v0.28.1
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
||||
github.com/mdlayher/netlink v1.6.0
|
||||
// TODO(a.garipov): This package is deprecated; find a new one or use
|
||||
// our own code for that.
|
||||
github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b
|
||||
github.com/miekg/dns v1.1.49
|
||||
github.com/stretchr/testify v1.7.0
|
||||
// our own code for that. Perhaps, use gopacket.
|
||||
github.com/mdlayher/raw v0.1.0
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/ti-mo/netfilter v0.4.0
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
||||
golang.org/x/net v0.0.0-20220728211354-c7608f3a8462
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
howett.net/plist v1.0.0
|
||||
)
|
||||
|
||||
@@ -47,8 +48,10 @@ require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/josharian/native v1.0.0 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1 // indirect
|
||||
github.com/mdlayher/packet v1.0.0 // indirect
|
||||
github.com/mdlayher/socket v0.2.3 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
@@ -58,10 +61,8 @@ require (
|
||||
github.com/stretchr/objx v0.1.1 // indirect
|
||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
85
go.sum
85
go.sum
@@ -12,8 +12,8 @@ github.com/AdguardTeam/dnsproxy v0.43.1/go.mod h1:JUGTm5dmlll47JltztsT0N//pVJjdg
|
||||
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.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
||||
github.com/AdguardTeam/golibs v0.10.8 h1:diU9gP9qG1qeLbAkzIwfUerpHSqzR6zaBgzvRMR/m6Q=
|
||||
github.com/AdguardTeam/golibs v0.10.8/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
||||
github.com/AdguardTeam/golibs v0.10.9 h1:F9oP2da0dQ9RQDM1lGR7LxUTfUWu8hEFOs4icwAkKM0=
|
||||
github.com/AdguardTeam/golibs v0.10.9/go.mod h1:W+5rznZa1cSNSFt+gPS7f4Wytnr9fOrd5ZYqwadPw14=
|
||||
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
||||
github.com/AdguardTeam/urlfilter v0.16.0 h1:IO29m+ZyQuuOnPLTzHuXj35V1DZOp1Dcryl576P2syg=
|
||||
github.com/AdguardTeam/urlfilter v0.16.0/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI=
|
||||
@@ -34,7 +34,6 @@ github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaE
|
||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
||||
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 h1:0b2vaepXIfMsG++IsjHiI2p4bxALD1Y2nQKGMR5zDQM=
|
||||
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -58,7 +57,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@@ -66,8 +64,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4=
|
||||
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
||||
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -97,8 +95,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
@@ -118,11 +117,10 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 h1:Yg3n3AI7GoHnWt7dyjsLPU+TEuZfPAg0OdiA3MJUV6I=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f h1:l1QCwn715k8nYkj4Ql50rzEog3WnMdrd4YYMMwemxEo=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
@@ -141,17 +139,19 @@ 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.27.1 h1:sOw+4kFSVrdWOYmUjufQ9GBVPqZ+tu+jMtXxXNmRJyk=
|
||||
github.com/lucas-clemente/quic-go v0.27.1/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI=
|
||||
github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU=
|
||||
github.com/lucas-clemente/quic-go v0.28.1/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0=
|
||||
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=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1 h1:7m/WlWcSROrcK5NxuXaxYD32BZqe/LEEnBrWcH/cOqQ=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE=
|
||||
@@ -164,11 +164,12 @@ github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZ
|
||||
github.com/mdlayher/netlink v1.1.2-0.20201013204415-ded538f7f4be/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
|
||||
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
|
||||
github.com/mdlayher/packet v1.0.0 h1:InhZJbdShQYt6XV2GPj5XHxChzOfhJJOMbvnGAmOfQ8=
|
||||
github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A=
|
||||
github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
|
||||
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||
github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM=
|
||||
@@ -176,9 +177,8 @@ github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaU
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.44/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/miekg/dns v1.1.49 h1:qe0mQU3Z/XpFeE+AEBo2rqaS1IPBJ3anmqZ4XiZJVG8=
|
||||
github.com/miekg/dns v1.1.49/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
@@ -248,8 +248,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/ti-mo/netfilter v0.2.0/go.mod h1:8GbBGsY/8fxtyIdfwy29JiluNcPK4K7wIT+x42ipqUU=
|
||||
github.com/ti-mo/netfilter v0.4.0 h1:rTN1nBYULDmMfDeBHZpKuNKX/bWEXQUhe02a/10orzg=
|
||||
@@ -265,7 +266,6 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
@@ -278,11 +278,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -290,7 +290,6 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -325,12 +324,10 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220728211354-c7608f3a8462 h1:UreQrH7DbFXSi9ZFox6FNT3WBooWmdANpU+IfkT1T4I=
|
||||
golang.org/x/net v0.0.0-20220728211354-c7608f3a8462/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -342,8 +339,9 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -377,7 +375,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -387,14 +384,13 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -419,15 +415,12 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12 h1:pODAJF0uBqx6zFa1MYaiTobVo5FzCbnTVUXeO8o71fE=
|
||||
golang.org/x/tools v0.1.11-0.20220426200323-dcaea06afc12/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
@@ -472,8 +465,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
// Package aghalg contains common generic algorithms and data structures.
|
||||
//
|
||||
// TODO(a.garipov): Update to use type parameters in Go 1.18.
|
||||
// TODO(a.garipov): Move parts of this into golibs.
|
||||
package aghalg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// comparable is an alias for interface{}. Values passed as arguments of this
|
||||
// type alias must be comparable.
|
||||
//
|
||||
// TODO(a.garipov): Remove in Go 1.18.
|
||||
type comparable = interface{}
|
||||
// Coalesce returns the first non-zero value. It is named after the function
|
||||
// COALESCE in SQL. If values or all its elements are empty, it returns a zero
|
||||
// value.
|
||||
func Coalesce[T comparable](values ...T) (res T) {
|
||||
var zero T
|
||||
for _, v := range values {
|
||||
if v != zero {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return zero
|
||||
}
|
||||
|
||||
// UniqChecker allows validating uniqueness of comparable items.
|
||||
type UniqChecker map[comparable]int64
|
||||
//
|
||||
// TODO(a.garipov): The Ordered constraint is only really necessary in Validate.
|
||||
// Consider ways of making this constraint comparable instead.
|
||||
type UniqChecker[T constraints.Ordered] map[T]int64
|
||||
|
||||
// Add adds a value to the validator. v must not be nil.
|
||||
func (uc UniqChecker) Add(elems ...comparable) {
|
||||
func (uc UniqChecker[T]) Add(elems ...T) {
|
||||
for _, e := range elems {
|
||||
uc[e]++
|
||||
}
|
||||
}
|
||||
|
||||
// Merge returns a checker containing data from both uc and other.
|
||||
func (uc UniqChecker) Merge(other UniqChecker) (merged UniqChecker) {
|
||||
merged = make(UniqChecker, len(uc)+len(other))
|
||||
func (uc UniqChecker[T]) Merge(other UniqChecker[T]) (merged UniqChecker[T]) {
|
||||
merged = make(UniqChecker[T], len(uc)+len(other))
|
||||
for elem, num := range uc {
|
||||
merged[elem] += num
|
||||
}
|
||||
@@ -39,10 +52,8 @@ func (uc UniqChecker) Merge(other UniqChecker) (merged UniqChecker) {
|
||||
}
|
||||
|
||||
// Validate returns an error enumerating all elements that aren't unique.
|
||||
// isBefore is an optional sorting function to make the error message
|
||||
// deterministic.
|
||||
func (uc UniqChecker) Validate(isBefore func(a, b comparable) (less bool)) (err error) {
|
||||
var dup []comparable
|
||||
func (uc UniqChecker[T]) Validate() (err error) {
|
||||
var dup []T
|
||||
for elem, num := range uc {
|
||||
if num > 1 {
|
||||
dup = append(dup, elem)
|
||||
@@ -53,23 +64,7 @@ func (uc UniqChecker) Validate(isBefore func(a, b comparable) (less bool)) (err
|
||||
return nil
|
||||
}
|
||||
|
||||
if isBefore != nil {
|
||||
sort.Slice(dup, func(i, j int) (less bool) {
|
||||
return isBefore(dup[i], dup[j])
|
||||
})
|
||||
}
|
||||
slices.Sort(dup)
|
||||
|
||||
return fmt.Errorf("duplicated values: %v", dup)
|
||||
}
|
||||
|
||||
// IntIsBefore is a helper sort function for UniqChecker.Validate.
|
||||
// a and b must be of type int.
|
||||
func IntIsBefore(a, b comparable) (less bool) {
|
||||
return a.(int) < b.(int)
|
||||
}
|
||||
|
||||
// StringIsBefore is a helper sort function for UniqChecker.Validate.
|
||||
// a and b must be of type string.
|
||||
func StringIsBefore(a, b comparable) (less bool) {
|
||||
return a.(string) < b.(string)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
// RegisterFunc is the function that sets the handler to handle the URL for the
|
||||
// method.
|
||||
//
|
||||
// TODO(e.burkov, a.garipov): Get rid of it.
|
||||
type RegisterFunc func(method, url string, handler http.HandlerFunc)
|
||||
|
||||
// OK responds with word OK.
|
||||
func OK(w http.ResponseWriter) {
|
||||
if _, err := io.WriteString(w, "OK\n"); err != nil {
|
||||
@@ -17,7 +23,7 @@ func OK(w http.ResponseWriter) {
|
||||
}
|
||||
|
||||
// Error writes formatted message to w and also logs it.
|
||||
func Error(r *http.Request, w http.ResponseWriter, code int, format string, args ...interface{}) {
|
||||
func Error(r *http.Request, w http.ResponseWriter, code int, format string, args ...any) {
|
||||
text := fmt.Sprintf(format, args...)
|
||||
log.Error("%s %s: %s", r.Method, r.URL, text)
|
||||
http.Error(w, text, code)
|
||||
|
||||
@@ -455,8 +455,8 @@ func (hp *hostsParser) equalSet(target *netutil.IPMap) (ok bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
hp.table.Range(func(ip net.IP, recVal interface{}) (cont bool) {
|
||||
var targetVal interface{}
|
||||
hp.table.Range(func(ip net.IP, recVal any) (cont bool) {
|
||||
var targetVal any
|
||||
targetVal, ok = target.Get(ip)
|
||||
if !ok {
|
||||
return false
|
||||
|
||||
@@ -470,7 +470,7 @@ func TestHostsContainer(t *testing.T) {
|
||||
}},
|
||||
}, {
|
||||
req: &urlfilter.DNSRequest{
|
||||
Hostname: "nonexisting",
|
||||
Hostname: "nonexistent.example",
|
||||
DNSType: dns.TypeA,
|
||||
},
|
||||
name: "non-existing",
|
||||
|
||||
@@ -154,10 +154,13 @@ func GetValidNetInterfacesForWeb() (netIfaces []*NetInterface, err error) {
|
||||
return netIfaces, nil
|
||||
}
|
||||
|
||||
// GetInterfaceByIP returns the name of interface containing provided ip.
|
||||
// InterfaceByIP returns the name of the interface bound to ip.
|
||||
//
|
||||
// TODO(e.burkov): See TODO on GetValidInterfacesForWeb.
|
||||
func GetInterfaceByIP(ip net.IP) string {
|
||||
// TODO(a.garipov, e.burkov): This function is technically incorrect, since one
|
||||
// IP address can be shared by multiple interfaces in some configurations.
|
||||
//
|
||||
// TODO(e.burkov): See TODO on GetValidNetInterfacesForWeb.
|
||||
func InterfaceByIP(ip net.IP) (ifaceName string) {
|
||||
ifaces, err := GetValidNetInterfacesForWeb()
|
||||
if err != nil {
|
||||
return ""
|
||||
@@ -177,7 +180,7 @@ func GetInterfaceByIP(ip net.IP) string {
|
||||
// GetSubnet returns pointer to net.IPNet for the specified interface or nil if
|
||||
// the search fails.
|
||||
//
|
||||
// TODO(e.burkov): See TODO on GetValidInterfacesForWeb.
|
||||
// TODO(e.burkov): See TODO on GetValidNetInterfacesForWeb.
|
||||
func GetSubnet(ifaceName string) *net.IPNet {
|
||||
netIfaces, err := GetValidNetInterfacesForWeb()
|
||||
if err != nil {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/google/renameio/maybe"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -22,17 +23,27 @@ import (
|
||||
const dhcpcdConf = "etc/dhcpcd.conf"
|
||||
|
||||
func canBindPrivilegedPorts() (can bool, err error) {
|
||||
cnbs, err := unix.PrctlRetInt(
|
||||
res, err := unix.PrctlRetInt(
|
||||
unix.PR_CAP_AMBIENT,
|
||||
unix.PR_CAP_AMBIENT_IS_SET,
|
||||
unix.CAP_NET_BIND_SERVICE,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, unix.EINVAL) {
|
||||
// Older versions of Linux kernel do not support this. Print a
|
||||
// warning and check admin rights.
|
||||
log.Info("warning: cannot check capability cap_net_bind_service: %s", err)
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Don't check the error because it's always nil on Linux.
|
||||
adm, _ := aghos.HaveAdminRights()
|
||||
|
||||
return cnbs == 1 || adm, err
|
||||
return res == 1 || adm, nil
|
||||
}
|
||||
|
||||
// dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to
|
||||
|
||||
@@ -132,7 +132,7 @@ func TestGatewayIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInterfaceByIP(t *testing.T) {
|
||||
func TestInterfaceByIP(t *testing.T) {
|
||||
ifaces, err := GetValidNetInterfacesForWeb()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, ifaces)
|
||||
@@ -142,7 +142,7 @@ func TestGetInterfaceByIP(t *testing.T) {
|
||||
require.NotEmpty(t, iface.Addresses)
|
||||
|
||||
for _, ip := range iface.Addresses {
|
||||
ifaceName := GetInterfaceByIP(ip)
|
||||
ifaceName := InterfaceByIP(ip)
|
||||
require.Equal(t, iface.Name, ifaceName)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package aghos
|
||||
package aghos_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
57
internal/aghos/filewalker_internal_test.go
Normal file
57
internal/aghos/filewalker_internal_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package aghos
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"path"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// errFS is an fs.FS implementation, method Open of which always returns
|
||||
// errFSOpen.
|
||||
type errFS struct{}
|
||||
|
||||
// errFSOpen is returned from errGlobFS.Open.
|
||||
const errFSOpen errors.Error = "test open error"
|
||||
|
||||
// Open implements the fs.FS interface for *errGlobFS. fsys is always nil and
|
||||
// err is always errFSOpen.
|
||||
func (efs *errFS) Open(name string) (fsys fs.File, err error) {
|
||||
return nil, errFSOpen
|
||||
}
|
||||
|
||||
func TestWalkerFunc_CheckFile(t *testing.T) {
|
||||
emptyFS := fstest.MapFS{}
|
||||
|
||||
t.Run("non-existing", func(t *testing.T) {
|
||||
_, ok, err := checkFile(emptyFS, nil, "lol")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("invalid_argument", func(t *testing.T) {
|
||||
_, ok, err := checkFile(&errFS{}, nil, "")
|
||||
require.ErrorIs(t, err, errFSOpen)
|
||||
|
||||
assert.False(t, ok)
|
||||
})
|
||||
|
||||
t.Run("ignore_dirs", func(t *testing.T) {
|
||||
const dirName = "dir"
|
||||
|
||||
testFS := fstest.MapFS{
|
||||
path.Join(dirName, "file"): &fstest.MapFile{Data: []byte{}},
|
||||
}
|
||||
|
||||
patterns, ok, err := checkFile(testFS, nil, dirName)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Empty(t, patterns)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package aghos
|
||||
package aghos_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
func TestFileWalker_Walk(t *testing.T) {
|
||||
const attribute = `000`
|
||||
|
||||
makeFileWalker := func(_ string) (fw FileWalker) {
|
||||
makeFileWalker := func(_ string) (fw aghos.FileWalker) {
|
||||
return func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||
s := bufio.NewScanner(r)
|
||||
for s.Scan() {
|
||||
@@ -113,7 +113,7 @@ func TestFileWalker_Walk(t *testing.T) {
|
||||
f := fstest.MapFS{
|
||||
filename: &fstest.MapFile{Data: []byte("[]")},
|
||||
}
|
||||
ok, err := FileWalker(func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||
ok, err := aghos.FileWalker(func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||
s := bufio.NewScanner(r)
|
||||
for s.Scan() {
|
||||
patterns = append(patterns, s.Text())
|
||||
@@ -134,7 +134,7 @@ func TestFileWalker_Walk(t *testing.T) {
|
||||
"mockfile.txt": &fstest.MapFile{Data: []byte(`mockdata`)},
|
||||
}
|
||||
|
||||
ok, err := FileWalker(func(r io.Reader) (patterns []string, ok bool, err error) {
|
||||
ok, err := aghos.FileWalker(func(r io.Reader) (patterns []string, ok bool, err error) {
|
||||
return nil, true, rerr
|
||||
}).Walk(f, "*")
|
||||
require.ErrorIs(t, err, rerr)
|
||||
@@ -142,45 +142,3 @@ func TestFileWalker_Walk(t *testing.T) {
|
||||
assert.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
type errFS struct {
|
||||
fs.GlobFS
|
||||
}
|
||||
|
||||
const errErrFSOpen errors.Error = "this error is always returned"
|
||||
|
||||
func (efs *errFS) Open(name string) (fs.File, error) {
|
||||
return nil, errErrFSOpen
|
||||
}
|
||||
|
||||
func TestWalkerFunc_CheckFile(t *testing.T) {
|
||||
emptyFS := fstest.MapFS{}
|
||||
|
||||
t.Run("non-existing", func(t *testing.T) {
|
||||
_, ok, err := checkFile(emptyFS, nil, "lol")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("invalid_argument", func(t *testing.T) {
|
||||
_, ok, err := checkFile(&errFS{}, nil, "")
|
||||
require.ErrorIs(t, err, errErrFSOpen)
|
||||
|
||||
assert.False(t, ok)
|
||||
})
|
||||
|
||||
t.Run("ignore_dirs", func(t *testing.T) {
|
||||
const dirName = "dir"
|
||||
|
||||
testFS := fstest.MapFS{
|
||||
path.Join(dirName, "file"): &fstest.MapFile{Data: []byte{}},
|
||||
}
|
||||
|
||||
patterns, ok, err := checkFile(testFS, nil, dirName)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Empty(t, patterns)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package aghtest
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Exchanger is a mock aghnet.Exchanger implementation for tests.
|
||||
type Exchanger struct {
|
||||
Ups upstream.Upstream
|
||||
}
|
||||
|
||||
// Exchange implements aghnet.Exchanger interface for *Exchanger.
|
||||
func (e *Exchanger) Exchange(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
if e.Ups == nil {
|
||||
e.Ups = &TestErrUpstream{}
|
||||
}
|
||||
|
||||
return e.Ups.Exchange(req)
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package aghtest
|
||||
|
||||
// FSWatcher is a mock aghos.FSWatcher implementation to use in tests.
|
||||
type FSWatcher struct {
|
||||
OnEvents func() (e <-chan struct{})
|
||||
OnAdd func(name string) (err error)
|
||||
OnClose func() (err error)
|
||||
}
|
||||
|
||||
// Events implements the aghos.FSWatcher interface for *FSWatcher.
|
||||
func (w *FSWatcher) Events() (e <-chan struct{}) {
|
||||
return w.OnEvents()
|
||||
}
|
||||
|
||||
// Add implements the aghos.FSWatcher interface for *FSWatcher.
|
||||
func (w *FSWatcher) Add(name string) (err error) {
|
||||
return w.OnAdd(name)
|
||||
}
|
||||
|
||||
// Close implements the aghos.FSWatcher interface for *FSWatcher.
|
||||
func (w *FSWatcher) Close() (err error) {
|
||||
return w.OnClose()
|
||||
}
|
||||
135
internal/aghtest/interface.go
Normal file
135
internal/aghtest/interface.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package aghtest
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Interface Mocks
|
||||
//
|
||||
// Keep entities in this file in alphabetic order.
|
||||
|
||||
// Standard Library
|
||||
|
||||
// type check
|
||||
var _ fs.FS = &FS{}
|
||||
|
||||
// FS is a mock [fs.FS] implementation for tests.
|
||||
type FS struct {
|
||||
OnOpen func(name string) (fs.File, error)
|
||||
}
|
||||
|
||||
// Open implements the [fs.FS] interface for *FS.
|
||||
func (fsys *FS) Open(name string) (fs.File, error) {
|
||||
return fsys.OnOpen(name)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ fs.GlobFS = &GlobFS{}
|
||||
|
||||
// GlobFS is a mock [fs.GlobFS] implementation for tests.
|
||||
type GlobFS struct {
|
||||
// FS is embedded here to avoid implementing all it's methods.
|
||||
FS
|
||||
OnGlob func(pattern string) ([]string, error)
|
||||
}
|
||||
|
||||
// Glob implements the [fs.GlobFS] interface for *GlobFS.
|
||||
func (fsys *GlobFS) Glob(pattern string) ([]string, error) {
|
||||
return fsys.OnGlob(pattern)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ fs.StatFS = &StatFS{}
|
||||
|
||||
// StatFS is a mock [fs.StatFS] implementation for tests.
|
||||
type StatFS struct {
|
||||
// FS is embedded here to avoid implementing all it's methods.
|
||||
FS
|
||||
OnStat func(name string) (fs.FileInfo, error)
|
||||
}
|
||||
|
||||
// Stat implements the [fs.StatFS] interface for *StatFS.
|
||||
func (fsys *StatFS) Stat(name string) (fs.FileInfo, error) {
|
||||
return fsys.OnStat(name)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ net.Listener = (*Listener)(nil)
|
||||
|
||||
// Listener is a mock [net.Listener] implementation for tests.
|
||||
type Listener struct {
|
||||
OnAccept func() (conn net.Conn, err error)
|
||||
OnAddr func() (addr net.Addr)
|
||||
OnClose func() (err error)
|
||||
}
|
||||
|
||||
// Accept implements the [net.Listener] interface for *Listener.
|
||||
func (l *Listener) Accept() (conn net.Conn, err error) {
|
||||
return l.OnAccept()
|
||||
}
|
||||
|
||||
// Addr implements the [net.Listener] interface for *Listener.
|
||||
func (l *Listener) Addr() (addr net.Addr) {
|
||||
return l.OnAddr()
|
||||
}
|
||||
|
||||
// Close implements the [net.Listener] interface for *Listener.
|
||||
func (l *Listener) Close() (err error) {
|
||||
return l.OnClose()
|
||||
}
|
||||
|
||||
// Module dnsproxy
|
||||
|
||||
// type check
|
||||
var _ upstream.Upstream = (*UpstreamMock)(nil)
|
||||
|
||||
// UpstreamMock is a mock [upstream.Upstream] implementation for tests.
|
||||
//
|
||||
// TODO(a.garipov): Replace with all uses of Upstream with UpstreamMock and
|
||||
// rename it to just Upstream.
|
||||
type UpstreamMock struct {
|
||||
OnAddress func() (addr string)
|
||||
OnExchange func(req *dns.Msg) (resp *dns.Msg, err error)
|
||||
}
|
||||
|
||||
// Address implements the [upstream.Upstream] interface for *UpstreamMock.
|
||||
func (u *UpstreamMock) Address() (addr string) {
|
||||
return u.OnAddress()
|
||||
}
|
||||
|
||||
// Exchange implements the [upstream.Upstream] interface for *UpstreamMock.
|
||||
func (u *UpstreamMock) Exchange(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return u.OnExchange(req)
|
||||
}
|
||||
|
||||
// Module AdGuardHome
|
||||
|
||||
// type check
|
||||
var _ aghos.FSWatcher = (*FSWatcher)(nil)
|
||||
|
||||
// FSWatcher is a mock [aghos.FSWatcher] implementation for tests.
|
||||
type FSWatcher struct {
|
||||
OnEvents func() (e <-chan struct{})
|
||||
OnAdd func(name string) (err error)
|
||||
OnClose func() (err error)
|
||||
}
|
||||
|
||||
// Events implements the [aghos.FSWatcher] interface for *FSWatcher.
|
||||
func (w *FSWatcher) Events() (e <-chan struct{}) {
|
||||
return w.OnEvents()
|
||||
}
|
||||
|
||||
// Add implements the [aghos.FSWatcher] interface for *FSWatcher.
|
||||
func (w *FSWatcher) Add(name string) (err error) {
|
||||
return w.OnAdd(name)
|
||||
}
|
||||
|
||||
// Close implements the [aghos.FSWatcher] interface for *FSWatcher.
|
||||
func (w *FSWatcher) Close() (err error) {
|
||||
return w.OnClose()
|
||||
}
|
||||
9
internal/aghtest/interface_test.go
Normal file
9
internal/aghtest/interface_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package aghtest_test
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
)
|
||||
|
||||
// type check
|
||||
var _ aghos.FSWatcher = (*aghtest.FSWatcher)(nil)
|
||||
@@ -1,46 +0,0 @@
|
||||
package aghtest
|
||||
|
||||
import "io/fs"
|
||||
|
||||
// type check
|
||||
var _ fs.FS = &FS{}
|
||||
|
||||
// FS is a mock fs.FS implementation to use in tests.
|
||||
type FS struct {
|
||||
OnOpen func(name string) (fs.File, error)
|
||||
}
|
||||
|
||||
// Open implements the fs.FS interface for *FS.
|
||||
func (fsys *FS) Open(name string) (fs.File, error) {
|
||||
return fsys.OnOpen(name)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ fs.StatFS = &StatFS{}
|
||||
|
||||
// StatFS is a mock fs.StatFS implementation to use in tests.
|
||||
type StatFS struct {
|
||||
// FS is embedded here to avoid implementing all it's methods.
|
||||
FS
|
||||
OnStat func(name string) (fs.FileInfo, error)
|
||||
}
|
||||
|
||||
// Stat implements the fs.StatFS interface for *StatFS.
|
||||
func (fsys *StatFS) Stat(name string) (fs.FileInfo, error) {
|
||||
return fsys.OnStat(name)
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ fs.GlobFS = &GlobFS{}
|
||||
|
||||
// GlobFS is a mock fs.GlobFS implementation to use in tests.
|
||||
type GlobFS struct {
|
||||
// FS is embedded here to avoid implementing all it's methods.
|
||||
FS
|
||||
OnGlob func(pattern string) ([]string, error)
|
||||
}
|
||||
|
||||
// Glob implements the fs.GlobFS interface for *GlobFS.
|
||||
func (fsys *GlobFS) Glob(pattern string) ([]string, error) {
|
||||
return fsys.OnGlob(pattern)
|
||||
}
|
||||
@@ -6,12 +6,18 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Additional Upstream Testing Utilities
|
||||
|
||||
// Upstream is a mock implementation of upstream.Upstream.
|
||||
//
|
||||
// TODO(a.garipov): Replace with UpstreamMock and rename it to just Upstream.
|
||||
type Upstream struct {
|
||||
// CName is a map of hostname to canonical name.
|
||||
CName map[string][]string
|
||||
@@ -25,6 +31,43 @@ type Upstream struct {
|
||||
Addr string
|
||||
}
|
||||
|
||||
// RespondTo returns a response with answer if req has class cl, question type
|
||||
// qt, and target targ.
|
||||
func RespondTo(t testing.TB, req *dns.Msg, cl, qt uint16, targ, answer string) (resp *dns.Msg) {
|
||||
t.Helper()
|
||||
|
||||
require.NotNil(t, req)
|
||||
require.Len(t, req.Question, 1)
|
||||
|
||||
q := req.Question[0]
|
||||
targ = dns.Fqdn(targ)
|
||||
if q.Qclass != cl || q.Qtype != qt || q.Name != targ {
|
||||
return nil
|
||||
}
|
||||
|
||||
respHdr := dns.RR_Header{
|
||||
Name: targ,
|
||||
Rrtype: qt,
|
||||
Class: cl,
|
||||
Ttl: 60,
|
||||
}
|
||||
|
||||
resp = new(dns.Msg).SetReply(req)
|
||||
switch qt {
|
||||
case dns.TypePTR:
|
||||
resp.Answer = []dns.RR{
|
||||
&dns.PTR{
|
||||
Hdr: respHdr,
|
||||
Ptr: answer,
|
||||
},
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unsupported question type: %s", dns.Type(qt))
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// Exchange implements the upstream.Upstream interface for *Upstream.
|
||||
//
|
||||
// TODO(a.garipov): Split further into handlers.
|
||||
@@ -76,74 +119,57 @@ func (u *Upstream) Address() string {
|
||||
return u.Addr
|
||||
}
|
||||
|
||||
// TestBlockUpstream implements upstream.Upstream interface for replacing real
|
||||
// upstream in tests.
|
||||
type TestBlockUpstream struct {
|
||||
Hostname string
|
||||
|
||||
// lock protects reqNum.
|
||||
lock sync.RWMutex
|
||||
reqNum int
|
||||
|
||||
Block bool
|
||||
}
|
||||
|
||||
// Exchange returns a message unique for TestBlockUpstream's Hostname-Block
|
||||
// pair.
|
||||
func (u *TestBlockUpstream) Exchange(r *dns.Msg) (*dns.Msg, error) {
|
||||
u.lock.Lock()
|
||||
defer u.lock.Unlock()
|
||||
u.reqNum++
|
||||
|
||||
hash := sha256.Sum256([]byte(u.Hostname))
|
||||
hashToReturn := hex.EncodeToString(hash[:])
|
||||
if !u.Block {
|
||||
hashToReturn = hex.EncodeToString(hash[:])[:2] + strings.Repeat("ab", 28)
|
||||
// NewBlockUpstream returns an [*UpstreamMock] that works like an upstream that
|
||||
// supports hash-based safe-browsing/adult-blocking feature. If shouldBlock is
|
||||
// true, hostname's actual hash is returned, blocking it. Otherwise, it returns
|
||||
// a different hash.
|
||||
func NewBlockUpstream(hostname string, shouldBlock bool) (u *UpstreamMock) {
|
||||
hash := sha256.Sum256([]byte(hostname))
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
if !shouldBlock {
|
||||
hashStr = hex.EncodeToString(hash[:])[:2] + strings.Repeat("ab", 28)
|
||||
}
|
||||
|
||||
m := &dns.Msg{}
|
||||
m.SetReply(r)
|
||||
m.Answer = []dns.RR{
|
||||
&dns.TXT{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: r.Question[0].Name,
|
||||
},
|
||||
Txt: []string{
|
||||
hashToReturn,
|
||||
},
|
||||
ans := &dns.TXT{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: "",
|
||||
Rrtype: dns.TypeTXT,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 60,
|
||||
},
|
||||
Txt: []string{hashStr},
|
||||
}
|
||||
respTmpl := &dns.Msg{
|
||||
Answer: []dns.RR{ans},
|
||||
}
|
||||
|
||||
return &UpstreamMock{
|
||||
OnAddress: func() (addr string) {
|
||||
return "sbpc.upstream.example"
|
||||
},
|
||||
OnExchange: func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = respTmpl.Copy()
|
||||
resp.SetReply(req)
|
||||
resp.Answer[0].(*dns.TXT).Hdr.Name = req.Question[0].Name
|
||||
|
||||
return resp, nil
|
||||
},
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Address always returns an empty string.
|
||||
func (u *TestBlockUpstream) Address() string {
|
||||
return ""
|
||||
}
|
||||
// ErrUpstream is the error returned from the [*UpstreamMock] created by
|
||||
// [NewErrorUpstream].
|
||||
const ErrUpstream errors.Error = "test upstream error"
|
||||
|
||||
// RequestsCount returns the number of handled requests. It's safe for
|
||||
// concurrent use.
|
||||
func (u *TestBlockUpstream) RequestsCount() int {
|
||||
u.lock.Lock()
|
||||
defer u.lock.Unlock()
|
||||
|
||||
return u.reqNum
|
||||
}
|
||||
|
||||
// TestErrUpstream implements upstream.Upstream interface for replacing real
|
||||
// upstream in tests.
|
||||
type TestErrUpstream struct {
|
||||
// The error returned by Exchange may be unwrapped to the Err.
|
||||
Err error
|
||||
}
|
||||
|
||||
// Exchange always returns nil Msg and non-nil error.
|
||||
func (u *TestErrUpstream) Exchange(*dns.Msg) (*dns.Msg, error) {
|
||||
return nil, fmt.Errorf("errupstream: %w", u.Err)
|
||||
}
|
||||
|
||||
// Address always returns an empty string.
|
||||
func (u *TestErrUpstream) Address() string {
|
||||
return ""
|
||||
// NewErrorUpstream returns an [*UpstreamMock] that returns [ErrUpstream] from
|
||||
// its Exchange method.
|
||||
func NewErrorUpstream() (u *UpstreamMock) {
|
||||
return &UpstreamMock{
|
||||
OnAddress: func() (addr string) {
|
||||
return "error.upstream.example"
|
||||
},
|
||||
OnExchange: func(_ *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return nil, errors.Error("test upstream error")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4/server4"
|
||||
"github.com/mdlayher/ethernet"
|
||||
|
||||
//lint:ignore SA1019 See the TODO in go.mod.
|
||||
"github.com/mdlayher/raw"
|
||||
)
|
||||
|
||||
@@ -49,16 +51,15 @@ type dhcpConn struct {
|
||||
}
|
||||
|
||||
// newDHCPConn creates the special connection for DHCP server.
|
||||
func (s *v4Server) newDHCPConn(ifi *net.Interface) (c net.PacketConn, err error) {
|
||||
// Create the raw connection.
|
||||
func (s *v4Server) newDHCPConn(iface *net.Interface) (c net.PacketConn, err error) {
|
||||
var ucast net.PacketConn
|
||||
if ucast, err = raw.ListenPacket(ifi, uint16(ethernet.EtherTypeIPv4), nil); err != nil {
|
||||
if ucast, err = raw.ListenPacket(iface, uint16(ethernet.EtherTypeIPv4), nil); err != nil {
|
||||
return nil, fmt.Errorf("creating raw udp connection: %w", err)
|
||||
}
|
||||
|
||||
// Create the UDP connection.
|
||||
var bcast net.PacketConn
|
||||
bcast, err = server4.NewIPv4UDPConn(ifi.Name, &net.UDPAddr{
|
||||
bcast, err = server4.NewIPv4UDPConn(iface.Name, &net.UDPAddr{
|
||||
// TODO(e.burkov): Listening on zeroes makes the server handle
|
||||
// requests from all the interfaces. Inspect the ways to
|
||||
// specify the interface-specific listening addresses.
|
||||
@@ -75,7 +76,7 @@ func (s *v4Server) newDHCPConn(ifi *net.Interface) (c net.PacketConn, err error)
|
||||
udpConn: bcast,
|
||||
bcastIP: s.conf.broadcastIP,
|
||||
rawConn: ucast,
|
||||
srcMAC: ifi.HardwareAddr,
|
||||
srcMAC: iface.HardwareAddr,
|
||||
srcIP: s.conf.dnsIPAddrs[0],
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -11,9 +11,11 @@ import (
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/mdlayher/raw"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
//lint:ignore SA1019 See the TODO in go.mod.
|
||||
"github.com/mdlayher/raw"
|
||||
)
|
||||
|
||||
func TestDHCPConn_WriteTo_common(t *testing.T) {
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
)
|
||||
@@ -126,7 +126,7 @@ type ServerConfig struct {
|
||||
ConfigModified func() `yaml:"-"`
|
||||
|
||||
// Register an HTTP handler
|
||||
HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request)) `yaml:"-"`
|
||||
HTTPRegister aghhttp.RegisterFunc `yaml:"-"`
|
||||
|
||||
Enabled bool `yaml:"enabled"`
|
||||
InterfaceName string `yaml:"interface_name"`
|
||||
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"github.com/go-ping/ping"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4/server4"
|
||||
|
||||
//lint:ignore SA1019 See the TODO in go.mod.
|
||||
"github.com/mdlayher/raw"
|
||||
)
|
||||
|
||||
|
||||
@@ -12,9 +12,11 @@ import (
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/mdlayher/raw"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
//lint:ignore SA1019 See the TODO in go.mod.
|
||||
"github.com/mdlayher/raw"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -214,7 +214,7 @@ func validateAccessSet(list *accessListJSON) (err error) {
|
||||
}
|
||||
|
||||
merged := allowed.Merge(disallowed)
|
||||
err = merged.Validate(aghalg.StringIsBefore)
|
||||
err = merged.Validate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("items in allowed and disallowed clients intersect: %w", err)
|
||||
}
|
||||
@@ -223,13 +223,13 @@ func validateAccessSet(list *accessListJSON) (err error) {
|
||||
}
|
||||
|
||||
// validateStrUniq returns an informative error if clients are not unique.
|
||||
func validateStrUniq(clients []string) (uc aghalg.UniqChecker, err error) {
|
||||
uc = make(aghalg.UniqChecker, len(clients))
|
||||
func validateStrUniq(clients []string) (uc aghalg.UniqChecker[string], err error) {
|
||||
uc = make(aghalg.UniqChecker[string], len(clients))
|
||||
for _, c := range clients {
|
||||
uc.Add(c)
|
||||
}
|
||||
|
||||
return uc, uc.Validate(aghalg.StringIsBefore)
|
||||
return uc, uc.Validate()
|
||||
}
|
||||
|
||||
func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
@@ -121,6 +121,7 @@ type FilteringConfig struct {
|
||||
EnableDNSSEC bool `yaml:"enable_dnssec"` // Set AD flag in outcoming DNS request
|
||||
EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option
|
||||
MaxGoroutines uint32 `yaml:"max_goroutines"` // Max. number of parallel goroutines for processing incoming requests
|
||||
HandleDDR bool `yaml:"handle_ddr"` // Handle DDR requests
|
||||
|
||||
// IpsetList is the ipset configuration that allows AdGuard Home to add
|
||||
// IP addresses of the specified domain names to an ipset list. Syntax:
|
||||
@@ -151,7 +152,7 @@ type TLSConfig struct {
|
||||
PrivateKeyData []byte `yaml:"-" json:"-"`
|
||||
|
||||
// ServerName is the hostname of the server. Currently, it is only being
|
||||
// used for ClientID checking.
|
||||
// used for ClientID checking and Discovery of Designated Resolvers (DDR).
|
||||
ServerName string `yaml:"-" json:"-"`
|
||||
|
||||
cert tls.Certificate
|
||||
@@ -191,7 +192,7 @@ type ServerConfig struct {
|
||||
ConfigModified func()
|
||||
|
||||
// Register an HTTP handler
|
||||
HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request))
|
||||
HTTPRegister aghhttp.RegisterFunc
|
||||
|
||||
// ResolveClients signals if the RDNS should resolve clients' addresses.
|
||||
ResolveClients bool
|
||||
@@ -276,6 +277,11 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
|
||||
return proxyConfig, nil
|
||||
}
|
||||
|
||||
const (
|
||||
defaultSafeBrowsingBlockHost = "standard-block.dns.adguard.com"
|
||||
defaultParentalBlockHost = "family-block.dns.adguard.com"
|
||||
)
|
||||
|
||||
// initDefaultSettings initializes default settings if nothing
|
||||
// is configured
|
||||
func (s *Server) initDefaultSettings() {
|
||||
@@ -287,12 +293,12 @@ func (s *Server) initDefaultSettings() {
|
||||
s.conf.BootstrapDNS = defaultBootstrap
|
||||
}
|
||||
|
||||
if len(s.conf.ParentalBlockHost) == 0 {
|
||||
s.conf.ParentalBlockHost = parentalBlockHost
|
||||
if s.conf.ParentalBlockHost == "" {
|
||||
s.conf.ParentalBlockHost = defaultParentalBlockHost
|
||||
}
|
||||
|
||||
if len(s.conf.SafeBrowsingBlockHost) == 0 {
|
||||
s.conf.SafeBrowsingBlockHost = safeBrowsingBlockHost
|
||||
if s.conf.SafeBrowsingBlockHost == "" {
|
||||
s.conf.SafeBrowsingBlockHost = defaultSafeBrowsingBlockHost
|
||||
}
|
||||
|
||||
if s.conf.UDPListenAddrs == nil {
|
||||
|
||||
@@ -76,6 +76,10 @@ const (
|
||||
resultCodeError
|
||||
)
|
||||
|
||||
// ddrHostFQDN is the FQDN used in Discovery of Designated Resolvers (DDR) requests.
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html.
|
||||
const ddrHostFQDN = "_dns.resolver.arpa."
|
||||
|
||||
// handleDNSRequest filters the incoming DNS requests and writes them to the query log
|
||||
func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error {
|
||||
ctx := &dnsContext{
|
||||
@@ -94,6 +98,7 @@ func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error {
|
||||
mods := []modProcessFunc{
|
||||
s.processRecursion,
|
||||
s.processInitial,
|
||||
s.processDDRQuery,
|
||||
s.processDetermineLocal,
|
||||
s.processDHCPHosts,
|
||||
s.processRestrictLocal,
|
||||
@@ -239,6 +244,98 @@ func (s *Server) onDHCPLeaseChanged(flags int) {
|
||||
s.setTableIPToHost(ipToHost)
|
||||
}
|
||||
|
||||
// processDDRQuery responds to SVCB query for a special use domain name
|
||||
// ‘_dns.resolver.arpa’. The result contains different types of encryption
|
||||
// supported by current user configuration.
|
||||
//
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html.
|
||||
func (s *Server) processDDRQuery(ctx *dnsContext) (rc resultCode) {
|
||||
d := ctx.proxyCtx
|
||||
question := d.Req.Question[0]
|
||||
|
||||
if !s.conf.HandleDDR {
|
||||
return resultCodeSuccess
|
||||
}
|
||||
|
||||
if question.Name == ddrHostFQDN {
|
||||
if s.dnsProxy.TLSListenAddr == nil && s.conf.HTTPSListenAddrs == nil &&
|
||||
s.dnsProxy.QUICListenAddr == nil || question.Qtype != dns.TypeSVCB {
|
||||
d.Res = s.makeResponse(d.Req)
|
||||
|
||||
return resultCodeFinish
|
||||
}
|
||||
|
||||
d.Res = s.makeDDRResponse(d.Req)
|
||||
|
||||
return resultCodeFinish
|
||||
}
|
||||
|
||||
return resultCodeSuccess
|
||||
}
|
||||
|
||||
// makeDDRResponse creates DDR answer according to server configuration. The
|
||||
// contructed SVCB resource records have the priority of 1 for each entry,
|
||||
// similar to examples provided by https://www.ietf.org/archive/id/draft-ietf-add-ddr-06.html.
|
||||
//
|
||||
// TODO(a.meshkov): Consider setting the priority values based on the protocol.
|
||||
func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) {
|
||||
resp = s.makeResponse(req)
|
||||
// TODO(e.burkov): Think about storing the FQDN version of the server's
|
||||
// name somewhere.
|
||||
domainName := dns.Fqdn(s.conf.ServerName)
|
||||
|
||||
for _, addr := range s.conf.HTTPSListenAddrs {
|
||||
values := []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"h2"}},
|
||||
&dns.SVCBPort{Port: uint16(addr.Port)},
|
||||
&dns.SVCBDoHPath{Template: "/dns-query?dns"},
|
||||
}
|
||||
|
||||
ans := &dns.SVCB{
|
||||
Hdr: s.hdr(req, dns.TypeSVCB),
|
||||
Priority: 1,
|
||||
Target: domainName,
|
||||
Value: values,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
}
|
||||
|
||||
for _, addr := range s.dnsProxy.TLSListenAddr {
|
||||
values := []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"dot"}},
|
||||
&dns.SVCBPort{Port: uint16(addr.Port)},
|
||||
}
|
||||
|
||||
ans := &dns.SVCB{
|
||||
Hdr: s.hdr(req, dns.TypeSVCB),
|
||||
Priority: 1,
|
||||
Target: domainName,
|
||||
Value: values,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
}
|
||||
|
||||
for _, addr := range s.dnsProxy.QUICListenAddr {
|
||||
values := []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"doq"}},
|
||||
&dns.SVCBPort{Port: uint16(addr.Port)},
|
||||
}
|
||||
|
||||
ans := &dns.SVCB{
|
||||
Hdr: s.hdr(req, dns.TypeSVCB),
|
||||
Priority: 1,
|
||||
Target: domainName,
|
||||
Value: values,
|
||||
}
|
||||
|
||||
resp.Answer = append(resp.Answer, ans)
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// processDetermineLocal determines if the client's IP address is from
|
||||
// locally-served network and saves the result into the context.
|
||||
func (s *Server) processDetermineLocal(dctx *dnsContext) (rc resultCode) {
|
||||
@@ -409,7 +506,7 @@ func (s *Server) ipToHost(ip net.IP) (host string, ok bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
var v interface{}
|
||||
var v any
|
||||
v, ok = s.tableIPToHost.Get(ip)
|
||||
if !ok {
|
||||
return "", false
|
||||
|
||||
@@ -14,6 +14,177 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
ddrTestDomainName = "dns.example.net"
|
||||
ddrTestFQDN = ddrTestDomainName + "."
|
||||
)
|
||||
|
||||
func TestServer_ProcessDDRQuery(t *testing.T) {
|
||||
dohSVCB := &dns.SVCB{
|
||||
Priority: 1,
|
||||
Target: ddrTestFQDN,
|
||||
Value: []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"h2"}},
|
||||
&dns.SVCBPort{Port: 8044},
|
||||
&dns.SVCBDoHPath{Template: "/dns-query?dns"},
|
||||
},
|
||||
}
|
||||
|
||||
dotSVCB := &dns.SVCB{
|
||||
Priority: 1,
|
||||
Target: ddrTestFQDN,
|
||||
Value: []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"dot"}},
|
||||
&dns.SVCBPort{Port: 8043},
|
||||
},
|
||||
}
|
||||
|
||||
doqSVCB := &dns.SVCB{
|
||||
Priority: 1,
|
||||
Target: ddrTestFQDN,
|
||||
Value: []dns.SVCBKeyValue{
|
||||
&dns.SVCBAlpn{Alpn: []string{"doq"}},
|
||||
&dns.SVCBPort{Port: 8042},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
host string
|
||||
want []*dns.SVCB
|
||||
wantRes resultCode
|
||||
portDoH int
|
||||
portDoT int
|
||||
portDoQ int
|
||||
qtype uint16
|
||||
ddrEnabled bool
|
||||
}{{
|
||||
name: "pass_host",
|
||||
wantRes: resultCodeSuccess,
|
||||
host: "example.net.",
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
portDoH: 8043,
|
||||
}, {
|
||||
name: "pass_qtype",
|
||||
wantRes: resultCodeFinish,
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeA,
|
||||
ddrEnabled: true,
|
||||
portDoH: 8043,
|
||||
}, {
|
||||
name: "pass_disabled_tls",
|
||||
wantRes: resultCodeFinish,
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
}, {
|
||||
name: "pass_disabled_ddr",
|
||||
wantRes: resultCodeSuccess,
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: false,
|
||||
portDoH: 8043,
|
||||
}, {
|
||||
name: "dot",
|
||||
wantRes: resultCodeFinish,
|
||||
want: []*dns.SVCB{dotSVCB},
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
portDoT: 8043,
|
||||
}, {
|
||||
name: "doh",
|
||||
wantRes: resultCodeFinish,
|
||||
want: []*dns.SVCB{dohSVCB},
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
portDoH: 8044,
|
||||
}, {
|
||||
name: "doq",
|
||||
wantRes: resultCodeFinish,
|
||||
want: []*dns.SVCB{doqSVCB},
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
portDoQ: 8042,
|
||||
}, {
|
||||
name: "dot_doh",
|
||||
wantRes: resultCodeFinish,
|
||||
want: []*dns.SVCB{dotSVCB, dohSVCB},
|
||||
host: ddrHostFQDN,
|
||||
qtype: dns.TypeSVCB,
|
||||
ddrEnabled: true,
|
||||
portDoT: 8043,
|
||||
portDoH: 8044,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s := prepareTestServer(t, tc.portDoH, tc.portDoT, tc.portDoQ, tc.ddrEnabled)
|
||||
|
||||
req := createTestMessageWithType(tc.host, tc.qtype)
|
||||
|
||||
dctx := &dnsContext{
|
||||
proxyCtx: &proxy.DNSContext{
|
||||
Req: req,
|
||||
},
|
||||
}
|
||||
|
||||
res := s.processDDRQuery(dctx)
|
||||
require.Equal(t, tc.wantRes, res)
|
||||
|
||||
if tc.wantRes != resultCodeFinish {
|
||||
return
|
||||
}
|
||||
|
||||
msg := dctx.proxyCtx.Res
|
||||
require.NotNil(t, msg)
|
||||
|
||||
for _, v := range tc.want {
|
||||
v.Hdr = s.hdr(req, dns.TypeSVCB)
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, tc.want, msg.Answer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled bool) (s *Server) {
|
||||
t.Helper()
|
||||
|
||||
proxyConf := proxy.Config{}
|
||||
|
||||
if portDoT > 0 {
|
||||
proxyConf.TLSListenAddr = []*net.TCPAddr{{Port: portDoT}}
|
||||
}
|
||||
|
||||
if portDoQ > 0 {
|
||||
proxyConf.QUICListenAddr = []*net.UDPAddr{{Port: portDoQ}}
|
||||
}
|
||||
|
||||
s = &Server{
|
||||
dnsProxy: &proxy.Proxy{
|
||||
Config: proxyConf,
|
||||
},
|
||||
conf: ServerConfig{
|
||||
FilteringConfig: FilteringConfig{
|
||||
HandleDDR: ddrEnabled,
|
||||
},
|
||||
TLSConfig: TLSConfig{
|
||||
ServerName: ddrTestDomainName,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if portDoH > 0 {
|
||||
s.conf.TLSConfig.HTTPSListenAddrs = []*net.TCPAddr{{Port: portDoH}}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func TestServer_ProcessDetermineLocal(t *testing.T) {
|
||||
s := &Server{
|
||||
privateNets: netutil.SubnetSetFunc(netutil.IsLocallyServed),
|
||||
|
||||
@@ -33,11 +33,6 @@ const DefaultTimeout = 10 * time.Second
|
||||
// requests between the BeforeRequestHandler stage and the actual processing.
|
||||
const defaultClientIDCacheCount = 1024
|
||||
|
||||
const (
|
||||
safeBrowsingBlockHost = "standard-block.dns.adguard.com"
|
||||
parentalBlockHost = "family-block.dns.adguard.com"
|
||||
)
|
||||
|
||||
var defaultDNS = []string{
|
||||
"https://dns10.quad9.net/dns-query",
|
||||
}
|
||||
@@ -66,7 +61,7 @@ type Server struct {
|
||||
dnsFilter *filtering.DNSFilter // DNS filter instance
|
||||
dhcpServer dhcpd.ServerInterface // DHCP server instance (optional)
|
||||
queryLog querylog.QueryLog // Query log instance
|
||||
stats stats.Stats
|
||||
stats stats.Interface
|
||||
access *accessCtx
|
||||
|
||||
// localDomainSuffix is the suffix used to detect internal hosts. It
|
||||
@@ -112,7 +107,7 @@ const defaultLocalDomainSuffix = "lan"
|
||||
// DNSCreateParams are parameters to create a new server.
|
||||
type DNSCreateParams struct {
|
||||
DNSFilter *filtering.DNSFilter
|
||||
Stats stats.Stats
|
||||
Stats stats.Interface
|
||||
QueryLog querylog.QueryLog
|
||||
DHCPServer dhcpd.ServerInterface
|
||||
PrivateNets netutil.SubnetSet
|
||||
|
||||
@@ -17,13 +17,13 @@ import (
|
||||
"testing/fstest"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
@@ -853,10 +853,7 @@ func TestBlockedByHosts(t *testing.T) {
|
||||
func TestBlockedBySafeBrowsing(t *testing.T) {
|
||||
const hostname = "wmconvirus.narod.ru"
|
||||
|
||||
sbUps := &aghtest.TestBlockUpstream{
|
||||
Hostname: hostname,
|
||||
Block: true,
|
||||
}
|
||||
sbUps := aghtest.NewBlockUpstream(hostname, true)
|
||||
ans4, _ := (&aghtest.TestResolver{}).HostToIPs(hostname)
|
||||
|
||||
filterConf := &filtering.Config{
|
||||
@@ -988,7 +985,7 @@ func TestRewrite(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func publicKey(priv interface{}) interface{} {
|
||||
func publicKey(priv any) any {
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &k.PublicKey
|
||||
@@ -1029,7 +1026,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
||||
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
||||
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
||||
s.conf.ProtectionEnabled = true
|
||||
|
||||
err = s.Prepare(nil)
|
||||
require.NoError(t, err)
|
||||
@@ -1177,25 +1174,48 @@ func TestNewServer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_Exchange(t *testing.T) {
|
||||
extUpstream := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"1.1.1.1.in-addr.arpa.": {"one.one.one.one"},
|
||||
const (
|
||||
onesHost = "one.one.one.one"
|
||||
localDomainHost = "local.domain"
|
||||
)
|
||||
|
||||
var (
|
||||
onesIP = net.IP{1, 1, 1, 1}
|
||||
localIP = net.IP{192, 168, 1, 1}
|
||||
)
|
||||
|
||||
revExtIPv4, err := netutil.IPToReversedAddr(onesIP)
|
||||
require.NoError(t, err)
|
||||
|
||||
extUpstream := &aghtest.UpstreamMock{
|
||||
OnAddress: func() (addr string) { return "external.upstream.example" },
|
||||
OnExchange: func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = aghalg.Coalesce(
|
||||
aghtest.RespondTo(t, req, dns.ClassINET, dns.TypePTR, revExtIPv4, onesHost),
|
||||
new(dns.Msg).SetRcode(req, dns.RcodeNameError),
|
||||
)
|
||||
|
||||
return resp, nil
|
||||
},
|
||||
}
|
||||
locUpstream := &aghtest.Upstream{
|
||||
Reverse: map[string][]string{
|
||||
"1.1.168.192.in-addr.arpa.": {"local.domain"},
|
||||
"2.1.168.192.in-addr.arpa.": {},
|
||||
|
||||
revLocIPv4, err := netutil.IPToReversedAddr(localIP)
|
||||
require.NoError(t, err)
|
||||
|
||||
locUpstream := &aghtest.UpstreamMock{
|
||||
OnAddress: func() (addr string) { return "local.upstream.example" },
|
||||
OnExchange: func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = aghalg.Coalesce(
|
||||
aghtest.RespondTo(t, req, dns.ClassINET, dns.TypePTR, revLocIPv4, localDomainHost),
|
||||
new(dns.Msg).SetRcode(req, dns.RcodeNameError),
|
||||
)
|
||||
|
||||
return resp, nil
|
||||
},
|
||||
}
|
||||
upstreamErr := errors.Error("upstream error")
|
||||
errUpstream := &aghtest.TestErrUpstream{
|
||||
Err: upstreamErr,
|
||||
}
|
||||
nonPtrUpstream := &aghtest.TestBlockUpstream{
|
||||
Hostname: "some-host",
|
||||
Block: true,
|
||||
}
|
||||
|
||||
errUpstream := aghtest.NewErrorUpstream()
|
||||
nonPtrUpstream := aghtest.NewBlockUpstream("some-host", true)
|
||||
|
||||
srv := NewCustomServer(&proxy.Proxy{
|
||||
Config: proxy.Config{
|
||||
@@ -1209,7 +1229,6 @@ func TestServer_Exchange(t *testing.T) {
|
||||
|
||||
srv.privateNets = netutil.SubnetSetFunc(netutil.IsLocallyServed)
|
||||
|
||||
localIP := net.IP{192, 168, 1, 1}
|
||||
testCases := []struct {
|
||||
name string
|
||||
want string
|
||||
@@ -1218,20 +1237,20 @@ func TestServer_Exchange(t *testing.T) {
|
||||
req net.IP
|
||||
}{{
|
||||
name: "external_good",
|
||||
want: "one.one.one.one",
|
||||
want: onesHost,
|
||||
wantErr: nil,
|
||||
locUpstream: nil,
|
||||
req: net.IP{1, 1, 1, 1},
|
||||
req: onesIP,
|
||||
}, {
|
||||
name: "local_good",
|
||||
want: "local.domain",
|
||||
want: localDomainHost,
|
||||
wantErr: nil,
|
||||
locUpstream: locUpstream,
|
||||
req: localIP,
|
||||
}, {
|
||||
name: "upstream_error",
|
||||
want: "",
|
||||
wantErr: upstreamErr,
|
||||
wantErr: aghtest.ErrUpstream,
|
||||
locUpstream: errUpstream,
|
||||
req: localIP,
|
||||
}, {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -17,6 +16,8 @@ import (
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type dnsConfig struct {
|
||||
@@ -363,6 +364,21 @@ func newUpstreamConfig(upstreams []string) (conf *proxy.UpstreamConfig, err erro
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, u := range upstreams {
|
||||
var ups string
|
||||
var domains []string
|
||||
ups, domains, err = separateUpstream(u)
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = validateUpstream(ups, domains)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("validating upstream %q: %w", u, err)
|
||||
}
|
||||
}
|
||||
|
||||
conf, err = proxy.ParseUpstreamsConfig(
|
||||
upstreams,
|
||||
&upstream.Options{Bootstrap: []string{}, Timeout: DefaultTimeout},
|
||||
@@ -373,13 +389,6 @@ func newUpstreamConfig(upstreams []string) (conf *proxy.UpstreamConfig, err erro
|
||||
return nil, errors.Error("no default upstreams specified")
|
||||
}
|
||||
|
||||
for _, u := range upstreams {
|
||||
_, err = validateUpstream(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
@@ -393,20 +402,6 @@ func ValidateUpstreams(upstreams []string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// stringKeysSorted returns the sorted slice of string keys of m.
|
||||
//
|
||||
// TODO(e.burkov): Use generics in Go 1.18. Move into golibs.
|
||||
func stringKeysSorted(m map[string][]upstream.Upstream) (sorted []string) {
|
||||
sorted = make([]string, 0, len(m))
|
||||
for s := range m {
|
||||
sorted = append(sorted, s)
|
||||
}
|
||||
|
||||
sort.Strings(sorted)
|
||||
|
||||
return sorted
|
||||
}
|
||||
|
||||
// ValidateUpstreamsPrivate validates each upstream and returns an error if any
|
||||
// upstream is invalid or if there are no default upstreams specified. It also
|
||||
// checks each domain of domain-specific upstreams for being ARPA pointing to
|
||||
@@ -421,9 +416,11 @@ func ValidateUpstreamsPrivate(upstreams []string, privateNets netutil.SubnetSet)
|
||||
return nil
|
||||
}
|
||||
|
||||
var errs []error
|
||||
keys := maps.Keys(conf.DomainReservedUpstreams)
|
||||
slices.Sort(keys)
|
||||
|
||||
for _, domain := range stringKeysSorted(conf.DomainReservedUpstreams) {
|
||||
var errs []error
|
||||
for _, domain := range keys {
|
||||
var subnet *net.IPNet
|
||||
subnet, err = netutil.SubnetFromReversedAddr(domain)
|
||||
if err != nil {
|
||||
@@ -449,16 +446,14 @@ func ValidateUpstreamsPrivate(upstreams []string, privateNets netutil.SubnetSet)
|
||||
|
||||
var protocols = []string{"udp://", "tcp://", "tls://", "https://", "sdns://", "quic://"}
|
||||
|
||||
func validateUpstream(u string) (useDefault bool, err error) {
|
||||
// Check if the user tries to specify upstream for domain.
|
||||
var isDomainSpec bool
|
||||
u, isDomainSpec, err = separateUpstream(u)
|
||||
if err != nil {
|
||||
return !isDomainSpec, err
|
||||
}
|
||||
|
||||
// validateUpstream returns an error if u alongside with domains is not a valid
|
||||
// upstream configuration. useDefault is true if the upstream is
|
||||
// domain-specific and is configured to point at the default upstream server
|
||||
// which is validated separately. The upstream is considered domain-specific
|
||||
// only if domains is at least not nil.
|
||||
func validateUpstream(u string, domains []string) (useDefault bool, err error) {
|
||||
// The special server address '#' means that default server must be used.
|
||||
if useDefault = !isDomainSpec; u == "#" && isDomainSpec {
|
||||
if useDefault = u == "#" && domains != nil; useDefault {
|
||||
return useDefault, nil
|
||||
}
|
||||
|
||||
@@ -485,12 +480,14 @@ func validateUpstream(u string) (useDefault bool, err error) {
|
||||
return useDefault, nil
|
||||
}
|
||||
|
||||
// separateUpstream returns the upstream without the specified domains.
|
||||
// isDomainSpec is true when the upstream is domains-specific.
|
||||
func separateUpstream(upstreamStr string) (upstream string, isDomainSpec bool, err error) {
|
||||
// separateUpstream returns the upstream and the specified domains. domains is
|
||||
// nil when the upstream is not domains-specific. Otherwise it may also be
|
||||
// empty.
|
||||
func separateUpstream(upstreamStr string) (ups string, domains []string, err error) {
|
||||
if !strings.HasPrefix(upstreamStr, "[/") {
|
||||
return upstreamStr, false, nil
|
||||
return upstreamStr, nil, nil
|
||||
}
|
||||
|
||||
defer func() { err = errors.Annotate(err, "bad upstream for domain %q: %w", upstreamStr) }()
|
||||
|
||||
parts := strings.Split(upstreamStr[2:], "/]")
|
||||
@@ -498,40 +495,46 @@ func separateUpstream(upstreamStr string) (upstream string, isDomainSpec bool, e
|
||||
case 2:
|
||||
// Go on.
|
||||
case 1:
|
||||
return "", false, errors.Error("missing separator")
|
||||
return "", nil, errors.Error("missing separator")
|
||||
default:
|
||||
return "", true, errors.Error("duplicated separator")
|
||||
return "", []string{}, errors.Error("duplicated separator")
|
||||
}
|
||||
|
||||
var domains string
|
||||
domains, upstream = parts[0], parts[1]
|
||||
for i, host := range strings.Split(domains, "/") {
|
||||
for i, host := range strings.Split(parts[0], "/") {
|
||||
if host == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
host = strings.TrimPrefix(host, "*.")
|
||||
err = netutil.ValidateDomainName(host)
|
||||
err = netutil.ValidateDomainName(strings.TrimPrefix(host, "*."))
|
||||
if err != nil {
|
||||
return "", true, fmt.Errorf("domain at index %d: %w", i, err)
|
||||
return "", domains, fmt.Errorf("domain at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
domains = append(domains, host)
|
||||
}
|
||||
|
||||
return upstream, true, nil
|
||||
return parts[1], domains, nil
|
||||
}
|
||||
|
||||
// excFunc is a signature of function to check if upstream exchanges correctly.
|
||||
type excFunc func(u upstream.Upstream) (err error)
|
||||
// healthCheckFunc is a signature of function to check if upstream exchanges
|
||||
// properly.
|
||||
type healthCheckFunc func(u upstream.Upstream) (err error)
|
||||
|
||||
// checkDNSUpstreamExc checks if the DNS upstream exchanges correctly.
|
||||
func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
|
||||
// testTLD is the special-use fully-qualified domain name for testing the
|
||||
// DNS server reachability.
|
||||
//
|
||||
// See https://datatracker.ietf.org/doc/html/rfc6761#section-6.2.
|
||||
const testTLD = "test."
|
||||
|
||||
req := &dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: dns.Id(),
|
||||
RecursionDesired: true,
|
||||
},
|
||||
Question: []dns.Question{{
|
||||
Name: "google-public-dns-a.google.com.",
|
||||
Name: testTLD,
|
||||
Qtype: dns.TypeA,
|
||||
Qclass: dns.ClassINET,
|
||||
}},
|
||||
@@ -541,12 +544,8 @@ func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
|
||||
reply, err = u.Exchange(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't communicate with upstream: %w", err)
|
||||
}
|
||||
|
||||
if len(reply.Answer) != 1 {
|
||||
return fmt.Errorf("wrong response")
|
||||
} else if a, ok := reply.Answer[0].(*dns.A); !ok || !a.A.Equal(net.IP{8, 8, 8, 8}) {
|
||||
return fmt.Errorf("wrong response")
|
||||
} else if len(reply.Answer) != 0 {
|
||||
return errors.Error("wrong response")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -554,14 +553,22 @@ func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
|
||||
|
||||
// checkPrivateUpstreamExc checks if the upstream for resolving private
|
||||
// addresses exchanges correctly.
|
||||
//
|
||||
// TODO(e.burkov): Think about testing the ip6.arpa. as well.
|
||||
func checkPrivateUpstreamExc(u upstream.Upstream) (err error) {
|
||||
// inAddrArpaTLD is the special-use fully-qualified domain name for PTR IP
|
||||
// address resolution.
|
||||
//
|
||||
// See https://datatracker.ietf.org/doc/html/rfc1035#section-3.5.
|
||||
const inAddrArpaTLD = "in-addr.arpa."
|
||||
|
||||
req := &dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: dns.Id(),
|
||||
RecursionDesired: true,
|
||||
},
|
||||
Question: []dns.Question{{
|
||||
Name: "1.0.0.127.in-addr.arpa.",
|
||||
Name: inAddrArpaTLD,
|
||||
Qtype: dns.TypePTR,
|
||||
Qclass: dns.ClassINET,
|
||||
}},
|
||||
@@ -574,46 +581,66 @@ func checkPrivateUpstreamExc(u upstream.Upstream) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFunc) (err error) {
|
||||
if IsCommentOrEmpty(input) {
|
||||
// domainSpecificTestError is a wrapper for errors returned by checkDNS to mark
|
||||
// the tested upstream domain-specific and therefore consider its errors
|
||||
// non-critical.
|
||||
//
|
||||
// TODO(a.garipov): Some common mechanism of distinguishing between errors and
|
||||
// warnings (non-critical errors) is desired.
|
||||
type domainSpecificTestError struct {
|
||||
error
|
||||
}
|
||||
|
||||
// checkDNS checks the upstream server defined by upstreamConfigStr using
|
||||
// healthCheck for actually exchange messages. It uses bootstrap to resolve the
|
||||
// upstream's address.
|
||||
func checkDNS(
|
||||
upstreamConfigStr string,
|
||||
bootstrap []string,
|
||||
timeout time.Duration,
|
||||
healthCheck healthCheckFunc,
|
||||
) (err error) {
|
||||
if IsCommentOrEmpty(upstreamConfigStr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Separate upstream from domains list.
|
||||
var useDefault bool
|
||||
if useDefault, err = validateUpstream(input); err != nil {
|
||||
upstreamAddr, domains, err := separateUpstream(upstreamConfigStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wrong upstream format: %w", err)
|
||||
}
|
||||
|
||||
// No need to check this DNS server.
|
||||
if !useDefault {
|
||||
useDefault, err := validateUpstream(upstreamAddr, domains)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wrong upstream format: %w", err)
|
||||
} else if useDefault {
|
||||
return nil
|
||||
}
|
||||
|
||||
if input, _, err = separateUpstream(input); err != nil {
|
||||
return fmt.Errorf("wrong upstream format: %w", err)
|
||||
}
|
||||
|
||||
if len(bootstrap) == 0 {
|
||||
bootstrap = defaultBootstrap
|
||||
}
|
||||
|
||||
log.Debug("checking if upstream %s works", input)
|
||||
log.Debug("dnsforward: checking if upstream %q works", upstreamAddr)
|
||||
|
||||
var u upstream.Upstream
|
||||
u, err = upstream.AddressToUpstream(input, &upstream.Options{
|
||||
u, err := upstream.AddressToUpstream(upstreamAddr, &upstream.Options{
|
||||
Bootstrap: bootstrap,
|
||||
Timeout: timeout,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to choose upstream for %q: %w", input, err)
|
||||
return fmt.Errorf("failed to choose upstream for %q: %w", upstreamAddr, err)
|
||||
}
|
||||
|
||||
if err = ef(u); err != nil {
|
||||
return fmt.Errorf("upstream %q fails to exchange: %w", input, err)
|
||||
if err = healthCheck(u); err != nil {
|
||||
err = fmt.Errorf("upstream %q fails to exchange: %w", upstreamAddr, err)
|
||||
if domains != nil {
|
||||
return domainSpecificTestError{error: err}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("upstream %s is ok", input)
|
||||
log.Debug("dnsforward: upstream %q is ok", upstreamAddr)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -636,6 +663,9 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Info("%v", err)
|
||||
result[host] = err.Error()
|
||||
if _, ok := err.(domainSpecificTestError); ok {
|
||||
result[host] = fmt.Sprintf("WARNING: %s", result[host])
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
@@ -651,6 +681,9 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
|
||||
// above, we rewriting the error for it. These cases should be
|
||||
// handled properly instead.
|
||||
result[host] = err.Error()
|
||||
if _, ok := err.(domainSpecificTestError); ok {
|
||||
result[host] = fmt.Sprintf("WARNING: %s", result[host])
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func (fsr *fakeSystemResolvers) Get() (rs []string) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadTestData(t *testing.T, casesFileName string, cases interface{}) {
|
||||
func loadTestData(t *testing.T, casesFileName string, cases any) {
|
||||
t.Helper()
|
||||
|
||||
var f *os.File
|
||||
@@ -185,7 +185,8 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||
wantSet: "",
|
||||
}, {
|
||||
name: "upstream_dns_bad",
|
||||
wantSet: `validating upstream servers: bad ipport address "!!!": ` +
|
||||
wantSet: `validating upstream servers: ` +
|
||||
`validating upstream "!!!": bad ipport address "!!!": ` +
|
||||
`address !!!: missing port in address`,
|
||||
}, {
|
||||
name: "bootstraps_bad",
|
||||
@@ -256,112 +257,6 @@ func TestIsCommentOrEmpty(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUpstream(t *testing.T) {
|
||||
testCases := []struct {
|
||||
wantDef assert.BoolAssertionFunc
|
||||
name string
|
||||
upstream string
|
||||
wantErr string
|
||||
}{{
|
||||
wantDef: assert.True,
|
||||
name: "invalid",
|
||||
upstream: "1.2.3.4.5",
|
||||
wantErr: `bad ipport address "1.2.3.4.5": address 1.2.3.4.5: missing port in address`,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "invalid",
|
||||
upstream: "123.3.7m",
|
||||
wantErr: `bad ipport address "123.3.7m": address 123.3.7m: missing port in address`,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "invalid",
|
||||
upstream: "htttps://google.com/dns-query",
|
||||
wantErr: `wrong protocol`,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "invalid",
|
||||
upstream: "[/host.com]tls://dns.adguard.com",
|
||||
wantErr: `bad upstream for domain "[/host.com]tls://dns.adguard.com": missing separator`,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "invalid",
|
||||
upstream: "[host.ru]#",
|
||||
wantErr: `bad ipport address "[host.ru]#": address [host.ru]#: missing port in address`,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "valid_default",
|
||||
upstream: "1.1.1.1",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "valid_default",
|
||||
upstream: "tls://1.1.1.1",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "valid_default",
|
||||
upstream: "https://dns.adguard.com/dns-query",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "valid_default",
|
||||
upstream: "sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "default_udp_host",
|
||||
upstream: "udp://dns.google",
|
||||
}, {
|
||||
wantDef: assert.True,
|
||||
name: "default_udp_ip",
|
||||
upstream: "udp://8.8.8.8",
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "valid",
|
||||
upstream: "[/host.com/]1.1.1.1",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "valid",
|
||||
upstream: "[//]tls://1.1.1.1",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "valid",
|
||||
upstream: "[/www.host.com/]#",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "valid",
|
||||
upstream: "[/host.com/google.com/]8.8.8.8",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "valid",
|
||||
upstream: "[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "idna",
|
||||
upstream: "[/пример.рф/]8.8.8.8",
|
||||
wantErr: ``,
|
||||
}, {
|
||||
wantDef: assert.False,
|
||||
name: "bad_domain",
|
||||
upstream: "[/!/]8.8.8.8",
|
||||
wantErr: `bad upstream for domain "[/!/]8.8.8.8": domain at index 0: ` +
|
||||
`bad domain name "!": bad domain name label "!": bad domain name label rune '!'`,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defaultUpstream, err := validateUpstream(tc.upstream)
|
||||
testutil.AssertErrorMsg(t, tc.wantErr, err)
|
||||
tc.wantDef(t, defaultUpstream)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUpstreams(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -376,7 +271,7 @@ func TestValidateUpstreams(t *testing.T) {
|
||||
wantErr: ``,
|
||||
set: []string{"# comment"},
|
||||
}, {
|
||||
name: "valid_no_default",
|
||||
name: "no_default",
|
||||
wantErr: `no default upstreams specified`,
|
||||
set: []string{
|
||||
"[/host.com/]1.1.1.1",
|
||||
@@ -386,7 +281,7 @@ func TestValidateUpstreams(t *testing.T) {
|
||||
"[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
|
||||
},
|
||||
}, {
|
||||
name: "valid_with_default",
|
||||
name: "with_default",
|
||||
wantErr: ``,
|
||||
set: []string{
|
||||
"[/host.com/]1.1.1.1",
|
||||
@@ -398,8 +293,46 @@ func TestValidateUpstreams(t *testing.T) {
|
||||
},
|
||||
}, {
|
||||
name: "invalid",
|
||||
wantErr: `cannot prepare the upstream dhcp://fake.dns ([]): unsupported url scheme: dhcp`,
|
||||
wantErr: `validating upstream "dhcp://fake.dns": wrong protocol`,
|
||||
set: []string{"dhcp://fake.dns"},
|
||||
}, {
|
||||
name: "invalid",
|
||||
wantErr: `validating upstream "1.2.3.4.5": bad ipport address "1.2.3.4.5": address 1.2.3.4.5: missing port in address`,
|
||||
set: []string{"1.2.3.4.5"},
|
||||
}, {
|
||||
name: "invalid",
|
||||
wantErr: `validating upstream "123.3.7m": bad ipport address "123.3.7m": address 123.3.7m: missing port in address`,
|
||||
set: []string{"123.3.7m"},
|
||||
}, {
|
||||
name: "invalid",
|
||||
wantErr: `bad upstream for domain "[/host.com]tls://dns.adguard.com": missing separator`,
|
||||
set: []string{"[/host.com]tls://dns.adguard.com"},
|
||||
}, {
|
||||
name: "invalid",
|
||||
wantErr: `validating upstream "[host.ru]#": bad ipport address "[host.ru]#": address [host.ru]#: missing port in address`,
|
||||
set: []string{"[host.ru]#"},
|
||||
}, {
|
||||
name: "valid_default",
|
||||
wantErr: ``,
|
||||
set: []string{
|
||||
"1.1.1.1",
|
||||
"tls://1.1.1.1",
|
||||
"https://dns.adguard.com/dns-query",
|
||||
"sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
|
||||
"udp://dns.google",
|
||||
"udp://8.8.8.8",
|
||||
"[/host.com/]1.1.1.1",
|
||||
"[//]tls://1.1.1.1",
|
||||
"[/www.host.com/]#",
|
||||
"[/host.com/google.com/]8.8.8.8",
|
||||
"[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
|
||||
"[/пример.рф/]8.8.8.8",
|
||||
},
|
||||
}, {
|
||||
name: "bad_domain",
|
||||
wantErr: `bad upstream for domain "[/!/]8.8.8.8": domain at index 0: ` +
|
||||
`bad domain name "!": bad domain name label "!": bad domain name label rune '!'`,
|
||||
set: []string{"[/!/]8.8.8.8"},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -34,7 +34,7 @@ func (l *testQueryLog) Add(p *querylog.AddParams) {
|
||||
type testStats struct {
|
||||
// Stats is embedded here simply to make testStats a stats.Stats without
|
||||
// actually implementing all methods.
|
||||
stats.Stats
|
||||
stats.Interface
|
||||
|
||||
lastEntry stats.Entry
|
||||
}
|
||||
|
||||
@@ -43,13 +43,14 @@ var serviceRulesArray = []svc{{
|
||||
}, {
|
||||
name: "youtube",
|
||||
rules: []string{
|
||||
"||youtube.com^",
|
||||
"||ytimg.com^",
|
||||
"||youtu.be^",
|
||||
"||googlevideo.com^",
|
||||
"||youtubei.googleapis.com^",
|
||||
"||youtube-nocookie.com^",
|
||||
"||wide-youtube.l.google.com^",
|
||||
"||youtu.be^",
|
||||
"||youtube",
|
||||
"||youtube-nocookie.com^",
|
||||
"||youtube.com^",
|
||||
"||youtubei.googleapis.com^",
|
||||
"||ytimg.com^",
|
||||
},
|
||||
}, {
|
||||
name: "twitch",
|
||||
|
||||
@@ -61,22 +61,22 @@ func TestDNSFilter_CheckHostRules_dnsrewrite(t *testing.T) {
|
||||
|
||||
testCasesA := []struct {
|
||||
name string
|
||||
want []interface{}
|
||||
want []any
|
||||
rcode int
|
||||
dtyp uint16
|
||||
}{{
|
||||
name: "a-record",
|
||||
rcode: dns.RcodeSuccess,
|
||||
want: []interface{}{ipv4p1},
|
||||
want: []any{ipv4p1},
|
||||
dtyp: dns.TypeA,
|
||||
}, {
|
||||
name: "aaaa-record",
|
||||
want: []interface{}{ipv6p1},
|
||||
want: []any{ipv6p1},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeAAAA,
|
||||
}, {
|
||||
name: "txt-record",
|
||||
want: []interface{}{"hello-world"},
|
||||
want: []any{"hello-world"},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeTXT,
|
||||
}, {
|
||||
@@ -86,22 +86,22 @@ func TestDNSFilter_CheckHostRules_dnsrewrite(t *testing.T) {
|
||||
dtyp: 0,
|
||||
}, {
|
||||
name: "a-records",
|
||||
want: []interface{}{ipv4p1, ipv4p2},
|
||||
want: []any{ipv4p1, ipv4p2},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeA,
|
||||
}, {
|
||||
name: "aaaa-records",
|
||||
want: []interface{}{ipv6p1, ipv6p2},
|
||||
want: []any{ipv6p1, ipv6p2},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeAAAA,
|
||||
}, {
|
||||
name: "disable-one",
|
||||
want: []interface{}{ipv4p2},
|
||||
want: []any{ipv4p2},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeA,
|
||||
}, {
|
||||
name: "disable-cname",
|
||||
want: []interface{}{ipv4p1},
|
||||
want: []any{ipv4p1},
|
||||
rcode: dns.RcodeSuccess,
|
||||
dtyp: dns.TypeA,
|
||||
}}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/cache"
|
||||
@@ -94,7 +94,7 @@ type Config struct {
|
||||
ConfigModified func() `yaml:"-"`
|
||||
|
||||
// Register an HTTP handler
|
||||
HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request)) `yaml:"-"`
|
||||
HTTPRegister aghhttp.RegisterFunc `yaml:"-"`
|
||||
|
||||
// CustomResolver is the resolver used by DNSFilter.
|
||||
CustomResolver Resolver `yaml:"-"`
|
||||
|
||||
@@ -21,6 +21,11 @@ func TestMain(m *testing.M) {
|
||||
aghtest.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
const (
|
||||
sbBlocked = "wmconvirus.narod.ru"
|
||||
pcBlocked = "pornhub.com"
|
||||
)
|
||||
|
||||
var setts = Settings{
|
||||
ProtectionEnabled: true,
|
||||
}
|
||||
@@ -173,43 +178,37 @@ func TestSafeBrowsing(t *testing.T) {
|
||||
|
||||
d := newForTest(t, &Config{SafeBrowsingEnabled: true}, nil)
|
||||
t.Cleanup(d.Close)
|
||||
const matching = "wmconvirus.narod.ru"
|
||||
d.SetSafeBrowsingUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: matching,
|
||||
Block: true,
|
||||
})
|
||||
d.checkMatch(t, matching)
|
||||
|
||||
require.Contains(t, logOutput.String(), "SafeBrowsing lookup for "+matching)
|
||||
d.SetSafeBrowsingUpstream(aghtest.NewBlockUpstream(sbBlocked, true))
|
||||
d.checkMatch(t, sbBlocked)
|
||||
|
||||
d.checkMatch(t, "test."+matching)
|
||||
require.Contains(t, logOutput.String(), fmt.Sprintf("safebrowsing lookup for %q", sbBlocked))
|
||||
|
||||
d.checkMatch(t, "test."+sbBlocked)
|
||||
d.checkMatchEmpty(t, "yandex.ru")
|
||||
d.checkMatchEmpty(t, "pornhub.com")
|
||||
d.checkMatchEmpty(t, pcBlocked)
|
||||
|
||||
// Cached result.
|
||||
d.safeBrowsingServer = "127.0.0.1"
|
||||
d.checkMatch(t, matching)
|
||||
d.checkMatchEmpty(t, "pornhub.com")
|
||||
d.checkMatch(t, sbBlocked)
|
||||
d.checkMatchEmpty(t, pcBlocked)
|
||||
d.safeBrowsingServer = defaultSafebrowsingServer
|
||||
}
|
||||
|
||||
func TestParallelSB(t *testing.T) {
|
||||
d := newForTest(t, &Config{SafeBrowsingEnabled: true}, nil)
|
||||
t.Cleanup(d.Close)
|
||||
const matching = "wmconvirus.narod.ru"
|
||||
d.SetSafeBrowsingUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: matching,
|
||||
Block: true,
|
||||
})
|
||||
|
||||
d.SetSafeBrowsingUpstream(aghtest.NewBlockUpstream(sbBlocked, true))
|
||||
|
||||
t.Run("group", func(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
t.Run(fmt.Sprintf("aaa%d", i), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
d.checkMatch(t, matching)
|
||||
d.checkMatch(t, "test."+matching)
|
||||
d.checkMatch(t, sbBlocked)
|
||||
d.checkMatch(t, "test."+sbBlocked)
|
||||
d.checkMatchEmpty(t, "yandex.ru")
|
||||
d.checkMatchEmpty(t, "pornhub.com")
|
||||
d.checkMatchEmpty(t, pcBlocked)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -382,23 +381,19 @@ func TestParentalControl(t *testing.T) {
|
||||
|
||||
d := newForTest(t, &Config{ParentalEnabled: true}, nil)
|
||||
t.Cleanup(d.Close)
|
||||
const matching = "pornhub.com"
|
||||
d.SetParentalUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: matching,
|
||||
Block: true,
|
||||
})
|
||||
|
||||
d.checkMatch(t, matching)
|
||||
require.Contains(t, logOutput.String(), "Parental lookup for "+matching)
|
||||
d.SetParentalUpstream(aghtest.NewBlockUpstream(pcBlocked, true))
|
||||
d.checkMatch(t, pcBlocked)
|
||||
require.Contains(t, logOutput.String(), fmt.Sprintf("parental lookup for %q", pcBlocked))
|
||||
|
||||
d.checkMatch(t, "www."+matching)
|
||||
d.checkMatch(t, "www."+pcBlocked)
|
||||
d.checkMatchEmpty(t, "www.yandex.ru")
|
||||
d.checkMatchEmpty(t, "yandex.ru")
|
||||
d.checkMatchEmpty(t, "api.jquery.com")
|
||||
|
||||
// Test cached result.
|
||||
d.parentalServer = "127.0.0.1"
|
||||
d.checkMatch(t, matching)
|
||||
d.checkMatch(t, pcBlocked)
|
||||
d.checkMatchEmpty(t, "yandex.ru")
|
||||
}
|
||||
|
||||
@@ -445,7 +440,7 @@ func TestMatching(t *testing.T) {
|
||||
}, {
|
||||
name: "sanity",
|
||||
rules: "||doubleclick.net^",
|
||||
host: "wmconvirus.narod.ru",
|
||||
host: sbBlocked,
|
||||
wantIsFiltered: false,
|
||||
wantReason: NotFilteredNotFound,
|
||||
wantDNSType: dns.TypeA,
|
||||
@@ -765,14 +760,9 @@ func TestClientSettings(t *testing.T) {
|
||||
}},
|
||||
)
|
||||
t.Cleanup(d.Close)
|
||||
d.SetParentalUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: "pornhub.com",
|
||||
Block: true,
|
||||
})
|
||||
d.SetSafeBrowsingUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: "wmconvirus.narod.ru",
|
||||
Block: true,
|
||||
})
|
||||
|
||||
d.SetParentalUpstream(aghtest.NewBlockUpstream(pcBlocked, true))
|
||||
d.SetSafeBrowsingUpstream(aghtest.NewBlockUpstream(sbBlocked, true))
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
@@ -787,12 +777,12 @@ func TestClientSettings(t *testing.T) {
|
||||
wantReason: FilteredBlockList,
|
||||
}, {
|
||||
name: "parental",
|
||||
host: "pornhub.com",
|
||||
host: pcBlocked,
|
||||
before: true,
|
||||
wantReason: FilteredParental,
|
||||
}, {
|
||||
name: "safebrowsing",
|
||||
host: "wmconvirus.narod.ru",
|
||||
host: sbBlocked,
|
||||
before: false,
|
||||
wantReason: FilteredSafeBrowsing,
|
||||
}, {
|
||||
@@ -836,33 +826,29 @@ func TestClientSettings(t *testing.T) {
|
||||
func BenchmarkSafeBrowsing(b *testing.B) {
|
||||
d := newForTest(b, &Config{SafeBrowsingEnabled: true}, nil)
|
||||
b.Cleanup(d.Close)
|
||||
blocked := "wmconvirus.narod.ru"
|
||||
d.SetSafeBrowsingUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: blocked,
|
||||
Block: true,
|
||||
})
|
||||
|
||||
d.SetSafeBrowsingUpstream(aghtest.NewBlockUpstream(sbBlocked, true))
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
res, err := d.CheckHost(blocked, dns.TypeA, &setts)
|
||||
res, err := d.CheckHost(sbBlocked, dns.TypeA, &setts)
|
||||
require.NoError(b, err)
|
||||
|
||||
assert.True(b, res.IsFiltered, "Expected hostname %s to match", blocked)
|
||||
assert.Truef(b, res.IsFiltered, "expected hostname %q to match", sbBlocked)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSafeBrowsingParallel(b *testing.B) {
|
||||
d := newForTest(b, &Config{SafeBrowsingEnabled: true}, nil)
|
||||
b.Cleanup(d.Close)
|
||||
blocked := "wmconvirus.narod.ru"
|
||||
d.SetSafeBrowsingUpstream(&aghtest.TestBlockUpstream{
|
||||
Hostname: blocked,
|
||||
Block: true,
|
||||
})
|
||||
|
||||
d.SetSafeBrowsingUpstream(aghtest.NewBlockUpstream(sbBlocked, true))
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
res, err := d.CheckHost(blocked, dns.TypeA, &setts)
|
||||
res, err := d.CheckHost(sbBlocked, dns.TypeA, &setts)
|
||||
require.NoError(b, err)
|
||||
|
||||
assert.True(b, res.IsFiltered, "Expected hostname %s to match", blocked)
|
||||
assert.Truef(b, res.IsFiltered, "expected hostname %q to match", sbBlocked)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,10 +24,11 @@ import (
|
||||
|
||||
// Safe browsing and parental control methods.
|
||||
|
||||
// TODO(a.garipov): Make configurable.
|
||||
const (
|
||||
dnsTimeout = 3 * time.Second
|
||||
defaultSafebrowsingServer = `https://dns-family.adguard.com/dns-query`
|
||||
defaultParentalServer = `https://dns-family.adguard.com/dns-query`
|
||||
defaultSafebrowsingServer = `https://family.adguard-dns.com/dns-query`
|
||||
defaultParentalServer = `https://family.adguard-dns.com/dns-query`
|
||||
sbTXTSuffix = `sb.dns.adguard.com.`
|
||||
pcTXTSuffix = `pc.dns.adguard.com.`
|
||||
)
|
||||
@@ -313,7 +314,7 @@ func (d *DNSFilter) checkSafeBrowsing(
|
||||
|
||||
if log.GetLevel() >= log.DEBUG {
|
||||
timer := log.StartTimer()
|
||||
defer timer.LogElapsed("SafeBrowsing lookup for %s", host)
|
||||
defer timer.LogElapsed("safebrowsing lookup for %q", host)
|
||||
}
|
||||
|
||||
sctx := &sbCtx{
|
||||
@@ -347,7 +348,7 @@ func (d *DNSFilter) checkParental(
|
||||
|
||||
if log.GetLevel() >= log.DEBUG {
|
||||
timer := log.StartTimer()
|
||||
defer timer.LogElapsed("Parental lookup for %s", host)
|
||||
defer timer.LogElapsed("parental lookup for %q", host)
|
||||
}
|
||||
|
||||
sctx := &sbCtx{
|
||||
|
||||
@@ -74,21 +74,20 @@ func TestSafeBrowsingCache(t *testing.T) {
|
||||
c.hashToHost[hash] = "sub.host.com"
|
||||
assert.Equal(t, -1, c.getCached())
|
||||
|
||||
// match "sub.host.com" from cache,
|
||||
// but another hash for "nonexisting.com" is not in cache
|
||||
// which means that we must get data from server for it
|
||||
// Match "sub.host.com" from cache. Another hash for "host.example" is not
|
||||
// in the cache, so get data for it from the server.
|
||||
c.hashToHost = make(map[[32]byte]string)
|
||||
hash = sha256.Sum256([]byte("sub.host.com"))
|
||||
c.hashToHost[hash] = "sub.host.com"
|
||||
hash = sha256.Sum256([]byte("nonexisting.com"))
|
||||
c.hashToHost[hash] = "nonexisting.com"
|
||||
hash = sha256.Sum256([]byte("host.example"))
|
||||
c.hashToHost[hash] = "host.example"
|
||||
assert.Empty(t, c.getCached())
|
||||
|
||||
hash = sha256.Sum256([]byte("sub.host.com"))
|
||||
_, ok := c.hashToHost[hash]
|
||||
assert.False(t, ok)
|
||||
|
||||
hash = sha256.Sum256([]byte("nonexisting.com"))
|
||||
hash = sha256.Sum256([]byte("host.example"))
|
||||
_, ok = c.hashToHost[hash]
|
||||
assert.True(t, ok)
|
||||
|
||||
@@ -111,8 +110,7 @@ func TestSBPC_checkErrorUpstream(t *testing.T) {
|
||||
d := newForTest(t, &Config{SafeBrowsingEnabled: true}, nil)
|
||||
t.Cleanup(d.Close)
|
||||
|
||||
ups := &aghtest.TestErrUpstream{}
|
||||
|
||||
ups := aghtest.NewErrorUpstream()
|
||||
d.SetSafeBrowsingUpstream(ups)
|
||||
d.SetParentalUpstream(ups)
|
||||
|
||||
@@ -170,10 +168,16 @@ func TestSBPC(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
// Prepare the upstream.
|
||||
ups := &aghtest.TestBlockUpstream{
|
||||
Hostname: hostname,
|
||||
Block: tc.block,
|
||||
ups := aghtest.NewBlockUpstream(hostname, tc.block)
|
||||
|
||||
var numReq int
|
||||
onExchange := ups.OnExchange
|
||||
ups.OnExchange = func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
numReq++
|
||||
|
||||
return onExchange(req)
|
||||
}
|
||||
|
||||
d.SetSafeBrowsingUpstream(ups)
|
||||
d.SetParentalUpstream(ups)
|
||||
|
||||
@@ -196,7 +200,7 @@ func TestSBPC(t *testing.T) {
|
||||
assert.Equal(t, hits, tc.testCache.Stats().Hit)
|
||||
|
||||
// There was one request to an upstream.
|
||||
assert.Equal(t, 1, ups.RequestsCount())
|
||||
assert.Equal(t, 1, numReq)
|
||||
|
||||
// Now make the same request to check the cache was used.
|
||||
res, err = tc.testFunc(hostname, dns.TypeA, setts)
|
||||
@@ -214,7 +218,7 @@ func TestSBPC(t *testing.T) {
|
||||
assert.Equal(t, hits+1, tc.testCache.Stats().Hit)
|
||||
|
||||
// Check that there were no additional requests.
|
||||
assert.Equal(t, 1, ups.RequestsCount())
|
||||
assert.Equal(t, 1, numReq)
|
||||
})
|
||||
|
||||
purgeCaches(d)
|
||||
|
||||
@@ -2,6 +2,7 @@ package home
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
@@ -60,6 +61,33 @@ const (
|
||||
ClientSourceHostsFile
|
||||
)
|
||||
|
||||
var _ fmt.Stringer = clientSource(0)
|
||||
|
||||
// String returns a human-readable name of cs.
|
||||
func (cs clientSource) String() (s string) {
|
||||
switch cs {
|
||||
case ClientSourceWHOIS:
|
||||
return "WHOIS"
|
||||
case ClientSourceARP:
|
||||
return "ARP"
|
||||
case ClientSourceRDNS:
|
||||
return "rDNS"
|
||||
case ClientSourceDHCP:
|
||||
return "DHCP"
|
||||
case ClientSourceHostsFile:
|
||||
return "etc/hosts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
var _ encoding.TextMarshaler = clientSource(0)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler for the clientSource.
|
||||
func (cs clientSource) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
||||
// clientSourceConf is used to configure where the runtime clients will be
|
||||
// obtained from.
|
||||
type clientSourcesConf struct {
|
||||
@@ -397,6 +425,7 @@ func (clients *clientsContainer) Find(id string) (c *Client, ok bool) {
|
||||
c.Tags = stringutil.CloneSlice(c.Tags)
|
||||
c.BlockedServices = stringutil.CloneSlice(c.BlockedServices)
|
||||
c.Upstreams = stringutil.CloneSlice(c.Upstreams)
|
||||
|
||||
return c, true
|
||||
}
|
||||
|
||||
@@ -493,7 +522,7 @@ func (clients *clientsContainer) findLocked(id string) (c *Client, ok bool) {
|
||||
// findRuntimeClientLocked finds a runtime client by their IP address. For
|
||||
// internal use only.
|
||||
func (clients *clientsContainer) findRuntimeClientLocked(ip net.IP) (rc *RuntimeClient, ok bool) {
|
||||
var v interface{}
|
||||
var v any
|
||||
v, ok = clients.ipToRC.Get(ip)
|
||||
if !ok {
|
||||
return nil, false
|
||||
@@ -769,7 +798,7 @@ func (clients *clientsContainer) addHostLocked(ip net.IP, host string, src clien
|
||||
// rmHostsBySrc removes all entries that match the specified source.
|
||||
func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
|
||||
n := 0
|
||||
clients.ipToRC.Range(func(ip net.IP, v interface{}) (cont bool) {
|
||||
clients.ipToRC.Range(func(ip net.IP, v any) (cont bool) {
|
||||
rc, ok := v.(*RuntimeClient)
|
||||
if !ok {
|
||||
log.Error("clients: bad type %T in ipToRC for %s", v, ip)
|
||||
@@ -797,7 +826,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
|
||||
clients.rmHostsBySrc(ClientSourceHostsFile)
|
||||
|
||||
n := 0
|
||||
hosts.Range(func(ip net.IP, v interface{}) (cont bool) {
|
||||
hosts.Range(func(ip net.IP, v any) (cont bool) {
|
||||
rec, ok := v.(*aghnet.HostsRecord)
|
||||
if !ok {
|
||||
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
|
||||
|
||||
@@ -47,9 +47,9 @@ type clientJSON struct {
|
||||
type runtimeClientJSON struct {
|
||||
WHOISInfo *RuntimeClientWHOISInfo `json:"whois_info"`
|
||||
|
||||
Name string `json:"name"`
|
||||
Source string `json:"source"`
|
||||
IP net.IP `json:"ip"`
|
||||
Name string `json:"name"`
|
||||
Source clientSource `json:"source"`
|
||||
IP net.IP `json:"ip"`
|
||||
}
|
||||
|
||||
type clientListJSON struct {
|
||||
@@ -70,7 +70,7 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||
data.Clients = append(data.Clients, cj)
|
||||
}
|
||||
|
||||
clients.ipToRC.Range(func(ip net.IP, v interface{}) (cont bool) {
|
||||
clients.ipToRC.Range(func(ip net.IP, v any) (cont bool) {
|
||||
rc, ok := v.(*RuntimeClient)
|
||||
if !ok {
|
||||
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
|
||||
@@ -81,20 +81,9 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||
cj := runtimeClientJSON{
|
||||
WHOISInfo: rc.WHOISInfo,
|
||||
|
||||
Name: rc.Host,
|
||||
IP: ip,
|
||||
}
|
||||
|
||||
cj.Source = "etc/hosts"
|
||||
switch rc.Source {
|
||||
case ClientSourceDHCP:
|
||||
cj.Source = "DHCP"
|
||||
case ClientSourceRDNS:
|
||||
cj.Source = "rDNS"
|
||||
case ClientSourceARP:
|
||||
cj.Source = "ARP"
|
||||
case ClientSourceWHOIS:
|
||||
cj.Source = "WHOIS"
|
||||
Name: rc.Host,
|
||||
Source: rc.Source,
|
||||
IP: ip,
|
||||
}
|
||||
|
||||
data.RuntimeClients = append(data.RuntimeClients, cj)
|
||||
@@ -107,13 +96,7 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
e := json.NewEncoder(w).Encode(data)
|
||||
if e != nil {
|
||||
aghhttp.Error(
|
||||
r,
|
||||
w,
|
||||
http.StatusInternalServerError,
|
||||
"Failed to encode to json: %v",
|
||||
e,
|
||||
)
|
||||
aghhttp.Error(r, w, http.StatusInternalServerError, "failed to encode to json: %v", e)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -279,9 +262,9 @@ func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http
|
||||
func (clients *clientsContainer) findRuntime(ip net.IP, idStr string) (cj *clientJSON) {
|
||||
rc, ok := clients.FindRuntimeClient(ip)
|
||||
if !ok {
|
||||
// It is still possible that the IP used to be in the runtime
|
||||
// clients list, but then the server was reloaded. So, check
|
||||
// the DNS server's blocked IP list.
|
||||
// It is still possible that the IP used to be in the runtime clients
|
||||
// list, but then the server was reloaded. So, check the DNS server's
|
||||
// blocked IP list.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2428.
|
||||
disallowed, rule := clients.dnsServer.IsBlockedClient(ip, idStr)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"github.com/google/renameio/maybe"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -27,15 +28,36 @@ const (
|
||||
filterDir = "filters" // cache location for downloaded filters, it's under DataDir
|
||||
)
|
||||
|
||||
// logSettings
|
||||
// logSettings are the logging settings part of the configuration file.
|
||||
//
|
||||
// TODO(a.garipov): Put them into a separate object.
|
||||
type logSettings struct {
|
||||
LogCompress bool `yaml:"log_compress"` // Compress determines if the rotated log files should be compressed using gzip (default: false)
|
||||
LogLocalTime bool `yaml:"log_localtime"` // If the time used for formatting the timestamps in is the computer's local time (default: false [UTC])
|
||||
LogMaxBackups int `yaml:"log_max_backups"` // Maximum number of old log files to retain (MaxAge may still cause them to get deleted)
|
||||
LogMaxSize int `yaml:"log_max_size"` // Maximum size in megabytes of the log file before it gets rotated (default 100 MB)
|
||||
LogMaxAge int `yaml:"log_max_age"` // MaxAge is the maximum number of days to retain old log files
|
||||
LogFile string `yaml:"log_file"` // Path to the log file. If empty, write to stdout. If "syslog", writes to syslog
|
||||
Verbose bool `yaml:"verbose"` // If true, verbose logging is enabled
|
||||
// File is the path to the log file. If empty, logs are written to stdout.
|
||||
// If "syslog", logs are written to syslog.
|
||||
File string `yaml:"log_file"`
|
||||
|
||||
// MaxBackups is the maximum number of old log files to retain.
|
||||
//
|
||||
// NOTE: MaxAge may still cause them to get deleted.
|
||||
MaxBackups int `yaml:"log_max_backups"`
|
||||
|
||||
// MaxSize is the maximum size of the log file before it gets rotated, in
|
||||
// megabytes. The default value is 100 MB.
|
||||
MaxSize int `yaml:"log_max_size"`
|
||||
|
||||
// MaxAge is the maximum duration for retaining old log files, in days.
|
||||
MaxAge int `yaml:"log_max_age"`
|
||||
|
||||
// Compress determines, if the rotated log files should be compressed using
|
||||
// gzip.
|
||||
Compress bool `yaml:"log_compress"`
|
||||
|
||||
// LocalTime determines, if the time used for formatting the timestamps in
|
||||
// is the computer's local time.
|
||||
LocalTime bool `yaml:"log_localtime"`
|
||||
|
||||
// Verbose determines, if verbose (aka debug) logging is enabled.
|
||||
Verbose bool `yaml:"verbose"`
|
||||
}
|
||||
|
||||
// osConfig contains OS-related configuration.
|
||||
@@ -187,6 +209,7 @@ var config = &configuration{
|
||||
Ratelimit: 20,
|
||||
RefuseAny: true,
|
||||
AllServers: false,
|
||||
HandleDDR: true,
|
||||
FastestTimeout: timeutil.Duration{
|
||||
Duration: fastip.DefaultPingWaitTimeout,
|
||||
},
|
||||
@@ -222,11 +245,11 @@ var config = &configuration{
|
||||
},
|
||||
},
|
||||
logSettings: logSettings{
|
||||
LogCompress: false,
|
||||
LogLocalTime: false,
|
||||
LogMaxBackups: 0,
|
||||
LogMaxSize: 100,
|
||||
LogMaxAge: 3,
|
||||
Compress: false,
|
||||
LocalTime: false,
|
||||
MaxBackups: 0,
|
||||
MaxSize: 100,
|
||||
MaxAge: 3,
|
||||
},
|
||||
OSConfig: &osConfig{},
|
||||
SchemaVersion: currentSchemaVersion,
|
||||
@@ -301,27 +324,28 @@ func parseConfig() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
uc := aghalg.UniqChecker{}
|
||||
addPorts(
|
||||
uc,
|
||||
tcpPort(config.BindPort),
|
||||
tcpPort(config.BetaBindPort),
|
||||
udpPort(config.DNS.Port),
|
||||
)
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
addPorts(tcpPorts, tcpPort(config.BindPort), tcpPort(config.BetaBindPort))
|
||||
|
||||
udpPorts := aghalg.UniqChecker[udpPort]{}
|
||||
addPorts(udpPorts, udpPort(config.DNS.Port))
|
||||
|
||||
if config.TLS.Enabled {
|
||||
addPorts(
|
||||
uc,
|
||||
// TODO(e.burkov): Consider adding a udpPort with the same value if
|
||||
// we ever support the HTTP/3 for web admin interface.
|
||||
tcpPorts,
|
||||
tcpPort(config.TLS.PortHTTPS),
|
||||
tcpPort(config.TLS.PortDNSOverTLS),
|
||||
udpPort(config.TLS.PortDNSOverQUIC),
|
||||
tcpPort(config.TLS.PortDNSCrypt),
|
||||
)
|
||||
|
||||
// TODO(e.burkov): Consider adding a udpPort with the same value when
|
||||
// we add support for HTTP/3 for web admin interface.
|
||||
addPorts(udpPorts, udpPort(config.TLS.PortDNSOverQUIC))
|
||||
}
|
||||
if err = uc.Validate(aghalg.IntIsBefore); err != nil {
|
||||
return fmt.Errorf("validating ports: %w", err)
|
||||
if err = tcpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating tcp ports: %w", err)
|
||||
} else if err = udpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating udp ports: %w", err)
|
||||
}
|
||||
|
||||
if !checkFiltersUpdateIntervalHours(config.DNS.FiltersUpdateIntervalHours) {
|
||||
@@ -341,23 +365,11 @@ type udpPort int
|
||||
// tcpPort is the port number for TCP protocol.
|
||||
type tcpPort int
|
||||
|
||||
// addPorts is a helper for ports validation. It skips zero ports. Each of
|
||||
// ports should be either a udpPort or a tcpPort.
|
||||
func addPorts(uc aghalg.UniqChecker, ports ...interface{}) {
|
||||
// addPorts is a helper for ports validation that skips zero ports.
|
||||
func addPorts[T tcpPort | udpPort](uc aghalg.UniqChecker[T], ports ...T) {
|
||||
for _, p := range ports {
|
||||
// Use separate cases for tcpPort and udpPort so that the untyped
|
||||
// constant zero is converted to the appropriate type.
|
||||
switch p := p.(type) {
|
||||
case tcpPort:
|
||||
if p != 0 {
|
||||
uc.Add(p)
|
||||
}
|
||||
case udpPort:
|
||||
if p != 0 {
|
||||
uc.Add(p)
|
||||
}
|
||||
default:
|
||||
// Go on.
|
||||
if p != 0 {
|
||||
uc.Add(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,13 +388,14 @@ func readConfigFile() (fileData []byte, err error) {
|
||||
}
|
||||
|
||||
// Saves configuration to the YAML file and also saves the user filter contents to a file
|
||||
func (c *configuration) write() error {
|
||||
func (c *configuration) write() (err error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
if Context.auth != nil {
|
||||
config.Users = Context.auth.GetUsers()
|
||||
}
|
||||
|
||||
if Context.tls != nil {
|
||||
tlsConf := tlsConfigSettings{}
|
||||
Context.tls.WriteDiskConfig(&tlsConf)
|
||||
@@ -428,19 +441,20 @@ func (c *configuration) write() error {
|
||||
config.Clients.Persistent = Context.clients.forConfig()
|
||||
|
||||
configFile := config.getConfigFilename()
|
||||
log.Debug("Writing YAML file: %s", configFile)
|
||||
yamlText, err := yaml.Marshal(&config)
|
||||
if err != nil {
|
||||
log.Error("Couldn't generate YAML file: %s", err)
|
||||
log.Debug("writing config file %q", configFile)
|
||||
|
||||
return err
|
||||
buf := &bytes.Buffer{}
|
||||
enc := yaml.NewEncoder(buf)
|
||||
enc.SetIndent(2)
|
||||
|
||||
err = enc.Encode(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating config file: %w", err)
|
||||
}
|
||||
|
||||
err = maybe.WriteFile(configFile, yamlText, 0o644)
|
||||
err = maybe.WriteFile(configFile, buf.Bytes(), 0o644)
|
||||
if err != nil {
|
||||
log.Error("Couldn't save YAML config: %s", err)
|
||||
|
||||
return err
|
||||
return fmt.Errorf("writing config file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -189,7 +189,7 @@ func registerControlHandlers() {
|
||||
RegisterAuthHandlers()
|
||||
}
|
||||
|
||||
func httpRegister(method, url string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
func httpRegister(method, url string, handler http.HandlerFunc) {
|
||||
if method == "" {
|
||||
// "/dns-query" handler doesn't need auth, gzip and isn't restricted by 1 HTTP method
|
||||
Context.mux.HandleFunc(url, postInstall(handler))
|
||||
|
||||
@@ -105,19 +105,22 @@ type checkConfResp struct {
|
||||
|
||||
// validateWeb returns error is the web part if the initial configuration can't
|
||||
// be set.
|
||||
func (req *checkConfReq) validateWeb(uc aghalg.UniqChecker) (err error) {
|
||||
func (req *checkConfReq) validateWeb(tcpPorts aghalg.UniqChecker[tcpPort]) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "validating ports: %w") }()
|
||||
|
||||
port := req.Web.Port
|
||||
addPorts(uc, tcpPort(config.BetaBindPort), tcpPort(port))
|
||||
if err = uc.Validate(aghalg.IntIsBefore); err != nil {
|
||||
// Avoid duplicating the error into the status of DNS.
|
||||
uc[port] = 1
|
||||
portInt := req.Web.Port
|
||||
port := tcpPort(portInt)
|
||||
addPorts(tcpPorts, tcpPort(config.BetaBindPort), port)
|
||||
if err = tcpPorts.Validate(); err != nil {
|
||||
// Reset the value for the port to 1 to make sure that validateDNS
|
||||
// doesn't throw the same error, unless the same TCP port is set there
|
||||
// as well.
|
||||
tcpPorts[port] = 1
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
switch port {
|
||||
switch portInt {
|
||||
case 0, config.BindPort:
|
||||
return nil
|
||||
default:
|
||||
@@ -125,21 +128,18 @@ func (req *checkConfReq) validateWeb(uc aghalg.UniqChecker) (err error) {
|
||||
// unbound after install.
|
||||
}
|
||||
|
||||
return aghnet.CheckPort("tcp", req.Web.IP, port)
|
||||
return aghnet.CheckPort("tcp", req.Web.IP, portInt)
|
||||
}
|
||||
|
||||
// validateDNS returns error if the DNS part of the initial configuration can't
|
||||
// be set. canAutofix is true if the port can be unbound by AdGuard Home
|
||||
// automatically.
|
||||
func (req *checkConfReq) validateDNS(uc aghalg.UniqChecker) (canAutofix bool, err error) {
|
||||
func (req *checkConfReq) validateDNS(
|
||||
tcpPorts aghalg.UniqChecker[tcpPort],
|
||||
) (canAutofix bool, err error) {
|
||||
defer func() { err = errors.Annotate(err, "validating ports: %w") }()
|
||||
|
||||
port := req.DNS.Port
|
||||
addPorts(uc, udpPort(port))
|
||||
if err = uc.Validate(aghalg.IntIsBefore); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
switch port {
|
||||
case 0:
|
||||
return false, nil
|
||||
@@ -148,6 +148,11 @@ func (req *checkConfReq) validateDNS(uc aghalg.UniqChecker) (canAutofix bool, er
|
||||
// by AdGuard Home for web interface.
|
||||
default:
|
||||
// Check TCP as well.
|
||||
addPorts(tcpPorts, tcpPort(port))
|
||||
if err = tcpPorts.Validate(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = aghnet.CheckPort("tcp", req.DNS.IP, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -185,13 +190,12 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
resp := &checkConfResp{}
|
||||
uc := aghalg.UniqChecker{}
|
||||
|
||||
if err = req.validateWeb(uc); err != nil {
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
if err = req.validateWeb(tcpPorts); err != nil {
|
||||
resp.Web.Status = err.Error()
|
||||
}
|
||||
|
||||
if resp.DNS.CanAutofix, err = req.validateDNS(uc); err != nil {
|
||||
if resp.DNS.CanAutofix, err = req.validateDNS(tcpPorts); err != nil {
|
||||
resp.DNS.Status = err.Error()
|
||||
} else if !req.DNS.IP.IsUnspecified() {
|
||||
resp.StaticIP = handleStaticIP(req.DNS.IP, req.SetStaticIP)
|
||||
@@ -212,7 +216,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request)
|
||||
func handleStaticIP(ip net.IP, set bool) staticIPJSON {
|
||||
resp := staticIPJSON{}
|
||||
|
||||
interfaceName := aghnet.GetInterfaceByIP(ip)
|
||||
interfaceName := aghnet.InterfaceByIP(ip)
|
||||
resp.Static = "no"
|
||||
|
||||
if len(interfaceName) == 0 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user