xnix:nginx_doh_proxy
使用 Nginx 代理 DoH
本文简述用 Nginx 代理 DoH (DNS Over HTTPS)的实现方式.
先说说碰到的坑.
- 根据 RFC, DoH 应该是承载在 HTTP2 上, 而 nginx 的 proxy_pass 是不支持 h2 的, 需要用 gRPC 模块 grpc_pass 来代理转发. 部分支持 http1 的可以继续使用 proxy_pass.
- grpc_pass 不支持指定远端 URI, 如果两端 URI 不一致, 要用 rewrite.
- 用 upstream 时, grpc_pass / proxy_pass 的 Host 头发送有问题, 需要指定. 而不用 upstream 则没问题
- nginx 不能直接记录 request body, 所以解包 DoH 的查询域名, 要靠其他方法. 这个会在Nginx + njs 记录 DoH 的查询域名介绍.
nginx.conf 配置
配置 upstream, 用于 keepalive.
http {
# ... 省略设置
upstream doh-google {
zone doh-google 64k;
server 8.8.8.8:443;
server 8.8.4.4:443;
# keepalive 的数量不需要多, 建议为 CPU 数*2
keepalive 16;
}
upstream doh-cloudflare {
zone doh-cloudflare 64k;
server 1.1.1.1:443;
server 1.1.1.1:443;
keepalive 16;
}
server {
# ... 省略设置
grpc_socket_keepalive on;
# 与 grpcs ssl 的协议, 如果远端不支持, 注释该行
grpc_ssl_protocols TLSv1.3;
location /dns-query {
# grpcs 代表远端是 ssl 连接, 如果不是, 则使用 grpc
grpc_pass grpcs://doh-cloudflare;
# 用 upstream 时, http 头中的 Host 会有问题, 一些服务商例如 cloudflare 需要依赖 Host, 所以要强制指定.
# 同样, 有些服务器商需要指定 SNI, 则需要设置 grpc_ssl_name 和 grpc_ssl_server_name. 详情参看 nginx 文档.
grpc_set_header Host cloudflare-dns.com;
}
location /dns-query2 {
# 两端 URI 不一致, 需要 rewrite
rewrite / /dns-query break;
grpc_pass grpcs://doh-google;
}
# 该范例转发至不加密的 h2 DoH
location /dns-query3 {
rewrite / /dns-query break;
grpc_pass grpc://127.0.0.1:8053;
}
}
}
xnix/nginx_doh_proxy.txt · 最后更改: 2024/08/15 16:59 由 Hshh