Merge branch 'master' into 4299-querylog-stats-api
This commit is contained in:
commit
e0cbfc1c40
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -31,6 +31,9 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
|||
- Two new HTTP APIs, `PUT /control/querylog/config/update` and `GET
|
||||
control/querylog/config`, which can be used to set and receive the statistics
|
||||
configuration. See openapi/openapi.yaml for the full description.
|
||||
- The ability to set custom IP for EDNS Client Subnet by using the new
|
||||
`dns.edns_client_subnet.use_custom` and `dns.edns_client_subnet.custom_ip`
|
||||
fields ([#1472]). The UI changes are coming in the upcoming releases.
|
||||
- The ability to use `dnstype` rules in the disallowed domains list ([#5468]).
|
||||
This allows dropping requests based on their question types.
|
||||
|
||||
|
@ -38,9 +41,9 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
|||
|
||||
#### Configuration Changes
|
||||
|
||||
In this release, the schema version has changed from 16 to 17.
|
||||
In this release, the schema version has changed from 16 to 18.
|
||||
|
||||
- Property `statistics.interval`, which in schema versions 16 and earlier used
|
||||
- Property `statistics.interval`, which in schema versions 17 and earlier used
|
||||
to be an integer number of days, is now a string with a human-readable
|
||||
duration:
|
||||
|
||||
|
@ -57,7 +60,31 @@ In this release, the schema version has changed from 16 to 17.
|
|||
```
|
||||
|
||||
To rollback this change, convert the property back into days and change the
|
||||
`schema_version` back to `16`.
|
||||
`schema_version` back to `17`.
|
||||
- Property `edns_client_subnet`, which in schema versions 16 and earlier used
|
||||
to be a part of the `dns` object, is now part of the `dns.edns_client_subnet`
|
||||
object:
|
||||
|
||||
```yaml
|
||||
# BEFORE:
|
||||
'dns':
|
||||
# …
|
||||
'edns_client_subnet': false
|
||||
|
||||
# AFTER:
|
||||
'dns':
|
||||
# …
|
||||
'edns_client_subnet':
|
||||
'enabled': false
|
||||
'use_custom': false
|
||||
'custom_ip': ''
|
||||
```
|
||||
|
||||
To rollback this change, move the value of `dns.edns_client_subnet.enabled`
|
||||
into the `dns.edns_client_subnet`, remove the fields
|
||||
`dns.edns_client_subnet.enabled`, `dns.edns_client_subnet.use_custom`,
|
||||
`dns.edns_client_subnet.custom_ip`, and change the `schema_version` back to
|
||||
`16`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
@ -78,17 +105,23 @@ In this release, the schema version has changed from 16 to 17.
|
|||
|
||||
### Fixed
|
||||
|
||||
- Various dark theme bugs ([#5439], [#5441], [#5442], [#5515]).
|
||||
- Automatic update on MIPS64 and little-endian 32-bit MIPS architectures
|
||||
([#5270], [#5373]).
|
||||
- Requirements to domain names in domain-specific upstream configurations have
|
||||
been relaxed to meet those from [RFC 3696][rfc3696] ([#4884]).
|
||||
- Failing service installation via script on FreeBSD ([#5431]).
|
||||
|
||||
[#1472]: https://github.com/AdguardTeam/AdGuardHome/issues/1472
|
||||
[#4884]: https://github.com/AdguardTeam/AdGuardHome/issues/4884
|
||||
[#5270]: https://github.com/AdguardTeam/AdGuardHome/issues/5270
|
||||
[#5373]: https://github.com/AdguardTeam/AdGuardHome/issues/5373
|
||||
[#5431]: https://github.com/AdguardTeam/AdGuardHome/issues/5431
|
||||
[#5439]: https://github.com/AdguardTeam/AdGuardHome/issues/5439
|
||||
[#5441]: https://github.com/AdguardTeam/AdGuardHome/issues/5441
|
||||
[#5442]: https://github.com/AdguardTeam/AdGuardHome/issues/5442
|
||||
[#5468]: https://github.com/AdguardTeam/AdGuardHome/issues/5468
|
||||
[#5515]: https://github.com/AdguardTeam/AdGuardHome/issues/5515
|
||||
|
||||
[rfc3696]: https://datatracker.ietf.org/doc/html/rfc3696
|
||||
|
||||
|
@ -172,6 +205,7 @@ In this release, the schema version has changed from 14 to 16.
|
|||
'file_enabled': true
|
||||
'interval': '2160h'
|
||||
'size_memory': 1000
|
||||
'ignored': []
|
||||
```
|
||||
|
||||
To rollback this change, rename and move properties back into the `dns`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"timeUpdated": "2023-02-21T12:46:33.324Z",
|
||||
"timeUpdated": "2023-03-01T10:05:51.445Z",
|
||||
"categories": {
|
||||
"0": "audio_video_player",
|
||||
"1": "comments",
|
||||
|
@ -19225,11 +19225,39 @@
|
|||
"url": "http://www.zypmedia.com/",
|
||||
"companyId": "zypmedia"
|
||||
},
|
||||
"slack": {
|
||||
"name": "Slack",
|
||||
"adguard_dns": {
|
||||
"name": "AdGuard DNS",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.slack.com/",
|
||||
"companyId": "salesforce",
|
||||
"url": "https://adguard-dns.io/",
|
||||
"companyId": "adguard",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adguard_vpn": {
|
||||
"name": "AdGuard VPN",
|
||||
"categoryId": 8,
|
||||
"url": "https://adguard-vpn.com/",
|
||||
"companyId": "adguard",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"appcenter": {
|
||||
"name": "Microsoft App Center",
|
||||
"categoryId": 5,
|
||||
"url": "https://appcenter.ms/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"alibaba_cloud": {
|
||||
"name": "Alibaba Cloud",
|
||||
"categoryId": 10,
|
||||
"url": "https://www.alibabacloud.com/",
|
||||
"companyId": "alibaba",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"alibaba_ucbrowser": {
|
||||
"name": "UC Browser",
|
||||
"categoryId": 8,
|
||||
"url": "https://ucweb.com/",
|
||||
"companyId": "alibaba",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"apple": {
|
||||
|
@ -19246,11 +19274,39 @@
|
|||
"companyId": "apple",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"facebook_audience": {
|
||||
"name": "Facebook Audience Network",
|
||||
"azure": {
|
||||
"name": "Microsoft Azure",
|
||||
"categoryId": 10,
|
||||
"url": "https://azure.microsoft.com/",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"azure_blob_storage": {
|
||||
"name": "Azure Blob Storage",
|
||||
"categoryId": 8,
|
||||
"url": "https://azure.microsoft.com/en-us/products/storage/blobs",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"bitwarden": {
|
||||
"name": "Bitwarden",
|
||||
"categoryId": 8,
|
||||
"url": "https://bitwarden.com/",
|
||||
"companyId": "bitwarden",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"branch": {
|
||||
"name": "Branch.io",
|
||||
"categoryId": 101,
|
||||
"url": "https://branch.io/",
|
||||
"companyId": "branch_metrics_inc",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"button": {
|
||||
"name": "Button",
|
||||
"categoryId": 4,
|
||||
"url": "https://www.facebook.com/business/products/audience-network",
|
||||
"companyId": "meta",
|
||||
"url": "https://www.usebutton.com/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"crashlytics": {
|
||||
|
@ -19260,18 +19316,25 @@
|
|||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"showrss": {
|
||||
"name": "showRSS",
|
||||
"categoryId": 8,
|
||||
"url": "https://showrss.info/",
|
||||
"companyId": "showrss",
|
||||
"element": {
|
||||
"name": "Element",
|
||||
"categoryId": 7,
|
||||
"url": "https://element.io/",
|
||||
"companyId": "element",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"hockeyapp": {
|
||||
"name": "HockeyApp",
|
||||
"facebook_audience": {
|
||||
"name": "Facebook Audience Network",
|
||||
"categoryId": 4,
|
||||
"url": "https://www.facebook.com/business/products/audience-network",
|
||||
"companyId": "meta",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"firebase": {
|
||||
"name": "Firebase",
|
||||
"categoryId": 101,
|
||||
"url": "https://hockeyapp.net/",
|
||||
"companyId": null,
|
||||
"url": "https://firebase.google.com/",
|
||||
"companyId": "google",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"gmail": {
|
||||
|
@ -19288,32 +19351,32 @@
|
|||
"companyId": "google",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"firebase": {
|
||||
"name": "Firebase",
|
||||
"hockeyapp": {
|
||||
"name": "HockeyApp",
|
||||
"categoryId": 101,
|
||||
"url": "https://firebase.google.com/",
|
||||
"companyId": "google",
|
||||
"url": "https://hockeyapp.net/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"yandex_appmetrica": {
|
||||
"name": "Yandex AppMetrica",
|
||||
"categoryId": 101,
|
||||
"url": "https://appmetrica.yandex.com/",
|
||||
"companyId": "yandex",
|
||||
"kik": {
|
||||
"name": "Kik",
|
||||
"categoryId": 7,
|
||||
"url": "https://kik.com/",
|
||||
"companyId": "kik",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"branch": {
|
||||
"name": "Branch.io",
|
||||
"categoryId": 101,
|
||||
"url": "https://branch.io/",
|
||||
"companyId": "branch_metrics_inc",
|
||||
"lets_encrypt": {
|
||||
"name": "Let's Encrypt",
|
||||
"categoryId": 5,
|
||||
"url": "https://letsencrypt.org/",
|
||||
"companyId": "lets_encrypt",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"telstra": {
|
||||
"name": "Telstra",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.telstra.com.au/",
|
||||
"companyId": "telstra",
|
||||
"matrix": {
|
||||
"name": "Matrix",
|
||||
"categoryId": 5,
|
||||
"url": "https://matrix.org/",
|
||||
"companyId": "matrix",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"medialab": {
|
||||
|
@ -19323,39 +19386,39 @@
|
|||
"companyId": "medialab",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"qualcomm": {
|
||||
"name": "Qualcomm",
|
||||
"meganz": {
|
||||
"name": "Mega Ltd.",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.qualcomm.com/",
|
||||
"companyId": "qualcomm",
|
||||
"url": "https://mega.io/",
|
||||
"companyId": "meganz",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"solaredge": {
|
||||
"name": "SolarEdge Technologies, Inc.",
|
||||
"msedge": {
|
||||
"name": "Microsoft Edge",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.solaredge.com/",
|
||||
"companyId": "solaredge",
|
||||
"url": "https://www.microsoft.com/en-us/edge",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"sectigo": {
|
||||
"name": "Sectigo Limited",
|
||||
"mozilla": {
|
||||
"name": "Mozilla Foundation",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.mozilla.org/",
|
||||
"companyId": "mozilla",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"notion": {
|
||||
"name": "Notion",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.notion.so/",
|
||||
"companyId": "notion",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"ntppool": {
|
||||
"name": "Network Time Protocol",
|
||||
"categoryId": 5,
|
||||
"url": "https://www.solaredge.com/",
|
||||
"companyId": "sectigo",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"element": {
|
||||
"name": "Element",
|
||||
"categoryId": 7,
|
||||
"url": "https://element.io/",
|
||||
"companyId": "element",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"oztam": {
|
||||
"name": "OzTAM",
|
||||
"categoryId": 8,
|
||||
"url": "https://oztam.com.au/",
|
||||
"companyId": "oztam",
|
||||
"url": "https://ntp.org/",
|
||||
"companyId": "ntppool",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"oppo": {
|
||||
|
@ -19372,46 +19435,11 @@
|
|||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"appcenter": {
|
||||
"name": "Microsoft App Center",
|
||||
"categoryId": 5,
|
||||
"url": "https://appcenter.ms/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"unity_ads": {
|
||||
"name": "Unity Ads",
|
||||
"categoryId": 4,
|
||||
"url": "https://unity.com/solutions/mobile-business/monetize-your-game",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"azure": {
|
||||
"name": "Microsoft Azure",
|
||||
"categoryId": 10,
|
||||
"url": "https://azure.microsoft.com/",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"button": {
|
||||
"name": "Button",
|
||||
"categoryId": 4,
|
||||
"url": "https://www.usebutton.com/",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"lets_encrypt": {
|
||||
"name": "Let's Encrypt",
|
||||
"categoryId": 5,
|
||||
"url": "https://letsencrypt.org/",
|
||||
"companyId": "lets_encrypt",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"kik": {
|
||||
"name": "Kik",
|
||||
"categoryId": 7,
|
||||
"url": "https://kik.com/",
|
||||
"companyId": "kik",
|
||||
"oztam": {
|
||||
"name": "OzTAM",
|
||||
"categoryId": 8,
|
||||
"url": "https://oztam.com.au/",
|
||||
"companyId": "oztam",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"plex": {
|
||||
|
@ -19421,25 +19449,60 @@
|
|||
"companyId": "plex",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"matrix": {
|
||||
"name": "Matrix",
|
||||
"categoryId": 5,
|
||||
"url": "https://matrix.org/",
|
||||
"companyId": "matrix",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"ntppool": {
|
||||
"name": "Network Time Protocol",
|
||||
"categoryId": 5,
|
||||
"url": "https://ntp.org/",
|
||||
"companyId": "ntppool",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"whatsapp": {
|
||||
"name": "WhatsApp",
|
||||
"qualcomm": {
|
||||
"name": "Qualcomm",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.whatsapp.com/",
|
||||
"companyId": "meta",
|
||||
"url": "https://www.qualcomm.com/",
|
||||
"companyId": "qualcomm",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"sectigo": {
|
||||
"name": "Sectigo Limited",
|
||||
"categoryId": 5,
|
||||
"url": "https://www.solaredge.com/",
|
||||
"companyId": "sectigo",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"showrss": {
|
||||
"name": "showRSS",
|
||||
"categoryId": 8,
|
||||
"url": "https://showrss.info/",
|
||||
"companyId": "showrss",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"similarweb": {
|
||||
"name": "SimilarWeb",
|
||||
"categoryId": 6,
|
||||
"url": "https://www.similarweb.com/",
|
||||
"companyId": "similarweb",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"slack": {
|
||||
"name": "Slack",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.slack.com/",
|
||||
"companyId": "salesforce",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"solaredge": {
|
||||
"name": "SolarEdge Technologies, Inc.",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.solaredge.com/",
|
||||
"companyId": "solaredge",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"telstra": {
|
||||
"name": "Telstra",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.telstra.com.au/",
|
||||
"companyId": "telstra",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"unity_ads": {
|
||||
"name": "Unity Ads",
|
||||
"categoryId": 4,
|
||||
"url": "https://unity.com/solutions/mobile-business/monetize-your-game",
|
||||
"companyId": null,
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"vscode": {
|
||||
|
@ -19449,12 +19512,47 @@
|
|||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"msedge": {
|
||||
"name": "Microsoft Edge",
|
||||
"whatsapp": {
|
||||
"name": "WhatsApp",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.microsoft.com/en-us/edge",
|
||||
"url": "https://www.whatsapp.com/",
|
||||
"companyId": "meta",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"windows_maps": {
|
||||
"name": "Windows Maps",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.microsoft.com/store/apps/9wzdncrdtbvb",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"windows_notifications": {
|
||||
"name": "The Windows Push Notification Services",
|
||||
"categoryId": 8,
|
||||
"url": "https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/windows-push-notification-services--wns--overview",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"windows_time": {
|
||||
"name": "Windows Time Service",
|
||||
"categoryId": 8,
|
||||
"url": "https://learn.microsoft.com/en-us/windows-server/networking/windows-time-service/how-the-windows-time-service-works",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"windowsupdate": {
|
||||
"name": "Windows Update",
|
||||
"categoryId": 9,
|
||||
"url": "https://support.microsoft.com/en-us/windows/windows-update-faq-8a903416-6f45-0718-f5c7-375e92dddeb2",
|
||||
"companyId": "microsoft",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"yandex_appmetrica": {
|
||||
"name": "Yandex AppMetrica",
|
||||
"categoryId": 101,
|
||||
"url": "https://appmetrica.yandex.com/",
|
||||
"companyId": "yandex",
|
||||
"source": "AdGuard"
|
||||
}
|
||||
},
|
||||
"trackerDomains": {
|
||||
|
@ -23785,10 +23883,111 @@
|
|||
"zwaar.net": "zwaar",
|
||||
"zwaar.org": "zwaar",
|
||||
"extend.tv": "zypmedia",
|
||||
"whatsapp.net": "whatsapp",
|
||||
"whatsapp.com": "whatsapp",
|
||||
"telstra.com.au": "telstra",
|
||||
"telstra.com": "telstra",
|
||||
"adtidy.org": "adguard",
|
||||
"agrd.io": "adguard",
|
||||
"adguard.app": "adguard",
|
||||
"adguard.io": "adguard",
|
||||
"adguard.org": "adguard",
|
||||
"adguard-dns.com": "adguard_dns",
|
||||
"adguard-dns.io": "adguard_dns",
|
||||
"adguardvpn.com": "adguard_vpn",
|
||||
"adguard-vpn.com": "adguard_vpn",
|
||||
"adguard-vpn.online": "adguard_vpn",
|
||||
"akadns.net": "akamai_technologies",
|
||||
"akamaiedge.net": "akamai_technologies",
|
||||
"akaquill.net": "akamai_technologies",
|
||||
"aliapp.org": "alibaba.com",
|
||||
"alibabachengdun.com": "alibaba.com",
|
||||
"alibabausercontent.com": "alibaba.com",
|
||||
"aliexpress.com": "alibaba.com",
|
||||
"alikunlun.com": "alibaba.com",
|
||||
"aliyuncs.com": "alibaba.com",
|
||||
"alibabacloud.com": "alibaba_cloud",
|
||||
"alibabadns.com": "alibaba_cloud",
|
||||
"aliyun.com": "alibaba_cloud",
|
||||
"ucweb.com": "alibaba_ucbrowser",
|
||||
"alipayobjects.com": "alipay.com",
|
||||
"taobao.com": "taobao",
|
||||
"appcenter.ms": "appcenter",
|
||||
"iadsdk.apple.com": "apple_ads",
|
||||
"me.com": "apple",
|
||||
"apple.news": "apple",
|
||||
"apple-dns.net": "apple",
|
||||
"aaplimg.com": "apple",
|
||||
"icloud.com": "apple",
|
||||
"itunes.com": "apple",
|
||||
"icloud-content.com": "apple",
|
||||
"mzstatic.com": "apple",
|
||||
"cdn-apple.com": "apple",
|
||||
"apple-mapkit.com": "apple",
|
||||
"icons.axm-usercontent-apple.com": "apple",
|
||||
"apple-cloudkit.com": "apple",
|
||||
"apzones.com": "apple",
|
||||
"apple-livephotoskit.com": "apple",
|
||||
"safebrowsing.apple": "apple",
|
||||
"safebrowsing.g.applimg.com": "apple",
|
||||
"blob.core.windows.net": "azure_blob_storage",
|
||||
"azure.com": "azure",
|
||||
"trafficmanager.net": "azure",
|
||||
"bitwarden.com": "bitwarden",
|
||||
"mobileapptracking.com": "branch",
|
||||
"bttn.io": "button",
|
||||
"cloudflare-dns.com": "cloudflare",
|
||||
"crashlytics.com": "crashlytics",
|
||||
"phicdn.net": "digicert_trust_seal",
|
||||
"element.io": "element",
|
||||
"riot.im": "element",
|
||||
"app-measurement.com": "firebase",
|
||||
"flipboard.com": "flipboard",
|
||||
"flurry.com": "flurry",
|
||||
"gmail.com": "gmail",
|
||||
"gvt1.com": "google_servers",
|
||||
"gvt2.com": "google_servers",
|
||||
"gvt3.com": "google_servers",
|
||||
"pki.goog": "google_trust_services",
|
||||
"hockeyapp.net": "hockeyapp",
|
||||
"kik.com": "kik",
|
||||
"apikik.com": "kik",
|
||||
"kik-live.com": "kik",
|
||||
"letsencrypt.org": "lets_encrypt",
|
||||
"slatic.net": "lazada",
|
||||
"lencr.org": "lets_encrypt",
|
||||
"edgecastcdn.net": "markmonitor",
|
||||
"matrix.org": "matrix",
|
||||
"medialab.la": "medialab",
|
||||
"media-lab.ai": "medialab",
|
||||
"mega.co.nz": "meganz",
|
||||
"mega.io": "meganz",
|
||||
"mega.nz": "meganz",
|
||||
"e-msedge.net": "msedge",
|
||||
"l-msedge.net": "msedge",
|
||||
"firefox.com": "mozilla",
|
||||
"mozaws.net": "mozilla",
|
||||
"mozgcp.net": "mozilla",
|
||||
"mozilla.com": "mozilla",
|
||||
"mozilla.net": "mozilla",
|
||||
"mozilla.org": "mozilla",
|
||||
"nflximg.com": "netflix",
|
||||
"notion.so": "notion",
|
||||
"ntp.org": "ntppool",
|
||||
"ntppool.org": "ntppool",
|
||||
"oppomobile.com": "oppo",
|
||||
"heytapmobi.com": "oppo",
|
||||
"heytapmobile.com": "oppo",
|
||||
"heytapdl.com": "oppo",
|
||||
"allawnos.com": "oppo",
|
||||
"allawntech.com": "oppo",
|
||||
"hotmail.com": "outlook",
|
||||
"outlook.com": "outlook",
|
||||
"oztam.com.au": "oztam",
|
||||
"plex.tv": "plex",
|
||||
"plex.direct": "plex",
|
||||
"xtracloud.net": "qualcomm",
|
||||
"qualcomm.com": "qualcomm",
|
||||
"sectigo.com": "sectigo",
|
||||
"showrss.info": "showrss",
|
||||
"similarweb.io": "similarweb",
|
||||
"similarweb.com": "similarweb",
|
||||
"slack.com": "slack",
|
||||
"slackb.com": "slack",
|
||||
"slack-edge.com": "slack",
|
||||
|
@ -23803,88 +24002,27 @@
|
|||
"snap-dev.net": "snap",
|
||||
"snapads.com": "snap",
|
||||
"snapkit.com": "snap",
|
||||
"adguard.app": "adguard",
|
||||
"adguard.io": "adguard",
|
||||
"adguard.org": "adguard",
|
||||
"adguard-dns.com": "adguard",
|
||||
"adguard-dns.io": "adguard",
|
||||
"adguard-vpn.com": "adguard",
|
||||
"adguardvpn.com": "adguard",
|
||||
"adguard-vpn.online": "adguard",
|
||||
"oppomobile.com": "oppo",
|
||||
"heytapmobi.com": "oppo",
|
||||
"heytapmobile.com": "oppo",
|
||||
"heytapdl.com": "oppo",
|
||||
"allawnos.com": "oppo",
|
||||
"allawntech.com": "oppo",
|
||||
"nflximg.com": "netflix",
|
||||
"element.io": "element",
|
||||
"riot.im": "element",
|
||||
"gvt1.com": "google_servers",
|
||||
"gvt2.com": "google_servers",
|
||||
"gvt3.com": "google_servers",
|
||||
"akadns.net": "akamai_technologies",
|
||||
"akamaiedge.net": "akamai_technologies",
|
||||
"akaquill.net": "akamai_technologies",
|
||||
"me.com": "apple",
|
||||
"apple.news": "apple",
|
||||
"apple-dns.net": "apple",
|
||||
"aaplimg.com": "apple",
|
||||
"icloud.com": "apple",
|
||||
"itunes.com": "apple",
|
||||
"icloud-content.com": "apple",
|
||||
"kik.com": "kik",
|
||||
"apikik.com": "kik",
|
||||
"kik-live.com": "kik",
|
||||
"mzstatic.com": "apple",
|
||||
"cdn-apple.com": "apple",
|
||||
"apple-mapkit.com": "apple",
|
||||
"icons.axm-usercontent-apple.com": "apple",
|
||||
"apple-cloudkit.com": "apple",
|
||||
"apzones.com": "apple",
|
||||
"apple-livephotoskit.com": "apple",
|
||||
"safebrowsing.apple": "apple",
|
||||
"safebrowsing.g.applimg.com": "apple",
|
||||
"matrix.org": "matrix",
|
||||
"medialab.la": "medialab",
|
||||
"media-lab.ai": "medialab",
|
||||
"phicdn.net": "digicert_trust_seal",
|
||||
"e-msedge.net": "msedge",
|
||||
"l-msedge.net": "msedge",
|
||||
"solaredge.com": "solaredge",
|
||||
"telstra.com.au": "telstra",
|
||||
"telstra.com": "telstra",
|
||||
"usertrust.com": "trustlogo",
|
||||
"unityads.unity3d.com": "unity_ads",
|
||||
"exp-tas.com": "vscode",
|
||||
"vscode-unpkg.net": "vscode",
|
||||
"v0cdn.net": "vscode",
|
||||
"vscode-cdn.net": "vscode",
|
||||
"iadsdk.apple.com": "apple_ads",
|
||||
"showrss.info": "showrss",
|
||||
"sectigo.com": "sectigo",
|
||||
"solaredge.com": "solaredge",
|
||||
"crashlytics.com": "crashlytics",
|
||||
"cloudflare-dns.com": "cloudflare",
|
||||
"flurry.com": "flurry",
|
||||
"hockeyapp.net": "hockeyapp",
|
||||
"app-measurement.com": "firebase",
|
||||
"appmetrica.yandex.com": "yandex_appmetrica",
|
||||
"letsencrypt.org": "lets_encrypt",
|
||||
"lencr.org": "lets_encrypt",
|
||||
"oztam.com.au": "oztam",
|
||||
"mobileapptracking.com": "branch",
|
||||
"ntp.org": "ntppool",
|
||||
"ntppool.org": "ntppool",
|
||||
"plex.tv": "plex",
|
||||
"plex.direct": "plex",
|
||||
"edgecastcdn.net": "markmonitor",
|
||||
"appcenter.ms": "appcenter",
|
||||
"unityads.unity3d.com": "unity_ads",
|
||||
"usertrust.com": "trustlogo",
|
||||
"azure.com": "azure",
|
||||
"trafficmanager.net": "azure",
|
||||
"hotmail.com": "outlook",
|
||||
"outlook.com": "outlook",
|
||||
"bttn.io": "button",
|
||||
"pki.goog": "google_trust_services",
|
||||
"xtracloud.net": "qualcomm",
|
||||
"qualcomm.com": "qualcomm",
|
||||
"gmail.com": "gmail"
|
||||
"whatsapp.net": "whatsapp",
|
||||
"whatsapp.com": "whatsapp",
|
||||
"maps.windows.com": "windows_maps",
|
||||
"client.wns.windows.com": "windows_notifications",
|
||||
"time.windows.com": "windows_time",
|
||||
"windowsupdate.com": "windowsupdate",
|
||||
"ya.ru": "yandex",
|
||||
"yandex.by": "yandex",
|
||||
"yandex.com": "yandex",
|
||||
"yandex.com.tr": "yandex",
|
||||
"yandex.fr": "yandex",
|
||||
"yandex.kz": "yandex",
|
||||
"appmetrica.yandex.com": "yandex_appmetrica"
|
||||
}
|
||||
}
|
|
@ -45,8 +45,10 @@ type DHCPServer interface {
|
|||
AddStaticLease(l *Lease) (err error)
|
||||
// RemoveStaticLease - remove a static lease
|
||||
RemoveStaticLease(l *Lease) (err error)
|
||||
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||
FindMACbyIP(ip net.IP) net.HardwareAddr
|
||||
|
||||
// FindMACbyIP returns a MAC address by the IP address of its lease, if
|
||||
// there is one.
|
||||
FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr)
|
||||
|
||||
// WriteDiskConfig4 - copy disk configuration
|
||||
WriteDiskConfig4(c *V4ServerConf)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
|
@ -42,7 +43,11 @@ type Lease struct {
|
|||
|
||||
Hostname string `json:"hostname"`
|
||||
HWAddr net.HardwareAddr `json:"mac"`
|
||||
IP net.IP `json:"ip"`
|
||||
|
||||
// IP is the IP address leased to the client.
|
||||
//
|
||||
// TODO(a.garipov): Migrate leases.db and use netip.Addr.
|
||||
IP net.IP `json:"ip"`
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of l.
|
||||
|
@ -160,7 +165,7 @@ type Interface interface {
|
|||
|
||||
Leases(flags GetLeasesFlags) (leases []*Lease)
|
||||
SetOnLeaseChanged(onLeaseChanged OnLeaseChangedT)
|
||||
FindMACbyIP(ip net.IP) (mac net.HardwareAddr)
|
||||
FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr)
|
||||
|
||||
WriteDiskConfig(c *ServerConfig)
|
||||
}
|
||||
|
@ -174,7 +179,7 @@ type MockInterface struct {
|
|||
OnEnabled func() (ok bool)
|
||||
OnLeases func(flags GetLeasesFlags) (leases []*Lease)
|
||||
OnSetOnLeaseChanged func(f OnLeaseChangedT)
|
||||
OnFindMACbyIP func(ip net.IP) (mac net.HardwareAddr)
|
||||
OnFindMACbyIP func(ip netip.Addr) (mac net.HardwareAddr)
|
||||
OnWriteDiskConfig func(c *ServerConfig)
|
||||
}
|
||||
|
||||
|
@ -195,8 +200,10 @@ func (s *MockInterface) Leases(flags GetLeasesFlags) (ls []*Lease) { return s.On
|
|||
// SetOnLeaseChanged implements the Interface for *MockInterface.
|
||||
func (s *MockInterface) SetOnLeaseChanged(f OnLeaseChangedT) { s.OnSetOnLeaseChanged(f) }
|
||||
|
||||
// FindMACbyIP implements the Interface for *MockInterface.
|
||||
func (s *MockInterface) FindMACbyIP(ip net.IP) (mac net.HardwareAddr) { return s.OnFindMACbyIP(ip) }
|
||||
// FindMACbyIP implements the [Interface] for *MockInterface.
|
||||
func (s *MockInterface) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
|
||||
return s.OnFindMACbyIP(ip)
|
||||
}
|
||||
|
||||
// WriteDiskConfig implements the Interface for *MockInterface.
|
||||
func (s *MockInterface) WriteDiskConfig(c *ServerConfig) { s.OnWriteDiskConfig(c) }
|
||||
|
@ -375,11 +382,13 @@ func (s *server) Leases(flags GetLeasesFlags) (leases []*Lease) {
|
|||
return append(s.srv4.GetLeases(flags), s.srv6.GetLeases(flags)...)
|
||||
}
|
||||
|
||||
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||
func (s *server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||
if ip.To4() != nil {
|
||||
// FindMACbyIP returns a MAC address by the IP address of its lease, if there is
|
||||
// one.
|
||||
func (s *server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
|
||||
if ip.Is4() {
|
||||
return s.srv4.FindMACbyIP(ip)
|
||||
}
|
||||
|
||||
return s.srv6.FindMACbyIP(ip)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,23 +4,26 @@ package dhcpd
|
|||
|
||||
// 'u-root/u-root' package, a dependency of 'insomniacslk/dhcp' package, doesn't build on Windows
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
type winServer struct{}
|
||||
|
||||
// type check
|
||||
var _ DHCPServer = winServer{}
|
||||
|
||||
func (winServer) ResetLeases(_ []*Lease) (err error) { return nil }
|
||||
func (winServer) GetLeases(_ GetLeasesFlags) (leases []*Lease) { return nil }
|
||||
func (winServer) getLeasesRef() []*Lease { return nil }
|
||||
func (winServer) AddStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) RemoveStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) FindMACbyIP(_ net.IP) (mac net.HardwareAddr) { return nil }
|
||||
func (winServer) WriteDiskConfig4(_ *V4ServerConf) {}
|
||||
func (winServer) WriteDiskConfig6(_ *V6ServerConf) {}
|
||||
func (winServer) Start() (err error) { return nil }
|
||||
func (winServer) Stop() (err error) { return nil }
|
||||
func (winServer) ResetLeases(_ []*Lease) (err error) { return nil }
|
||||
func (winServer) GetLeases(_ GetLeasesFlags) (leases []*Lease) { return nil }
|
||||
func (winServer) getLeasesRef() []*Lease { return nil }
|
||||
func (winServer) AddStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) RemoveStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) FindMACbyIP(_ netip.Addr) (mac net.HardwareAddr) { return nil }
|
||||
func (winServer) WriteDiskConfig4(_ *V4ServerConf) {}
|
||||
func (winServer) WriteDiskConfig6(_ *V6ServerConf) {}
|
||||
func (winServer) Start() (err error) { return nil }
|
||||
func (winServer) Stop() (err error) { return nil }
|
||||
|
||||
func v4Create(_ *V4ServerConf) (s DHCPServer, err error) { return winServer{}, nil }
|
||||
func v6Create(_ V6ServerConf) (s DHCPServer, err error) { return winServer{}, nil }
|
||||
|
|
|
@ -200,20 +200,20 @@ func (s *v4Server) GetLeases(flags GetLeasesFlags) (leases []*Lease) {
|
|||
return leases
|
||||
}
|
||||
|
||||
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||
func (s *v4Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||
// FindMACbyIP implements the [Interface] for *v4Server.
|
||||
func (s *v4Server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
|
||||
now := time.Now()
|
||||
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
ip4 := ip.To4()
|
||||
if ip4 == nil {
|
||||
if !ip.Is4() {
|
||||
return nil
|
||||
}
|
||||
|
||||
netIP := ip.AsSlice()
|
||||
for _, l := range s.leases {
|
||||
if l.IP.Equal(ip4) {
|
||||
if l.IP.Equal(netIP) {
|
||||
if l.Expiry.After(now) || l.IsStatic() {
|
||||
return l.HWAddr
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -107,21 +108,26 @@ func (s *v6Server) getLeasesRef() []*Lease {
|
|||
return s.leases
|
||||
}
|
||||
|
||||
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||
func (s *v6Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||
now := time.Now().Unix()
|
||||
// FindMACbyIP implements the [Interface] for *v6Server.
|
||||
func (s *v6Server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
|
||||
now := time.Now()
|
||||
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
if !ip.Is6() {
|
||||
return nil
|
||||
}
|
||||
|
||||
netIP := ip.AsSlice()
|
||||
for _, l := range s.leases {
|
||||
if l.IP.Equal(ip) {
|
||||
unix := l.Expiry.Unix()
|
||||
if unix > now || unix == leaseExpireStatic {
|
||||
if l.IP.Equal(netIP) {
|
||||
if l.Expiry.After(now) || l.IsStatic() {
|
||||
return l.HWAddr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ const (
|
|||
// The zero FilteringConfig is empty and ready for use.
|
||||
type FilteringConfig struct {
|
||||
// Callbacks for other modules
|
||||
// --
|
||||
|
||||
// FilterHandler is an optional additional filtering callback.
|
||||
FilterHandler func(clientAddr net.IP, clientID string, settings *filtering.Settings) `yaml:"-"`
|
||||
|
@ -64,50 +63,82 @@ type FilteringConfig struct {
|
|||
GetCustomUpstreamByClient func(id string) (conf *proxy.UpstreamConfig, err error) `yaml:"-"`
|
||||
|
||||
// Protection configuration
|
||||
// --
|
||||
|
||||
ProtectionEnabled bool `yaml:"protection_enabled"` // whether or not use any of filtering features
|
||||
BlockingMode BlockingMode `yaml:"blocking_mode"` // mode how to answer filtered requests
|
||||
BlockingIPv4 net.IP `yaml:"blocking_ipv4"` // IP address to be returned for a blocked A request
|
||||
BlockingIPv6 net.IP `yaml:"blocking_ipv6"` // IP address to be returned for a blocked AAAA request
|
||||
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"` // if 0, then default is used (3600)
|
||||
// ProtectionEnabled defines whether or not use any of filtering features.
|
||||
ProtectionEnabled bool `yaml:"protection_enabled"`
|
||||
|
||||
// IP (or domain name) which is used to respond to DNS requests blocked by parental control or safe-browsing
|
||||
ParentalBlockHost string `yaml:"parental_block_host"`
|
||||
// BlockingMode defines the way how blocked responses are constructed.
|
||||
BlockingMode BlockingMode `yaml:"blocking_mode"`
|
||||
|
||||
// BlockingIPv4 is the IP address to be returned for a blocked A request.
|
||||
BlockingIPv4 net.IP `yaml:"blocking_ipv4"`
|
||||
|
||||
// BlockingIPv6 is the IP address to be returned for a blocked AAAA
|
||||
// request.
|
||||
BlockingIPv6 net.IP `yaml:"blocking_ipv6"`
|
||||
|
||||
// BlockedResponseTTL is the time-to-live value for blocked responses. If
|
||||
// 0, then default value is used (3600).
|
||||
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"`
|
||||
|
||||
// ParentalBlockHost is the IP (or domain name) which is used to respond to
|
||||
// DNS requests blocked by parental control.
|
||||
ParentalBlockHost string `yaml:"parental_block_host"`
|
||||
|
||||
// SafeBrowsingBlockHost is the IP (or domain name) which is used to
|
||||
// respond to DNS requests blocked by safe-browsing.
|
||||
SafeBrowsingBlockHost string `yaml:"safebrowsing_block_host"`
|
||||
|
||||
// Anti-DNS amplification
|
||||
// --
|
||||
|
||||
Ratelimit uint32 `yaml:"ratelimit"` // max number of requests per second from a given IP (0 to disable)
|
||||
RatelimitWhitelist []string `yaml:"ratelimit_whitelist"` // a list of whitelisted client IP addresses
|
||||
RefuseAny bool `yaml:"refuse_any"` // if true, refuse ANY requests
|
||||
// Ratelimit is the maximum number of requests per second from a given IP
|
||||
// (0 to disable).
|
||||
Ratelimit uint32 `yaml:"ratelimit"`
|
||||
|
||||
// RatelimitWhitelist is the list of whitelisted client IP addresses.
|
||||
RatelimitWhitelist []string `yaml:"ratelimit_whitelist"`
|
||||
|
||||
// RefuseAny, if true, refuse ANY requests.
|
||||
RefuseAny bool `yaml:"refuse_any"`
|
||||
|
||||
// Upstream DNS servers configuration
|
||||
// --
|
||||
|
||||
UpstreamDNS []string `yaml:"upstream_dns"`
|
||||
UpstreamDNSFileName string `yaml:"upstream_dns_file"`
|
||||
BootstrapDNS []string `yaml:"bootstrap_dns"` // a list of bootstrap DNS for DoH and DoT (plain DNS only)
|
||||
AllServers bool `yaml:"all_servers"` // if true, parallel queries to all configured upstream servers are enabled
|
||||
FastestAddr bool `yaml:"fastest_addr"` // use Fastest Address algorithm
|
||||
// UpstreamDNS is the list of upstream DNS servers.
|
||||
UpstreamDNS []string `yaml:"upstream_dns"`
|
||||
|
||||
// UpstreamDNSFileName, if set, points to the file which contains upstream
|
||||
// DNS servers.
|
||||
UpstreamDNSFileName string `yaml:"upstream_dns_file"`
|
||||
|
||||
// BootstrapDNS is the list of bootstrap DNS servers for DoH and DoT
|
||||
// resolvers (plain DNS only).
|
||||
BootstrapDNS []string `yaml:"bootstrap_dns"`
|
||||
|
||||
// AllServers, if true, parallel queries to all configured upstream servers
|
||||
// are enabled.
|
||||
AllServers bool `yaml:"all_servers"`
|
||||
|
||||
// FastestAddr, if true, use Fastest Address algorithm.
|
||||
FastestAddr bool `yaml:"fastest_addr"`
|
||||
|
||||
// FastestTimeout replaces the default timeout for dialing IP addresses
|
||||
// when FastestAddr is true.
|
||||
FastestTimeout timeutil.Duration `yaml:"fastest_timeout"`
|
||||
|
||||
// Access settings
|
||||
// --
|
||||
|
||||
// AllowedClients is the slice of IP addresses, CIDR networks, and ClientIDs
|
||||
// of allowed clients. If not empty, only these clients are allowed, and
|
||||
// [FilteringConfig.DisallowedClients] are ignored.
|
||||
// AllowedClients is the slice of IP addresses, CIDR networks, and
|
||||
// ClientIDs of allowed clients. If not empty, only these clients are
|
||||
// allowed, and [FilteringConfig.DisallowedClients] are ignored.
|
||||
AllowedClients []string `yaml:"allowed_clients"`
|
||||
|
||||
// DisallowedClients is the slice of IP addresses, CIDR networks, and
|
||||
// ClientIDs of disallowed clients.
|
||||
DisallowedClients []string `yaml:"disallowed_clients"`
|
||||
|
||||
BlockedHosts []string `yaml:"blocked_hosts"` // hosts that should be blocked
|
||||
// BlockedHosts is the list of hosts that should be blocked.
|
||||
BlockedHosts []string `yaml:"blocked_hosts"`
|
||||
|
||||
// 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
|
||||
|
@ -115,26 +146,46 @@ type FilteringConfig struct {
|
|||
TrustedProxies []string `yaml:"trusted_proxies"`
|
||||
|
||||
// DNS cache settings
|
||||
// --
|
||||
|
||||
CacheSize uint32 `yaml:"cache_size"` // DNS cache size (in bytes)
|
||||
CacheMinTTL uint32 `yaml:"cache_ttl_min"` // override TTL value (minimum) received from upstream server
|
||||
CacheMaxTTL uint32 `yaml:"cache_ttl_max"` // override TTL value (maximum) received from upstream server
|
||||
// CacheSize is the DNS cache size (in bytes).
|
||||
CacheSize uint32 `yaml:"cache_size"`
|
||||
|
||||
// CacheMinTTL is the override TTL value (minimum) received from upstream
|
||||
// server.
|
||||
CacheMinTTL uint32 `yaml:"cache_ttl_min"`
|
||||
|
||||
// CacheMaxTTL is the override TTL value (maximum) received from upstream
|
||||
// server.
|
||||
CacheMaxTTL uint32 `yaml:"cache_ttl_max"`
|
||||
|
||||
// CacheOptimistic defines if optimistic cache mechanism should be used.
|
||||
CacheOptimistic bool `yaml:"cache_optimistic"`
|
||||
|
||||
// Other settings
|
||||
// --
|
||||
|
||||
BogusNXDomain []string `yaml:"bogus_nxdomain"` // transform responses with these IP addresses to NXDOMAIN
|
||||
AAAADisabled bool `yaml:"aaaa_disabled"` // Respond with an empty answer to all AAAA requests
|
||||
EnableDNSSEC bool `yaml:"enable_dnssec"` // Set AD flag in outcoming DNS request
|
||||
EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option
|
||||
MaxGoroutines uint32 `yaml:"max_goroutines"` // Max. number of parallel goroutines for processing incoming requests
|
||||
HandleDDR bool `yaml:"handle_ddr"` // Handle DDR requests
|
||||
// BogusNXDomain is the list of IP addresses, responses with them will be
|
||||
// transformed to NXDOMAIN.
|
||||
BogusNXDomain []string `yaml:"bogus_nxdomain"`
|
||||
|
||||
// IpsetList is the ipset configuration that allows AdGuard Home to add
|
||||
// IP addresses of the specified domain names to an ipset list. Syntax:
|
||||
// AAAADisabled, if true, respond with an empty answer to all AAAA
|
||||
// requests.
|
||||
AAAADisabled bool `yaml:"aaaa_disabled"`
|
||||
|
||||
// EnableDNSSEC, if true, set AD flag in outcoming DNS request.
|
||||
EnableDNSSEC bool `yaml:"enable_dnssec"`
|
||||
|
||||
// EDNSClientSubnet is the settings list for EDNS Client Subnet.
|
||||
EDNSClientSubnet *EDNSClientSubnet `yaml:"edns_client_subnet"`
|
||||
|
||||
// MaxGoroutines is the max number of parallel goroutines for processing
|
||||
// incoming requests.
|
||||
MaxGoroutines uint32 `yaml:"max_goroutines"`
|
||||
|
||||
// HandleDDR, if true, handle DDR requests
|
||||
HandleDDR bool `yaml:"handle_ddr"`
|
||||
|
||||
// IpsetList is the ipset configuration that allows AdGuard Home to add IP
|
||||
// addresses of the specified domain names to an ipset list. Syntax:
|
||||
//
|
||||
// DOMAIN[,DOMAIN].../IPSET_NAME
|
||||
//
|
||||
|
@ -146,6 +197,18 @@ type FilteringConfig struct {
|
|||
IpsetListFileName string `yaml:"ipset_file"`
|
||||
}
|
||||
|
||||
// EDNSClientSubnet is the settings list for EDNS Client Subnet.
|
||||
type EDNSClientSubnet struct {
|
||||
// CustomIP for EDNS Client Subnet.
|
||||
CustomIP string `yaml:"custom_ip"`
|
||||
|
||||
// Enabled defines if EDNS Client Subnet is enabled.
|
||||
Enabled bool `yaml:"enabled"`
|
||||
|
||||
// UseCustom defines if CustomIP should be used.
|
||||
UseCustom bool `yaml:"use_custom"`
|
||||
}
|
||||
|
||||
// TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS
|
||||
type TLSConfig struct {
|
||||
cert tls.Certificate
|
||||
|
@ -270,12 +333,24 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
|
|||
UpstreamConfig: srvConf.UpstreamConfig,
|
||||
BeforeRequestHandler: s.beforeRequestHandler,
|
||||
RequestHandler: s.handleDNSRequest,
|
||||
EnableEDNSClientSubnet: srvConf.EnableEDNSClientSubnet,
|
||||
EnableEDNSClientSubnet: srvConf.EDNSClientSubnet.Enabled,
|
||||
MaxGoroutines: int(srvConf.MaxGoroutines),
|
||||
UseDNS64: srvConf.UseDNS64,
|
||||
DNS64Prefs: srvConf.DNS64Prefixes,
|
||||
}
|
||||
|
||||
if srvConf.EDNSClientSubnet.UseCustom {
|
||||
// TODO(s.chzhen): Add wrapper around netip.Addr.
|
||||
var ip net.IP
|
||||
ip, err = netutil.ParseIP(srvConf.EDNSClientSubnet.CustomIP)
|
||||
if err != nil {
|
||||
return conf, fmt.Errorf("edns: %w", err)
|
||||
}
|
||||
|
||||
// TODO(s.chzhen): Use netip.Addr instead of net.IP inside dnsproxy.
|
||||
conf.EDNSAddr = ip
|
||||
}
|
||||
|
||||
if srvConf.CacheSize != 0 {
|
||||
conf.CacheEnabled = true
|
||||
conf.CacheSizeBytes = int(srvConf.CacheSize)
|
||||
|
|
|
@ -287,6 +287,9 @@ func TestServer_HandleDNSRequest_dns64(t *testing.T) {
|
|||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
UseDNS64: true,
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, localUps)
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
|
|
@ -467,6 +467,11 @@ func TestServer_ProcessRestrictLocal(t *testing.T) {
|
|||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
|
||||
// Improve FilteringConfig declaration for tests.
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, ups)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{ups}
|
||||
startDeferStop(t, s)
|
||||
|
@ -539,6 +544,9 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
|
|||
ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
},
|
||||
aghtest.NewUpstreamMock(func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return aghalg.Coalesce(
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
@ -155,6 +156,9 @@ func createTestTLS(t *testing.T, tlsConf TLSConfig) (s *Server, certPem []byte)
|
|||
s = createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
tlsConf.CertificateChainData, tlsConf.PrivateKeyData = certPem, keyPem
|
||||
|
@ -266,6 +270,9 @@ func TestServer(t *testing.T) {
|
|||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{newGoogleUpstream()}
|
||||
startDeferStop(t, s)
|
||||
|
@ -304,7 +311,8 @@ func TestServer_timeout(t *testing.T) {
|
|||
srvConf := &ServerConfig{
|
||||
UpstreamTimeout: timeout,
|
||||
FilteringConfig: FilteringConfig{
|
||||
BlockingMode: BlockingModeDefault,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -322,6 +330,9 @@ func TestServer_timeout(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
}
|
||||
err = s.Prepare(&s.conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -333,6 +344,9 @@ func TestServerWithProtectionDisabled(t *testing.T) {
|
|||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, nil)
|
||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{newGoogleUpstream()}
|
||||
startDeferStop(t, s)
|
||||
|
@ -437,6 +451,9 @@ func TestSafeSearch(t *testing.T) {
|
|||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||
|
@ -492,6 +509,11 @@ func TestInvalidRequest(t *testing.T) {
|
|||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
startDeferStop(t, s)
|
||||
|
||||
|
@ -518,6 +540,9 @@ func TestBlockedRequest(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
|
@ -543,6 +568,9 @@ func TestServerCustomClientUpstream(t *testing.T) {
|
|||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
|
@ -591,6 +619,11 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
|||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
testUpstm := &aghtest.Upstream{
|
||||
CName: testCNAMEs,
|
||||
|
@ -621,6 +654,9 @@ func TestBlockCNAME(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
|
@ -690,6 +726,9 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
|
|||
FilterHandler: func(_ net.IP, _ string, settings *filtering.Settings) {
|
||||
settings.FilteringEnabled = false
|
||||
},
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
|
@ -731,6 +770,9 @@ func TestNullBlockedRequest(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeNullIP,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
||||
|
@ -783,6 +825,9 @@ func TestBlockedCustomIP(t *testing.T) {
|
|||
BlockingMode: BlockingModeCustomIP,
|
||||
BlockingIPv4: nil,
|
||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -831,6 +876,9 @@ func TestBlockedByHosts(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -864,6 +912,9 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
SafeBrowsingBlockHost: ans4.String(),
|
||||
ProtectionEnabled: true,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||
|
@ -918,6 +969,9 @@ func TestRewrite(t *testing.T) {
|
|||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
UpstreamDNS: []string{"8.8.8.8:53"},
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
|
@ -1009,7 +1063,7 @@ var testDHCP = &dhcpd.MockInterface{
|
|||
}}
|
||||
},
|
||||
OnSetOnLeaseChanged: func(olct dhcpd.OnLeaseChangedT) {},
|
||||
OnFindMACbyIP: func(ip net.IP) (mac net.HardwareAddr) { panic("not implemented") },
|
||||
OnFindMACbyIP: func(ip netip.Addr) (mac net.HardwareAddr) { panic("not implemented") },
|
||||
OnWriteDiskConfig: func(c *dhcpd.ServerConfig) { panic("not implemented") },
|
||||
}
|
||||
|
||||
|
@ -1032,6 +1086,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
|||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
||||
|
||||
err = s.Prepare(&s.conf)
|
||||
require.NoError(t, err)
|
||||
|
@ -1107,6 +1162,7 @@ func TestPTRResponseFromHosts(t *testing.T) {
|
|||
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
||||
|
||||
err = s.Prepare(&s.conf)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -29,6 +29,9 @@ func TestHandleDNSRequest_filterDNSResponse(t *testing.T) {
|
|||
FilteringConfig: FilteringConfig{
|
||||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
EDNSClientSubnet: &EDNSClientSubnet{
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
filters := []filtering.Filter{{
|
||||
|
|
|
@ -57,7 +57,7 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) {
|
|||
blockingIPv4 := s.conf.BlockingIPv4
|
||||
blockingIPv6 := s.conf.BlockingIPv6
|
||||
ratelimit := s.conf.Ratelimit
|
||||
enableEDNSClientSubnet := s.conf.EnableEDNSClientSubnet
|
||||
enableEDNSClientSubnet := s.conf.EDNSClientSubnet.Enabled
|
||||
enableDNSSEC := s.conf.EnableDNSSEC
|
||||
aaaaDisabled := s.conf.AAAADisabled
|
||||
cacheSize := s.conf.CacheSize
|
||||
|
@ -280,7 +280,7 @@ func (s *Server) setConfigRestartable(dc *jsonDNSConfig) (shouldRestart bool) {
|
|||
setIfNotNil(&s.conf.LocalPTRResolvers, dc.LocalPTRUpstreams),
|
||||
setIfNotNil(&s.conf.UpstreamDNSFileName, dc.UpstreamsFile),
|
||||
setIfNotNil(&s.conf.BootstrapDNS, dc.Bootstraps),
|
||||
setIfNotNil(&s.conf.EnableEDNSClientSubnet, dc.EDNSCSEnabled),
|
||||
setIfNotNil(&s.conf.EDNSClientSubnet.Enabled, dc.EDNSCSEnabled),
|
||||
setIfNotNil(&s.conf.CacheSize, dc.CacheSize),
|
||||
setIfNotNil(&s.conf.CacheMinTTL, dc.CacheMinTTL),
|
||||
setIfNotNil(&s.conf.CacheMaxTTL, dc.CacheMaxTTL),
|
||||
|
|
|
@ -69,6 +69,7 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
|||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
ConfigModified: func() {},
|
||||
}
|
||||
|
@ -144,6 +145,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
|||
ProtectionEnabled: true,
|
||||
BlockingMode: BlockingModeDefault,
|
||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
ConfigModified: func() {},
|
||||
}
|
||||
|
@ -227,7 +229,10 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
|||
require.True(t, ok)
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Cleanup(func() { s.conf = defaultConf })
|
||||
t.Cleanup(func() {
|
||||
s.conf = defaultConf
|
||||
s.conf.FilteringConfig.EDNSClientSubnet.Enabled = false
|
||||
})
|
||||
|
||||
rBody := io.NopCloser(bytes.NewReader(caseData.Req))
|
||||
var r *http.Request
|
||||
|
@ -443,6 +448,9 @@ func TestServer_handleTestUpstreaDNS(t *testing.T) {
|
|||
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||
UpstreamTimeout: upsTimeout,
|
||||
FilteringConfig: FilteringConfig{
|
||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||
},
|
||||
}, nil)
|
||||
startDeferStop(t, srv)
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ var blockedServices = []blockedService{{
|
|||
"||amazon.jp^",
|
||||
"||amazon.nl^",
|
||||
"||amazon.red^",
|
||||
"||amazon.se^",
|
||||
"||amazon.sg^",
|
||||
"||amazon^",
|
||||
"||amazonalexavoxcon.com^",
|
||||
|
@ -1290,6 +1291,14 @@ var blockedServices = []blockedService{{
|
|||
"||iq.com^",
|
||||
"||iqiyi.com^",
|
||||
},
|
||||
}, {
|
||||
ID: "kakaotalk",
|
||||
Name: "KakaoTalk",
|
||||
IconSVG: []byte("<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" viewBox=\"0 0 24 24\" ><path d=\"M22.125 0H1.875C.839 0 0 .84 0 1.875v20.25C0 23.161.84 24 1.875 24h20.25C23.161 24 24 23.16 24 22.125V1.875C24 .839 23.16 0 22.125 0zM12 18.75c-.591 0-1.17-.041-1.732-.12-.562.396-3.813 2.679-4.12 2.722 0 0-.125.049-.232-.014s-.088-.229-.088-.229c.032-.22.843-3.018.992-3.533-2.745-1.36-4.57-3.769-4.57-6.513 0-4.246 4.365-7.688 9.75-7.688s9.75 3.442 9.75 7.688c0 4.245-4.365 7.687-9.75 7.687zM8.05 9.867h-.878v3.342c0 .296-.252.537-.563.537s-.562-.24-.562-.537V9.867h-.878a.552.552 0 0 1 0-1.101h2.88a.552.552 0 0 1 0 1.101zm10.987 2.957a.558.558 0 0 1 .109.417.559.559 0 0 1-.219.37.557.557 0 0 1-.338.114.558.558 0 0 1-.45-.224l-1.319-1.747-.195.195v1.227a.564.564 0 0 1-.562.563.563.563 0 0 1-.563-.563V9.328a.563.563 0 0 1 1.125 0v1.21l1.57-1.57a.437.437 0 0 1 .311-.126c.14 0 .282.061.388.167a.555.555 0 0 1 .165.356.438.438 0 0 1-.124.343l-1.282 1.281 1.385 1.835zm-8.35-3.502c-.095-.27-.383-.548-.75-.556-.366.008-.654.286-.749.555l-1.345 3.541c-.171.53-.022.728.133.8a.857.857 0 0 0 .357.077c.235 0 .414-.095.468-.248l.279-.73h1.715l.279.73c.054.153.233.248.468.248a.86.86 0 0 0 .357-.078c.155-.071.304-.268.133-.8l-1.345-3.54zm-1.311 2.443.562-1.596.561 1.596H9.376zm5.905 1.383a.528.528 0 0 1-.539.516h-1.804a.528.528 0 0 1-.54-.516v-3.82c0-.31.258-.562.575-.562s.574.252.574.562v3.305h1.195c.297 0 .54.231.54.515z\"/></svg>"),
|
||||
Rules: []string{
|
||||
"||kakao.com^",
|
||||
"||kgslb.com^",
|
||||
},
|
||||
}, {
|
||||
ID: "leagueoflegends",
|
||||
Name: "League of Legends",
|
||||
|
@ -1336,13 +1345,13 @@ var blockedServices = []blockedService{{
|
|||
"||aus.social^",
|
||||
"||awscommunity.social^",
|
||||
"||cyberplace.social^",
|
||||
"||defcon.social^",
|
||||
"||det.social^",
|
||||
"||fosstodon.org^",
|
||||
"||glasgow.social^",
|
||||
"||h4.io^",
|
||||
"||hachyderm.io^",
|
||||
"||hessen.social^",
|
||||
"||home.social^",
|
||||
"||hostux.social^",
|
||||
"||ieji.de^",
|
||||
"||indieweb.social^",
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
)
|
||||
|
||||
// Client contains information about persistent clients.
|
||||
type Client struct {
|
||||
// upstreamConfig is the custom upstream config for this client. If
|
||||
// it's nil, it has not been initialized yet. If it's non-nil and
|
||||
// empty, there are no valid upstreams. If it's non-nil and non-empty,
|
||||
// these upstream must be used.
|
||||
upstreamConfig *proxy.UpstreamConfig
|
||||
|
||||
Name string
|
||||
|
||||
IDs []string
|
||||
Tags []string
|
||||
BlockedServices []string
|
||||
Upstreams []string
|
||||
|
||||
UseOwnSettings bool
|
||||
FilteringEnabled bool
|
||||
SafeSearchEnabled bool
|
||||
SafeBrowsingEnabled bool
|
||||
ParentalEnabled bool
|
||||
UseOwnBlockedServices bool
|
||||
}
|
||||
|
||||
// closeUpstreams closes the client-specific upstream config of c if any.
|
||||
func (c *Client) closeUpstreams() (err error) {
|
||||
if c.upstreamConfig != nil {
|
||||
err = c.upstreamConfig.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing upstreams of client %q: %w", c.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// clientSource represents the source from which the information about the
|
||||
// client has been obtained.
|
||||
type clientSource uint
|
||||
|
||||
// Clients information sources. The order determines the priority.
|
||||
const (
|
||||
ClientSourceNone clientSource = iota
|
||||
ClientSourceWHOIS
|
||||
ClientSourceARP
|
||||
ClientSourceRDNS
|
||||
ClientSourceDHCP
|
||||
ClientSourceHostsFile
|
||||
ClientSourcePersistent
|
||||
)
|
||||
|
||||
// type check
|
||||
var _ fmt.Stringer = clientSource(0)
|
||||
|
||||
// String returns a human-readable name of cs.
|
||||
func (cs clientSource) String() (s string) {
|
||||
switch cs {
|
||||
case ClientSourceWHOIS:
|
||||
return "WHOIS"
|
||||
case ClientSourceARP:
|
||||
return "ARP"
|
||||
case ClientSourceRDNS:
|
||||
return "rDNS"
|
||||
case ClientSourceDHCP:
|
||||
return "DHCP"
|
||||
case ClientSourceHostsFile:
|
||||
return "etc/hosts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ encoding.TextMarshaler = clientSource(0)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler for the clientSource.
|
||||
func (cs clientSource) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
||||
// RuntimeClient is a client information about which has been obtained using the
|
||||
// source described in the Source field.
|
||||
type RuntimeClient struct {
|
||||
WHOISInfo *RuntimeClientWHOISInfo
|
||||
Host string
|
||||
Source clientSource
|
||||
}
|
||||
|
||||
// RuntimeClientWHOISInfo is the filtered WHOIS data for a runtime client.
|
||||
type RuntimeClientWHOISInfo struct {
|
||||
City string `json:"city,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Orgname string `json:"orgname,omitempty"`
|
||||
}
|
|
@ -2,7 +2,6 @@ package home
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
@ -25,122 +24,16 @@ import (
|
|||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const clientsUpdatePeriod = 10 * time.Minute
|
||||
|
||||
var webHandlersRegistered = false
|
||||
|
||||
// Client contains information about persistent clients.
|
||||
type Client struct {
|
||||
// upstreamConfig is the custom upstream config for this client. If
|
||||
// it's nil, it has not been initialized yet. If it's non-nil and
|
||||
// empty, there are no valid upstreams. If it's non-nil and non-empty,
|
||||
// these upstream must be used.
|
||||
upstreamConfig *proxy.UpstreamConfig
|
||||
|
||||
Name string
|
||||
|
||||
IDs []string
|
||||
Tags []string
|
||||
BlockedServices []string
|
||||
Upstreams []string
|
||||
|
||||
UseOwnSettings bool
|
||||
FilteringEnabled bool
|
||||
SafeSearchEnabled bool
|
||||
SafeBrowsingEnabled bool
|
||||
ParentalEnabled bool
|
||||
UseOwnBlockedServices bool
|
||||
}
|
||||
|
||||
// closeUpstreams closes the client-specific upstream config of c if any.
|
||||
func (c *Client) closeUpstreams() (err error) {
|
||||
if c.upstreamConfig != nil {
|
||||
err = c.upstreamConfig.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing upstreams of client %q: %w", c.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type clientSource uint
|
||||
|
||||
// Clients information sources. The order determines the priority.
|
||||
const (
|
||||
ClientSourceNone clientSource = iota
|
||||
ClientSourceWHOIS
|
||||
ClientSourceARP
|
||||
ClientSourceRDNS
|
||||
ClientSourceDHCP
|
||||
ClientSourceHostsFile
|
||||
ClientSourcePersistent
|
||||
)
|
||||
|
||||
// type check
|
||||
var _ fmt.Stringer = clientSource(0)
|
||||
|
||||
// String returns a human-readable name of cs.
|
||||
func (cs clientSource) String() (s string) {
|
||||
switch cs {
|
||||
case ClientSourceWHOIS:
|
||||
return "WHOIS"
|
||||
case ClientSourceARP:
|
||||
return "ARP"
|
||||
case ClientSourceRDNS:
|
||||
return "rDNS"
|
||||
case ClientSourceDHCP:
|
||||
return "DHCP"
|
||||
case ClientSourceHostsFile:
|
||||
return "etc/hosts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ encoding.TextMarshaler = clientSource(0)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler for the clientSource.
|
||||
func (cs clientSource) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
||||
// clientSourceConf is used to configure where the runtime clients will be
|
||||
// obtained from.
|
||||
type clientSourcesConf struct {
|
||||
WHOIS bool `yaml:"whois"`
|
||||
ARP bool `yaml:"arp"`
|
||||
RDNS bool `yaml:"rdns"`
|
||||
DHCP bool `yaml:"dhcp"`
|
||||
HostsFile bool `yaml:"hosts"`
|
||||
}
|
||||
|
||||
// RuntimeClient information
|
||||
type RuntimeClient struct {
|
||||
WHOISInfo *RuntimeClientWHOISInfo
|
||||
Host string
|
||||
Source clientSource
|
||||
}
|
||||
|
||||
// RuntimeClientWHOISInfo is the filtered WHOIS data for a runtime client.
|
||||
type RuntimeClientWHOISInfo struct {
|
||||
City string `json:"city,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Orgname string `json:"orgname,omitempty"`
|
||||
}
|
||||
|
||||
// clientsContainer is the storage of all runtime and persistent clients.
|
||||
type clientsContainer struct {
|
||||
// TODO(a.garipov): Perhaps use a number of separate indices for
|
||||
// different types (string, netip.Addr, and so on).
|
||||
// TODO(a.garipov): Perhaps use a number of separate indices for different
|
||||
// types (string, netip.Addr, and so on).
|
||||
list map[string]*Client // name -> client
|
||||
idIndex map[string]*Client // ID -> client
|
||||
|
||||
// ipToRC is the IP address to *RuntimeClient map.
|
||||
ipToRC map[netip.Addr]*RuntimeClient
|
||||
|
||||
lock sync.Mutex
|
||||
|
||||
allTags *stringutil.Set
|
||||
|
||||
// dhcpServer is used for looking up clients IP addresses by MAC addresses
|
||||
|
@ -156,7 +49,16 @@ type clientsContainer struct {
|
|||
// arpdb stores the neighbors retrieved from ARP.
|
||||
arpdb aghnet.ARPDB
|
||||
|
||||
testing bool // if TRUE, this object is used for internal tests
|
||||
// lock protects all fields.
|
||||
//
|
||||
// TODO(a.garipov): Use a pointer and describe which fields are protected in
|
||||
// more detail.
|
||||
lock sync.Mutex
|
||||
|
||||
// testing is a flag that disables some features for internal tests.
|
||||
//
|
||||
// TODO(a.garipov): Awful. Remove.
|
||||
testing bool
|
||||
}
|
||||
|
||||
// Init initializes clients container
|
||||
|
@ -202,24 +104,34 @@ func (clients *clientsContainer) handleHostsUpdates() {
|
|||
}
|
||||
}
|
||||
|
||||
// Start - start the module
|
||||
// webHandlersRegistered prevents a [clientsContainer] from regisering its web
|
||||
// handlers more than once.
|
||||
//
|
||||
// TODO(a.garipov): Refactor HTTP handler registration logic.
|
||||
var webHandlersRegistered = false
|
||||
|
||||
// Start starts the clients container.
|
||||
func (clients *clientsContainer) Start() {
|
||||
if !clients.testing {
|
||||
if !webHandlersRegistered {
|
||||
webHandlersRegistered = true
|
||||
clients.registerWebHandlers()
|
||||
}
|
||||
go clients.periodicUpdate()
|
||||
if clients.testing {
|
||||
return
|
||||
}
|
||||
|
||||
if !webHandlersRegistered {
|
||||
webHandlersRegistered = true
|
||||
clients.registerWebHandlers()
|
||||
}
|
||||
|
||||
go clients.periodicUpdate()
|
||||
}
|
||||
|
||||
// Reload reloads runtime clients.
|
||||
func (clients *clientsContainer) Reload() {
|
||||
// reloadARP reloads runtime clients from ARP, if configured.
|
||||
func (clients *clientsContainer) reloadARP() {
|
||||
if clients.arpdb != nil {
|
||||
clients.addFromSystemARP()
|
||||
}
|
||||
}
|
||||
|
||||
// clientObject is the YAML representation of a persistent client.
|
||||
type clientObject struct {
|
||||
Name string `yaml:"name"`
|
||||
|
||||
|
@ -317,12 +229,15 @@ func (clients *clientsContainer) forConfig() (objs []*clientObject) {
|
|||
return objs
|
||||
}
|
||||
|
||||
// arpClientsUpdatePeriod defines how often ARP clients are updated.
|
||||
const arpClientsUpdatePeriod = 10 * time.Minute
|
||||
|
||||
func (clients *clientsContainer) periodicUpdate() {
|
||||
defer log.OnPanic("clients container")
|
||||
|
||||
for {
|
||||
clients.Reload()
|
||||
time.Sleep(clientsUpdatePeriod)
|
||||
clients.reloadARP()
|
||||
time.Sleep(arpClientsUpdatePeriod)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,7 +400,8 @@ func (clients *clientsContainer) findUpstreams(
|
|||
return conf, nil
|
||||
}
|
||||
|
||||
// findLocked searches for a client by its ID. For internal use only.
|
||||
// findLocked searches for a client by its ID. clients.lock is expected to be
|
||||
// locked.
|
||||
func (clients *clientsContainer) findLocked(id string) (c *Client, ok bool) {
|
||||
c, ok = clients.idIndex[id]
|
||||
if ok {
|
||||
|
@ -499,13 +415,13 @@ func (clients *clientsContainer) findLocked(id string) (c *Client, ok bool) {
|
|||
|
||||
for _, c = range clients.list {
|
||||
for _, id := range c.IDs {
|
||||
var n netip.Prefix
|
||||
n, err = netip.ParsePrefix(id)
|
||||
var subnet netip.Prefix
|
||||
subnet, err = netip.ParsePrefix(id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if n.Contains(ip) {
|
||||
if subnet.Contains(ip) {
|
||||
return c, true
|
||||
}
|
||||
}
|
||||
|
@ -515,20 +431,25 @@ func (clients *clientsContainer) findLocked(id string) (c *Client, ok bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
macFound := clients.dhcpServer.FindMACbyIP(ip.AsSlice())
|
||||
if macFound == nil {
|
||||
return clients.findDHCP(ip)
|
||||
}
|
||||
|
||||
// findDHCP searches for a client by its MAC, if the DHCP server is active and
|
||||
// there is such client. clients.lock is expected to be locked.
|
||||
func (clients *clientsContainer) findDHCP(ip netip.Addr) (c *Client, ok bool) {
|
||||
foundMAC := clients.dhcpServer.FindMACbyIP(ip)
|
||||
if foundMAC == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
for _, c = range clients.list {
|
||||
for _, id := range c.IDs {
|
||||
var mac net.HardwareAddr
|
||||
mac, err = net.ParseMAC(id)
|
||||
mac, err := net.ParseMAC(id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if bytes.Equal(mac, macFound) {
|
||||
if bytes.Equal(mac, foundMAC) {
|
||||
return c, true
|
||||
}
|
||||
}
|
||||
|
@ -565,24 +486,13 @@ func (clients *clientsContainer) check(c *Client) (err error) {
|
|||
}
|
||||
|
||||
for i, id := range c.IDs {
|
||||
// Normalize structured data.
|
||||
var (
|
||||
ip netip.Addr
|
||||
n netip.Prefix
|
||||
mac net.HardwareAddr
|
||||
)
|
||||
|
||||
if ip, err = netip.ParseAddr(id); err == nil {
|
||||
c.IDs[i] = ip.String()
|
||||
} else if n, err = netip.ParsePrefix(id); err == nil {
|
||||
c.IDs[i] = n.String()
|
||||
} else if mac, err = net.ParseMAC(id); err == nil {
|
||||
c.IDs[i] = mac.String()
|
||||
} else if err = dnsforward.ValidateClientID(id); err == nil {
|
||||
c.IDs[i] = strings.ToLower(id)
|
||||
} else {
|
||||
return fmt.Errorf("invalid clientid at index %d: %q", i, id)
|
||||
var norm string
|
||||
norm, err = normalizeClientIdentifier(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("client at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
c.IDs[i] = norm
|
||||
}
|
||||
|
||||
for _, t := range c.Tags {
|
||||
|
@ -601,6 +511,35 @@ func (clients *clientsContainer) check(c *Client) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// normalizeClientIdentifier returns a normalized version of idStr. If idStr
|
||||
// cannot be normalized, it returns an error.
|
||||
func normalizeClientIdentifier(idStr string) (norm string, err error) {
|
||||
if idStr == "" {
|
||||
return "", errors.Error("clientid is empty")
|
||||
}
|
||||
|
||||
var ip netip.Addr
|
||||
if ip, err = netip.ParseAddr(idStr); err == nil {
|
||||
return ip.String(), nil
|
||||
}
|
||||
|
||||
var subnet netip.Prefix
|
||||
if subnet, err = netip.ParsePrefix(idStr); err == nil {
|
||||
return subnet.String(), nil
|
||||
}
|
||||
|
||||
var mac net.HardwareAddr
|
||||
if mac, err = net.ParseMAC(idStr); err == nil {
|
||||
return mac.String(), nil
|
||||
}
|
||||
|
||||
if err = dnsforward.ValidateClientID(idStr); err == nil {
|
||||
return strings.ToLower(idStr), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("bad client identifier %q", idStr)
|
||||
}
|
||||
|
||||
// Add adds a new client object. ok is false if such client already exists or
|
||||
// if an error occurred.
|
||||
func (clients *clientsContainer) Add(c *Client) (ok bool, err error) {
|
||||
|
@ -666,21 +605,6 @@ func (clients *clientsContainer) Del(name string) (ok bool) {
|
|||
return true
|
||||
}
|
||||
|
||||
// equalStringSlices returns true if the slices are equal.
|
||||
func equalStringSlices(a, b []string) (ok bool) {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Update updates a client by its name.
|
||||
func (clients *clientsContainer) Update(name string, c *Client) (err error) {
|
||||
err = clients.check(c)
|
||||
|
@ -704,22 +628,11 @@ func (clients *clientsContainer) Update(name string, c *Client) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Second, check the IP index.
|
||||
if !equalStringSlices(prev.IDs, c.IDs) {
|
||||
for _, id := range c.IDs {
|
||||
c2, ok2 := clients.idIndex[id]
|
||||
if ok2 && c2 != prev {
|
||||
return fmt.Errorf("another client uses the same id (%q): %q", id, c2.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Update ID index.
|
||||
for _, id := range prev.IDs {
|
||||
delete(clients.idIndex, id)
|
||||
}
|
||||
for _, id := range c.IDs {
|
||||
clients.idIndex[id] = prev
|
||||
}
|
||||
// Second, update the ID index.
|
||||
err = clients.updateIDIndex(prev, c.IDs)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
// Update name index.
|
||||
|
@ -739,6 +652,32 @@ func (clients *clientsContainer) Update(name string, c *Client) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// updateIDIndex updates the ID index data for cli using the information from
|
||||
// newIDs.
|
||||
func (clients *clientsContainer) updateIDIndex(cli *Client, newIDs []string) (err error) {
|
||||
if slices.Equal(cli.IDs, newIDs) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, id := range newIDs {
|
||||
existing, ok := clients.idIndex[id]
|
||||
if ok && existing != cli {
|
||||
return fmt.Errorf("id %q is used by client with name %q", id, existing.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the IDs in the index.
|
||||
for _, id := range cli.IDs {
|
||||
delete(clients.idIndex, id)
|
||||
}
|
||||
|
||||
for _, id := range newIDs {
|
||||
clients.idIndex[id] = cli
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setWHOISInfo sets the WHOIS information for a client.
|
||||
func (clients *clientsContainer) setWHOISInfo(ip netip.Addr, wi *RuntimeClientWHOISInfo) {
|
||||
clients.lock.Lock()
|
||||
|
|
|
@ -75,11 +75,21 @@ type osConfig struct {
|
|||
|
||||
type clientsConfig struct {
|
||||
// Sources defines the set of sources to fetch the runtime clients from.
|
||||
Sources *clientSourcesConf `yaml:"runtime_sources"`
|
||||
Sources *clientSourcesConfig `yaml:"runtime_sources"`
|
||||
// Persistent are the configured clients.
|
||||
Persistent []*clientObject `yaml:"persistent"`
|
||||
}
|
||||
|
||||
// clientSourceConfig is used to configure where the runtime clients will be
|
||||
// obtained from.
|
||||
type clientSourcesConfig struct {
|
||||
WHOIS bool `yaml:"whois"`
|
||||
ARP bool `yaml:"arp"`
|
||||
RDNS bool `yaml:"rdns"`
|
||||
DHCP bool `yaml:"dhcp"`
|
||||
HostsFile bool `yaml:"hosts"`
|
||||
}
|
||||
|
||||
// configuration is loaded from YAML
|
||||
// field ordering is important -- yaml fields will mirror ordering from here
|
||||
type configuration struct {
|
||||
|
@ -334,7 +344,7 @@ var config = &configuration{
|
|||
},
|
||||
},
|
||||
Clients: &clientsConfig{
|
||||
Sources: &clientSourcesConf{
|
||||
Sources: &clientSourcesConfig{
|
||||
WHOIS: true,
|
||||
ARP: true,
|
||||
RDNS: true,
|
||||
|
|
|
@ -125,7 +125,7 @@ func Main(clientBuildFS fs.FS) {
|
|||
log.Info("Received signal %q", sig)
|
||||
switch sig {
|
||||
case syscall.SIGHUP:
|
||||
Context.clients.Reload()
|
||||
Context.clients.reloadARP()
|
||||
Context.tls.reload()
|
||||
default:
|
||||
cleanup(context.Background())
|
||||
|
|
|
@ -90,6 +90,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
|||
upgradeSchema14to15,
|
||||
upgradeSchema15to16,
|
||||
upgradeSchema16to17,
|
||||
upgradeSchema17to18,
|
||||
}
|
||||
|
||||
n := 0
|
||||
|
@ -793,7 +794,7 @@ func upgradeSchema13to14(diskConf yobj) (err error) {
|
|||
|
||||
diskConf["clients"] = yobj{
|
||||
"persistent": clientsVal,
|
||||
"runtime_sources": &clientSourcesConf{
|
||||
"runtime_sources": &clientSourcesConfig{
|
||||
WHOIS: true,
|
||||
ARP: true,
|
||||
RDNS: rdnsSrc,
|
||||
|
@ -893,13 +894,13 @@ func upgradeSchema15to16(diskConf yobj) (err error) {
|
|||
"ignored": []any{},
|
||||
}
|
||||
|
||||
k := "statistics_interval"
|
||||
v, has := dns[k]
|
||||
const field = "statistics_interval"
|
||||
v, has := dns[field]
|
||||
if has {
|
||||
stats["enabled"] = v != 0
|
||||
stats["interval"] = v
|
||||
}
|
||||
delete(dns, k)
|
||||
delete(dns, field)
|
||||
|
||||
diskConf["statistics"] = stats
|
||||
|
||||
|
@ -909,15 +910,52 @@ func upgradeSchema15to16(diskConf yobj) (err error) {
|
|||
// upgradeSchema16to17 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'dns':
|
||||
// 'edns_client_subnet': false
|
||||
//
|
||||
// # AFTER:
|
||||
// 'dns':
|
||||
// 'edns_client_subnet':
|
||||
// 'enabled': false
|
||||
// 'use_custom': false
|
||||
// 'custom_ip': ""
|
||||
func upgradeSchema16to17(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 16 to 17")
|
||||
diskConf["schema_version"] = 17
|
||||
|
||||
dnsVal, ok := diskConf["dns"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
dns, ok := dnsVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||
}
|
||||
|
||||
const field = "edns_client_subnet"
|
||||
|
||||
dns[field] = map[string]any{
|
||||
"enabled": dns[field] == true,
|
||||
"use_custom": false,
|
||||
"custom_ip": "",
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeSchema17to18 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'statistics':
|
||||
// 'interval': 1
|
||||
//
|
||||
// # AFTER:
|
||||
// 'statistics':
|
||||
// 'interval': 24h
|
||||
func upgradeSchema16to17(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 16 to 17")
|
||||
diskConf["schema_version"] = 17
|
||||
func upgradeSchema17to18(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 17 to 18")
|
||||
diskConf["schema_version"] = 18
|
||||
|
||||
statsVal, ok := diskConf["statistics"]
|
||||
if !ok {
|
||||
|
|
|
@ -579,7 +579,7 @@ func TestUpgradeSchema13to14(t *testing.T) {
|
|||
// The clients field will be added anyway.
|
||||
"clients": yobj{
|
||||
"persistent": yarr{},
|
||||
"runtime_sources": &clientSourcesConf{
|
||||
"runtime_sources": &clientSourcesConfig{
|
||||
WHOIS: true,
|
||||
ARP: true,
|
||||
RDNS: false,
|
||||
|
@ -597,7 +597,7 @@ func TestUpgradeSchema13to14(t *testing.T) {
|
|||
"schema_version": newSchemaVer,
|
||||
"clients": yobj{
|
||||
"persistent": []*clientObject{testClient},
|
||||
"runtime_sources": &clientSourcesConf{
|
||||
"runtime_sources": &clientSourcesConfig{
|
||||
WHOIS: true,
|
||||
ARP: true,
|
||||
RDNS: false,
|
||||
|
@ -618,7 +618,7 @@ func TestUpgradeSchema13to14(t *testing.T) {
|
|||
"schema_version": newSchemaVer,
|
||||
"clients": yobj{
|
||||
"persistent": []*clientObject{testClient},
|
||||
"runtime_sources": &clientSourcesConf{
|
||||
"runtime_sources": &clientSourcesConfig{
|
||||
WHOIS: true,
|
||||
ARP: true,
|
||||
RDNS: true,
|
||||
|
@ -749,6 +749,67 @@ func TestUpgradeSchema15to16(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUpgradeSchema16to17(t *testing.T) {
|
||||
const newSchemaVer = 17
|
||||
|
||||
defaultWantObj := yobj{
|
||||
"dns": map[string]any{
|
||||
"edns_client_subnet": map[string]any{
|
||||
"enabled": false,
|
||||
"use_custom": false,
|
||||
"custom_ip": "",
|
||||
},
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
in yobj
|
||||
want yobj
|
||||
name string
|
||||
}{{
|
||||
in: yobj{
|
||||
"dns": map[string]any{
|
||||
"edns_client_subnet": false,
|
||||
},
|
||||
},
|
||||
want: defaultWantObj,
|
||||
name: "basic",
|
||||
}, {
|
||||
in: yobj{
|
||||
"dns": map[string]any{},
|
||||
},
|
||||
want: defaultWantObj,
|
||||
name: "default_values",
|
||||
}, {
|
||||
in: yobj{
|
||||
"dns": map[string]any{
|
||||
"edns_client_subnet": true,
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"dns": map[string]any{
|
||||
"edns_client_subnet": map[string]any{
|
||||
"enabled": true,
|
||||
"use_custom": false,
|
||||
"custom_ip": "",
|
||||
},
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
name: "is_true",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := upgradeSchema16to17(tc.in)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, tc.in)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpgradeSchema17to18(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ivl any
|
||||
want any
|
||||
|
@ -771,10 +832,10 @@ func TestUpgradeSchema16to17(t *testing.T) {
|
|||
"statistics": yobj{
|
||||
"interval": tc.ivl,
|
||||
},
|
||||
"schema_version": 16,
|
||||
"schema_version": 17,
|
||||
}
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := upgradeSchema16to17(conf)
|
||||
err := upgradeSchema17to18(conf)
|
||||
|
||||
if tc.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
|
@ -785,7 +846,7 @@ func TestUpgradeSchema16to17(t *testing.T) {
|
|||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, conf["schema_version"], 17)
|
||||
require.Equal(t, conf["schema_version"], 18)
|
||||
|
||||
statsVal, ok := conf["statistics"]
|
||||
require.True(t, ok)
|
||||
|
@ -803,13 +864,13 @@ func TestUpgradeSchema16to17(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("no_stats", func(t *testing.T) {
|
||||
err := upgradeSchema16to17(yobj{})
|
||||
err := upgradeSchema17to18(yobj{})
|
||||
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("bad_stats", func(t *testing.T) {
|
||||
err := upgradeSchema16to17(yobj{
|
||||
err := upgradeSchema17to18(yobj{
|
||||
"statistics": 0,
|
||||
})
|
||||
|
||||
|
@ -821,7 +882,7 @@ func TestUpgradeSchema16to17(t *testing.T) {
|
|||
"statistics": yobj{},
|
||||
}
|
||||
|
||||
err := upgradeSchema16to17(conf)
|
||||
err := upgradeSchema17to18(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
statsVal, ok := conf["statistics"]
|
||||
|
|
|
@ -315,7 +315,7 @@ func (u *Updater) clean() {
|
|||
// MaxPackageFileSize is a maximum package file length in bytes. The largest
|
||||
// package whose size is limited by this constant currently has the size of
|
||||
// approximately 9 MiB.
|
||||
const MaxPackageFileSize = 32 * 10 * 1024
|
||||
const MaxPackageFileSize = 32 * 1024 * 1024
|
||||
|
||||
// Download package file and save it to disk
|
||||
func (u *Updater) downloadPackageFile() (err error) {
|
||||
|
|
Loading…
Reference in New Issue