Deploy DNS-over-HTTPs server

Protect you on public places.

DNS-over-HTTPs is one of the "securing" your connection, especially on public place, you'll need this. By default, DNS communicate via UDP protocol in port 53, with this DNS-over-HTTPs, when we need name/address resolution, we create request to DNS server over HTTPs, which is more secure.

On this article, we will using Docker to deploy DNS-over-HTTPs server, with image from satishweb/doh-server. But we need setup our own http listener, use nginx for easy setup.

Install NGINX

sudo apt install nginx

Install certbot:

sudo apt install certbot python3-certbot-nginx

Generate new SSL for domain:

sudo certbot --nginx -d doh.yourdomain.com

Deploy image from Docker Images

docker run \
    -itd --restart=always \
    --name doh-server \
    -p 127.0.0.1:9990:9990\
    -e UPSTREAM_DNS_SERVER="udp:1.1.1.1:53" \
    -e DOH_HTTP_PREFIX="/dns" \
    -e DOH_SERVER_LISTEN=":9990" \
    -e DOH_SERVER_TIMEOUT="10" \
    -e DOH_SERVER_TRIES="3" \
    -e DOH_SERVER_VERBOSE="false" satishweb/doh-server

Take a note, UPSTREAM_DNS_SERVER is using Cloudflare Public DNS, you can change this to Google Public, AdGuard, etc.

Modify nginx configuration

This is my configuration; change yourdomain.com to your own domain.

server {
        root /var/www/dns;
        index index.html;
        server_name doh.yourdomain.com;

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/doh.yourdomain.com/fullchain.pem; 
        ssl_certificate_key /etc/letsencrypt/live/doh.yourdomain.com/privkey.pem; 
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        resolver 1.1.1.1 valid=300s;
        resolver_timeout 5s;

        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header Strict-Transport-Security "max-age=63072000";

        location /dns {
                proxy_pass http://localhost:9990/dns;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
        }
}

Adjust with your current nginx configuration. For DoH client itself, you can use directly on the browser (Chrome, Firefox, Edge has this feature; Settings>Security>Secure DNS), or you can use cloudflared to apply system-wide.

Reference: