详解 SNI、DoH 与本地 Nginx 反向代理实践
本文将详细介绍 SNI(Server Name Indication)、DoH(DNS over HTTPS)相关原理,并通过一个实用的 Nginx 本地反代配置实例,结合自制的 SNI 封锁检测脚本,帮助你理解在严苛网络环境下如何提升访问 DNS 及 Web 资源的可达性和隐私性。
一、SNI(Server Name Indication)是什么?
SNI 是 TLS/SSL 握手时用于指明目标主机名的扩展。客户端在建立 HTTPS 连接时,会在握手的 ClientHello 阶段明文发送欲访问的域名。这样,服务器可以基于域名选择对应的证书,支持一个 IP 托管多个站点。
SNI 特点与风险:
- SNI 明文传输,易被中间人(如审查防火墙)检测和拦截。
- 某些网络环境会针对 SNI 字段中的“敏感域名”进行封锁(即“SNI 封锁”),导致即使你有正确 IP,也无法访问目标站点。
二、DoH(DNS over HTTPS)简介
DoH 是一种通过 HTTPS 协议进行 DNS 查询的方式,目的是防止传统明文 DNS 查询被劫持、污染或监控。
DoH 优势:
- 查询过程加密,难以被中间人监听和篡改。
- 可防止 DNS 污染、劫持,提升隐私性。
- 可绕过部分基于 DNS 的封锁手段。
典型 DoH 服务商:
三、Nginx 本地反向代理 DoH 实践
有时直连 DoH 服务(如 cloudflare-dns.com)会遇到 SNI 封锁,或希望统一流量出口、加速 DoH 访问,可以利用 Nginx 本地反代:
1. 反代配置解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| map $host $doh_upstream { cloudflare-dns.com 104.16.248.249; }
server { listen 443 ssl; server_name cloudflare-dns.com;
ssl_certificate certs/cloudflare-dns.com.pem; ssl_certificate_key certs/cloudflare-dns.com-key.pem;
location / { proxy_pass https://$doh_upstream; proxy_set_header Host cloudflare-dns.com; } }
|
四、SNI 封锁检测脚本详解
结合以上配置,我们可以用下述脚本检测某域名是否遭遇 SNI 封锁,以及本地 DNS 污染等多种网络问题:
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
| #!/bin/bash
DOMAIN=$1 PROXY="192.168.1.2:7890" echo "DOMAIN: $DOMAIN" echo "=== 1. 本地 dig 查询 IP(可能被污染) ===" LOCAL_IP=$(dig +short $DOMAIN | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1) echo "dig IP: $LOCAL_IP" echo
echo "=== 2. Cloudflare DoH 查询 IP(防污染) ===" DOH_IP=$(curl -s "https://cloudflare-dns.com/dns-query?name=$DOMAIN&type=A" \ -H 'accept: application/dns-json' -x $PROXY | grep -oP '"data":"\K[\d.]+' | head -1) echo "DoH IP: $DOH_IP" echo
echo "=== 3. Ping 检测 dig IP 是否可达 ===" if [ -n "$LOCAL_IP" ]; then if ping -c 4 "$LOCAL_IP" > /dev/null 2>&1; then echo "Ping $LOCAL_IP 成功,可达。" else echo "Ping $LOCAL_IP 失败,不可达。" fi else echo "本地 dig 未查到 IP。" fi echo
echo "=== 4. Ping 检测 DoH IP 是否可达 ===" if [ -n "$DOH_IP" ]; then if ping -c 4 "$DOH_IP" > /dev/null 2>&1; then echo "Ping $DOH_IP 成功,可达。" else echo "Ping $DOH_IP 失败,不可达。" fi else echo "DoH 查询未查到 IP。" fi echo
echo "=== 5. 通过域名不使用代理进行 curl 测试 ===" curl -I --connect-timeout 8 "https://${DOMAIN}" echo
echo "=== 6. 用 dig IP 直连 curl(带 Host) ===" if [ -n "$LOCAL_IP" ]; then curl -k "https://${LOCAL_IP}/" -H "Host: $DOMAIN" -I --connect-timeout 8 else echo "DoH 查询无 IP,跳过。" fi echo
echo "=== 7. 用 DoH IP 直连 curl(带 Host) ===" if [ -n "$DOH_IP" ]; then curl -k "https://${DOH_IP}/" -H "Host: $DOMAIN" -I --connect-timeout 8 else echo "DoH 查询无 IP,跳过。" fi echo
echo "=== 8. 通过代理直连域名(模拟国外环境)===" curl "https://${DOMAIN}" -x $PROXY -I --connect-timeout 8 echo
echo "=== 流程结束 ==="
|
五、总结与实践建议
- 利用 Nginx 本地反代 可规避 SNI 封锁,让内网设备稳定访问 DoH 服务。
- 结合 SNI 检测脚本,可快速定位访问失败的症结,是 DNS 污染、SNI 封锁还是 IP 被墙。
- 安全建议:
- 本地部署 Nginx 时注意证书安全,避免泄露私钥。
- 可适当定制反代规则,支持多家 DoH 服务切换。
- 灵活运用:
- 企业或家庭网络可统一出口 DNS,提升隐私与安全性。
- 科学上网场景可配合代理使用,进一步绕开封锁。
参考链接:
欢迎根据你的实际需求调整配置,提升网络可用性与安全性!