在阿里云上用 Nginx 开启 DoT (DNS Over TLS )服务加密 DNS 流量

DNS 的安全性至关重要,第一个层次需要防范的就是运营商的劫持。因为最近使用 Ubuntu 桌面替代了 Win 7 。所以,折腾一下,把 DNS 流量加密一下。

Ubuntu 上可以安装一个叫做 stubby 的 DoT 客户端,apt install stubby 后, 修改 /etc/stubby/stubby.yml 设置好 DoT 服务器的地址,就可以工作。

但是问题是,国内的网址都会解析成国外的 IP,严重影响速度。 所以,决定在国内的阿里云上搭建一个DoT 的 DNS 转发器。教程很多,就是用 Nginx 的 stream 来实现,在云服务器上把侦听到的 DoT 端口(853) 的 DNS 流量转发到服务器本机的解析器上。我没有关闭 systemd-resolved,所以转发的地址是 127.0.0.53:53 。修改 /etc/nginx/nginx.conf ,添加如下内容后,重启 Nginx,并确保防火墙的853端口已经开启。这里省略了一个步骤就是 X.mydomain.com 的证书要另外申请好。

stream {
     # DoT server for decryption
   server {
        listen 853 ssl;
        ssl_certificate /etc/letsencrypt/live/X/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/X/privkey.pem;
	proxy_pass 127.0.0.53:53;
	proxy_connect_timeout   1s;
	preread_timeout         2s;
   }
        ssl_session_timeout             1d;
        ssl_session_tickets             off;
        ssl_protocols                   TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers       on;
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;

        ssl_session_cache               shared:DoT:10m;

        log_format dot '$remote_addr\t-\t-\t[$time_local]\t$ssl_protocol\t'
            '$ssl_session_reused\t$ssl_cipher\t$ssl_server_name\t$status\t'
            '$bytes_sent\t$bytes_received';

        access_log /var/log/nginx/X.log dot;
}

在家里的 Ubuntu 桌面上,配置 stubby.yml 在 round_robin_upstreams: 1 行后面添加类似如下的两行后重启 stubby:

 - address_data: 1.2.3.4
    tls_auth_name: "X.mydomain.com"

在云端服务器上看 Nginx 日志,我们可以看到如下的信息:
117.143.xx.xx – – [24/Feb/2021:00:14:33 +0800] TLSv1.3 . TLS_AES_256_GCM_SHA384 X.mydomain.com 200 186 260

就表示客户端的 DNS 请求已经转发到服务器了。