Compare commits

...

64 Commits

Author SHA1 Message Date
Ainar Garipov
6d0a43aad6 Pull request: client: upd i18n
Merge in DNS/adguard-home from upd-i18n to master

Squashed commit of the following:

commit e2f9e9f52a424b7c13beebfc2f8fea3814d3b2f4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 8 13:48:17 2022 +0300

    client: upd i18n
2022-02-08 13:53:58 +03:00
Eugene Burkov
1bc2186c2d Pull request: upd changelog
Merge in DNS/adguard-home from changelog-right-now to master

Squashed commit of the following:

commit b391a1f8ac666de67ad6d00c9cbf6e90614f16c7
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Feb 7 20:18:25 2022 +0300

    fix changelog

commit 39878b75c9ecc91668be759d4cc033961c91c2c5
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Feb 7 20:15:43 2022 +0300

    all: log changes
2022-02-07 20:23:07 +03:00
Eugene Burkov
6584c300b8 Pull request: 4254 fix optimistic
Merge in DNS/adguard-home from 4254-fix-optimistic to master

Updates #4254.

Squashed commit of the following:

commit 652e2c2ab9405b9a6ed5d153b6b508e3b87ce66e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Feb 7 18:55:34 2022 +0300

    all: upd proxy
2022-02-07 19:01:51 +03:00
Ainar Garipov
dc480ae70f Pull request #1432: all: add gh milestone links to chlog
Merge in DNS/adguard-home from chlog-ms-links to master

Squashed commit of the following:

commit 97156f1452a7713e5e8d66a9b5eeac25fb97ab04
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Feb 4 17:56:58 2022 +0300

    all: add gh milestone links to chlog
2022-02-04 18:18:28 +03:00
Eugene Burkov
e783564084 Pull request: 4238 response filtering
Merge in DNS/adguard-home from 4238-response-filtering to master

Closes #4238.

Squashed commit of the following:

commit 2113f83c617a396a39f910bb8df939364fedf391
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Feb 3 21:04:25 2022 +0300

    dnsforward: restore a bit

commit f78607ed97892557c6bd6f3c3332f0bae01c1987
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Feb 3 20:52:45 2022 +0300

    all: imp code, docs

commit 646074ce141e8ac12a972f46d071389a2ce124e4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Feb 3 20:37:05 2022 +0300

    all: log changes

commit 94556d810549370fc455bcf14537fa1d2783eed1
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Feb 3 20:30:57 2022 +0300

    all: imp test upstream, cover resp filtering

commit 63e7721822a049734a390c7d7ea6d8416a43c8b5
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Feb 1 21:58:08 2022 +0300

    all: filter response by rrtype
2022-02-03 21:19:32 +03:00
Ainar Garipov
0ee34534c6 Pull request: all: switch to SOURCE_DATE_EPOCH for source date
Closes #4221.

Squashed commit of the following:

commit c84a5699280cf4c0b1c2ed034a44f05ffc74d30d
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 1 21:13:30 2022 +0300

    all: switch to SOURCE_DATE_EPOCH for source date
2022-02-01 21:44:01 +03:00
Ainar Garipov
9146df5493 Pull request: scripts: add link to platforms page
Closes #4209.

Squashed commit of the following:

commit 12d99e7454ff01e00f29e51d002147a04a77a2b3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 1 19:55:31 2022 +0300

    scripts: imp docs

commit 12c4dabea2bac04601202a05d0c820ff2e32c93e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 1 19:49:16 2022 +0300

    scripts: add link to platforms page
2022-02-01 20:00:32 +03:00
Ainar Garipov
76fa60498e Pull request: all: imp ann url
Updates #4209.

Squashed commit of the following:

commit 0c31a59c5bf6bcc27a4779adf226d9a1ac9eece1
Merge: 803f32db 8455940b
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 1 19:33:55 2022 +0300

    Merge branch 'master' into 4209-ann-url

commit 803f32dbc7276077a4374ed0f5e0a1fa36f91c9b
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 1 14:46:47 2022 +0300

    client: add manual update link to update topline

commit ca375b52fa53503a3987b9723eb9a1d74878e890
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jan 31 20:49:42 2022 +0300

    all: imp ann url
2022-02-01 19:42:07 +03:00
Ainar Garipov
8455940b59 Pull request: all: upd quic-go
Merge in DNS/adguard-home from upd-quic-go to master

Squashed commit of the following:

commit c7f0ab02a54ac435b6e0040dd221d819cf3ecdd4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 1 14:33:26 2022 +0300

    all: upd quic-go
2022-02-01 14:39:05 +03:00
Ildar Kamalov
2d46aa7121 Pull request: 4212 fix query log search results
Closes #4212.

Squashed commit of the following:

commit cd854e5bf71953c753c690c28b5571f2c8b1ea0f
Merge: 8532ca80 bf9b35b9
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jan 31 20:10:17 2022 +0300

    Merge branch 'master' into 4212-logs

commit 8532ca80d135e4c306ac4d0c999475d77ba51a02
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Jan 31 19:22:52 2022 +0300

    fix lint

commit 1a85074180d95d7a7aad854c75a7a811aee719e9
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Jan 31 19:14:54 2022 +0300

    client: fix query log search results
2022-01-31 20:14:09 +03:00
Ainar Garipov
bf9b35b9c6 Pull request: client: upd manual upd link
Closes #4208.

Squashed commit of the following:

commit 4ae27b5f7cd6b0f4ec0c9041d92c4d1ac00dd622
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jan 31 18:34:18 2022 +0300

    client: upd manual upd link
2022-01-31 18:40:21 +03:00
Eugene Burkov
f9aa5ae86a Pull request: 4216 simpl hosts
Merge in DNS/adguard-home from 4216-hosts-explode to master

Updates #4216.

Squashed commit of the following:

commit a6ed131923496d9bbd1d80c652d4584951528c4a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 27 19:11:23 2022 +0300

    aghnet: imp docs

commit 25cca065c3c6dc227288cdd0803dc3ff8f9c3ca4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 27 18:53:16 2022 +0300

    aghnet: simpl hosts container
2022-01-27 20:18:52 +03:00
Ainar Garipov
642d68c482 Pull request: scripts: do not require sudo where not needed
Merge in DNS/adguard-home from fix-install to master

Squashed commit of the following:

commit 54c3b18c946c88def396f82a941b0b35eb6ef60d
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Jan 26 19:08:48 2022 +0300

    scripts: do not require sudo where not needed
2022-01-26 19:19:16 +03:00
Ainar Garipov
5ff7cdbac8 Pull request: all: fix chlog, imp
Merge in DNS/adguard-home from fix-chlog to master

Squashed commit of the following:

commit e69da2f574923b95ac3d0fa9057fffe2a716b5be
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Jan 26 14:41:04 2022 +0300

    all: fix chlog, imp
2022-01-26 14:47:50 +03:00
Ainar Garipov
504c54ab0e Pull request: all: imp tls cipher selection
Closes #2993.

Squashed commit of the following:

commit 6c521e56de024bf92ab7489ed2289da6bce1f3dc
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 25 21:39:48 2022 +0300

    all: imp tls cipher selection
2022-01-26 14:39:34 +03:00
Ainar Garipov
90c17c79de Pull request: home: mv local domain name to dhcp setts
Closes #3367.

Squashed commit of the following:

commit e2cabcac2d91af24b9e5f4ac8f78daf5e8d339b9
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 25 19:35:31 2022 +0300

    home: imp test, skip dhcp test on windows

commit e58053f11e081630ad4e8d1e77a7a74226029db0
Merge: ff2fe87d 0b72bcc5
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 25 19:10:25 2022 +0300

    Merge branch 'master' into 3367-dhcp-local-domain-name

commit ff2fe87d8cab12e60d045be636e366e392d6d96f
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 30 20:55:34 2021 +0300

    home: mv local domain name to dhcp setts
2022-01-25 19:47:02 +03:00
Eugene Burkov
0b72bcc5a1 Pull request: 1730 bogus cidr
Merge in DNS/adguard-home from 1730-bogus-cidr to master

Closes #1730.

Squashed commit of the following:

commit 0be54259ca4edb8752e9f7e5ea5104a2b51ed440
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 25 18:50:01 2022 +0300

    all: imp log of changes

commit 59fb7a8c469216823ff54621ec40a4d084836132
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 25 18:46:34 2022 +0300

    all: log changes

commit 9206b13dd715fdf1180d1d572d1b80024b9e6592
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 25 18:41:26 2022 +0300

    all: upd dnsproxy
2022-01-25 18:54:37 +03:00
Ainar Garipov
dc14f89c9f Pull request: 4162 fix theme color
Updates #4162.

* commit '2263adbbe0c14cb914451d131d94ab6fd236852c':
  Update login.html
  Update install.html
  Update index.html
2022-01-25 18:25:47 +03:00
Ainar Garipov
2263adbbe0 Merge branch 'master' into 4162-fix-theme-color 2022-01-25 18:20:37 +03:00
Ainar Garipov
e29261516f Pull request: all: upd chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit ad258a27abfce7b1060d9937b446f6e794f8c172
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 25 18:15:59 2022 +0300

    all: upd chlog
2022-01-25 18:20:26 +03:00
Ainar Garipov
f12eaf29a2 Pull request: client: upd i18n
Updates #2643.

Squashed commit of the following:

commit bd6bc0aeaa1bd928ae39642691b913befbc0f396
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 25 14:04:10 2022 +0300

    client: upd i18n
2022-01-25 14:08:41 +03:00
Ainar Garipov
3e2ab87293 Pull request: all: upd dnsproxy
Merge in DNS/adguard-home from imp-logs to master

Squashed commit of the following:

commit bff4c3757b61db63320af72e1af56649f6f70a50
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jan 24 17:25:34 2022 +0300

    all: upd dnsproxy
2022-01-24 17:39:39 +03:00
Eugene Burkov
41e8db4221 Pull request: client: upd i18n
Merge in DNS/adguard-home from upd-i18n to master

Squashed commit of the following:

commit e3dfb6cd66813d45591f74c9cdddab8b61143db3
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 24 14:52:19 2022 +0300

    client: upd i18n
2022-01-24 15:02:47 +03:00
Eugene Burkov
3f5605c42e Pull request: 2846 cover aghnet vol.1
Merge in DNS/adguard-home from 2846-cover-aghnet-vol.1 to master

Updates #2846.

Squashed commit of the following:

commit 368e75b0bacb290f9929b8a5a682b06f2d75df6a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 21 19:11:59 2022 +0300

    aghnet: imp tests

commit 8bb3e2a1680fd30294f7c82693891ffb19474c6a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 21 18:27:06 2022 +0300

    aghnet: rm unused test

commit 28d8e64880f845810d0af629e5d1f06b9bde5b28
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 21 18:18:22 2022 +0300

    aghnet: cover with tests
2022-01-21 19:21:38 +03:00
Ildar Kamalov
f7ff02f3b1 Pull request: 3971 fix client id error message
Updates #3971

Squashed commit of the following:

commit f6b855a16daaec7bfca1e1653b4b9c4180c2d80e
Merge: 0cb31dbb 5ec4a4da
Author: Ildar Kamalov <ik@adguard.com>
Date:   Thu Jan 20 18:19:20 2022 +0300

    Merge branch 'master' into 3971-client-id

commit 0cb31dbbea785fb5ba11a8efe2b6653aece7cd97
Author: Natalia Sokolova <n.sokolova@adguard.com>
Date:   Thu Jan 20 11:41:06 2022 +0300

    client/src/__locales/en.json edited online with Bitbucket

commit 7999f260d83adcb2fc8d5d5e40cb1934e0333873
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Jan 19 15:58:18 2022 +0300

    client: fix client id error message
2022-01-20 18:24:21 +03:00
Eugene Burkov
5ec4a4dab8 Pull request: 4142 stats panic
Merge in DNS/adguard-home from 4142-stats-panic to master

Updates #4142.

Squashed commit of the following:

commit bf168f50ac86bdfdab73bf7285705f09f87b6c72
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 20 17:13:41 2022 +0300

    stats: imp more

commit bb638211da7d0c51959ded2dacb72faea00befb4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 20 17:09:31 2022 +0300

    stats: imp code quality

commit 27ac52f15e4e0f4112ce7a6b47b03f963463393e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 20 17:00:09 2022 +0300

    stats: recover panic on init

commit 1ffcebbb9062438170b010e1c7bad3c6cef4cfc1
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 20 14:19:01 2022 +0300

    all: fix some typos
2022-01-20 17:19:09 +03:00
Ainar Garipov
13871977f9 Pull request: all: upd dnsproxy
Updates #4128.

Squashed commit of the following:

commit c177750f3f4d3ae29133154eca4dfe4051de1310
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Jan 20 17:01:02 2022 +0300

    all: upd dnsproxy
2022-01-20 17:05:59 +03:00
Ildar Kamalov
2fdda8a22c Pull request: 4143 sort client ids
Merge in DNS/adguard-home from 4143-clients-sort to master

Updates #4143.

Squashed commit of the following:

commit a4b547eb46a54bdfdc7d342fab5f8ecfa54f5d06
Merge: d369c11c d82b2902
Author: Ildar Kamalov <ik@adguard.com>
Date:   Thu Jan 20 11:58:42 2022 +0300

    Merge branch 'master' into 4143-clients-sort

commit d369c11c69665510043f63e0283e1ca1b2974289
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Jan 19 16:53:39 2022 +0300

    client: fix sort ip method

commit d767a1199c37ad9df7f3bc2d362d840b0226d836
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Jan 19 16:23:23 2022 +0300

    client: sort client ids
2022-01-20 12:23:59 +03:00
Eugene Burkov
d82b290251 Pull request: 4095 fix duplicating port
Merge in DNS/adguard-home from 4095-port-3000 to master

Updates #4095.

Squashed commit of the following:

commit 968cc806264898523d29c4ec20b3ce6a69abb09c
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 20:26:33 2022 +0300

    home: fix typo

commit 03c6798db6a4ca726a7b5a683e475a8a74f79fe1
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 20:20:34 2022 +0300

    all: more naming imps

commit d3d417fcb24a1859f53a743b3533faa81b6bef19
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 20:10:14 2022 +0300

    aghalgo: rename into aghalg

commit 6e106006d07a747ff4ddf1271532106c3a3e2b20
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 20:05:43 2022 +0300

    all: imp names, docs

commit 12c8d9fde0d0cc5b953da30b042171ba7c53da5d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 19:57:21 2022 +0300

    all: fix log of changes

commit 49c7a705b9b1ad8f2ef68fa807f9b6b8c447b421
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 19 19:51:00 2022 +0300

    home: fix duplicating port 3000
2022-01-19 20:45:50 +03:00
Ainar Garipov
eb15304ff4 scripts: imp sh lint 2022-01-19 15:06:23 +03:00
Eugene Burkov
1a3bf5ebda Pull request: 4133 empty rewrite
Merge in DNS/adguard-home from 4133-empty-rewrite to master

Closes #4133.

Squashed commit of the following:

commit 4d2313c211c3955922d340c006b323c65e5e5ba4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 18 21:36:21 2022 +0300

    all: log changes

commit 5b8e392a2225c215fc117223d3f6553f8bdf21cd
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 18 21:32:57 2022 +0300

    all: upd urlfilter
2022-01-19 14:19:12 +03:00
Agneev Mukherjee
15956f4511 Update login.html 2022-01-18 18:38:57 +05:30
Agneev Mukherjee
09d0ce4578 Update install.html 2022-01-18 18:38:37 +05:30
Agneev Mukherjee
9735a35123 Update index.html 2022-01-18 18:38:22 +05:30
Ainar Garipov
813a06d09a Pull request: home: show version in install api
Closes #4026.

Squashed commit of the following:

commit bcd1315a10e819daee3aee323427d90a27860b4a
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 18 14:57:49 2022 +0300

    openapi: fix example

commit b56e27c5ac1fc7c3f595057d77607479d72ec50a
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Jan 18 14:55:51 2022 +0300

    client: show version on install page

commit 95dfbfaa1235deef7b55e51457d11c677f6ef6b5
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Jan 18 14:29:08 2022 +0300

    home: show version in install api
2022-01-18 15:05:34 +03:00
Eugene Burkov
061136508e Pull request: 4120 service domain validation
Merge in DNS/adguard-home from 4120-fix-services to master

Closes #4120.

Squashed commit of the following:

commit ca2e5faf64f567cc6647a300181712236158e69d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 18 14:14:54 2022 +0300

    dnsforward: imp docs

commit 9ed5f536e691dcdee5b7c94e161c738d31ff8588
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 18 13:50:33 2022 +0300

    dnsforward: fix reverse domain validation
2022-01-18 14:20:25 +03:00
Ainar Garipov
008f58c863 Pull request: all: upd dnsproxy
Updates #4065.

Squashed commit of the following:

commit d65d2e3a783910b9cb95c5bcfbcf1af11da666d5
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jan 17 18:47:17 2022 +0300

    all: upd dnsproxy
2022-01-17 18:54:00 +03:00
Eugene Burkov
0e4ffd339f Pull request: 4074 fix upstream test
Merge in DNS/adguard-home from 4074-upstream-test to master

Updates #4074.

Squashed commit of the following:

commit 0de155b1e175a892b259791ff6d6e6f351bcfcf2
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 12 19:20:01 2022 +0500

    dnsforward: fix upstream test
2022-01-13 15:05:44 +03:00
Eugene Burkov
1458600c37 Pull request: 4079 fix hosts container aliases
Merge in DNS/adguard-home from 4079-hosts-again to master

Updates #4079.

Squashed commit of the following:

commit 6aa8cbf32e8e47ba46bf5fba7681a10b68b4bc01
Merge: 19dba371 34c95f99
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 12 14:05:30 2022 +0500

    Merge branch 'master' into 4079-hosts-again

commit 19dba371cc30ab8b75b0116833f4ecf0ef0f182f
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 12 14:05:20 2022 +0500

    aghnet: imp docs

commit 9f341eb8ee4ba8468240bc3eeeb4951a3f7f5e6d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 10 18:44:17 2022 +0500

    aghnet: fix races

commit fd66191c7637c8584711e5bb8186494327ce0f87
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 6 17:21:14 2022 +0500

    aghnet: fix hosts container aliases
2022-01-12 12:14:59 +03:00
Eugene Burkov
34c95f99f8 Pull request: 4046 darwin service message
Merge in DNS/adguard-home from 4046-log-dir to master

Closes #4046.

Squashed commit of the following:

commit 05140550b14f477f52487c575f56428ce9e6fa10
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 5 17:54:11 2022 +0500

    all: add macOS service msg
2022-01-11 21:33:14 +03:00
Ainar Garipov
e9c59b098e Pull request: all: upd chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit 737525aa065bff7b1ec99876447bbc2f961a4c4d
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 23:23:52 2021 +0300

    all: upd chlog
2021-12-30 13:36:04 +03:00
Ainar Garipov
a0bb5ce8a4 Pull request: all: upd dnsproxy
Updates #4042.

Squashed commit of the following:

commit 7531b974a6142fafee825ce9ca2ea202619b95af
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 22:01:54 2021 +0300

    all: upd dnsproxy
2021-12-29 22:09:46 +03:00
Ainar Garipov
01947bedb4 Pull request: all: upd chlog, bamboo
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit 2607bd4f6734735c6b100e657a121726783f7ec4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 20:26:16 2021 +0300

    all: fmt chlog

commit fc379e379515a2bc5b2cd8e8324a95c49b908773
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 20:24:16 2021 +0300

    all: upd chlog, bamboo
2021-12-29 20:31:22 +03:00
Ainar Garipov
a6ca824064 Pull request: client: upd i18n
Updates #2643.

Squashed commit of the following:

commit bc3de579e00762bc2c4b62fb1f7ba73837c10bff
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 15:37:29 2021 +0300

    client: upd si-lk i18n again

commit 2cd5436b6e8c1918855aff58dd0958fe47b47e90
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 29 15:08:21 2021 +0300

    client: upd i18n
2021-12-29 15:44:48 +03:00
Ainar Garipov
380cff07f2 Pull request: all: opt log levels more
Updates #3929.

Squashed commit of the following:

commit 0d4aadeff1c4de1440795faf83eb072c46392ff3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 28 16:34:44 2021 +0300

    all: opt log levels more
2021-12-28 17:25:43 +03:00
Ainar Garipov
d2ce06e1ca Pull request: all: imp uniq validation err msgs
Updates #3975.

Squashed commit of the following:

commit f8578c2afb1bb5786e7b855a1715e0757bc08510
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 28 16:39:13 2021 +0300

    aghalgo: imp docs

commit d9fc625f7c4ede2cf4b0683ad5efd0ddf9b966b1
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 28 16:21:24 2021 +0300

    all: imp uniq validation err msgs
2021-12-28 17:00:52 +03:00
Ainar Garipov
2ed1f939b5 Pull request: aghnet: fix ipset init errors
Updates #4027.

Squashed commit of the following:

commit 9ac0cc27ca94e630cc321c90b60b271499af4d9b
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 20:26:22 2021 +0300

    aghnet: fix ipset init errors
2021-12-27 20:54:00 +03:00
Ainar Garipov
dea8a585f8 Pull request: filtering: fix rw to subdomain
Updates #4016.

Squashed commit of the following:

commit 83bb15c5a5098103cd17e76b49f456fb4fa73408
Merge: 81905503 313555b1
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 19:36:44 2021 +0300

    Merge branch 'master' into 4016-rw-subdomain

commit 81905503c977c004d7ddca1d4e7537bf76443a6e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 19:35:51 2021 +0300

    filtering: fix self reqs

commit b706f481f00232d28dade0bd747a7496753c7deb
Merge: 29cf83de 661f4ece
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 19:13:08 2021 +0300

    Merge branch 'master' into 4016-rw-subdomain

commit 29cf83de8e3ff60ea1c471c2a161055b1377392d
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 19:07:08 2021 +0300

    all: fix docs

commit 9213fd8ec2b81e65b1198ab241400065f14684b1
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Dec 27 18:44:06 2021 +0300

    filtering: fix rw to subdomain
2021-12-27 19:40:39 +03:00
Eugene Burkov
313555b10c Pull request: 3868 log freebsd reload fix
Merge in DNS/adguard-home from 3868-changelog to master

Squashed commit of the following:

commit 92ccf7422c4c1342c160e4806cbf9fb17c22749b
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 27 19:22:47 2021 +0300

    all: log more changes
2021-12-27 19:29:42 +03:00
Eugene Burkov
661f4ece48 Pull request: 3868 imp service uninstall
Merge in DNS/adguard-home from 3868-imp-uninstall to master

Closes #3868.
Updates #3457.

Squashed commit of the following:

commit 6f50713407980c27e5b14bef4dc8839e134ec5c8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 27 19:06:13 2021 +0300

    all: imp openwrt

commit 59f058f8ec7f5ac8cb795bf837c396601652a6ff
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 27 17:26:32 2021 +0300

    all: imp code && docs

commit bab95366b0ffa40d96de5bb8116ec14606e310ed
Merge: 92ebc210 52f36f20
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 27 17:06:25 2021 +0300

    Merge branch 'master' into 3868-imp-uninstall

commit 92ebc210f04d5e02c3eef726017a0d5687f4bc4c
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 27 13:18:58 2021 +0300

    home: imp freebsd script & log changes

commit 583ffc256e9f87cf19da2eca8bbefc9e00ea86cc
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 16 14:08:46 2021 +0300

    all: imp service uninstall
2021-12-27 19:12:40 +03:00
Ainar Garipov
52f36f201e Pull request: filtering: restore rewrite behavior with other question types
Updates #4008.

Squashed commit of the following:

commit babbc29331cfc2603c0c3b0987f5ba926690ec3e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Dec 24 18:46:20 2021 +0300

    filtering: restore rewrite behavior with other question types
2021-12-24 20:14:36 +03:00
Ainar Garipov
46cd974e2a Pull request: all: opt log levels
Updates #3929.

Squashed commit of the following:

commit bfb2361d81a0667c36193484ca125d08e5638b21
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Dec 24 17:23:39 2021 +0300

    all: opt log levels
2021-12-24 17:29:57 +03:00
Eugene Burkov
201ef10de6 Pull request: 3987 Fix nil pointer dereference
Merge in DNS/adguard-home from 3987-fix-nil-deref to master

Updates #3987.
Updates #2846.

Squashed commit of the following:

commit d653e09ce88a8b10b2a17fea1563c419895c714c
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 20:08:51 2021 +0300

    all: log changes

commit c47a4eeacf76fa7df2d01af166dee9d52528ac58
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 19:22:39 2021 +0300

    aghnet: fix windows tests

commit 9c91f14ccfe967ada3c00ddb86d673238e52c12d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 19:09:49 2021 +0300

    aghnet: imp code readability, docs

commit d3df15d1892e4ebfe7f8ea7144e39a0c712fce52
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 18:47:28 2021 +0300

    aghnet: fix nil pointer dereference
2021-12-23 20:16:08 +03:00
Eugene Burkov
d9df7c13be Pull request: 3998 Make hosts rules match exactly
Merge in DNS/adguard-home from 3998-fix-hosts-gen to master

Closes #3998

Squashed commit of the following:

commit b565d51afb6c292dd16accd45b7d37ed386714e8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 16:25:02 2021 +0300

    aghnet: make hosts rules match exactly
2021-12-23 16:35:10 +03:00
Ainar Garipov
64e751e579 Pull request: all: upd dnsproxy
Updates #3977.

Squashed commit of the following:

commit 3aaaacac102cdea04ae46b36d2dd3a3be7d50147
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 23 16:15:11 2021 +0300

    all: upd dnsproxy
2021-12-23 16:25:44 +03:00
Ainar Garipov
e6e5958595 Pull request: 3945 log success
Updates #3945.

* commit 'ebe86ce00ebca3431a96a44c3616af3ac42250ab':
  home: imp auth
  Log successful login attempts in addition to failed ones
2021-12-23 13:58:28 +03:00
Eugene Burkov
ff3df0ec33 Pull request: Update miekg/dns
Merge in DNS/adguard-home from upd-dns-lib to master

Updates #2275.

Squashed commit of the following:

commit 54d0485157ac4f08830ad7d8ca9be49eef87d678
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 23 13:31:34 2021 +0300

    all: upd dns lib
2021-12-23 13:38:38 +03:00
Ainar Garipov
ebe86ce00e Merge branch 'master' into 3945-log-success 2021-12-22 21:29:31 +03:00
Ainar Garipov
d317e19291 home: imp auth 2021-12-22 21:27:36 +03:00
Ainar Garipov
39c4999d2d Pull request: client: imp en i18n
Merge in DNS/adguard-home from en-i18n-safe-browsing to master

Squashed commit of the following:

commit dd32a58c3761818a10386b4a1d9e6871da59c71e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 22 17:31:35 2021 +0300

    client: imp en i18n
2021-12-22 18:14:28 +03:00
Ainar Garipov
7f55bd8461 Pull request: all: temp disable gh notifications
Merge in DNS/adguard-home from temp-disable-notify to master

Squashed commit of the following:

commit c7f1393668e4dfe8681c9ed1c6f2ef45aed9106b
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 22 17:07:37 2021 +0300

    all: temp disable gh notifications
2021-12-22 17:11:41 +03:00
Ainar Garipov
2968a65f14 Pull request: all: upd go, tools, deps
Updates #2275.
Updates #3057.

Squashed commit of the following:

commit da22ad203cec1ef2a5d0a218933ddc3ac03c2ad3
Merge: dbd7e202 779fbe79
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 22 16:26:46 2021 +0300

    Merge branch 'master' into 2275-upd-go

commit dbd7e20209ddc04198e89698b7e3c2750c4d9902
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 22 15:04:17 2021 +0300

    all: upd docker img

commit 269796e3a00f60120a6327d6501f2dde031435c4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 21 21:04:25 2021 +0300

    all: upd go, tools, deps
2021-12-22 16:34:51 +03:00
Ainar Garipov
779fbe79b8 Pull request: scripts: add network-control plug
Updates #3976.

Squashed commit of the following:

commit 49d8a3a2d333c7896530c8a44c5ef06c396b5ae0
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 22 16:20:45 2021 +0300

    scripts: add network-control plug
2021-12-22 16:26:01 +03:00
Matt
da0d1cb754 Log successful login attempts in addition to failed ones 2021-12-15 23:05:51 +00:00
131 changed files with 3451 additions and 2000 deletions

View File

@@ -1,7 +1,7 @@
'name': 'build'
'env':
'GO_VERSION': '1.16'
'GO_VERSION': '1.17'
'NODE_VERSION': '14'
'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint'
'env':
'GO_VERSION': '1.16'
'GO_VERSION': '1.17'
'on':
'push':

View File

@@ -7,14 +7,175 @@ The format is based on
and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
<!--
## [v0.107.1] - 2022-01-25 (APPROX.)
## [v0.108.0] - 2022-06-01 (APPROX.)
-->
### Added
- `windows/arm64` support ([#3057]).
### Changed
- Response filtering is now performed using the record types of the answer
section of messages as opposed to the type of the question ([#4238]).
- Instead of adding the build time information, the build scripts now use the
standardized environment variable [`SOURCE_DATE_EPOCH`][repr] to add the date
of the commit from which the binary was built ([#4221]). This should simplify
reproducible builds for package maintainers and those who compile their own
AdGuard Home.
- The setting `local_domain_name` is now in the `dhcp` block in the
configuration file to avoid confusion ([#3367]).
- The `dns.bogus_nxdomain` configuration file parameter now supports CIDR
notation alongside IP addresses ([#1730]).
#### Configuration Changes
In this release, the schema version has changed from 12 to 13.
- Parameter `local_domain_name`, which in schema versions 12 and earlier used to
be a part of the `dns` object, is now a part of the `dhcp` object:
```yaml
# BEFORE:
'dns':
# …
'local_domain_name': 'lan'
# AFTER:
'dhcp':
# …
'local_domain_name': 'lan'
```
To rollback this change, move the parameter back into `dns` and change the
`schema_version` back to `12`.
### Deprecated
- Go 1.17 support. v0.109.0 will require at least Go 1.18 to build.
### Fixed
- Optimistic cache now responds with expired items even if those can't be
resolved again ([#4254]).
- Unnecessarily complex hosts-related logic leading to infinite recursion in
some cases ([#4216]).
### Removed
- Go 1.16 support.
### Security
- Weaker cipher suites that use the CBC (cipher block chaining) mode of
operation have been disabled ([#2993]).
[#1730]: https://github.com/AdguardTeam/AdGuardHome/issues/1730
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
[#3057]: https://github.com/AdguardTeam/AdGuardHome/issues/3057
[#3367]: https://github.com/AdguardTeam/AdGuardHome/issues/3367
[#4216]: https://github.com/AdguardTeam/AdGuardHome/issues/4216
[#4221]: https://github.com/AdguardTeam/AdGuardHome/issues/4221
[#4238]: https://github.com/AdguardTeam/AdGuardHome/issues/4238
[#4254]: https://github.com/AdguardTeam/AdGuardHome/issues/4254
[repr]: https://reproducible-builds.org/docs/source-date-epoch/
<!--
## [v0.107.4] - 2022-03-01 (APPROX.)
See also the [v0.107.4 GitHub milestone][ms-v0.107.4].
[ms-v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/milestone/41?closed=1
-->
## [v0.107.3] - 2022-01-25
See also the [v0.107.3 GitHub milestone][ms-v0.107.3].
### Added
- Support for a `$dnsrewrite` modifier with an empty `NOERROR` response
([#4133]).
### Fixed
- Wrong set of ports checked for duplicates during the initial setup ([#4095]).
- Incorrectly invalidated service domains ([#4120]).
- Poor testing of domain-specific upstream servers ([#4074]).
- Omitted aliases of hosts specified by another line within the OS's hosts file
([#4079]).
[#4074]: https://github.com/AdguardTeam/AdGuardHome/issues/4074
[#4079]: https://github.com/AdguardTeam/AdGuardHome/issues/4079
[#4095]: https://github.com/AdguardTeam/AdGuardHome/issues/4095
[#4120]: https://github.com/AdguardTeam/AdGuardHome/issues/4120
[#4133]: https://github.com/AdguardTeam/AdGuardHome/issues/4133
[ms-v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/40?closed=1
## [v0.107.2] - 2021-12-29
See also the [v0.107.2 GitHub milestone][ms-v0.107.2].
### Fixed
- Infinite loops when TCP connections time out ([#4042]).
[#4042]: https://github.com/AdguardTeam/AdGuardHome/issues/4042
[ms-v0.107.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/38?closed=1
## [v0.107.1] - 2021-12-29
See also the [v0.107.1 GitHub milestone][ms-v0.107.1].
### Changed
- The validation error message for duplicated allow- and blocklists in DNS
settings now shows the duplicated elements ([#3975]).
### Fixed
- `ipset` initialization bugs ([#4027]).
- Legacy DNS rewrites from a wildcard pattern to a subdomain ([#4016]).
- Service not being stopped before running the `uninstall` service action
([#3868]).
- Broken `reload` service action on FreeBSD.
- Legacy DNS rewrites responding from upstream when a request other than `A` or
`AAAA` is received ([#4008]).
- Panic on port availability check during installation ([#3987]).
- Incorrect application of rules from the OS's hosts files ([#3998]).
[#3868]: https://github.com/AdguardTeam/AdGuardHome/issues/3868
[#3975]: https://github.com/AdguardTeam/AdGuardHome/issues/3975
[#3987]: https://github.com/AdguardTeam/AdGuardHome/issues/3987
[#3998]: https://github.com/AdguardTeam/AdGuardHome/issues/3998
[#4008]: https://github.com/AdguardTeam/AdGuardHome/issues/4008
[#4016]: https://github.com/AdguardTeam/AdGuardHome/issues/4016
[#4027]: https://github.com/AdguardTeam/AdGuardHome/issues/4027
[ms-v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/37?closed=1
## [v0.107.0] - 2021-12-21
See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
### Added
- Upstream server information for responses from cache ([#3772]). Note that old
@@ -251,10 +412,14 @@ In this release, the schema version has changed from 10 to 12.
[#3904]: https://github.com/AdguardTeam/AdGuardHome/issues/3904
[#3933]: https://github.com/AdguardTeam/AdGuardHome/pull/3933
[ms-v0.107.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/23?closed=1
## [v0.106.3] - 2021-05-19
See also the [v0.106.3 GitHub milestone][ms-v0.106.3].
### Added
- Support for reinstall (`-r`) and uninstall (`-u`) flags in the installation
@@ -284,20 +449,28 @@ In this release, the schema version has changed from 10 to 12.
[#3115]: https://github.com/AdguardTeam/AdGuardHome/issues/3115
[#3127]: https://github.com/AdguardTeam/AdGuardHome/issues/3127
[ms-v0.106.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/35?closed=1
## [v0.106.2] - 2021-05-06
See also the [v0.106.2 GitHub milestone][ms-v0.106.2].
### Fixed
- Uniqueness validation for dynamic DHCP leases ([#3056]).
[#3056]: https://github.com/AdguardTeam/AdGuardHome/issues/3056
[ms-v0.106.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/34?closed=1
## [v0.106.1] - 2021-04-30
See also the [v0.106.1 GitHub milestone][ms-v0.106.1].
### Fixed
- Local domain name handling when the DHCP server is disabled ([#3028]).
@@ -308,10 +481,14 @@ In this release, the schema version has changed from 10 to 12.
[#3027]: https://github.com/AdguardTeam/AdGuardHome/issues/3027
[#3028]: https://github.com/AdguardTeam/AdGuardHome/issues/3028
[ms-v0.106.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/33?closed=1
## [v0.106.0] - 2021-04-28
See also the [v0.106.0 GitHub milestone][ms-v0.106.0].
### Added
- The ability to block user for login after configurable number of unsuccessful
@@ -400,11 +577,14 @@ In this release, the schema version has changed from 10 to 12.
[#2994]: https://github.com/AdguardTeam/AdGuardHome/issues/2994
[doq-draft-02]: https://tools.ietf.org/html/draft-ietf-dprive-dnsoquic-02
[ms-v0.106.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/26?closed=1
## [v0.105.2] - 2021-03-10
See also the [v0.105.2 GitHub milestone][ms-v0.105.2].
### Fixed
- Incomplete hostnames with trailing zero-bytes handling ([#2582]).
@@ -416,6 +596,11 @@ In this release, the schema version has changed from 10 to 12.
- Incomplete DNS upstreams validation ([#2674]).
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
### Security
- Session token doesn't contain user's information anymore ([#2470]).
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582
[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
@@ -424,16 +609,14 @@ In this release, the schema version has changed from 10 to 12.
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757
### Security
- Session token doesn't contain user's information anymore ([#2470]).
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
[ms-v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/32?closed=1
## [v0.105.1] - 2021-02-15
See also the [v0.105.1 GitHub milestone][ms-v0.105.1].
### Changed
- Increased HTTP API timeouts ([#2671], [#2682]).
@@ -473,10 +656,14 @@ In this release, the schema version has changed from 10 to 12.
[#2678]: https://github.com/AdguardTeam/AdGuardHome/issues/2678
[#2682]: https://github.com/AdguardTeam/AdGuardHome/issues/2682
[ms-v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/milestone/31?closed=1
## [v0.105.0] - 2021-02-10
See also the [v0.105.0 GitHub milestone][ms-v0.105.0].
### Added
- Added more services to the "Blocked services" list ([#2224], [#2401]).
@@ -574,18 +761,28 @@ In this release, the schema version has changed from 10 to 12.
[#2639]: https://github.com/AdguardTeam/AdGuardHome/issues/2639
[#2646]: https://github.com/AdguardTeam/AdGuardHome/issues/2646
[ms-v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/milestone/27?closed=1
## [v0.104.3] - 2020-11-19
See also the [v0.104.3 GitHub milestone][ms-v0.104.3].
### Fixed
- The accidentally exposed profiler HTTP API ([#2336]).
[#2336]: https://github.com/AdguardTeam/AdGuardHome/issues/2336
[ms-v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/milestone/30?closed=1
## [v0.104.2] - 2020-11-19
See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
### Added
- This changelog :-) ([#2294]).
@@ -610,14 +807,20 @@ In this release, the schema version has changed from 10 to 12.
[#2324]: https://github.com/AdguardTeam/AdGuardHome/issues/2324
[#2325]: https://github.com/AdguardTeam/AdGuardHome/issues/2325
[ms-v0.104.2]: https://github.com/AdguardTeam/AdGuardHome/milestone/28?closed=1
<!--
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.1...HEAD
[v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.0...v0.107.1
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.4...HEAD
[v0.107.4]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...v0.107.4
-->
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.0...HEAD
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.3...HEAD
[v0.107.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.2...v0.107.3
[v0.107.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.1...v0.107.2
[v0.107.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.0...v0.107.1
[v0.107.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.3...v0.107.0
[v0.106.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.2...v0.106.3
[v0.106.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.1...v0.106.2

View File

@@ -185,7 +185,7 @@ Run `make init` to prepare the development environment.
You will need this to build AdGuard Home:
* [go](https://golang.org/dl/) v1.16 or later.
* [go](https://golang.org/dl/) v1.17 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.

View File

@@ -7,7 +7,7 @@
# Make sure to sync any changes with the branch overrides below.
'variables':
'channel': 'edge'
'dockerGo': 'adguard/golang-ubuntu:3.8'
'dockerGo': 'adguard/golang-ubuntu:4.0'
'stages':
- 'Make release':
@@ -266,14 +266,19 @@
# need to build a few of these.
'variables':
'channel': 'beta'
'dockerGo': 'adguard/golang-ubuntu:3.8'
'dockerGo': 'adguard/golang-ubuntu:4.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]+':
# Disable integration branches for release branches.
'branch-config':
'integration':
'push-on-success': false
'merge-from': 'beta-v0.107'
# Build final releases on release branches manually.
'triggers': []
# Set the default release channel on the final branch to release, as these
# are the ones that actually get released.
'variables':
'channel': 'release'
'dockerGo': 'adguard/golang-ubuntu:3.8'
'dockerGo': 'adguard/golang-ubuntu:4.0'

View File

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

View File

@@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<meta http-equiv="x-dns-prefetch-control" content="off">
<meta name="mobile-web-app-capable" content="yes" />

View File

@@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />

View File

@@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png" />
<meta name="mobile-web-app-capable" content="yes" />

View File

@@ -163,8 +163,8 @@
"apply_btn": "Ужыць",
"disabled_filtering_toast": "Фільтрацыя выкл.",
"enabled_filtering_toast": "Фільтрацыя ўкл.",
"disabled_safe_browsing_toast": "Бяспечная навігацыя выкл.",
"enabled_safe_browsing_toast": "Бяспечная навігацыя ўкл.",
"disabled_safe_browsing_toast": "Бяспечная навігацыя выключана",
"enabled_safe_browsing_toast": "Бяспечная навігацыя ўключана",
"disabled_parental_toast": "Бацькоўскі кантроль выкл.",
"enabled_parental_toast": "Бацькоўскі кантроль укл.",
"disabled_safe_search_toast": "Бяспечны пошук выкл.",
@@ -200,6 +200,7 @@
"form_error_url_or_path_format": "Няслушны URL ці абсалютны шлях да спіса",
"custom_filter_rules": "Карыстацкае рэдагавала фільтрацыі",
"custom_filter_rules_hint": "Уводзьце па адным правіле на радок. Вы можаце выкарыстоўваць правілы блакавання ці сінтаксіс файлаў hosts.",
"system_host_files": "Сістэмныя hosts-файлы",
"examples_title": "Прыклады",
"example_meaning_filter_block": "заблакаваць доступ да дамена example.org і ўсім яго паддаменам",
"example_meaning_filter_whitelist": "адблакаваць доступ да дамена example.org і ўсім яго паддаменам",
@@ -586,8 +587,8 @@
"show_blocked_responses": "Заблакавана",
"show_whitelisted_responses": "Белы спіс",
"show_processed_responses": "Апрацавана",
"blocked_safebrowsing": "Заблакавана згодна базе дадзеных Safebrowsing",
"blocked_adult_websites": "Заблакаваныя \"дарослыя\" сайты",
"blocked_safebrowsing": "Заблакавана згодна базе дадзеных Safe Browsing",
"blocked_adult_websites": "Заблакавана Бацькоўскім кантролем",
"blocked_threats": "Заблакавана пагроз",
"allowed": "Дазволены",
"filtered": "Адфільтраваныя",
@@ -624,5 +625,7 @@
"last_rule_in_allowlist": "Няможна заблакаваць гэтага кліента, бо вынятак правіла «{{disallowed_rule}}» АДКЛЮЧЫЦЬ рэжым белага спіса.",
"experimental": "Эксперыментальны",
"use_saved_key": "Скарыстаць захаваны раней ключ",
"parental_control": "Бацькоўскі кантроль"
"parental_control": "Бацькоўскі кантроль",
"safe_browsing": "Бяспечны інтэрнэт",
"served_from_cache": "{{value}} <i>(атрымана з кэша)</i>"
}

View File

@@ -110,7 +110,6 @@
"example_upstream_doh": "криптиран <a href='https://en.wikipedia.org/wiki/DNS_over_HTTPS' target='_blank'>DNS-върху-HTTPS</a>",
"example_upstream_sdns": "може да ползвате <a href='https://dnscrypt.info/stamps/' target='_blank'>DNS Подписване</a> за <a href='https://dnscrypt.info/' target='_blank'>DNSCrypt</a> или <a href='https://en.wikipedia.org/wiki/DNS_over_HTTPS' target='_blank'>DNS-върху-HTTPS</a> сървъри",
"example_upstream_tcp": "класически DNS (TCP протокол)",
"updated_upstream_dns_toast": "Глобалните DNS сървъри са обновени",
"dns_test_ok_toast": "Въведените DNS сървъри работят коректно",
"dns_test_not_ok_toast": "Сървър \"{{key}}\": не работи, моля проверете дали е въведен коректно",
"unblock": "Отблокирай",
@@ -245,5 +244,6 @@
"allowed": "В белия списък",
"filter_category_general": "General",
"filter_category_security": "Сигурност",
"port_53_faq_link": "Порт 53 често е зает от \"DNSStubListener\" или \"systemd-resolved\" услуги. Моля, прочетете <0>тази инструкция</0> как да решите това."
"port_53_faq_link": "Порт 53 често е зает от \"DNSStubListener\" или \"systemd-resolved\" услуги. Моля, прочетете <0>тази инструкция</0> как да решите това.",
"parental_control": "Родителски контрол"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Neplatná adresa IPv6",
"form_error_ip_format": "Neplatná adresa IP",
"form_error_mac_format": "Neplatná adresa MAC",
"form_error_client_id_format": "Neplatné ID klienta",
"form_error_client_id_format": "ID klienta musí obsahovat pouze čísla, malá písmena a spojovníky",
"form_error_server_name": "Neplatný název serveru",
"form_error_subnet": "Podsíť \"{{cidr}}\" neobsahuje IP adresu \"{{ip}}\"",
"form_error_positive": "Musí být větší než 0",
@@ -403,6 +403,7 @@
"dns_providers": "Zde je <0>seznam známých poskytovatelů DNS</0>, z nichž si můžete vybrat.",
"update_now": "Aktualizovat nyní",
"update_failed": "Automatická aktualizace selhala. Prosím <a>následujte tyto kroky</a> a aktualizujte ručně.",
"manual_update": "Prosím <a>následujte tyto kroky</a> a aktualizujte ručně.",
"processing_update": "Čekejte prosím, AdGuard Home se aktualizuje",
"clients_title": "Klienti",
"clients_desc": "Konfigurace zařízení připojených k AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Zablokované",
"show_whitelisted_responses": "Povolené",
"show_processed_responses": "Zpracovaný",
"blocked_safebrowsing": "Blokované bezpečné prohlížení",
"blocked_adult_websites": "Blokované stránky pro dospělé",
"blocked_safebrowsing": "Blokováno modulem Bezpečné prohlížení",
"blocked_adult_websites": "Blokováno modulem Rodičovská kontrola",
"blocked_threats": "Blokované hrozby",
"allowed": "Povoleno",
"filtered": "Filtrováno",
@@ -625,7 +626,7 @@
"last_rule_in_allowlist": "Nelze zakázat tohoto klienta, protože vyloučení pravidla \"{{disallowed_rule}}\" ZRUŠÍ seznam \"Povolených klientů\".",
"experimental": "Experimentální",
"use_saved_key": "Použít dříve uložený klíče",
"parental_control": "Rodičovská kontrola",
"parental_control": "Rodičovská ochrana",
"safe_browsing": "Bezpečné prohlížení",
"served_from_cache": "{{value}} <i>(převzato z mezipaměti)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Ugyldig IPv6-adresse",
"form_error_ip_format": "Ugyldig IP-adresse",
"form_error_mac_format": "Ugyldig MAC-adresse",
"form_error_client_id_format": "Ugyldigt klient-ID",
"form_error_client_id_format": "Klient-ID må kun indeholde cifre, minuskler og bindestreger",
"form_error_server_name": "Ugyldigt servernavn",
"form_error_subnet": "Subnet \"{{cidr}}\" indeholder ikke IP-adressen \"{{ip}}\"",
"form_error_positive": "Skal være større end 0",
@@ -403,6 +403,7 @@
"dns_providers": "Her er en <0>liste over kendte DNS-udbydere</ 0> at vælge imellem.",
"update_now": "Opdatér nu",
"update_failed": "Autoopdatering mislykkedes. Følg <a>disse trin</a> for at opdatere manuelt.",
"manual_update": "<a>Følg disse trin</a> for at opdatere manuelt.",
"processing_update": "Vent venligst, AdGuard Home bliver opdateret",
"clients_title": "Klienter",
"clients_desc": "Opsæt enheder forbundet til AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Blokeret",
"show_whitelisted_responses": "Hvidlistet",
"show_processed_responses": "Behandlet",
"blocked_safebrowsing": "Blokeret af Safebrowsing",
"blocked_adult_websites": "Blokerede Voksen Websteder",
"blocked_safebrowsing": "Blokeret af Safe Browsing",
"blocked_adult_websites": "Blokeret af Forælderkontrol",
"blocked_threats": "Blokerede Trusler",
"allowed": "Tilladt",
"filtered": "Filtreret",
@@ -626,6 +627,6 @@
"experimental": "Eksperimentel",
"use_saved_key": "Brug den tidligere gemte nøgle",
"parental_control": "Forældrekontrol",
"safe_browsing": "Sikker browsing",
"safe_browsing": "Sikker Browsing",
"served_from_cache": "{{value}} <i>(leveret fra cache)</i>"
}

View File

@@ -6,7 +6,7 @@
"parallel_requests": "Paralleles Abfragen",
"load_balancing": "Lastverteilung",
"load_balancing_desc": "Einen Server nach dem anderen abfragen. AdGuard Home verwendet den gewichteten Zufallsalgorithmus, um den Server so auszuwählen, dass der schnellste Server häufiger verwendet wird.",
"bootstrap_dns": "Bootstrap DNS-Server starten",
"bootstrap_dns": "Bootstrap DNS-Server",
"bootstrap_dns_desc": "Bootstrap-DNS-Server werden verwendet, um IP-Adressen der DoH/DoT-Resolver aufzulösen, die Sie als Upstreams angeben.",
"local_ptr_title": "Private inverse DNS-Server",
"local_ptr_desc": "Die DNS-Server, die AdGuard Home für lokale PTR-Abfragen verwendet. Diese Server werden verwendet, um die Hostnamen von Clients mit privaten IP-Adressen, z. B. „192.168.12.34“, per inverse DNS-Anfragen aufzulösen. Wenn nicht festgelegt, verwendet AdGuard Home die Adressen der Standard-DNS-Auflöser Ihres Betriebssystems mit Ausnahme der Adressen von AdGuard Home selbst.",
@@ -43,7 +43,7 @@
"form_error_ip6_format": "Ungültige IPv6-Adresse",
"form_error_ip_format": "Ungültige IP-Adresse",
"form_error_mac_format": "Ungültige MAC-Adresse",
"form_error_client_id_format": "Ungültiges Client-ID",
"form_error_client_id_format": "Client-ID muss nur Zahlen, Kleinbuchstaben und Bindestriche enthalten",
"form_error_server_name": "Ungültiger Servername",
"form_error_subnet": "Subnetz „{{cidr}}“ enthält nicht die IP-Adresse „{{ip}}“",
"form_error_positive": "Muss größer als 0 (Null) sein",
@@ -70,9 +70,9 @@
"dhcp_error": "AdGuard Home konnte nicht ermitteln, ob es einen anderen aktiven DHCP-Server im Netzwerk gibt.",
"dhcp_static_ip_error": "Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Es konnte nicht ermittelt werden, ob diese Netzwerkschnittstelle mit statischer IP-Adresse konfiguriert ist. Bitte legen Sie eine statische IP-Adresse manuell fest.",
"dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}</0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}</0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP-Server aktivieren“ klicken.",
"dhcp_lease_added": "Statischer Zuweisung „{{key}}“ erfolgreich hinzugefügt",
"dhcp_lease_added": "Statische Zuweisung „{{key}}“ erfolgreich hinzugefügt",
"dhcp_lease_deleted": "Statische Zuweisung „{{key}}“ erfolgreich entfernt",
"dhcp_new_static_lease": "Neuer statischer Zuweisung",
"dhcp_new_static_lease": "Neue statische Zuweisung",
"dhcp_static_leases_not_found": "Keine statischen DHCP-Zuweisungen gefunden",
"dhcp_add_static_lease": "Statische Zuweisung hinzufügen",
"dhcp_reset_leases": "Alle Zuweisungen zurücksetzen",
@@ -133,8 +133,8 @@
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Sperrlisten abgelehnte DNS-Anfragen",
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul „Internetsicherheit“ gesperrten DNS-Anfragen",
"number_of_dns_query_blocked_24_hours_adult": "Anzahl der gesperrten Websites mit jugendgefährdenden Inhalten",
"enforced_save_search": "SafeSearch erzwungen",
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen SafeSearch für Suchanfragen erzwungen wurde",
"enforced_save_search": "Sichere Suche erzwungen",
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen Sichere Suche für Suchanfragen erzwungen wurde",
"average_processing_time": "Durchschnittliche Bearbeitungsdauer",
"average_processing_time_hint": "Durchschnittliche Zeit in Millisekunden zur Bearbeitung von DNS-Anfragen",
"block_domain_use_filters_and_hosts": "Domains durch Filter und Host-Dateien sperren",
@@ -143,8 +143,8 @@
"use_adguard_browsing_sec_hint": "AdGuard Home prüft, ob die Domain durch den Webdienst für Internetsicherheit auf eine Sperrliste gesetzt wurde. Es verwendet eine datenschutzfreundliche Lookup-API, um die Prüfung durchzuführen: Nur ein kurzes Präfix des Domänennamens SHA256-Hash wird an den Server gesendet.",
"use_adguard_parental": "AdGuard Webservice für Kindersicherung verwenden",
"use_adguard_parental_hint": "AdGuard Home wird prüfen, ob die Domain jugendgefährdende Inhalte enthält. Zum Schutz Ihrer Privatsphäre wird die selbe API wie für den Webservice für Internetsicherheit verwendet.",
"enforce_safe_search": "SafeSearch erzwingen",
"enforce_save_search_hint": "AdGuard kann SafeSearch für folgende Suchmaschinen erzwingen: Google, YouTube, Bing, DuckDuckGo, Yandex und Pixabay.",
"enforce_safe_search": "Sichere Suche verwenden",
"enforce_save_search_hint": "AdGuard kann Sichere Suche für folgende Suchmaschinen erzwingen: Google, YouTube, Bing, DuckDuckGo, Yandex und Pixabay.",
"no_servers_specified": "Keine Server festgelegt",
"general_settings": "Allgemeine Einstellungen",
"dns_settings": "DNS-Einstellungen",
@@ -167,8 +167,8 @@
"enabled_safe_browsing_toast": "Internetsicherheit aktiviert",
"disabled_parental_toast": "Kindersicherung deaktiviert",
"enabled_parental_toast": "Kindersicherung aktiviert",
"disabled_safe_search_toast": "SafeSearch deaktiviert",
"enabled_save_search_toast": "SafeSearch aktiviert",
"disabled_safe_search_toast": "Sichere Suche deaktiviert",
"enabled_save_search_toast": "Sichere Suche aktiviert",
"enabled_table_header": "Aktiviert",
"name_table_header": "Name",
"list_url_table_header": "Adressliste",
@@ -403,6 +403,7 @@
"dns_providers": "Hier finden Sie eine <0>Liste der bekannten DNS-Anbieter</0> zur Auswahl.",
"update_now": "Jetzt aktualisieren",
"update_failed": "Das automatische Aktualisieren ist fehlgeschlagen. Bitte <a>folgen Sie den Schritten</a>, um manuell zu aktualisieren.",
"manual_update": "Bitte <a>befolgen Sie diese Schritte</a>, um manuell zu aktualisieren.",
"processing_update": "Bitte warten Sie, AdGuard Home wird aktualisiert …",
"clients_title": "Clients",
"clients_desc": "Geräte einrichten, die mit AdGuard Home verbunden sind",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Auf der Positivliste",
"show_processed_responses": "Verarbeitet",
"blocked_safebrowsing": "Gesperrt durch Internetsicherheit",
"blocked_adult_websites": "Gesperrte jugendgefährdende Websites",
"blocked_adult_websites": "Gesperrt durch Kindersicherung",
"blocked_threats": "Gesperrte Bedrohungen",
"allowed": "Zugelassen",
"filtered": "Gefiltert",
@@ -626,6 +627,6 @@
"experimental": "Experimentell",
"use_saved_key": "Zuvor gespeicherten Schlüssel verwenden",
"parental_control": "Kindersicherung",
"safe_browsing": "Sicheres Surfen",
"safe_browsing": "Internetsicherheit",
"served_from_cache": "{{value}} <i>(aus dem Zwischenspeicher abgerufen)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Invalid IPv6 address",
"form_error_ip_format": "Invalid IP address",
"form_error_mac_format": "Invalid MAC address",
"form_error_client_id_format": "Invalid client ID",
"form_error_client_id_format": "Client ID must contain only numbers, lowercase letters, and hyphens",
"form_error_server_name": "Invalid server name",
"form_error_subnet": "Subnet \"{{cidr}}\" does not contain the IP address \"{{ip}}\"",
"form_error_positive": "Must be greater than 0",
@@ -163,8 +163,8 @@
"apply_btn": "Apply",
"disabled_filtering_toast": "Disabled filtering",
"enabled_filtering_toast": "Enabled filtering",
"disabled_safe_browsing_toast": "Disabled safebrowsing",
"enabled_safe_browsing_toast": "Enabled safebrowsing",
"disabled_safe_browsing_toast": "Disabled Safe Browsing",
"enabled_safe_browsing_toast": "Enabled Safe Browsing",
"disabled_parental_toast": "Disabled parental control",
"enabled_parental_toast": "Enabled parental control",
"disabled_safe_search_toast": "Disabled safe search",
@@ -403,6 +403,7 @@
"dns_providers": "Here is a <0>list of known DNS providers</0> to choose from.",
"update_now": "Update now",
"update_failed": "Auto-update failed. Please <a>follow these steps</a> to update manually.",
"manual_update": "Please <a>follow these steps</a> to update manually.",
"processing_update": "Please wait, AdGuard Home is being updated",
"clients_title": "Clients",
"clients_desc": "Configure devices connected to AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Blocked",
"show_whitelisted_responses": "Allowed",
"show_processed_responses": "Processed",
"blocked_safebrowsing": "Blocked by Safebrowsing",
"blocked_adult_websites": "Blocked Adult Websites",
"blocked_safebrowsing": "Blocked by Safe Browsing",
"blocked_adult_websites": "Blocked by Parental Control",
"blocked_threats": "Blocked Threats",
"allowed": "Allowed",
"filtered": "Filtered",
@@ -625,7 +626,7 @@
"last_rule_in_allowlist": "Cannot disallow this client because excluding the rule \"{{disallowed_rule}}\" will DISABLE \"Allowed clients\" list.",
"experimental": "Experimental",
"use_saved_key": "Use the previously saved key",
"parental_control": "Parental control",
"safe_browsing": "Safe browsing",
"parental_control": "Parental Control",
"safe_browsing": "Safe Browsing",
"served_from_cache": "{{value}} <i>(served from cache)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Dirección IPv6 no válida",
"form_error_ip_format": "Dirección IP no válida",
"form_error_mac_format": "Dirección MAC no válida",
"form_error_client_id_format": "ID de cliente no válido",
"form_error_client_id_format": "El ID de cliente debe contener solo números, letras minúsculas y guiones",
"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",
@@ -403,6 +403,7 @@
"dns_providers": "Aquí hay una <0>lista de proveedores DNS</0> conocidos para elegir.",
"update_now": "Actualizar ahora",
"update_failed": "Error en la actualización automática. Por favor <a>sigue estos pasos</a> para actualizar manualmente.",
"manual_update": "Por favor <a>sigue estos pasos</a> para actualizar manualmente.",
"processing_update": "Por favor espera, AdGuard Home se está actualizando",
"clients_title": "Clientes",
"clients_desc": "Configurar dispositivos conectados con AdGuard Home",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Permitido",
"show_processed_responses": "Procesado",
"blocked_safebrowsing": "Bloqueado por navegación segura",
"blocked_adult_websites": "Sitios web para adultos bloqueado",
"blocked_adult_websites": "Bloqueado por control parental",
"blocked_threats": "Amenazas bloqueadas",
"allowed": "Permitido",
"filtered": "Filtrado",

View File

@@ -17,7 +17,7 @@
"form_error_required": "فیلد مورد نیاز",
"form_error_ip4_format": "فرمت نامعتبر IPv4",
"form_error_ip6_format": "فرمت نامعتبر IPv6",
"form_error_ip_format": "فرمت IPv4 نامعتبر است",
"form_error_ip_format": "آدرس آی پی نامعتبر است",
"form_error_mac_format": "فرمت مَک نامعتبر است",
"form_error_client_id_format": "فرمت شناسه کلاینت نامعتبر است",
"form_error_positive": "باید بزرگتر از 0 باشد",
@@ -159,7 +159,6 @@
"example_upstream_sdns": "شما میتوانید از <a href='https://dnscrypt.info/stamps/' target='_blank'>DNS Stamps</a> برای <a href='https://dnscrypt.info/' target='_blank'>DNSCrypt</a> یا <a href='https://en.wikipedia.org/wiki/DNS_over_HTTPS' target='_blank'>DNS-over-HTTPS</a> resolvers استفاده کنید",
"example_upstream_tcp": "DNS عادی (بر TCP)",
"all_lists_up_to_date_toast": "همه لیست ها از قبل بروز اند",
"updated_upstream_dns_toast": "سرورهای DNS جریان ارسالی بروز رسانی شده است",
"dns_test_ok_toast": "سرورهای DNS تعیین شده بدرستی کار می کنند",
"dns_test_not_ok_toast": "سرور \"{{key}}\": نمیتواند مورد استفاده قرار گیرد،لطفا بررسی کنید آن را بدرستی نوشته اید",
"unblock": "رفع انسداد",
@@ -314,7 +313,7 @@
"fix": "تعمیر",
"dns_providers": "در اینجا یک <0>لیست از سرویس های ارائه دهنده DNS</0> برای انتخاب هست.",
"update_now": "حالا بروز رسانی",
"update_failed": "بروز رسانی خودکار موفق نشد. لطفا <a href='https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update'>مراحل را دنبال کرده</a> تا بطور دستی بروز رسانی کنید.",
"update_failed": "بروز رسانی خودکار موفق نشد. لطفا <a>مراحل را دنبال کرده</a> تا بطور دستی بروز رسانی کنید.",
"processing_update": "منتظر بمانید،AdGuard Home در حال بروز رسانی است",
"clients_title": "کلاینت ها",
"clients_desc": "پیکربندی دستگاه های متصل شده به AdGuard Home",
@@ -478,7 +477,7 @@
"show_whitelisted_responses": "لیست سفید",
"show_processed_responses": "پردازش شده",
"blocked_safebrowsing": "بستن وب گردی اَمن",
"blocked_adult_websites": "وبسایت غیراخلاقی مسدود شده",
"blocked_adult_websites": "مسدود شده با نظارت والدین",
"blocked_threats": "تهدیدات مسدود شده",
"allowed": "اجازه داده شده",
"filtered": "فیلتر شده",

View File

@@ -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": "Virheellinen päätelaitteen ID",
"form_error_client_id_format": "Päätelaitteen 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",
@@ -403,6 +403,7 @@
"dns_providers": "Katso <0>luettelo tunnetuista DNS-palveluista</0>, joista valita.",
"update_now": "Päivitä nyt",
"update_failed": "Automaattinen päivitys epäonnistui. Seuraa <a>näitä ohjeita</a> päivittääksesi manuaalisesti.",
"manual_update": "Seuraa <a>näitä ohjeita</a> päivittääksesi manuaalisesti.",
"processing_update": "Odota kun AdGuard Home päivittyy",
"clients_title": "Päätelaitteet",
"clients_desc": "Määritä AdGuard Homeen yhdistetyt päätelaitteet",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Sallitut",
"show_processed_responses": "Käsitelty",
"blocked_safebrowsing": "Turvallisen selauksen estämät",
"blocked_adult_websites": "Estetyt aikuisille tarkoitetut sivustot",
"blocked_adult_websites": "Lapsilukon estämät",
"blocked_threats": "Estetyt uhat",
"allowed": "Sallitut",
"filtered": "Suodatetut",
@@ -603,9 +604,9 @@
"enter_cache_size": "Syötä välimuistin koko (tavuina)",
"enter_cache_ttl_min_override": "Syötä vähimmäis-TTL (sekunteina)",
"enter_cache_ttl_max_override": "Syötä enimmäis-TTL (sekunteina)",
"cache_ttl_min_override_desc": "Pidennä ylävirran palvelimelta vastaanotettuja, lyhyitä time-to-live -arvoja (sekunteina) tallennettaessa DNS-vastauksia välimuistiin.",
"cache_ttl_max_override_desc": "Määritä DNS-välimuistin kohteiden suurin time-to-live -arvo (sekunteina)",
"ttl_cache_validation": "Välimuistin TTL-vähimmäisarvon tulee olla pienempi tai sama kuin enimmäisarvon",
"cache_ttl_min_override_desc": "Pidennä ylävirran palvelimelta vastaanotettuja, lyhyitä elinaika-arvoja (sekunteina) tallennettaessa DNS-vastauksia välimuistiin.",
"cache_ttl_max_override_desc": "Määritä DNS-välimuistin kohteiden suurin elinaika-arvo (sekunteina)",
"ttl_cache_validation": "Välimuistin elinajan vähimmäisarvon tulee olla pienempi tai sama kuin enimmäisarvon",
"cache_optimistic": "Optimistinen välimuisti",
"cache_optimistic_desc": "Pakota AdGuard Home vastaamaan välimuistista vaikka sen tiedot olisivat vanhentuneet. Pyri samalla myös päivittämään tiedot.",
"filter_category_general": "Yleiset",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Adresse IPv6 invalide",
"form_error_ip_format": "Adresse IP invalide",
"form_error_mac_format": "Adresse MAC invalide",
"form_error_client_id_format": "Identifiant de client invalide",
"form_error_client_id_format": "L'ID du client ne doit contenir que des chiffres, des lettres minuscules et des traits d'union.",
"form_error_server_name": "Nom de serveur invalide",
"form_error_subnet": "Le sous-réseau « {{cidr}} » ne contient pas l'adresse IP « {{ip}} »",
"form_error_positive": "Doit être supérieur à 0",
@@ -163,8 +163,8 @@
"apply_btn": "Appliquer",
"disabled_filtering_toast": "Filtrage désactivé",
"enabled_filtering_toast": "Filtrage activé",
"disabled_safe_browsing_toast": "Surfing sécurisé désactivé",
"enabled_safe_browsing_toast": "Surfing sécurisé activé",
"disabled_safe_browsing_toast": "Navigation sécurisée désactivée",
"enabled_safe_browsing_toast": "Navigation sécurisée activée",
"disabled_parental_toast": "Contrôle parental désactivé",
"enabled_parental_toast": "Contrôle parental activé",
"disabled_safe_search_toast": "Recherche sécurisée désactivée",
@@ -402,7 +402,8 @@
"fix": "Corriger",
"dns_providers": "Voici une <0>liste de fournisseurs DNS connus</0>.",
"update_now": "Mettre à jour maintenant",
"update_failed": "Échec de la mise à jour automatique. Veuillez <a href='https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update'>suivre ces étapes</a> pour mettre à jour manuellement.",
"update_failed": "Échec de la mise à jour automatique. Veuillez <a>suivre ces étapes</a> pour mettre à jour manuellement.",
"manual_update": "Veuillez <a>suivre ces étapes</a> pour mettre à jour manuellement.",
"processing_update": "Veuillez patienter, AdGuard Home est en cours de mise à jour",
"clients_title": "Clients",
"clients_desc": "Configurer les appareils connectés à AdGuard Home",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Ajouté à la liste blanche",
"show_processed_responses": "Traité",
"blocked_safebrowsing": "Navigation sécurisée bloquée",
"blocked_adult_websites": "Sites à contenu adulte bloqués",
"blocked_adult_websites": "Bloqué par le Contrôle Parental",
"blocked_threats": "Menaces bloquées",
"allowed": "Autorisé",
"filtered": "Filtré",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Nevažeći IPv6 format",
"form_error_ip_format": "Nevažeći format IP adrese",
"form_error_mac_format": "Nevažeći MAC format",
"form_error_client_id_format": "Nevažeći format ID-a klijenta",
"form_error_client_id_format": "ID klijenta može sadržavati samo brojeve, mala slova i crtice",
"form_error_server_name": "Nevažeće ime poslužitelja",
"form_error_subnet": "Podmrežu \"{{cidr}}\" ne sadrži IP adresu \"{{ip}}\"",
"form_error_positive": "Mora biti veće od 0",
@@ -163,8 +163,8 @@
"apply_btn": "Primijeni",
"disabled_filtering_toast": "Onemogućeno filtriranje",
"enabled_filtering_toast": "Omogućeno filtriranje",
"disabled_safe_browsing_toast": "Onemogućena sigurna pretraga",
"enabled_safe_browsing_toast": "Omogućena sigurna pretraga",
"disabled_safe_browsing_toast": "Onemogućena Sigurna pretraga",
"enabled_safe_browsing_toast": "Omogućena Sigurna pretraga",
"disabled_parental_toast": "Onemogućen roditeljski nadzor",
"enabled_parental_toast": "Omogućen roditeljski nadzor",
"disabled_safe_search_toast": "Onemogućeno sigurno pretraživanje",
@@ -588,7 +588,7 @@
"show_whitelisted_responses": "Na popisu dopuštenih",
"show_processed_responses": "Obrađeno",
"blocked_safebrowsing": "Blokirano s Sigurnom pretragom",
"blocked_adult_websites": "Blokirane web stranice za odrasle",
"blocked_adult_websites": "Blokirano Roditeljskom kontrolom",
"blocked_threats": "Blokirane prijetnje",
"allowed": "Dopušteno",
"filtered": "Filtrirano",

View File

@@ -36,14 +36,23 @@
"dhcp_ipv4_settings": "DHCP IPv4 Beállítások",
"dhcp_ipv6_settings": "DHCP IPv6 Beállítások",
"form_error_required": "Kötelező mező",
"form_error_ip4_format": "Érvénytelen IPv4 formátum",
"form_error_ip6_format": "Érvénytelen IPv6 formátum",
"form_error_ip_format": "Érvénytelen IP formátum",
"form_error_mac_format": "Érvénytelen MAC formátum",
"form_error_client_id_format": "Érvénytelen kliens ID formátum",
"form_error_ip4_format": "Érvénytelen IPv4 m",
"form_error_ip4_range_start_format": "Érvénytelen IPv4-cím a tartomány kezdetéhez",
"form_error_ip4_range_end_format": "Érvénytelen IPv4-cím a tartomány végén",
"form_error_ip4_gateway_format": "Érvénytelen IPv4-cím az átjáró",
"form_error_ip6_format": "Érvénytelen IPv6 cím",
"form_error_ip_format": "Érvénytelen IP-cím",
"form_error_mac_format": "Érvénytelen MAC cím",
"form_error_client_id_format": "Az ügyfél-azonosító csak számokat, kisbetűket és kötőjeleket tartalmazhat",
"form_error_server_name": "Érvénytelen szervernév",
"form_error_subnet": "A(z) \"{{cidr}}\" alhálózat nem tartalmazza a(z) \"{{ip}}\" IP címet",
"form_error_positive": "0-nál nagyobbnak kell lennie",
"out_of_range_error": "A tartományon kívül legyen \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete",
"greater_range_start_error": "Nagyobbbb legyen, mint a tartomány kezdete",
"greater_range_end_error": "Nagyobb legyen, mint a tartomány vége",
"subnet_error": "A címeknek egy alhálózatban kell lenniük",
"gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen",
"dhcp_form_gateway_input": "Átjáró IP",
"dhcp_form_subnet_input": "Alhálózati maszk",
"dhcp_form_range_title": "IP-címek tartománya",
@@ -191,6 +200,7 @@
"form_error_url_or_path_format": "Helytelen URL vagy elérési út a listához",
"custom_filter_rules": "Egyéni szűrési szabályok",
"custom_filter_rules_hint": "Adjon meg egy szabályt egy sorban. Használhat egyszerű hirdetésblokkolási szabályokat vagy hosztfájl szintaxist.",
"system_host_files": "Rendszer hosztfájlok",
"examples_title": "Példák",
"example_meaning_filter_block": "letiltja a hozzáférést az example.org domainhez, valamint annak az összes aldomainjéhez is",
"example_meaning_filter_whitelist": "feloldja a hozzáférést az example.org domainhez, valamint annak az összes aldomainjéhez is",
@@ -577,8 +587,8 @@
"show_blocked_responses": "Blokkolva",
"show_whitelisted_responses": "Kivételezett",
"show_processed_responses": "Feldolgozva",
"blocked_safebrowsing": "Blokkolva a biztonságos böngészés által",
"blocked_adult_websites": "Blokkolva a felnőtt tartalmak által",
"blocked_safebrowsing": "Blokkolva a Biztonságos böngészés által",
"blocked_adult_websites": "Szülői felügyelet által blokkolva",
"blocked_threats": "Blokkolt fenyegetések",
"allowed": "Engedve",
"filtered": "Megszűrt",
@@ -611,7 +621,11 @@
"click_to_view_queries": "Kattintson a lekérésekért",
"port_53_faq_link": "Az 53-as portot gyakran a \"DNSStubListener\" vagy a \"systemd-resolved\" (rendszer által feloldott) szolgáltatások használják. Kérjük, olvassa el <0>ezt az útmutatót</0> a probléma megoldásához.",
"adg_will_drop_dns_queries": "Az AdGuard Home eldobja az összes DNS kérést erről a kliensről.",
"filter_allowlist": "FIGYELMEZTETÉS: Ez a művelet a \"{{disallowed_rule}}\" szabályt is kizárja az engedélyezett ügyfelek listájából.",
"last_rule_in_allowlist": "Nem lehet letiltani ezt az ügyfelet, mert a \"{{disallowed_rule}}\" szabály kizárása letiltja az \"Allowed clients\" listát.",
"experimental": "Kísérleti",
"use_saved_key": "Előzőleg mentett kulcs használata",
"parental_control": "Szülői felügyelet"
"parental_control": "Szülői felügyelet",
"safe_browsing": "Biztonságos böngészés",
"served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>"
}

View File

@@ -36,10 +36,23 @@
"dhcp_ipv4_settings": "Pengaturan DHCP IPv4",
"dhcp_ipv6_settings": "Pengaturan DHCP IPv6",
"form_error_required": "Kolom yang harus diisi",
"form_error_ip_format": "Alamat IP salah",
"form_error_ip4_format": "Alamat IPv4 tidak valid",
"form_error_ip4_range_start_format": "Alamat IPv4 tidak valid dari rentang awal",
"form_error_ip4_range_end_format": "Alamat IPv4 tidak valid dari rentang akhir",
"form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid",
"form_error_ip6_format": "Alamat IPv6 tidak valid",
"form_error_ip_format": "Alamat IP tidak valid",
"form_error_mac_format": "Alamat MAC tidak valid",
"form_error_client_id_format": "ID Klien hanya boleh berisi angka, huruf kecil, dan tanda hubung",
"form_error_server_name": "Nama server tidak valid",
"form_error_subnet": "Subnet \"{{cidr}}\" tidak berisi alamat IP \"{{ip}}\"",
"form_error_positive": "Harus lebih dari 0",
"out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Harus lebih rendah dari rentang awal",
"greater_range_start_error": "Harus lebih besar dari rentang awal",
"greater_range_end_error": "Harus lebih besar dari rentang akhir",
"subnet_error": "Alamat harus dalam satu subnet",
"gateway_or_subnet_invalid": "Subnet mask tidak valid",
"dhcp_form_gateway_input": "IP gateway",
"dhcp_form_subnet_input": "Subnet mask",
"dhcp_form_range_title": "Rentang alamat IP",
@@ -150,8 +163,8 @@
"apply_btn": "Terapkan",
"disabled_filtering_toast": "Penyaringan nonaktif",
"enabled_filtering_toast": "Penyaringan aktif",
"disabled_safe_browsing_toast": "Penelusuran aman dinonaktifkan",
"enabled_safe_browsing_toast": "Penelusuran aman diaktifkan",
"disabled_safe_browsing_toast": "Penjelajahan Aman dinonaktifkan",
"enabled_safe_browsing_toast": "Penjelajahan Aman Diaktifkan",
"disabled_parental_toast": "Kontrol orang tua dinonaktifkan",
"enabled_parental_toast": "Kontrol orang tua diaktifkan",
"disabled_safe_search_toast": "Pencarian aman dinonaktifkan",
@@ -187,6 +200,7 @@
"form_error_url_or_path_format": "URL atau jalur absolut dari daftar tidak valid",
"custom_filter_rules": "Aturan penyaringan khusus",
"custom_filter_rules_hint": "Masukkan satu aturan dalam sebuah baris. Anda dapat menggunakan baik aturan adblock maupun sintaks file hosts.",
"system_host_files": "File host sistem",
"examples_title": "Contoh",
"example_meaning_filter_block": "Blokir akses ke example.org dan seluruh subdomainnya",
"example_meaning_filter_whitelist": "Buka blokir akses ke domain example.orf dan seluruh subdomainnya",
@@ -202,6 +216,7 @@
"example_upstream_sdns": "anda bisa menggunakan <0>Stempel DNS</0> untuk <1>DNSCrypt</1> atau pengarah <2>DNS-over-HTTPS</2>",
"example_upstream_tcp": "DNS reguler (melalui TCP)",
"all_lists_up_to_date_toast": "Semua daftar sudah diperbarui",
"updated_upstream_dns_toast": "Server upstream berhasil disimpan",
"dns_test_ok_toast": "Server DNS yang ditentukan bekerja dengan benar",
"dns_test_not_ok_toast": "Server \"{{key}}\": tidak dapat digunakan, mohon cek bahwa Anda telah menulisnya dengan benar",
"unblock": "Buka Blokir",
@@ -299,6 +314,7 @@
"install_settings_dns_desc": "Anda perlu mengkonfigurasi perangkat atau router anda untuk menggunakan server DNS berikut ini",
"install_settings_all_interfaces": "Semua antarmuka",
"install_auth_title": "Otentikasi",
"install_auth_desc": "Otentikasi kata sandi ke antarmuka web admin AdGuard Home Anda harus dikonfigurasi. Meskipun AdGuard Home hanya dapat diakses di jaringan lokal Anda, tetap penting untuk melindunginya dari akses tak terbatas.",
"install_auth_username": "Nama Pengguna",
"install_auth_password": "Kata Sandi",
"install_auth_confirm": "Konfirmasi kata sandi",
@@ -495,6 +511,7 @@
"statistics_clear_confirm": "Apakah Anda yakin ingin menghapus statistik?",
"statistics_retention_confirm": "Apakah Anda yakin ingin mengubah retensi statistik? Jika Anda menurunkan nilai interval, beberapa data akan hilang",
"statistics_cleared": "Statistik berhasil dihapus",
"statistics_enable": "Aktifkan statistik",
"interval_hours": "{{count}} jam",
"interval_hours_plural": "{{count}} jam",
"filters_configuration": "Konfigurasi filter",
@@ -570,8 +587,8 @@
"show_blocked_responses": "Diblokir",
"show_whitelisted_responses": "Dalam Daftar Putih",
"show_processed_responses": "Terproses",
"blocked_safebrowsing": "Terblokir oleh Safebrowsing",
"blocked_adult_websites": "Situs Dewasa Terblokir",
"blocked_safebrowsing": "Diblokir oleh Penjelajahan Aman",
"blocked_adult_websites": "Diblok oleh Kontrol Orang tua",
"blocked_threats": "Blokir Ancaman",
"allowed": "Dibolehkan",
"filtered": "Tersaring",
@@ -604,7 +621,11 @@
"click_to_view_queries": "Klik untuk lihat permintaan",
"port_53_faq_link": "Port 53 sering ditempati oleh layanan \"DNSStubListener\" atau \"systemd-resolved\". Silakan baca <0>instruksi ini</0> tentang cara menyelesaikan ini.",
"adg_will_drop_dns_queries": "AdGuard Home akan menghapus semua permintaan DNS dari klien ini.",
"filter_allowlist": "PERINGATAN: Tindakan ini juga akan mengecualikan aturan \"{{disallowed_rule}}\" dari daftar klien yang diizinkan.",
"last_rule_in_allowlist": "Tidak dapat melarang klien ini karena mengecualikan aturan \"{{disallowed_rule}}\" akan MENONAKTIFKAN daftar \"Klien yang diizinkan\".",
"experimental": "Eksperimental",
"use_saved_key": "Gunakan kunci yang disimpan sebelumnya",
"parental_control": "Kontrol orang tua"
"parental_control": "Kontrol Orang Tua",
"safe_browsing": "Penjelajahan Aman",
"served_from_cache": "{{value}} <i>(disajikan dari cache)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Indirizzo IPv6 non valido",
"form_error_ip_format": "Indirizzo IP non valido",
"form_error_mac_format": "Indirizzo MAC non valido",
"form_error_client_id_format": "ID cliente non valido",
"form_error_client_id_format": "Il client ID deve contenere solo numeri, lettere minuscole e trattini",
"form_error_server_name": "Nome server non valido",
"form_error_subnet": "La subnet \"{{cidr}}\" non contiene l'indirizzo IP \"{{ip}}\"",
"form_error_positive": "Deve essere maggiore di 0",
@@ -163,8 +163,8 @@
"apply_btn": "Applica",
"disabled_filtering_toast": "Disattiva filtri",
"enabled_filtering_toast": "Attiva filtri",
"disabled_safe_browsing_toast": "Disattiva navigazione sicura",
"enabled_safe_browsing_toast": "Attiva navigazione sicura",
"disabled_safe_browsing_toast": "Disattiva Navigazione Sicura",
"enabled_safe_browsing_toast": "Attiva Navigazione Sicura",
"disabled_parental_toast": "Disattiva il Controllo Parentale",
"enabled_parental_toast": "Attiva Controllo Parentale",
"disabled_safe_search_toast": "Ricerca sicura disattivata",
@@ -295,16 +295,16 @@
"blocking_mode_null_ip": "IP nullo: Rispondi con indirizzo IP zero (0.0.0.0 per A; :: per AAAA)",
"blocking_mode_custom_ip": "IP personalizzato: Rispondi con un indirizzo IP impostato manualmente",
"upstream_dns_client_desc": "Se lasci questo spazio vuoto, AdGuard Home utilizzerà i server configurati nelle <0>impostazioni DNS</0>.",
"tracker_source": "Origine tracker",
"tracker_source": "Origine del tracciatore",
"source_label": "Fonte",
"found_in_known_domain_db": "Trovato nel database dei domini conosciuti.",
"found_in_known_domain_db": "Trovato nel database dei domini noti.",
"category_label": "Categoria",
"rule_label": "Regola(e)",
"list_label": "Elenco",
"unknown_filter": "Filtro sconosciuto {{filterId}}",
"known_tracker": "Tracker conosciuto",
"known_tracker": "Tracciatore noto",
"install_welcome_title": "Benvenuto nella Home di AdGuard!",
"install_welcome_desc": "AdGuard Home è un server DNS che blocca annunci e tracker in tutta la rete. Il suo scopo è quello di consentire di controllare l'intera rete e tutti i dispositivi, e non richiede l'utilizzo di un programma sul lato client.",
"install_welcome_desc": "AdGuard Home è un server DNS che blocca annunci e tracciatori a livello di rete. Il suo scopo è quello di permetterti il controllo dell'intera rete e di tutti i dispositivi, e non richiede l'utilizzo di un programma lato client.",
"install_settings_title": "Interfaccia Web dell'Admin",
"install_settings_listen": "Interfaccia d'ascolto",
"install_settings_port": "Porta",
@@ -400,9 +400,10 @@
"dns_status_error": "Errore nel recupero dello stato del server DNS",
"down": "Spenta",
"fix": "Risolvi",
"dns_providers": "Qui c'è un <0>elenco di fornitori DNS conosciuti</0> da cui scegliere.",
"dns_providers": "Qui c'è un <0>elenco di fornitori DNS noti</0> da cui scegliere.",
"update_now": "Aggiorna ora",
"update_failed": "Aggiornamento automatico non riuscito. Ti suggeriamo di <a>seguire questi passaggi</a> per aggiornare manualmente.",
"manual_update": "Ti invitiamo a <a>seguire questi passaggi</a> per aggiornare manualmente.",
"processing_update": "Perfavore aspetta, AdGuard Home si sta aggiornando",
"clients_title": "Client",
"clients_desc": "Configura i dispositivi connessi ad AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Bloccato",
"show_whitelisted_responses": "Consentito",
"show_processed_responses": "Processato",
"blocked_safebrowsing": "Blocco Navigazione sicura",
"blocked_adult_websites": "Siti per adulti bloccati",
"blocked_safebrowsing": "Bloccato da Navigazione Sicura",
"blocked_adult_websites": "Bloccato da Controllo Parentale",
"blocked_threats": "Minacce bloccate",
"allowed": "Consentito",
"filtered": "Filtrato",
@@ -612,9 +613,9 @@
"filter_category_security": "Sicurezza",
"filter_category_regional": "Regionale",
"filter_category_other": "Altro",
"filter_category_general_desc": "Elenchi per il blocco dei traccianti e degli annunci sulla maggioranza dei dispositivi",
"filter_category_general_desc": "Elenchi per il blocco dei tracciatori e degli annunci sulla maggioranza dei dispositivi",
"filter_category_security_desc": "Elenchi progettati specificamente per bloccare domini malevoli, di phishing o truffa",
"filter_category_regional_desc": "Elenchi focalizzati su annunci regionali e server traccianti",
"filter_category_regional_desc": "Elenchi focalizzati su annunci regionali e server tracciatori",
"filter_category_other_desc": "Altre liste nere",
"setup_config_to_enable_dhcp_server": "Configurazione dell'installazione per l'attivazione del server DHCP",
"original_response": "Responso originale",
@@ -625,7 +626,7 @@
"last_rule_in_allowlist": "Impossibile bloccare questo client perché escludere la regola \"{{disallowed_rule}}\" DISATIVERÁ l'elenco \"Clienti consentiti\".",
"experimental": "Sperimentale",
"use_saved_key": "Utilizza la chiave salvata in precedenza",
"parental_control": "Controllo parentale",
"safe_browsing": "Navigazione sicura",
"parental_control": "Controllo Parentale",
"safe_browsing": "Navigazione Sicura",
"served_from_cache": "{{value}} <i>(fornito dalla cache)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "IPv6アドレスが無効です",
"form_error_ip_format": "IPアドレスが無効です",
"form_error_mac_format": "MACアドレスが無効です",
"form_error_client_id_format": "クライアントIDが無効です",
"form_error_client_id_format": "クライアントIDには、数字、小文字、ハイフンのみが使われている必要があります",
"form_error_server_name": "サーバ名が無効です",
"form_error_subnet": "IPアドレス「{{ip}}」はサブネット「{{cidr}}」に含まれていません",
"form_error_positive": "0より大きい必要があります",
@@ -403,6 +403,7 @@
"dns_providers": "こちらは、選択可能な<0>既知のDNSプロバイダの一覧</0>です。",
"update_now": "今すぐ更新する",
"update_failed": "自動更新に失敗しました。手動で更新するには、<a>手順に従って</a>ください。",
"manual_update": "手動でアップデートするには、<a>こちらの手順</a>を使ってください。",
"processing_update": "AdGuard Homeを更新しています。しばらくお待ちください",
"clients_title": "クライアント",
"clients_desc": "AdGuard Homeに接続されているデバイスを設定します",
@@ -587,8 +588,8 @@
"show_blocked_responses": "ブロック済",
"show_whitelisted_responses": "ホワイトリストにあり",
"show_processed_responses": "処理済",
"blocked_safebrowsing": "ブロックされたセーフブラウジング",
"blocked_adult_websites": "ブロックされたアダルトウェブサイト",
"blocked_safebrowsing": "セーフブラウジングによってブロック済み",
"blocked_adult_websites": "ペアレンタルコントロールによってブロック済み",
"blocked_threats": "ブロックされた脅威",
"allowed": "許可",
"filtered": "フィルタで処理",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "잘못된 IPv6 형식",
"form_error_ip_format": "잘못된 IP 형식",
"form_error_mac_format": "잘못된 MAC 형식",
"form_error_client_id_format": "잘못된 클라이언트 ID 형식",
"form_error_client_id_format": "클라이언트 ID는 숫자, 소문자 및 하이픈만 포함해야 합니다",
"form_error_server_name": "유효하지 않은 서버 이름입니다",
"form_error_subnet": "서브넷 \"{{cidr}}\"에 \"{{ip}}\" IP 주소가 없습니다",
"form_error_positive": "0보다 커야 합니다",
@@ -403,6 +403,7 @@
"dns_providers": "다음은 선택할 수 있는 <0>알려진 DNS 공급자 목록</0>입니다.",
"update_now": "지금 업데이트",
"update_failed": "자동 업데이트 실패 되었습니다. <a> 단계를 따라 수동으로 업데이트하세요</a>",
"manual_update": "<a>절차를 따라</a> 수동으로 업데이트하십시오.",
"processing_update": "잠시만 기다려주세요, AdGuard Home가 업데이트 중입니다.",
"clients_title": "클라이언트",
"clients_desc": "AdGuard Home에 연결할 기기들을 설정",
@@ -587,8 +588,8 @@
"show_blocked_responses": "차단됨",
"show_whitelisted_responses": "예외 적용됨",
"show_processed_responses": "처리됨",
"blocked_safebrowsing": "차단된 세이프 브라우징",
"blocked_adult_websites": "차단된 성인 웹사이트",
"blocked_safebrowsing": "세이프 브라우징에 의해 차단됨",
"blocked_adult_websites": "자녀 보호에 의해 차단됨",
"blocked_threats": "차단된 위협",
"allowed": "허용됨",
"filtered": "필터링됨",
@@ -626,6 +627,6 @@
"experimental": "실험",
"use_saved_key": "이전에 저장했던 키 사용하기",
"parental_control": "자녀 보호",
"safe_browsing": "안전한 브라우징",
"safe_browsing": "세이프 브라우징",
"served_from_cache": "{{value}} <i>(캐시에서 제공)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Ongeldig IPv6-adres",
"form_error_ip_format": "Ongeldig IP-adres",
"form_error_mac_format": "Ongeldig MAC-adres",
"form_error_client_id_format": "Ongeldige cliënt-ID",
"form_error_client_id_format": "Client-ID mag alleen cijfers, kleine letters en koppeltekens bevatten",
"form_error_server_name": "Ongeldige servernaam",
"form_error_subnet": "Subnet “{{cidr}}” bevat niet het IP-adres “{{ip}}”",
"form_error_positive": "Moet groter zijn dan 0",
@@ -403,6 +403,7 @@
"dns_providers": "hier is een <0>lijst of gekende DNS providers</0> waarvan je kan kiezen.",
"update_now": "Update nu",
"update_failed": "Automatisch bijwerken is mislukt. <a>Volg deze stappen</a> om handmatig bij te werken.",
"manual_update": "<a>Volg deze stappen</a> om handmatig bij te werken.",
"processing_update": "Even geduld, AdGuard Home wordt bijgewerkt",
"clients_title": "Gebruikers",
"clients_desc": "Configureer apparaten die gebruik maken van AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Geblokkeerd",
"show_whitelisted_responses": "Op toestemmingslijst",
"show_processed_responses": "Verwerkt",
"blocked_safebrowsing": "Geblokkeerd door Veilig Browsen",
"blocked_adult_websites": "Geblokkeerde 18+ websites",
"blocked_safebrowsing": "Geblokkeerd door Veilig browsen",
"blocked_adult_websites": "Geblokkeerd door ouderlijk toezicht",
"blocked_threats": "Geblokkeerde bedreigingen",
"allowed": "Toegestaan",
"filtered": "Gefilterd",
@@ -626,6 +627,6 @@
"experimental": "Experimenteel",
"use_saved_key": "De eerder opgeslagen sleutel gebruiken",
"parental_control": "Ouderlijk toezicht",
"safe_browsing": "Veilig surfen",
"safe_browsing": "Veilig browsen",
"served_from_cache": "{{value}} <i>(geleverd vanuit cache)</i>"
}

View File

@@ -1,11 +1,18 @@
{
"client_settings": "Klientinnstillinger",
"example_upstream_reserved": "Du kan bestemme en oppstrøms-DNS <0>for et spesifikt domene(r)</0>",
"example_upstream_comment": "Du kan spesifisere en kommentar",
"upstream_parallel": "Bruk parallele forespørsler for å få oppfarten på behandlinger, ved å forespørre til alle oppstrømstjenerne samtidig",
"parallel_requests": "Parallelle forespørsler",
"load_balancing": "Pågangstrykk-utjevning",
"load_balancing_desc": "Forespør én tjener om gangen. AdGuard Home vil bruke en 'vektlagt tilfeldig valg'-algoritme for å velge tjener, slik at den raskeste tjeneren blir brukt oftere.",
"bootstrap_dns": "Bootstrap-DNS-tjenere",
"bootstrap_dns_desc": "Bootstrap-DNS-tjenere brukes til å oppklare IP-adressene til DoH/DoT-oppklarerene som du har valgt som oppstrømstjenere.",
"local_ptr_title": "Private DNS-tjenere",
"local_ptr_desc": "DNS-tjenerne som AdGuard Home bruker for lokale PTR-spørringer. Disse tjenerne brukes til å løse vertsnavnene til klienter med private IP-adresser, for eksempel \"192.168.12.34\", ved bruk av omvendt DNS. Hvis det ikke er angitt, bruker AdGuard Home adressene til standard-DNS-løserne til operativsystemet ditt, bortsett fra adressene til selve AdGuard Home.",
"use_private_ptr_resolvers_title": "Bruk private omvendte DNS-løsere",
"check_dhcp_servers": "Se etter DHCP-tjenere",
"save_config": "Lagre oppsettet",
"enabled_dhcp": "DHCP-tjeneren ble skrudd på",
"disabled_dhcp": "DHCP-tjeneren ble skrudd av",
"unavailable_dhcp": "DHCP er utilgjengelig",
@@ -23,7 +30,7 @@
"form_error_required": "Påkrevd felt",
"form_error_ip4_format": "Ugyldig IPv4-format",
"form_error_ip6_format": "Ugyldig IPv6-format",
"form_error_ip_format": "Ugyldig IPv4-format",
"form_error_ip_format": "Ugyldig IP-adresse",
"form_error_mac_format": "Ugyldig MAC-format",
"form_error_client_id_format": "Ugyldig ID-klientformat",
"form_error_server_name": "Ugyldig tjenernavn",
@@ -102,6 +109,7 @@
"use_adguard_parental": "Benytt AdGuard sin foreldrekontroll-nettjeneste",
"use_adguard_parental_hint": "AdGuard Home vil sjekke om domenet inneholder erotisk materiale. Den benytter den samme privatlivsvennlige API-en som nettlesersikkerhetstjenesten.",
"enforce_safe_search": "Påtving barnevennlige søk",
"enforce_save_search_hint": "AdGuard Home kan fremtvinge \"Safe Search\" i de følgende søkemotorene: Google, YouTube, Bing, DuckDuckGo, Yandex, og Pixabay.",
"no_servers_specified": "Ingen tjenere er spesifisert",
"general_settings": "Generelle innstillinger",
"dns_settings": "DNS-innstillinger",
@@ -113,6 +121,7 @@
"encryption_settings": "Krypteringsinnstillinger",
"dhcp_settings": "DHCP-innstillinger",
"upstream_dns": "Oppstrøms-DNS-tjenere",
"upstream_dns_help": "Skriv inn én tjeneradresse per linje. <a>Lær mer</a> om å konfigurere oppstrøms-DNS-tjenere.",
"upstream_dns_configured_in_file": "Satt opp i {{path}}",
"test_upstream_btn": "Test oppstrømstilkoblinger",
"upstreams": "Oppstrømstjenere",
@@ -156,6 +165,7 @@
"form_error_url_or_path_format": "Listens URL eller fulle filbane er ugyldig",
"custom_filter_rules": "Selvvalgte filtreringsregler",
"custom_filter_rules_hint": "Skriv inn én oppføring per linje. Du kan bruke adblock-oppføringer, «hosts»-filsyntaks, eller rå domener.",
"system_host_files": "System-'hosts'-filer",
"examples_title": "Eksempler",
"example_meaning_filter_block": "blokker tilgang til 'example.org'-domenet og alle dens underdomener",
"example_meaning_filter_whitelist": "opphev blokkeringen av 'example.org'-domenet og alle dens underdomener",
@@ -171,7 +181,6 @@
"example_upstream_sdns": "du kan bruke <0>DNS-stempler</0> med <1>DNSCrypt</1> eller <2>DNS-over-HTTPS</2>-behandlere",
"example_upstream_tcp": "vanlig DNS (over TCP)",
"all_lists_up_to_date_toast": "Alle listene er allerede oppdatert",
"updated_upstream_dns_toast": "Oppdaterte oppstrøms-DNS-tjenerne",
"dns_test_ok_toast": "De spesifiserte DNS-tjenerne fungerer riktig",
"dns_test_not_ok_toast": "Tjeneren «{{key}}» kunne ikke brukes, vennligst dobbeltsjekk at du har skrevet den riktig",
"unblock": "Tillat",
@@ -309,6 +318,7 @@
"encryption_desc": "Krypteringsstøtte (HTTPS/TLS) for både DNS og admin-nettgrensesnittet",
"encryption_server": "Tjenerens navn",
"encryption_server_enter": "Skriv inn domenenavnet ditt",
"encryption_server_desc": "For å kunne bruke HTTPS, må du skrive inn tjenernavnet som samsvarer med ditt SSL-sertifikat eller jokertegnsertifikat. Hvis feltet er tomt, vil den akseptere TLS-tilkoblinger til ethvert domene.",
"encryption_redirect": "Automatisk omdiriger til HTTPS",
"encryption_redirect_desc": "Dersom dette er valgt, vil AdGuard Home automatisk omdirigere deg fra HTTP til HTTPS-adresser.",
"encryption_https": "HTTPS-port",
@@ -340,6 +350,7 @@
"form_error_password": "Passordet samsvarer ikke",
"reset_settings": "Tilbakestill innstillinger",
"update_announcement": "AdGuard Home {{version}} er nå tilgjengelig! <0>Klikk her</0> for mere informasjon.",
"setup_guide": "Oppsettsveiledning",
"dns_addresses": "DNS-adresser",
"dns_start": "DNS-tjeneren starter opp",
"dns_status_error": "Feil ved sjekk av DNS-tjenerstatusen",
@@ -361,6 +372,7 @@
"client_edit": "Rediger klienten",
"client_identifier": "Identifikator",
"ip_address": "IP-adresse",
"client_identifier_desc": "Klienter kan bli identifisert gjennom IP-adressen, CIDR, MAC-adressen, eller en spesiell klient-ID (kan også brukes for DoT/DoH/DoQ). <0>Her</0> kan du lære mer om å identifisere klienter.",
"form_enter_ip": "Skriv inn IP",
"form_enter_mac": "Skriv inn MAC",
"form_enter_id": "Skriv inn identifikator",
@@ -383,6 +395,7 @@
"access_disallowed_title": "Klienter som skal avvises",
"access_disallowed_desc": "En liste over CIDR- eller IP-adresser. Dersom dette er satt opp, vil AdGuard Home avslå forespørsler fra disse IP-adressene.",
"access_blocked_title": "Blokkerte domener",
"access_blocked_desc": "Ikke forveksle dette med filtre. AdGuard Home vil nekte å behandle DNS-forespørsler som har disse domenene, og disse forespørslene dukker ikke engang opp i forespørselsloggen. Du kan spesifisere nøyaktige domene navn, jokertegn, eller URL-filterregler, f.eks. «example.org», «*.example.log» eller «||example.org^» derav.",
"access_settings_saved": "Tilgangsinnstillingene ble vellykket lagret",
"updates_checked": "Oppdateringene ble vellykket sett etter",
"updates_version_equal": "AdGuard Home er fullt oppdatert",
@@ -391,6 +404,7 @@
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Benytt <1>{{address}}</1>-strengen.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Benytt <1>{{address}}</1>-strengen.",
"setup_dns_privacy_3": "<0>Her er en liste over programvarer du kan bruke.</0>",
"setup_dns_privacy_4": "På en iOS 14 eller macOS Big Sur-enhet kan du laste ned en spesiell '.mobileconfig'-fil som legger til<highlight>DNS-over-HTTPS</highlight>- eller<highlight>DNS-over-TLS</highlight>-tjenere til DNS-innstillingene.",
"setup_dns_privacy_android_1": "Android 9 har innebygd støtte for DNS-over-TLS. For å sette det opp, gå til Innstillinger → Nettverk og internett → Avansert → Privat DNS, og skriv inn domenenavnet ditt der.",
"setup_dns_privacy_android_2": "<0>AdGuard for Android</0> støtter <1>DNS-over-HTTPS</1> og <1>DNS-over-TLS</1>.",
"setup_dns_privacy_android_3": "<0>Intra</0> legger til <1>DNS-over-HTTPS</1>-støtte i Android.",
@@ -450,6 +464,7 @@
"statistics_clear_confirm": "Er du sikker på at du vil slette statistikkene?",
"statistics_retention_confirm": "Er du sikker på at du vil endre hvor lenge statistikkene skal beholdes? Hvis du reduserer den interne verdien, vil noe av dataene gå tapt",
"statistics_cleared": "Statistikkene ble vellykket tømt",
"statistics_enable": "Skru på statistikker",
"interval_hours": "{{count}} time",
"interval_hours_plural": "{{count}} timer",
"filters_configuration": "Oppsett av filtre",
@@ -524,7 +539,7 @@
"show_whitelisted_responses": "Hvitelistet",
"show_processed_responses": "Bearbeidet",
"blocked_safebrowsing": "Blokkert av barnevennlig nettlesing",
"blocked_adult_websites": "Blokkerte voksennettsteder",
"blocked_adult_websites": "Blokkert av foreldrekontroll",
"blocked_threats": "Blokkerte trusler",
"allowed": "Unntak",
"filtered": "Filtrert",
@@ -542,6 +557,8 @@
"cache_ttl_min_override_desc": "Overstyr korte levetidsverdier (i sekunder) som mottas fra oppstrømstjeneren under mellomlagring av DNS-responser",
"cache_ttl_max_override_desc": "Velg en maks-levetidsverdi (i sekunder) for oppføringer i DNS-mellomlageret",
"ttl_cache_validation": "Minimums-mellomlagringslevetidsverdien må være mindre enn eller det samme som maksverdien",
"cache_optimistic": "Optimistisk mellomlagring",
"cache_optimistic_desc": "Få AdGuard Home til å svare fra hurtigbufferen selv når oppføringene er utløpt, og prøv også å oppfriske dem.",
"filter_category_general": "Generelt",
"filter_category_security": "Sikkerhet",
"filter_category_regional": "Regional",
@@ -555,5 +572,7 @@
"port_53_faq_link": "Port 53 er ofte opptatt av «DNSStubListener»- eller «systemd-resolved»-tjenestene. Vennligst les <0>denne instruksjonen</0> om hvordan man løser dette.",
"adg_will_drop_dns_queries": "AdGuard Home vil droppe alle DNS-forespørsler fra denne klienten.",
"experimental": "Eksperimentell",
"parental_control": "Foreldrekontroll"
"use_saved_key": "Bruk den tidligere lagrede nøkkelen",
"parental_control": "Foreldrekontroll",
"served_from_cache": "{{value}} <i>(formidlet fra mellomlageret)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Nieprawidłowy adres IPv6",
"form_error_ip_format": "Nieprawidłowy adres IP",
"form_error_mac_format": "Nieprawidłowy adres MAC",
"form_error_client_id_format": "Nieprawidłowy ID klienta",
"form_error_client_id_format": "ID klienta musi zawierać tylko cyfry, małe litery i myślniki",
"form_error_server_name": "Nieprawidłowa nazwa serwera",
"form_error_subnet": "Podsieć \"{{cidr}}\" nie zawiera adresu IP \"{{ip}}\"",
"form_error_positive": "Musi być większa niż 0",
@@ -163,8 +163,8 @@
"apply_btn": "Zastosuj",
"disabled_filtering_toast": "Wyłączone filtrowanie",
"enabled_filtering_toast": "Włączone filtrowanie",
"disabled_safe_browsing_toast": "Bezpieczne przeglądanie zostało wyłączone",
"enabled_safe_browsing_toast": "Bezpieczne przeglądanie zostało włączone",
"disabled_safe_browsing_toast": "Wyłączone Bezpieczne przeglądanie",
"enabled_safe_browsing_toast": "Włączone Bezpieczne przeglądanie",
"disabled_parental_toast": "Wyłączona Kontrola Rodzicielska",
"enabled_parental_toast": "Włączona Kontrola Rodzicielska",
"disabled_safe_search_toast": "Bezpieczne wyszukiwanie zostało włączone",
@@ -403,6 +403,7 @@
"dns_providers": "Oto lista <0>znanych dostawców DNS</0> do wyboru.",
"update_now": "Aktualizuj teraz",
"update_failed": "Automatyczna aktualizacja nie powiodła się. Proszę <a>wykonaj kroki</a> aby zaktualizować ręcznie.",
"manual_update": "Proszę <a>wykonać te czynności</a>, aby zaktualizować ręcznie.",
"processing_update": "Poczekaj, trwa aktualizacja AdGuard Home",
"clients_title": "Klienci",
"clients_desc": "Skonfiguruj urządzenia podłączone do AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Zablokowane",
"show_whitelisted_responses": "Biała lista",
"show_processed_responses": "Przetworzono",
"blocked_safebrowsing": "Zablokowane przez bezpieczne przeglądanie",
"blocked_adult_websites": "Zablokowane witryny dla dorosłych",
"blocked_safebrowsing": "Zablokowane przez Bezpieczne przeglądanie",
"blocked_adult_websites": "Zablokowane przez Kontrolę rodzicielską",
"blocked_threats": "Zablokowane zagrożenia",
"allowed": "Dozwolone",
"filtered": "Filtrowane",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Endereço de IPv6 inválido",
"form_error_ip_format": "Endereço de IP inválido",
"form_error_mac_format": "Endereço de MAC inválido",
"form_error_client_id_format": "ID de cliente inválido",
"form_error_client_id_format": "O ID do cliente deve conter apenas números, letras minúsculas e hifens",
"form_error_server_name": "Nome de servidor inválido",
"form_error_subnet": "A sub-rede \"{{cidr}}\" não contém o endereço IP \"{{ip}}\"",
"form_error_positive": "Deve ser maior que 0",
@@ -403,6 +403,7 @@
"dns_providers": "Aqui está uma <0>lista de provedores de DNS conhecidos</0> para escolher.",
"update_now": "Atualizar agora",
"update_failed": "A atualização automática falhou. Por favor, <a>siga estes passos</a> para atualizar manualmente.",
"manual_update": "Por favor, <a>siga estes passos</a> para atualizar manualmente.",
"processing_update": "Por favor, aguarde enquanto o AdGuard Home está sendo atualizado",
"clients_title": "Clientes",
"clients_desc": "Configure dispositivos conectados ao AdGuard",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Na lista branca",
"show_processed_responses": "Processado",
"blocked_safebrowsing": "Bloqueado pela navegação segura",
"blocked_adult_websites": "Sites adultos bloqueados",
"blocked_adult_websites": "Bloqueado pelo controle parental",
"blocked_threats": "Ameaças bloqueadas",
"allowed": "Permitido",
"filtered": "Filtrado",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Endereço de IPv6 inválido",
"form_error_ip_format": "Endereço de IP inválido",
"form_error_mac_format": "Endereço de MAC inválido",
"form_error_client_id_format": "ID de cliente inválido",
"form_error_client_id_format": "O ID do cliente deve conter apenas números, letras minúsculas e hifens",
"form_error_server_name": "Nome de servidor inválido",
"form_error_subnet": "A sub-rede \"{{cidr}}\" não contém o endereço IP \"{{ip}}\"",
"form_error_positive": "Deve ser maior que 0",
@@ -403,6 +403,7 @@
"dns_providers": "Aqui está uma <0>lista de provedores de DNS conhecidos</0> para escolher.",
"update_now": "Atualizar agora",
"update_failed": "A atualização automática falhou. Por favor, <a>siga estes passos</a> para atualizar manualmente.",
"manual_update": "Por favor, <a>siga estes passos</a> para atualizar manualmente.",
"processing_update": "Por favor espere, o AdGuard Home está a atualizar-se",
"clients_title": "Clientes",
"clients_desc": "Configure os dispositivos ligados ao AdGuard",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Na lista branca",
"show_processed_responses": "Processado",
"blocked_safebrowsing": "Bloqueado pela navegação segura",
"blocked_adult_websites": "Sítios adultos bloqueados",
"blocked_adult_websites": "Bloqueado pelo controlo parental",
"blocked_threats": "Ameaças bloqueadas",
"allowed": "Permitido",
"filtered": "Filtrado",
@@ -625,7 +626,7 @@
"last_rule_in_allowlist": "Não é possível desautorizar este cliente porque excluir a regra \"{{disallowed_rule}}\" DESATIVARÁ a lista de \"Clientes permitidos\".",
"experimental": "Experimental",
"use_saved_key": "Use a chave guardada anteriormente",
"parental_control": "Controle parental",
"parental_control": "Controlo parental",
"safe_browsing": "Navegação segura",
"served_from_cache": "{{value}} <i>(servido do cache)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Adresa IPv6 nevalidă",
"form_error_ip_format": "Adresă IP nevalidă",
"form_error_mac_format": "Adresă MAC nevalidă",
"form_error_client_id_format": "ID client nevalid",
"form_error_client_id_format": "ID-ul clientului trebuie să conțină numai numere, litere minuscule și liniuțe.",
"form_error_server_name": "Nume de server nevalid",
"form_error_subnet": "Subrețeaua „{{cidr}}” nu conține adresa IP „{{ip}}”",
"form_error_positive": "Trebuie să fie mai mare de 0",
@@ -149,9 +149,9 @@
"general_settings": "Setări Generale",
"dns_settings": "Setări DNS",
"dns_blocklists": "Liste de blocări DNS",
"dns_allowlists": "Listă de DNS-uri autorizate",
"dns_allowlists": "Listă de autorizări DNS",
"dns_blocklists_desc": "AdGuard Home blochează domenii incluse în liste de blocări.",
"dns_allowlists_desc": "Domeniile DNS autorizate vor fi permise, chiar dacă se află pe orice listă de blocări.",
"dns_allowlists_desc": "Domeniile din listele de autorizări DNS vor fi permise chiar dacă se află în oricare dintre listele de blocări.",
"custom_filtering_rules": "Reguli filtrare personale",
"encryption_settings": "Setări de criptare",
"dhcp_settings": "Setări DHCP",
@@ -163,10 +163,10 @@
"apply_btn": "Aplică",
"disabled_filtering_toast": "Filtrare dezactivată",
"enabled_filtering_toast": "Filtrare activată",
"disabled_safe_browsing_toast": "Navigare securitară dezactivată",
"enabled_safe_browsing_toast": "Navigare securitară activată",
"disabled_parental_toast": "Control parental dezactivat",
"enabled_parental_toast": "Control parental activat",
"disabled_safe_browsing_toast": "Navigare în siguranță dezactivată",
"enabled_safe_browsing_toast": "Navigare în siguranță activată",
"disabled_parental_toast": "Control Parental dezactivat",
"enabled_parental_toast": "Control Parental activat",
"disabled_safe_search_toast": "Căutare protejată dezactivată",
"enabled_save_search_toast": "Căutare protejată activată",
"enabled_table_header": "Activat",
@@ -181,7 +181,7 @@
"elapsed": "Scurs",
"filters_and_hosts_hint": "AdGuard Home înțelege regulile de bază de blocare cât și sintaxa fișierelor hosts.",
"no_blocklist_added": "Listă blocări goală",
"no_whitelist_added": "Listă autorizări goală",
"no_whitelist_added": "Nu s-au adăugat autorizări",
"add_blocklist": "Adăugați blocaj",
"add_allowlist": "Adăugați autorizare",
"cancel_btn": "Anulare",
@@ -193,7 +193,7 @@
"edit_blocklist": "Editare blocare",
"edit_allowlist": "Editare autorizare",
"choose_blocklist": "Alegeți liste de blocări",
"choose_allowlist": "Alegeți liste de autorizări",
"choose_allowlist": "Selectați liste de autorizări",
"enter_valid_blocklist": "Introduceți un URL valid pentru blocare.",
"enter_valid_allowlist": "Introduceți un URL valid pentru autorizare.",
"form_error_url_format": "Format URL invalid",
@@ -403,6 +403,7 @@
"dns_providers": "Iată o <0>listă de furnizori DNS cunoscuți</0> ce pot fi aleși.",
"update_now": "Actualizați acum",
"update_failed": "Auto-actualizarea a eșuat. Vă rugăm să <a>urmați aceste etape</a> pentru a actualiza manual.",
"manual_update": "Vă rugăm <a>să urmați etapele următoare</a> pentru a actualiza manual.",
"processing_update": "Vă rugăm să așteptați, AdGuard Home se actualizează...",
"clients_title": "Clienți",
"clients_desc": "Configură aparatele conectate la AdGuard Home",
@@ -585,9 +586,9 @@
"validated_with_dnssec": "Validat cu DNSSEC",
"all_queries": "Toate interogările",
"show_blocked_responses": "Blocat",
"show_whitelisted_responses": "Pe lista albă",
"show_whitelisted_responses": "Autorizate",
"show_processed_responses": "Tratat",
"blocked_safebrowsing": "Blocat de Navigarea securitară",
"blocked_safebrowsing": "Blocat de Navigarea în siguranță",
"blocked_adult_websites": "Site-uri pentru adulți blocate",
"blocked_threats": "Amenințări blocate",
"allowed": "Permise",
@@ -625,6 +626,7 @@
"last_rule_in_allowlist": "Acest client nu poate fi exclus deoarece excluderea regulii „{{disallowed_rule}}” va DEZACTIVA lista „Clienți acceptați”.",
"experimental": "Experimental",
"use_saved_key": "Folosiți cheia salvată anterior",
"parental_control": "Control parental",
"safe_browsing": "Navigare sigura"
"parental_control": "Control Parental",
"safe_browsing": "Navigare în siguranță",
"served_from_cache": "{{value}} <i>(furnizat din cache)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Некорректный IPv6-адрес",
"form_error_ip_format": "Некорректный IP-адрес",
"form_error_mac_format": "Некорректный MAC-адрес",
"form_error_client_id_format": "Некорректный ID клиента",
"form_error_client_id_format": "ID клиента может содержать только цифры, строчные латинские буквы и дефисы",
"form_error_server_name": "Некорректное имя сервера",
"form_error_subnet": "Подсеть «{{cidr}}» не содержит IP-адрес «{{ip}}»",
"form_error_positive": "Должно быть больше 0",
@@ -163,8 +163,8 @@
"apply_btn": "Применить",
"disabled_filtering_toast": "Фильтрация выкл.",
"enabled_filtering_toast": "Фильтрация вкл.",
"disabled_safe_browsing_toast": "Безопасная навигация выкл.",
"enabled_safe_browsing_toast": "Безопасная навигация вкл.",
"disabled_safe_browsing_toast": "Антифишинг отключен",
"enabled_safe_browsing_toast": "Антифишинг включен",
"disabled_parental_toast": "Родительский контроль выкл.",
"enabled_parental_toast": "Родительский контроль вкл.",
"disabled_safe_search_toast": "Безопасный поиск выкл.",
@@ -403,6 +403,7 @@
"dns_providers": "<0>Список известных DNS-провайдеров</0> на выбор.",
"update_now": "Обновить сейчас",
"update_failed": "Ошибка авто-обновления. Пожалуйста, <a>следуйте инструкции</a> для обновления вручную.",
"manual_update": "Пожалуйста, <a>следуйте инструкции</a> для обновления вручную.",
"processing_update": "Пожалуйста, подождите, AdGuard Home обновляется",
"clients_title": "Клиенты",
"clients_desc": "Настройте устройства, использующие AdGuard Home",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Заблокировано",
"show_whitelisted_responses": "В белом списке",
"show_processed_responses": "Обработан",
"blocked_safebrowsing": "Заблокировано согласно базе данных Safebrowsing",
"blocked_adult_websites": "Заблокированные «взрослые» сайты",
"blocked_safebrowsing": "Заблокировано согласно базе данных Safe Browsing",
"blocked_adult_websites": "Заблокировано Родительским контролем",
"blocked_threats": "Заблокировано угроз",
"allowed": "Разрешённые",
"filtered": "Отфильтрованные",

View File

@@ -3,14 +3,14 @@
"example_upstream_comment": "ඔබට අදහසක් සඳහන් කළ හැකිය",
"parallel_requests": "සමාන්තර ඉල්ලීම්",
"load_balancing": "ධාරිතාව තුලනය",
"local_ptr_title": "පෞද්ගලික ප්‍රතිවර්ත ව.නා.ප. සේවාදායකයන්",
"local_ptr_title": "පෞද්ගලික ප්‍රතිවර්ත ව.නා.ප. සේවාදායක",
"local_ptr_placeholder": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් යොදන්න",
"resolve_clients_title": "අනුග්‍රාහකවල අ.ජා. කෙ. ලිපින ප්‍රතිවර්ත විසඳීම සබල කරන්න",
"check_dhcp_servers": "ග.ධා.වි.කෙ. සේවාදායකයන් සඳහා පරීක්ෂා කරන්න",
"resolve_clients_title": "අනුග්‍රාහකවල අ.ජා.කෙ. ලිපින ප්‍රතිවර්ත විසඳීම සබල කරන්න",
"check_dhcp_servers": "ග.ධා.වි.කෙ. සේවාදායක සඳහා පරීක්ෂා කරන්න",
"save_config": "වින්‍යාසය සුරකින්න",
"enabled_dhcp": "ග.ධා.වි.කෙ. සේවාදායකය සබල කර ඇත",
"disabled_dhcp": "ග.ධා.වි.කෙ. සේවාදායකය අබල කර ඇත",
"unavailable_dhcp_desc": "ඇඩ්ගාර්ඩ් හෝම් හට ඔබගේ මෙහෙයුම් පද්ධතියේ ග.ධා.වි.කෙ. සේවාදායකයක් ධාවනය ක නොහැක",
"enabled_dhcp": "ග.ධා.වි.කෙ. සේවාදායකය සබල කෙරිණි",
"disabled_dhcp": "ග.ධා.වි.කෙ. සේවාදායකය අබල කෙරිණි",
"unavailable_dhcp_desc": "ඇඩ්ගාර්ඩ් හෝම් හට ඔබගේ මෙහෙයුම් පද්ධතියේ ග.ධා.වි.කෙ. සේවාදායකයක් ධාවනය කිරීමට නොහැකිය",
"dhcp_title": "ග.ධා.වි.කෙ. සේවාදායකය (පර්යේෂණාත්මක!)",
"dhcp_description": "ඔබගේ මාර්ගකාරකය ග.ධා.වි.කෙ. (DHCP) සැකසුම් ලබා නොදෙන්නේ නම්, ඔබට ඇඩ්ගාර්ඩ් හි ඇති ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කළ හැකිය.",
"dhcp_enable": "ග.ධා.වි.කෙ. සේවාදායකය සබල කරන්න",
@@ -19,24 +19,25 @@
"dhcp_ipv4_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 4 සැකසුම්",
"dhcp_ipv6_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 6 සැකසුම්",
"form_error_required": "අවශ්‍ය ක්ෂේත්‍රයකි",
"form_error_ip4_format": "වලංගු නොවන IPv4 ආකෘතියකි",
"form_error_ip6_format": "වලංගු නොවන IPv6 ආකෘතියකි",
"form_error_ip_format": "වලංගු නොවන අ.ජා. කෙ. (IP) ආකෘතියකි",
"form_error_mac_format": "වලංගු නොවන මා.ප්‍ර.පා. ආකෘතියකි",
"form_error_client_id_format": "වලංගු නොවන අනුග්‍රාහක හැඳුනුම් ආකෘතියකි",
"form_error_ip4_format": "වලංගු නොවන IPv4 ලිපිනයකි",
"form_error_ip4_range_start_format": "පරාසය ආරම්භයේ අ.ජා.කෙ.4 ලිපිනය වලංගු නොවේ",
"form_error_ip4_range_end_format": "පරාසය අවසානයේ අ.ජා.කෙ.4 ලිපිනය වලංගු නොවේ",
"form_error_ip6_format": "වලංගු නොවන අ.ජා.කෙ.6 ලිපිනයකි",
"form_error_ip_format": "අ.ජා.කෙ. (IP) ලිපිනය වලංගු නොවේ",
"form_error_mac_format": "මා.ප්‍ර.පා. ලිපිනය වලංගු නොවේ",
"form_error_client_id_format": "අනුග්‍රාහකයේ හැඳු. වලංගු නොවේ",
"form_error_server_name": "වලංගු නොවන සේවාදායක නාමයකි",
"form_error_positive": "0 ට වඩා වැඩි විය යුතුය",
"form_error_negative": "0 හෝ ඊට වැඩි විය යුතුය",
"dhcp_form_range_title": "අ.ජා. කෙ. (IP) ලිපින පරාසය",
"dhcp_form_range_start": "පරාසය ආරම්භය",
"dhcp_form_range_end": "පරාසය අවසානය",
"dhcp_interface_select": "ග.ධා.වි.කෙ. අතුරුමුහුණත තෝරන්න",
"dhcp_hardware_address": "දෘඩාංග ලිපිනය",
"dhcp_ip_addresses": "අ.ජා. කෙ. (IP) ලිපින",
"ip": "අ.ජා. කෙ. (IP)",
"dhcp_ip_addresses": "අ.ජා.කෙ. (IP) ලිපින",
"ip": "අ.ජා.කෙ. (IP)",
"dhcp_table_hostname": "ධාරක නාමය",
"dhcp_table_expires": "කල් ඉකුත් වීම",
"dhcp_warning": "ඔබට කෙසේ හෝ ග.ධා.වි.කෙ. සේවාදායකය සබල කිරීමට අවශ්‍ය නම්, ඔබේ ජාලයේ වෙනත් ක්‍රියාකාරී ග.ධා.වි.කෙ. සේවාදායකයක් නොමැති බව තහවුරු කරගන්න. මෙය සම්බන්ධිත උපාංග සඳහා අන්තර්ජාලය බිඳ දැමිය හැකිය!",
"dhcp_warning": "ඔබට කෙසේ හෝ ග.ධා.වි.කෙ. සේවාදායකය සබල කිරීමට අවශ්‍ය නම්, ඔබේ ජාලයේ වෙනත් ක්‍රියාකාරී ග.ධා.වි.කෙ. සේවාදායකයක් නැති බව තහවුරු කරගන්න. මෙය සම්බන්ධිත උපාංග සඳහා අන්තර්ජාලය බිඳ දැමිය හැකිය!",
"dhcp_error": "ජාලයේ තවත් ග.ධා.වි.කෙ. සේවාදායකයක් තිබේද යන්න නිශ්චය කළ නොහැකි විය.",
"dhcp_static_ip_error": "ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කිරීම සඳහා ස්ථිතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනයක් සැකසිය යුතුය. මෙම ජාල අතුරුමුහුණත ස්ථිතික අ.ජා. කෙ. ලිපිනයක් භාවිතයෙන් වින්‍යාසගත කර තිබේද යන්න තීරණය කිරීමට ඇඩ්ගාර්ඩ් හෝම් අසමත් විය. කරුණාකර ස්ථිතික අ.ජා. කෙ. ලිපිනයක් අතින් සකසන්න.",
"dhcp_dynamic_ip_found": "ඔබගේ පද්ධතිය <0>{{interfaceName}}</0> අතුරු මුහුණත සඳහා ගතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපින වින්‍යාසය භාවිතා කරයි. ග.ධා.වි.කෙ. සේවාදායකය භාවිතා කිරීම සඳහා ස්ථිතික අ.ජා. කෙ. ලිපිනයක් සැකසිය යුතුය. ඔබගේ වර්තමාන අ.ජා. කෙ. ලිපිනය <0>{{ipAddress}}</0> වේ. ඔබ \"ග.ධා.වි.කෙ. සබල කරන්න\" බොත්තම එබුවහොත් ඇඩ්ගාර්ඩ් හෝම් ස්වයංක්‍රීයව මෙම අ.ජා. කෙ. ලිපිනය ස්ථිතික ලෙස සකසනු ඇත.",
@@ -46,7 +47,7 @@
"delete_confirm": "\"{{key}}\" මකා දැමීමට අවශ්‍ය බව ඔබට විශ්වාසද?",
"form_enter_hostname": "ධාරක නාමය ඇතුල් කරන්න",
"error_details": "දෝෂ විස්තර",
"response_details": "ප්‍රතිචාරයෙහි විස්තර",
"response_details": "ප්‍රතිචාරයෙහි විස්තර",
"request_details": "ඉල්ලීමෙහි විස්තර",
"client_details": "අනුග්‍රාහකයේ විස්තර",
"details": "විස්තර",
@@ -57,8 +58,8 @@
"filter": "පෙරහන",
"query_log": "විමසුම් ලොගය",
"compact": "සංක්ෂිප්ත",
"nothing_found": "කිසිවක් සොයාගත නොහැක",
"faq": "නිති අසන පැණ",
"nothing_found": "කිසිවක් හමු නොවිණි",
"faq": "නිති පැණ",
"version": "අනුවාදය",
"address": "ලිපිනය",
"protocol": "කෙටුම්පත",
@@ -68,87 +69,89 @@
"homepage": "මුල් පිටුව",
"report_an_issue": "ගැටලුවක් වාර්තා කරන්න",
"privacy_policy": "රහස්‍යතා ප්‍රතිපත්තිය",
"enable_protection": "ආරක්ෂණය සබල කරන්න",
"enabled_protection": "ආරක්ෂණය සබල කර ඇත",
"disable_protection": "ආරක්ෂණය අබල කරන්න",
"disabled_protection": "ආරක්ෂණය අබල කර ඇත",
"enable_protection": "රැකවරණය සබල කරන්න",
"enabled_protection": "රැකවරණය සබල කෙරිණි",
"disable_protection": "රැකවරණය අබල කරන්න",
"disabled_protection": "රැකවරණය අබල කෙරිණි",
"refresh_statics": "සංඛ්‍යාලේඛන නැවුම් කරන්න",
"dns_query": "ව.නා.ප. (DNS) විමසුම්",
"blocked_by": "<0>පෙරහන් මගින් අවහිර කරන ලද</0>",
"blocked_by": "<0>පෙරහන් මගින් අවහිර ක</0>",
"stats_malware_phishing": "අවහිර කළ ද්වේශාංග/තතුබෑම්",
"stats_adult": "අවහිර කළ වැඩිහිටි වියමන අඩවි",
"stats_query_domain": "ජනප්‍රිය විමසන ලද වසම්",
"for_last_24_hours": "පසුගිය පැය 24 සඳහා",
"for_last_days": "පසුගිය දින {{count}} සඳහා",
"for_last_days_plural": "පසුගිය දින {{count}} සඳහා",
"no_domains_found": "වසම් කිසිවක් සොයා ගත නොහැකි විය",
"for_last_days": "පසුගිය දවස් {{count}} සඳහා",
"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": "අනුග්‍රාහකයින් හමු නොවිණි",
"top_clients": "ජනප්‍රිය අනුග්‍රාහක",
"no_clients_found": "අනුග්‍රාහක හමු නොවිණි",
"general_statistics": "පොදු සංඛ්‍යාලේඛන",
"number_of_dns_query_days": "පසුගිය දින {{count}} සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_days_plural": "පසුගිය දින {{count}} සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_24_hours": "පසුගිය හෝරා 24 සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_blocked_24_hours": "දැන්වීම් වාරණ පෙරහන් සහ ධාරක වාරණ ලැයිස්තු මගින් අවහිර කරන ලද ව.නා.ප. ඉල්ලීම් ගණන",
"number_of_dns_query_blocked_24_hours_by_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ ඒකකය මගින් අවහිර කරන ලද ව.නා.ප. ඉල්ලීම් ගණන",
"number_of_dns_query_days": "පසුගිය දවස් {{count}} සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_days_plural": "පසුගිය දවස් {{count}} සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_24_hours": "පසුගිය පැය 24 සඳහා සැකසූ ව.නා.ප. විමසුම් ගණන",
"number_of_dns_query_blocked_24_hours": "දැන්වීම් වාරණ පෙරහන් සහ ධාරක වාරණ ලැයිස්තු මගින් අවහිර ක ව.නා.ප. ඉල්ලීම් ගණන",
"number_of_dns_query_blocked_24_hours_by_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ ඒකකය මගින් අවහිර ක ව.නා.ප. ඉල්ලීම් ගණන",
"number_of_dns_query_blocked_24_hours_adult": "අවහිර කළ වැඩිහිටි වියමන අඩවි ගණන",
"enforced_save_search": "ආරක්ෂිත සෙවීම බලාත්මක කරන ලද",
"enforced_save_search": "ආරක්ෂිත සෙවීම බලාත්මක ක",
"number_of_dns_query_to_safe_search": "ආරක්ෂිත සෙවීම බලාත්මක කළ සෙවුම් යන්ත්‍ර සඳහා ව.නා.ප. ඉල්ලීම් ගණන",
"average_processing_time": "සාමාන්‍ය සැකසුම් කාලය",
"average_processing_time_hint": "ව.නා.ප. ඉල්ලීමක් සැකසීමේ සාමාන්‍ය කාලය මිලි තත්පර වලින්",
"block_domain_use_filters_and_hosts": "පෙරහන් සහ ධාරක ගොනු භාවිතා කරමින් වසම් අවහිර කරන්න",
"filters_block_toggle_hint": "ඔබට අවහිර කිරීමේ නීති <a>පෙරහන්</a> තුළ පිහිටුවිය හැකිය.",
"use_adguard_browsing_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ වියමන සේවාව භාවිතා කරන්න",
"use_adguard_browsing_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ වියමන සේවාව භාවිතා කරන්න",
"use_adguard_parental": "ඇඩ්ගාර්ඩ් දෙමාපිය පාලන වියමන සේවාව භාවිතා කරන්න",
"use_adguard_parental_hint": "වසමේ වැඩිහිටියන්ට අදාල කරුණු අඩංගු දැයි ඇඩ්ගාර්ඩ් හෝම් විසින් පරීක්ෂා කරනු ඇත. එය පිරික්සුම් ආරක්ෂණ වියමන සේවාව මෙන් රහස්‍යතා හිතකාමී යෙ.ක්‍ර. අ.මු. (API) භාවිතා කරයි.",
"enforce_safe_search": "ආරක්ෂිත සෙවම භාවිතා කරන්න",
"enforce_save_search_hint": "ඇඩ්ගාර්ඩ් හෝම් පහත සෙවුම් යන්ත්‍ර තුළ ආරක්ෂිත සෙවම බලාත්මක කරනු ඇත: ගූගල්, යූටියුබ්, බින්ග්, ඩක්ඩක්ගෝ, යාන්ඩෙක්ස් සහ පික්සාබේ.",
"use_adguard_parental_hint": "වසමේ වැඩිහිටියන්ට අදාල කරුණු අඩංගු දැයි ඇඩ්ගාර්ඩ් හෝම් විසින් පරීක්ෂා කරනු ඇත. එය පිරික්සුම් ආරක්ෂණ වියමන සේවාව මෙන් රහස්‍යතා හිතකාමී යෙ.ක්‍ර. අ.මු. (API) භාවිතා කරයි.",
"enforce_safe_search": "ආරක්ෂිත සෙවම භාවිතා කරන්න",
"enforce_save_search_hint": "ඇඩ්ගාර්ඩ් හෝම් පහත සෙවුම් යන්ත්‍ර තුළ ආරක්ෂිත සෙවම බලාත්මක කරනු ඇත: ගූගල්, යූටියුබ්, බින්ග්, ඩක්ඩක්ගෝ, යාන්ඩෙක්ස් සහ පික්සාබේ.",
"no_servers_specified": "සේවාදායක කිසිවක් නිශ්චිතව දක්වා නැත",
"general_settings": "පොදු සැකසුම්",
"dns_settings": "ව.නා.ප. සැකසුම්",
"dns_blocklists": "ව.නා.ප. අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තු",
"dns_allowlists": "ව.නා.ප. ඉඩ දීමේ ලැයිස්තු",
"dns_blocklists_desc": "ඇඩ්ගාර්ඩ් හෝම් විසින් අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තු වලට ගැපෙන වසම් අවහිර කරනු ඇත.",
"dns_blocklists_desc": "ඇඩ්ගාර්ඩ් හෝම් විසින් අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තු වලට ගැපෙන වසම් අවහිර කරනු ඇත.",
"dns_allowlists_desc": "ඉඩ දීමේ ව.නා.ප. ලැයිස්තුවල වසම් කිසියම් අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුවක අඩංගු වුවද එය නොසලකා හැර ඉඩ දෙනු ලැබේ.",
"custom_filtering_rules": "අභිරුචි පෙරීමේ නීති",
"encryption_settings": "සංකේතාංකන සැකසුම්",
"encryption_settings": "සංකේතන සැකසුම්",
"dhcp_settings": "ග.ධා.වි.කෙ. සැකසුම්",
"upstream_dns": "Upstream ව.නා.ප. සේවාදායකයන්",
"upstream_dns_help": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් ඇතුල් කරන්න. upstream ව.නා.ප. (DNS) \n සේවාදායකයන් වින්‍යාසගත කිරීම ගැන <a>තව දැනගන්න</a>.",
"upstream_dns": "Upstream ව.නා.ප. සේවාදායක",
"upstream_dns_help": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් ඇතුල් කරන්න. upstream ව.නා.ප. (DNS) \n සේවාදායක වින්‍යාසගත කිරීම ගැන <a>තව දැනගන්න</a>.",
"upstream_dns_configured_in_file": "{{path}} හි වින්‍යාසගත කර ඇත",
"apply_btn": "යොදන්න",
"disabled_filtering_toast": "පෙරීම අබල කර ඇත",
"enabled_filtering_toast": "පෙරීම සබල කර ඇත",
"disabled_safe_browsing_toast": "ආරක්ෂිත සෙවීම අබල කර ඇත",
"enabled_safe_browsing_toast": "ආරක්ෂිත සෙවීම සබල කර ඇත",
"disabled_parental_toast": "Parental control අබල කර ඇත",
"enabled_parental_toast": "Parental control සබල කර ඇත",
"disabled_safe_search_toast": "ආරක්ෂිත සෙවම අබල කර ඇත",
"enabled_save_search_toast": "ආරක්ෂිත සෙවම සබල කර ඇත",
"enabled_table_header": "සබල කර ඇත",
"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": "ඒ.ස.නි.(URL) ලැයිස්තුව",
"rules_count_table_header": "නීති ගණන",
"last_time_updated_table_header": "අවසන් වරට යාවත්කාලීන කරන ලද",
"last_time_updated_table_header": "අවසන් යාවත්කාල වීම",
"actions_table_header": "ක්‍රියාමාර්ග",
"request_table_header": "ඉල්ලීම",
"edit_table_action": "සංස්කරණය කරන්න",
"delete_table_action": "මකන්න",
"elapsed": "ගත වූූූ කාලය",
"elapsed": "ගත වූ කාලය",
"filters_and_hosts_hint": "ඇඩ්ගාර්ඩ් හෝම් මූලික දැන්වීම් වාරණ නීති සහ ධාරක ගොනු පද ගැලපුම් තේරුම් ගනී.",
"no_blocklist_added": "අවහිර කිරීමේ ලැයිස්තු එකතු කර නැත",
"no_whitelist_added": "ඉඩ දීමේ ලැයිස්තු එකතු කර නැත",
"add_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුවක් එකතු කරන්න",
"add_allowlist": "ඉඩ දීමේ ලැයිස්තුවක් එකතු කරන්න",
"cancel_btn": "අහෝසි කරන්න",
"cancel_btn": "අවලංගු",
"enter_name_hint": "නම ඇතුල් කරන්න",
"enter_url_or_path_hint": "ලැයිස්තුවක ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයක් ඇතුල් කරන්න",
"check_updates_btn": "යාවත්කාල පරීක්ෂා කරන්න",
"check_updates_btn": "යාවත්කාල පරීක්ෂා කරන්න",
"new_blocklist": "නව අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුව",
"new_allowlist": "නව ඉඩ දීමේ ලැයිස්තුව",
"edit_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුව සංස්කරණය කරන්න",
"edit_allowlist": "ඉඩ දීමේ ලැයිස්තුව සංස්කරණය කරන්න",
"edit_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුව සංස්කරණය",
"edit_allowlist": "ඉඩ දීමේ ලැයිස්තුව සංස්කරණය",
"choose_blocklist": "අවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න",
"choose_allowlist": "ඉඩ දීමේ ලැයිස්තු තෝරන්න",
"enter_valid_blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුල් කරන්න.",
@@ -157,22 +160,23 @@
"form_error_url_or_path_format": "ලැයිස්තුවක වලංගු නොවන ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයකි",
"custom_filter_rules": "අභිරුචි පෙරීමේ නීති",
"custom_filter_rules_hint": "පේළියකට එක් නීතියක් බැගින් ඇතුල් කරන්න. ඔබට දැන්වීම් අවහිර කිරීමේ නීති හෝ ධාරක ගොනු පද ගැලපුම් භාවිතා කළ හැකිය.",
"system_host_files": "පද්ධතියේ සත්කාරක ගොනු",
"examples_title": "උදාහරණ",
"example_meaning_filter_block": "example.org වසමට සහ එහි සියුම උප වසම් වලට පිවිසීම අවහිර කරයි",
"example_meaning_filter_whitelist": "example.org වසමට සහ එහි සියුම උප වසම් වලට ප්‍රවේශය අවහිර නොකරයි",
"example_meaning_host_block": "ඇඩ්ගාර්ඩ් හෝම් දැන් example.org වසම සඳහා 127.0.0.1 ලිපිනය ලබා දෙනු ඇත (නමුත් එහි උප ලිපින නොවේ).",
"example_meaning_filter_block": "උදාහරණය.ලංකා වසමට සහ එහි සියුම උප වසම් වලට ප්‍රවේශය අවහිර කරයි",
"example_meaning_filter_whitelist": "උදාහරණය.ලංකා වසමට සහ එහි සියුම උප වසම් වලට ප්‍රවේශය අවහිර කරයි",
"example_meaning_host_block": "ඇඩ්ගාර්ඩ් හෝම් දැන් උදාහරණය.ලංකා වසම සඳහා 127.0.0.1 ලිපිනය ලබා දෙනු ඇත (නමුත් එහි උප ලිපින නොවේ).",
"example_comment": "! මෙතැන අදහස් දැක්වීමක්",
"example_comment_meaning": "විස්තර කිරීමක්",
"example_comment_meaning": "අදහසක්",
"example_comment_hash": "# එසේම අදහස් දැක්වීමක්",
"example_regex_meaning": "නිශ්චිතව දක්වා ඇති නිත්‍ය වාක්‍යවිධියට ගැලපෙන වසම් වෙත පිවිසීම අවහිර කරයි",
"example_regex_meaning": "නිශ්චිතව දක්වා ඇති නිත්‍ය වාක්‍යවිධියට ගැලපෙන වසම් වෙත ප්‍රවේශය අවහිර කරයි",
"example_upstream_regular": "සාමාන්‍ය ව.නා.ප. (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_dot": "සංකේතිත <0>DNS-over-TLS</0>",
"example_upstream_doh": "සංකේතිත <0>DNS-over-HTTPS</0>",
"example_upstream_doq": "සංකේතිත <0>DNS-over-QUIC</0>",
"example_upstream_tcp": "සාමාන්‍ය ව.නා.ප. (TCP/ස.පා.කෙ. හරහා) ",
"all_lists_up_to_date_toast": "සියුම ලැයිස්තු දැනටමත් යාවත්කාලීනයි",
"dns_test_ok_toast": "සඳහන් කළ ව.නා.ප. සේවාදායකයන් නිවැරදිව ක්‍රියා කරයි",
"dns_test_not_ok_toast": "සේවාදායක \"{{key}}\": භාවිතා ක නොහැකි විය, කරුණාකර ඔබ එය නිවැරදිව ලියා ඇතදැයි පරීක්ෂා කරන්න",
"all_lists_up_to_date_toast": "සියුම ලැයිස්තු දැනටමත් යාවත්කාලීනයි",
"dns_test_ok_toast": "සඳහන් කළ ව.නා.ප. සේවාදායක නිවැරදිව ක්‍රියා කරයි",
"dns_test_not_ok_toast": "\"{{key}}\" සේවාදායක(ය): භාවිතා කිරීමට නොහැකි විය, ඔබ එය නිවැරදිව ලියා ඇතදැයි පරීක්ෂා කරන්න",
"unblock": "අනවහිර",
"block": "අවහිර",
"disallow_this_client": "මෙම අනුග්‍රාහකයට නොඉඩ දෙන්න",
@@ -196,11 +200,11 @@
"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}} මගින් පෙරහන් කරන ලදි",
"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_updated": "විමසුම් ලොගය සාර්ථකව යාවත්කාලීන කරන ලදි",
"query_log_clear": "විමසුම් ලොග ඉවත් කරන්න",
@@ -208,10 +212,10 @@
"query_log_enable": "ලොගය සබල කරන්න",
"query_log_configuration": "ලොග වින්‍යාසය",
"query_log_disabled": "විමසුම් ලොගය අබල කර ඇති අතර එය <0>සැකසුම්</0> තුළ වින්‍යාසගත කළ හැකිය",
"query_log_strict_search": "ඉතා නිවැරදිව සෙවීම සඳහා ද්විත්ව උද්ධෘතය භාවිතා කරන්න",
"query_log_strict_search": "ඉතා නිවැරදිව සෙවීම ද්විත්ව උද්ධෘතය භාවිතා කරන්න",
"query_log_retention_confirm": "විමසුම් ලොගය රඳවා තබා ගැනීම වෙනස් කිරීමට අවශ්‍ය බව ඔබට විශ්වාසද? ඔබ කාල පරතරයෙහි අගය අඩු කළහොත් සමහර දත්ත නැති වී යනු ඇත",
"anonymize_client_ip": "අනුග්‍රාහකයෙහි අ.ජා. කෙ. (IP) නිර්නාමික කරන්න",
"anonymize_client_ip_desc": "ලොග සහ සංඛ්‍යාලේඛන තුළ අනුග්‍රාහකයේ සම්පූර්ණ අ.ජා. කෙ. ලිපිනය සුරකීමෙන් වලකින්න",
"anonymize_client_ip": "අනුග්‍රාහකයෙහි අ.ජා.කෙ. (IP) නිර්නාමික කරන්න",
"anonymize_client_ip_desc": "ලොග සහ සංඛ්‍යාලේඛන තුළ අනුග්‍රාහකයේ සම්පූර්ණ අ.ජා.කෙ. ලිපිනය සුරකීමෙන් වලකින්න",
"dns_config": "ව.නා.ප. සේවාදායක වින්‍යාසය",
"dns_cache_config": "ව.නා.ප. නිහිත වින්‍යාසය",
"dns_cache_config_desc": "මෙහිදී ඔබට ව.නා.ප. නිහිතය වින්‍යාසගත කළ හැකිය",
@@ -219,8 +223,8 @@
"default": "සුපුරුදු",
"nxdomain": "නොපවතින වසම",
"refused": "REFUSED",
"null_ip": "අභිශූන්‍යය අ.ජා. කෙ.",
"custom_ip": "අභිරුචි අ.ජා. කෙ.",
"null_ip": "අභිශූන්‍යය අ.ජා.කෙ.",
"custom_ip": "අභිරුචි අ.ජා.කෙ.",
"blocking_ipv4": "අ.ජා.කෙ.4 අවහිර කිරීම",
"blocking_ipv6": "අ.ජා.කෙ.6 අවහිර කිරීම",
"client_id": "අනුග්‍රාහකයේ හැඳුනුම",
@@ -229,15 +233,16 @@
"plain_dns": "සරල ව.නා.ප.",
"form_enter_rate_limit": "අනුපාත සීමාව ඇතුල් කරන්න",
"rate_limit": "අනුපාත සීමාව",
"edns_enable": "EDNS අනුග්‍රාහක අනුජාලය සබල කරන්න",
"rate_limit_desc": "එක් අනුග්‍රාහකයකට ඉඩ දී ඇති තත්පරයට ඉල්ලීම් ගණන. එය 0 ලෙස සැකසීම යනුවෙන් අදහස් කරන්නේ සීමාවක් නැති බවයි.",
"blocking_ipv4_desc": "අවහිර කළ A ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා.කෙ. (IP) ලිපිනය",
"blocking_ipv6_desc": "අවහිර කළ AAAA ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා.කෙ. (IP) ලිපිනය",
"blocking_mode_default": "පොදු: දැන්වීම් අවහිර කරන ආකාරයේ නීතියක් මගින් අවහිර කළ විට REFUSED සමඟ ප්‍රතිචාර දක්වයි; /etc/host-style ආකාරයේ නීතියක් මගින් අවහිර කළ විට නීතියේ දක්වා ඇති අ.ජා. කෙ. ලිපිනය සමඟ ප්‍රතිචාර දක්වයි",
"blocking_mode_refused": "REFUSED: REFUSED කේතය සමඟ ප්‍රතිචාර දක්වයි",
"blocking_mode_nxdomain": "නොපවතින වසම (NXDOMAIN): NXDOMAIN කේතය සමඟ ප්‍රතිචාර දක්වයි",
"blocking_mode_null_ip": "අභිශූන්‍යය අ.ජා. කෙ. : ශුන්‍ය අ.ජා. කෙ. ලිපිනය සමඟ ප්‍රතිචාර දක්වයි (A සඳහා 0.0.0.0; AAAA සඳහා ::)",
"blocking_mode_nxdomain": "නොපවතින වසම: NXDOMAIN කේතය සමඟ ප්‍රතිචාර දක්වයි",
"blocking_mode_null_ip": "අභිශූන්‍යය අ.ජා.කෙ.: ශුන්‍ය අ.ජා.කෙ. ලිපිනය සමඟ ප්‍රතිචාර දක්වයි (A සඳහා 0.0.0.0; AAAA සඳහා ::)",
"blocking_mode_custom_ip": "අභිරුචි අන්තර්ජාල කෙටුම්පත: අතින් සැකසූ අ.ජා. කෙ. ලිපිනයක් සමඟ ප්‍රතිචාර දක්වයි",
"upstream_dns_client_desc": "ඔබ මෙම ක්ෂේත්‍රය හිස්ව තබා ගන්නේ නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් <0>ව.නා.ප. සැකසුම්</0> හි වින්‍යාසගත කර ඇති සේවාදායකයන් භාවිතා කරනු ඇත.",
"upstream_dns_client_desc": "ඔබ මෙම ක්ෂේත්‍රය හිස්ව තබා ගන්නේ නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් <0>ව.නා.ප. සැකසුම්</0> හි වින්‍යාසගත කර ඇති සේවාදායක භාවිතා කරනු ඇත.",
"tracker_source": "ලුහුබැඳීම් මූලාශ්‍රය",
"source_label": "මූලාශ්‍රය",
"found_in_known_domain_db": "දැනුවත් වසම් දත්ත ගබඩාවේ හමු විය.",
@@ -245,61 +250,60 @@
"rule_label": "නීති(ය)",
"list_label": "ලැයිස්තුව",
"unknown_filter": "{{filterId}} නොදන්නා පෙරහනකි",
"known_tracker": "දැනුවත් ලුහුබැඳීමක",
"known_tracker": "දැනුවත් ලුහුබැඳීමක",
"install_welcome_title": "ඇඩ්ගාර්ඩ් හෝම් වෙත සාදරයෙන් පිළිගනිමු!",
"install_welcome_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු ජාලය පුරා ඇති දැන්වීම් සහ ලුහුබැඳීම අවහිර කරන ව.නා.ප. සේවාදායකි. ඔබගේ මුළු ජාලය සහ සියුම උපාංග පාලනය කිරීමට ඉඩ සලසා දීම එහි පරමාර්ථය යි, එයට අනුග්‍රාහක පාර්ශවීය වැඩසටහනක් භාවිතා කිරීම අවශ්‍ය නොවේ.",
"install_welcome_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු ජාලය පුරා ඇති දැන්වීම් සහ ලුහුබැඳීම අවහිර කරන ව.නා.ප. සේවාදායකයකි. ඔබගේ මුළු ජාලය සහ සියුම උපාංග පාලනය කිරීමට ඉඩ සලසා දීම එහි පරමාර්ථය යි, එයට අනුග්‍රාහක පාර්ශවීය වැඩසටහනක් භාවිතා කිරීම අවශ්‍ය නොවේ.",
"install_settings_title": "පරිපාලක වියමන අතුරු මුහුණත",
"install_settings_listen": "සවන් දෙන අතුරු මුහුණත",
"install_settings_port": "කෙවෙනිය",
"install_settings_interface_link": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාලක වියමන අතුරු මුහුණත පහත ලිපිනයන්ගෙන් ප්‍රවේශ විය හැකිය:",
"install_settings_interface_link": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාලක වියමන අතුරු මුහුණත පහත ලිපින වලින් ප්‍රවේශ වීමට හැකිය:",
"form_error_port": "වලංගු කෙවෙනියක අගයක් යොදන්න",
"install_settings_dns": "ව.නා.ප. සේවාදායකය",
"install_settings_dns_desc": "පහත ලිපිනයන්හි ව.නා.ප. සේවාදායකය භාවිතා කිරීම සඳහා ඔබගේ උපාංග හෝ මාර්ගකාරකය වින්‍යාසගත කිරීමට අවශ්‍ය වනු ඇත:",
"install_settings_all_interfaces": "සියලුම අතුරුමුහුණත්",
"install_auth_title": "සත්‍යාපනය",
"install_auth_desc": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාල වියමන අතුරු මුහුණතට මුරපද සත්‍යාපනය වින්‍යාසගත කිරීම අතිශයින් නිර්දේශ කෙරේ. එය ඔබගේ ස්ථානීය ජාල‌යෙන් පමණක් ප්‍රවේශ විය හැකි වුවද, එය තව දුරටත් සීමා රහිත ප්‍රවේශයකින් ආරක්ෂා කර ගැනීම වැදගත් ය.",
"install_auth_desc": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාල වියමන අතුරු මුහුණතට මුරපද සත්‍යාපනය වින්‍යාසගත කළ යුතුය. එය ඔබගේ ස්ථානීය ජාල‌යෙන් පමණක් ප්‍රවේශ විය හැකි වුවද, එය තව දුරටත් සීමා රහිත ප්‍රවේශයකින් ආරක්ෂා කර ගැනීම වැදගත් ය.",
"install_auth_username": "පරිශීලක නාමය",
"install_auth_password": "මුරපදය",
"install_auth_confirm": "මුරපදය තහවුරු කරන්න",
"install_auth_username_enter": "පරිශීලක නාමය ඇතුල් කරන්න",
"install_auth_username_enter": "පරිශීලක නාමය යොදන්න",
"install_auth_password_enter": "මුරපදය ඇතුල් කරන්න",
"install_step": "පියවර",
"install_devices_title": "ඔබගේ උපාංග වින්‍යාසගත කරන්න",
"install_devices_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කිරීම ආරම්භයට, ඔබගේ උපාංග එය පරිශ්‍රීලනයට වින්‍යාසගත කිරීම අවශ්‍ය වේ.",
"install_devices_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කිරීම ආරම්භයට, ඔබගේ උපාංග එය පරිශ්‍රීලනයට වින්‍යාසගත කළ යුතුය.",
"install_submit_title": "සුභ පැතුම්!",
"install_submit_desc": "පිහිටුවීමේ ක්‍රියා පටිපාටිය අවසන් වී ඇති අතර ඔබ දැන් ඇඩ්ගාර්ඩ් හෝම් භාවිතය ආරම්භ කිරීමට සූදානම්ය.",
"install_devices_router": "මාර්ගකාරකය",
"install_devices_router_desc": "මෙම පිහිටුම ඔබගේ නිවසේ මාර්ගකාරකයට සම්බන්ධ සියලුම උපාංග ස්වයංක්‍රීයව ආවරණය කරන අතර ඔබට ඒ සෑම එකක්ම අතින් වින්‍යාසගත කිරීමට අවශ්‍ය නොවේ.",
"install_devices_address": "ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය පහත ලිපිනයන්ට සවන් දෙමින් පවතී",
"install_devices_router_list_2": "ග.ධා.වි.කෙ. (DHCP)/ ව.නා.ප. (DNS) සැකසුම් සොයා ගන්න. ඉලක්කම් කට්ටල දෙකකට හෝ තුනකට ඉඩ දෙන ක්ෂේත්‍රයක් අසල ඇති ව.නා.ප. අක්ෂර සොයන්න, සෑම එකක්ම ඉලක්කම් එකේ සිට තුන දක්වා කාණ්ඩ හතරකට බෙදා ඇත.",
"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_router_list_4": "සමහර වර්ගයේ මාර්ගකාරක වල අභිරුචි ව.නා.ප. සේවාදායකයක් සැකසීමට නොහැකිය. මෙම අවස්ථාවේදී ඇඩ්ගාර්ඩ් හෝම් <0>ග.ධා.වි.කෙ. සේවාදායකයක්</0> ලෙස පිහිටුවන්නේ නම් එය උපකාර වනු ඇත. එසේ නැතිනම්, ඔබගේ විශේෂිත මාර්ගකාරකය සඳහා වූ ව.නා.ප. සේවාදායක රිසිකරණය කරන්නේ කෙසේද යන්න පිළිබඳ අත්පොත පරීක්ෂා කළ යුතුය.",
"install_devices_windows_list_2": "ජාල සහ අන්තර්ජාල ප්‍රවර්ගයට ගොස් පසුව ජාල සහ බෙදාගැනීමේ මධ්‍යස්ථානය වෙත යන්න.",
"install_devices_windows_list_3": "උපයුක්තක‌‌‌යෙහි සැකසුම් වෙනස් කිරීම තිරයේ වම් පසින් සොයාගෙන එය මත ක්ලික් කරන්න.",
"install_devices_windows_list_3": "\"උපයුක්තක‌‌‌යෙහි සැකසුම් වෙනස් කිරීම\" තිරයේ වම් පසින් සොයාගෙන එය මත ඔබන්න.",
"install_devices_windows_list_4": "ඔබගේ ක්‍රියාකාරී සම්බන්ධතාවය තෝරන්න, එය මත දකුණු-ක්ලික් කර ගුණාංග තෝරන්න.",
"install_devices_windows_list_5": "ලැයිස්තුවේ ඇති අන්තර්ජාල කෙටුම්පත් අනුවාදය 4 (TCP/IP) සොයාගෙන එය තෝරා ඉන්පසු ගුණාංග මත නැවත ක්ලික් කරන්න.",
"install_devices_windows_list_6": "'පහත සඳහන් ව.නා.ප. සේවාදායක ලිපින භාවිතා කරන්න' යන්න තෝරා ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුළත් කරන්න.",
"install_devices_macos_list_1": "ඇපල් අයිකනය මත ක්ලික් කර පද්ධති මනාපයන් වෙත යන්න.",
"install_devices_macos_list_2": "ජාලය මත ක්ලික් කරන්න.",
"install_devices_macos_list_3": "ඔබගේ ලැයිස්තුවේ පළමු සම්බන්ධතාවය තෝරා උසස් මත ක්ලික් කරන්න.",
"install_devices_windows_list_5": "ලැයිස්තුවෙන් \"අන්තර්ජාල කෙටුම්පත් අනුවාදය 4 (TCP/IPv4)\" (හෝ, IPv6 සඳහා, \"අන්තර්ජාල කෙටුම්පත් අනුවාදය 6 (TCP/IPv6)\") සොයාගෙන එය තෝරා ඉන්පසු ගුණාංග මත නැවත ඔබන්න.",
"install_devices_windows_list_6": "'පහත සඳහන් ව.නා.ප. සේවාදායක ලිපින භාවිතා කරන්න' යන්න තෝරා ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතු් කරන්න.",
"install_devices_macos_list_1": "ඇපල් නිරූපකය එබීමෙන් පසු පද්ධතියේ මනාප වෙත යන්න.",
"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_3": "ඔබ සම්බන්ධ වී ඇති ජාලය මත දිගු වේලාවක් ඔබන්න, ඉන්පසුව ජාලය වෙනස් කිරීම මත තට්ටු කරන්න.",
"install_devices_android_list_4": "ඔබට සමහර උපාංගවල වැඩිදුර සැකසුම් බැලීමට \"උසස්\" සඳහා වූ කොටුව සලකුණු කිරීමට අවශ්‍ය විය හැකිය. එමෙන්ම ඔබගේ ඇන්ඩ්‍රොයිඩ් ව.නා.ප. (DNS) සැකසුම් වෙනස් කිරීමට අ.ජා. කෙ. (IP) සැකසුම්, ග.ධා.වි.කෙ. (DHCP) සිට ස්ථිතික වෙත මාරු කළ යුතුය.",
"install_devices_android_list_3": "සම්බන්ධි ජාලය මත දිගු වේලාවක් ඔබන්න, ඉන්පසුව ජාලය වෙනස් කිරීම මත තට්ටු කරන්න.",
"install_devices_android_list_4": "ඔබට සමහර උපාංගවල සියළු සැකසුම් බැලීමට \"වැඩිදුර\" සඳහා වූ කොටුව සලකුණු කිරීමට අවශ්‍ය විය හැකිය. එමෙන්ම ඔබගේ ඇන්ඩ්‍රොයිඩ් ව.නා.ප. (DNS) සැකසුම් වෙනස් කිරීමට අ.ජා.කෙ. (IP) සැකසුම්, ග.ධා.වි.කෙ. (DHCP) සිට ස්ථිතික වෙත මාරු කළ යුතුය.",
"install_devices_android_list_5": "ව.නා.ප. 1 සහ ව.නා.ප. 2 පිහිටුවීම් අගයන් ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින වලට වෙනස් කරන්න.",
"install_devices_ios_list_1": "මුල් තිරයේ සිට, සැකසුම් මත තට්ටු කරන්න.",
"install_devices_ios_list_2": "වම්පස මෙනුවෙහි වයි-ෆයි තෝරන්න (ජංගම දුරකථන සඳහා ව.නා.ප. වින්‍යාසගත කිරීමට නොහැකිය).",
"install_devices_ios_list_2": "වම්පස මෙනුවෙහි වයි-ෆයි තෝරන්න (ජං. දු.ක. සඳහා ව.නා.ප. වින්‍යාසගත කිරීමට නොහැකිය).",
"install_devices_ios_list_3": "දැනට ක්‍රියාකාරී ජාලයයහෙි නම මත තට්ටු කරන්න.",
"install_devices_ios_list_4": "ව.නා.ප. (DNS) ක්ෂේත්‍රය තුළ ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුල් කරන්න.",
"get_started": "ආරම්භ කර ගන්න",
"get_started": "පටන් ගන්න",
"next": "ඊළඟ",
"open_dashboard": "උපකරණ පුවරුව විවෘත කරන්න",
"install_saved": "සාර්ථකව සුරකින ලදි",
"encryption_title": "සංකේතාංකනය",
"encryption_title": "සංකේතනය",
"encryption_desc": "ගුප්තකේතනය (HTTPS/TLS) සඳහා ව.නා.ප. සහ පරිපාලක වියමන අතුරු මුහුණත සහය දක්වයි",
"encryption_config_saved": "සංකේතාංකන වින්‍යාසය සුරකින ලදි",
"encryption_config_saved": "සංකේතන වින්‍යාසය සුරකින ලදි",
"encryption_server": "සේවාදායක‌‌‌‌යේ නම",
"encryption_server_enter": "ඔබගේ වසම් නාමය ඇතුල් කරන්න",
"encryption_redirect": "ස්වයංක්‍රීයව HTTPS වෙත හරවා යවන්න",
@@ -311,13 +315,13 @@
"encryption_doq": "DNS-over-QUIC කෙවෙනිය",
"encryption_doq_desc": "මෙම කෙවෙනිය වින්‍යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කෙවෙනිය හරහා DNS-over-QUIC සේවාදායකයක් ධාවනය කරනු ඇත. එය පර්යේෂණාත්මක වන අතර විශ්වාසදායක නොවිය හැකිය. එසේම, මේ වන විට එයට සහාය දක්වන බොහෝ අනුග්‍රාහකයින් නැත.",
"encryption_certificates": "සහතික",
"encryption_certificates_input": "ඔබගේ PEM-කේතාංකනය කළ සහතික පිටපත් කර මෙහි අලවන්න.",
"encryption_status": "තත්ත්වය",
"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_key_input": "ඔබගේ සහතිකය සඳහා PEM-කේතනය කළ පුද්ගලික යතුර පිටපත් කර මෙහි අලවන්න.",
"encryption_enable": "සංකේතනය සබල කරන්න (HTTPS, DNS-over-HTTPS සහ DNS-over-TLS)",
"encryption_enable_desc": "සංකේතනය සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ක්‍රියා කරනු ඇති අතර ව.නා.ප. සේවාදායකය DNS-over-HTTPS සහ DNS-over-TLS හරහා ලැබෙන ඉල්ලීම් සඳහා සවන් දෙනු ඇත.",
"encryption_chain_valid": "සහතික දාමය වලංගු ය",
"encryption_chain_invalid": "සහතික දාමය වලංගු නොවේ",
"encryption_key_valid": "මෙය වලංගු {{type}} පුද්ගලික යතුරකි",
@@ -326,26 +330,26 @@
"encryption_issuer": "නිකුත් කරන්නා",
"encryption_hostnames": "ධාරක නාම",
"encryption_reset": "සංකේතාංකන සැකසුම් යළි පිහිටුවීමට අවශ්‍ය බව ඔබට විශ්වාස ද?",
"topline_expiring_certificate": "ඔබගේ SSL සහතිකය කල් ඉකුත්වීමට ආසන්න වී ඇත. <0>සංකේතාංකන සැකසුම්</0> යාවත්කාල කරන්න.",
"topline_expired_certificate": "ඔබගේ SSL සහතිකය කල් ඉකුත් වී ඇත. <0>සංකේතාංකන සැකසුම්</0> යාවත්කාල කරන්න.",
"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": "මුරපදය නොගැලපුුුුුුණි",
"form_error_password": "මුරපදය නොගැලපුණි",
"reset_settings": "සැකසුම් යළි පිහිටුවන්න",
"update_announcement": "ඇඩ්ගාර්ඩ් හෝම් {{version}} දැන් ලබා ගත හැකිය! වැඩි විස්තර සඳහා <0>මෙහි ක්ලික් කරන්න</0>.",
"update_announcement": "ඇඩ්ගාර්ඩ් හෝම් {{version}} දැන් ලබා ගත හැකිය! වැඩි විස්තර සඳහා <0>මෙය ඔබන්න</0>.",
"setup_guide": "පිහිටුවීමේ මාර්ගෝපදේශය",
"dns_addresses": "ව.නා.ප. ලිපින",
"dns_start": "ව.නා.ප. සේවාදායකය ආරම්භ වෙමින් පවතී",
"dns_status_error": "ව.නා.ප. සේවාදායකයේ තත්වය පරීක්ෂා කිරීමේදී දෝෂයකි",
"down": "පහත",
"fix": "නිරාකරණය කරන්න",
"dns_start": "ව.නා.ප. සේවාදායකය ආරම්භ වෙමින්",
"dns_status_error": "ව.නා.ප. සේවාදායකයේ තත්වය පරීක්ෂා කිරීමේදී දෝෂයකි",
"down": "බිඳ වැටී",
"fix": "නිරාකරණය",
"dns_providers": "මෙහි තෝරා ගැනීමට <0>දැනුවත් ව.නා.ප. සපයන්නන්ගේ ලැයිස්තුවක්</0> ඇත.",
"update_now": "දැන් \tයාවත්කාල කරන්න",
"update_failed": "ස්වයංක්‍රීය යාවත්කාල කිරීම අසාර්ථක විය. අතින් යාවත්කාල කිරීමට කරුණාකර <a>පියවර අනුගමනය කරන්න</a>.",
"processing_update": "කරුණාකර රැඳී සිටින්න, ඇඩ්ගාර්ඩ් හෝම් යාවත්කාලීන වෙමින් පවතී",
"clients_title": "අනුග්‍රාහකයන්",
"clients_desc": "ඇඩ්ගාර්ඩ් හෝම් වෙත සම්බන්ධ කර ඇති උපාංග වින්‍යාසගත කරන්න",
"update_now": "යාවත්කාල කරන්න",
"update_failed": "ස්වයං යාවත්කාලය අසමත් විය. අතින් යාවත්කාල කිරීමට කරුණාකර <a>පියවර අනුගමනය කරන්න</a>.",
"processing_update": "රැඳී සිටින්න, ඇඩ්ගාර්ඩ් හෝම් යාවත්කාල වෙමින්",
"clients_title": "අනුග්‍රාහක",
"clients_desc": "ඇඩ්ගාර්ඩ් හෝම් වෙත සම්බන්ධි උපාංග වින්‍යාසගත කරන්න",
"settings_global": "ගෝලීය",
"settings_custom": "අභිරුචි",
"table_client": "අනුග්‍රාහකය",
@@ -353,24 +357,24 @@
"save_btn": "සුරකින්න",
"client_add": "අනුග්‍රාහකයක් එකතු කරන්න",
"client_new": "නව අනුග්‍රාහකය",
"client_edit": "අනුග්‍රාහකය සංස්කරණය කරන්න",
"client_edit": "අනුග්‍රාහකය සංස්කරණය",
"client_identifier": "හඳුන්වනය",
"ip_address": "අ.ජා. කෙ. (IP) ලිපිනය",
"form_enter_ip": "අ.ජා. කෙ. (IP) ඇතුල් කරන්න",
"form_enter_subnet_ip": "\"{{cidr}}\" අනුජාලයෙහි අ.ජා. කෙ. ලිපිනයක් යොදන්න.",
"form_enter_mac": "මා.ප්‍ර.පා. (MAC) ඇතුල් කරන්න",
"ip_address": "අ.ජා.කෙ. ලිපිනය",
"form_enter_ip": "අ.ජා.කෙ. (IP) ඇතුල් කරන්න",
"form_enter_subnet_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_deleted": "\"{{key}}\" අනුග්‍රාහකය සාර්ථකව ඉවත් කෙරිණි",
"client_added": "\"{{key}}\" අනුග්‍රාහකය සාර්ථකව එකතු කෙරිණි",
"client_updated": "\"{{key}}\" අනුග්‍රාහකය සාර්ථකව යාවත්කාල කෙරිණි",
"clients_not_found": "අනුග්‍රාහක හමු නොවිණි",
"client_confirm_delete": "\"{{key}}\" අනුග්‍රාහකය ඉවත් කිරීමට අවශ්‍ය බව ඔබට විශ්වාසද?",
"list_confirm_delete": "මෙම ලැයිස්තුව ඉවත් කිරීමට අවශ්‍ය බව ඔබට විශ්වාස ද?",
"auto_clients_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කරන අනුග්‍රාහකයන්‌ගේ දත්ත, නමුත් වින්‍යාසය තුළ ගබඩා කර නොමැති",
"auto_clients_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කරන අනුග්‍රාහක දත්ත, නමුත් වින්‍යාසය තුළ ගබඩා කර නැති",
"access_title": "ප්‍රවේශවීමට සැකසුම්",
"access_desc": "මෙහිදී ඔබට ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය සඳහා ප්‍රවේශ වී‌‌‌‌මේ නීති වින්‍යාසගත කළ හැකිය.",
"access_allowed_title": "ඉඩ ලත් අනුග්‍රාහකයින්",
@@ -379,42 +383,42 @@
"access_disallowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්‍යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් ඉල්ලීම් අත්හරිනු ඇත.",
"access_blocked_title": "නොඉඩ ලත් වසම්",
"access_settings_saved": "ප්‍රවේශ වීමේ සැකසුම් සාර්ථකව සුරකින ලදි",
"updates_checked": "යාවත්කාලීන කිරීම් සාර්ථකව පරික්ෂා කර ඇත",
"updates_checked": "යාවත්කාල සාර්ථකව පරික්ෂා කෙරිණි",
"updates_version_equal": "ඇඩ්ගාර්ඩ් හෝම් යාවත්කාලීනයි",
"check_updates_now": "යාවත්කාල කිරීම සඳහා දැන් පරීක්ෂා කරන්න",
"check_updates_now": "දැන් යාවත්කාල පරීක්ෂා කරන්න",
"dns_privacy": "ව.නා.ප. රහස්‍යතා",
"setup_dns_privacy_3": "<0>මෙහි ඔබට භාවිතා කළ හැකි මෘදුකාංග ලැයිස්තුවක් ඇත.</0>",
"setup_dns_privacy_other_title": "වෙනත් ක්‍රියාවට නැංවූ දෑ",
"setup_dns_privacy_other_2": "<0>ඩීඑන්එස්ප්‍රොක්සි</0> දන්නා සියලුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහාය දක්වයි.",
"setup_dns_privacy_other_2": "<0>ඩීඑන්එස්ප්‍රොක්සි</0> දන්නා සියලුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහාය දක්වයි.",
"setup_dns_privacy_other_3": "<1>DNS-over-HTTPS</1> සඳහා <0>dnscrypt-පෙරකලාසිය</0> සහාය දක්වයි.",
"setup_dns_privacy_other_4": "<1>DNS-over-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> කිරීමට අවශ්‍ය වේ.",
"rewrite_added": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම සාර්ථකව එකතු කරන ලදි",
"setup_dns_notice": "ඔබට <1>DNS-over-HTTPS</1> හෝ <1>DNS-over-TLS</1> භාවිතයට ඇඩ්ගාර්ඩ් හෝම් සැකසුම් තුළ <0>සංකේතනය වින්‍යාසගත</0> කිරීමට ඇවැසිය.",
"rewrite_added": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම සාර්ථකව එකතු කෙරිණි",
"rewrite_add": "ව.නා.ප. නැවත ලිවීමක් එකතු කරන්න",
"rewrite_not_found": "ව.නා.ප. නැවත ලිවීම් හමු නොවීය",
"rewrite_not_found": "ව.නා.ප. නැවත ලිවීම් හමු නොවිණි",
"rewrite_confirm_delete": "\"{{key}}\" සඳහා ව.නා.ප. නැවත ලිවීම ඉවත් කිරීමට අවශ්‍ය බව ඔබට විශ්වාසද?",
"rewrite_desc": "ිශේෂිත වසම් නාමයක් සඳහා අභිරුචි ව.නා.ප. ප්‍රතිචාර පහසුවෙන් වින්‍යාසගත කිරීමට ඉඩ දෙයි.",
"rewrite_desc": "ිශ්චිත වසම් නාමයක් සඳහා අභිරුචි ව.නා.ප. ප්‍රතිචාර පහසුවෙන් වින්‍යාසගත කිරීමට ඉඩ දෙයි.",
"rewrite_applied": "නැවත ලිවීමේ නීතිය යොදා ඇත",
"rewrite_hosts_applied": "ධාරක ගොනු නීතිය මගින් නැවත ලියා ඇත",
"dns_rewrites": "ව.නා.ප. නැවත ලිවීම්",
"form_answer": "අ.ජා. කෙ. (IP) ලිපිනය ‌හෝ වසම ඇතුල් කරන්න ",
"form_answer": "අ.ජා.කෙ. (IP) ලිපිනය ‌හෝ වසම ඇතුල් කරන්න ",
"form_error_domain_format": "වලංගු නොවන වසම් ආකෘතියකි",
"form_error_answer_format": "වලංගු නොවන පිළිතුරු ආකෘතියකි",
"form_error_answer_format": "වලංගු නොවන උත්තර ආකෘතියකි",
"configure": "වින්‍යාසගත කරන්න",
"main_settings": "ප්‍රධාන සැකසුම්",
"block_services": "ිශේෂිත සේවාවන් අවහිර කරන්න",
"blocked_services": "අවහිර කළ සේවාවන්",
"blocked_services_desc": "ජනප්‍රිය අඩවි සහ සේවාවන් ඉක්මනින් අවහිර කිරීමට ඉඩ දෙයි.",
"blocked_services_saved": "අවහිර කළ සේවාවන් සාර්ථකව සුරකින ලදි",
"blocked_services_global": "ගෝලීය අවහිර කළ සේවාවන් භාවිතා කරන්න",
"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_path": "සහතික ගොනු‌ව‌ මාර්ගය සකසන්න",
"encryption_certificates_source_content": "සහතිකවල අන්තර්ගත අලවන්න",
"encryption_key_source_path": "පුද්ගලික යතුරක ගොනුවක් සකසන්න",
"encryption_key_source_content": "පුද්ගලික යතු‌රෙහි අන්තර්ගත අලවන්න",
@@ -422,20 +426,21 @@
"config_successfully_saved": "වින්‍යාසය සාර්ථකව සුරකින ලදි",
"interval_6_hour": "පැය 6",
"interval_24_hour": "පැය 24",
"interval_days": "{{count}} දිනය",
"interval_days_plural": "දින {{count}}",
"interval_days": "දවස් {{count}}",
"interval_days_plural": "දවස් {{count}}",
"domain": "වසම",
"answer": "පිළිතුර",
"filter_added_successfully": "පෙරහන සාර්ථකව එකතු කරන ලදි",
"filter_removed_successfully": "ලැයිස්තුව සාර්ථකව ඉවත් කරන ලදි",
"filter_updated": "ලැයිස්තුව සාර්ථකව යාවත්කාලීන කර ඇත",
"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_cleared": "සංඛ්‍යාලේඛන සාර්ථකව ඉවත් කෙරිණි",
"statistics_enable": "සංඛ්‍යාලේඛන සබල කරන්න",
"interval_hours": "පැය {{count}}",
"interval_hours_plural": "පැය {{count}}",
"filters_configuration": "පෙරහන් වින්‍යාසය",
@@ -443,7 +448,7 @@
"filters_interval": "පෙරහන් යාවත්කාල කාල පරතරය",
"disabled": "අබල කර ඇත",
"username_label": "පරිශීලක නාමය",
"username_placeholder": "පරිශීලක නාමය ඇතුල් කරන්න",
"username_placeholder": "පරිශීලක නාමය යොදන්න",
"password_label": "මුරපදය",
"password_placeholder": "මුරපදය ඇතුල් කරන්න",
"sign_in": "පුරන්න",
@@ -454,89 +459,91 @@
"orgname": "සංවිධානයේ නම",
"netname": "ජාල‌යේ නම",
"network": "ජාලය",
"descr": "විස්තරය",
"descr": "විස්තරය",
"whois": "Whois",
"filtering_rules_learn_more": "ඔබගේ ම ධාරක ලැයිස්තු සෑදීම පිළිබඳව <0>තව දැනගන්න</0>.",
"blocked_by_response": "ප්‍රතිචාරය අන්. නාමයක් (CNAME) හෝ අ.ජා. කෙ. මගින් අවහිර කර ඇත",
"blocked_by_cname_or_ip": "අන්. නාමයක් (CNAME) හෝ අ.ජා. කෙ. මගින් අවහිර කර ඇත",
"try_again": "නැවත උත්සහා කරන්න",
"blocked_by_response": "ප්‍රතිචාරය අන්. නාමයක් (CNAME) හෝ අ.ජා.කෙ. මගින් අවහිර කර ඇත",
"blocked_by_cname_or_ip": "අන්. නාමයක් (CNAME) හෝ අ.ජා.කෙ. මගින් අවහිර කර ඇත",
"try_again": "යළි උත්සාහය",
"example_rewrite_domain": "මෙම වසම් නාමය සඳහා පමණක් ප්‍රතිචාර නැවත ලියන්න.",
"example_rewrite_wildcard": "<0>example.org</0> සහ එහි සියුම උප වසම් සඳහා ප්‍රතිචාර නැවත ලියයි.",
"rewrite_ip_address": "අ.ජා. කෙ. ලිපිනය: මෙම අ.ජා. කෙටුම්පත A හෝ AAAA ප්‍රතිචාරයකට භාවිතා කරන්න",
"rewrite_domain_name": "වසම් නාමය: අන්. නා. (CNAME) වාර්තාවක් එක් කරන්න",
"disable_ipv6": "IPv6 ලිපින විසඳීම අබල කරන්න",
"disable_ipv6_desc": "අ.ජා.කෙ. අනු. 6 ලිපින (AAAA වර්ගය) සඳහා වන සියුම ව.නා.ප. විමසුම් අතහැර දමනු ලැබේ.",
"example_rewrite_wildcard": "<0>උදාහරණය.ලංකා</0> සහ එහි සියුම උප වසම් සඳහා ප්‍රතිචාර නැවත ලියයි.",
"rewrite_ip_address": "අ.ජා.කෙ. ලිපිනය: මෙම අ.ජා.කෙ. A හෝ AAAA ප්‍රතිචාරයකට න්න",
"rewrite_domain_name": "වසම් නාමය: අන්. නා (CNAME) වාර්තාවක් එක්කරන්න",
"disable_ipv6": "අයිපීවී6 ලිපින විසඳීම අබල කරන්න",
"disable_ipv6_desc": "අ.ජා.කෙ. අනු.6 ලිපින (AAAA වර්ගය) සඳහා වන සියුම ව.නා.ප. විමසුම් අතහැර දමයි.",
"fastest_addr": "වේගවත්ම අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනය",
"fastest_addr_desc": "සියුම ව.නා.ප. සේවාදායකයන්ගෙන් විමසා සියු ප්‍රතිචාර අතරින් වේගවත්ම අ.ජා. කෙ. ලිපිනය ලබා දෙයි. සියුම ව.නා.ප. සේවාදායකයන්ගේ ප්‍රතිචාර සඳහා ඇඩ්ගාර්ඩ් හෝම් රැඳී සිටිය යුතු බැවින් මෙය ව.නා.ප. විමසුම් මන්දගාමී කරන නමුත් සමස්ත සම්බන්ධතාවය වැඩි දියුණු කරයි.",
"autofix_warning_text": "ඔබ \"නිරාකරණය කරන්න\" බොත්තම එබුවහොත්, ඔබගේ පද්ධතිය ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය භාවිතා කිරීමට වින්‍යාසගත කනු ඇත.",
"autofix_warning_result": "ප්‍රතිඵලයක් ලෙස ඔබගේ පද්ධතියෙන් ලැබෙන සියුම ව.නා.ප. ඉල්ලීම් මූලිකවම ඇඩ්ගාර්ඩ් හෝම් විසින් සකසනු ඇත.",
"fastest_addr_desc": "සියුම ව.නා.ප. සේවාදායක වලින් විමසා සියු ප්‍රතිචාර අතරින් වේගවත්ම අ.ජා.කෙ. ලිපිනය ලබා දෙයි. සියුම ව.නා.ප. ප්‍රතිචාර සඳහා ඇඩ්ගාර්ඩ් හෝම් රැඳී සිටිය යුතු බැවින් මෙය ව.නා.ප. විමසුම් මන්දගාමී කරන නමුත් සමස්ත සම්බන්ධතාවය වැඩි දියුණු කරයි.",
"autofix_warning_text": "ඔබ \"නිරාකරණය\" යන්න එබුවහොත්, ඔබගේ පද්ධතිය ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය භාවිතට වින්‍යාසගත කෙරෙනු ඇත.",
"autofix_warning_result": "ප්‍රතිඵලයක් ලෙස ඔබගේ පද්ධතියෙන් ලැබෙන සියුම ව.නා.ප. ඉල්ලීම් මූලිකවම ඇඩ්ගාර්ඩ් හෝම් විසින් සකසනු ඇත.",
"tags_title": "හැඳුනුම් සංකේත",
"tags_desc": "අනුග්‍රාහකයට අනුරූප වන හැඳුනුම් සංකේත ඔබට තෝරා ගත හැකිය. පෙරහන් නීති වලට හැඳුනුම් සංකේත ඇතුළත් කළ හැකි අතර ඒවා වඩාත් නිවැරදිව යෙදීමට ඔබට ඉඩ සලසයි. <0>තව දැන ගන්න</0>",
"form_select_tags": "අනුග්‍රාහක හැඳුනුම් සංකේත",
"check_title": "පෙරීම පරීක්ෂා කරන්න",
"check_desc": "ධාරක නාමය පෙරහන් කර ඇත්දැයි පරීක්ෂා කරන්න",
"check": "පරීක්ෂා කරන්න",
"check_title": "පෙරීම පරීක්ෂා කරන්න",
"check_desc": "ධාරක නාමය පෙරහන් වේ දැයි පරීක්ෂා කරන්න",
"check": "පරීක්ෂා",
"form_enter_host": "ධාරක නාමයක් ඇතුල් කරන්න",
"filtered_custom_rules": "අභිරුචි පෙරීමේ නීති මගින් පෙරහන් කරන ලදි",
"choose_from_list": "ලැයිස්තුවෙන් තෝරන්න",
"add_custom_list": "අභිරුචි ලැයිස්තුවක් එකතු කරන්න",
"add_custom_list": "අභිරුචි ලැයිස්තුවක් එකකරන්න",
"host_whitelisted": "ධාරකයට ඉඩ දී ඇත",
"check_ip": "අ.ජා. කෙ. (IP) ලිපින: {{ip}}",
"check_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}}\" සාර්ථකව අනවහිර කරන ලදි",
"check_not_found": "ඔබගේ පෙරහන් ලැයිස්තු තුළ නැත",
"client_confirm_block": "{{ip}} අනුග්‍රාහකය අවහිර කිරීමට ඇවැසි බව ඔබට විශ්වාසද?",
"client_confirm_unblock": "{{ip}} අනුග්‍රාහකය අනවහිර කිරීමට ඇවැසි බව ඔබට විශ්වාසද?",
"client_blocked": "අනුග්‍රාහකය \"{{ip}}\" සාර්ථකව අවහිර කෙරිණි",
"client_unblocked": "අනුග්‍රාහකය \"{{ip}}\" සාර්ථකව අනවහිර කෙරිණි",
"static_ip": "ස්ථිතික අ.ජා. කෙ. ලිපිනය",
"static_ip_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු සේවාදායකයක් බැවින් එය නිසි ලෙස ක්‍රියා කිරීමට ස්ථිතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනයක් අවශ්‍ය වේ. එසේ නොමැතිනම්, යම් අවස්ථාවක දී ඔබගේ මාර්ගකාරකය මෙම උපාංගයට වෙනත් අ.ජා. කෙ. ලිපිනයක් ලබා දිය හැකිය.",
"set_static_ip": "ස්ථිතික අ.ජා. කෙ. (IP) ලිපිනයක් සකසන්න",
"static_ip_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු සේවාදායකයක් බැවින් එය නිසි ලෙස ක්‍රියා කිරීමට ස්ථිතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනයක් ඇවැසිය. එසේ නැතිනම්, යම් අවස්ථාවක දී ඔබගේ මාර්ගකාරකය මෙම උපාංගයට වෙනත් අ.ජා. කෙ. ලිපිනයක් ලබා දිය හැකිය.",
"set_static_ip": "ස්ථිතික අ.ජා.කෙ. (IP) ලිපිනයක් සකසන්න",
"install_static_ok": "සුභ තොරතුරක්! ස්ථිතික අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනය දැනටමත් වින්‍යාසගත කර ඇත",
"install_static_error": "මෙම ජාල අතුරුමුහුණත සඳහා ඇඩ්ගාර්ඩ් හෝම් හට එය ස්වයංක්‍රීයව වින්‍යාසගත ක නොහැක. කරුණාකර මෙය අතින් කරන්නේ කෙසේද යන්න පිළිබඳ උපදෙස් සොයා ගන්න.",
"install_static_configure": "ගතික අ.ජා. කෙ. (IP) ලිපිනයක් භාවිතා කරන බව ඇඩ්ගාර්ඩ් හෝම් හඳුනාගෙන ඇත - <0>{{ip}}</0>. එය ඔබගේ ස්ථිතික ලිපිනය ලෙස භාවිතා කිරීමට අවශ්‍යද?",
"confirm_static_ip": "ඇඩ්ගාර්ඩ් හෝම් ඔබේ ස්ථිතික අ.ජා. කෙ. (IP) ලිපිනය ලෙස {{ip}} වින්‍යාසගත කරනු ඇත. ඔබට ඉදිරියට යාමට අවශ්‍යද?",
"list_updated": "{{count}} ලැයිස්තුව යාවත්කාලීන කරන ලදි",
"list_updated_plural": "ලැයිස්තු {{count}} ක් යාවත්කාලීන කරන ලදි",
"all_queries": "සියුම විමසුම්",
"install_static_error": "මෙම ජාල අතුරුමුහුණත සඳහා ඇඩ්ගාර්ඩ් හෝම් හට එය ස්වයංක්‍රීයව වින්‍යාසගත කිරීමට නොහැකිය. මෙය අතින් කරන්නේ කෙසේද යන්න පිළිබඳ උපදෙස් සොයා ගන්න.",
"install_static_configure": "ගතික අ.ජා.කෙ. (IP) ලිපිනයක් භාවිතා කරන බව ඇඩ්ගාර්ඩ් හෝම් හඳුනාගෙන ඇත - <0>{{ip}}</0>. එය ඔබගේ ස්ථිතික ලිපිනය ලෙස භාවිතා කිරීමට අවශ්‍යද?",
"confirm_static_ip": "ඇඩ්ගාර්ඩ් හෝම් ඔබේ ස්ථිතික අ.ජා.කෙ. (IP) ලිපිනය ලෙස {{ip}} වින්‍යාසගත කරනු ඇත. ඔබට ඉදිරියට යාමට අවශ්‍යද?",
"list_updated": "ලැයිස්තු {{count}} ක් යාවත්කාල කෙරිණි",
"list_updated_plural": "ලැයිස්තු {{count}} ක් යාවත්කාල කෙරිණි",
"all_queries": "සියුම විමසුම්",
"show_blocked_responses": "අවහිර කර ඇත",
"show_whitelisted_responses": "ඉඩ දී ඇත",
"show_processed_responses": "සකසා ඇත",
"blocked_safebrowsing": "ආරක්ෂිත සෙවීම මගින් අවහිර කරන ලද",
"blocked_adult_websites": "අවහිර කළ වැඩිහිටි වියමන අඩවි",
"blocked_safebrowsing": "ආරක්ෂිත පිරික්සුම මගින් අවහිර ක",
"blocked_adult_websites": "දෙමාපිය පාලනය මගින් අවහිර කළ",
"blocked_threats": "අවහිර කළ තර්ජන",
"allowed": "ඉඩ දී ඇත",
"filtered": "පෙරහන් කරන ලද",
"rewritten": "නැවත ලියන ලද",
"safe_search": "ආරක්ෂිත සෙවීම",
"safe_search": "ආරක්ෂිත සෙවීම",
"blocklist": "අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තුව",
"milliseconds_abbreviation": "මිලි තත්.",
"cache_size": "නිහිතයෙහි ප්‍රමාණය",
"cache_size_desc": "ව.නා.ප. නිහිතයෙහි ප්‍රමාණය (බයිට වලින්)",
"cache_ttl_min_override": "අවම පව. කා. අභිබවන්න",
"cache_ttl_max_override": "උපරිම පව. කා. අභිබවන්න",
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්‍රමාණය ඇතුල් කරන්න (බයිට)",
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්‍රමාණය යොදන්න (බයිට)",
"enter_cache_ttl_min_override": "අවම පව. කා. (TTL) ඇතුල් කරන්න",
"enter_cache_ttl_max_override": "උපරිම පව. කා. (TTL) ඇතුල් කරන්න",
"cache_ttl_max_override_desc": "ව.නා.ප. නිහිතයෙහි ඇති ඇතුළත් කිරීම් සඳහා ඉතා වැඩි පවත්නා කාලයක අගයක් (තත්පර) සකසන්න",
"cache_ttl_max_override_desc": "ව.නා.ප. නිහිතයෙහි නිවේශිත සඳහා ඉතා වැඩි පවත්නා කාලයක අගයක් (තත්.) සකසන්න",
"ttl_cache_validation": "නිහිතයෙහි අවම පව. කා. (TTL) අගය උපරිම අගයට වඩා අඩු හෝ සමාන විය යුතුය",
"cache_optimistic_desc": "නිවේශිත කල් ඉකුත් වූ විට පවා ඇඩ්ගාර්ඩ් හෝම් ට නිහිතයෙන් ප්‍රතිචාර දැක්වීමට සලස්වයි එමෙන්ම ඒවා නැවත නැවුම් කිරීමට ද උත්සාහ කරයි.",
"filter_category_general": "පොදු",
"filter_category_security": "ආරක්ෂණ",
"filter_category_regional": "ප්‍රාදේශ්‍රීය",
"filter_category_security": "ආරක්ෂණ",
"filter_category_regional": "ප්‍රාදේශීය",
"filter_category_other": "වෙනත්",
"filter_category_general_desc": "බොහෝ උපාංගවල ලුහුබැඳීම් සහ දැන්වීම් අවහිර කරන ලැයිස්තු",
"filter_category_security_desc": "ද්වේෂසහගත, තතුබෑම් සහ වංචනික වසම් අවහිර කිරීමට නිර්මාණය කළ ලැයිස්තු",
"filter_category_regional_desc": "ප්‍රාදේශ්‍රීය දැන්වීම් සහ ලුහුබැඳීමේ සේවාදායකයන් කෙරෙහි අවධානය යොමු කරන ලැයිස්තු",
"filter_category_regional_desc": "ප්‍රාදේශීය දැන්වීම් සහ ලුහුබැඳීමේ සේවාදායක කෙරෙහි අවධානය යොමු කරන ලැයිස්තු",
"filter_category_other_desc": "වෙනත් අවහිර කිරී‌‌‌‌‌මේ ලැයිස්තු",
"setup_config_to_enable_dhcp_server": "ග.ධා.වි.කෙ. සේවාදායකය සක්‍රීය කිරීම සඳහා වින්‍යාසය පිහිටුවන්න",
"setup_config_to_enable_dhcp_server": "ග.ධා.වි.කෙ. සේවාදායකය සබල කිරීම වින්‍යාසය පිහිටුවන්න",
"original_response": "මුල් ප්‍රතිචාරය",
"click_to_view_queries": "විමසුම් බැලීමට ඔබන්න",
"port_53_faq_link": "53 වන කෙවෙනිය බොහෝ විට \"DNSStubListener\" හෝ \"systemd-resolved\" සේවාවන් භාවිතයට ගනු ලැබේ. කරුණාකර මෙය විසඳන්නේ කෙසේද යන්න පිළිබඳ <0>මෙම උපදෙස්</0> කියවන්න.",
"adg_will_drop_dns_queries": "ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම අනුග්‍රාහකයේ සියුම ව.නා.ප. විමසුම් අතහැර දමනු ඇත.",
"client_not_in_allowed_clients": "\"ඉඩ දුන් අනුග්‍රාහකයින්\" ලැයිස්තුවේ නැති නිසා අනුග්‍රාහකයට ඉඩ දී නැත.",
"experimental": "පරීක්ෂණාත්මක",
"use_saved_key": "පෙර සුරැකි යතුර භාවිතා කරන්න"
"port_53_faq_link": "53 වන කෙවෙනිය බොහෝ විට \"DNSStubListener\" හෝ \"systemd-resolved\" සේවා භාවිතයට ගනු ලැබේ. කරුණාකර මෙය විසඳන්නේ කෙසේද යන්න පිළිබඳ <0>මෙම උපදෙස්</0> කියවන්න.",
"adg_will_drop_dns_queries": "ඇඩ්ගාර්ඩ් හෝම් මෙම අනුග්‍රාහකයේ සියුම ව.නා.ප. විමසුම් අතහැර දමනු ඇත.",
"experimental": "පරීක්‍ෂාත්මක",
"use_saved_key": "පෙර සුරැකි යතුර භාවිතා කරන්න",
"parental_control": "දෙමාපිය පාලනය",
"safe_browsing": "ආරක්‍ෂිත පිරික්සුම",
"served_from_cache": "{{value}} <i>(නිහිතයෙන් ගැනිණි)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Neplatná IPv6 adresa",
"form_error_ip_format": "Neplatná IP adresa",
"form_error_mac_format": "Neplatná MAC adresa",
"form_error_client_id_format": "Neplatné ID klienta",
"form_error_client_id_format": "ID klienta musí obsahovať iba čísla, malé písmená a spojovníky",
"form_error_server_name": "Neplatné meno servera",
"form_error_subnet": "Podsieť \"{{cidr}}\" neobsahuje IP adresu \"{{ip}}\"",
"form_error_positive": "Musí byť väčšie ako 0",
@@ -163,8 +163,8 @@
"apply_btn": "Použiť",
"disabled_filtering_toast": "Vypnutá filtrácia",
"enabled_filtering_toast": "Zapnutá filtrácia",
"disabled_safe_browsing_toast": "Vypnuté Bezpečné prehliadanie",
"enabled_safe_browsing_toast": "Zapnuté Bezpečné prehliadanie",
"disabled_safe_browsing_toast": "Bezpečné prehliadanie vypnuté",
"enabled_safe_browsing_toast": "Bezpečné prehliadanie zapnuté",
"disabled_parental_toast": "Vypnutá Rodičovská kontrola",
"enabled_parental_toast": "Zapnutá Rodičovská kontrola",
"disabled_safe_search_toast": "Vypnuté bezpečné vyhľadávanie",
@@ -403,6 +403,7 @@
"dns_providers": "Tu je <0>zoznam známych poskytovateľov DNS</0>, z ktorého si vyberiete.",
"update_now": "Aktualizovať teraz",
"update_failed": "Automatická aktualizácia zlyhala. Prosím <a>sledujte postup</a> pre manuálnu aktualizáciu.",
"manual_update": "Pre manuálnu aktualizáciu prosím <a>sledujte tento postup</a>.",
"processing_update": "Čakajte prosím, AdGuard Home sa aktualizuje",
"clients_title": "Klienti",
"clients_desc": "Konfigurácia zariadení pripojených k AdGuard Home",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Neveljaven naslov IPv6",
"form_error_ip_format": "Neveljaven naslov IP",
"form_error_mac_format": "Neveljaven naslov MAC",
"form_error_client_id_format": "Neveljaven ID odjemalca",
"form_error_client_id_format": "ID odjemalca mora vsebovati samo številke, male črke in vezaje",
"form_error_server_name": "Neveljavno ime strežnika",
"form_error_subnet": "Podomrežje \"{{cidr}}\" ne vsebuje naslova IP \"{{ip}}\"",
"form_error_positive": "Mora biti večja od 0",
@@ -403,6 +403,7 @@
"dns_providers": "Tukaj je <0>seznam znanih ponudnikov DNS</0>, med katerimi lahko izbirate.",
"update_now": "Posodobi zdaj",
"update_failed": "Samodejna posodobitev ni uspela. Prosimo <a>sledite korakom</a>, da ročno posodobite.",
"manual_update": "Za ročno posodobitev <a>sledite tem korakom</a>.",
"processing_update": "Prosimo, počakajte. AdGuard Home se posodablja!",
"clients_title": "Odjemalci",
"clients_desc": "Konfigurirajte naprave, ki so povezane z AdGuard Home",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "Na seznamu dovoljenih",
"show_processed_responses": "Obdelana",
"blocked_safebrowsing": "Onemogočeno z 'Varnim brskanjem'",
"blocked_adult_websites": "Onemogočeno spletnih strani za odrasle",
"blocked_adult_websites": "Onemogočeno s Starševskim nadzorom",
"blocked_threats": "Onemogočeno groženj",
"allowed": "Dovoljeno",
"filtered": "Filtrirano",

View File

@@ -22,7 +22,7 @@
"form_error_required": "Obavezno polje",
"form_error_ip4_format": "Nevažeći IPv4 format",
"form_error_ip6_format": "Nevažeći IPv6 format",
"form_error_ip_format": "Nevažeći IPv4 oblik",
"form_error_ip_format": "Pogrešna IP adresa",
"form_error_mac_format": "Nevažeći MAC format",
"form_error_client_id_format": "Nevažeći format klijenta",
"form_error_positive": "Mora biti veće od 0",
@@ -169,7 +169,6 @@
"example_upstream_sdns": "možete koristiti <0>DNS brojeve</0> za <1>DNSCrypt</1> ili <2>DNS-over-HTTPS</2>",
"example_upstream_tcp": "uobičajeni DNS (preko TCP)",
"all_lists_up_to_date_toast": "Sve liste su već ažurirane",
"updated_upstream_dns_toast": "Ažurirani upstream DNS serveri",
"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",
"unblock": "Odblokiraj",
@@ -520,7 +519,7 @@
"show_whitelisted_responses": "Na beloj listi",
"show_processed_responses": "Obrađeno",
"blocked_safebrowsing": "Blokiralo bezbedno pregledanje",
"blocked_adult_websites": "Blokiraj sajtove za odrasle",
"blocked_adult_websites": "Blokirala roditeljska kontrola",
"blocked_threats": "Blokiranih pretnji",
"allowed": "Dozvoljeno",
"filtered": "Filtrirano",

View File

@@ -1,24 +1,58 @@
{
"client_settings": "Klientinställningar",
"example_upstream_reserved": "Du kan specificera DNS-uppström <0>för en specifik domän</0>",
"example_upstream_comment": "Du kan ange en kommentar",
"upstream_parallel": "Använd parallella förfrågningar för att snabba upp dessa genom att fråga alla uppströmsservrar samtidigt.",
"parallel_requests": "Parallella förfrågningar",
"load_balancing": "Lastbalansering",
"load_balancing_desc": "Fråga en uppströmsserver åt gången. AdGuard Home använder sin viktade slumpmässiga algoritm för att välja server så att den snabbaste servern används oftare.",
"bootstrap_dns": "Bootstrap-DNS-servrar",
"bootstrap_dns_desc": "Bootstrap-DNS-servrar används för att slå upp DoH/DoT-resolvrarnas IP-adresser som du specificerat som uppström.",
"local_ptr_title": "Privata omvända DNS-servrar",
"local_ptr_desc": "DNS servrarna som AdGuard Home använder för lokala PTR frågor. Dessa servrar används för att lösa värdnamnen på klienter med privata IP-adresser, till exempel \"192.168.12.34\", genom omvänd DNS. Om inga servrar angetts använder AdGuard Home adresserna till standard DNS servrar för ditt operativsystem förutom adresserna till AdGuard Home själv.",
"local_ptr_default_resolver": "Som standard använder AdGuard Home följande omvända DNS upplösare: {{ip}}.",
"local_ptr_no_default_resolver": "AdGuard Home kunde inte fastställa lämpliga privata omvända DNS upplösare för detta system.",
"local_ptr_placeholder": "Ange en serveradress per rad",
"resolve_clients_title": "Aktivera omvänd upplösning av klienters IP-adresser",
"resolve_clients_desc": "Lös upp klienternas värdnamn med omvänt uppslag av klienternas IP-adresser genom att skicka PTR-frågor till motsvarande upplösare (privata DNS-servrar för lokala klienter, uppströmsservrar för klienter med offentliga IP-adresser).",
"use_private_ptr_resolvers_title": "Använd privata omvända DNS upplösare",
"use_private_ptr_resolvers_desc": "Utför omvända DNS-sökningar för lokalt betjänade adresser med dessa uppströmsservrar. Om det är inaktiverat svarar AdGuard Home med NXDOMAIN på alla sådana PTR-förfrågningar förutom klienter kända från DHCP, /etc/hosts, och så vidare.",
"check_dhcp_servers": "Letar efter DHCP-servrar",
"save_config": "Spara konfiguration",
"enabled_dhcp": "DHCP-server aktiverad",
"disabled_dhcp": "Dhcp-server avaktiverad",
"unavailable_dhcp": "DHCP är inte tillgängligt",
"unavailable_dhcp_desc": "AdGuard Home kan inte köra en DHCP-server på ditt operativsystem",
"dhcp_title": "DHCP-server (experimentell)",
"dhcp_description": "Om din router inte har inställningar för DHCP kan du använda AdGuards inbyggda server.",
"dhcp_enable": "Aktivera DHCP.-server",
"dhcp_disable": "Avaktivera DHCP-server",
"dhcp_not_found": "Det är säkert att aktivera den inbyggda DHCP-servern eftersom AdGuard Home inte hittade några aktiva DHCP-servrar i nätverket. Du bör dock kontrollera det igen manuellt eftersom den automatiska sökningenn efter DHCP-servrar inte ger 100 % garanti.",
"dhcp_found": "Några aktiva DHCP-servar upptäcktes. Det är inte säkert att aktivera inbyggda DHCP-servrar.",
"dhcp_leases": "DHCP-lease",
"dhcp_static_leases": "Statiska DHCP-leases",
"dhcp_leases_not_found": "Ingen DHCP-lease hittad",
"dhcp_config_saved": "DHCP-konfigurationen har sparats",
"dhcp_ipv4_settings": "DHCP IPv4 inställningar",
"dhcp_ipv6_settings": "DHCP IPv6 inställningar",
"form_error_required": "Obligatoriskt fält",
"form_error_ip4_format": "Ogiltig IPv4-adress",
"form_error_ip4_range_start_format": "Ogiltig IPv4-adress för starten av intervallet",
"form_error_ip4_range_end_format": "Ogiltig IPv4-adress för slutet av intervallet",
"form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen",
"form_error_ip6_format": "Ogiltig IPv6-adress",
"form_error_ip_format": "Ogiltig IP-adress",
"form_error_mac_format": "Ogiltig MAC-adress",
"form_error_client_id_format": "Ogiltigt klient-ID",
"form_error_server_name": "Ogiltigt servernamn",
"form_error_subnet": "Subnätet \"{{cidr}}\" innehåller inte IP-adressen \"{{ip}}\"",
"form_error_positive": "Måste vara större än noll",
"out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Måste vara lägre än starten på intervallet",
"greater_range_start_error": "Måste vara högre än starten på intervallet",
"greater_range_end_error": "Måste vara större än intervallets slut",
"subnet_error": "Adresser måste finnas i ett subnät",
"gateway_or_subnet_invalid": "Subnätmask ogiltig",
"dhcp_form_gateway_input": "Gateway-IP",
"dhcp_form_subnet_input": "Subnetmask",
"dhcp_form_range_title": "IP-adressgränser",
@@ -29,17 +63,30 @@
"dhcp_interface_select": "Välj DHCP-gränssnitt",
"dhcp_hardware_address": "Hårdvaruadress",
"dhcp_ip_addresses": "IP-adresser",
"ip": "IP",
"dhcp_table_hostname": "Värdnamn",
"dhcp_table_expires": "Utgår",
"dhcp_warning": "Om du vill använda den inbyggda DHCP servern ändå, se till att det inte finns några andra aktiva DHCP servrar. Annars kan den störa internetanslutningen för anslutna enheter!",
"dhcp_error": "Vi kunde inte avgöra om det finns en till DHCP-server på nätverket.",
"dhcp_static_ip_error": "För att kunna använda en DHCP-server måste det finnas en statisk IP-adress. AdGuard Home kunde inte avgöra om nätverksgränssnittet är konfigurerat med en statisk IP-adress. Ställ in en statisk IP-adress manuellt.",
"dhcp_dynamic_ip_found": "Din enhet använder en dynamisk IP-adress för gränssnittet <0>{{interfaceName}}</0>. För att kunna använda DHCP-servern behövs en statisk IP-adress. Din nuvarande IP-adress är <0>{{ipAddress}}</0>. AdGuard Home kommer automatiskt att göra denna IP-adress statisk om du trycker på knappen \"Aktivera DHCP\".",
"dhcp_lease_added": "Statisk lease \"{{key}}\" har lagts till",
"dhcp_lease_deleted": "Statisk lease \"{{key}}\" har raderats",
"dhcp_new_static_lease": "Ny statisk lease",
"dhcp_static_leases_not_found": "Inga statiska DHCP-leases hittade",
"dhcp_add_static_lease": "Lägg till statisk lease",
"dhcp_reset_leases": "Återställ alla leasingavtal",
"dhcp_reset_leases_confirm": "Är du säker på att du vill ta bort alla leasingavtal?",
"dhcp_reset_leases_success": "DHCP-leasing har återställts",
"dhcp_reset": "Är du säker på att du vill ta bort DHCP inställningarna?",
"country": "Land",
"city": "Stad",
"delete_confirm": "Är du säker på att du vill ta bort \"{{key}}\"?",
"form_enter_hostname": "Skriv in värdnamn",
"error_details": "Felinformation",
"response_details": "Svarsdetaljer",
"request_details": "Förfrågningsdetaljer",
"client_details": "Klient information",
"details": "Detaljer",
"back": "Tiilbaka",
"dashboard": "Kontrollpanel",
@@ -47,6 +94,8 @@
"filters": "Filter",
"filter": "Filter",
"query_log": "Förfrågningslogg",
"compact": "Komprimera",
"nothing_found": "Inget hittades",
"faq": "FAQ",
"version": "version",
"address": "Adress",
@@ -70,52 +119,88 @@
"for_last_24_hours": "under de senaste 24 timmarna",
"for_last_days": "för den senaste {{count}} dagen",
"for_last_days_plural": "för de senaste {{count}} dagarna",
"stats_disabled": "Statistiken har inaktiverats. Du kan aktivera det från <0>inställningssidan</0>.",
"stats_disabled_short": "Statistiken har inaktiverats",
"no_domains_found": "Inga domäner hittade",
"requests_count": "Förfrågningsantal",
"top_blocked_domains": "Flest blockerade domäner",
"top_clients": "Toppklienter",
"no_clients_found": "Inga klienter hittade",
"general_statistics": "Allmän statistik",
"number_of_dns_query_days": "Antalet DNS-förfrågningar som utfördes under senaste {{count}} dagen",
"number_of_dns_query_days_plural": "Ett antal DNS förfrågningar utfördes under de senaste {{count}} dagarna",
"number_of_dns_query_24_hours": "Antalet DNS-förfrågningar som utfördes under de senaste 24 timmarna",
"number_of_dns_query_blocked_24_hours": "Antalet DNS-förfrågningar som blockerades av annonsfilter och värdens blockeringsklistor",
"number_of_dns_query_blocked_24_hours_by_sec": "Antalet DNS-förfrågningar som blockerades av AdGuards modul för surfsäkerhet",
"number_of_dns_query_blocked_24_hours_adult": "Antalet vuxensajter som blockerats",
"enforced_save_search": "Aktivering av Säker surf",
"number_of_dns_query_to_safe_search": "Antalet DNS-förfrågningar mot sökmotorer där Säker surf tvingats",
"average_processing_time": "Genomsnittlig processtid",
"average_processing_time_hint": "Genomsnittlig processtid i millisekunder för DNS-förfrågning",
"block_domain_use_filters_and_hosts": "Blockera domäner med filter- och värdfiler",
"filters_block_toggle_hint": "Du kan ställa in egna blockerings regler i <a>Filterinställningar</a>.",
"use_adguard_browsing_sec": "Använd AdGuards webbservice för surfsäkerhet",
"use_adguard_browsing_sec_hint": "AdGuard Home kommer att kontrollera om en domän är svartlistad i webbservicens surfsäkerhet. Med en integritetsvänlig metod görs en API-lookup för att kontrollera : endast en kort prefix i domännamnet SHA256 hash skickas till servern.",
"use_adguard_browsing_sec_hint": "AdGuard Home kommer att kontrollera om en domän är blockerad av webbservicen surfsäkerhet. Med en integritetsvänlig metod görs en API-lookup för att kontrollera: endast ett kort prefix i domännamnet SHA256 hash skickas till servern.",
"use_adguard_parental": "Använda AdGuards webbservice för föräldrakontroll",
"use_adguard_parental_hint": "AdGuard Home kommer att kontrollera domäner för innehåll av vuxenmaterial . Samma integritetsvänliga metod för API-lookup som tillämpas i webbservicens surfsäkerhet används.",
"enforce_safe_search": "Tillämpa Säker surf",
"enforce_safe_search": "Använd säker webbsökning",
"enforce_save_search_hint": "AdGuard Home kommer tvinga säker surf på följande sökmotorer: Google, Youtube, Bing, DuckDuckGo, Yandex, Pixabay.",
"no_servers_specified": "Inga servrar angivna",
"general_settings": "Allmänna inställningar",
"dns_settings": "DNS-inställningar",
"dns_blocklists": "DNS blockeringslistor",
"dns_allowlists": "DNS frilistor",
"dns_blocklists_desc": "AdGuard Home kommer att blockera domäner som matchar blockeringslistorna.",
"dns_allowlists_desc": "Domäner från DNS frilistor kommer att tillåtas även om de finns i någon av blockeringslistorna.",
"custom_filtering_rules": "Egna filterregler",
"encryption_settings": "Krypteringsinställningar",
"dhcp_settings": "DHCP-inställningar",
"upstream_dns": "Upstream DNS-servrar",
"upstream_dns_help": "Ange en serveradress per rad. <a>Läs mer</a> om att konfigurera uppströms DNS-servrar.",
"upstream_dns_configured_in_file": "Konfigurerad i {{path}}",
"test_upstream_btn": "Testa uppströmmar",
"upstreams": "Uppströms",
"apply_btn": "Tillämpa",
"disabled_filtering_toast": "Filtrering bortkopplad",
"enabled_filtering_toast": "Filtrering inkopplad",
"disabled_safe_browsing_toast": "Säker surfning bortkopplat",
"enabled_safe_browsing_toast": "Säker surfning inkopplat",
"disabled_safe_browsing_toast": "Säker surfning inaktiverad",
"enabled_safe_browsing_toast": "Säker surfning aktiverat",
"disabled_parental_toast": "Föräldrakontroll bortkopplat",
"enabled_parental_toast": "Föräldrakontroll inkopplat",
"disabled_safe_search_toast": "Säker webbsökning bortkopplat",
"enabled_save_search_toast": "Säker webbsökning inkopplat",
"enabled_table_header": "Inkopplat",
"name_table_header": "Namn",
"list_url_table_header": "Lista URL",
"rules_count_table_header": "Regelantal",
"last_time_updated_table_header": "Uppdaterades senast",
"actions_table_header": "Åtgärder",
"request_table_header": "Förfrågning",
"edit_table_action": "Redigera",
"delete_table_action": "Radera",
"elapsed": "Förfluten tid",
"filters_and_hosts_hint": "AdGuard tillämpar grundläggande annonsblockeringsregler och värdfiltersyntaxer",
"no_blocklist_added": "Inga blocklistor har lagts till",
"no_whitelist_added": "Inga frilistor har lagts till",
"add_blocklist": "Lägg till blockeringslista",
"add_allowlist": "Lägg till frilista",
"cancel_btn": "Avbryt",
"enter_name_hint": "Skriv in namn",
"enter_url_or_path_hint": "Ange en URL eller en absolut sökväg till listan",
"check_updates_btn": "Sök efter uppdateringar",
"new_blocklist": "Ny blockeringslista",
"new_allowlist": "Ny frilista",
"edit_blocklist": "Redigera blockeringslista",
"edit_allowlist": "Redigera frilista",
"choose_blocklist": "Välj blockeringslistor",
"choose_allowlist": "Välj frilistor",
"enter_valid_blocklist": "Ange en giltig URL till blockeringslistan.",
"enter_valid_allowlist": "Ange en giltig URL till frilistan.",
"form_error_url_format": "Ogiltigt URL format",
"form_error_url_or_path_format": "Ogiltig URL eller absolut sökväg till listan",
"custom_filter_rules": "Egna filterregler",
"custom_filter_rules_hint": "Skriv en regel per rad. Du kan använda antingen annonsblockeringsregler eller värdfilssyntax.",
"system_host_files": "Systemfiler",
"examples_title": "Exempel",
"example_meaning_filter_block": "blockera åtkomst till domän example.org domain och alla dess subdomäner",
"example_meaning_filter_whitelist": "avblockera åtkomst till domän example.org domain och alla dess subdomäner",
@@ -127,18 +212,26 @@
"example_upstream_regular": "vanlig DNS (över UDP)",
"example_upstream_dot": "krypterat <0>DNS-over-TLS</0>",
"example_upstream_doh": "krypterat <0>DNS-over-HTTPS</0>",
"example_upstream_doq": "krypterat <0>DNS-over-QUIC</0>",
"example_upstream_sdns": "Du kan använda <0>DNS-stamps</0> för <1>DNSCrypt</1> eller <2>DNS-over-HTTPS</2>-resolvers",
"example_upstream_tcp": "vanlig DNS (över UDP)",
"updated_upstream_dns_toast": "Uppdaterade uppströms-dns-servrar",
"all_lists_up_to_date_toast": "Alla listor är redan uppdaterade",
"updated_upstream_dns_toast": "Sparade uppströms dns-servrar",
"dns_test_ok_toast": "Angivna DNS servrar fungerar korrekt",
"dns_test_not_ok_toast": "Server \"{{key}}\": kunde inte användas. Var snäll och kolla att du skrivit in rätt",
"unblock": "Avblockera",
"block": "Blockera",
"disallow_this_client": "Tillåt inte den här klienten",
"allow_this_client": "Tillåt den här klienten",
"block_for_this_client_only": "Blockera endast för denna klient",
"unblock_for_this_client_only": "Avblockera endast för denna klient",
"time_table_header": "Tid",
"date": "Datum",
"domain_name_table_header": "Domännamn",
"domain_or_client": "Domän eller klient",
"type_table_header": "Typ",
"response_table_header": "Svar",
"response_code": "Svarskod",
"client_table_header": "Klient",
"empty_response_status": "Tomt",
"show_all_filter_type": "Visa alla",
@@ -150,13 +243,14 @@
"loading_table_status": "Läser in...",
"page_table_footer_text": "Sida",
"rows_table_footer_text": "rader",
"updated_custom_filtering_toast": "Uppdaterade de egna filterreglerna",
"updated_custom_filtering_toast": "Anpassade filterregler sparade",
"rule_removed_from_custom_filtering_toast": "Regel borttagen från de egna filterreglerna: {{rule}}",
"rule_added_to_custom_filtering_toast": "Regel tillagd till de egna filterreglerna: {{rule}}",
"query_log_response_status": "Status: {{value}}",
"query_log_filtered": "Filtrerat av {{filter}}",
"query_log_confirm_clear": "Är du säker på att du vill rensa hela förfrågningsloggen?",
"query_log_cleared": "Förfrågningsloggen har rensats",
"query_log_updated": "Förfrågningsloggen har uppdaterats",
"query_log_clear": "Rensa förfrågningsloggar",
"query_log_retention": "Förfrågningsloggars retentionstid",
"query_log_enable": "Aktivera logg",
@@ -164,27 +258,63 @@
"query_log_disabled": "Förfrågningsloggen är avaktiverad och kan konfigureras i <0>inställningar</0>",
"query_log_strict_search": "Använd dubbla citattecken för strikt sökning",
"query_log_retention_confirm": "Är du säker på att du vill ändra förfrågningsloggars retentionstid? Om du minskar intervallet kommer viss data att gå förlorad",
"anonymize_client_ip": "Anonymisera klientens IP",
"anonymize_client_ip_desc": "Spara inte klientens fullständiga IP-adress i loggar och statistik",
"dns_config": "DNS server konfiguration",
"dns_cache_config": "DNS cache konfiguration",
"dns_cache_config_desc": "Här kan du konfigurera DNS cache",
"blocking_mode": "Blockeringsläge",
"default": "Standard",
"nxdomain": "NXDOMÄN",
"refused": "REFUSED",
"null_ip": "Null IP",
"custom_ip": "Eget IP",
"blocking_ipv4": "Blockera IPv4",
"blocking_ipv6": "Blockera IPv6",
"dnscrypt": "DNSCrypt",
"dns_over_https": "DNS-over-HTTPS",
"dns_over_tls": "DNS-over-TLS",
"dns_over_quic": "DNS-over-QUIC",
"client_id": "Klient ID",
"client_id_placeholder": "Ange klient ID",
"client_id_desc": "Olika klienter kan identifieras med ett speciellt klient ID. <a>Här</a> kan du lära dig mer om hur du identifierar klienter.",
"download_mobileconfig_doh": "Ladda ner .mobileconfig för DNS-over-HTTPS",
"download_mobileconfig_dot": "Ladda ner .mobileconfig för DNS-over-TLS",
"download_mobileconfig": "Ladda ner konfigurationsfil",
"plain_dns": "Vanlig DNS",
"form_enter_rate_limit": "Ange förfrågnings gräns",
"rate_limit": "Förfrågnings gräns",
"edns_enable": "Aktivera EDNS-klient subnät",
"edns_cs_desc": "Skicka klienternas subnät till DNS servrarna.",
"rate_limit_desc": "Antalet förfrågningar per sekund som tillåts per klient. Att sätta den till 0 innebär ingen gräns.",
"blocking_ipv4_desc": "IP adress som ska returneras för en blockerad A förfrågan",
"blocking_ipv6_desc": "IP adress som ska returneras för en blockerad AAAA förfrågan",
"blocking_mode_default": "Standard: Svara med noll IP-adress (0.0.0.0 för A; :: för AAAA) när det blockeras av regel i Adblock-stil; svara med IP-adressen som anges i regeln när den blockeras av regel i /etc/hosts-stil",
"blocking_mode_refused": "REFUSED: Svara med REFUSED kod",
"blocking_mode_nxdomain": "NXDOMAIN: Svara med NXDOMAIN kod",
"blocking_mode_null_ip": "Null IP: Svara med noll IP adress (0.0.0.0 för A; :: för AAAA)",
"blocking_mode_custom_ip": "Anpassad IP: Svara med en manuellt inställd IP adress",
"upstream_dns_client_desc": "Om detta fält är tomt kommer AdGuard Home att använda de servrar som konfigurerats i <0>DNS inställningarna</0>.",
"tracker_source": "Spårningskälla",
"source_label": "Källa",
"found_in_known_domain_db": "Hittad i domändatabas.",
"category_label": "Kategori",
"rule_label": "Regel(er)",
"list_label": "Lista",
"unknown_filter": "Okänt filter {{filterId}}",
"known_tracker": "Känd spårare",
"install_welcome_title": "Välkommen till AdGuard Home!",
"install_welcome_desc": "AdGuard Home är en DNS-server för nätverkstäckande annons- och spårningsblockering. Dess syfte är att de dig kontroll över hela nätverket och alla dina enheter, utan behov av att använda klientbaserade program.",
"install_settings_title": "Administratörens webbgränssnitt",
"install_settings_listen": "Övervakningsgränssnitt",
"install_settings_port": "Port",
"install_settings_interface_link": "Din administratörssida för AdGuard Home finns på följande adresser:",
"form_error_port": "Skriv in ett giltigt portnummer",
"install_settings_dns": "DNS-server",
"install_settings_dns_desc": "Du behöver ställa in dina enheter eller din router för att använda DNS-server på följande adresser.",
"install_settings_all_interfaces": "Alla gränssnitt",
"install_auth_title": "Autentisering",
"install_auth_desc": "Det rekommenderas starkt att ställa in lösenordsskydd till webbgränssnittets administrativa del i ditt AdGuard Home. Även om den endast är åtkomlig på ditt lokala nätverk rekommenderas det ändå att skydda det mot oönskad åtkomst.",
"install_auth_desc": "Lösenordsautentisering till ditt AdGuard Home administratörsgränssnitt måste konfigureras. Även om AdGuard Home bara är tillgängligt i ditt lokala nätverk är det fortfarande viktigt att skydda det från obegränsad åtkomst.",
"install_auth_username": "Användarnamn",
"install_auth_password": "Lösenord",
"install_auth_confirm": "Bekräfta lösenord",
@@ -194,18 +324,20 @@
"install_devices_title": "Ställ in dina enheter",
"install_devices_desc": "För att kunna använda AdGuard Home måste du ställa in dina enheter för att utnyttja den.",
"install_submit_title": "Grattis!",
"install_submit_desc": "Inställningsproceduren är klar och du kan börja använda AdGuard Home.",
"install_submit_desc": "Installationen är klar och du kan börja använda AdGuard Home.",
"install_devices_router": "Router",
"install_devices_router_desc": "Den här anpassningen kommer att automatiskt täcka in alla de enheter som är anslutna till din hemmarouter och du behöver därför inte konfigurera var och en individuellt.",
"install_devices_address": "AdGuard Home DNS-server täcker följande adresser",
"install_devices_router_list_1": "Öppna inställningarna för din router. Vanligtvis kan du komma åt den från din webbläsare via en URL, som http://192.168.0.1/ eller http://192.168.1.1/. Du kan bli ombedd att ange ett lösenord. Om du inte kommer ihåg det kan du ofta återställa lösenordet genom att trycka på en knapp på själva routern, men var medveten om att om denna procedur väljs kommer du förmodligen att förlora hela routerkonfigurationen. Om din router kräver en app för att konfigurera den, installera appen på din telefon eller dator och använd den för att komma åt routerns inställningar.",
"install_devices_router_list_2": "Leta upp DHCP/DNS-inställningarna. Titta efter DNS-tecken intill ett fält med två eller tre uppsättningar siffror, var och en uppdelade i grupper om fyra med en eller tre siffror.",
"install_devices_router_list_3": "Ange serveradressen till ditt AdGuard Home.",
"install_devices_router_list_4": "På vissa routertyper kan en anpassad DNS server inte konfigureras. I så fall kan det hjälpa att konfigurera AdGuard Home som en <0>DHCP server</0>. Annars bör du kontrollera routermanualen om hur du anpassar DNS servrar på din specifika routermodell.",
"install_devices_windows_list_1": "Öppna Kontrollpanelen via Start eller Windows Sök.",
"install_devices_windows_list_2": "Välj Nätverks och delningscenter, Nätverk och Internet.",
"install_devices_windows_list_3": "Leta upp Ändra nätverkskortsalternativ",
"install_devices_windows_list_3": "På vänster sida av skärmen hittar du \"Ändra adapterinställningar\" och klicka på den.",
"install_devices_windows_list_4": "Markera din aktiva anslutning. Högerklicka på den och välj Egenskaper.",
"install_devices_windows_list_5": "Markera Internet Protocol Version 4 (TCP/IP) och klicka på knappen Egenskaper.",
"install_devices_windows_list_6": "Markera Använd följande DNS-serveradresser och skriv in adresserna till ditt AdGuard Home.",
"install_devices_windows_list_5": "Hitta \"Internet Protocol Version 4 (TCP/IPv4)\" (eller, för IPv6, \"Internet Protocol Version 6 (TCP/IPv6)\") i listan, välj den och klicka sedan på Egenskaper igen.",
"install_devices_windows_list_6": "Välj \"Använd följande DNS-serveradresser\" och ange dina AdGuard Home-serveradresser.",
"install_devices_macos_list_1": "Klicka på Apple-ikonen och välj Systemalternativ.",
"install_devices_macos_list_2": "Klicka på Nätverk.",
"install_devices_macos_list_3": "Välj den första anslutningen i listan och klicka på Avancerat.",
@@ -214,7 +346,7 @@
"install_devices_android_list_2": "Tryck på Nätverk och Internet, Wi-Fi. Alla tillgängliga nätverk visas i en lista (det går inte all välja egen DNS på mobilnätverk.",
"install_devices_android_list_3": "Håll ner på nätverksnamnet som du är ansluten till och välj Ändra nätverk.",
"install_devices_android_list_4": "På en del enheter kan du behöva välja Avancerat för att komma åt ytterligare inställningar. För att ändra på DNS-inställningar måste du byta IP-inställning från DHCP till Statisk. På Android Pie väljs Privat DNS på Nätverk och internet.",
"install_devices_android_list_5": "Ändra DNS 1 och DNS 2 till serveradresserna för AdGuard Home.",
"install_devices_android_list_5": "Ändra DNS 1 och DNS 2 värdena till serveradresserna för din AdGuard Home.",
"install_devices_ios_list_1": "Tryck Inställningar från hemskärmen.",
"install_devices_ios_list_2": "Välj Wi_Fi på den vänstra menyn (det går inte att ställa in egen DNS för mobila nätverk).",
"install_devices_ios_list_3": "Tryck på namnet på den aktiva anslutningen.",
@@ -225,14 +357,18 @@
"install_saved": "Sparat utan fel",
"encryption_title": "Kryptering",
"encryption_desc": "Krypteringsstöd (HTTPS/TLS) för både DNS och adminwebbgränssnitt.",
"encryption_config_saved": "Krypteringsinställningar sparade",
"encryption_server": "Servernamn",
"encryption_server_enter": "Skriv in ditt domännamn",
"encryption_server_desc": "För att kunna använda HTTPS måste du ange servernamnet som matchar ditt SSL-certifikat eller jokerteckencertifikat. Om fältet inte är inställt kommer det att acceptera TLS-anslutningar för alla domäner.",
"encryption_redirect": "Omdirigera till HTTPS automatiskt",
"encryption_redirect_desc": "Om bockad kommer AdGuard Home automatiskt att omdirigera dig från HTTP till HTTPS-adresser.",
"encryption_https": "HTTPS-port",
"encryption_https_desc": "Om en HTTPS-port är inställd kommer gränssnittet till AdGuard Home administrering att kunna nås via HTTPS och kommer också att erbjuda DNS-over-HTTPS på '/dns-query' plats.",
"encryption_dot": "DNS-över-TLS port",
"encryption_dot_desc": "Om den här porten ställs in kommer AdGuard Home att använda DNS-over-TLS-server på porten.",
"encryption_doq": "DNS-over-QUIC port",
"encryption_doq_desc": "Om denna port är konfigurerad kommer AdGuard Home att köra en DNS-over-QUIC-server på denna port. Det är experimentellt och kanske inte är tillförlitligt. Dessutom finns det inte så många klienter som stödjer det för tillfället.",
"encryption_certificates": "Certifikat",
"encryption_certificates_desc": "För att använda kryptering måste du ange ett giltigt SSL-certifikat för din domän. Du kan skaffa ett certifikat gratis på <0>{{link}}</0> eller köpa ett från någon av de godkända certifikatutfärdare.",
"encryption_certificates_input": "Kopiera/klistra in dina PEM-kodade certifikat här.",
@@ -252,16 +388,22 @@
"encryption_reset": "Är du säker på att du vill återställa krypteringsinställningarna?",
"topline_expiring_certificate": "Ditt SSL-certifikat håller på att gå ut. <0>Krypteringsinställningar</0>.",
"topline_expired_certificate": "Ditt SSL-certifikat har gått ut. Uppdatera <0>Krypteringsinställningar</0>-",
"form_error_port_range": "Ange ett portnummer inom värdena 80-65535",
"form_error_port_unsafe": "Det här är en osäker port",
"form_error_equal": "Får inte vara samma",
"form_error_password": "Lösenorden överensstämmer inte",
"reset_settings": "Återställ inställningar",
"update_announcement": "AdGuard Home {{version}} är nu tillgänglig! <0>Klicka här</0> för mer information.",
"setup_guide": "Installationsguide",
"dns_addresses": "DNS-adresser",
"dns_start": "DNS servern startar",
"dns_status_error": "Fel vid kontroll av DNS serverns status",
"down": "Ner",
"fix": "Fixa",
"dns_providers": "Här är en <0>lista över kända DNS-leverantörer</0> att välja från.",
"update_now": "Uppdatera nu",
"update_failed": "Automatisk uppdatering misslyckad. Var god <a>följ stegen</a> för att uppdatera manuellt.",
"manual_update": "Vänligen <a>följ dessa steg</a> för att uppdatera manuellt.",
"processing_update": "Vänta, AdGuard Home uppdateras",
"clients_title": "Klienter",
"clients_desc": "Konfigurera enheter uppkopplade mot AdGuard Home",
@@ -275,8 +417,12 @@
"client_edit": "Redigera klient",
"client_identifier": "Identifikator",
"ip_address": "IP-adress",
"client_identifier_desc": "Klienter kan identifieras med IP-adressen, CIDR, MAC-adressen eller ett speciellt klient-ID (kan användas för DoT/DoH/DoQ). <0>Här</0> kan du lära dig mer om hur du identifierar klienter.",
"form_enter_ip": "Skriv in IP",
"form_enter_subnet_ip": "Ange en IP adress i subnätet \"{{cidr}}\"",
"form_enter_mac": "Skriv in MAC",
"form_enter_id": "Ange identifierare",
"form_add_id": "Lägg till identifierare",
"form_client_name": "Skriv in klientnamn",
"name": "Namn",
"client_global_settings": "Använda globala inställningar",
@@ -285,15 +431,17 @@
"client_updated": "Klient \"{{key}}\" har uppdaterats",
"clients_not_found": "Inga klienter hittade",
"client_confirm_delete": "Är du säker på att du vill ta bort klient \"{{key}}\"?",
"list_confirm_delete": "Är du säker på att du vill ta bort den här listan?",
"auto_clients_title": "Klienter (körtid)",
"auto_clients_desc": "Data från klienter som använder AdGuard Home, men inte är sparade i konfigurationen",
"access_title": "Åtkomstinställningar",
"access_desc": "Här kan du konfigurera åtkomstregler för AdGuard Homes DNS-server.",
"access_allowed_title": "Tillåtna klienter",
"access_allowed_desc": "En lista över CIDR eller IP-adresser. Om konfigurerad kommer AdGuard Home endast acceptera förfrågningar från dessa IP-adresser.",
"access_allowed_desc": "En lista över CIDR, IP-adresser eller klient-ID. Om det är konfigurerat accepterar AdGuard Home endast förfrågningar från dessa klienter.",
"access_disallowed_title": "Otillåtna klienter",
"access_disallowed_desc": "En lista över CIDR eller IP-adresser. Om konfigurerad kommer AdGuard Home inte acceptera förfrågningar från dessa IP-adresser.",
"access_disallowed_desc": "En lista över CIDR, IP-adresser eller klient-ID. Om det är konfigurerat kommer AdGuard Home att kasta förfrågningar från dessa klienter. Om tillåtna klienter är konfigurerade ignoreras detta fält.",
"access_blocked_title": "Blockerade domäner",
"access_blocked_desc": "Ej att förväxla med filter. AdGuard Home kastar DNS-frågor som matchar dessa domäner, och dessa frågor visas inte ens i frågeloggen. Du kan ange exakta domännamn, jokertecken eller URL-filterregler, t.ex. \"example.org\", \"*.example.org\" eller \"||example.org^\" på motsvarande sätt.",
"access_settings_saved": "Åtkomstinställningar sparade",
"updates_checked": "Sökning efter uppdateringar genomförd",
"updates_version_equal": "AdGuard Home är uppdaterat",
@@ -301,6 +449,8 @@
"dns_privacy": "DNS-Integritet",
"setup_dns_privacy_1": "<0>DNS-över-TLS:</0> Använd: <1>{{address}}</1>",
"setup_dns_privacy_2": "<0>DNS-över-HTTPS:</0> Använd: <1>{{address}}</1>",
"setup_dns_privacy_3": "<0>Här är en lista över program du kan använda.</0>",
"setup_dns_privacy_4": "På en iOS 14 eller macOS Big Sur enhet kan du ladda ner en speciell '.mobileconfig' fil som lägger till <highlight>DNS-over-HTTPS</highlight> eller <highlight>DNS-over-TLS</highlight>-servrar till DNS inställningarna.",
"setup_dns_privacy_android_1": "Android 9 har inbyggt stöd för DNS-över-TLS. Konfigurera och uppge domännamn under Inställningar → Nätverk & Internet → Avancerat → Privat DNS.",
"setup_dns_privacy_android_2": "<0>AdGuard för Android</0> stödjer <1>DNS-över-HTTPS</1> samt <1>DNS-över-TLS</1>.",
"setup_dns_privacy_android_3": "<0>Intra</0> lägger till stöd för <1>DNS-ÖVER-HTTPS</1> till Android.",
@@ -312,15 +462,51 @@
"setup_dns_privacy_other_3": "<0>dnscrypt-proxy</0> stödjer <1>DNS-over-HTTPS</1>.",
"setup_dns_privacy_other_4": "<0>Mozilla Firefox</0> stödjer <1>DNS-over-HTTPS</1>.",
"setup_dns_privacy_other_5": "Du kan hitta fler implementeringar <0>här</0> och <1>här</1>.",
"setup_dns_privacy_ioc_mac": "iOS och macOS konfiguration",
"setup_dns_notice": "För att kunna använda <1>DNS-över-HTTPS</1> eller <1>DNS-över-TLS</1>, behöver du <0>konfigurera Kryptering</0> i AdGuard Home-inställningar.",
"rewrite_added": "DNS-omskrivning för \"{{key}}\" lyckad",
"rewrite_deleted": "DNS-omskrivning för \"{{key}}\" har tagits bort",
"rewrite_add": "Lägg till DNS omskrivning",
"rewrite_not_found": "Inga DNS omskrivningar hittades",
"rewrite_confirm_delete": "Är du säker på att du vill ta bort DNS-omskrivningen för \"{{key}}\"?",
"rewrite_desc": "Gör det enkelt att konfigurera anpassat DNS svar för ett specifikt domännamn.",
"rewrite_applied": "Omskrivningsregeln tillämpas",
"rewrite_hosts_applied": "Omskriven av värd fil regel",
"dns_rewrites": "DNS omskrivningar",
"form_domain": "Ange domännamn eller jokertecken",
"form_answer": "Ange IP adress eller domännamn",
"form_error_domain_format": "Ogiltigt domänformat",
"form_error_answer_format": "Ogiltigt svarsformat",
"configure": "Konfigurera",
"main_settings": "Huvudinställningar",
"block_services": "Blockera specifika tjänster",
"blocked_services": "Blockerade tjänster",
"blocked_services_desc": "Gör det möjligt att snabbt blockera populära webbplatser och tjänster.",
"blocked_services_saved": "Blockerade tjänster har sparats",
"blocked_services_global": "Använd globalt blockerade tjänster",
"blocked_service": "Blockerad tjänst",
"block_all": "Blockera alla",
"unblock_all": "Avblockera alla",
"encryption_certificate_path": "Certifikatsökväg",
"encryption_private_key_path": "Privat nyckel sökväg",
"encryption_certificates_source_path": "Ange sökväg för certifikatfilen",
"encryption_certificates_source_content": "Klistra in certifikatets innehåll",
"encryption_key_source_path": "Ställ in en privat nyckelfil",
"encryption_key_source_content": "Klistra in den privata nyckelns innehåll",
"stats_params": "Statistikkonfiguration",
"config_successfully_saved": "Konfigurationen har sparats",
"interval_6_hour": "6 timmar",
"interval_24_hour": "24 timmar",
"interval_days": "{{count}} dag",
"interval_days_plural": "{{count}} dagar",
"domain": "Domän",
"punycode": "Punycode",
"answer": "Svar",
"filter_added_successfully": "Listan har lagts till",
"filter_removed_successfully": "Listan har tagits bort",
"filter_updated": "Listan har uppdaterats",
"statistics_configuration": "Statistikkonfiguration",
"statistics_retention": "Bevarande av statistik",
"statistics_retention_desc": "Om du minskar intervallet kommer viss data att gå förlorad",
"statistics_clear": "Rensa statistik",
"statistics_clear_confirm": "Är du säker på att du vill radera statistiken?",
@@ -348,17 +534,99 @@
"descr": "Beskrivning",
"whois": "Whois",
"filtering_rules_learn_more": "<0>Mer info</0> om att skapa dina egna blockeringslistor för värdar.",
"blocked_by_response": "Blockerad av CNAME eller IP i svaret",
"blocked_by_cname_or_ip": "Blockerad av CNAME eller IP",
"try_again": "Försök igen",
"domain_desc": "Ange domännamnet eller jokertecken som du vill ska skrivas om.",
"example_rewrite_domain": "skriv bara om svar för detta domännamn.",
"example_rewrite_wildcard": "skriv om svar för alla <0>example.org</0> subdomäner.",
"rewrite_ip_address": "IP adress: använd denna IP i ett A- eller AAAA-svar",
"rewrite_domain_name": "Domännamn: lägg till en CNAME post",
"rewrite_A": "<0>A</0>: specialvärde, behåll <0>A</0> poster från uppströms",
"rewrite_AAAA": "<0>AAAA</0>: specialvärde, behåll <0>AAAA</0> poster från uppströms",
"disable_ipv6": "Inaktivera upplösning av IPv6 adresser",
"disable_ipv6_desc": "Kasta alla DNS-frågor för IPv6-adresser (typ AAAA).",
"fastest_addr": "Snabbaste IP adressen",
"fastest_addr_desc": "Fråga alla DNS servrar och returnera den snabbaste IP adressen bland alla svar. Detta saktar ner DNS-frågor eftersom AdGuard Home måste vänta på svar från alla DNS servrar, men förbättrar den övergripande anslutningen.",
"autofix_warning_text": "Om du klickar på \"Fix\" kommer AdGuard Home att konfigurera ditt system för att använda AdGuard Home DNS server.",
"autofix_warning_list": "Den kommer att utföra följande uppgifter: <0>Avaktivera system DNSStubListener</0> <0>Sätt DNS serveradress till 127.0.0.1</0> <0>Ersätt symboliskt länkmål för /etc/resolv.conf med /run/systemd /resolve/resolv.conf</0> <0>Stoppa DNSStubListener (ladda om systemd-resolved tjänst)</0>",
"autofix_warning_result": "Som ett resultat kommer alla DNS-förfrågningar från ditt system att behandlas av AdGuard Home som standard.",
"tags_title": "Taggar",
"tags_desc": "Du kan välja de taggar som motsvarar klienten. Taggar kan inkluderas i filtreringsreglerna och låter dig tillämpa dem mer exakt. <0>Läs mer</0>",
"form_select_tags": "Välj klienttaggar",
"check_title": "Kontrollera filtreringen",
"check_desc": "Kontrollera om värdnamnet är filtrerat",
"check": "Kontrollera",
"form_enter_host": "Ange ett värdnamn",
"filtered_custom_rules": "Filtrerat efter anpassade filtreringsregler",
"choose_from_list": "Välj från listan",
"add_custom_list": "Lägg till en anpassad lista",
"host_whitelisted": "Värden är tillåten",
"check_ip": "IP adresser: {{ip}}",
"check_cname": "CNAME: {{cname}}",
"check_reason": "Anledning: {{reason}}",
"check_service": "Service namn: {{service}}",
"service_name": "Service namn",
"check_not_found": "Hittades inte i dina filterlistor",
"client_confirm_block": "Är du säker på att du vill blockera klienten \"{{ip}}\"?",
"client_confirm_unblock": "Är du säker på att du vill avblockera klienten \"{{ip}}\"?",
"client_blocked": "Klienten \"{{ip}}\" har blockerats",
"client_unblocked": "Klienten \"{{ip}}\" har avblockerats",
"static_ip": "Statisk IP adress",
"static_ip_desc": "AdGuard Home är en server så den behöver en statisk IP-adress för att fungera korrekt. Annars kan din router vid något tillfälle tilldela en annan IP-adress till den här enheten.",
"set_static_ip": "Ställ in en statisk IP adress",
"install_static_ok": "Goda nyheter! Den statiska IP adressen är redan konfigurerad",
"install_static_error": "AdGuard Home kan inte konfigurera det automatiskt för detta nätverksgränssnitt. Vänligen leta efter en instruktion om hur du gör detta manuellt.",
"install_static_configure": "AdGuard Home har upptäckt att den dynamiska IP adressen <0>{{ip}}</0> används. Vill du att den ska ställas in som din statiska adress?",
"confirm_static_ip": "AdGuard Home kommer att konfigurera {{ip}} för att vara din statiska IP adress. Vill du fortsätta?",
"list_updated": "{{count}} listan uppdaterad",
"list_updated_plural": "{{count}} listor uppdaterade",
"dnssec_enable": "Aktivera DNSSEC",
"dnssec_enable_desc": "Ställ in DNSSEC flagga i de utgående DNS frågorna och kontrollera resultatet (DNSSEC-aktiverad upplösare krävs).",
"validated_with_dnssec": "Validerad med DNSSEC",
"all_queries": "Alla förfrågningar",
"show_blocked_responses": "Blockerade",
"show_whitelisted_responses": "Vitlistade",
"show_processed_responses": "Utförda",
"blocked_adult_websites": "Blockerade vuxensajter",
"blocked_safebrowsing": "Blockerad av Säker webbsökning",
"blocked_adult_websites": "Blockerad av Föräldrakontroll",
"blocked_threats": "Blockerade hot",
"allowed": "Vitlistade",
"filtered": "Filtrerad",
"rewritten": "Omskriven",
"safe_search": "Säker surf",
"blocklist": "Blocklista",
"milliseconds_abbreviation": "ms",
"cache_size": "Cachestorlek",
"cache_size_desc": "DNS cachestorlek (i byte)",
"cache_ttl_min_override": "Åsidosätt minsta TTL",
"cache_ttl_max_override": "Åsidosätt maximal TTL",
"enter_cache_size": "Ange cachestorlek (byte)",
"enter_cache_ttl_min_override": "Ange minsta TTL (sekunder)",
"enter_cache_ttl_max_override": "Ange maximal TTL (sekunder)",
"cache_ttl_min_override_desc": "Förläng värden för korta time-to-live värden (sekunder) som tas emot från uppströms server när DNS svar cachelagras",
"cache_ttl_max_override_desc": "Ställ in ett maximalt värde för time-to-live (sekunder) för poster i DNS cachen",
"ttl_cache_validation": "Minsta cache TTL-värde måste vara mindre än eller lika med maxvärdet",
"cache_optimistic": "Optimistisk cachning",
"cache_optimistic_desc": "Få AdGuard Home att svara från cachen även när posterna har gått ut och försök även uppdatera dem.",
"filter_category_general": "General",
"filter_category_security": "säkerhet",
"filter_category_regional": "Regional",
"filter_category_other": "Övrigt",
"filter_category_general_desc": "Listor som blockerar spårning och reklam på de flesta enheterna",
"filter_category_security_desc": "Listor utformade specifikt för att blockera skadliga domäner, nätfiske och bluffdomäner",
"filter_category_regional_desc": "Listor som fokuserar på regionala annonser och spårningsservrar",
"filter_category_other_desc": "Andra blockeringslistor",
"setup_config_to_enable_dhcp_server": "Ställ in konfiguration för att aktivera DHCP-server",
"original_response": "Ursprungligt svar",
"click_to_view_queries": "Klicka för att se förfrågningar",
"port_53_faq_link": "Port 53 är ofta upptagen av \"DNSStubListener\" eller \"systemd-resolved\" tjänster. Läs <0>denna instruktion</0> om hur du löser detta.",
"adg_will_drop_dns_queries": "AdGuard Home kommer att kasta alla DNS-frågor från den här klienten.",
"filter_allowlist": "VARNING: Denna åtgärd kommer också att utesluta regeln \"{{disallowed_rule}}\" från listan över tillåtna klienter.",
"last_rule_in_allowlist": "Det går inte att avvisa den här klienten eftersom att utesluta regeln \"{{disallowed_rule}}\" kommer att INAKTIVERA listan \"Tillåtna klienter\".",
"experimental": "Experimentell",
"use_saved_key": "Använd den tidigare sparade nyckeln",
"parental_control": "Föräldrakontroll"
"parental_control": "Föräldrakontroll",
"safe_browsing": "Säker surfning",
"served_from_cache": "{{value}} <i>(levereras från cache)</i>"
}

View File

@@ -128,7 +128,6 @@
"example_upstream_doh": "เข้ารหัส <0>DNS-over-HTTPS</0> แล้ว",
"example_upstream_sdns": "คุณสามรถใช้ <0>DNS Stamps</0> กับ <1>DNSCrypt</1> หรือ <2>DNS-over-HTTPS</2> ตัวแก้ปัญหา",
"example_upstream_tcp": "dNS ปกติ (ผ่าน TCP)",
"updated_upstream_dns_toast": "อัปเดตเซิร์ฟเวอร์ DNS ต้นทาง",
"dns_test_ok_toast": "เซิร์ฟเวอร์ DNS ที่ระบุทำงานอย่างถูกต้อง",
"dns_test_not_ok_toast": "เซิร์ฟเวอร์ \"{{key}}\": ไม่สามารถใช้งานได้ โปรดตรวจสอบว่าคุณเขียนถูกต้อง",
"unblock": "เลิกปิดกั้น",
@@ -390,6 +389,7 @@
"check_desc": "ตรวจสอบว่าชื่อโฮสต์ถูกกรอง",
"form_enter_host": "ป้อนชื่อโฮสต์",
"show_processed_responses": "การประมวลผล",
"blocked_adult_websites": "ถูกปิดกั้นโดยการควบคุมของผู้ปกครอง",
"safe_search": "ค้นหาอย่างปลอดภัย",
"filter_category_other": "อื่น ๆ",
"parental_control": "ควบคุมโดยผู้ปกครอง"

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "IPv6 adresi geçersiz",
"form_error_ip_format": "IP adresi geçersiz",
"form_error_mac_format": "MAC adresi geçersiz",
"form_error_client_id_format": "İstemci kimliği geçersiz",
"form_error_client_id_format": "İstemci kimliği yalnızca sayılar, küçük harfler ve kısa çizgiler içermelidir",
"form_error_server_name": "Sunucu adı geçersiz",
"form_error_subnet": "\"{{cidr}}\" alt ağı, \"{{ip}}\" IP adresini içermiyor",
"form_error_positive": "0'dan büyük olmalıdır",
@@ -53,7 +53,7 @@
"greater_range_end_error": "Bitiş aralığından daha büyük olmalıdır",
"subnet_error": "Adresler bir alt ağda olmalıdır",
"gateway_or_subnet_invalid": "Alt ağ maskesi geçersiz",
"dhcp_form_gateway_input": "Ağ Geçidi IP'si",
"dhcp_form_gateway_input": "Ağ geçidi IP",
"dhcp_form_subnet_input": "Alt ağ maskesi",
"dhcp_form_range_title": "IP adresi aralığı",
"dhcp_form_range_start": "Başlangıç aralığı",
@@ -138,7 +138,7 @@
"average_processing_time": "Ortalama işlem süresi",
"average_processing_time_hint": "Bir DNS isteğinin milisaniye cinsinden ortalama işlem süresi",
"block_domain_use_filters_and_hosts": "Filtre ve ana bilgisayar listelerini kullanarak alan adlarını engelle",
"filters_block_toggle_hint": "<a>Filtreler</a> sayfasından engelleme kurallarını ayarlayabilirsiniz.",
"filters_block_toggle_hint": "<a>Filtreler</a> ayarlarında engelleme kuralları oluşturabilirsiniz.",
"use_adguard_browsing_sec": "AdGuard gezinti koruması web hizmetini kullan",
"use_adguard_browsing_sec_hint": "AdGuard Home, alan adının gezinti koruması web hizmeti tarafından engellenip engellenmediğini kontrol eder. Kontrolü gerçekleştirmek için gizlilik dostu arama API'sini kullanır: sunucuya yalnızca SHA256 karma alan adının kısa bir ön eki gönderilir.",
"use_adguard_parental": "AdGuard ebeveyn denetimi web hizmetini kullan",
@@ -163,12 +163,12 @@
"apply_btn": "Uygula",
"disabled_filtering_toast": "Filtreleme devre dışı",
"enabled_filtering_toast": "Filtreleme etkin",
"disabled_safe_browsing_toast": "Güvenli gezinti devre dışı",
"enabled_safe_browsing_toast": "Güvenli gezinti etkin",
"disabled_parental_toast": "Ebeveyn denetimi devre dışı",
"enabled_parental_toast": "Ebeveyn denetimi etkin",
"disabled_safe_search_toast": "Güvenli arama devre dışı",
"enabled_save_search_toast": "Güvenli arama etkin",
"disabled_safe_browsing_toast": "Güvenli Gezinti devre dışı bırakıldı",
"enabled_safe_browsing_toast": "Güvenli Gezinti etkinleştirildi",
"disabled_parental_toast": "Ebeveyn denetimi devre dışı bırakıldı",
"enabled_parental_toast": "Ebeveyn denetimi etkinleştirildi",
"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",
"list_url_table_header": "Liste URL'si",
@@ -178,7 +178,7 @@
"request_table_header": "İstek",
"edit_table_action": "Düzenle",
"delete_table_action": "Sil",
"elapsed": "Geçen zaman",
"elapsed": "Geçen süre",
"filters_and_hosts_hint": "AdGuard Home, temel reklam engelleme kurallarını ve ana bilgisayar engelleme dosyalarının söz dizimini anlar.",
"no_blocklist_added": "Engel listesi eklenmedi",
"no_whitelist_added": "İzin listesi eklenmedi",
@@ -327,10 +327,10 @@
"install_submit_desc": "Yükleme işlemi tamamlandı ve artık AdGuard Home'u kullanmaya hazırsınız.",
"install_devices_router": "Yönlendirici",
"install_devices_router_desc": "Bu kurulum, ev yönlendiricinize bağlı tüm cihazları otomatik olarak kapsar ve her birini elle yapılandırmanıza gerek yoktur.",
"install_devices_address": "AdGuard Home DNS sunucusu şu adresi dinleyecektir",
"install_devices_address": "AdGuard Home DNS sunucusu aşağıdaki adresleri dinliyor",
"install_devices_router_list_1": "Yönlendiricinizin ayarlarına gidin. Genellikle tarayıcınızdan http://192.168.0.1/ veya http://192.168.1.1/ gibi bir URL aracılığıyla erişebilirsiniz. Bir parola girmeniz istenebilir. Hatırlamıyorsanız, genellikle yönlendiricinin üzerindeki bir düğmeye basarak parolayı sıfırlayabilirsiniz, ancak bu işlemin seçilmesi durumunda yüksek ihtimalle tüm yönlendirici yapılandırmasını kaybedeceğinizi unutmayın. Yönlendiricinizin kurulumu için bir uygulama gerekiyorsa, lütfen uygulamayı telefonunuza veya PC'nize yükleyin ve yönlendiricinin ayarlarına erişmek için kullanın.",
"install_devices_router_list_2": "DHCP/DNS ayarlarını bulun. DNS satırlarını arayın, genelde iki veya üç tanedir, üç rakam girilebilen dört ayrı grup içeren satırdır.",
"install_devices_router_list_3": "AdGuard Home sunucusunun adresini o kısma yazın.",
"install_devices_router_list_3": "AdGuard Home sunucu adreslerinizi oraya girin.",
"install_devices_router_list_4": "Bazı yönlendirici türlerinde özel bir DNS sunucusu ayarlanamaz. Bu durumda, AdGuard Home'u <0>DHCP sunucusu</0> olarak ayarlamak yardımcı olabilir. Aksi takdirde, yönlendirici modeliniz için DNS sunucularını nasıl ayarlayacağınız konusunda yönlendirici kılavuzuna bakmalısınız.",
"install_devices_windows_list_1": "Başlat menüsünden veya Windows araması aracılığıyla Denetim Masası'nıın.",
"install_devices_windows_list_2": "Ağ ve İnternet kategorisine girin ve ardından Ağ ve Paylaşım Merkezi'ne girin.",
@@ -339,15 +339,15 @@
"install_devices_windows_list_5": "Listede \"İnternet Protokolü Sürüm 4 (TCP/IPv4)\" (veya IPv6 için \"İnternet Protokolü Sürüm 6 (TCP/IPv6)\") öğesini bulun, seçin ve ardından tekrar Özellikler'e tıklayın.",
"install_devices_windows_list_6": "\"Aşağıdaki DNS sunucu adreslerini kullan\"ı seçin ve AdGuard Home sunucu adreslerinizi girin.",
"install_devices_macos_list_1": "Apple simgesinde bulunan Sistem Tercihleri'ne tıklayın.",
"install_devices_macos_list_2": "Ağ seçeneğine tıklayın.",
"install_devices_macos_list_2": "Ağ'a tıklayın.",
"install_devices_macos_list_3": "Listedeki ilk bağlantıyı seçin ve Gelişmiş öğesine tıklayın.",
"install_devices_macos_list_4": "DNS sekmesini seçin ve AdGuard Home sunucunuzun adreslerini girin.",
"install_devices_android_list_1": "Android cihazınızda Ayarlar simgesine dokunun.",
"install_devices_android_list_1": "Android Menüsü ana ekranından Ayarlar'a dokunun.",
"install_devices_android_list_2": "Menüde bulunan Wi-Fi seçeneğine dokunun. Mevcut tüm ağlar listelenecektir (mobil ağlar için özel DNS sunucusu ayarlanamaz).",
"install_devices_android_list_3": "Bağlı olduğunuz ağın üzerine basılı tutun ve Ağı Değiştir'e dokunun.",
"install_devices_android_list_4": "Bazı cihazlarda, diğer ayarları görmek için \"Gelişmiş\" seçeneğini seçmeniz gerekebilir. Android DNS ayarlarınızı yapmak için IP ayarlarını DHCP modundan Statik moda almanız gerekecektir.",
"install_devices_android_list_5": "DNS 1 ve DNS 2 değerlerini AdGuard Home sunucunuzun adresleriyle değiştirin.",
"install_devices_ios_list_1": "Ana ekrandaki Ayarlar simgesine dokunun.",
"install_devices_ios_list_1": "Ana ekrandan Ayarlar'a dokunun.",
"install_devices_ios_list_2": "Sol menüde bulunan Wi-Fi bölümüne girin (mobil ağlar için özel DNS sunucusu ayarlanamaz).",
"install_devices_ios_list_3": "Bağlı olduğunuz ağın ismine dokunun.",
"install_devices_ios_list_4": "DNS alanına AdGuard Home sunucunuzun adreslerini girin.",
@@ -386,8 +386,8 @@
"encryption_issuer": "Sağlayan",
"encryption_hostnames": "Ana bilgisayar adları",
"encryption_reset": "Şifreleme ayarlarını sıfırlamak istediğinizden emin misiniz?",
"topline_expiring_certificate": "SSL sertifikanızın süresi dolmak üzere. <0>Şifreleme ayarlarını</0> güncelleyin.",
"topline_expired_certificate": "SSL sertifikanızın süresi doldu. <0>Şifreleme ayarlarını</0> güncelleyin.",
"topline_expiring_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını</0> güncelleyin.",
"topline_expired_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını</0> güncelleyin.",
"form_error_port_range": "80-65535 aralığında geçerli bir bağlantı noktası değeri girin",
"form_error_port_unsafe": "Bu bağlantı noktası güvenli değil",
"form_error_equal": "Aynı olmamalı",
@@ -403,6 +403,7 @@
"dns_providers": "Aralarından seçim yapabileceğiniz, bilinen <0>DNS sağlayıcıların listesi</0>.",
"update_now": "Şimdi güncelle",
"update_failed": "Otomatik güncelleme başarısız oldu. Elle güncellemek için lütfen <a>bu adımları uygulayın</a>.",
"manual_update": "Elle güncellemek için lütfen <a>bu adımları uygulayın</a>.",
"processing_update": "Lütfen bekleyin, AdGuard Home güncelleniyor",
"clients_title": "İstemciler",
"clients_desc": "AdGuard Home'a bağlı cihazları yapılandırın",
@@ -417,7 +418,7 @@
"client_identifier": "Tanımlayıcı",
"ip_address": "IP adresi",
"client_identifier_desc": "İstemciler IP adresi, CIDR, MAC adresi veya özel bir istemci kimliği ile tanımlanabilir (DoT/DoH/DoQ için kullanılabilir). İstemcileri nasıl tanımlayacağınız hakkında daha fazla bilgiyi <0>burada</0> bulabilirsiniz.",
"form_enter_ip": "IP adresi girin",
"form_enter_ip": "IP girin",
"form_enter_subnet_ip": "\"{{cidr}}\" alt ağına bir IP adresi girin",
"form_enter_mac": "MAC adresi girin",
"form_enter_id": "Tanımlayıcı girin",
@@ -439,7 +440,7 @@
"access_allowed_desc": "CIDR'lerin, IP adreslerinin veya istemci kimliklerinin listesi. Yapılandırılırsa, AdGuard Home yalnızca bu istemcilerden gelen istekleri kabul eder.",
"access_disallowed_title": "İzin verilmeyen istemciler",
"access_disallowed_desc": "CIDR'lerin, IP adreslerinin veya istemci kimliklerinin listesi. Yapılandırılırsa, AdGuard Home bu istemcilerden gelen istekleri keser. İzin verilen istemciler yapılandırılırsa, bu alan yok sayılır.",
"access_blocked_title": "Engellenen alan adları",
"access_blocked_title": "İzin verilmeyen alan adları",
"access_blocked_desc": "Bu işlem filtrelerle ilgili değildir. AdGuard Home, bu alan adlarından gelen DNS sorgularını yanıtsız bırakır ve bu sorgular sorgu günlüğünde görünmez. Tam alan adlarını, joker karakterleri veya URL filtre kurallarını belirtebilirsiniz, ör. \"example.org\", \"*.example.org\" veya \"||example.org^\".",
"access_settings_saved": "Erişim ayarları başarıyla kaydedildi!",
"updates_checked": "Güncelleme kontrolü başarılı",
@@ -587,8 +588,8 @@
"show_blocked_responses": "Engellenen",
"show_whitelisted_responses": "İzin verilen",
"show_processed_responses": "İşlenen",
"blocked_safebrowsing": "Güvenli gezinti tarafından engellendi",
"blocked_adult_websites": "Engellenen yetişkin içerikli siteler",
"blocked_safebrowsing": "Güvenli Gezinti tarafından engellendi",
"blocked_adult_websites": "Ebeveyn Denetimi tarafından engellendi",
"blocked_threats": "Engellenen tehditler",
"allowed": "İzin verilen",
"filtered": "Filtrelenen",
@@ -601,8 +602,8 @@
"cache_ttl_min_override": "Minimum TTL'i değiştir",
"cache_ttl_max_override": "Maksimum TTL'i değiştir",
"enter_cache_size": "Önbellek boyutunu girin (bayt)",
"enter_cache_ttl_min_override": "Minimum TTL değerini girin (saniye)",
"enter_cache_ttl_max_override": "Maksimum TTL değerini girin (saniye)",
"enter_cache_ttl_min_override": "Minimum TTL değerini girin (saniye olarak)",
"enter_cache_ttl_max_override": "Maksimum TTL değerini girin (saniye olarak)",
"cache_ttl_min_override_desc": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan kullanım süresi değerini uzatın (saniye olarak)",
"cache_ttl_max_override_desc": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak)",
"ttl_cache_validation": "Minimum önbellek TTL değeri, maksimum değerden küçük veya bu değere eşit olmalıdır",
@@ -625,6 +626,7 @@
"last_rule_in_allowlist": "\"{{disallowed_rule}}\" kuralı hariç tutulduğunda \"İzin verilen istemciler\" listesi DEVRE DIŞI bırakılacağı için bu istemciye izin verilemez.",
"experimental": "Deneysel",
"use_saved_key": "Önceden kaydedilmiş anahtarı kullan",
"parental_control": "Ebeveyn denetimi",
"safe_browsing": "Güvenli gezinti"
"parental_control": "Ebeveyn Denetimi",
"safe_browsing": "Güvenli Gezinti",
"served_from_cache": "{{value}} <i>(önbellekten kullanıldı)</i>"
}

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "Неправильна IPv6-адреса",
"form_error_ip_format": "Неправильна IP-адреса",
"form_error_mac_format": "Неправильна MAC-адреса",
"form_error_client_id_format": "Неправильний ID клієнта",
"form_error_client_id_format": "ID клієнта має містити лише цифри, малі букви та дефіси",
"form_error_server_name": "Неправильна назва сервера",
"form_error_subnet": "Підмережа «{{cidr}}» не містить IP-адресу «{{ip}}»",
"form_error_positive": "Повинно бути більше 0",
@@ -587,8 +587,8 @@
"show_blocked_responses": "Заблоковані",
"show_whitelisted_responses": "Дозволені",
"show_processed_responses": "Оброблені",
"blocked_safebrowsing": "Безпечний перегляд заблоковано",
"blocked_adult_websites": "Заблоковані вебсайти для дорослих",
"blocked_safebrowsing": "Заблоковано Безпечним переглядом",
"blocked_adult_websites": "Заблоковано Батьківським контролем",
"blocked_threats": "Заблоковано загроз",
"allowed": "Дозволено",
"filtered": "Відфільтровано",
@@ -626,6 +626,6 @@
"experimental": "Експериментальний",
"use_saved_key": "Використати раніше збережений ключ",
"parental_control": "Батьківський контроль",
"safe_browsing": "Безпечний інтернет",
"safe_browsing": "Безпечний перегляд",
"served_from_cache": "{{value}} <i>(отримано з кешу)</i>"
}

View File

@@ -38,7 +38,7 @@
"form_error_required": "Trường bắt buộc",
"form_error_ip4_format": "Định dạng IPv4 không hợp lệ",
"form_error_ip6_format": "Định dạng IPv6 không hợp lệ",
"form_error_ip_format": "Định dạng IPv4 không hợp lệ",
"form_error_ip_format": "Địa chỉ IP không hợp lệ",
"form_error_mac_format": "Định dạng MAC không hợp lệ",
"form_error_client_id_format": "Định dạng client ID không hợp lệ",
"form_error_server_name": "Tên máy chủ không hợp lệ",
@@ -578,7 +578,7 @@
"show_whitelisted_responses": "Đã thêm vào danh sách cho phép",
"show_processed_responses": "Đã xử lý",
"blocked_safebrowsing": "Chặn bởi Safebrowsing",
"blocked_adult_websites": "Website người lớn đã chặn",
"blocked_adult_websites": "Bị chặn bởi Quản lý của Phụ huynh",
"blocked_threats": "Mối nguy hiểm đã chặn",
"allowed": "Được phép",
"filtered": "Đã lọc",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "无效的 IPv6 地址",
"form_error_ip_format": "无效的 IP 地址",
"form_error_mac_format": "无效的 MAC 地址",
"form_error_client_id_format": "无效的客户端 ID",
"form_error_client_id_format": "无效的客户端 ID 格式客户 ID 必须只包含数字、小写字母和连字符",
"form_error_server_name": "无效的服务器名",
"form_error_subnet": "子网 \"{{cidr}}\" 不包含 IP 地址 \"{{ip}}\"",
"form_error_positive": "必须大于 0",
@@ -403,6 +403,7 @@
"dns_providers": "此为可从中选择的<0>已知 DNS 提供商列表</0>。",
"update_now": "立即更新",
"update_failed": "自动更新失败。请<a>跟随这些步骤</a>以手动更新。",
"manual_update": "请跟随<a>此步骤</a>以进行手动更新。",
"processing_update": "正在更新 AdGuard Home请稍侯",
"clients_title": "客户端",
"clients_desc": "配置已连接到 AdGuard Home 的设备",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "已列入白名单",
"show_processed_responses": "已处理",
"blocked_safebrowsing": "被安全浏览阻止",
"blocked_adult_websites": "拦截的成人网站",
"blocked_adult_websites": "被家长控制阻止",
"blocked_threats": "拦截的威胁",
"allowed": "允许项",
"filtered": "已过滤",

View File

@@ -38,7 +38,7 @@
"form_error_required": "必要欄位",
"form_error_ip4_format": "無效的 IPv4 格式",
"form_error_ip6_format": "無效的 IPv6 格式",
"form_error_ip_format": "無效的 IP 格式",
"form_error_ip_format": "無效的 IP 位址",
"form_error_mac_format": "無效的 「MAC 位址」格式",
"form_error_client_id_format": "無效的「客戶端 ID」格式",
"form_error_server_name": "無效伺服器名稱",
@@ -206,7 +206,6 @@
"example_upstream_sdns": "您可以使透過 <0>DNS Stamps</0> 來解析 <1>DNSCrypt</1> 或 <2>DNS-over-HTTPS</2>",
"example_upstream_tcp": "一般 DNS透過 TCP",
"all_lists_up_to_date_toast": "所有清單已更新至最新",
"updated_upstream_dns_toast": "已更新上游 DNS 伺服器",
"dns_test_ok_toast": "設定中的 DNS 上游運作正常",
"dns_test_not_ok_toast": "DNS 設定中的 \"{{key}}\" 出現錯誤,請確認是否正確輸入",
"unblock": "解除封鎖",

View File

@@ -43,7 +43,7 @@
"form_error_ip6_format": "無效的 IPv6 位址",
"form_error_ip_format": "無效的 IP 位址",
"form_error_mac_format": "無效的媒體存取控制MAC位址",
"form_error_client_id_format": "無效的用戶端 ID",
"form_error_client_id_format": "用戶端 ID 必須只包含數字、小寫字母和連字號",
"form_error_server_name": "無效的伺服器名稱",
"form_error_subnet": "子網路 \"{{cidr}}\" 不包含該 IP 位址 \"{{ip}}\"",
"form_error_positive": "必須大於 0",
@@ -141,12 +141,12 @@
"filters_block_toggle_hint": "您可在<a>過濾器</a>設定中設置封鎖規則。",
"use_adguard_browsing_sec": "使用 AdGuard 瀏覽安全網路服務",
"use_adguard_browsing_sec_hint": "AdGuard Home 將檢查該網域是否被瀏覽安全網路服務封鎖。它將使用友好的隱私查找應用程式介面API以執行檢查僅域名 SHA256 雜湊的短前綴被傳送到該伺服器。",
"use_adguard_parental": "使用 AdGuard 家長控之網路服務",
"use_adguard_parental": "使用 AdGuard 家長控之網路服務",
"use_adguard_parental_hint": "AdGuard Home 將檢查網域是否包含成人資料。它使用如同瀏覽安全網路服務一樣之友好的隱私應用程式介面API。",
"enforce_safe_search": "使用安全搜尋",
"enforce_save_search_hint": "AdGuard Home 將在下列的搜尋引擎Google、YouTube、Bing、DuckDuckGo、Yandex 和 Pixabay 中強制執行安全搜尋。",
"no_servers_specified": "無已明確指定的伺服器",
"general_settings": "一般設定",
"general_settings": "一般設定",
"dns_settings": "DNS 設定",
"dns_blocklists": "DNS 封鎖清單",
"dns_allowlists": "DNS 允許清單",
@@ -165,8 +165,8 @@
"enabled_filtering_toast": "已啟用過濾",
"disabled_safe_browsing_toast": "已禁用安全瀏覽",
"enabled_safe_browsing_toast": "已啟用安全瀏覽",
"disabled_parental_toast": "已禁用家長控",
"enabled_parental_toast": "已啟用家長控",
"disabled_parental_toast": "已禁用家長控",
"enabled_parental_toast": "已啟用家長控",
"disabled_safe_search_toast": "已禁用安全搜尋",
"enabled_save_search_toast": "已啟用安全搜尋",
"enabled_table_header": "已啟用",
@@ -403,6 +403,7 @@
"dns_providers": "這裡是一個從中選擇之<0>已知的 DNS 供應商之清單</0>。",
"update_now": "立即更新",
"update_failed": "自動更新已失敗。請<a>遵循這些步驟</a>以手動地更新。",
"manual_update": "請<a>遵循這些步驟</a>以手動地更新。",
"processing_update": "請稍候AdGuard Home 正被更新",
"clients_title": "用戶端",
"clients_desc": "配置被連線到 AdGuard Home 的裝置",
@@ -548,7 +549,7 @@
"fastest_addr": "最快的 IP 位址",
"fastest_addr_desc": "查詢所有的 DNS 伺服器並返回在所有的回應之中最快的 IP 位址。因為 AdGuard Home 必須等待來自所有的 DNS 伺服器之回應,這使 DNS 查詢變慢,但改善總體的連線。",
"autofix_warning_text": "如果您點擊\"修復\"AdGuard Home 將配置您的系統使用 AdGuard Home DNS 伺服器。",
"autofix_warning_list": "它將執行這些任務:<0>撤銷系統 DNSStubListener</0> <0>設定 DNS 伺服器位址為 127.0.0.1</0> <0>用 /run/systemd/resolve/resolv.conf 取代 /etc/resolv.conf 的符號連結目標</0> <0>停止 DNSStubListener重新載入 systemd 已解析的服務)</0>",
"autofix_warning_list": "它將執行這些任務:<0>撤銷系統 DNSStubListener</0> <0>設定 DNS 伺服器位址為 127.0.0.1</0> <0>用 /run/systemd/resolve/resolv.conf 取代 /etc/resolv.conf 的符號連結目標</0> <0>停止 DNSStubListener重新載入 systemd-resolved 服務)</0>",
"autofix_warning_result": "因此,預設下,來自您的系統之所有的 DNS 請求將被 AdGuard Home 處理。",
"tags_title": "標記",
"tags_desc": "您可選擇對應該用戶端的標記。標記可被包括在過濾規則中並允許您更準確地套用它們。<0>了解更多</0>",
@@ -566,7 +567,7 @@
"check_reason": "原因:{{reason}}",
"check_service": "服務名稱:{{service}}",
"service_name": "服務名稱",
"check_not_found": "未在您的過濾器中被找到",
"check_not_found": "未在您的過濾器清單中被找到",
"client_confirm_block": "您確定您想要封鎖該用戶端 \"{{ip}}\" 嗎?",
"client_confirm_unblock": "您確定您想要解除封鎖該用戶端 \"{{ip}}\" 嗎?",
"client_blocked": "用戶端 \"{{ip}}\" 被成功地封鎖",
@@ -588,7 +589,7 @@
"show_whitelisted_responses": "已允許的",
"show_processed_responses": "已處理的",
"blocked_safebrowsing": "被安全瀏覽封鎖",
"blocked_adult_websites": "已封鎖的成人網站",
"blocked_adult_websites": "被家長控制封鎖",
"blocked_threats": "已封鎖的威脅",
"allowed": "已允許的",
"filtered": "受過濾的",
@@ -613,7 +614,7 @@
"filter_category_regional": "區域性的",
"filter_category_other": "其它的",
"filter_category_general_desc": "封鎖大多數朝向裝置的追蹤和廣告之清單",
"filter_category_security_desc": "專門地封鎖惡意、網路釣魚和詐騙的網域之清單",
"filter_category_security_desc": "專門地旨在封鎖惡意、網路釣魚和詐騙的網域之清單",
"filter_category_regional_desc": "專注於區域性的廣告和追蹤伺服器之清單",
"filter_category_other_desc": "其它的封鎖清單",
"setup_config_to_enable_dhcp_server": "設置配置以啟用 DHCP 伺服器",
@@ -625,7 +626,7 @@
"last_rule_in_allowlist": "無法禁止此用戶端,因為排除 “{{disallowed_rule}}” 規則將禁用“已允許用戶端”的清單。",
"experimental": "實驗性的",
"use_saved_key": "使用該先前已儲存的金鑰",
"parental_control": "家長控",
"parental_control": "家長控",
"safe_browsing": "安全瀏覽",
"served_from_cache": "{{value}} <i>(由快取提供)</i>"
}

View File

@@ -13,7 +13,7 @@ import {
STATUS_RESPONSE,
SETTINGS_NAMES,
FORM_NAME,
GETTING_STARTED_LINK,
MANUAL_UPDATE_LINK,
} from '../helpers/constants';
import { areEqualVersions } from '../helpers/version';
import { getTlsStatus } from './encryption';
@@ -193,7 +193,7 @@ export const getUpdate = () => async (dispatch, getState) => {
const handleRequestError = () => {
const options = {
components: {
a: <a href={GETTING_STARTED_LINK} target="_blank"
a: <a href={MANUAL_UPDATE_LINK} target="_blank"
rel="noopener noreferrer" />,
},
};

View File

@@ -4,7 +4,7 @@ import { Trans, withTranslation } from 'react-i18next';
import ReactTable from 'react-table';
import { MODAL_TYPE } from '../../../helpers/constants';
import { splitByNewLine, countClientsStatistics } from '../../../helpers/helpers';
import { splitByNewLine, countClientsStatistics, sortIp } from '../../../helpers/helpers';
import Card from '../../ui/Card';
import Modal from './Modal';
import CellWrap from '../../ui/CellWrap';
@@ -106,6 +106,7 @@ class ClientsTable extends Component {
</div>
);
},
sortMethod: sortIp,
},
{
Header: this.props.t('table_name'),

View File

@@ -1,8 +1,10 @@
import React from 'react';
import { Trans } from 'react-i18next';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import Topline from './Topline';
import { getUpdate } from '../../actions';
import { MANUAL_UPDATE_LINK } from '../../helpers/constants';
const UpdateTopline = () => {
const {
@@ -29,16 +31,27 @@ const UpdateTopline = () => {
>
update_announcement
</Trans>
{canAutoUpdate
&& <button
type="button"
className="btn btn-sm btn-primary ml-3"
onClick={handleUpdate}
disabled={processingUpdate}
>
<Trans>update_now</Trans>
</button>
}
&nbsp;
{canAutoUpdate ? (
<button
type="button"
className="btn btn-sm btn-primary ml-3"
onClick={handleUpdate}
disabled={processingUpdate}
>
<Trans>update_now</Trans>
</button>
) : (
<Trans components={{
a: (
<a href={MANUAL_UPDATE_LINK} target="_blank" rel="noopener noreferrer" key="0">
Link
</a>
),
}}>
manual_update
</Trans>
)}
</>
</Topline>;
};

View File

@@ -13,6 +13,12 @@ const Version = () => {
checkUpdateFlag,
} = useSelector((state) => state?.dashboard ?? {}, shallowEqual);
const {
dnsVersion: installDnsVersion,
} = useSelector((state) => state?.install ?? {}, shallowEqual);
const version = dnsVersion || installDnsVersion;
const onClick = () => {
dispatch(getVersion(true));
};
@@ -20,11 +26,12 @@ const Version = () => {
return (
<div className="version">
<div className="version__text">
{dnsVersion
&& <>
<Trans>version</Trans>:&nbsp;
<span className="version__value" title={dnsVersion}>{dnsVersion}</span>
</>}
{version && (
<>
<Trans>version</Trans>:&nbsp;
<span className="version__value" title={version}>{version}</span>
</>
)}
{checkUpdateFlag && <button
type="button"
className="btn btn-icon btn-icon-sm btn-outline-primary btn-sm ml-2"

View File

@@ -58,7 +58,7 @@ export const REPOSITORY = {
export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html';
export const PORT_53_FAQ_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#bindinuse';
export const UPSTREAM_CONFIGURATION_WIKI_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#upstreams';
export const GETTING_STARTED_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update';
export const MANUAL_UPDATE_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#manual-update';
export const FILTERS_RELATIVE_LINK = '#filters';

View File

@@ -754,8 +754,10 @@ const getAddressesComparisonBytes = (item) => {
*/
export const sortIp = (a, b) => {
try {
const comparisonBytesA = getAddressesComparisonBytes(a);
const comparisonBytesB = getAddressesComparisonBytes(b);
const comparisonBytesA = Array.isArray(a)
? getAddressesComparisonBytes(a[0]) : getAddressesComparisonBytes(a);
const comparisonBytesB = Array.isArray(b)
? getAddressesComparisonBytes(b[0]) : getAddressesComparisonBytes(b);
for (let i = 0; i < comparisonBytesA.length; i += 1) {
const byteA = comparisonBytesA[i];

View File

@@ -12,13 +12,19 @@ const install = handleActions({
[actions.getDefaultAddressesRequest]: (state) => ({ ...state, processingDefault: true }),
[actions.getDefaultAddressesFailure]: (state) => ({ ...state, processingDefault: false }),
[actions.getDefaultAddressesSuccess]: (state, { payload }) => {
const { interfaces } = payload;
const { interfaces, version } = payload;
const web = { ...state.web, port: payload.web_port };
const dns = { ...state.dns, port: payload.dns_port };
const newState = {
...state, web, dns, interfaces, processingDefault: false,
...state,
web,
dns,
interfaces,
processingDefault: false,
dnsVersion: version,
};
return newState;
},
@@ -64,6 +70,7 @@ const install = handleActions({
error: '',
},
interfaces: {},
dnsVersion: '',
});
export default combineReducers({

View File

@@ -28,11 +28,7 @@ const queryLogs = handleActions(
};
},
[actions.setLogsFilterRequest]: (state, { payload }) => {
const { filter } = payload;
return { ...state, filter };
},
[actions.setLogsFilterRequest]: (state, { payload }) => ({ ...state, filter: payload }),
[actions.getLogsRequest]: (state) => ({ ...state, processingGetLogs: true }),
[actions.getLogsFailure]: (state) => ({ ...state, processingGetLogs: false }),

72
go.mod
View File

@@ -1,42 +1,66 @@
module github.com/AdguardTeam/AdGuardHome
go 1.16
go 1.17
require (
github.com/AdguardTeam/dnsproxy v0.39.13
github.com/AdguardTeam/golibs v0.10.3
github.com/AdguardTeam/urlfilter v0.15.1
github.com/AdguardTeam/dnsproxy v0.41.1
github.com/AdguardTeam/golibs v0.10.4
github.com/AdguardTeam/urlfilter v0.15.2
github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.2.2
github.com/ameshkov/dnscrypt/v2 v2.2.3
github.com/digineo/go-ipset/v2 v2.2.1
github.com/fsnotify/fsnotify v1.4.9
github.com/go-ping/ping v0.0.0-20210506233800-ff8be3320020
github.com/google/go-cmp v0.5.5
github.com/fsnotify/fsnotify v1.5.1
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534
github.com/google/go-cmp v0.5.6
github.com/google/gopacket v1.1.19
github.com/google/renameio v1.0.1
github.com/insomniacslk/dhcp v0.0.0-20210310193751-cfd4d47082c2
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489
github.com/kardianos/service v1.2.0
github.com/lucas-clemente/quic-go v0.21.1
github.com/lucas-clemente/quic-go v0.25.0
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7
github.com/mdlayher/netlink v1.4.0
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf
github.com/miekg/dns v1.1.43
github.com/mdlayher/netlink v1.5.0
github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b
github.com/miekg/dns v1.1.45
github.com/satori/go.uuid v1.2.0
github.com/stretchr/testify v1.7.0
github.com/ti-mo/netfilter v0.4.0
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v2 v2.4.0
howett.net/plist v0.0.0-20201203080718-1454fab16a06
howett.net/plist v1.0.0
)
require github.com/stretchr/objx v0.1.1 // indirect
// TODO(e.burkov): Get rid of the fork in v0.108.0.
replace github.com/insomniacslk/dhcp => github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf
// TODO(a.garipov): Return to the main repo once miekg/dns#1317 is merged.
replace github.com/miekg/dns => github.com/ameshkov/dns v1.1.32-0.20211214123418-7a5e0dc5f1b0
require (
github.com/BurntSushi/toml v0.4.1 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
github.com/ameshkov/dnsstamps v1.0.3 // indirect
github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect
github.com/mdlayher/socket v0.1.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.1.1 // indirect
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.8 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
honnef.co/go/tools v0.2.2 // indirect
)

179
go.sum
View File

@@ -7,20 +7,19 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf h1:gc042VRSIRSUzZ+Px6xQCRWNJZTaPkomisDfUZmoFNk=
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI=
github.com/AdguardTeam/dnsproxy v0.39.13 h1:7YM5Mr4EpFZ8UO4/4xd6zBG3lZ6AzZO6Xq29Cr4ydOY=
github.com/AdguardTeam/dnsproxy v0.39.13/go.mod h1:g7zjF1TWpKNeDVh6h3YrjQN8565zsWRd7zo++C/935c=
github.com/AdguardTeam/dnsproxy v0.41.1 h1:sDWami83ZNp0XNdWsLECwIX/hPI5UnVrotRtPnrgDuo=
github.com/AdguardTeam/dnsproxy v0.41.1/go.mod h1:PZ9l22h3Er+5mxFQB7oHZMTvx+aa9R6LbzA/ikXQlS0=
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
github.com/AdguardTeam/golibs v0.9.2/go.mod h1:fCAMwPBJ8S7YMYbTWvYS+eeTLblP5E04IDtNAo7y7IY=
github.com/AdguardTeam/golibs v0.10.3 h1:FBgk17zf35ESVWQKIqEUiqqB2bDaCBC8X5vMU760yB4=
github.com/AdguardTeam/golibs v0.10.3/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
github.com/AdguardTeam/golibs v0.10.4 h1:TMBkablZC0IZOpRgg9fzAKlxxNhSN2YJq7qbgtuZ7PQ=
github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
github.com/AdguardTeam/urlfilter v0.15.1 h1:dP6S7J6eFAk8MN4IDpUq2fZoBo8K8fmc6pXpxNIv84M=
github.com/AdguardTeam/urlfilter v0.15.1/go.mod h1:EwXwrYhowP7bedqmOrmKKmQtpBYFyDNEBFQ+lxdUgQU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/AdguardTeam/urlfilter v0.15.2 h1:LZGgrm4l4Ys9eAqB+UUmZfiC6vHlDlYFhx0WXqo6LtQ=
github.com/AdguardTeam/urlfilter v0.15.2/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
@@ -29,10 +28,8 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmH
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
github.com/ameshkov/dns v1.1.32-0.20211214123418-7a5e0dc5f1b0 h1:a6ca3WlDG4zvUWqVFpVu48b9NZJ0fUFlRhiZKKkq+aw=
github.com/ameshkov/dns v1.1.32-0.20211214123418-7a5e0dc5f1b0/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/ameshkov/dnscrypt/v2 v2.2.2 h1:lxtS1iSA2EjTOMToSi+2+rwspNA+b/wG5/JpccvE9CU=
github.com/ameshkov/dnscrypt/v2 v2.2.2/go.mod h1:+8SbPbVXpxxcUsgGi8eodkqWPo1MyNHxKYC8hDpqLSo=
github.com/ameshkov/dnscrypt/v2 v2.2.3 h1:X9UP5AHtwp46Ji+sGFfF/1Is6OPI/SjxLqhKpx0P5UI=
github.com/ameshkov/dnscrypt/v2 v2.2.3/go.mod h1:xJB9cE1/GF+NB6EEQqRlkoa4bjcV2w7VYn1G+zVq7Bs=
github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
@@ -44,6 +41,8 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -56,17 +55,20 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
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-20210506233800-ff8be3320020 h1:mdi6AbCEoKCA1xKCmp7UtRB5fvGFlP92PvlhxgdvXEw=
github.com/go-ping/ping v0.0.0-20210506233800-ff8be3320020/go.mod h1:KmHOjTUmJh/l04ukqPoBWPEZr9jwN05h5NXQl5C+DyY=
github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
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-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=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
@@ -83,6 +85,9 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -90,8 +95,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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=
@@ -100,6 +106,9 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -108,10 +117,11 @@ 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-20211214070828-5297eed8f489 h1:jhdHqd7DxBrzfuFSoPxjD6nUVaV/1RIn9aHA0WCf/as=
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489/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/joomcode/errorx v1.0.3 h1:3e1mi0u7/HTPNdg6d6DYyKGBhA5l9XpsfuVE29NxnWw=
github.com/joomcode/errorx v1.0.3/go.mod h1:eQzdtdlNyN7etw6YCS4W4+lu442waxZYw5yvz0ULrRo=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
@@ -121,8 +131,10 @@ github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN
github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs=
github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA=
github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b h1:c3NTyLNozICy8B4mlMXemD3z/gXgQzVXZS/HqT+i3do=
github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U=
github.com/jsimonetti/rtnetlink v0.0.0-20210525051524-4cc836578190/go.mod h1:NmKSdU4VGSiv1bMsdqNALI4RSvvjtz65tTMCnD05qLo=
github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786 h1:N527AHMa793TP5z5GNAn/VLPzlc0ewzWdeP/25gDfgQ=
github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786/go.mod h1:v4hqbTdfQngbVSZJVWUhGE/lbTFf9jb+ygmNUDQMuOs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -130,27 +142,31 @@ github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB
github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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.21.1 h1:uuhCcu885TE9u/piPYMChI/yqA1lXfaLUEx8uCMxf8w=
github.com/lucas-clemente/quic-go v0.21.1/go.mod h1:U9kFi5LKbNIlU30dkuM9vxmTxWq4Bvzee/MjBI+07UA=
github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0=
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls-go1-15 v0.1.4 h1:RehYMOyRW8hPVEja1KBVsFVNSm35Jj9Mvs5yNoZZ28A=
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
github.com/marten-seemann/qtls-go1-16 v0.1.3 h1:XEZ1xGorVy9u+lJq+WXNE+hiqRYLNvJGYmwfwKQN2gU=
github.com/marten-seemann/qtls-go1-16 v0.1.3/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.0-beta.1.2 h1:SficYjyOthSrliKI+EaFuXS6HqSsX3dkY9AqxAAjBjw=
github.com/marten-seemann/qtls-go1-17 v0.1.0-beta.1.2/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco=
github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM=
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY=
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
github.com/mdlayher/ethtool v0.0.0-20211028163843-288d040e9d60 h1:tHdB+hQRHU10CfcK0furo6rSNgZ38JT8uPh70c/pFD8=
github.com/mdlayher/ethtool v0.0.0-20211028163843-288d040e9d60/go.mod h1:aYbhishWc4Ai3I2U4Gaa2n3kHWSwzme6EsG/46HRQbE=
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
github.com/mdlayher/netlink v0.0.0-20190313131330-258ea9dff42c/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
@@ -163,28 +179,45 @@ github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klX
github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU=
github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU=
github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys=
github.com/mdlayher/netlink v1.4.0 h1:n3ARR+Fm0dDv37dj5wSWZXDKcy+U0zwcXS3zKMnSiT0=
github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8=
github.com/mdlayher/netlink v1.4.1/go.mod h1:e4/KuJ+s8UhfUpO9z00/fDZZmhSrs+oxyqAS9cNgn6Q=
github.com/mdlayher/netlink v1.5.0 h1:r4fa439+SsMarM0rMONU3iSshSV3ArVqJl6H/zjrhh4=
github.com/mdlayher/netlink v1.5.0/go.mod h1:1Kr8BBFxGyUyNmztC9WLOayqYVAd2wsgOZm18nqGuzQ=
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-20210412142147-51b895745faf h1:InctQoB89TIkmgIFQeIL4KXNvWc1iebQXdZggqPSwL8=
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf/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/socket v0.0.0-20210307095302-262dc9984e00/go.mod h1:GAFlyu4/XV68LkQKYzKhIo/WW7j3Zi0YRAz/BOoanUc=
github.com/mdlayher/socket v0.0.0-20211007213009-516dcbdf0267/go.mod h1:nFZ1EtZYK8Gi/k6QNu7z7CgO20i/4ExeQswwWuPmG/g=
github.com/mdlayher/socket v0.1.0/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
github.com/mdlayher/socket v0.1.1 h1:q3uOGirUPfAV2MUoaC7BavjQ154J7+JOkTWyiV+intI=
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
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.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
github.com/miekg/dns v1.1.45/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=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
@@ -246,11 +279,15 @@ github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/u-root/u-root v7.0.0+incompatible h1:u+KSS04pSxJGI5E7WE4Bs9+Zd75QjFv+REkjy/aoAc8=
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 h1:XMAtQHwKjWHIRwg+8Nj/rzUomQY1q6cM3ncA0wP8GU4=
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
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.0/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=
@@ -263,17 +300,18 @@ 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-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
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.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -288,24 +326,34 @@ golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210908191846-a5e095526f91/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/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-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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=
@@ -316,6 +364,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -332,9 +381,9 @@ golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -347,23 +396,35 @@ golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/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=
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3 h1:3Ad41xy2WCESpufXwgs7NpDSu+vjxqLt2UFqUV+20bI=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
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-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -382,10 +443,15 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
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=
@@ -413,6 +479,9 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
@@ -423,6 +492,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXL
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -431,13 +501,16 @@ 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-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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=
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=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
howett.net/plist v0.0.0-20201203080718-1454fab16a06 h1:QDxUo/w2COstK1wIBYpzQlHX/NqaQTcf9jyz347nI58=
howett.net/plist v0.0.0-20201203080718-1454fab16a06/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

75
internal/aghalg/aghalg.go Normal file
View File

@@ -0,0 +1,75 @@
// Package aghalg contains common generic algorithms and data structures.
//
// TODO(a.garipov): Update to use type parameters in Go 1.18.
package aghalg
import (
"fmt"
"sort"
)
// 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{}
// UniqChecker allows validating uniqueness of comparable items.
type UniqChecker map[comparable]int64
// Add adds a value to the validator. v must not be nil.
func (uc UniqChecker) Add(elems ...comparable) {
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))
for elem, num := range uc {
merged[elem] += num
}
for elem, num := range other {
merged[elem] += num
}
return merged
}
// 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
for elem, num := range uc {
if num > 1 {
dup = append(dup, elem)
}
}
if len(dup) == 0 {
return nil
}
if isBefore != nil {
sort.Slice(dup, func(i, j int) (less bool) {
return isBefore(dup[i], dup[j])
})
}
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)
}

View File

@@ -19,7 +19,8 @@ import (
"github.com/insomniacslk/dhcp/iana"
)
// defaultDiscoverTime is the
// defaultDiscoverTime is the default timeout of checking another DHCP server
// response.
const defaultDiscoverTime = 3 * time.Second
func checkOtherDHCP(ifaceName string) (ok4, ok6 bool, err4, err6 error) {
@@ -110,7 +111,7 @@ func discover4(iface *net.Interface, dstAddr *net.UDPAddr, hostname string) (ok
// is spoiled.
//
// It's also known that listening on the specified interface's address
// ignores broadcasted packets when reading.
// ignores broadcast packets when reading.
var c net.PacketConn
if c, err = listenPacketReusable(iface.Name, "udp4", ":68"); err != nil {
return false, fmt.Errorf("couldn't listen on :68: %w", err)

View File

@@ -46,13 +46,8 @@ type requestMatcher struct {
}
// MatchRequest processes the request rewriting hostnames and addresses read
// from the operating system's hosts files.
//
// res is nil for any request having not an A/AAAA or PTR type. Results
// containing CNAME information may be queried again with the same question type
// and the returned CNAME for Host field of request. Results are guaranteed to
// be direct, i.e. any returned CNAME resolves into actual address like an alias
// in hosts does, see man hosts (5).
// from the operating system's hosts files. res is nil for any request having
// not an A/AAAA or PTR type, see man 5 hosts.
//
// It's safe for concurrent use.
func (rm *requestMatcher) MatchRequest(
@@ -72,7 +67,11 @@ func (rm *requestMatcher) MatchRequest(
}
// Translate returns the source hosts-syntax rule for the generated dnsrewrite
// rule or an empty string if the last doesn't exist.
// rule or an empty string if the last doesn't exist. The returned rules are in
// a processed format like:
//
// ip host1 host2 ...
//
func (rm *requestMatcher) Translate(rule string) (hostRule string) {
rm.stateLock.RLock()
defer rm.stateLock.RUnlock()
@@ -179,7 +178,7 @@ func NewHostsContainer(
return nil, fmt.Errorf("adding path: %w", err)
}
log.Debug("%s: file %q expected to exist but doesn't", hostsContainerPref, p)
log.Debug("%s: %s is expected to exist but doesn't", hostsContainerPref, p)
}
}
@@ -228,8 +227,9 @@ func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error)
return patterns, nil
}
// handleEvents concurrently handles the events. It closes the update channel
// of HostsContainer when finishes. Used to be called within a goroutine.
// handleEvents concurrently handles the file system events. It closes the
// update channel of HostsContainer when finishes. It's used to be called
// within a separate goroutine.
func (hc *HostsContainer) handleEvents() {
defer log.OnPanic(fmt.Sprintf("%s: handling events", hostsContainerPref))
@@ -257,27 +257,23 @@ func (hc *HostsContainer) handleEvents() {
// hostsParser is a helper type to parse rules from the operating system's hosts
// file. It exists for only a single refreshing session.
type hostsParser struct {
// rulesBuilder builds the resulting rulesBuilder list content.
// rulesBuilder builds the resulting rules list content.
rulesBuilder *strings.Builder
// translations maps generated $dnsrewrite rules to the hosts-translations
// rules.
// translations maps generated rules into actual hosts file lines.
translations map[string]string
// cnameSet prevents duplicating cname rules.
cnameSet *stringutil.Set
// table stores only the unique IP-hostname pairs. It's also sent to the
// updates channel afterwards.
table *netutil.IPMap
}
// newHostsParser creates a new *hostsParser with buffers of size taken from the
// previous parse.
func (hc *HostsContainer) newHostsParser() (hp *hostsParser) {
return &hostsParser{
rulesBuilder: &strings.Builder{},
// For A/AAAA and PTRs.
translations: make(map[string]string, hc.last.Len()*2),
cnameSet: stringutil.NewSet(),
translations: map[string]string{},
table: netutil.NewIPMap(hc.last.Len()),
}
}
@@ -286,9 +282,7 @@ func (hc *HostsContainer) newHostsParser() (hp *hostsParser) {
// never signs to stop walking and never returns any additional patterns.
//
// See man hosts(5).
func (hp *hostsParser) parseFile(
r io.Reader,
) (patterns []string, cont bool, err error) {
func (hp *hostsParser) parseFile(r io.Reader) (patterns []string, cont bool, err error) {
s := bufio.NewScanner(r)
for s.Scan() {
ip, hosts := hp.parseLine(s.Text())
@@ -326,6 +320,8 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
// Make sure that invalid hosts aren't turned into rules.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
//
// TODO(e.burkov): Investigate if hosts may contain DNS-SD domains.
err := netutil.ValidateDomainName(f)
if err != nil {
log.Error("%s: host %q is invalid, ignoring", hostsContainerPref, f)
@@ -339,90 +335,45 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
return ip, hosts
}
// Simple types of hosts in hosts database. Zero value isn't used to be able
// quizzaciously emulate nil with 0.
const (
_ = iota
hostAlias
hostMain
)
// add tries to add the ip-host pair. It returns:
//
// hostAlias if the host is not the first one added for the ip.
// hostMain if the host is the first one added for the ip.
// 0 if the ip-host pair has already been added.
//
func (hp *hostsParser) add(ip net.IP, host string) (hostType int) {
v, ok := hp.table.Get(ip)
switch hosts, _ := v.(*stringutil.Set); {
case ok && hosts.Has(host):
return 0
case hosts == nil:
hosts = stringutil.NewSet(host)
hp.table.Set(ip, hosts)
return hostMain
default:
hosts.Add(host)
return hostAlias
}
}
// addPair puts the pair of ip and host to the rules builder if needed. For
// each ip the first member of hosts will become the main one.
func (hp *hostsParser) addPairs(ip net.IP, hosts []string) {
// Put the rule in a preproccesed format like:
//
// ip host1 host2 ...
//
hostsLine := strings.Join(append([]string{ip.String()}, hosts...), " ")
var mainHost string
for _, host := range hosts {
switch hp.add(ip, host) {
case 0:
v, ok := hp.table.Get(ip)
if !ok {
// This ip is added at the first time.
v = stringutil.NewSet()
hp.table.Set(ip, v)
}
var set *stringutil.Set
set, ok = v.(*stringutil.Set)
if !ok {
log.Debug("%s: adding pairs: unexpected value type %T", hostsContainerPref, v)
return
}
processed := strings.Join(append([]string{ip.String()}, hosts...), " ")
for _, h := range hosts {
if set.Has(h) {
continue
case hostMain:
mainHost = host
added, addedPtr := hp.writeMainHostRule(host, ip)
hp.translations[added], hp.translations[addedPtr] = hostsLine, hostsLine
case hostAlias:
pair := fmt.Sprint(host, " ", mainHost)
if hp.cnameSet.Has(pair) {
continue
}
// Since the hostAlias couldn't be returned from add before the
// hostMain the mainHost shouldn't appear empty.
hp.writeAliasHostRule(host, mainHost)
hp.cnameSet.Add(pair)
}
log.Debug("%s: added ip-host pair %q-%q", hostsContainerPref, ip, host)
set.Add(h)
rule, rulePtr := hp.writeRules(h, ip)
hp.translations[rule], hp.translations[rulePtr] = processed, processed
log.Debug("%s: added ip-host pair %q-%q", hostsContainerPref, ip, h)
}
}
// writeAliasHostRule writes the CNAME rule for the alias-host pair into
// internal builders.
func (hp *hostsParser) writeAliasHostRule(alias, host string) {
const (
nl = "\n"
sc = ";"
rwSuccess = rules.MaskSeparator + "$dnsrewrite=NOERROR" + sc + "CNAME" + sc
constLen = len(rules.MaskStartURL) + len(rwSuccess) + len(nl)
)
hp.rulesBuilder.Grow(constLen + len(host) + len(alias))
stringutil.WriteToBuilder(hp.rulesBuilder, rules.MaskStartURL, alias, rwSuccess, host, nl)
}
// writeMainHostRule writes the actual rule for the qtype and the PTR for the
// writeRules writes the actual rule for the qtype and the PTR for the
// host-ip pair into internal builders.
func (hp *hostsParser) writeMainHostRule(host string, ip net.IP) (added, addedPtr string) {
func (hp *hostsParser) writeRules(host string, ip net.IP) (rule, rulePtr string) {
arpa, err := netutil.IPToReversedAddr(ip)
if err != nil {
return
return "", ""
}
const (
@@ -431,8 +382,8 @@ func (hp *hostsParser) writeMainHostRule(host string, ip net.IP) (added, addedPt
rwSuccess = "^$dnsrewrite=NOERROR;"
rwSuccessPTR = "^$dnsrewrite=NOERROR;PTR;"
modLen = len("||") + len(rwSuccess) + len(";")
modLenPTR = len("||") + len(rwSuccessPTR)
modLen = len(rules.MaskPipe) + len(rwSuccess) + len(";")
modLenPTR = len(rules.MaskPipe) + len(rwSuccessPTR)
)
var qtype string
@@ -449,32 +400,20 @@ func (hp *hostsParser) writeMainHostRule(host string, ip net.IP) (added, addedPt
ruleBuilder := &strings.Builder{}
ruleBuilder.Grow(modLen + len(host) + len(qtype) + len(ipStr))
stringutil.WriteToBuilder(
ruleBuilder,
"||",
host,
rwSuccess,
qtype,
";",
ipStr,
)
added = ruleBuilder.String()
stringutil.WriteToBuilder(ruleBuilder, rules.MaskPipe, host, rwSuccess, qtype, ";", ipStr)
rule = ruleBuilder.String()
ruleBuilder.Reset()
ruleBuilder.Grow(modLenPTR + len(arpa) + len(fqdn))
stringutil.WriteToBuilder(
ruleBuilder,
"||",
arpa,
rwSuccessPTR,
fqdn,
)
addedPtr = ruleBuilder.String()
stringutil.WriteToBuilder(ruleBuilder, rules.MaskPipe, arpa, rwSuccessPTR, fqdn)
hp.rulesBuilder.Grow(len(added) + len(addedPtr) + 2*len(nl))
stringutil.WriteToBuilder(hp.rulesBuilder, added, nl, addedPtr, nl)
rulePtr = ruleBuilder.String()
return added, addedPtr
hp.rulesBuilder.Grow(len(rule) + len(rulePtr) + 2*len(nl))
stringutil.WriteToBuilder(hp.rulesBuilder, rule, nl, rulePtr, nl)
return rule, rulePtr
}
// equalSet returns true if the internal hosts table just parsed equals target.
@@ -488,18 +427,20 @@ func (hp *hostsParser) equalSet(target *netutil.IPMap) (ok bool) {
return false
}
hp.table.Range(func(ip net.IP, val interface{}) (cont bool) {
v, hasIP := target.Get(ip)
hp.table.Range(func(ip net.IP, b interface{}) (cont bool) {
// ok is set to true if the target doesn't contain ip or if the
// appropriate hosts set isn't equal to the checked one, i.e. the maps
// have at least one disperancy.
ok = !hasIP || !v.(*stringutil.Set).Equal(val.(*stringutil.Set))
// appropriate hosts set isn't equal to the checked one.
if a, hasIP := target.Get(ip); !hasIP {
ok = true
} else if hosts, aok := a.(*stringutil.Set); aok {
ok = !hosts.Equal(b.(*stringutil.Set))
}
// Continue only if maps has no discrepancies.
return !ok
})
// Return true if every value from the IP map has no disperancies with the
// Return true if every value from the IP map has no discrepancies with the
// appropriate one from the target.
return !ok
}
@@ -544,7 +485,7 @@ func (hc *HostsContainer) refresh() (err error) {
}
if hp.equalSet(hc.last) {
log.Debug("%s: no updates detected", hostsContainerPref)
log.Debug("%s: no changes detected", hostsContainerPref)
return nil
}

View File

@@ -9,10 +9,12 @@ import (
"sync/atomic"
"testing"
"testing/fstest"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/AdguardTeam/urlfilter"
"github.com/AdguardTeam/urlfilter/rules"
"github.com/miekg/dns"
@@ -85,6 +87,7 @@ func TestNewHostsContainer(t *testing.T) {
return
}
testutil.CleanupAndRequireSuccess(t, hc.Close)
require.NoError(t, err)
require.NotNil(t, hc)
@@ -129,24 +132,13 @@ func TestNewHostsContainer(t *testing.T) {
})
}
func TestHostsContainer_Refresh(t *testing.T) {
knownIP := net.IP{127, 0, 0, 1}
func TestHostsContainer_refresh(t *testing.T) {
// TODO(e.burkov): Test the case with no actual updates.
const knownHost = "localhost"
const knownAlias = "hocallost"
ip := net.IP{127, 0, 0, 1}
ipStr := ip.String()
const dirname = "dir"
const filename1 = "file1"
const filename2 = "file2"
p1 := path.Join(dirname, filename1)
p2 := path.Join(dirname, filename2)
testFS := fstest.MapFS{
p1: &fstest.MapFile{
Data: []byte(strings.Join([]string{knownIP.String(), knownHost}, sp) + nl),
},
}
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}}
// event is a convenient alias for an empty struct{} to emit test events.
type event = struct{}
@@ -157,15 +149,16 @@ func TestHostsContainer_Refresh(t *testing.T) {
w := &aghtest.FSWatcher{
OnEvents: func() (e <-chan event) { return eventsCh },
OnAdd: func(name string) (err error) {
assert.Equal(t, dirname, name)
assert.Equal(t, "dir", name)
return nil
},
OnClose: func() (err error) { panic("not implemented") },
}
hc, err := NewHostsContainer(0, testFS, w, dirname)
hc, err := NewHostsContainer(0, testFS, w, "dir")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
checkRefresh := func(t *testing.T, wantHosts *stringutil.Set) {
upd, ok := <-hc.Upd()
@@ -174,102 +167,99 @@ func TestHostsContainer_Refresh(t *testing.T) {
assert.Equal(t, 1, upd.Len())
v, ok := upd.Get(knownIP)
v, ok := upd.Get(ip)
require.True(t, ok)
var hosts *stringutil.Set
hosts, ok = v.(*stringutil.Set)
var set *stringutil.Set
set, ok = v.(*stringutil.Set)
require.True(t, ok)
assert.True(t, hosts.Equal(wantHosts))
assert.True(t, set.Equal(wantHosts))
}
t.Run("initial_refresh", func(t *testing.T) {
checkRefresh(t, stringutil.NewSet(knownHost))
checkRefresh(t, stringutil.NewSet("hostname"))
})
testFS[p2] = &fstest.MapFile{
Data: []byte(strings.Join([]string{knownIP.String(), knownAlias}, sp) + nl),
}
eventsCh <- event{}
t.Run("second_refresh", func(t *testing.T) {
checkRefresh(t, stringutil.NewSet(knownHost, knownAlias))
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + ` alias` + nl)}
eventsCh <- event{}
checkRefresh(t, stringutil.NewSet("hostname", "alias"))
})
eventsCh <- event{}
t.Run("double_refresh", func(t *testing.T) {
// Make a change once.
testFS["dir/file1"] = &fstest.MapFile{Data: []byte(ipStr + ` alias` + nl)}
eventsCh <- event{}
t.Run("no_changes_refresh", func(t *testing.T) {
assert.Empty(t, hc.Upd())
// Require the changes are written.
require.Eventually(t, func() bool {
res, ok := hc.MatchRequest(urlfilter.DNSRequest{
Hostname: "hostname",
DNSType: dns.TypeA,
})
return !ok && res.DNSRewrites() == nil
}, 5*time.Second, time.Second/2)
// Make a change again.
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}
eventsCh <- event{}
// Require the changes are written.
require.Eventually(t, func() bool {
res, ok := hc.MatchRequest(urlfilter.DNSRequest{
Hostname: "hostname",
DNSType: dns.TypeA,
})
return !ok && res.DNSRewrites() != nil
}, 5*time.Second, time.Second/2)
assert.Len(t, hc.Upd(), 1)
})
}
func TestHostsContainer_PathsToPatterns(t *testing.T) {
const (
dir0 = "dir"
dir1 = "dir_1"
fn1 = "file_1"
fn2 = "file_2"
fn3 = "file_3"
fn4 = "file_4"
)
fp1 := path.Join(dir0, fn1)
fp2 := path.Join(dir0, fn2)
fp3 := path.Join(dir0, dir1, fn3)
gsfs := fstest.MapFS{
fp1: &fstest.MapFile{Data: []byte{1}},
fp2: &fstest.MapFile{Data: []byte{2}},
fp3: &fstest.MapFile{Data: []byte{3}},
"dir_0/file_1": &fstest.MapFile{Data: []byte{1}},
"dir_0/file_2": &fstest.MapFile{Data: []byte{2}},
"dir_0/dir_1/file_3": &fstest.MapFile{Data: []byte{3}},
}
testCases := []struct {
name string
wantErr error
want []string
paths []string
name string
paths []string
want []string
}{{
name: "no_paths",
wantErr: nil,
want: nil,
paths: nil,
name: "no_paths",
paths: nil,
want: nil,
}, {
name: "single_file",
wantErr: nil,
want: []string{fp1},
paths: []string{fp1},
name: "single_file",
paths: []string{"dir_0/file_1"},
want: []string{"dir_0/file_1"},
}, {
name: "several_files",
wantErr: nil,
want: []string{fp1, fp2},
paths: []string{fp1, fp2},
name: "several_files",
paths: []string{"dir_0/file_1", "dir_0/file_2"},
want: []string{"dir_0/file_1", "dir_0/file_2"},
}, {
name: "whole_dir",
wantErr: nil,
want: []string{path.Join(dir0, "*")},
paths: []string{dir0},
name: "whole_dir",
paths: []string{"dir_0"},
want: []string{"dir_0/*"},
}, {
name: "file_and_dir",
wantErr: nil,
want: []string{fp1, path.Join(dir0, dir1, "*")},
paths: []string{fp1, path.Join(dir0, dir1)},
name: "file_and_dir",
paths: []string{"dir_0/file_1", "dir_0/dir_1"},
want: []string{"dir_0/file_1", "dir_0/dir_1/*"},
}, {
name: "non-existing",
wantErr: nil,
want: nil,
paths: []string{path.Join(dir0, "file_3")},
name: "non-existing",
paths: []string{path.Join("dir_0", "file_3")},
want: nil,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
patterns, err := pathsToPatterns(gsfs, tc.paths)
if tc.wantErr != nil {
assert.ErrorIs(t, err, tc.wantErr)
return
}
require.NoError(t, err)
assert.Equal(t, tc.want, patterns)
@@ -290,93 +280,235 @@ func TestHostsContainer_PathsToPatterns(t *testing.T) {
})
}
func TestHostsContainer_Translate(t *testing.T) {
testdata := os.DirFS("./testdata")
stubWatcher := aghtest.FSWatcher{
OnEvents: func() (e <-chan struct{}) { return nil },
OnAdd: func(name string) (err error) { return nil },
OnClose: func() (err error) { panic("not implemented") },
}
hc, err := NewHostsContainer(0, testdata, &stubWatcher, "etc_hosts")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
testCases := []struct {
name string
rule string
wantTrans []string
}{{
name: "simplehost",
rule: "|simplehost^$dnsrewrite=NOERROR;A;1.0.0.1",
wantTrans: []string{"1.0.0.1", "simplehost"},
}, {
name: "hello",
rule: "|hello^$dnsrewrite=NOERROR;A;1.0.0.0",
wantTrans: []string{"1.0.0.0", "hello", "hello.world"},
}, {
name: "hello-alias",
rule: "|hello.world.again^$dnsrewrite=NOERROR;A;1.0.0.0",
wantTrans: []string{"1.0.0.0", "hello.world.again"},
}, {
name: "simplehost_v6",
rule: "|simplehost^$dnsrewrite=NOERROR;AAAA;::1",
wantTrans: []string{"::1", "simplehost"},
}, {
name: "hello_v6",
rule: "|hello^$dnsrewrite=NOERROR;AAAA;::",
wantTrans: []string{"::", "hello", "hello.world"},
}, {
name: "hello_v6-alias",
rule: "|hello.world.again^$dnsrewrite=NOERROR;AAAA;::",
wantTrans: []string{"::", "hello.world.again"},
}, {
name: "simplehost_ptr",
rule: "|1.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;simplehost.",
wantTrans: []string{"1.0.0.1", "simplehost"},
}, {
name: "hello_ptr",
rule: "|0.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;hello.",
wantTrans: []string{"1.0.0.0", "hello", "hello.world"},
}, {
name: "hello_ptr-alias",
rule: "|0.0.0.1.in-addr.arpa^$dnsrewrite=NOERROR;PTR;hello.world.again.",
wantTrans: []string{"1.0.0.0", "hello.world.again"},
}, {
name: "simplehost_ptr_v6",
rule: "|1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
"^$dnsrewrite=NOERROR;PTR;simplehost.",
wantTrans: []string{"::1", "simplehost"},
}, {
name: "hello_ptr_v6",
rule: "|0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
"^$dnsrewrite=NOERROR;PTR;hello.",
wantTrans: []string{"::", "hello", "hello.world"},
}, {
name: "hello_ptr_v6-alias",
rule: "|0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" +
"^$dnsrewrite=NOERROR;PTR;hello.world.again.",
wantTrans: []string{"::", "hello.world.again"},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := stringutil.NewSet(strings.Fields(hc.Translate(tc.rule))...)
assert.True(t, stringutil.NewSet(tc.wantTrans...).Equal(got))
})
}
}
func TestHostsContainer(t *testing.T) {
const listID = 1234
testdata := os.DirFS("./testdata")
nRewrites := func(t *testing.T, res *urlfilter.DNSResult, n int) (rws []*rules.DNSRewrite) {
t.Helper()
rewrites := res.DNSRewrites()
assert.Len(t, rewrites, n)
for _, rewrite := range rewrites {
require.Equal(t, listID, rewrite.FilterListID)
rw := rewrite.DNSRewrite
require.NotNil(t, rw)
rws = append(rws, rw)
}
return rws
}
testCases := []struct {
testTail func(t *testing.T, res *urlfilter.DNSResult)
name string
req urlfilter.DNSRequest
want []*rules.DNSRewrite
name string
req urlfilter.DNSRequest
}{{
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
Value: net.IPv4(1, 0, 0, 1),
RRType: dns.TypeA,
}, {
RCode: dns.RcodeSuccess,
Value: net.ParseIP("::1"),
RRType: dns.TypeAAAA,
}},
name: "simple",
req: urlfilter.DNSRequest{
Hostname: "simplehost",
DNSType: dns.TypeA,
},
testTail: func(t *testing.T, res *urlfilter.DNSResult) {
rws := nRewrites(t, res, 2)
v, ok := rws[0].Value.(net.IP)
require.True(t, ok)
assert.True(t, net.IP{1, 0, 0, 1}.Equal(v))
v, ok = rws[1].Value.(net.IP)
require.True(t, ok)
// It's ::1.
assert.True(t, net.IP(append((&[15]byte{})[:], byte(1))).Equal(v))
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
Value: net.IPv4(1, 0, 0, 0),
RRType: dns.TypeA,
}, {
RCode: dns.RcodeSuccess,
Value: net.ParseIP("::"),
RRType: dns.TypeAAAA,
}},
name: "hello_alias",
req: urlfilter.DNSRequest{
Hostname: "hello.world",
DNSType: dns.TypeA,
},
testTail: func(t *testing.T, res *urlfilter.DNSResult) {
assert.Equal(t, "hello", nRewrites(t, res, 1)[0].NewCNAME)
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
Value: net.IPv4(1, 0, 0, 0),
RRType: dns.TypeA,
}, {
RCode: dns.RcodeSuccess,
Value: net.ParseIP("::"),
RRType: dns.TypeAAAA,
}},
name: "other_line_alias",
req: urlfilter.DNSRequest{
Hostname: "hello.world.again",
DNSType: dns.TypeA,
},
}, {
want: []*rules.DNSRewrite{},
name: "hello_subdomain",
req: urlfilter.DNSRequest{
Hostname: "say.hello",
DNSType: dns.TypeA,
},
}, {
want: []*rules.DNSRewrite{},
name: "hello_alias_subdomain",
req: urlfilter.DNSRequest{
Hostname: "say.hello.world",
DNSType: dns.TypeA,
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
RRType: dns.TypeA,
Value: net.IPv4(1, 0, 0, 2),
}, {
RCode: dns.RcodeSuccess,
RRType: dns.TypeAAAA,
Value: net.ParseIP("::2"),
}},
name: "lots_of_aliases",
req: urlfilter.DNSRequest{
Hostname: "for.testing",
DNSType: dns.TypeA,
},
testTail: func(t *testing.T, res *urlfilter.DNSResult) {
assert.Equal(t, "a.whole", nRewrites(t, res, 1)[0].NewCNAME)
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
RRType: dns.TypePTR,
Value: "simplehost.",
}},
name: "reverse",
req: urlfilter.DNSRequest{
Hostname: "1.0.0.1.in-addr.arpa",
DNSType: dns.TypePTR,
},
testTail: func(t *testing.T, res *urlfilter.DNSResult) {
rws := nRewrites(t, res, 1)
assert.Equal(t, dns.TypePTR, rws[0].RRType)
assert.Equal(t, "simplehost.", rws[0].Value)
},
}, {
want: []*rules.DNSRewrite{},
name: "non-existing",
req: urlfilter.DNSRequest{
Hostname: "nonexisting",
DNSType: dns.TypeA,
},
testTail: func(t *testing.T, res *urlfilter.DNSResult) {
require.NotNil(t, res)
assert.Nil(t, res.DNSRewrites())
}, {
want: nil,
name: "bad_type",
req: urlfilter.DNSRequest{
Hostname: "1.0.0.1.in-addr.arpa",
DNSType: dns.TypeSRV,
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
RRType: dns.TypeA,
Value: net.IPv4(4, 2, 1, 6),
}, {
RCode: dns.RcodeSuccess,
RRType: dns.TypeAAAA,
Value: net.ParseIP("::42"),
}},
name: "issue_4216_4_6",
req: urlfilter.DNSRequest{
Hostname: "domain",
DNSType: dns.TypeA,
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
RRType: dns.TypeA,
Value: net.IPv4(7, 5, 3, 1),
}, {
RCode: dns.RcodeSuccess,
RRType: dns.TypeA,
Value: net.IPv4(1, 3, 5, 7),
}},
name: "issue_4216_4",
req: urlfilter.DNSRequest{
Hostname: "domain4",
DNSType: dns.TypeA,
},
}, {
want: []*rules.DNSRewrite{{
RCode: dns.RcodeSuccess,
RRType: dns.TypeAAAA,
Value: net.ParseIP("::13"),
}, {
RCode: dns.RcodeSuccess,
RRType: dns.TypeAAAA,
Value: net.ParseIP("::31"),
}},
name: "issue_4216_6",
req: urlfilter.DNSRequest{
Hostname: "domain6",
DNSType: dns.TypeAAAA,
},
}}
@@ -388,25 +520,39 @@ func TestHostsContainer(t *testing.T) {
hc, err := NewHostsContainer(listID, testdata, &stubWatcher, "etc_hosts")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
res, ok := hc.MatchRequest(tc.req)
require.False(t, ok)
if tc.want == nil {
assert.Nil(t, res)
return
}
require.NotNil(t, res)
tc.testTail(t, res)
rewrites := res.DNSRewrites()
require.Len(t, rewrites, len(tc.want))
for i, rewrite := range rewrites {
require.Equal(t, listID, rewrite.FilterListID)
rw := rewrite.DNSRewrite
require.NotNil(t, rw)
assert.Equal(t, tc.want[i], rw)
}
})
}
}
func TestUniqueRules_ParseLine(t *testing.T) {
const (
hostname = "localhost"
alias = "hocallost"
)
knownIP := net.IP{127, 0, 0, 1}
ip := net.IP{127, 0, 0, 1}
ipStr := ip.String()
testCases := []struct {
name string
@@ -415,39 +561,39 @@ func TestUniqueRules_ParseLine(t *testing.T) {
wantHosts []string
}{{
name: "simple",
line: strings.Join([]string{knownIP.String(), hostname}, sp),
wantIP: knownIP,
wantHosts: []string{"localhost"},
line: ipStr + ` hostname`,
wantIP: ip,
wantHosts: []string{"hostname"},
}, {
name: "aliases",
line: strings.Join([]string{knownIP.String(), hostname, alias}, sp),
wantIP: knownIP,
wantHosts: []string{"localhost", "hocallost"},
line: ipStr + ` hostname alias`,
wantIP: ip,
wantHosts: []string{"hostname", "alias"},
}, {
name: "invalid_line",
line: knownIP.String(),
line: ipStr,
wantIP: nil,
wantHosts: nil,
}, {
name: "invalid_line_hostname",
line: strings.Join([]string{knownIP.String(), "#" + hostname}, sp),
wantIP: knownIP,
line: ipStr + ` # hostname`,
wantIP: ip,
wantHosts: nil,
}, {
name: "commented_aliases",
line: strings.Join([]string{knownIP.String(), hostname, "#" + alias}, sp),
wantIP: knownIP,
wantHosts: []string{"localhost"},
line: ipStr + ` hostname # alias`,
wantIP: ip,
wantHosts: []string{"hostname"},
}, {
name: "whole_comment",
line: strings.Join([]string{"#", knownIP.String(), hostname}, sp),
line: `# ` + ipStr + ` hostname`,
wantIP: nil,
wantHosts: nil,
}, {
name: "partial_comment",
line: strings.Join([]string{knownIP.String(), hostname[:4] + "#" + hostname[4:]}, sp),
wantIP: knownIP,
wantHosts: []string{hostname[:4]},
line: ipStr + ` host#name`,
wantIP: ip,
wantHosts: []string{"host"},
}, {
name: "empty",
line: ``,
@@ -458,8 +604,8 @@ func TestUniqueRules_ParseLine(t *testing.T) {
for _, tc := range testCases {
hp := hostsParser{}
t.Run(tc.name, func(t *testing.T) {
ip, hosts := hp.parseLine(tc.line)
assert.True(t, tc.wantIP.Equal(ip))
got, hosts := hp.parseLine(tc.line)
assert.True(t, tc.wantIP.Equal(got))
assert.Equal(t, tc.wantHosts, hosts)
})
}

View File

@@ -8,8 +8,8 @@ import (
"github.com/AdguardTeam/golibs/log"
)
// IPVersion is a documentational alias for int. Use it when the integer means
// IP version.
// IPVersion is a alias for int for documentation purposes. Use it when the
// integer means IP version.
type IPVersion = int
// IP version constants.
@@ -25,6 +25,13 @@ type NetIface interface {
// IfaceIPAddrs returns the interface's IP addresses.
func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {
switch ipv {
case IPVersion4, IPVersion6:
// Go on.
default:
return nil, fmt.Errorf("invalid ip version %d", ipv)
}
addrs, err := iface.Addrs()
if err != nil {
return nil, err
@@ -41,20 +48,16 @@ func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {
continue
}
// Assume that net.(*Interface).Addrs can only return valid IPv4
// and IPv6 addresses. Thus, if it isn't an IPv4 address, it
// must be an IPv6 one.
switch ipv {
case IPVersion4:
if ip4 := ip.To4(); ip4 != nil {
// Assume that net.(*Interface).Addrs can only return valid IPv4 and
// IPv6 addresses. Thus, if it isn't an IPv4 address, it must be an
// IPv6 one.
ip4 := ip.To4()
if ipv == IPVersion4 {
if ip4 != nil {
ips = append(ips, ip4)
}
case IPVersion6:
if ip6 := ip.To4(); ip6 == nil {
ips = append(ips, ip)
}
default:
return nil, fmt.Errorf("invalid ip version %d", ipv)
} else if ip4 == nil {
ips = append(ips, ip)
}
}
@@ -67,7 +70,7 @@ func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {
//
// It makes up to maxAttempts attempts to get the addresses if there are none,
// each time using the provided backoff. Sometimes an interface needs a few
// seconds to really ititialize.
// seconds to really initialize.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/2304.
func IfaceDNSIPAddrs(
@@ -96,16 +99,16 @@ func IfaceDNSIPAddrs(
switch len(addrs) {
case 0:
// Don't return errors in case the users want to try and enable
// the DHCP server later.
// Don't return errors in case the users want to try and enable the DHCP
// server later.
t := time.Duration(n) * backoff
log.Error("dhcpv%d: no ip for iface after %d attempts and %s", ipv, n, t)
return nil, nil
case 1:
// Some Android devices use 8.8.8.8 if there is not a secondary
// DNS server. Fix that by setting the secondary DNS address to
// the same address.
// Some Android devices use 8.8.8.8 if there is not a secondary DNS
// server. Fix that by setting the secondary DNS address to the same
// address.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/1708.
log.Debug("dhcpv%d: setting secondary dns ip to itself", ipv)

View File

@@ -5,13 +5,15 @@ import (
"testing"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// fakeIface is a stub implementation of aghnet.NetIface to simplify testing.
type fakeIface struct {
addrs []net.Addr
err error
addrs []net.Addr
}
// Addrs implements the NetIface interface for *fakeIface.
@@ -33,61 +35,86 @@ func TestIfaceIPAddrs(t *testing.T) {
addr6 := &net.IPNet{IP: ip6}
testCases := []struct {
name string
iface NetIface
ipv IPVersion
want []net.IP
wantErr error
iface NetIface
name string
wantErrMsg string
want []net.IP
ipv IPVersion
}{{
name: "ipv4_success",
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
ipv: IPVersion4,
want: []net.IP{ip4},
wantErr: nil,
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
name: "ipv4_success",
wantErrMsg: "",
want: []net.IP{ip4},
ipv: IPVersion4,
}, {
name: "ipv4_success_with_ipv6",
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
ipv: IPVersion4,
want: []net.IP{ip4},
wantErr: nil,
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
name: "ipv4_success_with_ipv6",
wantErrMsg: "",
want: []net.IP{ip4},
ipv: IPVersion4,
}, {
name: "ipv4_error",
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
ipv: IPVersion4,
want: nil,
wantErr: errTest,
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
name: "ipv4_error",
wantErrMsg: errTest.Error(),
want: nil,
ipv: IPVersion4,
}, {
name: "ipv6_success",
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
ipv: IPVersion6,
want: []net.IP{ip6},
wantErr: nil,
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
name: "ipv6_success",
wantErrMsg: "",
want: []net.IP{ip6},
ipv: IPVersion6,
}, {
name: "ipv6_success_with_ipv4",
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
ipv: IPVersion6,
want: []net.IP{ip6},
wantErr: nil,
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
name: "ipv6_success_with_ipv4",
wantErrMsg: "",
want: []net.IP{ip6},
ipv: IPVersion6,
}, {
name: "ipv6_error",
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
ipv: IPVersion6,
want: nil,
wantErr: errTest,
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
name: "ipv6_error",
wantErrMsg: errTest.Error(),
want: nil,
ipv: IPVersion6,
}, {
iface: &fakeIface{addrs: nil, err: nil},
name: "bad_proto",
wantErrMsg: "invalid ip version 10",
want: nil,
ipv: IPVersion6 + IPVersion4,
}, {
iface: &fakeIface{addrs: []net.Addr{&net.IPAddr{IP: ip4}}, err: nil},
name: "ipaddr_v4",
wantErrMsg: "",
want: []net.IP{ip4},
ipv: IPVersion4,
}, {
iface: &fakeIface{addrs: []net.Addr{&net.IPAddr{IP: ip6, Zone: ""}}, err: nil},
name: "ipaddr_v6",
wantErrMsg: "",
want: []net.IP{ip6},
ipv: IPVersion6,
}, {
iface: &fakeIface{addrs: []net.Addr{&net.UnixAddr{}}, err: nil},
name: "non-ipv4",
wantErrMsg: "",
want: nil,
ipv: IPVersion4,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got, gotErr := IfaceIPAddrs(tc.iface, tc.ipv)
require.True(t, errors.Is(gotErr, tc.wantErr))
got, err := IfaceIPAddrs(tc.iface, tc.ipv)
testutil.AssertErrorMsg(t, tc.wantErrMsg, err)
assert.Equal(t, tc.want, got)
})
}
}
type waitingFakeIface struct {
addrs []net.Addr
err error
addrs []net.Addr
n int
}
@@ -116,11 +143,11 @@ func TestIfaceDNSIPAddrs(t *testing.T) {
addr6 := &net.IPNet{IP: ip6}
testCases := []struct {
name string
iface NetIface
ipv IPVersion
want []net.IP
wantErr error
name string
want []net.IP
ipv IPVersion
}{{
name: "ipv4_success",
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
@@ -169,12 +196,25 @@ func TestIfaceDNSIPAddrs(t *testing.T) {
ipv: IPVersion6,
want: []net.IP{ip6, ip6},
wantErr: nil,
}, {
name: "empty",
iface: &fakeIface{addrs: nil, err: nil},
ipv: IPVersion4,
want: nil,
wantErr: nil,
}, {
name: "many",
iface: &fakeIface{addrs: []net.Addr{addr4, addr4}},
ipv: IPVersion4,
want: []net.IP{ip4, ip4},
wantErr: nil,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got, gotErr := IfaceDNSIPAddrs(tc.iface, tc.ipv, 2, 0)
require.True(t, errors.Is(gotErr, tc.wantErr))
got, err := IfaceDNSIPAddrs(tc.iface, tc.ipv, 2, 0)
require.ErrorIs(t, err, tc.wantErr)
assert.Equal(t, tc.want, got)
})
}

View File

@@ -0,0 +1,44 @@
package aghnet
import (
"net"
"testing"
"github.com/AdguardTeam/golibs/netutil"
"github.com/stretchr/testify/assert"
)
func TestIPMut(t *testing.T) {
testIPs := []net.IP{{
127, 0, 0, 1,
}, {
192, 168, 0, 1,
}, {
8, 8, 8, 8,
}}
t.Run("nil_no_mut", func(t *testing.T) {
ipmut := NewIPMut(nil)
ips := netutil.CloneIPs(testIPs)
for i := range ips {
ipmut.Load()(ips[i])
assert.True(t, ips[i].Equal(testIPs[i]))
}
})
t.Run("not_nil_mut", func(t *testing.T) {
ipmut := NewIPMut(func(ip net.IP) {
for i := range ip {
ip[i] = 0
}
})
want := netutil.IPv4Zero()
ips := netutil.CloneIPs(testIPs)
for i := range ips {
ipmut.Load()(ips[i])
assert.True(t, ips[i].Equal(want))
}
})
}

View File

@@ -20,7 +20,12 @@ type IpsetManager interface {
//
// DOMAIN[,DOMAIN].../IPSET_NAME[,IPSET_NAME]...
//
// The error is of type *aghos.UnsupportedError if the OS is not supported.
// If ipsetConf is empty, msg and err are nil. The error is of type
// *aghos.UnsupportedError if the OS is not supported.
func NewIpsetManager(ipsetConf []string) (mgr IpsetManager, err error) {
if len(ipsetConf) == 0 {
return nil, nil
}
return newIpsetMgr(ipsetConf)
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/digineo/go-ipset/v2"
"github.com/mdlayher/netlink"
"github.com/ti-mo/netfilter"
"golang.org/x/sys/unix"
)
// How to test on a real Linux machine:
@@ -42,11 +43,17 @@ import (
// newIpsetMgr returns a new Linux ipset manager.
func newIpsetMgr(ipsetConf []string) (set IpsetManager, err error) {
dial := func(pf netfilter.ProtoFamily, conf *netlink.Config) (conn ipsetConn, err error) {
return ipset.Dial(pf, conf)
return newIpsetMgrWithDialer(ipsetConf, defaultDial)
}
// defaultDial is the default netfilter dialing function.
func defaultDial(pf netfilter.ProtoFamily, conf *netlink.Config) (conn ipsetConn, err error) {
conn, err = ipset.Dial(pf, conf)
if err != nil {
return nil, err
}
return newIpsetMgrWithDialer(ipsetConf, dial)
return conn, nil
}
// ipsetConn is the ipset conn interface.
@@ -103,8 +110,8 @@ func (m *ipsetMgr) dialNetfilter(conf *netlink.Config) (err error) {
// The kernel API does not actually require two sockets but package
// github.com/digineo/go-ipset does.
//
// TODO(a.garipov): Perhaps we can ditch package ipset altogether and
// just use packages netfilter and netlink.
// TODO(a.garipov): Perhaps we can ditch package ipset altogether and just
// use packages netfilter and netlink.
m.ipv4Conn, err = m.dial(netfilter.ProtoIPv4, conf)
if err != nil {
return fmt.Errorf("dialing v4: %w", err)
@@ -214,6 +221,14 @@ func newIpsetMgrWithDialer(ipsetConf []string, dial ipsetDialer) (mgr IpsetManag
err = m.dialNetfilter(&netlink.Config{})
if err != nil {
if errors.Is(err, unix.EPROTONOSUPPORT) {
// The implementation doesn't support this protocol version. Just
// issue a warning.
log.Info("ipset: dialing netfilter: warning: %s", err)
return nil, nil
}
return nil, fmt.Errorf("dialing netfilter: %w", err)
}

View File

@@ -42,8 +42,7 @@ func GatewayIP(ifaceName string) net.IP {
fields := strings.Fields(string(d))
// The meaningful "ip route" command output should contain the word
// "default" at first field and default gateway IP address at third
// field.
// "default" at first field and default gateway IP address at third field.
if len(fields) < 3 || fields[0] != "default" {
return nil
}
@@ -187,7 +186,8 @@ func GetSubnet(ifaceName string) *net.IPNet {
return nil
}
// CheckPort checks if the port is available for binding.
// CheckPort checks if the port is available for binding. network is expected
// to be one of "udp" and "tcp".
func CheckPort(network string, ip net.IP, port int) (err error) {
var c io.Closer
addr := netutil.IPPort{IP: ip, Port: port}.String()
@@ -200,7 +200,11 @@ func CheckPort(network string, ip net.IP, port int) (err error) {
return nil
}
return errors.WithDeferred(err, closePortChecker(c))
if err != nil {
return err
}
return closePortChecker(c)
}
// IsAddrInUse checks if err is about unsuccessful address binding.
@@ -213,28 +217,6 @@ func IsAddrInUse(err error) (ok bool) {
return isAddrInUse(sysErr)
}
// SplitHost is a wrapper for net.SplitHostPort for the cases when the hostport
// does not necessarily contain a port.
func SplitHost(hostport string) (host string, err error) {
host, _, err = net.SplitHostPort(hostport)
if err != nil {
// Check for the missing port error. If it is that error, just
// use the host as is.
//
// See the source code for net.SplitHostPort.
const missingPort = "missing port in address"
addrErr := &net.AddrError{}
if !errors.As(err, &addrErr) || addrErr.Err != missingPort {
return "", err
}
host = hostport
}
return host, nil
}
// CollectAllIfacesAddrs returns the slice of all network interfaces IP
// addresses without port number.
func CollectAllIfacesAddrs() (addrs []string, err error) {

View File

@@ -5,6 +5,8 @@ import (
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -13,12 +15,20 @@ func TestMain(m *testing.M) {
aghtest.DiscardLogOutput(m)
}
func TestGetValidNetInterfacesForWeb(t *testing.T) {
func TestGetInterfaceByIP(t *testing.T) {
ifaces, err := GetValidNetInterfacesForWeb()
require.NoErrorf(t, err, "cannot get net interfaces: %s", err)
require.NotEmpty(t, ifaces, "no net interfaces found")
require.NoError(t, err)
require.NotEmpty(t, ifaces)
for _, iface := range ifaces {
require.NotEmptyf(t, iface.Addresses, "no addresses found for %s", iface.Name)
t.Run(iface.Name, func(t *testing.T) {
require.NotEmpty(t, iface.Addresses)
for _, ip := range iface.Addresses {
ifaceName := GetInterfaceByIP(ip)
require.Equal(t, iface.Name, ifaceName)
}
})
}
}
@@ -69,3 +79,49 @@ func TestBroadcastFromIPNet(t *testing.T) {
})
}
}
func TestCheckPort(t *testing.T) {
t.Run("tcp_bound", func(t *testing.T) {
l, err := net.Listen("tcp", "127.0.0.1:")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, l.Close)
ipp := netutil.IPPortFromAddr(l.Addr())
require.NotNil(t, ipp)
require.NotNil(t, ipp.IP)
require.NotZero(t, ipp.Port)
err = CheckPort("tcp", ipp.IP, ipp.Port)
target := &net.OpError{}
require.ErrorAs(t, err, &target)
assert.Equal(t, "listen", target.Op)
})
t.Run("udp_bound", func(t *testing.T) {
conn, err := net.ListenPacket("udp", "127.0.0.1:")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, conn.Close)
ipp := netutil.IPPortFromAddr(conn.LocalAddr())
require.NotNil(t, ipp)
require.NotNil(t, ipp.IP)
require.NotZero(t, ipp.Port)
err = CheckPort("udp", ipp.IP, ipp.Port)
target := &net.OpError{}
require.ErrorAs(t, err, &target)
assert.Equal(t, "listen", target.Op)
})
t.Run("bad_network", func(t *testing.T) {
err := CheckPort("bad_network", nil, 0)
assert.NoError(t, err)
})
t.Run("can_bind", func(t *testing.T) {
err := CheckPort("udp", net.IP{0, 0, 0, 0}, 0)
assert.NoError(t, err)
})
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/AdguardTeam/golibs/errors"
)
// closePortChecker closes c. c must be non-nil.
func closePortChecker(c io.Closer) (err error) {
return c.Close()
}

View File

@@ -25,6 +25,7 @@ func ifaceSetStaticIP(string) (err error) {
return aghos.Unsupported("setting static ip")
}
// closePortChecker closes c. c must be non-nil.
func closePortChecker(c io.Closer) (err error) {
if err = c.Close(); err != nil {
return err

View File

@@ -12,9 +12,27 @@
1.0.0.3 *
1.0.0.4 *.com
# See https://github.com/AdguardTeam/AdGuardHome/issues/4079.
1.0.0.0 hello.world.again
# Duplicates of a main host and an alias.
1.0.0.1 simplehost
1.0.0.0 hello.world
# Same for IPv6.
::1 simplehost
:: hello hello.world
::2 a.whole lot.of aliases for.testing
::3 *
::4 *.com
:: hello.world.again
::1 simplehost
:: hello.world
# See https://github.com/AdguardTeam/AdGuardHome/issues/4216.
4.2.1.6 domain domain.alias
::42 domain.alias domain
1.3.5.7 domain4 domain4.alias
7.5.3.1 domain4.alias domain4
::13 domain6 domain6.alias
::31 domain6.alias domain6

View File

@@ -20,17 +20,19 @@ func DiscardLogOutput(m *testing.M) {
// ReplaceLogWriter moves logger output to w and uses Cleanup method of t to
// revert changes.
func ReplaceLogWriter(t *testing.T, w io.Writer) {
stdWriter := log.Writer()
t.Cleanup(func() {
log.SetOutput(stdWriter)
})
func ReplaceLogWriter(t testing.TB, w io.Writer) {
t.Helper()
prev := log.Writer()
t.Cleanup(func() { log.SetOutput(prev) })
log.SetOutput(w)
}
// ReplaceLogLevel sets logging level to l and uses Cleanup method of t to
// revert changes.
func ReplaceLogLevel(t *testing.T, l log.Level) {
func ReplaceLogLevel(t testing.TB, l log.Level) {
t.Helper()
switch l {
case log.INFO, log.DEBUG, log.ERROR:
// Go on.
@@ -38,9 +40,7 @@ func ReplaceLogLevel(t *testing.T, l log.Level) {
t.Fatalf("wrong l value (must be one of %v, %v, %v)", log.INFO, log.DEBUG, log.ERROR)
}
stdLevel := log.GetLevel()
t.Cleanup(func() {
log.SetLevel(stdLevel)
})
prev := log.GetLevel()
t.Cleanup(func() { log.SetLevel(prev) })
log.SetLevel(l)
}

View File

@@ -11,10 +11,10 @@ import (
"github.com/miekg/dns"
)
// TestUpstream is a mock of real upstream.
type TestUpstream struct {
// Upstream is a mock implementation of upstream.Upstream.
type Upstream struct {
// CName is a map of hostname to canonical name.
CName map[string]string
CName map[string][]string
// IPv4 is a map of hostname to IPv4.
IPv4 map[string][]net.IP
// IPv6 is a map of hostname to IPv6.
@@ -25,78 +25,45 @@ type TestUpstream struct {
Addr string
}
// Exchange implements upstream.Upstream interface for *TestUpstream.
// Exchange implements the upstream.Upstream interface for *Upstream.
//
// TODO(a.garipov): Split further into handlers.
func (u *TestUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
resp = &dns.Msg{}
resp.SetReply(m)
func (u *Upstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
resp = new(dns.Msg).SetReply(m)
if len(m.Question) == 0 {
return nil, fmt.Errorf("question should not be empty")
}
name := m.Question[0].Name
if cname, ok := u.CName[name]; ok {
ans := &dns.CNAME{
Hdr: dns.RR_Header{
Name: name,
Rrtype: dns.TypeCNAME,
},
q := m.Question[0]
name := q.Name
for _, cname := range u.CName[name] {
resp.Answer = append(resp.Answer, &dns.CNAME{
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME},
Target: cname,
}
resp.Answer = append(resp.Answer, ans)
})
}
rrType := m.Question[0].Qtype
qtype := q.Qtype
hdr := dns.RR_Header{
Name: name,
Rrtype: rrType,
Rrtype: qtype,
}
var names []string
var ips []net.IP
switch m.Question[0].Qtype {
switch qtype {
case dns.TypeA:
ips = u.IPv4[name]
for _, ip := range u.IPv4[name] {
resp.Answer = append(resp.Answer, &dns.A{Hdr: hdr, A: ip})
}
case dns.TypeAAAA:
ips = u.IPv6[name]
for _, ip := range u.IPv6[name] {
resp.Answer = append(resp.Answer, &dns.AAAA{Hdr: hdr, AAAA: ip})
}
case dns.TypePTR:
names = u.Reverse[name]
}
for _, ip := range ips {
var ans dns.RR
if rrType == dns.TypeA {
ans = &dns.A{
Hdr: hdr,
A: ip,
}
resp.Answer = append(resp.Answer, ans)
continue
for _, name := range u.Reverse[name] {
resp.Answer = append(resp.Answer, &dns.PTR{Hdr: hdr, Ptr: name})
}
ans = &dns.AAAA{
Hdr: hdr,
AAAA: ip,
}
resp.Answer = append(resp.Answer, ans)
}
for _, n := range names {
ans := &dns.PTR{
Hdr: hdr,
Ptr: n,
}
resp.Answer = append(resp.Answer, ans)
}
if len(resp.Answer) == 0 {
resp.SetRcode(m, dns.RcodeNameError)
}
@@ -104,8 +71,8 @@ func (u *TestUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
return resp, nil
}
// Address implements upstream.Upstream interface for *TestUpstream.
func (u *TestUpstream) Address() string {
// Address implements upstream.Upstream interface for *Upstream.
func (u *Upstream) Address() string {
return u.Addr
}

30
internal/aghtls/aghtls.go Normal file
View File

@@ -0,0 +1,30 @@
// Package aghtls contains utilities for work with TLS.
package aghtls
import "crypto/tls"
// SaferCipherSuites returns a set of default cipher suites with vulnerable and
// weak cipher suites removed.
func SaferCipherSuites() (safe []uint16) {
for _, s := range tls.CipherSuites() {
switch s.ID {
case
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
// Less safe 3DES and CBC suites, go on.
default:
safe = append(safe, s.ID)
}
}
return safe
}

View File

@@ -119,23 +119,28 @@ func (l *Lease) UnmarshalJSON(data []byte) (err error) {
return nil
}
// ServerConfig - DHCP server configuration
// field ordering is important -- yaml fields will mirror ordering from here
// ServerConfig is the configuration for the DHCP server. The order of YAML
// fields is important, since the YAML configuration file follows it.
type ServerConfig struct {
Enabled bool `yaml:"enabled"`
InterfaceName string `yaml:"interface_name"`
Conf4 V4ServerConf `yaml:"dhcpv4"`
Conf6 V6ServerConf `yaml:"dhcpv6"`
WorkDir string `yaml:"-"`
DBFilePath string `yaml:"-"` // path to DB file
// Called when the configuration is changed by HTTP request
ConfigModified func() `yaml:"-"`
// Register an HTTP handler
HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request)) `yaml:"-"`
Enabled bool `yaml:"enabled"`
InterfaceName string `yaml:"interface_name"`
// LocalDomainName is the domain name used for DHCP hosts. For example,
// a DHCP client with the hostname "myhost" can be addressed as "myhost.lan"
// when LocalDomainName is "lan".
LocalDomainName string `yaml:"local_domain_name"`
Conf4 V4ServerConf `yaml:"dhcpv4"`
Conf6 V6ServerConf `yaml:"dhcpv6"`
WorkDir string `yaml:"-"`
DBFilePath string `yaml:"-"`
}
// OnLeaseChangedT is a callback for lease changes.
@@ -156,7 +161,9 @@ type Server struct {
srv4 DHCPServer
srv6 DHCPServer
conf ServerConfig
// TODO(a.garipov): Either create a separate type for the internal config or
// just put the config values into Server.
conf *ServerConfig
// Called when the leases DB is modified
onLeaseChanged []OnLeaseChangedT
@@ -181,14 +188,21 @@ type ServerInterface interface {
}
// Create - create object
func Create(conf ServerConfig) (s *Server, err error) {
s = &Server{}
func Create(conf *ServerConfig) (s *Server, err error) {
s = &Server{
conf: &ServerConfig{
ConfigModified: conf.ConfigModified,
s.conf.Enabled = conf.Enabled
s.conf.InterfaceName = conf.InterfaceName
s.conf.HTTPRegister = conf.HTTPRegister
s.conf.ConfigModified = conf.ConfigModified
s.conf.DBFilePath = filepath.Join(conf.WorkDir, dbFilename)
HTTPRegister: conf.HTTPRegister,
Enabled: conf.Enabled,
InterfaceName: conf.InterfaceName,
LocalDomainName: conf.LocalDomainName,
DBFilePath: filepath.Join(conf.WorkDir, dbFilename),
},
}
if !webHandlersRegistered && s.conf.HTTPRegister != nil {
if runtime.GOOS == "windows" {
@@ -305,6 +319,7 @@ func (s *Server) notify(flags int) {
func (s *Server) WriteDiskConfig(c *ServerConfig) {
c.Enabled = s.conf.Enabled
c.InterfaceName = s.conf.InterfaceName
c.LocalDomainName = s.conf.LocalDomainName
s.srv4.WriteDiskConfig4(&c.Conf4)
s.srv6.WriteDiskConfig6(&c.Conf6)
}

View File

@@ -27,7 +27,7 @@ func testNotify(flags uint32) {
func TestDB(t *testing.T) {
var err error
s := Server{
conf: ServerConfig{
conf: &ServerConfig{
DBFilePath: dbFilename,
},
}
@@ -140,27 +140,27 @@ func TestNormalizeLeases(t *testing.T) {
func TestV4Server_badRange(t *testing.T) {
testCases := []struct {
name string
wantErrMsg string
gatewayIP net.IP
subnetMask net.IP
wantErrMsg string
}{{
name: "gateway_in_range",
gatewayIP: net.IP{192, 168, 10, 120},
subnetMask: net.IP{255, 255, 255, 0},
name: "gateway_in_range",
wantErrMsg: "dhcpv4: gateway ip 192.168.10.120 in the ip range: " +
"192.168.10.20-192.168.10.200",
gatewayIP: net.IP{192, 168, 10, 120},
subnetMask: net.IP{255, 255, 255, 0},
}, {
name: "outside_range_start",
gatewayIP: net.IP{192, 168, 10, 1},
subnetMask: net.IP{255, 255, 255, 240},
name: "outside_range_start",
wantErrMsg: "dhcpv4: range start 192.168.10.20 is outside network " +
"192.168.10.1/28",
}, {
name: "outside_range_end",
gatewayIP: net.IP{192, 168, 10, 1},
subnetMask: net.IP{255, 255, 255, 224},
subnetMask: net.IP{255, 255, 255, 240},
}, {
name: "outside_range_end",
wantErrMsg: "dhcpv4: range end 192.168.10.200 is outside network " +
"192.168.10.1/27",
gatewayIP: net.IP{192, 168, 10, 1},
subnetMask: net.IP{255, 255, 255, 224},
}}
for _, tc := range testCases {

View File

@@ -575,12 +575,15 @@ func (s *Server) handleReset(w http.ResponseWriter, r *http.Request) {
log.Error("dhcp: removing db: %s", err)
}
oldconf := s.conf
s.conf = ServerConfig{
WorkDir: oldconf.WorkDir,
HTTPRegister: oldconf.HTTPRegister,
ConfigModified: oldconf.ConfigModified,
DBFilePath: oldconf.DBFilePath,
s.conf = &ServerConfig{
ConfigModified: s.conf.ConfigModified,
HTTPRegister: s.conf.HTTPRegister,
LocalDomainName: s.conf.LocalDomainName,
WorkDir: s.conf.WorkDir,
DBFilePath: s.conf.DBFilePath,
}
v4conf := V4ServerConf{

View File

@@ -14,8 +14,8 @@ import (
//
// It is safe for concurrent use.
//
// TODO(a.garipov): Perhaps create an optimised version with uint32 for
// IPv4 ranges? Or use one of uint128 packages?
// TODO(a.garipov): Perhaps create an optimized version with uint32 for IPv4
// ranges? Or use one of uint128 packages?
type ipRange struct {
start *big.Int
end *big.Int

View File

@@ -12,33 +12,33 @@ import (
func TestNullBool_UnmarshalJSON(t *testing.T) {
testCases := []struct {
name string
data []byte
wantErrMsg string
data []byte
want nullBool
}{{
name: "empty",
data: []byte{},
wantErrMsg: "",
data: []byte{},
want: nbNull,
}, {
name: "null",
data: []byte("null"),
wantErrMsg: "",
data: []byte("null"),
want: nbNull,
}, {
name: "true",
data: []byte("true"),
wantErrMsg: "",
data: []byte("true"),
want: nbTrue,
}, {
name: "false",
data: []byte("false"),
wantErrMsg: "",
data: []byte("false"),
want: nbFalse,
}, {
name: "invalid",
data: []byte("flase"),
wantErrMsg: `invalid nullBool value "flase"`,
wantErrMsg: `invalid nullBool value "invalid"`,
data: []byte("invalid"),
want: nbNull,
}}

View File

@@ -130,21 +130,19 @@ func parseDHCPOption(s string) (opt dhcpv4.Option, err error) {
// prepareOptions builds the set of DHCP options according to host requirements
// document and values from conf.
func prepareOptions(conf V4ServerConf) (opts dhcpv4.Options) {
// Set default values for host configuration parameters listed in Appendix
// A of RFC-2131. Those parameters, if requested by client, should be
// returned with values defined by Host Requirements Document.
//
// See https://datatracker.ietf.org/doc/html/rfc2131#appendix-A.
//
// See also https://datatracker.ietf.org/doc/html/rfc1122,
// https://datatracker.ietf.org/doc/html/rfc1123, and
// https://datatracker.ietf.org/doc/html/rfc2132.
opts = dhcpv4.Options{
// Set default values for host configuration parameters listed
// in Appendix A of RFC-2131. Those parameters, if requested by
// client, should be returned with values defined by Host
// Requirements Document.
//
// See https://datatracker.ietf.org/doc/html/rfc2131#appendix-A.
//
// See also https://datatracker.ietf.org/doc/html/rfc1122,
// https://datatracker.ietf.org/doc/html/rfc1123, and
// https://datatracker.ietf.org/doc/html/rfc2132.
// IP-Layer Per Host
dhcpv4.OptionNonLocalSourceRouting.Code(): []byte{0},
// Set the current recommended default time to live for the
// Internet Protocol which is 64, see
// https://datatracker.ietf.org/doc/html/rfc1700.

View File

@@ -27,7 +27,6 @@ type DHCPServer interface {
Start() (err error)
// Stop - stop server
Stop() (err error)
getLeasesRef() []*Lease
}

View File

@@ -969,11 +969,10 @@ func (s *v4Server) send(peer net.Addr, conn net.PacketConn, req, resp *dhcpv4.DH
Port: dhcpv4.ServerPort,
}
if mtype == dhcpv4.MessageTypeNak {
// Set the broadcast bit in the DHCPNAK, so that the
// relay agent broadcasted it to the client, because the
// client may not have a correct network address or
// subnet mask, and the client may not be answering ARP
// requests.
// Set the broadcast bit in the DHCPNAK, so that the relay agent
// broadcasts it to the client, because the client may not have
// a correct network address or subnet mask, and the client may not
// be answering ARP requests.
resp.SetBroadcast()
}
case mtype == dhcpv4.MessageTypeNak:
@@ -1056,8 +1055,6 @@ func (s *v4Server) Start() (err error) {
go func() {
if serr := s.srv.Serve(); errors.Is(serr, net.ErrClosed) {
log.Info("dhcpv4: server is closed")
return
} else if serr != nil {
log.Error("dhcpv4: srv.Serve: %s", serr)
}

View File

@@ -662,8 +662,11 @@ func (s *v6Server) Start() (err error) {
}
go func() {
err = s.srv.Serve()
log.Error("dhcpv6: srv.Serve: %s", err)
if serr := s.srv.Serve(); errors.Is(serr, net.ErrClosed) {
log.Info("dhcpv6: server is closed")
} else if serr != nil {
log.Error("dhcpv6: srv.Serve: %s", serr)
}
}()
return nil

View File

@@ -7,8 +7,8 @@ import (
"net/http"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil"
@@ -194,62 +194,46 @@ func (s *Server) handleAccessList(w http.ResponseWriter, r *http.Request) {
}
}
func isUniq(slice []string) (ok bool, uniqueMap map[string]unit) {
exists := make(map[string]unit)
for _, key := range slice {
if _, has := exists[key]; has {
return false, nil
}
exists[key] = unit{}
}
return true, exists
}
func intersect(mapA, mapB map[string]unit) bool {
for key := range mapA {
if _, has := mapB[key]; has {
return true
}
}
return false
}
// validateAccessSet checks the internal accessListJSON lists. To search for
// duplicates, we cannot compare the new stringutil.Set and []string, because
// creating a set for a large array can be an unnecessary algorithmic complexity
func validateAccessSet(list accessListJSON) (err error) {
const (
errAllowedDup errors.Error = "duplicates in allowed clients"
errDisallowedDup errors.Error = "duplicates in disallowed clients"
errBlockedDup errors.Error = "duplicates in blocked hosts"
errIntersect errors.Error = "some items in allowed and " +
"disallowed lists at the same time"
)
ok, allowedClients := isUniq(list.AllowedClients)
if !ok {
return errAllowedDup
func validateAccessSet(list *accessListJSON) (err error) {
allowed, err := validateStrUniq(list.AllowedClients)
if err != nil {
return fmt.Errorf("validating allowed clients: %w", err)
}
ok, disallowedClients := isUniq(list.DisallowedClients)
if !ok {
return errDisallowedDup
disallowed, err := validateStrUniq(list.DisallowedClients)
if err != nil {
return fmt.Errorf("validating disallowed clients: %w", err)
}
ok, _ = isUniq(list.BlockedHosts)
if !ok {
return errBlockedDup
_, err = validateStrUniq(list.BlockedHosts)
if err != nil {
return fmt.Errorf("validating blocked hosts: %w", err)
}
if intersect(allowedClients, disallowedClients) {
return errIntersect
merged := allowed.Merge(disallowed)
err = merged.Validate(aghalg.StringIsBefore)
if err != nil {
return fmt.Errorf("items in allowed and disallowed clients intersect: %w", err)
}
return nil
}
// 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))
for _, c := range clients {
uc.Add(c)
}
return uc, uc.Validate(aghalg.StringIsBefore)
}
func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
list := accessListJSON{}
list := &accessListJSON{}
err := json.NewDecoder(r.Body).Decode(&list)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "decoding request: %s", err)

View File

@@ -31,8 +31,8 @@ func (c testTLSConn) ConnectionState() (cs tls.ConnectionState) {
// testQUICSession is a quicSession for tests.
type testQUICSession struct {
// Session is embedded here simply to make testQUICSession
// a quic.Session without acctually implementing all methods.
// Session is embedded here simply to make testQUICSession a quic.Session
// without actually implementing all methods.
quic.Session
serverName string

View File

@@ -11,6 +11,7 @@ import (
"strings"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
@@ -98,10 +99,10 @@ type FilteringConfig struct {
AllowedClients []string `yaml:"allowed_clients"` // IP addresses of whitelist clients
DisallowedClients []string `yaml:"disallowed_clients"` // IP addresses of clients that should be blocked
BlockedHosts []string `yaml:"blocked_hosts"` // hosts that should be blocked
// TrustedProxies is the list of IP addresses and CIDR networks to
// detect proxy servers addresses the DoH requests from which should be
// handled. The value of nil or an empty slice for this field makes
// Proxy not trust any address.
// TrustedProxies is the list of IP addresses and CIDR networks to detect
// proxy servers addresses the DoH requests from which should be handled.
// The value of nil or an empty slice for this field makes Proxy not trust
// any address.
TrustedProxies []string `yaml:"trusted_proxies"`
// DNS cache settings
@@ -243,15 +244,15 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
proxyConfig.FastestPingTimeout = s.conf.FastestTimeout.Duration
}
if len(s.conf.BogusNXDomain) > 0 {
for _, s := range s.conf.BogusNXDomain {
ip := net.ParseIP(s)
if ip == nil {
log.Error("Invalid bogus IP: %s", s)
} else {
proxyConfig.BogusNXDomain = append(proxyConfig.BogusNXDomain, ip)
}
for i, s := range s.conf.BogusNXDomain {
subnet, err := netutil.ParseSubnet(s)
if err != nil {
log.Error("subnet at index %d: %s", i, err)
continue
}
proxyConfig.BogusNXDomain = append(proxyConfig.BogusNXDomain, subnet)
}
// TLS settings
@@ -426,6 +427,7 @@ func (s *Server) prepareTLS(proxyConfig *proxy.Config) error {
proxyConfig.TLSConfig = &tls.Config{
GetCertificate: s.onGetCertificate,
CipherSuites: aghtls.SaferCipherSuites(),
MinVersion: tls.VersionTLS12,
}

View File

@@ -215,9 +215,8 @@ func (s *Server) onDHCPLeaseChanged(flags int) {
ipToHost = netutil.NewIPMap(len(ll))
for _, l := range ll {
// TODO(a.garipov): Remove this after we're finished
// with the client hostname validations in the DHCP
// server code.
// TODO(a.garipov): Remove this after we're finished with the client
// hostname validations in the DHCP server code.
err = netutil.ValidateDomainName(l.Hostname)
if err != nil {
log.Debug(
@@ -293,14 +292,16 @@ func (s *Server) processInternalHosts(dctx *dnsContext) (rc resultCode) {
req := dctx.proxyCtx.Req
q := req.Question[0]
// Go on processing the AAAA request despite the fact that we don't
// support it yet. The expected behavior here is to respond with an
// empty asnwer and not NXDOMAIN.
// Go on processing the AAAA request despite the fact that we don't support
// it yet. The expected behavior here is to respond with an empty answer
// and not NXDOMAIN.
if q.Qtype != dns.TypeA && q.Qtype != dns.TypeAAAA {
return resultCodeSuccess
}
reqHost := strings.ToLower(q.Name)
// TODO(a.garipov): Move everything related to DHCP local domain to the DHCP
// server.
host := strings.TrimSuffix(reqHost, s.localDomainSuffix)
if host == reqHost {
return resultCodeSuccess
@@ -352,9 +353,22 @@ func (s *Server) processRestrictLocal(ctx *dnsContext) (rc resultCode) {
ip, err := netutil.IPFromReversedAddr(q.Name)
if err != nil {
log.Debug("dns: reversed addr: %s", err)
log.Debug("dns: parsing reversed addr: %s", err)
return resultCodeError
// DNS-Based Service Discovery uses PTR records having not an ARPA
// format of the domain name in question. Those shouldn't be
// invalidated. See http://www.dns-sd.org/ServerStaticSetup.html and
// RFC 2782.
name := strings.TrimSuffix(q.Name, ".")
if err = netutil.ValidateSRVDomainName(name); err != nil {
log.Debug("dns: validating service domain: %s", err)
return resultCodeError
}
log.Debug("dns: request is for a service domain")
return resultCodeSuccess
}
// Restrict an access to local addresses for external clients. We also
@@ -599,9 +613,9 @@ func (s *Server) processFilteringAfterResponse(ctx *dnsContext) (rc resultCode)
d.Res.Answer = answer
}
default:
// Check the response only if the it's from an upstream. Don't check
// the response if the protection is disabled since dnsrewrite rules
// aren't applied to it anyway.
// Check the response only if it's from an upstream. Don't check the
// response if the protection is disabled since dnsrewrite rules aren't
// applied to it anyway.
if !ctx.protectionEnabled || !ctx.responseFromUpstream || s.dnsFilter == nil {
break
}

View File

@@ -261,7 +261,7 @@ func TestServer_ProcessInternalHosts(t *testing.T) {
}
func TestServer_ProcessRestrictLocal(t *testing.T) {
ups := &aghtest.TestUpstream{
ups := &aghtest.Upstream{
Reverse: map[string][]string{
"251.252.253.254.in-addr.arpa.": {"host1.example.net."},
"1.1.168.192.in-addr.arpa.": {"some.local-client."},
@@ -339,7 +339,7 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
s := createTestServer(t, &filtering.Config{}, ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
}, &aghtest.TestUpstream{
}, &aghtest.Upstream{
Reverse: map[string][]string{
reqAddr: {locDomain},
},

View File

@@ -443,7 +443,7 @@ func (s *Server) setupResolvers(localAddrs []string) (err error) {
&upstream.Options{
Bootstrap: bootstraps,
Timeout: defaultLocalTimeout,
// TODO(e.burkov): Should we verify server's ceritificates?
// TODO(e.burkov): Should we verify server's certificates?
},
)
if err != nil {
@@ -559,7 +559,7 @@ func (s *Server) IsRunning() bool {
return s.isRunning
}
// srvClosedErr is returned when the method can't complete without inacessible
// srvClosedErr is returned when the method can't complete without inaccessible
// data from the closing server.
const srvClosedErr errors.Error = "server is closed"

View File

@@ -89,7 +89,7 @@ func createTestServer(
defer s.serverLock.Unlock()
if localUps != nil {
s.localResolvers.Config.UpstreamConfig.Upstreams = []upstream.Upstream{localUps}
s.localResolvers.UpstreamConfig.Upstreams = []upstream.Upstream{localUps}
s.conf.UsePrivateRDNS = true
}
@@ -247,7 +247,7 @@ func TestServer(t *testing.T) {
TCPListenAddrs: []*net.TCPAddr{{}},
}, nil)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
IPv4: map[string][]net.IP{
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
},
@@ -316,7 +316,7 @@ func TestServerWithProtectionDisabled(t *testing.T) {
TCPListenAddrs: []*net.TCPAddr{{}},
}, nil)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
IPv4: map[string][]net.IP{
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
},
@@ -339,7 +339,7 @@ func TestDoTServer(t *testing.T) {
TLSListenAddrs: []*net.TCPAddr{{}},
})
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
IPv4: map[string][]net.IP{
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
},
@@ -369,7 +369,7 @@ func TestDoQServer(t *testing.T) {
QUICListenAddrs: []*net.UDPAddr{{IP: net.IP{127, 0, 0, 1}}},
})
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
IPv4: map[string][]net.IP{
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
},
@@ -413,7 +413,7 @@ func TestServerRace(t *testing.T) {
}
s := createTestServer(t, filterConf, forwardConf, nil)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
IPv4: map[string][]net.IP{
"google-public-dns-a.google.com.": {{8, 8, 8, 8}},
},
@@ -552,7 +552,7 @@ func TestServerCustomClientUpstream(t *testing.T) {
}
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
s.conf.GetCustomUpstreamByClient = func(_ string) (conf *proxy.UpstreamConfig, err error) {
ups := &aghtest.TestUpstream{
ups := &aghtest.Upstream{
IPv4: map[string][]net.IP{
"host.": {{192, 168, 0, 1}},
},
@@ -580,9 +580,9 @@ func TestServerCustomClientUpstream(t *testing.T) {
}
// testCNAMEs is a map of names and CNAMEs necessary for the TestUpstream work.
var testCNAMEs = map[string]string{
"badhost.": "NULL.example.org.",
"whitelist.example.org.": "NULL.example.org.",
var testCNAMEs = map[string][]string{
"badhost.": {"NULL.example.org."},
"whitelist.example.org.": {"NULL.example.org."},
}
// testIPv4 is a map of names and IPv4s necessary for the TestUpstream work.
@@ -596,7 +596,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
}, nil)
testUpstm := &aghtest.TestUpstream{
testUpstm := &aghtest.Upstream{
CName: testCNAMEs,
IPv4: testIPv4,
IPv6: nil,
@@ -630,7 +630,7 @@ func TestBlockCNAME(t *testing.T) {
}
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
CName: testCNAMEs,
IPv4: testIPv4,
},
@@ -640,14 +640,17 @@ func TestBlockCNAME(t *testing.T) {
addr := s.dnsProxy.Addr(proxy.ProtoUDP).String()
testCases := []struct {
name string
host string
want bool
}{{
name: "block_request",
host: "badhost.",
// 'badhost' has a canonical name 'NULL.example.org' which is
// blocked by filters: response is blocked.
want: true,
}, {
name: "allowed",
host: "whitelist.example.org.",
// 'whitelist.example.org' has a canonical name
// 'NULL.example.org' which is blocked by filters
@@ -655,6 +658,7 @@ func TestBlockCNAME(t *testing.T) {
// response isn't blocked.
want: false,
}, {
name: "block_response",
host: "example.org.",
// 'example.org' has a canonical name 'cname1' with IP
// 127.0.0.255 which is blocked by filters: response is blocked.
@@ -662,9 +666,9 @@ func TestBlockCNAME(t *testing.T) {
}}
for _, tc := range testCases {
t.Run("block_cname_"+tc.host, func(t *testing.T) {
req := createTestMessage(tc.host)
req := createTestMessage(tc.host)
t.Run(tc.name, func(t *testing.T) {
reply, err := dns.Exchange(req, addr)
require.NoError(t, err)
@@ -674,7 +678,7 @@ func TestBlockCNAME(t *testing.T) {
ans := reply.Answer[0]
a, ok := ans.(*dns.A)
require.Truef(t, ok, "got %T", ans)
require.True(t, ok)
assert.True(t, a.A.IsUnspecified())
}
@@ -695,7 +699,7 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
}
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
&aghtest.Upstream{
CName: testCNAMEs,
IPv4: testIPv4,
},
@@ -892,7 +896,7 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
func TestRewrite(t *testing.T) {
c := &filtering.Config{
Rewrites: []filtering.RewriteEntry{{
Rewrites: []*filtering.LegacyRewrite{{
Domain: "test.com",
Answer: "1.2.3.4",
Type: dns.TypeA,
@@ -931,9 +935,9 @@ func TestRewrite(t *testing.T) {
}))
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.TestUpstream{
CName: map[string]string{
"example.org": "somename",
&aghtest.Upstream{
CName: map[string][]string{
"example.org": {"somename"},
},
IPv4: map[string][]net.IP{
"example.org.": {{4, 3, 2, 1}},
@@ -1193,12 +1197,12 @@ func TestNewServer(t *testing.T) {
}
func TestServer_Exchange(t *testing.T) {
extUpstream := &aghtest.TestUpstream{
extUpstream := &aghtest.Upstream{
Reverse: map[string][]string{
"1.1.1.1.in-addr.arpa.": {"one.one.one.one"},
},
}
locUpstream := &aghtest.TestUpstream{
locUpstream := &aghtest.Upstream{
Reverse: map[string][]string{
"1.1.168.192.in-addr.arpa.": {"local.domain"},
"2.1.168.192.in-addr.arpa.": {},

View File

@@ -116,7 +116,7 @@ func (s *Server) filterDNSRequest(ctx *dnsContext) (*filtering.Result, error) {
// checkHostRules checks the host against filters. It is safe for concurrent
// use.
func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Settings) (
func (s *Server) checkHostRules(host string, rrtype uint16, setts *filtering.Settings) (
r *filtering.Result,
err error,
) {
@@ -128,7 +128,7 @@ func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Sett
}
var res filtering.Result
res, err = s.dnsFilter.CheckHostRules(host, qtype, setts)
res, err = s.dnsFilter.CheckHostRules(host, rrtype, setts)
if err != nil {
return nil, err
}
@@ -136,33 +136,36 @@ func (s *Server) checkHostRules(host string, qtype uint16, setts *filtering.Sett
return &res, err
}
// If response contains CNAME, A or AAAA records, we apply filtering to each
// canonical host name or IP address. If this is a match, we set a new response
// in d.Res and return.
func (s *Server) filterDNSResponse(ctx *dnsContext) (*filtering.Result, error) {
// filterDNSResponse checks each resource record of the response's answer
// section from ctx and returns a non-nil res if at least one of canonnical
// names or IP addresses in it matches the filtering rules.
func (s *Server) filterDNSResponse(ctx *dnsContext) (res *filtering.Result, err error) {
d := ctx.proxyCtx
setts := ctx.setts
if !setts.FilteringEnabled {
return nil, nil
}
for _, a := range d.Res.Answer {
host := ""
switch v := a.(type) {
var rrtype uint16
switch a := a.(type) {
case *dns.CNAME:
log.Debug("DNSFwd: Checking CNAME %s for %s", v.Target, v.Hdr.Name)
host = strings.TrimSuffix(v.Target, ".")
host = strings.TrimSuffix(a.Target, ".")
rrtype = dns.TypeCNAME
case *dns.A:
host = v.A.String()
log.Debug("DNSFwd: Checking record A (%s) for %s", host, v.Hdr.Name)
host = a.A.String()
rrtype = dns.TypeA
case *dns.AAAA:
host = v.AAAA.String()
log.Debug("DNSFwd: Checking record AAAA (%s) for %s", host, v.Hdr.Name)
host = a.AAAA.String()
rrtype = dns.TypeAAAA
default:
continue
}
host = strings.TrimSuffix(host, ".")
res, err := s.checkHostRules(host, d.Req.Question[0].Qtype, ctx.setts)
log.Debug("dnsforward: checking %s %s for %s", dns.Type(rrtype), host, a.Header().Name)
res, err = s.checkHostRules(host, rrtype, setts)
if err != nil {
return nil, err
} else if res == nil {

View File

@@ -0,0 +1,159 @@
package dnsforward
import (
"net"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/netutil"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHandleDNSRequest_filterDNSResponse(t *testing.T) {
rules := `
||blocked.domain^
@@||allowed.domain^
||cname.specific^$dnstype=~CNAME
||0.0.0.1^$dnstype=~A
||::1^$dnstype=~AAAA
`
forwardConf := ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
FilteringConfig: FilteringConfig{
ProtectionEnabled: true,
BlockingMode: BlockingModeDefault,
},
}
filters := []filtering.Filter{{
ID: 0, Data: []byte(rules),
}}
f := filtering.New(&filtering.Config{}, filters)
f.SetEnabled(true)
snd, err := aghnet.NewSubnetDetector()
require.NoError(t, err)
require.NotNil(t, snd)
s, err := NewServer(DNSCreateParams{
DHCPServer: &testDHCP{},
DNSFilter: f,
SubnetDetector: snd,
})
require.NoError(t, err)
s.conf = forwardConf
err = s.Prepare(nil)
require.NoError(t, err)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
&aghtest.Upstream{
CName: map[string][]string{
"cname.exception.": {"cname.specific."},
"should.block.": {"blocked.domain."},
"allowed.first.": {"allowed.domain.", "blocked.domain."},
"blocked.first.": {"blocked.domain.", "allowed.domain."},
},
IPv4: map[string][]net.IP{
"a.exception.": {{0, 0, 0, 1}},
},
IPv6: map[string][]net.IP{
"aaaa.exception.": {net.ParseIP("::1")},
},
},
}
startDeferStop(t, s)
testCases := []struct {
req *dns.Msg
name string
wantAns []dns.RR
}{{
req: createTestMessage("cname.exception."),
name: "cname_exception",
wantAns: []dns.RR{&dns.CNAME{
Hdr: dns.RR_Header{
Name: "cname.exception.",
Rrtype: dns.TypeCNAME,
},
Target: "cname.specific.",
}},
}, {
req: createTestMessage("should.block."),
name: "blocked_by_cname",
wantAns: []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: "should.block.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
},
A: netutil.IPv4Zero(),
}},
}, {
req: createTestMessage("a.exception."),
name: "a_exception",
wantAns: []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: "a.exception.",
Rrtype: dns.TypeA,
},
A: net.IP{0, 0, 0, 1},
}},
}, {
req: createTestMessageWithType("aaaa.exception.", dns.TypeAAAA),
name: "aaaa_exception",
wantAns: []dns.RR{&dns.AAAA{
Hdr: dns.RR_Header{
Name: "aaaa.exception.",
Rrtype: dns.TypeAAAA,
},
AAAA: net.ParseIP("::1"),
}},
}, {
req: createTestMessage("allowed.first."),
name: "allowed_first",
wantAns: []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: "allowed.first.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
},
A: netutil.IPv4Zero(),
}},
}, {
req: createTestMessage("blocked.first."),
name: "blocked_first",
wantAns: []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: "blocked.first.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
},
A: netutil.IPv4Zero(),
}},
}}
for _, tc := range testCases {
dctx := &proxy.DNSContext{
Proto: proxy.ProtoUDP,
Req: tc.req,
Addr: &net.UDPAddr{IP: net.IP{127, 0, 0, 1}, Port: 1},
}
t.Run(tc.name, func(t *testing.T) {
err = s.handleDNSRequest(nil, dctx)
require.NoError(t, err)
require.NotNil(t, dctx.Res)
assert.Equal(t, tc.wantAns, dctx.Res.Answer)
})
}
}

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"net"
"net/http"
"strconv"
"strings"
"time"
@@ -192,22 +191,23 @@ func (req *dnsConfig) checkCacheTTL() bool {
func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
req := dnsConfig{}
dec := json.NewDecoder(r.Body)
if err := dec.Decode(&req); err != nil {
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "json Encode: %s", err)
return
}
if req.Upstreams != nil {
if err := ValidateUpstreams(*req.Upstreams); err != nil {
if err = ValidateUpstreams(*req.Upstreams); err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "wrong upstreams specification: %s", err)
return
}
}
if errBoot, err := req.checkBootstrap(); err != nil {
var errBoot string
if errBoot, err = req.checkBootstrap(); err != nil {
aghhttp.Error(
r,
w,
@@ -220,19 +220,16 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
return
}
if !req.checkBlockingMode() {
switch {
case !req.checkBlockingMode():
aghhttp.Error(r, w, http.StatusBadRequest, "blocking_mode: incorrect value")
return
}
if !req.checkUpstreamsMode() {
case !req.checkUpstreamsMode():
aghhttp.Error(r, w, http.StatusBadRequest, "upstream_mode: incorrect value")
return
}
if !req.checkCacheTTL() {
case !req.checkCacheTTL():
aghhttp.Error(
r,
w,
@@ -241,13 +238,15 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
)
return
default:
// Go on.
}
restart := s.setConfig(req)
s.conf.ConfigModified()
if restart {
if err := s.Reconfigure(nil); err != nil {
if err = s.Reconfigure(nil); err != nil {
aghhttp.Error(r, w, http.StatusInternalServerError, "%s", err)
}
}
@@ -387,14 +386,14 @@ func ValidateUpstreams(upstreams []string) (err error) {
var defaultUpstreamFound bool
for _, u := range upstreams {
var ok bool
ok, err = validateUpstream(u)
var useDefault bool
useDefault, err = validateUpstream(u)
if err != nil {
return err
}
if !defaultUpstreamFound {
defaultUpstreamFound = ok
defaultUpstreamFound = useDefault
}
}
@@ -407,50 +406,62 @@ func ValidateUpstreams(upstreams []string) (err error) {
var protocols = []string{"tls://", "https://", "tcp://", "sdns://", "quic://"}
func validateUpstream(u string) (bool, error) {
func validateUpstream(u string) (useDefault bool, err error) {
// Check if the user tries to specify upstream for domain.
u, useDefault, err := separateUpstream(u)
var isDomainSpec bool
u, isDomainSpec, err = separateUpstream(u)
if err != nil {
return useDefault, err
return !isDomainSpec, err
}
// The special server address '#' means "use the default servers"
if u == "#" && !useDefault {
// The special server address '#' means that default server must be used.
if useDefault = !isDomainSpec; u == "#" && isDomainSpec {
return useDefault, nil
}
// Check if the upstream has a valid protocol prefix
// Check if the upstream has a valid protocol prefix.
//
// TODO(e.burkov): Validate the domain name.
for _, proto := range protocols {
if strings.HasPrefix(u, proto) {
return useDefault, nil
}
}
// Return error if the upstream contains '://' without any valid protocol
if strings.Contains(u, "://") {
return useDefault, fmt.Errorf("wrong protocol")
return useDefault, errors.Error("wrong protocol")
}
// Check if upstream is valid plain DNS
return useDefault, checkPlainDNS(u)
// Check if upstream is either an IP or IP with port.
if net.ParseIP(u) != nil {
return useDefault, nil
} else if _, err = netutil.ParseIPPort(u); err != nil {
return useDefault, err
}
return useDefault, nil
}
// separateUpstream returns the upstream without the specified domains.
// useDefault is true when a default upstream must be used.
func separateUpstream(upstreamStr string) (upstream string, useDefault bool, err error) {
defer func() { err = errors.Annotate(err, "bad upstream for domain spec %q: %w", upstreamStr) }()
// isDomainSpec is true when the upstream is domains-specific.
func separateUpstream(upstreamStr string) (upstream string, isDomainSpec bool, err error) {
if !strings.HasPrefix(upstreamStr, "[/") {
return upstreamStr, true, nil
return upstreamStr, false, nil
}
defer func() { err = errors.Annotate(err, "bad upstream for domain %q: %w", upstreamStr) }()
parts := strings.Split(upstreamStr[2:], "/]")
if len(parts) != 2 {
return "", false, errors.Error("duplicated separator")
switch len(parts) {
case 2:
// Go on.
case 1:
return "", false, errors.Error("missing separator")
default:
return "", true, errors.Error("duplicated separator")
}
domains := parts[0]
upstream = parts[1]
var domains string
domains, upstream = parts[0], parts[1]
for i, host := range strings.Split(domains, "/") {
if host == "" {
continue
@@ -458,36 +469,11 @@ func separateUpstream(upstreamStr string) (upstream string, useDefault bool, err
err = netutil.ValidateDomainName(host)
if err != nil {
return "", false, fmt.Errorf("domain at index %d: %w", i, err)
return "", true, fmt.Errorf("domain at index %d: %w", i, err)
}
}
return upstream, false, nil
}
// checkPlainDNS checks if host is plain DNS
func checkPlainDNS(upstream string) error {
// Check if host is ip without port
if net.ParseIP(upstream) != nil {
return nil
}
// Check if host is ip with port
ip, port, err := net.SplitHostPort(upstream)
if err != nil {
return err
}
if net.ParseIP(ip) == nil {
return fmt.Errorf("%s is not a valid IP", ip)
}
_, err = strconv.ParseInt(port, 0, 64)
if err != nil {
return fmt.Errorf("%s is not a valid port: %w", port, err)
}
return nil
return upstream, true, nil
}
// excFunc is a signature of function to check if upstream exchanges correctly.
@@ -515,12 +501,8 @@ func checkDNSUpstreamExc(u upstream.Upstream) (err error) {
if len(reply.Answer) != 1 {
return fmt.Errorf("wrong response")
}
if t, ok := reply.Answer[0].(*dns.A); ok {
if !net.IPv4(8, 8, 8, 8).Equal(t.A) {
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")
}
return nil
@@ -555,7 +537,7 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
// Separate upstream from domains list.
var useDefault bool
if input, useDefault, err = separateUpstream(input); err != nil {
if useDefault, err = validateUpstream(input); err != nil {
return fmt.Errorf("wrong upstream format: %w", err)
}
@@ -564,7 +546,7 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
return nil
}
if _, err = validateUpstream(input); err != nil {
if input, _, err = separateUpstream(input); err != nil {
return fmt.Errorf("wrong upstream format: %w", err)
}
@@ -572,7 +554,8 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
bootstrap = defaultBootstrap
}
log.Debug("checking if dns server %q works...", input)
log.Debug("checking if upstream %s works", input)
var u upstream.Upstream
u, err = upstream.AddressToUpstream(input, &upstream.Options{
Bootstrap: bootstrap,
@@ -586,7 +569,7 @@ func checkDNS(input string, bootstrap []string, timeout time.Duration, ef excFun
return fmt.Errorf("upstream %q fails to exchange: %w", input, err)
}
log.Debug("dns %s works OK", input)
log.Debug("upstream %s is ok", input)
return nil
}
@@ -620,9 +603,9 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
err = checkDNS(host, bootstraps, timeout, checkPrivateUpstreamExc)
if err != nil {
log.Info("%v", err)
// TODO(e.burkov): If passed upstream have already
// written an error above, we rewriting the error for
// it. These cases should be handled properly instead.
// TODO(e.burkov): If passed upstream have already written an error
// above, we rewriting the error for it. These cases should be
// handled properly instead.
result[host] = err.Error()
continue

View File

@@ -184,7 +184,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
wantSet: "",
}, {
name: "upstream_dns_bad",
wantSet: `wrong upstreams specification: address !!!: ` +
wantSet: `wrong upstreams specification: bad ipport address "!!!": address !!!: ` +
`missing port in address`,
}, {
name: "bootstraps_bad",
@@ -235,107 +235,117 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
}
func TestIsCommentOrEmpty(t *testing.T) {
assert.True(t, IsCommentOrEmpty(""))
assert.True(t, IsCommentOrEmpty("# comment"))
assert.False(t, IsCommentOrEmpty("1.2.3.4"))
for _, tc := range []struct {
want assert.BoolAssertionFunc
str string
}{{
want: assert.True,
str: "",
}, {
want: assert.True,
str: "# comment",
}, {
want: assert.False,
str: "1.2.3.4",
}} {
tc.want(t, IsCommentOrEmpty(tc.str))
}
}
// TODO(a.garipov): Rewrite to check the actual error messages.
func TestValidateUpstream(t *testing.T) {
testCases := []struct {
wantDef assert.BoolAssertionFunc
name string
upstream string
valid bool
wantDef bool
wantErr string
}{{
wantDef: assert.True,
name: "invalid",
upstream: "1.2.3.4.5",
valid: false,
wantDef: false,
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",
valid: false,
wantDef: false,
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",
valid: false,
wantDef: false,
wantErr: `wrong protocol`,
}, {
wantDef: assert.True,
name: "invalid",
upstream: "[/host.com]tls://dns.adguard.com",
valid: false,
wantDef: false,
wantErr: `bad upstream for domain "[/host.com]tls://dns.adguard.com": missing separator`,
}, {
wantDef: assert.True,
name: "invalid",
upstream: "[host.ru]#",
valid: false,
wantDef: false,
wantErr: `bad ipport address "[host.ru]#": address [host.ru]#: missing port in address`,
}, {
wantDef: assert.True,
name: "valid_default",
upstream: "1.1.1.1",
valid: true,
wantDef: true,
wantErr: ``,
}, {
wantDef: assert.True,
name: "valid_default",
upstream: "tls://1.1.1.1",
valid: true,
wantDef: true,
wantErr: ``,
}, {
wantDef: assert.True,
name: "valid_default",
upstream: "https://dns.adguard.com/dns-query",
valid: true,
wantDef: true,
wantErr: ``,
}, {
wantDef: assert.True,
name: "valid_default",
upstream: "sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
valid: true,
wantDef: true,
wantErr: ``,
}, {
wantDef: assert.False,
name: "valid",
upstream: "[/host.com/]1.1.1.1",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "valid",
upstream: "[//]tls://1.1.1.1",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "valid",
upstream: "[/www.host.com/]#",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "valid",
upstream: "[/host.com/google.com/]8.8.8.8",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "valid",
upstream: "[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "idna",
upstream: "[/пример.рф/]8.8.8.8",
valid: true,
wantDef: false,
wantErr: ``,
}, {
wantDef: assert.False,
name: "bad_domain",
upstream: "[/!/]8.8.8.8",
valid: false,
wantDef: false,
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)
require.Equal(t, tc.valid, err == nil)
if tc.valid {
assert.Equal(t, tc.wantDef, defaultUpstream)
}
testutil.AssertErrorMsg(t, tc.wantErr, err)
tc.wantDef(t, defaultUpstream)
})
}
}
@@ -343,22 +353,19 @@ func TestValidateUpstream(t *testing.T) {
func TestValidateUpstreamsSet(t *testing.T) {
testCases := []struct {
name string
msg string
wantErr string
set []string
wantNil bool
}{{
name: "empty",
msg: "empty upstreams array should be valid",
wantErr: ``,
set: nil,
wantNil: true,
}, {
name: "comment",
msg: "comments should not be validated",
wantErr: ``,
set: []string{"# comment"},
wantNil: true,
}, {
name: "valid_no_default",
msg: "there is no default upstream",
name: "valid_no_default",
wantErr: `no default upstreams specified`,
set: []string{
"[/host.com/]1.1.1.1",
"[//]tls://1.1.1.1",
@@ -366,10 +373,9 @@ func TestValidateUpstreamsSet(t *testing.T) {
"[/host.com/google.com/]8.8.8.8",
"[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
},
wantNil: false,
}, {
name: "valid_with_default",
msg: "upstreams set is valid, but doesn't pass through validation cause: %s",
name: "valid_with_default",
wantErr: ``,
set: []string{
"[/host.com/]1.1.1.1",
"[//]tls://1.1.1.1",
@@ -378,19 +384,16 @@ func TestValidateUpstreamsSet(t *testing.T) {
"[/host/]sdns://AQMAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20",
"8.8.8.8",
},
wantNil: true,
}, {
name: "invalid",
msg: "there is an invalid upstream in set, but it pass through validation",
wantErr: `cannot prepare the upstream dhcp://fake.dns ([]): unsupported URL scheme: dhcp`,
set: []string{"dhcp://fake.dns"},
wantNil: false,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := ValidateUpstreams(tc.set)
assert.Equalf(t, tc.wantNil, err == nil, tc.msg, err)
testutil.AssertErrorMsg(t, tc.wantErr, err)
})
}
}

View File

@@ -24,20 +24,19 @@ type ipsetCtx struct {
func (c *ipsetCtx) init(ipsetConf []string) (err error) {
c.ipsetMgr, err = aghnet.NewIpsetManager(ipsetConf)
if errors.Is(err, os.ErrInvalid) || errors.Is(err, os.ErrPermission) {
// ipset cannot currently be initialized if the server was
// installed from Snap or when the user or the binary doesn't
// have the required permissions, or when the kernel doesn't
// support netfilter.
// ipset cannot currently be initialized if the server was installed
// from Snap or when the user or the binary doesn't have the required
// permissions, or when the kernel doesn't support netfilter.
//
// Log and go on.
//
// TODO(a.garipov): The Snap problem can probably be solved if
// we add the netlink-connector interface plug.
log.Info("warning: cannot initialize ipset: %s", err)
// TODO(a.garipov): The Snap problem can probably be solved if we add
// the netlink-connector interface plug.
log.Info("ipset: warning: cannot initialize: %s", err)
return nil
} else if unsupErr := (&aghos.UnsupportedError{}); errors.As(err, &unsupErr) {
log.Info("warning: %s", err)
log.Info("ipset: warning: %s", err)
return nil
} else if err != nil {

View File

@@ -78,8 +78,8 @@ func newRecursionDetector(ttl time.Duration, suspectsNum uint) (rd *recursionDet
// msgToSignature converts msg into it's signature represented in bytes.
func msgToSignature(msg dns.Msg) (sig []byte) {
sig = make([]byte, uint16sz*2+netutil.MaxDomainNameLen)
// The binary.BigEndian byte order is used everywhere except when the
// real machine's endianess is needed.
// The binary.BigEndian byte order is used everywhere except when the real
// machine's endianness is needed.
byteOrder := binary.BigEndian
byteOrder.PutUint16(sig[0:], msg.Id)
q := msg.Question[0]

View File

@@ -28,7 +28,7 @@ import (
// The IDs of built-in filter lists.
//
// Keep in sync with client/src/helpers/contants.js.
// Keep in sync with client/src/helpers/constants.js.
const (
CustomListID = -iota
SysHostsListID
@@ -80,7 +80,7 @@ type Config struct {
ParentalCacheSize uint `yaml:"parental_cache_size"` // (in bytes)
CacheTime uint `yaml:"cache_time"` // Element's TTL (in minutes)
Rewrites []RewriteEntry `yaml:"rewrites"`
Rewrites []*LegacyRewrite `yaml:"rewrites"`
// Names of services to block (globally).
// Per-client settings can override this configuration.
@@ -161,9 +161,14 @@ type DNSFilter struct {
// Filter represents a filter list
type Filter struct {
ID int64 // auto-assigned when filter is added (see nextFilterID)
Data []byte `yaml:"-"` // List of rules divided by '\n'
FilePath string `yaml:"-"` // Path to a filtering rules file
// FilePath is the path to a filtering rules list file.
FilePath string `yaml:"-"`
// Data is the content of the file.
Data []byte `yaml:"-"`
// ID is automatically assigned when filter is added using nextFilterID.
ID int64
}
// Reason holds an enum detailing why it was filtered or not filtered
@@ -281,8 +286,14 @@ func (d *DNSFilter) WriteDiskConfig(c *Config) {
c.Rewrites = cloneRewrites(c.Rewrites)
}
func cloneRewrites(entries []RewriteEntry) (clone []RewriteEntry) {
return append([]RewriteEntry(nil), entries...)
// cloneRewrites returns a deep copy of entries.
func cloneRewrites(entries []*LegacyRewrite) (clone []*LegacyRewrite) {
clone = make([]*LegacyRewrite, len(entries))
for i, rw := range entries {
clone[i] = rw.clone()
}
return clone
}
// SetFilters - set new filters (synchronously or asynchronously)
@@ -409,14 +420,8 @@ func (r Reason) Matched() bool {
}
// CheckHostRules tries to match the host against filtering rules only.
func (d *DNSFilter) CheckHostRules(host string, qtype uint16, setts *Settings) (Result, error) {
if !setts.FilteringEnabled {
return Result{}, nil
}
host = strings.ToLower(host)
return d.matchHost(host, qtype, setts)
func (d *DNSFilter) CheckHostRules(host string, rrtype uint16, setts *Settings) (Result, error) {
return d.matchHost(strings.ToLower(host), rrtype, setts)
}
// CheckHost tries to match the host against filtering rules, then safebrowsing
@@ -466,7 +471,7 @@ func (d *DNSFilter) matchSysHosts(
return res, nil
}
return d.matchSysHostsIntl(&urlfilter.DNSRequest{
dnsres, _ := d.EtcHosts.MatchRequest(urlfilter.DNSRequest{
Hostname: host,
SortedClientTags: setts.ClientTags,
// TODO(e.burkov): Wait for urlfilter update to pass net.IP.
@@ -474,14 +479,6 @@ func (d *DNSFilter) matchSysHosts(
ClientName: setts.ClientName,
DNSType: qtype,
})
}
// matchSysHostsIntl actually matches the request. It's separated to avoid
// perfoming checks twice.
func (d *DNSFilter) matchSysHostsIntl(
req *urlfilter.DNSRequest,
) (res Result, err error) {
dnsres, _ := d.EtcHosts.MatchRequest(*req)
if dnsres == nil {
return res, nil
}
@@ -492,13 +489,6 @@ func (d *DNSFilter) matchSysHostsIntl(
}
res = d.processDNSRewrites(dnsr)
if cn := res.CanonName; cn != "" {
// Probably an alias.
req.Hostname = cn
return d.matchSysHostsIntl(req)
}
res.Reason = RewrittenAutoHosts
for _, r := range res.Rules {
r.Text = stringutil.Coalesce(d.EtcHosts.Translate(r.Text), r.Text)
@@ -507,61 +497,86 @@ func (d *DNSFilter) matchSysHostsIntl(
return res, nil
}
// Process rewrites table
// . Find CNAME for a domain name (exact match or by wildcard)
// . if found and CNAME equals to domain name - this is an exception; exit
// . if found, set domain name to canonical name
// . repeat for the new domain name (Note: we return only the last CNAME)
// . Find A or AAAA record for a domain name (exact match or by wildcard)
// . if found, set IP addresses (IPv4 or IPv6 depending on qtype) in Result.IPList array
// processRewrites performs filtering based on the legacy rewrite records.
//
// Firstly, it finds CNAME rewrites for host. If the CNAME is the same as host,
// this query isn't filtered. If it's different, repeat the process for the new
// CNAME, breaking loops in the process.
//
// Secondly, it finds A or AAAA rewrites for host and, if found, sets res.IPList
// accordingly. If the found rewrite has a special value of "A" or "AAAA", the
// result is an exception.
func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Result) {
d.confLock.RLock()
defer d.confLock.RUnlock()
rr := findRewrites(d.Rewrites, host, qtype)
if len(rr) != 0 {
res.Reason = Rewritten
rewrites, matched := findRewrites(d.Rewrites, host, qtype)
if !matched {
return Result{}
}
res.Reason = Rewritten
cnames := stringutil.NewSet()
origHost := host
for len(rr) != 0 && rr[0].Type == dns.TypeCNAME {
log.Debug("rewrite: CNAME for %s is %s", host, rr[0].Answer)
for matched && len(rewrites) > 0 && rewrites[0].Type == dns.TypeCNAME {
rw := rewrites[0]
rwPat := rw.Domain
rwAns := rw.Answer
if host == rr[0].Answer { // "host == CNAME" is an exception
res.Reason = NotFilteredNotFound
log.Debug("rewrite: cname for %s is %s", host, rwAns)
return res
if origHost == rwAns || rwPat == rwAns {
// Either a request for the hostname itself or a rewrite of
// a pattern onto itself, both of which are an exception rules.
// Return a not filtered result.
return Result{}
} else if host == rwAns && isWildcard(rwPat) {
// An "*.example.com → sub.example.com" rewrite matching in a loop.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/4016.
res.CanonName = host
break
}
host = rr[0].Answer
host = rwAns
if cnames.Has(host) {
log.Info("rewrite: breaking CNAME redirection loop: %s. Question: %s", host, origHost)
log.Info("rewrite: cname loop for %q on %q", origHost, host)
return res
}
cnames.Add(host)
res.CanonName = rr[0].Answer
rr = findRewrites(d.Rewrites, host, qtype)
res.CanonName = host
rewrites, matched = findRewrites(d.Rewrites, host, qtype)
}
for _, r := range rr {
if r.Type == qtype && (qtype == dns.TypeA || qtype == dns.TypeAAAA) {
if r.IP == nil { // IP exception
res.Reason = NotFilteredNotFound
return res
}
res.IPList = append(res.IPList, r.IP)
log.Debug("rewrite: A/AAAA for %s is %s", host, r.IP)
}
}
setRewriteResult(&res, host, rewrites, qtype)
return res
}
// setRewriteResult sets the Reason or IPList of res if necessary. res must not
// be nil.
func setRewriteResult(res *Result, host string, rewrites []*LegacyRewrite, qtype uint16) {
for _, rw := range rewrites {
if rw.Type == qtype && (qtype == dns.TypeA || qtype == dns.TypeAAAA) {
if rw.IP == nil {
// "A"/"AAAA" exception: allow getting from upstream.
res.Reason = NotFilteredNotFound
return
}
res.IPList = append(res.IPList, rw.IP)
log.Debug("rewrite: a/aaaa for %s is %s", host, rw.IP)
}
}
}
// matchBlockedServicesRules checks the host against the blocked services rules
// in settings, if any. The err is always nil, it is only there to make this
// a valid hostChecker function.
@@ -705,8 +720,7 @@ func hostRulesToRules(netRules []*rules.HostRule) (res []rules.Rule) {
return res
}
// matchHostProcessAllowList processes the allowlist logic of host
// matching.
// matchHostProcessAllowList processes the allowlist logic of host matching.
func (d *DNSFilter) matchHostProcessAllowList(
host string,
dnsres *urlfilter.DNSResult,
@@ -777,11 +791,11 @@ func (d *DNSFilter) matchHostProcessDNSResult(
return Result{}
}
// matchHost is a low-level way to check only if hostname is filtered by rules,
// matchHost is a low-level way to check only if host is filtered by rules,
// skipping expensive safebrowsing and parental lookups.
func (d *DNSFilter) matchHost(
host string,
qtype uint16,
rrtype uint16,
setts *Settings,
) (res Result, err error) {
if !setts.FilteringEnabled {
@@ -794,7 +808,7 @@ func (d *DNSFilter) matchHost(
// TODO(e.burkov): Wait for urlfilter update to pass net.IP.
ClientIP: setts.ClientIP.String(),
ClientName: setts.ClientName,
DNSType: qtype,
DNSType: rrtype,
}
d.engineLock.RLock()
@@ -834,7 +848,7 @@ func (d *DNSFilter) matchHost(
return Result{}, nil
}
res = d.matchHostProcessDNSResult(qtype, dnsres)
res = d.matchHostProcessDNSResult(rrtype, dnsres)
for _, r := range res.Rules {
log.Debug(
"filtering: found rule %q for host %q, filter list id: %d",
@@ -917,12 +931,18 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter) {
err := d.initSecurityServices()
if err != nil {
log.Error("filtering: initialize services: %s", err)
return nil
}
if c != nil {
d.Config = *c
d.prepareRewrites()
err = d.prepareRewrites()
if err != nil {
log.Error("rewrites: preparing: %s", err)
return nil
}
}
bsvcs := []string{}

View File

@@ -4,94 +4,121 @@ package filtering
import (
"encoding/json"
"fmt"
"net"
"net/http"
"sort"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/miekg/dns"
)
// RewriteEntry is a rewrite array element
type RewriteEntry struct {
// Domain is the domain for which this rewrite should work.
// LegacyRewrite is a single legacy DNS rewrite record.
//
// Instances of *LegacyRewrite must never be nil.
type LegacyRewrite struct {
// Domain is the domain pattern for which this rewrite should work.
Domain string `yaml:"domain"`
// Answer is the IP address, canonical name, or one of the special
// values: "A" or "AAAA".
Answer string `yaml:"answer"`
// IP is the IP address that should be used in the response if Type is
// A or AAAA.
// dns.TypeA or dns.TypeAAAA.
IP net.IP `yaml:"-"`
// Type is the DNS record type: A, AAAA, or CNAME.
Type uint16 `yaml:"-"`
}
// equal returns true if the entry is considered equal to the other.
func (e *RewriteEntry) equal(other RewriteEntry) (ok bool) {
return e.Domain == other.Domain && e.Answer == other.Answer
// clone returns a deep clone of rw.
func (rw *LegacyRewrite) clone() (cloneRW *LegacyRewrite) {
return &LegacyRewrite{
Domain: rw.Domain,
Answer: rw.Answer,
IP: netutil.CloneIP(rw.IP),
Type: rw.Type,
}
}
// matchesQType returns true if the entry matched qtype.
func (e *RewriteEntry) matchesQType(qtype uint16) (ok bool) {
// equal returns true if the rw is equal to the other.
func (rw *LegacyRewrite) equal(other *LegacyRewrite) (ok bool) {
return rw.Domain == other.Domain && rw.Answer == other.Answer
}
// matchesQType returns true if the entry matches the question type qt.
func (rw *LegacyRewrite) matchesQType(qt uint16) (ok bool) {
// Add CNAMEs, since they match for all types requests.
if e.Type == dns.TypeCNAME {
if rw.Type == dns.TypeCNAME {
return true
}
// Reject types other than A and AAAA.
if qtype != dns.TypeA && qtype != dns.TypeAAAA {
if qt != dns.TypeA && qt != dns.TypeAAAA {
return false
}
// If the types match or the entry is set to allow only the other type,
// include them.
return e.Type == qtype || e.IP == nil
return rw.Type == qt || rw.IP == nil
}
// normalize makes sure that the a new or decoded entry is normalized with
// regards to domain name case, IP length, and so on.
func (e *RewriteEntry) normalize() {
// TODO(a.garipov): Write a case-agnostic version of strings.HasSuffix
// and use it in matchDomainWildcard instead of using strings.ToLower
//
// If rw is nil, it returns an errors.
func (rw *LegacyRewrite) normalize() (err error) {
if rw == nil {
return errors.Error("nil rewrite entry")
}
// TODO(a.garipov): Write a case-agnostic version of strings.HasSuffix and
// use it in matchDomainWildcard instead of using strings.ToLower
// everywhere.
e.Domain = strings.ToLower(e.Domain)
rw.Domain = strings.ToLower(rw.Domain)
switch e.Answer {
switch rw.Answer {
case "AAAA":
e.IP = nil
e.Type = dns.TypeAAAA
rw.IP = nil
rw.Type = dns.TypeAAAA
return
return nil
case "A":
e.IP = nil
e.Type = dns.TypeA
rw.IP = nil
rw.Type = dns.TypeA
return
return nil
default:
// Go on.
}
ip := net.ParseIP(e.Answer)
ip := net.ParseIP(rw.Answer)
if ip == nil {
e.Type = dns.TypeCNAME
rw.Type = dns.TypeCNAME
return
return nil
}
ip4 := ip.To4()
if ip4 != nil {
e.IP = ip4
e.Type = dns.TypeA
rw.IP = ip4
rw.Type = dns.TypeA
} else {
e.IP = ip
e.Type = dns.TypeAAAA
rw.IP = ip
rw.Type = dns.TypeAAAA
}
return nil
}
func isWildcard(host string) bool {
return len(host) > 1 && host[0] == '*' && host[1] == '.'
// isWildcard returns true if pat is a wildcard domain pattern.
func isWildcard(pat string) bool {
return len(pat) > 1 && pat[0] == '*' && pat[1] == '.'
}
// matchDomainWildcard returns true if host matches the wildcard pattern.
@@ -107,16 +134,16 @@ func matchDomainWildcard(host, wildcard string) (ok bool) {
// wildcard > exact
// lower level wildcard > higher level wildcard
//
type rewritesSorted []RewriteEntry
type rewritesSorted []*LegacyRewrite
// Len implements the sort.Interface interface for legacyRewritesSorted.
func (a rewritesSorted) Len() int { return len(a) }
func (a rewritesSorted) Len() (l int) { return len(a) }
// Swap implements the sort.Interface interface for legacyRewritesSorted.
func (a rewritesSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// Less implements the sort.Interface interface for legacyRewritesSorted.
func (a rewritesSorted) Less(i, j int) bool {
func (a rewritesSorted) Less(i, j int) (less bool) {
if a[i].Type == dns.TypeCNAME && a[j].Type != dns.TypeCNAME {
return true
} else if a[i].Type != dns.TypeCNAME && a[j].Type == dns.TypeCNAME {
@@ -133,49 +160,62 @@ func (a rewritesSorted) Less(i, j int) bool {
}
}
// both are wildcards
// Both are wildcards.
return len(a[i].Domain) > len(a[j].Domain)
}
func (d *DNSFilter) prepareRewrites() {
for i := range d.Rewrites {
d.Rewrites[i].normalize()
// prepareRewrites normalizes and validates all legacy DNS rewrites.
func (d *DNSFilter) prepareRewrites() (err error) {
for i, r := range d.Rewrites {
err = r.normalize()
if err != nil {
return fmt.Errorf("at index %d: %w", i, err)
}
}
return nil
}
// findRewrites returns the list of matched rewrite entries. The priority is:
// CNAME, then A and AAAA; exact, then wildcard. If the host is matched
// exactly, wildcard entries aren't returned. If the host matched by wildcards,
// return the most specific for the question type.
func findRewrites(entries []RewriteEntry, host string, qtype uint16) (matched []RewriteEntry) {
rr := rewritesSorted{}
// findRewrites returns the list of matched rewrite entries. If rewrites are
// empty, but matched is true, the domain is found among the rewrite rules but
// not for this question type.
//
// The result priority is: CNAME, then A and AAAA; exact, then wildcard. If the
// host is matched exactly, wildcard entries aren't returned. If the host
// matched by wildcards, return the most specific for the question type.
func findRewrites(
entries []*LegacyRewrite,
host string,
qtype uint16,
) (rewrites []*LegacyRewrite, matched bool) {
for _, e := range entries {
if e.Domain != host && !matchDomainWildcard(host, e.Domain) {
continue
}
matched = true
if e.matchesQType(qtype) {
rr = append(rr, e)
rewrites = append(rewrites, e)
}
}
if len(rr) == 0 {
return nil
if len(rewrites) == 0 {
return nil, matched
}
sort.Sort(rr)
sort.Sort(rewritesSorted(rewrites))
for i, r := range rr {
for i, r := range rewrites {
if isWildcard(r.Domain) {
// Don't use rr[:0], because we need to return at least
// one item here.
rr = rr[:max(1, i)]
// Don't use rewrites[:0], because we need to return at least one
// item here.
rewrites = rewrites[:max(1, i)]
break
}
}
return rr
return rewrites, matched
}
func max(a, b int) int {
@@ -214,24 +254,32 @@ func (d *DNSFilter) handleRewriteList(w http.ResponseWriter, r *http.Request) {
}
func (d *DNSFilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
jsent := rewriteEntryJSON{}
err := json.NewDecoder(r.Body).Decode(&jsent)
rwJSON := rewriteEntryJSON{}
err := json.NewDecoder(r.Body).Decode(&rwJSON)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "json.Decode: %s", err)
return
}
ent := RewriteEntry{
Domain: jsent.Domain,
Answer: jsent.Answer,
rw := &LegacyRewrite{
Domain: rwJSON.Domain,
Answer: rwJSON.Answer,
}
ent.normalize()
err = rw.normalize()
if err != nil {
// Shouldn't happen currently, since normalize only returns a non-nil
// error when a rewrite is nil, but be change-proof.
aghhttp.Error(r, w, http.StatusBadRequest, "normalizing: %s", err)
return
}
d.confLock.Lock()
d.Config.Rewrites = append(d.Config.Rewrites, ent)
d.Config.Rewrites = append(d.Config.Rewrites, rw)
d.confLock.Unlock()
log.Debug("Rewrites: added element: %s -> %s [%d]",
ent.Domain, ent.Answer, len(d.Config.Rewrites))
log.Debug("rewrite: added element: %s -> %s [%d]", rw.Domain, rw.Answer, len(d.Config.Rewrites))
d.Config.ConfigModified()
}
@@ -245,17 +293,20 @@ func (d *DNSFilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request)
return
}
entDel := RewriteEntry{
entDel := &LegacyRewrite{
Domain: jsent.Domain,
Answer: jsent.Answer,
}
arr := []RewriteEntry{}
arr := []*LegacyRewrite{}
d.confLock.Lock()
for _, ent := range d.Config.Rewrites {
if ent.equal(entDel) {
log.Debug("Rewrites: removed element: %s -> %s", ent.Domain, ent.Answer)
log.Debug("rewrite: removed element: %s -> %s", ent.Domain, ent.Answer)
continue
}
arr = append(arr, ent)
}
d.Config.Rewrites = arr

View File

@@ -15,7 +15,7 @@ func TestRewrites(t *testing.T) {
d := newForTest(t, nil, nil)
t.Cleanup(d.Close)
d.Rewrites = []RewriteEntry{{
d.Rewrites = []*LegacyRewrite{{
// This one and below are about CNAME, A and AAAA.
Domain: "somecname",
Answer: "somehost.com",
@@ -66,98 +66,123 @@ func TestRewrites(t *testing.T) {
}, {
Domain: "BIGHOST.COM",
Answer: "1.2.3.7",
}, {
Domain: "*.issue4016.com",
Answer: "sub.issue4016.com",
}}
d.prepareRewrites()
require.NoError(t, d.prepareRewrites())
testCases := []struct {
name string
host string
wantCName string
wantVals []net.IP
dtyp uint16
name string
host string
wantCName string
wantIPs []net.IP
wantReason Reason
dtyp uint16
}{{
name: "not_filtered_not_found",
host: "hoost.com",
wantCName: "",
wantVals: nil,
dtyp: dns.TypeA,
name: "not_filtered_not_found",
host: "hoost.com",
wantCName: "",
wantIPs: nil,
wantReason: NotFilteredNotFound,
dtyp: dns.TypeA,
}, {
name: "rewritten_a",
host: "www.host.com",
wantCName: "host.com",
wantVals: []net.IP{{1, 2, 3, 4}, {1, 2, 3, 5}},
dtyp: dns.TypeA,
name: "rewritten_a",
host: "www.host.com",
wantCName: "host.com",
wantIPs: []net.IP{{1, 2, 3, 4}, {1, 2, 3, 5}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "rewritten_aaaa",
host: "www.host.com",
wantCName: "host.com",
wantVals: []net.IP{net.ParseIP("1:2:3::4")},
dtyp: dns.TypeAAAA,
name: "rewritten_aaaa",
host: "www.host.com",
wantCName: "host.com",
wantIPs: []net.IP{net.ParseIP("1:2:3::4")},
wantReason: Rewritten,
dtyp: dns.TypeAAAA,
}, {
name: "wildcard_match",
host: "abc.host.com",
wantCName: "",
wantVals: []net.IP{{1, 2, 3, 5}},
dtyp: dns.TypeA,
name: "wildcard_match",
host: "abc.host.com",
wantCName: "",
wantIPs: []net.IP{{1, 2, 3, 5}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "wildcard_override",
host: "a.host.com",
wantCName: "",
wantVals: []net.IP{{1, 2, 3, 4}},
dtyp: dns.TypeA,
name: "wildcard_override",
host: "a.host.com",
wantCName: "",
wantIPs: []net.IP{{1, 2, 3, 4}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "wildcard_cname_interaction",
host: "www.host2.com",
wantCName: "host.com",
wantVals: []net.IP{{1, 2, 3, 4}, {1, 2, 3, 5}},
dtyp: dns.TypeA,
name: "wildcard_cname_interaction",
host: "www.host2.com",
wantCName: "host.com",
wantIPs: []net.IP{{1, 2, 3, 4}, {1, 2, 3, 5}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "two_cnames",
host: "b.host.com",
wantCName: "somehost.com",
wantVals: []net.IP{{0, 0, 0, 0}},
dtyp: dns.TypeA,
name: "two_cnames",
host: "b.host.com",
wantCName: "somehost.com",
wantIPs: []net.IP{{0, 0, 0, 0}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "two_cnames_and_wildcard",
host: "b.host3.com",
wantCName: "x.host.com",
wantVals: []net.IP{{1, 2, 3, 5}},
dtyp: dns.TypeA,
name: "two_cnames_and_wildcard",
host: "b.host3.com",
wantCName: "x.host.com",
wantIPs: []net.IP{{1, 2, 3, 5}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "issue3343",
host: "www.hostboth.com",
wantCName: "",
wantVals: []net.IP{net.ParseIP("1234::5678")},
dtyp: dns.TypeAAAA,
name: "issue3343",
host: "www.hostboth.com",
wantCName: "",
wantIPs: []net.IP{net.ParseIP("1234::5678")},
wantReason: Rewritten,
dtyp: dns.TypeAAAA,
}, {
name: "issue3351",
host: "bighost.com",
wantCName: "",
wantVals: []net.IP{{1, 2, 3, 7}},
dtyp: dns.TypeA,
name: "issue3351",
host: "bighost.com",
wantCName: "",
wantIPs: []net.IP{{1, 2, 3, 7}},
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "issue4008",
host: "somehost.com",
wantCName: "",
wantIPs: nil,
wantReason: Rewritten,
dtyp: dns.TypeHTTPS,
}, {
name: "issue4016",
host: "www.issue4016.com",
wantCName: "sub.issue4016.com",
wantIPs: nil,
wantReason: Rewritten,
dtyp: dns.TypeA,
}, {
name: "issue4016_self",
host: "sub.issue4016.com",
wantCName: "",
wantIPs: nil,
wantReason: NotFilteredNotFound,
dtyp: dns.TypeA,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
valsNum := len(tc.wantVals)
r := d.processRewrites(tc.host, tc.dtyp)
if valsNum == 0 {
assert.Equal(t, NotFilteredNotFound, r.Reason)
return
}
require.Equalf(t, Rewritten, r.Reason, "got %s", r.Reason)
require.Equalf(t, tc.wantReason, r.Reason, "got %s", r.Reason)
if tc.wantCName != "" {
assert.Equal(t, tc.wantCName, r.CanonName)
}
require.Len(t, r.IPList, valsNum)
for i, ip := range tc.wantVals {
assert.Equal(t, ip, r.IPList[i])
}
assert.Equal(t, tc.wantIPs, r.IPList)
})
}
}
@@ -166,7 +191,7 @@ func TestRewritesLevels(t *testing.T) {
d := newForTest(t, nil, nil)
t.Cleanup(d.Close)
// Exact host, wildcard L2, wildcard L3.
d.Rewrites = []RewriteEntry{{
d.Rewrites = []*LegacyRewrite{{
Domain: "host.com",
Answer: "1.1.1.1",
Type: dns.TypeA,
@@ -179,7 +204,8 @@ func TestRewritesLevels(t *testing.T) {
Answer: "3.3.3.3",
Type: dns.TypeA,
}}
d.prepareRewrites()
require.NoError(t, d.prepareRewrites())
testCases := []struct {
name string
@@ -212,7 +238,7 @@ func TestRewritesExceptionCNAME(t *testing.T) {
d := newForTest(t, nil, nil)
t.Cleanup(d.Close)
// Wildcard and exception for a sub-domain.
d.Rewrites = []RewriteEntry{{
d.Rewrites = []*LegacyRewrite{{
Domain: "*.host.com",
Answer: "2.2.2.2",
}, {
@@ -222,29 +248,32 @@ func TestRewritesExceptionCNAME(t *testing.T) {
Domain: "*.sub.host.com",
Answer: "*.sub.host.com",
}}
d.prepareRewrites()
require.NoError(t, d.prepareRewrites())
testCases := []struct {
name string
host string
want net.IP
}{{
name: "match_sub-domain",
name: "match_subdomain",
host: "my.host.com",
want: net.IP{2, 2, 2, 2},
}, {
name: "exception_cname",
host: "sub.host.com",
want: nil,
}, {
name: "exception_wildcard",
host: "my.sub.host.com",
want: nil,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
r := d.processRewrites(tc.host, dns.TypeA)
if tc.want == nil {
assert.Equal(t, NotFilteredNotFound, r.Reason)
assert.Equal(t, NotFilteredNotFound, r.Reason, "got %s", r.Reason)
return
}
@@ -260,7 +289,7 @@ func TestRewritesExceptionIP(t *testing.T) {
d := newForTest(t, nil, nil)
t.Cleanup(d.Close)
// Exception for AAAA record.
d.Rewrites = []RewriteEntry{{
d.Rewrites = []*LegacyRewrite{{
Domain: "host.com",
Answer: "1.2.3.4",
Type: dns.TypeA,
@@ -281,7 +310,8 @@ func TestRewritesExceptionIP(t *testing.T) {
Answer: "A",
Type: dns.TypeA,
}}
d.prepareRewrites()
require.NoError(t, d.prepareRewrites())
testCases := []struct {
name string

View File

@@ -404,8 +404,8 @@ func realIP(r *http.Request) (ip net.IP, err error) {
return ip, nil
}
// When everything else fails, just return the remote address as
// understood by the stdlib.
// When everything else fails, just return the remote address as understood
// by the stdlib.
ipStr, err := netutil.SplitHost(r.RemoteAddr)
if err != nil {
return nil, fmt.Errorf("getting ip from client addr: %w", err)
@@ -424,7 +424,8 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
}
var remoteAddr string
// The realIP couldn't be used here due to security issues.
// realIP cannot be used here without taking TrustedProxies into account due
// to security issues.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/2799.
//
@@ -438,13 +439,7 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
if blocker := Context.auth.blocker; blocker != nil {
if left := blocker.check(remoteAddr); left > 0 {
w.Header().Set("Retry-After", strconv.Itoa(int(left.Seconds())))
aghhttp.Error(
r,
w,
http.StatusTooManyRequests,
"auth: blocked for %s",
left,
)
aghhttp.Error(r, w, http.StatusTooManyRequests, "auth: blocked for %s", left)
return
}
@@ -458,17 +453,18 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
return
}
// Use realIP here, since this IP address is only used for logging.
ip, err := realIP(r)
if err != nil {
log.Error("auth: getting real ip from request: %s", err)
} else if ip == nil {
// Technically shouldn't happen.
log.Error("auth: unknown ip")
}
if len(cookie) == 0 {
var ip net.IP
ip, err = realIP(r)
if err != nil {
log.Info("auth: getting real ip from request: %s", err)
} else if ip == nil {
// Technically shouldn't happen.
log.Info("auth: failed to login user %q from unknown ip", req.Name)
} else {
log.Info("auth: failed to login user %q from ip %q", req.Name, ip)
}
log.Info("auth: failed to login user %q from ip %v", req.Name, ip)
time.Sleep(1 * time.Second)
http.Error(w, "invalid username or password", http.StatusBadRequest)
@@ -476,11 +472,13 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Set-Cookie", cookie)
log.Info("auth: user %q successfully logged in from ip %v", req.Name, ip)
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
h := w.Header()
h.Set("Set-Cookie", cookie)
h.Set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate")
h.Set("Pragma", "no-cache")
h.Set("Expires", "0")
aghhttp.OK(w)
}
@@ -530,7 +528,7 @@ func optionalAuthThird(w http.ResponseWriter, r *http.Request) (authFirst bool)
cookie, err := r.Cookie(sessionCookieName)
if glProcessCookie(r) {
log.Debug("auth: authentification was handled by GL-Inet submodule")
log.Debug("auth: authentication was handled by GL-Inet submodule")
ok = true
} else if err == nil {
r := Context.auth.checkSession(cookie.Value)

View File

@@ -96,7 +96,7 @@ type clientsContainer struct {
dnsServer *dnsforward.Server
// etcHosts contains list of rewrite rules taken from the operating system's
// hosts databse.
// hosts database.
etcHosts *aghnet.HostsContainer
testing bool // if TRUE, this object is used for internal tests
@@ -175,7 +175,7 @@ type clientObject struct {
UseGlobalBlockedServices bool `yaml:"use_global_blocked_services"`
}
// addFromConfig initializes the clients containter with objects from the
// addFromConfig initializes the clients container with objects from the
// configuration file.
func (clients *clientsContainer) addFromConfig(objects []*clientObject) {
for _, o := range objects {
@@ -783,12 +783,14 @@ func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
n := 0
hosts.Range(func(ip net.IP, v interface{}) (cont bool) {
names, ok := v.(*stringutil.Set)
hosts, ok := v.(*stringutil.Set)
if !ok {
log.Error("dns: bad type %T in ipToRC for %s", v, ip)
return true
}
names.Range(func(name string) (cont bool) {
hosts.Range(func(name string) (cont bool) {
if clients.addHostLocked(ip, name, ClientSourceHostsFile) {
n++
}

View File

@@ -3,10 +3,12 @@ package home
import (
"net"
"os"
"runtime"
"testing"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -271,12 +273,18 @@ func TestClientsAddExisting(t *testing.T) {
})
t.Run("complicated", func(t *testing.T) {
// TODO(a.garipov): Properly decouple the DHCP server from the client
// storage.
if runtime.GOOS == "windows" {
t.Skip("skipping dhcp test on windows")
}
var err error
ip := net.IP{1, 2, 3, 4}
// First, init a DHCP server with a single static lease.
config := dhcpd.ServerConfig{
config := &dhcpd.ServerConfig{
Enabled: true,
DBFilePath: "leases.db",
Conf4: dhcpd.V4ServerConf{
@@ -290,10 +298,9 @@ func TestClientsAddExisting(t *testing.T) {
clients.dhcpServer, err = dhcpd.Create(config)
require.NoError(t, err)
// TODO(e.burkov): leases.db isn't created on Windows so removing it
// causes an error. Split the test to make it run properly on different
// operating systems.
t.Cleanup(func() { _ = os.Remove("leases.db") })
testutil.CleanupAndRequireSuccess(t, func() (err error) {
return os.Remove("leases.db")
})
err = clients.dhcpServer.AddStaticLease(&dhcpd.Lease{
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},

View File

@@ -1,11 +1,13 @@
package home
import (
"fmt"
"net"
"os"
"path/filepath"
"sync"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
@@ -81,7 +83,7 @@ type configuration struct {
WhitelistFilters []filter `yaml:"whitelist_filters"`
UserRules []string `yaml:"user_rules"`
DHCP dhcpd.ServerConfig `yaml:"dhcp"`
DHCP *dhcpd.ServerConfig `yaml:"dhcp"`
// Clients contains the YAML representations of the persistent clients.
// This field is only used for reading and writing persistent client data.
@@ -121,11 +123,6 @@ type dnsConfig struct {
// UpstreamTimeout is the timeout for querying upstream servers.
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
// LocalDomainName is the domain name used for known internal hosts.
// For example, a machine called "myhost" can be addressed as
// "myhost.lan" when LocalDomainName is "lan".
LocalDomainName string `yaml:"local_domain_name"`
// ResolveClients enables and disables resolving clients with RDNS.
ResolveClients bool `yaml:"resolve_clients"`
@@ -164,7 +161,7 @@ type tlsConfigSettings struct {
// config is the global configuration structure.
//
// TODO(a.garipov, e.burkov): This global is afwul and must be removed.
// TODO(a.garipov, e.burkov): This global is awful and must be removed.
var config = &configuration{
BindPort: 3000,
BetaBindPort: 0,
@@ -197,7 +194,6 @@ var config = &configuration{
FilteringEnabled: true, // whether or not use filter lists
FiltersUpdateIntervalHours: 24,
UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout},
LocalDomainName: "lan",
ResolveClients: true,
UsePrivateRDNS: true,
},
@@ -206,6 +202,9 @@ var config = &configuration{
PortDNSOverTLS: defaultPortTLS, // needs to be passed through to dnsproxy
PortDNSOverQUIC: defaultPortQUIC,
},
DHCP: &dhcpd.ServerConfig{
LocalDomainName: "lan",
},
logSettings: logSettings{
LogCompress: false,
LogLocalTime: false,
@@ -286,22 +285,25 @@ func parseConfig() (err error) {
return err
}
pm := portsMap{}
pm.add(
uc := aghalg.UniqChecker{}
addPorts(
uc,
config.BindPort,
config.BetaBindPort,
config.DNS.Port,
)
if config.TLS.Enabled {
pm.add(
addPorts(
uc,
config.TLS.PortHTTPS,
config.TLS.PortDNSOverTLS,
config.TLS.PortDNSOverQUIC,
config.TLS.PortDNSCrypt,
)
}
if err = pm.validate(); err != nil {
return err
if err = uc.Validate(aghalg.IntIsBefore); err != nil {
return fmt.Errorf("validating ports: %w", err)
}
if !checkFiltersUpdateIntervalHours(config.DNS.FiltersUpdateIntervalHours) {
@@ -315,6 +317,15 @@ func parseConfig() (err error) {
return nil
}
// addPorts is a helper for ports validation. It skips zero ports.
func addPorts(uc aghalg.UniqChecker, ports ...int) {
for _, p := range ports {
if p != 0 {
uc.Add(p)
}
}
}
// readConfigFile reads configuration file contents.
func readConfigFile() (fileData []byte, err error) {
if len(config.fileData) > 0 {
@@ -375,8 +386,8 @@ func (c *configuration) write() error {
}
if Context.dhcpServer != nil {
c := dhcpd.ServerConfig{}
Context.dhcpServer.WriteDiskConfig(&c)
c := &dhcpd.ServerConfig{}
Context.dhcpServer.WriteDiskConfig(c)
config.DHCP = c
}

Some files were not shown because too many files have changed in this diff Show More