Nginx如何配置TCP/UDP流代理实现四层转发?

来源:SEO作者:叶知晏头衔:草根站长
导读:本期聚焦于叶知晏创作的《Nginx如何配置TCP/UDP流代理实现四层转发?》,敬请观看详情。Nginx除了大家熟悉的HTTP七层反向代理能力之外,其stream模块还提供了强大的四层代理功能,可以直接转发TCP和UDP流量。本文将深入讲解stream模块的工作原理,包括 ngx_http_stream_module 的编译安装方式、stream块与server块的核心配置语法、proxy_pass 指令在四层场景下的用法,以及UDP转发、负载均衡、连接超时等常见参数的设置技巧。同时结合MySQL数据库端口转发、DNS服务代理、长连接保持等实际案例,给出完整的可运行配置示例,并分析转发过程中的会话保持、真实来源IP传递以及常见故障排查思路,帮助你快速在生产环境中落地稳定的四层流量代理方案。

Nginx最初以HTTP反向代理和Web服务器闻名,但自从1.9.0版本引入stream模块之后,它已经具备了完整的四层(传输层)代理能力。所谓四层代理,就是Nginx不解析应用层协议的内容,只根据IP地址和端口号对TCP或UDP流量进行转发。这种方式开销更低、通用性更强,无论是MySQL、Redis、Postfix,还是DNS、MQTT,只要基于TCP或UDP的协议都可以代理。本文将从模块原理、核心配置语法到实战案例,完整讲解Nginx流代理的配置方法。

Nginx如何配置TCP/UDP流代理实现四层转发?

一、stream模块的原理与启用方式

stream模块与http模块是并列关系,两者都直接位于main配置块之下。这一点非常重要:stream块不能写在http块内部,否则Nginx启动时会直接报错。stream模块工作在传输层,收到客户端连接后,它与后端服务器建立一条新的TCP连接,然后把两条连接之间的数据原样搬运,全程不去解析HTTP头或者任何应用层内容。

默认情况下,官方发布的Nginx并没有编译stream模块,需要手动启用。可以先通过nginx -V命令查看编译参数,确认是否包含--with-stream。如果没有,就需要重新编译:

# 查看当前编译参数
nginx -V 2>&1 | tr ' ' '\n' | grep stream

# 编译时启用stream模块,同时启用UDP负载均衡支持
./configure --with-stream --with-stream_realip_module
make && make install

如果使用的是包管理器安装,例如Ubuntu下的nginx-full或者CentOS下的EPEL源Nginx,stream模块通常以动态包形式提供,执行apt install libnginx-mod-streamyum install nginx-mod-stream即可。动态模块方式下,还需要在nginx.conf顶部加上load_module modules/ngx_stream_module.so;来手动加载。

二、TCP代理的核心配置语法

stream配置的基本结构是一个stream块包含多个server块,每个server块定义监听端口和转发目标。与HTTP代理不同,四层代理使用的是proxy_pass指令(属于stream模块自己的同名指令),后面直接跟后端的IP和端口,不支持URI路径。下面是一个最简单的TCP转发配置:

# nginx.conf 主配置文件
stream {
    upstream mysql_backend {
        server 192.168.1.10:3306 weight=1 max_fails=3 fail_timeout=30s;
        server 192.168.1.11:3306 weight=1 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 3306;              # 对外监听的端口
        proxy_pass mysql_backend; # 转发到后端MySQL集群
        proxy_connect_timeout 5s; # 与后端建立连接的超时时间
        proxy_timeout 600s;       # 两条连接之间无数据的空闲超时
    }
}

这个配置把本机3306端口的流量转发到内网两台MySQL服务器,同时实现了负载均衡。upstream中的weight控制权重,max_fails配合fail_timeout实现后端健康剔除:如果某台后端在30秒内失败3次,就会被暂时摘除。对于MySQL这类长连接服务,proxy_timeout一定要设置得足够大,默认值是10分钟,空闲连接超过这个时间会被Nginx主动断开,应用层经常表现为莫名其妙的连接重置。

另一个常用指令是proxy_next_upstream。当与某台后端建立连接失败时,Nginx可以自动尝试下一台,配置为proxy_next_upstream on;即可。要注意的是,这个机制只在连接阶段生效,一旦连接建立并开始传输数据,中途断开是不会重试的,所以它适合TCP握手失败的场景,不能当作业务层的重试机制使用。

三、UDP转发与会话保持

UDP代理只需在listen指令后加上udp参数。UDP是无连接协议,Nginx通过客户端的源地址和端口来识别一个会话,维护一张会话表。最常见的场景是代理DNS服务:

stream {
    resolver 114.114.114.114 valid=300s;

    upstream dns_servers {
        server 8.8.8.8:53;
        server 1.1.1.1:53;
    }

    server {
        listen 53 udp reuseport;  # udp表示监听UDP协议
        proxy_pass dns_servers;
        proxy_responses 1;        # 每个请求期望1个响应,收到即结束会话
        proxy_timeout 10s;        # UDP会话的空闲超时
    }
}

proxy_responses是UDP代理的关键参数,表示客户端一个请求对应后端几个响应包。对于普通DNS查询是1,如果转发的是syslog这类单向上报,设置为0表示不等待响应。如果不合理设置这个值,会话表可能膨胀,占用大量内存。reuseport参数让多个worker进程各自绑定套接字,提升UDP接收性能,在高流量场景下建议开启。

会话保持方面,TCP场景可以使用hash $remote_addr consistent;让同一客户端IP始终落到同一台后端,配合一致性哈希算法可以在后端增减时减少会话迁移。对于需要更细粒度控制的场景,还可以通过split_clients模块或者map指令结合自定义变量来做路由。

四、获取客户端真实IP与生产注意事项

四层代理有一个绕不开的问题:后端看到的连接来源是Nginx的IP,而不是客户端真实IP。stream模块提供了PROXY protocol支持来解决这个问题。Nginx作为接收端配置proxy_protocol on;,作为发送端配置proxy_protocol on;转发时带上协议头,后端也必须支持解析PROXY protocol才行,例如HAProxy、PostgreSQL较新版本都支持。配置示例:

server {
    listen 3306 proxy_protocol;   # 接收带PROXY protocol的连接
    proxy_pass mysql_backend;
    proxy_protocol on;            # 向后端转发时附带真实源IP信息
}

生产环境还有几点需要注意。第一,stream和http可以共存于同一个Nginx实例,但监听端口不能冲突,可以用netstat -tlnpu排查。第二,Nginx的worker_connections要调大,因为每一个四层代理连接会占用两个连接资源,默认的1024远远不够,建议设置到65535以上,同时调整系统的文件描述符限制。第三,排障时开启访问日志非常关键,stream模块有自己的log_format指令,可以记录客户端地址、后端地址、连接时长、收发字节数等信息:

log_format stream_log '$remote_addr [$time_local] $protocol '
                      '$status $bytes_sent $bytes_received '
                      '$session_time "$upstream_addr"';

server {
    listen 3306;
    proxy_pass mysql_backend;
    access_log /var/log/nginx/stream.access.log stream_log;
}

通过日志中的session_time和字节数,可以快速判断连接是否被提前掐断、流量是否异常。掌握了stream模块的这些配置要点后,Nginx就不再只是一个Web服务器,而是一个轻量高效的四层负载均衡器,完全可以替代HAProxy完成大部分TCP/UDP转发场景的任务。

Nginxstream模块TCP代理修改时间:2026-09-01 03:20:51

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。