Nginx TCP 代理 (Stream 模块)

吴书松
吴书松
发布于 2026-04-10 / 1 阅读
0
0

Nginx TCP 代理 (Stream 模块)

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 install

2. 基础 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. 常用指令说明

表格

指令

说明

示例

listen

监听端口

listen 3306; / listen 3306 ssl;

proxy_pass

上游地址

proxy_pass backend; / proxy_pass 127.0.0.1:3306;

proxy_timeout

代理超时

proxy_timeout 10s;

proxy_connect_timeout

连接超时

proxy_connect_timeout 5s;

proxy_buffer_size

缓冲区大小

proxy_buffer_size 16k;

allow/deny

访问控制

allow 192.168.1.0/24;

ssl_preread

SNI 路由(不终止 SSL)

ssl_preread on;

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 3306

7. 与 HTTP 代理的区别

表格

特性

Stream (TCP)

HTTP

层级

四层(传输层)

七层(应用层)

处理内容

原始 TCP/UDP 数据包

HTTP 请求/响应

SSL 处理

可终止或透传

通常终止

负载均衡依据

连接级别

请求级别(URL、Header等)

适用场景

数据库、Redis、SSH、SMTP

Web 应用、API

8. 注意事项

  1. 配置文件位置stream 块必须与 http 块同级,不能嵌套在 http

  2. 日志分离:建议为 stream 单独配置访问日志

  3. 防火墙:确保 Nginx 服务器防火墙开放代理端口

  4. 性能:四层代理性能通常优于七层代理,因为无需解析应用层协议


评论