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多线安全的真正答案。