1. Nginx作为四层代理的核心价值
Nginx从1.9.0版本开始正式支持stream模块,使其具备了四层(传输层)代理能力。这意味着我们不再需要额外部署HAProxy等专门的四层代理工具,单靠Nginx就能同时处理HTTP(七层)和TCP/UDP(四层)流量。在实际生产环境中,这种架构简化带来的好处非常明显:
- 统一运维入口:所有流量管控通过Nginx单一界面完成
- 资源利用率提升:避免多组件带来的内存和CPU开销
- 配置管理集中化:使用相同的语法管理不同层级的代理规则
重要提示:编译Nginx时必须显式启用
--with-stream配置参数,否则无法使用TCP/UDP代理功能。如果是通过包管理器安装的版本,可能需要额外安装nginx-extras包。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. TCP代理配置实战
2.1 基础TCP代理实现
在nginx.conf的全局块中添加stream上下文,这是与http平级的配置区域:
nginx复制stream {
upstream tcp_backend {
server 192.168.1.100:3306; # MySQL示例
server 192.168.1.101:3306 backup;
}
server {
listen 3307;
proxy_pass tcp_backend;
proxy_connect_timeout 3s;
proxy_timeout 1h;
}
}
关键参数解析:
proxy_connect_timeout:建立到后端连接的超时时间proxy_timeout:连接保持的最长时间proxy_buffer_size:调优TCP窗口大小(默认4k/8k)
2.2 高级TCP调优技巧
对于高并发TCP场景(如数据库连接池),需要调整内核参数:
bash复制# 增加本地端口范围
echo "net.ipv4.ip_local_port_range = 1024 65535" >> /etc/sysctl.conf
# 提高TCP最大连接数
echo "net.core.somaxconn = 32768" >> /etc/sysctl.conf
# 启用TCP快速回收
echo "net.ipv4.tcp_tw_recycle = 1" >> /etc/sysctl.conf
sysctl -p
在Nginx配置中对应需要设置:
nginx复制server {
listen 3307 so_keepalive=on;
proxy_pass tcp_backend;
proxy_socket_keepalive on;
proxy_buffer_size 16k;
}
3. UDP代理的特殊处理
3.1 基础UDP配置示例
UDP代理需要显式指定协议,以下以DNS服务为例:
nginx复制stream {
upstream udp_dns {
server 8.8.8.8:53; # Google DNS
}
server {
listen 53 udp reuseport;
proxy_pass udp_dns;
proxy_timeout 5s;
}
}
关键差异点:
listen指令必须包含udp参数reuseport选项可显著提升UDP性能- 超时时间通常设置较短(UDP是无状态协议)
3.2 UDP性能优化要点
UDP代理容易遇到缓冲区溢出问题,需要调整:
bash复制# 增加UDP缓冲区大小
sysctl -w net.core.rmem_max=26214400
sysctl -w net.core.wmem_max=26214400
对应Nginx配置:
nginx复制server {
listen 53 udp reuseport rcvbuf=256k sndbuf=256k;
proxy_pass udp_dns;
proxy_responses 1; # 预期接收的响应包数量
}
4. 生产环境常见问题排查
4.1 连接拒绝(Connection Refused)
典型错误日志:
code复制connect() failed (111: Connection refused) while connecting to upstream
排查步骤:
- 检查后端服务是否监听正确端口:
netstat -tulnp | grep 3306 - 验证防火墙规则:
iptables -L -n -v - 测试基础连通性:
telnet 192.168.1.100 3306
4.2 UDP包丢失问题
诊断方法:
bash复制# 使用tcpdump抓包
tcpdump -i eth0 udp port 53 -vv -w /tmp/dns.pcap
# 使用iperf3测试吞吐量
iperf3 -s -p 5001 # 服务端
iperf3 -c server_ip -p 5001 -u -b 100M # 客户端
解决方案:
- 增加
proxy_responses数量 - 调整
rcvbuf/sndbuf缓冲区大小 - 启用
reuseport减少锁竞争
5. 安全加固配置
5.1 访问控制列表
nginx复制server {
listen 3307;
allow 10.0.0.0/8;
deny all;
proxy_pass tcp_backend;
}
5.2 SSL/TLS终止
对于需要加密的TCP流量:
nginx复制server {
listen 443;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
proxy_pass backend_servers;
proxy_ssl on;
proxy_ssl_verify off; # 根据实际情况调整
}
6. 性能监控与日志
6.1 关键指标监控
nginx复制stream {
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr"';
access_log /var/log/nginx/stream-access.log proxy;
open_log_file_cache off;
}
推荐监控指标:
nginx.stream.sessions.total:当前活跃连接数nginx.stream.bytes.received:接收字节数nginx.stream.bytes.sent:发送字节数
6.2 动态负载均衡
使用nginx-plus或openresty实现动态路由:
lua复制stream {
lua_add_variable $target_backend;
server {
listen 3307;
set_by_lua_block $target_backend {
-- 基于客户端IP的哈希算法
return ngx.var.remote_addr:gsub("%.+", "") % 2 == 0
and "backend1:3306" or "backend2:3306"
}
proxy_pass $target_backend;
}
}
在实际部署中发现,UDP代理对MTU大小特别敏感。曾经遇到一个案例:当客户端MTU为1500而服务器端MTU为9000时,会导致大包被静默丢弃。解决方案是在Nginx所在主机上统一MTU设置:
bash复制# 查看当前MTU
ip link show eth0 | grep mtu
# 临时修改MTU
ip link set dev eth0 mtu 1500
# 永久修改(CentOS)
echo "MTU=1500" >> /etc/sysconfig/network-scripts/ifcfg-eth0
