1273 字
6 分钟
使用DOH和ECH防止DNS污染和劫持
2025-03-14

前言#

DoH(DNS over HTTPS)是一种安全协议,它通过 HTTPS(TLS 加密)传输 DNS 解析请求,防止 DNS 查询被窃听、篡改或屏蔽。

正常情况下,当你访问一个 HTTPS 网站时,需要先向 DNS 发送查询该域名 IP 地址的请求。由于传统 DNS 查询是明文传输的,ISP 或其他网络中间人可以看到你查询了哪个域名。虽然 HTTPS 内容是加密的,无法看到具体内容,但可以得知你在访问什么网站。

另外,访问 HTTPS 网站需要进行 TLS 握手,握手时会携带域名信息,也就是 SNI(Server Name Indication)。ISP 同样能看到这个信息。

此时,中间人可以劫持并篡改 DNS 查询返回的 IP 地址。

当我们使用加密 DNS 后,可以隐藏 DNS 查询的域名信息,但由于 TLS 握手仍会携带 SNI 信息,中间人依然能够监控。为了进一步保护隐私,网站可以配置 ECH(Encrypted Client Hello)来加密 SNI 信息。

目前 Cloudflare 已支持 ECH,使用其 CDN 服务的网站会默认开启此功能。ECH 会加密真实的 SNI 信息,只有支持 ECH 的服务器才能解密,从而实现对真实访问目标的隐藏。

ECH 配合 DoH 加密 DNS 可以提供更完整的隐私保护。

享受ECH加密的一些注意事项#

  • 服务端域名开启了ECH
  • 服务端域名支持TLS 1.3
  • 域名托管商支持HTTPS解析
  • 客户端使用国际主流浏览器
  • 客户端不要用代理
  • 客户端使用加密DNS

Windows 11 配置加密 DNS#

由于网络环境限制,国外的加密 DNS 服务可能无法直接访问。本文教大家配置阿里云的加密 DNS 服务。

系统设置方法:

  1. 打开 设置 > 网络和 Internet
  2. 找到当前网络连接的 属性
  3. DNS 服务器分配 中选择 手动
  4. 首选 DNS 填入 223.5.5.5
  5. DNS over HTTPS 选择 手动模板
  6. 模板地址填入 https://dns.alidns.com/dns-query

控制面板配置方法:

  1. 打开控制面板,选择 查看网络状态和任务
  2. 点击你的网卡连接
  3. 选择 属性
  4. 双击 Internet 协议版本 4 (TCP/IPv4)
  5. 点击 属性
  6. 首选 DNS 填入 223.5.5.5,备选 DNS 填入 8.8.8.8
  7. 点击 确定 保存设置

配置完成后,你的 DNS 查询将通过加密通道进行,提升上网安全性和隐私保护。

验证是否开启#

访问域名 https://cdnjs.com/cdn-cgi/trace 查看sni参数,如果是图中这样,则代表开启成功。

图片

或者也可以访问https://tls-ech.dev 如果如图所示则代表开启成功。

图片

服务端域名配置ECH教程#

由于Cloudflare CDN国内访问速度慢,所以我介绍一下不使用CDN的教程

我使用caddy较多,所以用caddy做演示,其他同理

caddy2.10.0正式版本 已经加入了ECH的支持,需要使用2.10.0以上的版本。

要使用caddy自动配置ech则需要编译cloudflare dns插件,官方编译的包默认不带此插件。

编译caddy并加入cloudflare DNS插件的支持#

1:安装go环境

2:下载xcaddy

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

3:编译带cloudflare dns插件的caddy

xcaddy build --with github.com/caddy-dns/cloudflare

此时你的当前目录会生成一个已经包含了cloudflare dns插件的caddy二进制文件

debug模式测试运行#

创建/etc/caddy/Caddyfile文件,并写入以下文件

{
    debug
    dns cloudflare xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ech ech.example.com

    log {
        output stdout
        format console
        level DEBUG
    }
}

test.example.com {
    root * /tmp
    file_server browse
    encode zstd gzip
}

配置说明#

dns cloudflare这个配置填CF的区域 DNS API 令牌

ech ech.example.com这里的域名应该使用公共域名,要跟你域名无关的,所以可以无需修改

test.example.com替换你的域名,并且解析到你的IP,不用开小黄云

root * /tmp这个配置代表以网页浏览文件的形式,浏览你服务器的/tmp目录

启动caddy#

sudo ./caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

不出意外的话就启动成功了,然后可以访问你的域名看下是否能成功访问

并且/root/.local/share/caddy目录会生成一个锁文件,如果需要重新部署则需要删除这个目录

CF里也会自动添加一个类型为HTTPS的解析记录

检查ech是否配置成功#

dig test.example.com TYPE65

执行这个命令后,在输出的信息里可以看到有如下类似的信息就代表启用成功

ech=AEr+DEBUGAgACBDEMOnixVAfd/ASODJKADKSODAPSkZIwAMADQABAAIASDASDADHw9lY2guZXhhbXBsZS5jb20AAA==

生产环境#

移动二进制文件

mv ~/caddy /usr/bin/caddy

创建系统服务配置

touch /etc/systemd/system/caddy.service

写入配置

[Unit]
Description=Caddy Web Server
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Wants=network-online.target

[Service]
User=root
Group=root
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

管理命令

# 重新加载 systemd 配置
sudo systemctl daemon-reexec
sudo systemctl daemon-reload

# 启动 Caddy
sudo systemctl start caddy

# 设置开机启动
sudo systemctl enable caddy

# 查看运行状态
sudo systemctl status caddy

生产环境反代配置示例#

{
	dns cloudflare xxxxxxxxxxxxxxxxxxxxx
	ech ech.example.com
}

test.example.com {
	reverse_proxy localhost:8080
}

重新部署记得删除:/root/.local/share/caddy锁文件,和CF里的HTTPS解析记录

使用DOH和ECH防止DNS污染和劫持
https://emohe.cn/posts/25/
作者
阿涛の小破站
发布于
2025-03-14
许可协议
CC BY-NC-SA 4.0