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