ebpf无法直接识别go应用层的syn flood,只能在网卡/协议栈层捕获原始syn行为;其核心逻辑需用c编写ebpf程序,在xdp或tc层解析ip/tcp头、统计每ip syn速率并实时丢弃,go仅能消费ebpf map中的聚合结果用于策略响应。

eBPF无法直接识别Go应用层的SYN Flood,只能在网卡/协议栈层捕获原始SYN行为
SYN Flood是TCP握手阶段的攻击,发生在Go应用收到Accept()之前,eBPF根本看不到Go进程——它看到的是网卡进来的SYN包、内核半连接队列状态、以及tcp_max_syn_backlog是否溢出。任何试图在Go代码里用net/http中间件或rate.Limiter拦截SYN Flood的做法,都属于“等炸弹进屋了才拉窗帘”。
必须用XDP或TC eBPF程序统计每IP的SYN速率
核心逻辑不在Go里写,而在C写的eBPF程序中实现:
- 在
SEC("xdp")或SEC("classifier")中解析struct iphdr和struct tcphdr,只处理tcp->syn == 1 && tcp->ack == 0的包 - 用
BPF_MAP_TYPE_PERCPU_HASH按源IP(__u32)记录最近100ms内的SYN计数,避免跨CPU锁竞争 - 调用
bpf_ktime_get_ns()维护滑动窗口,不依赖定时器重置 - 对超过阈值(如50个/秒)的IP,直接
XDP_DROP或标记后交由tc-bpf限速 - 注意:不能只看
iphdr->saddr,要结合tcp->source端口做粗粒度哈希,防端口扫描混淆
Go进程唯一能做的,是读取eBPF map里的攻击聚合结果
Go不参与实时判断,但可作为策略中枢消费统计数据:
- 定期用
bpf_map__lookup_elem()遍历syn_per_ip_map,找出Top 10异常IP - 把IP推给风控系统,触发
iptables -I INPUT -s x.x.x.x -j DROP或更新云防火墙规则 - 向Prometheus暴露
ebpf_syn_flood_attackers_total指标,驱动自动扩缩容或告警 - 别尝试在Go里
net.ListenTCP后抓SYN包——此时SYN早已被内核收走,你拿到的是已完成三次握手的conn
验证是否真被SYN Flood,别信netstat -s单点数据
netstat -s | grep "SYNs to LISTEN sockets dropped"只是结果,不是原因。真正要看的是:
- 用
cilium monitor --type trace确认SYN包是否被eBPF策略drop: Syn flood threshold exceeded - 查
/proc/sys/net/ipv4/tcp_abort_on_overflow是否为0——若为1,内核会发RST,掩盖真实丢包位置 - 对比
cat /proc/net/netstat | grep -i "SyncookiesSent"和"EmbryonicRsts",判断SYN Cookie是否已启用并生效 - 如果
ss -s显示synrecv持续>90%tcp_max_syn_backlog,说明防护已失效,需立刻切到XDP层
SO_ATTACH_REUSEPORT_CBPF也完全插不上手——那层流量,Go连影子都碰不到。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











