My Router - Part 9
DoT and DoH Services
Adding SSL certificates to AdGuardHome
Since we installed AdGuardHome in Part 2 of this series, and both ACME and DDNS in Part 4 of this series, we can modify the AdguardHome configuration to enable DoH and DoT:
1
2
3
4
5
6
7
FILE=/etc/adguardhome/adguardhome.yaml
sed -i "s|server_name: .*|server_name: dns.${DOMAIN}|g" ${FILE}
sed -i "s|certificate_path: .*|certificate_path: /etc/acme/${DOMAIN}_ecc/fullchain.cer|g" ${FILE}
sed -i "s|private_key_path: .*|private_key_path: /etc/acme/${DOMAIN}_ecc/${DOMAIN}.key|g" ${FILE}
sed -i "s|port_https: .*|port_https: 3001|g" ${FILE}
sed -i '/^tls:/{n;s/.*/ enabled: true/}' ${FILE}
sed -i 's|insecure_enabled:.*|insecure_enabled: true|g' ${FILE}
we need to add the directory to the jail mounts so the AGH can actually read the certificate and key, and change ownership and permissions:
1
2
3
4
chown root:adguardhome /etc/acme/*/*.key
chmod 640 /etc/acme/*/*.key
uci add_list adguardhome.config.jail_mount='/etc/acme/'
uci commit
Finally, we need to restart AdGuardHome so it can listen for DNS requests from DNS-over-TLS (DoT) and DNS-over-HTTPS (DoH).
1
service adguardhome restart
Now AGH is available at https://router.example.com:3001, fully excrypted! Note that https://openwrt.lan:3001 will give errors, but that’s because the name in the SSL certificate doesn’t match the hostname used.
Is it possible to fix this particular issue? Nope, no way to build a SSL certificate through Let’s Encrypt for these domain names….
DNS-over-HTTPS (DoH) Access
AdGuardHome is now “secured” at https://openwrt.lan:3001. However, the SSL certificate cannot match the hostname because the certificate will never be able to include the hostname, so accessing it through that name is impractical for common use.
Since we installed Nginx in Part 4 of this series, we need to add a Nginx configuration section to pass any DNS requests over DoH to AdGuardHome:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uci set nginx.https_dns=server
uci add_list nginx.https_dns.listen='443 ssl'
uci add_list nginx.https_dns.listen='[::]:443 ssl'
uci add_list nginx.https_dns.include='conf.d/error_403.locations'
uci set nginx.https_dns.server_name='dns.'${DOMAIN}
uci set nginx.https_dns.ssl_certificate='/etc/acme/'${DOMAIN}'_ecc/'${DOMAIN}'.cer'
uci set nginx.https_dns.ssl_certificate_key='/etc/acme/'${DOMAIN}'_ecc/'${DOMAIN}'.key'
uci set nginx.https_dns.ssl_session_cache='shared:SSL:32k'
uci set nginx.https_dns.ssl_session_timeout='64m'
uci set nginx.https_dns.access_log='off; # logd openwrt'
uci set nginx.https_dns.location='/ { deny all; } # dns'
uci add_list nginx.https_dns.location='/dns-proxy { proxy_pass https://127.0.0.1:3001; allow all; proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $proxy_protocol_addr; proxy_set_header Host $host; } # dns'
uci commit
service nginx restart
Now your new DNS-over-HTTPS server is available at https://dns.example.com!
Allowing DNS-over-TLS (DoT) from WAN
If access to your DoT server from outside your intranet is desired, then we have to configure firewall to allow port 853 through:
1
2
3
4
5
6
7
8
9
uci -q del firewall.dot
uci set firewall.dot="rule"
uci set firewall.dot.name='Allow DoT from WAN'
uci set firewall.dot.src='wan'
uci set firewall.dot.dest_port='853'
uci add_list firewall.dot.proto='tcp'
uci set firewall.dot.target='ACCEPT'
uci commit
service firewall restart
Blocking DNS-over-TLS from LAN
We honestly don’t want our connected devices to communcate outside our network using DoT.
Unfortunately, we can’t redirect port 853 to the router because all requests would then fail the SSL certificate test. We can’t fix this particular situation, so lets just block DoT (port 853) from LAN using a firewall rule. This will force the client to failback to regular DNS requests, which we can redirect!
1
2
3
4
5
6
7
8
9
uci set firewall.block_dot=rule
uci set firewall.block_dot.name='Block DoT from LAN'
uci set firewall.block_dot.src='lan'
uci set firewall.block_dot.dest='wan'
uci set firewall.block_dot.proto='tcp udp'
uci set firewall.block_dot.dest_port='853'
uci set firewall.block_dot.target='REJECT'
uci commit
service firewall restart
Fixing DNS requests from LAN and WAN
We have a situation now. DNS requests from the WAN should obivously reach the WAN interface. This is expected and good! However, traffic from the LAN might make our data transfer over the WAN interface increase dramatically. I do not want to pay higher internet bills simply because I can’t keep the LAN from communication with services exposed via WAN from using WAN bandwidth…. What can I do, what can I do?
I know! We can rewrite the DNS requests to our services coming from our LAN interfaces! We need to edit /etc/adguardhome/adguardhome.yaml. Scroll down to the line that reads clients and insert this block:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
clients:
runtime_sources:
whois: true
arp: true
rdns: true
dhcp: true
hosts: true
persistent:
- safe_search:
enabled: false
bing: true
duckduckgo: true
ecosia: true
google: true
pixabay: true
yandex: true
youtube: true
blocked_services:
schedule:
time_zone: UTC
ids: []
name: LAN
ids:
- 192.168.20.0/24
- 192.168.8.0/24
tags: []
upstreams:
- '[/pool.ntp.org/]1.1.1.2'
- '[/pool.ntp.org/]1.0.0.2'
- '[/pool.ntp.org/]2606:4700:4700::1112'
- '[/pool.ntp.org/]2606:4700:4700::1002'
- '[/lan/]127.0.0.1:54'
- '[//]127.0.0.1:54'
- tls://security.cloudflare-dns.com
uid: 01a05025-0a8b-73e0-91fa-7d0ee5b11fb2
upstreams_cache_size: 0
upstreams_cache_enabled: false
use_global_settings: true
filtering_enabled: false
parental_enabled: false
safebrowsing_enabled: false
use_global_blocked_services: true
ignore_querylog: false
ignore_statistics: false
- safe_search:
enabled: true
bing: true
duckduckgo: true
ecosia: true
google: true
pixabay: true
yandex: true
youtube: true
blocked_services:
schedule:
time_zone: UTC
ids: []
name: Guests
ids:
- 192.168.3.0/24
tags: []
upstreams:
- tls://1.1.1.3
- tls://1.0.0.3
- tls://2606:4700:4700::1113
- tls://2606:4700:4700::1003
uid: 01a01b8e-b089-779d-84db-d6eca8e77ba1
upstreams_cache_size: 0
upstreams_cache_enabled: false
use_global_settings: false
filtering_enabled: true
parental_enabled: true
safebrowsing_enabled: true
use_global_blocked_services: true
ignore_querylog: false
ignore_statistics: false
AGH Clients: 192.168.20.0/24 and 192.168.8.0/24
What does this do? Well, the first block defines the LAN interface as 192.168.20.0/24 (our LAN interface) and 192.168.8.0/24 (our trusted Wireguard interface). Global settings are used, but DNS servers are copied from global settings.
AGH Clients: 192.168.3.0/23
This IP address range defines our Wifi Guest network. We want this network to use CloudFlare’s Malware and adult content blocking DNS servers.
These client settings do the following:
- Uncheck
Use global settingsfor these clients - Enable
Block domains using filters and hosts filesfor these clients - Enable
Use AdGuard browsing security web servicefor these clients, which checks to see if domain is blocked by the browsing security web service. - Enable
Use AdGuard parental control web servicefor these clients, which checks if domain contains adult materials. - Enable
Use Safe Searchto enforce Safe Search on Google, YouTube, Bing, DuckDuckGo, Ecosia, Yandex, and Pixabay. - Keep
Ignore this client in query logunchecked - Keep
Ignore this client in statisticsunchecked
Our guests don’t like this? Awwww, I don’t care, they can use their mobile data for web browsing. Don’t have that? Too bad…
Custom Filtering Rules
Now that we have our LAN clients clearly defined, we can add some custom filtering rules to aid in solving the problem. Let’s edit /etc/adguardhome/adguardhome.yaml again:
1
2
user_rules:
- '||*.example.com^$client=LAN,dnsrewrite=192.168.20.1'
This forces LAN DNS requests to our external domain name to have the LAN IP address of our router. So executing nslookup meh.example.com on our router would return 192.168.20.1, but a DNS request from outside our network would return the proper WAN IP address that our router uses.
The filtering rule must ALWAYS have ONLY subdomains specified (aka *.example.com), NEVER the top-level domain (aka example.com). Doing otherwise will keep server connections, for example WireGuard and HTTPS, from working properly, especially if you have the Private DNS setting on your phone/tablet set!
Summary
We’ve set up DNS-over-TLS (DoT) and DNS-over-HTTPS (DoH), as well as shared both with the Internet. We’ve also restricted Guest clients to “safer” DNS service, while keeping the regular LAN-side DNS service normal. What else can we do?
