Nginx基础教程(93)Nginx Stream机制监听端口:别让数据库裸奔!Nginx Stream:你家的服务端口,需要一个“隐形保安”

第一章:开门见山——那个“裸奔”的数据库,我看不下去了!

兄弟们,不知道你们有没有干过这种事:项目紧,任务急,为了图省事,直接把测试服务器,甚至是生产环境的Redis或者MySQL端口(比如3306, 6379)在防火墙上一开放,啪一下,就能连了。

方便是真方便,但你这相当于把家里的金库大门,直接对着大马路敞开啊!每天都有无数脚本小子在网络上扫描这些默认端口,尝试各种弱密码攻击。你这不叫开放,这叫“裸奔”,是在危险的边缘疯狂试探!

那有同学要问了:“我知道危险啊,但我需要用远程工具连上去看数据、做调试啊,不暴露端口怎么办?用SSH隧道?太麻烦!用跳板机?还得维护一台机器!”

今天,我就来给你介绍一位被你严重低估的“隐形保安”——Nginx Stream模块。它就能完美、优雅且强大地解决这个问题。

第二章:重新认识Nginx——它不只是个“网站前台”

在咱们的固有印象里,Nginx是干啥的?处理HTTP请求的,做反向代理的,动静分离的,负载均衡的。没错,它是个顶级的“网站前台”和“流量调度员”。

但你知道吗?从Nginx 1.9.0版本开始,它解锁了一个新姿势:
ngx_stream_core_module
模块。这个模块让Nginx的能力,从应用层(HTTP/HTTPS)一下子下沉到了传输层(TCP/UDP)

打个比方你就懂了:

传统的HTTP反向代理:像一个大公司的前台总机。你打电话(发HTTP请求)过来,说“喂,我找销售部”,前台帮你转接到销售部的分机。她只处理“找部门”这种特定规则的请求。今天的Stream代理:像一家国际货运港的中央调度。它不关心集装箱里装的是玩具汽车还是冰箱(不解析HTTP协议),它只认集装箱上的目的港标签(目标端口)。你的货船(TCP数据流)来了,它根据标签,指挥吊车把集装箱准确无误地装上去往目的港的另一艘货船上。

所以,Stream模块的核心能力就是:“无脑”转发TCP/UDP数据流。这意味着,它几乎可以代理任何基于TCP/UDP的服务!

数据库?MySQL, PostgreSQL, Redis, 没问题!邮件服务?SMTP, POP3, IMAP, 拿下!SSH, RDP远程桌面?照样通吃!甚至你可以用它来代理游戏服务器、内网穿透……

第三章:Stream模块的“超能力”详解——不只是转发那么简单

如果你以为Stream模块就是个端口转发工具,那可就太小看它了。这位“保安”可是身怀绝技的:

负载均衡:没错,和HTTP模块一样,它可以在多个后端服务实例之间做负载均衡。你的数据库搞了主从复制、读写分离?用Stream模块,一个入口,智能分发到不同的数据库实例上,支持
round-robin

least_conn
等算法。连接限速与控制:可以限制到后端服务的并发连接数,防止某个服务被海量连接拖垮。SSL/TLS终结/加密:可以在Nginx这一层就完成SSL/TLS的加解密。比如,你可以让客户端到Nginx走加密的SSL连接,而Nginx到后端服务走内网明文,既保证了公网传输的安全,又减轻了后端服务的计算压力。反过来,也可以做SSL加密转发。访问控制:基于IP地址允许或拒绝连接,这是最基本的安保措施。高可用与健康检查:虽然Stream模块默认的健康检查比较基础(主要靠连接成功与否),但通过一些第三方模块或商业版Nginx Plus,可以实现主动式健康检查,确保流量只被转发到健康的后端节点。日志记录:可以对TCP/UDP会话进行日志记录,方便你排查网络连接问题,看看是谁、在什么时候、想连你的服务。

看到没,它不是一个简单的“端口映射工具”,而是一个企业级的传输层网关

第四章:手把手实战——给你的数据库请一位“保安”

理论吹得再响,不如上手干一把。我们来一个最经典的场景:通过Nginx Stream代理,让公网安全地访问内网的Redis服务。

环境准备:

Nginx服务器:假设IP是
123.123.123.123
,已经安装Nginx,且版本 >= 1.9.0。Redis服务器:假设IP是
192.168.1.100
,端口
6379
,只在内部网络可达。

第一步:确认你的Nginx“武功”没被废

Stream模块默认可能没有编译进去。检查一下:


nginx -V

在输出的巨长一串参数里,睁大眼睛找
--with-stream
这个字样。如果有,恭喜你,神功已成。如果没有……你可能需要重新编译安装Nginx,或者找找包含此模块的发行版。

第二步:配置你的“保安工作手册”

Nginx的配置文件通常是
/etc/nginx/nginx.conf
。我们需要在
http
块的同级,配置一个
stream
块。



# /etc/nginx/nginx.conf
 
# 这里是处理HTTP流量的传统区域,我们今天不碰它
http {
    ... # 你原来的各种server、location配置
}
 
# 注意!这里是和 http 平级的 stream 区域,我们的“保安”在这里上班
stream {
    # 定义一个上游服务器组,名字叫 redis_backend
    upstream redis_backend {
        server 192.168.1.100:6379 max_fails=3 fail_timeout=30s;
    }
 
    # 定义一个Stream类型的服务器,用来监听外部请求
    server {
        # 监听本机的6390端口。注意!我们不用6379,用一个新的。
        listen 6390;
        
        # 重要:指定协议是TCP,Redis用的是TCP协议
        proxy_pass redis_backend;
        
        # 可选:设置代理连接的超时时间
        proxy_timeout 3s;
        proxy_connect_timeout 2s;
        
        # 可选:开启日志,记录TCP连接信息
        # 需要你在 http 块里定义一个合适的 log_format,比如 ‘main’
        access_log /var/log/nginx/redis_stream.access.log main;
        
        # 可选:简单的访问控制,只允许你的办公IP连接
        # allow 202.96.134.100;
        # deny all;
    }
    
    # 你还可以继续配置其他服务的代理,比如MySQL
    # server {
    #    listen 33060;
    #    proxy_pass mysql_backend;
    #    ...
    # }
}

配置文件解读:


stream { ... }
:这是Stream功能的“大本营”,所有传输层代理配置都写在这里。
upstream redis_backend { ... }
:定义后端真正的服务地址。这里可以写多个
server
做负载均衡。
server { ... }
:在Stream语境下,这个
server
块代表一个“监听器”。
listen 6390
:让Nginx在公网IP的6390端口上“竖起耳朵”监听。我们故意不用Redis的默认6379端口,这也是一种简单的安全规避。
proxy_pass redis_backend
:核心指令,把所有发到本机6390端口的TCP流量,原封不动地转发给
upstream
里定义的
192.168.1.100:6379

proxy_timeout
:如果连接空闲超过这个时间,Nginx会主动关闭它。
access_log
:记录下来谁连过,非常重要。

第三步:让“保安”上岗

保存配置文件。测试配置文件语法是否正确:


nginx -t

如果显示
syntax is ok, test is successful
,就可以继续。

重载Nginx配置,让它生效:


systemctl reload nginx  # 或者 service nginx reload

第四步:验收“保安”的工作成果

现在,不要再去直连你的
192.168.1.100:6379
了。你的Redis客户端应该连接的是:

主机:
123.123.123.123

端口:
6390

你可以用
redis-cli
测试一下:


redis-cli -h 123.123.123.123 -p 6390

然后输入
ping
,如果返回
PONG
,恭喜你!你的“隐形保安”正式上岗了!

你的连接路径现在是:
你的电脑 -> Nginx公网IP:6390 -> 内网Redis服务器:6379
。那个危险的6379端口,已经从公网上“消失”了。

第五章:高级玩法与避坑指南

1. 负载均衡实战:

如果你的Redis有多个从节点做读扩展,可以这样配置:



stream {
    upstream redis_cluster {
        server 192.168.1.100:6379 weight=2; # 主库,权重高一点
        server 192.168.1.101:6379; # 从库1
        server 192.168.1.102:6379; # 从库2
    }
 
    server {
        listen 6390;
        proxy_pass redis_cluster;
    }
}

2. SSL/TLS加密:

假设你要代理一个需要SSL的MySQL:



stream {
    upstream mysql_backend {
        server 192.168.1.200:3306;
    }
 
    server {
        listen 33060 ssl; # 监听时开启SSL
        proxy_pass mysql_backend;
        
        # 指定SSL证书和密钥
        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_session_cache shared:SSL:10m;
        
        # 如果你的MySQL也要求SSL,那么Nginx到后端也需要配置
        # proxy_ssl on;
        # proxy_ssl_certificate ...;
    }
}

3. 常见大坑:

权限问题:在Linux上,Nginx默认可能没有权限绑定1024以下的端口(如80, 443)。如果你要用低端口,需要给Nginx主进程相应的权限,或者用
authbind
等工具。协议混淆:一定要记住,
stream
块和
http
块是平级的,不能嵌套。
http
里的
server

location
等指令在
stream
里是无效的。性能调优:对于高并发场景,你可能需要调整
worker_processes

worker_connections
,以及在
stream
块内使用
proxy_buffer_size
等指令来优化TCP代理性能。

第六章:总结——让“裸奔”成为历史

好了,到这里,相信你已经对Nginx Stream模块有了一个全新且深入的认识。它绝不是Nginx的一个小插件,而是一个能够极大提升你架构安全性和灵活性的神兵利器。

从今天起,忘掉那种把数据库端口直接暴露在公网上的危险操作吧。给你的核心服务请一位像Nginx Stream这样靠谱的“隐形保安”。

它不关心你后端跑的是什么协议(Redis, MySQL, SSH……),它只负责一件事:安全、可靠、高效地把网络数据包送到该去的地方。这种“专注”,正是它强大和优雅的地方。

行动起来,点开你的服务器,修改一下Nginx配置,让你家的服务端口,从此告别“裸奔”时代!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
夏末秋至的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容