Nginx作为DNS over TLS反向代理,如何向Pi-hole转发客户端真实IP?
问题描述
在Ubuntu 20.04 VPS中部署了Pi-hole(v5.12.2),并使用Nginx作为DNS over TLS(DoT)反向代理,功能运行正常,但Pi-hole日志中所有请求均显示为127.0.0.1,原因是Nginx未转发客户端真实IP。
当前Nginx配置如下:
upstream dns-servers { server 127.0.0.1:53; } server { listen 853 ssl; ssl_certificate /etc/letsencrypt/live/domainname.here/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/domainname.here/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_handshake_timeout 10s; ssl_session_cache shared:SSL:20m; ssl_session_timeout 4h; proxy_pass dns-servers; proxy_responses 1; proxy_timeout 1s; }
尝试添加proxy_set_header或real_ip_header指令时,提示directive is not allowed here;使用proxy_bind $remote_addr transparent;指令虽能通过配置,但所有请求均超时。需找到正确配置以向Pi-hole转发客户端真实IP。
解决方案
DNS基于UDP/TCP协议,并非HTTP,因此proxy_set_header这类HTTP头指令完全不适用,必须通过透明代理让Nginx以客户端IP身份转发请求,具体操作如下:
1. 配置内核参数支持透明代理
编辑/etc/sysctl.conf文件,添加或修改以下参数:
net.ipv4.ip_forward = 1 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.conf.lo.send_redirects = 0 net.ipv4.conf.eth0.send_redirects = 0 # 替换为你的公网网卡名称,可通过`ip addr`查看
执行命令使参数生效:
sysctl -p
2. 给Nginx添加网络管理权限
透明代理需要Nginx具备修改网络配置的权限,执行:
setcap cap_net_admin+ep /usr/sbin/nginx
重启Nginx应用权限:
systemctl restart nginx
3. 修改Nginx配置
调整server块,补充UDP监听并启用透明代理:
upstream dns-servers { server 127.0.0.1:53; } server { listen 853 ssl tcp; # 明确TCP监听 listen 853 ssl udp; # 添加UDP监听,DoT支持UDP协议 ssl_certificate /etc/letsencrypt/live/domainname.here/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/domainname.here/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_handshake_timeout 10s; ssl_session_cache shared:SSL:20m; ssl_session_timeout 4h; proxy_pass dns-servers; proxy_responses 1; proxy_timeout 1s; proxy_bind $remote_addr transparent; # 绑定客户端真实IP做透明转发 }
4. 验证配置
重启Nginx和Pi-hole服务:
systemctl restart nginx pihole-FTL
发起DNS请求后,查看Pi-hole日志即可看到客户端真实IP。
内容的提问来源于stack exchange,提问作者kampias
相关产品推荐
相关产品推荐

