Nginx stream模块通过allow/deny指令实现TCP/UDP层IP黑白名单,按自上而下顺序匹配,首条命中即生效,默认隐含deny all;白名单仅配allow,黑名单先allow后deny,推荐用geo变量实现动态控制。

在 Nginx 的 stream 模块中,可以通过 allow 和 deny 指令实现四层(TCP/UDP)的 IP 白名单或黑名单控制。它工作在传输层,不解析应用层协议(如 HTTP),因此适用于 SSH、MySQL、Redis、TLS 直通等场景。
基础语法与作用顺序
allow 和 deny 必须放在 stream 块内的 server 块中,按**自上而下顺序匹配**,遇到第一条匹配规则即生效,后续规则不再检查。默认行为是拒绝所有未显式允许的连接(即隐含 deny all)。
常见写法示例:
-
allow 192.168.1.0/24;→ 允许该网段 -
deny 203.0.113.5;→ 拒绝该单个 IP -
deny all;→ 显式拒绝其余所有(可选,因默认即如此)
实现白名单(仅允许可信 IP 访问)
白名单模式下,只列出 allow 规则,其余自动拒绝。适合严格管控的后端服务(如数据库主库)。
配置示例:
stream {
server {
listen 3306;
proxy_pass backend_mysql;
allow 10.0.2.10;
allow 10.0.2.11;
allow 172.16.0.0/16;
# 没有 deny all 也可,Nginx 默认拒绝未匹配的连接
}
}注意:如果配置中混入了 deny,需确保 allow 在 deny 之前,否则可能被提前拦截。
实现黑名单(放行大部分,禁用特定恶意 IP)
黑名单模式下,先放行大范围(如内网或全部),再用 deny 精确屏蔽。适合对外提供服务但需封禁已知攻击源的场景。
配置示例:
stream {
server {
listen 22;
proxy_pass backend_ssh;
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny 198.51.100.23;
deny 203.0.113.0/24;
deny all; # 显式兜底,增强可读性
}
}⚠️ 关键点:deny all 必须放在最后;若漏掉,且前面没有覆盖全部合法来源,则可能意外放行非法 IP。
结合 geo 或 map 实现动态黑白名单
硬编码 IP 不利于维护。可通过 geo 或 map 指令将 IP 映射为变量,再用 if + deny 控制(注意:stream 中 if 仅支持有限上下文,推荐用 geo 配合 allow/deny)。
推荐方式(使用 geo):
stream {
geo $blocked_ip {
default 0;
192.0.2.100 1;
203.0.113.0/24 1;
}
<pre class="brush:php;toolbar:false;">server {
listen 6379;
proxy_pass backend_redis;
if ($blocked_ip) {
deny all;
}
allow all;
}}
说明:Nginx stream 模块中 if 仅支持简单条件(如变量值判断),且必须配合 deny/allow 使用;allow all 放在最后,确保非黑名单 IP 可通过。


















