Nginx TCP 代理 (Stream 模块)
Nginx 从 1.9.0 版本开始引入了 ngx_stream_core_module 模块,支持四层(TCP/UDP)代理,不再仅限于七层 HTTP 代理。
1. 模块检查与安装
bash
复制
# 检查是否包含 stream 模块
nginx -V 2>&1 | grep -o with-stream
# 如果没有,需要重新编译安装
./configure --with-stream --with-stream_ssl_module
make && make install2. 基础 TCP 代理配置
编辑 nginx.conf,在顶层添加 stream 块(与 http 块同级):
nginx
复制
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
# ========== TCP 代理配置 ==========
stream {
# 日志格式
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received"';
access_log /var/log/nginx/stream-access.log proxy;
# 上游服务器组(负载均衡)
upstream backend_mysql {
server 192.168.1.10:3306 weight=5;
server 192.168.1.11:3306 weight=5;
server 192.168.1.12:3306 backup; # 备用服务器
}
# MySQL 代理
server {
listen 3306;
proxy_pass backend_mysql;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
# Redis 代理
upstream backend_redis {
server 192.168.1.20:6379;
server 192.168.1.21:6379;
}
server {
listen 6379;
proxy_pass backend_redis;
proxy_timeout 30s;
}
# SSH 代理(跳板机场景)
server {
listen 2222;
proxy_pass 192.168.1.100:22;
allow 10.0.0.0/8; # 允许的内网IP
deny all; # 拒绝其他所有
}
}
# =================================
http {
# 原有的 HTTP 配置...
}3. 高级配置示例
3.1 SSL/TLS 终止(数据库加密代理)
nginx
复制
stream {
# MySQL SSL 代理:客户端->Nginx(SSL)->MySQL(明文)
server {
listen 3307 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
proxy_pass 192.168.1.10:3306;
proxy_ssl off; # 后端不使用 SSL
}
# 或者:SSL 透传(不解密,仅转发)
server {
listen 3306;
proxy_pass 192.168.1.10:3306;
proxy_ssl on; # 与后端建立 SSL 连接
proxy_ssl_certificate /etc/nginx/ssl/client.crt;
proxy_ssl_certificate_key /etc/nginx/ssl/client.key;
}
}3.2 健康检查与故障转移
nginx
复制
stream {
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
# 健康检查(需要 nginx_upstream_check_module 或商业版)
check interval=3000 rise=2 fall=3 timeout=1000;
}
server {
listen 8080;
proxy_pass backend;
# 连接数限制
limit_conn addr 10;
}
}3.3 根据端口分流(多服务代理)
nginx
复制
stream {
# 使用 map 根据端口路由到不同后端
map $server_port $backend_port {
3306 3306; # MySQL
6379 6379; # Redis
5432 5432; # PostgreSQL
}
server {
listen 3306;
listen 6379;
listen 5432;
proxy_pass 192.168.1.10:$backend_port;
}
}4. 常用指令说明
表格
5. 实际应用场景
场景 1:数据库统一入口
nginx
复制
stream {
upstream mysql_cluster {
least_conn; # 最少连接算法
server db1.internal:3306;
server db2.internal:3306;
}
server {
listen 3306;
proxy_pass mysql_cluster;
# 应用只需连接 Nginx 地址,无需知道真实数据库位置
}
}场景 2:端口转发 + 安全限制
nginx
复制
stream {
server {
listen 8080;
proxy_pass 10.0.0.5:80;
# 仅允许特定 IP 访问
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
}
}场景 3:SNI 路由(基于域名的 TCP 代理)
nginx
复制
stream {
map $ssl_preread_server_name $backend {
hostnames;
mysql.example.com 192.168.1.10:3306;
redis.example.com 192.168.1.11:6379;
default 192.168.1.10:3306;
}
server {
listen 443;
ssl_preread on; # 不解密,只读取 SNI
proxy_pass $backend;
}
}6. 验证与调试
bash
复制
# 检查配置语法
nginx -t
# 重载配置
nginx -s reload
# 查看 stream 模块日志
tail -f /var/log/nginx/stream-access.log
# 测试连接
nc -zv nginx-server 3306
telnet nginx-server 33067. 与 HTTP 代理的区别
表格
8. 注意事项
配置文件位置:
stream块必须与http块同级,不能嵌套在http内日志分离:建议为 stream 单独配置访问日志
防火墙:确保 Nginx 服务器防火墙开放代理端口
性能:四层代理性能通常优于七层代理,因为无需解析应用层协议