186 lines
7.4 KiB
Markdown
186 lines
7.4 KiB
Markdown
+++
|
|
title = "Setup dns with adblock and dot/doh with pi-hole and unbound"
|
|
date = 2023-09-27
|
|
tags = ['self-host', 'dns', 'pi-hole', 'unbound']
|
|
+++
|
|
|
|
Just another day I seted up my own private dns server that has adblocking ( and other stuff ) using pihole and uses unbound as a resolver. To safelly connect to the dns server I'm using DNS over HTTPS for my browser's and HTTPS over TLS for stuffy for my whole desktop and private dns in android ( Android has DoH support but only for google and cloudflare right now). Let's get on to setting everything up
|
|
|
|
<!-- more -->
|
|
|
|
## 1. Pihole
|
|
|
|
Let's start with setting up pihole. I will be installing it with their script on a debian system for easier unbound integration ( unbound doesn't have an official docker container ).
|
|
|
|
|
|
I recommend to read up on the pihole's docs on exactly how to install it since pihole get's frequent updates. [DOCS](https://docs.pi-hole.net/main/basic-install/)
|
|
|
|
I recommend you to install the admin page for easier managmenet and ability to change the upstream dns server ( needed for changing it to unbound later on ). To be able to access the admin page I use an nginx configuration like this one.
|
|
|
|
```nginx
|
|
server {
|
|
server_name example.com ;
|
|
|
|
location / {
|
|
return 403;
|
|
}
|
|
|
|
location /admin {
|
|
proxy_pass http://127.0.0.1:8185/admin;
|
|
proxy_set_header Host $host;
|
|
}
|
|
|
|
# If you want to log user activity, comment these
|
|
access_log /dev/null;
|
|
error_log /dev/null;
|
|
|
|
listen [::]:443 ssl; # managed by Certbot
|
|
listen 443 ssl; # managed by Certbot
|
|
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
|
|
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
|
|
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
|
}
|
|
server {
|
|
if ($host = example.com) {
|
|
return 301 https://$host$request_uri;
|
|
} # managed by Certbot
|
|
|
|
|
|
server_name example.com ;
|
|
listen 80;
|
|
listen [::]:80;
|
|
return 404; # managed by Certbot
|
|
}
|
|
```
|
|
|
|
The main point of this config is the `/admin` location that you need to pass the lighttpd port to acces the website, you can just do it on your main website also.
|
|
Also to make lighttpd work with nginx listening on port 80 you need to edit the `server.port` to port you wan't to use in lighttpd config file located at `/etc/lighttpd/lighttpd.conf` and then just restart lighttpd
|
|
|
|
## 2. Unbound
|
|
|
|
For this part I will just link the pi-hole's unbound documentation because it is the most correct one and updated as things change regulary.
|
|
[Pi-hole unbound docs](https://docs.pi-hole.net/guides/dns/unbound/)
|
|
|
|
## 3. DNS over TLS
|
|
|
|
For dns over tls you need to first have a ssl certificate. I recommend on using certbot to generate one with this command `certbot --nginx -d dot.example.com`.
|
|
|
|
Next you will need a reverse proxy, in my case I use nginx. You will need to add this configuration to your main nginx config located at `/etc/nginx/nginx.conf`. **Make sure to add this outside of the http block and change example.com to your domain**
|
|
|
|
```nginx
|
|
stream {
|
|
log_format basic '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time $upstream_addr';
|
|
|
|
upstream dns
|
|
{
|
|
zone dns 64k;
|
|
server 127.0.0.1:53;
|
|
}
|
|
|
|
server {
|
|
listen 853 ssl;
|
|
|
|
access_log /var/log/nginx/dot-access.log basic;
|
|
error_log /var/log/nginx/dot-error.log;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/dot.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/dot.example.com/privkey.pem;
|
|
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
|
|
ssl_handshake_timeout 10s;
|
|
ssl_session_cache shared:SSL:20m;
|
|
ssl_session_timeout 4h;
|
|
proxy_pass dns;
|
|
proxy_responses 1;
|
|
proxy_timeout 1s;
|
|
}
|
|
}
|
|
```
|
|
|
|
|
|
Also make sure to enable port 853, example ufw command is `ufw allow 853/tcp`. Then restart nginx, to test if this configuration is working you can use your android phone by setting the private dns address to `dot.example.com` and then visit the website[dnsleaktest](https://dnsleaktest.com)
|
|
|
|
## 4. DNS over HTTPS
|
|
|
|
For using dns over https we will be installing additional package called dnsdinst. On debian systems just run `apt install dnsdinst`. Next you will need to setup dnsdinst config and restart it. Make sure to change example.com.
|
|
|
|
```conf
|
|
-- dnsdist configuration file, an example can be found in /usr/share/doc/dnsdist/examples/
|
|
|
|
-- disable security status polling via DNS
|
|
setSecurityPollSuffix("")
|
|
|
|
-- fix up possibly badly truncated answers from pdns 2.9.22
|
|
-- truncateTC(true)
|
|
|
|
-- Answer to only clients from this subnet
|
|
setACL("127.0.0.1/8")
|
|
|
|
-- Define upstream DNS server (Pi-hole)
|
|
newServer({address="127.0.0.1", name="Pi-hole", checkName="example.com", checkInterval=60, mustResolve=true})
|
|
|
|
-- Create local DOH server listener in DNS over HTTP mode, otherwise the information coming from nginx won't be processed well
|
|
addDOHLocal("127.0.0.1:5300", nil, nil, "/dns-query", { reusePort=true })
|
|
```
|
|
|
|
Next we will need another ssl certificate for the doh domain, for that we will once again using certbot with this command `certbot --nginx -d doh.example.com`after that add this configuratin to nginx either in sites-available and linking it to sites enabled or in http block in main nginx configuration.
|
|
|
|
```nginx
|
|
# Proxy Cache storage - so we can cache the DoH response from the upstream
|
|
proxy_cache_path /var/run/doh_cache levels=1:2 keys_zone=doh_cache:10m;
|
|
|
|
server {
|
|
listen 80;
|
|
server_name doh.example.com;
|
|
return 301 https://doh.example.com/$request_uri;
|
|
}
|
|
|
|
# This virtual server accepts HTTP/2 over HTTPS
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name doh.example.com;
|
|
|
|
access_log /var/log/nginx/doh.access;
|
|
error_log /var/log/nginx/doh.error error;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/doh.example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/doh.example.com/privkey.pem;
|
|
|
|
|
|
# DoH may use GET or POST requests, Cache both
|
|
proxy_cache_methods GET POST;
|
|
|
|
# Return 404 to all responses, except for those using our published DoH URI
|
|
location / {
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
|
|
|
|
# This is our published DoH URI
|
|
location /dns-query {
|
|
# Proxy HTTP/1.1, clear the connection header to enable Keep-Alive
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Connection "";
|
|
|
|
# Enable Cache, and set the cache_key to include the request_body
|
|
proxy_cache doh_cache;
|
|
proxy_cache_key $scheme$proxy_host$uri$is_args$args$request_body;
|
|
|
|
# proxy pass to dnsdist
|
|
proxy_pass http://127.0.0.1:5300;
|
|
|
|
# proxy pass address
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
}
|
|
}
|
|
```
|
|
|
|
After restarting nginx with this configuration you can it to your web browser as a DNS over HTTPS resolver and once again checkout [dnsleaktest](https://dnsleaktest.com) website and check if it is all working.
|
|
|
|
Hope this has been helpfull and if anybody has any way on how to make this guied better you can open a pull request or make an issue on the website's [repo](https://code.cronyakatsuki.xyz/crony/website).
|