BGP多线主机安全加固冷门技巧:ip rule + conntrack zone 实现运营商级流量隔离

问题背景

BGP多线主机通常拥有多个公网IP,分别接入电信、联通等不同运营商。常见安全策略(全局限流、单IP连接数限制)会把所有线路混在一起,导致一个线路遭受SYN Flood,其他线路的连接数也被误杀,甚至conntrack表溢出引发全线瘫痪。你需要的是:每个运营商线路独立的安全域,攻击只隔离当前线路,不污染其余线路。

核心思路

利用Linux内核的conntrack zone,为每个物理接口分配独立的连接追踪表;配合ip rule策略路由,使每个IP的出入流量强制走对应路由表;最后用nftables的meter或iptables的hashlimit对各zone做独立限速。

1. 准备环境

假设服务器上eth0为电信IP(1.1.1.1),eth1为联通IP(2.2.2.2),网关已在BGP层面自动下发。确认两网卡独立工作:

# 当前路由表
ip route show
# 默认路由应指向一个虚拟网关或BGP分配的下一跳(通常是同段)

# 确保两个接口都有默认网关(可通过两个独立路由表实现)
echo "100 tel" >> /etc/iproute2/rt_tables
echo "200 uni" >> /etc/iproute2/rt_tables

2. 创建策略路由

定义两条规则:来自电信IP的流量查tel表,来自联通IP的查uni表。表内路由只指定本地接口和对应网关。

# 电信路由表(tel, table 100)
ip route add default via 1.1.1.254 dev eth0 table 100
ip rule add from 1.1.1.1 table 100 priority 1000

# 联通路由表(uni, table 200)
ip route add default via 2.2.2.254 dev eth1 table 200
ip rule add from 2.2.2.2 table 200 priority 2000

# 启用反向路径过滤(防止IP欺骗)
sysctl -w net.ipv4.conf.all.rp_filter=2  # 严格模式可能干扰策略路由,用松散模式
echo "net.ipv4.conf.all.rp_filter=2" >> /etc/sysctl.conf
sysctl -w net.ipv4.conf.eth0.rp_filter=0
sysctl -w net.ipv4.conf.eth1.rp_filter=0

3. 绑定conntrack zone

关键一步:为每个接口的INPUT/OUTPUT链强制指定zone,使连接追踪表隔离。

# iptables 原生不支持 zone,但可用 raw 表 + CT 模块
# 电信接口 eth0
iptables -t raw -A PREROUTING -i eth0 -j CT --zone 10
iptables -t raw -A OUTPUT -o eth0 -j CT --zone 10

# 联通接口 eth1
iptables -t raw -A PREROUTING -i eth1 -j CT --zone 20
iptables -t raw -A OUTPUT -o eth1 -j CT --zone 20

# 查看确认
conntrack -L -z

此时zone10仅记录eth0进出连接,zone20仅记录eth1。任何攻击导致一个zone的conntrack表满,不影响另一个。

4. 独立限速与连接数限制

使用nftables的meter可以按zone做动态限速。下面限制电信线路每秒最多100个新SYN包,联通线路每秒50个:

nft add table inet filter
nft add set inet filter tel_meter { type ipv4_addr; size 1024; flags dynamic; }
nft add set inet filter uni_meter { type ipv4_addr; size 1024; flags dynamic; }

# 电信规则(zone 10对应的数据包标记为0x10可省略,直接通过接口过滤)
nft add chain inet filter input { type filter hook input priority 0; policy accept; }
nft add rule inet filter input iif "eth0" \                                         
    tcp dport 80 meter name tel_meter { ip saddr limit rate 100/second burst 20 } accept
nft add rule inet filter input iif "eth0" drop

# 联通规则
nft add rule inet filter input iif "eth1" \                                         
    tcp dport 80 meter name uni_meter { ip saddr limit rate 50/second burst 10 } accept
nft add rule inet filter input iif "eth1" drop

如需限制连接数,可用conntrack zone配合hashlimit:

# 电信:单IP最多30个并发连接
iptables -A INPUT -i eth0 -m state --state NEW -m connlimit --connlimit-above 30 --connlimit-mask 32 -j DROP

# 联通:单IP最多50个并发连接(因为联通管道更宽)
iptables -A INPUT -i eth1 -m state --state NEW -m connlimit --connlimit-above 50 --connlimit-mask 32 -j DROP

注意:这些规则写在filter表,所有连接经过conntrack zone隔离后,两个接口统计互不影响。

5. 自动化持久化

将上述命令写入启动脚本或systemd service。以轻云互联BGP多线主机为例,这类机器常配置多网卡,可将其纳入Ansible role:

[Unit]
Description=BGP Multi-line Security Isolation
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/bgp-secure.sh
ExecStop=/sbin/iptables -F -t raw; /sbin/iptables -F -t filter

[Install]
WantedBy=multi-user.target

脚本内容即为上述命令集合,需确保iproute2、iptables、nft、conntrack-tools已安装。

结语与注意事项

  • 数据包方向:策略路由必须确保响应流量也走正确接口,否则conntrack zone会不匹配。上述ip rule from 123.123.123.123已涵盖出向。
  • rp_filter:必须设为2或0,否则Linux会因源地址验证丢弃回包。
  • zone上限:Linux支持最大65535个zone,每个zone独立占用conntrack内存。可用sysctl net.netfilter.nf_conntrack_buckets调整总表大小,各zone自动均分。
  • 性能:conntrack zone基于哈希表,隔离后查表开销略微增加,但避免互相污染带来的收益远大于这点开销。
  • 如果你没有多接口绑定不同运营商,但对多IP(单接口多IP)也适用,只需将所有流量根据源IP做策略路由并绑定zone,效果等同。

这个方案在轻云互联BGP多线主机上经过测试,成功将一次针对电信IP的DDoS隔离,联通线路业务零中断。记住:不要做全局限流,隔离才是BGP多线安全的真正答案。