Nginx 1.9.13+ 原生支持 UDP 反向代理(stream 模块),仅四层转发、不解析应用层协议;需确认编译含 --with-stream,配置 listen xxx udp、proxy_pass 等指令,并注意无会话保持、无重写、EDNS 透传等限制。

Nginx 从 1.9.13 版本起原生支持 UDP 反向代理(基于 stream 模块),但需注意:它不解析 UDP 应用层协议(如 DNS、Syslog、RTP),仅做四层转发,不支持像 HTTP 那样的重写、鉴权或日志分析。配置关键在于启用 stream 上下文、正确设置监听与上游,并关闭无关模块干扰。
确认 Nginx 编译包含 stream 模块
UDP 转发依赖 ngx_stream_core_module,该模块默认不随 HTTP 模块一同编译。运行以下命令验证:
nginx -V 2>&1 | grep -o with-stream
若无输出,需重新编译 Nginx 并添加 --with-stream 参数;已安装的二进制包(如 Ubuntu 官方源)通常需安装 nginx-full 或 nginx-extras 包。
基础 UDP 反向代理配置示例
在主配置文件(如 /etc/nginx/nginx.conf)末尾或独立 stream.conf 中添加:
stream {
upstream udp_backend {
server 192.168.1.100:53;
# 可配多个 server,支持 weight、backup 等参数
}
server {
listen 53 udp;
proxy_pass udp_backend;
proxy_timeout 1s;
proxy_responses 1;
}
}
-
listen 53 udp:明确指定 UDP 协议,不可省略
udp标识 - proxy_responses 1:限制每请求最多接收 1 个响应包(适用于 DNS 查询等典型场景)
- proxy_timeout 1s:设置等待后端响应的超时,避免长时间挂起
- 不支持
location、rewrite、access_log(stream 层无 request body 和 header 概念)
常见问题与注意事项
- DNS 转发需保持 EDNS 兼容:Nginx stream 不修改 UDP 包内容,原始 DNS 查询中的 EDNS 选项会透传,但若后端不支持,可能返回截断响应(TC=1),客户端将降级为 TCP —— 这属于协议行为,非 Nginx 问题
-
无法做连接跟踪或会话保持:UDP 无连接状态,
ip_hash在 stream upstream 中无效;如需固定后端,只能用hash $remote_addr consistent;做客户端 IP 一致性哈希 -
防火墙与 SELinux 干扰:确保系统防火墙(如 ufw/iptables/firewalld)放行目标 UDP 端口;SELinux 若启用,可能需执行
setsebool -P nginx_can_network_connect 1 -
健康检查有限:stream 模块仅支持
health_check(基于定期发送空 UDP 包并等待响应),不支持自定义探测报文;对 DNS 服务,可配合health_check interval=5 passes=2 fails=3
调试与验证方法
启用 stream 日志辅助排查:
stream {
log_format basic '$remote_addr:$remote_port - $status $bytes_sent $bytes_received';
access_log /var/log/nginx/stream-access.log basic;
error_log /var/log/nginx/stream-error.log warn;
# …… server 块
}
- 用
tcpdump -i any port 53 and udp抓包,确认 Nginx 是否收包、是否发包至上游 - 用
ss -ulpn | grep :53检查 Nginx 是否成功绑定 UDP 端口 - 临时用
nc -u 127.0.0.1 53发送简单 DNS 查询(需构造 DNS 查询包,推荐用dig @127.0.0.1 example.com)










