“无感知灰度推流”可通过nftables基于源ip的dnat实现:创建带超时的ipv4集合,优先匹配灰度ip并dnat至新后端,其余流量默认dnat至旧后端,全程四层处理、不干预协议,毫秒级生效且无连接中断。

“无感知灰度推流”不是 nftables 的原生能力,nftables 本身不处理媒体流、不解析音视频协议(如 RTMP、SRT、HLS),也不具备流量调度或 AB 测试意义上的“灰度发布”逻辑。nft add element 命令仅用于向已定义的集合(set)中添加元素(如 IP、端口、IPv4/IPv6 地址),它没有路由决策、负载均衡、会话保持或内容感知功能。
但如果你的目标是:
✅ 在流媒体服务(如 Nginx-RTMP、SRS、FFmpeg 推流网关)前,用 nftables 按客户端 IP 实现轻量级、低延迟的灰度分流;
✅ 让部分用户(例如指定 IP 段)被静默导向新版本流服务,其余走默认路径;
✅ 整个过程对终端播放器无重连、无卡顿、无协议层感知(即“无感知”);
那么可借助 nft add element 配合 DNAT + 集合 + 连接跟踪 构建一个基于源 IP 的透明灰度入口网关。关键在于:分流动作发生在四层(TCP/UDP),不触碰应用层流协议,因此播放器完全无感。
1. 前提:部署双流服务后端并明确区分路径
假设你有:
- 默认流服务:
10.0.0.10:1935(旧版 RTMP 推流) - 灰度流服务:
10.0.0.20:1935(新版,功能/性能待验证) - 公网入口:
eth0,IP 为203.0.113.5,监听1935端口
✅ 注意:两个后端需提供完全兼容的协议行为和流路径(如相同 app 名、stream 名),否则播放器会因 404 或协议错误中断——这才是“感知”的根源,而非防火墙。
2. 创建带超时的灰度 IP 集合
# 创建一个支持自动过期的 IPv4 地址集合(用于灰度名单)
sudo nft add set inet filter gray_ips { type ipv4_addr\; flags timeout\; }
# 示例:将测试用户 IP 加入灰度池,10 分钟后自动移除(便于快速回滚)
sudo nft add element inet filter gray_ips { 192.168.10.42 timeout 10m }
sudo nft add element inet filter gray_ips { 203.0.113.111 timeout 10m }
⚠️ 不要用
flags dynamic—— 它不支持 timeout,无法自动清理;必须用flags timeout才能实现“临时灰度”。
3. 在 NAT 表中插入灰度 DNAT 规则(顺序关键)
在 nat prerouting 链顶部插入规则,确保灰度匹配优先于默认转发:
# 1. 匹配灰度 IP + 目标端口 1935 → DNAT 到新后端 sudo nft add rule inet filter prerouting ip saddr @gray_ips tcp dport 1935 dnat to 10.0.0.20:1935 # 2. 默认所有 1935 流量 → DNAT 到旧后端(兜底) sudo nft add rule inet filter prerouting tcp dport 1935 dnat to 10.0.0.10:1935
? 为什么“无感知”?因为:
- 所有连接都经过
prerouting阶段完成目标地址改写;- 客户端始终连接
203.0.113.5:1935,不知道自己被导向哪台机器;- TCP 三次握手、RTMP 握手、流数据均在改写后透明传输,无协议干预;
nft add element操作毫秒级生效,无需 reload、无连接中断。
4. 配合 conntrack 避免连接状态错乱
确保连接跟踪正常工作,防止 DNAT 后响应包无法正确返回:
# 确保 raw 表未禁用 conntrack(常见误操作) sudo nft add rule ip raw prerouting ct state invalid drop # 在 filter 表放行已建立连接(保障回程通路) sudo nft add rule inet filter forward ct state established,related accept
? 若后端使用不同网段,还需配置
masquerade或静态路由,确保响应包能原路返回。
5. 动态灰度扩缩容(运维友好)
-
加灰度用户:
sudo nft add element inet filter gray_ips { 192.168.10.99 timeout 2h } -
删灰度用户:
sudo nft delete element inet filter gray_ips { 192.168.10.99 } -
清空全部灰度:
sudo nft flush set inet filter gray_ips -
查看当前灰度列表:
sudo nft list set inet filter gray_ips
所有操作原子执行,不影响已有连接,真正实现“热灰度”。
不复杂但容易忽略。











