BGP多线主机DDoS清洗实战:基于Flowspec + 策略路由的自动化流量牵引与回注

背景

BGP多线主机天然具备多出口优势,但面对UDP Flood、SYN Flood等大流量攻击时,传统高防IP回源模式会引入额外延迟和成本。本文以“轻云互联”的BGP多线实例为例,演示一种不需要高防IP清洗机,而是直接利用主机自身多线网卡和BGP Flowspec协议,实现攻击流量的自动牵引到空路由,并将正常业务流量平滑回注的实战方案。

前置条件

  • 拥有BGP多线主机(已从ISP获取AS号及IP段,且支持Flowspec能力)
  • 安装FRRouting (FRR) 作为BGP Speaker,版本 ≥ 7.5
  • 安装iptables + ipset + nftables(用于流量采样和标记)

Step 1: 部署BGP Flowspec节点

Flowspec本质是通过BGP扩展属性向路由器下发流量规则。我们让主机自身充当Flowspec客户端,将检测到的攻击源IP动态注入到上游路由器的黑洞路由。以下配置基于FRR:

# /etc/frr/frr.conf
router bgp 65001
 bgp router-id 10.0.0.1
 neighbor 10.0.0.254 remote-as 65000
 !
 address-family ipv4 flowspec
  neighbor 10.0.0.254 activate
 exit-address-family
!
route-map FLOWSPEC-TO-BLACKHOLE permit 10
 set ip next-hop 192.0.2.1   # 特殊黑洞下一跳(上游路由器配置drop)
!
ip prefix-list ATTACK_SRC seq 5 permit 203.0.113.0/24

启用Flowspec后,上游路由器会接受我们宣告的ip next-hop 192.0.2.1的规则,从而将流量黑洞。攻击检测由后续脚本触发。

Step 2: 基于netfilter的实时攻击检测

利用iptables的hashlimit模块对每源IP的SYN和UDP包速率进行采样,超过阈值后自动将源IP加入attack_ips集合:

# 创建ipset集合(支持IPv6可改为hash:net)
ipset create attack_ips hash:ip timeout 600

# iptables规则(在FORWARD链或INPUT链均可)
iptables -A FORWARD -m set ! --match-set attack_ips src \
    -p tcp --syn -m hashlimit --hashlimit-name syn_limit \
    --hashlimit-above 200/sec --hashlimit-burst 300 \
    --hashlimit-mode srcip --hashlimit-srcmask 32 -j SET --add-set attack_ips src

iptables -A FORWARD -m set ! --match-set attack_ips src \
    -p udp -m hashlimit --hashlimit-name udp_limit \
    --hashlimit-above 1000/sec --hashlimit-burst 1500 \
    --hashlimit-mode srcip --hashlimit-srcmask 32 -j SET --add-set attack_ips src

说明:attack_ips中的IP自动过期,避免误封永久生效。

Step 3: 自动宣告Flowspec规则

编写Python脚本监控attack_ips集合的变动,通过FRR的Unix Socket动态创建Flowspec路由:

#!/usr/bin/env python3
import ipset
import frr_socket  # 简化示意,实际使用pyroute2或直接vtysh

def flowspec_ban(ip):
    cmd = f"vtysh -c 'configure terminal' -c 'route-map FLOWSPEC-TO-BLACKHOLE permit 20' \
           -c 'match ip address prefix-list BLACKHOLE' \
           -c 'set ip next-hop 192.0.2.1' \
           -c 'ip prefix-list BLACKHOLE seq 5 permit {ip}/32'"
    os.system(cmd)

def monitor():
    s = ipset.IPSET()
    while True:
        changes = s.changes()
        for entry in changes.get('added', []):
            flowspec_ban(entry)
        time.sleep(5)

if __name__ == "__main__":
    monitor()

注意:实际生产环境中需用IPC调用FRR的vtysh或使用pyroute2.BGPSpeaker直接发送Flowspec update。上方代码仅用于演示逻辑。

Step 4: 多线策略路由实现正常流量回注

攻击流量被上游黑洞后,正常流量仍需要正确返回。利用BGP多线主机的多张网卡(如eth1对应电信,eth2对应联通),使用ip ruleiptables的MARK标记实现基于源IP的回注策略:

# 建立两个路由表
echo "100 telecom" >> /etc/iproute2/rt_tables
echo "200 unicom" >> /etc/iproute2/rt_tables

# 默认路由指向电信(主表)
ip route add default via 电信网关 dev eth1

# 联通表添加默认路由
ip route add default via 联通网关 dev eth2 table unicom

# 对于来自联通IP段的流量,标记后使用联通表
iptables -t mangle -A PREROUTING -i eth2 -s 联通IP段 -j MARK --set-mark 200
iptables -t mangle -A PREROUTING -i eth2 -s 联通IP段 -j CONNMARK --save-mark

# 策略路由
ip rule add fwmark 200 table unicom priority 100
ip rule add from 联通IP段 table unicom priority 200  # 冗余策略

通过conntrack保证同一条连接的返回包也走对应出口。上述配置需结合rp_filter的调整,避免反向路径过滤误杀:

sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.eth1.rp_filter=0
sysctl -w net.ipv4.conf.eth2.rp_filter=0

验证与排障

  • Flowspec生效检查:登录上游路由器执行show bgp ipv4 flowspec,应能看到主机的规则。
  • 攻击源自动被黑洞后,本地ipset list attack_ips可见。
  • 回注测试:从不同运营商ping主机IP,通过traceroute确认路径差异。

若遇到策略路由不生效,检查ip rule show优先级以及conntrack -L中MARK值是否正确传递。在“轻云互联”的BGP多线主机上,建议将上述脚本纳入cron或systemd服务实现自愈。

总结

此方案将DDoS防护重心从依赖高防节点转向主机自身能力,充分利用BGP多线主机的网络灵活性。实际部署中需注意Flowspec规则数量限制(通常建议不超过100条),以及上游路由器对Flowspec的支持程度。使用“轻云互联”主机的用户可直接复用上述配置,其BGP邻居对Flowspec宣告兼容性较好。