XDP 与 eBPF 包过滤
Arc 的内核程序(arc-xdp)挂载在网卡 XDP hook 点,在内核 TCP 栈处理之前就能拦截每个入站包。整个处理流程都在内核态完成,不需要每包切回用户态。
检查流程
每个包都会经过以下步骤:- 解析以太网头和可选 VLAN 头
- 解析 IPv4/IPv6 并提取源 IP
- 查 白名单:命中即
XDP_PASS - 查 黑名单:命中且未过期即
XDP_DROP - TCP 包继续做:
- SYN flood 评分(按 IP 指数衰减)
- SYN proxy(返回 syncookie SYN-ACK,并校验 ACK)
- RST 校验(序列号窗口)
- ACK flood 评分
- UDP 包做按端口 PPS/BPS 限速
BPF Map
所有 map 默认 pin 到
/sys/fs/bpf/arc/。
功能开关
通过 control plane 的POST /v1/xdp/config 在运行时开关 XDP 功能:
动态阈值计算
用户态管理器每 100ms 运行一次后台任务,用 Welford 在线算法计算 SYN 速率的均值和标准差,动态阈值计算公式为:黑白名单管理
可通过 网关控制面 API 参考 在运行时管理 XDP 黑白名单:Kubernetes 说明
XDP 需要NET_ADMIN、SYS_ADMIN 和 privileged: true。多数托管 Kubernetes 平台不支持这组能力。部署清单中仅以注释形式保留示例。
速率限制
Arc 内置两套独立限流机制。路由级限流(GCRA)
最常用的是直接在路由上配置:HashMap,不会产生跨线程协调。
两级全局限流
跨节点统一限流由GlobalRateLimiter 实现两级架构:
L1(worker 本地): 每个 worker 维护按 key 的令牌桶 HashMap,热路径无锁,try_acquire 每请求内联执行。L2(Redis 后端): 独立后端线程通过 Lua 脚本访问 Redis,做集群级令牌一致性。
熔断器: Redis 不可达时自动 open,worker 退化为 L1-only,默认 open 窗口 500ms。 worker 热路径:
- 从后端最多拉取 8 条待处理补令牌结果
- 在本地
l1HashMap查找或创建 key 对应Entry - 后端健康且全局令牌足够时消费 1 个全局令牌
- 后端健康但全局令牌耗尽时返回 429
- 后端故障时使用本地 L1 令牌桶
- 当令牌低于低水位时异步发起补充请求
L7 防护
在正式进入限流前,Arc 会对每条连接执行三类 L7 防护。SlowlorisGuard
用于识别 Slowloris 攻击(极慢发送请求头,占满连接资源)。TlsFloodGuard
按 IP 限制每秒 TLS 握手速率。状态存储在固定大小AtomicU64 数组中,每个槽编码 (second << 32) | count。当当前秒计数超过 max_handshakes_per_ip_per_sec 时拒绝连接。
H2StreamFloodGuard
面向 HTTP/2 的 per-connection 防护,用于处理 stream flood 和 RST flood。
计数窗口按秒重置,实际
GOAWAY 发送由 worker 负责。
请求超时
Arc 以纳秒精度跟踪请求 deadline,不额外分配计时器对象。每个请求都会应用四类边界:
每个阶段会同时受“阶段超时、单次尝试超时、总超时”三重约束,避免局部超时突破整体预算。
示例:
故障排查
XDP 加载失败(XDP attach failed)
XDP 加载失败(XDP attach failed)
XDP 依赖网卡驱动支持。可先用
ip link show <iface> 检查。系统会按 native → generic → skb 兜底尝试;全部失败时网关会在无 XDP 模式继续启动并记录告警。可通过 GET /v1/xdp/status 确认状态。误封 IP 变多
误封 IP 变多
先查看黑名单:
curl http://localhost:22100/v1/xdp/blacklist。流量突刺下动态阈值可能误判,可用 DELETE /v1/xdp/blacklist 解封,并通过 POST /v1/xdp/config 提高 sigma_multiplier(如 {"sigma_multiplier": 5.0})来放宽阈值。配合 /metrics 中 arc_xdp_blacklisted_total 一起观察。限流看起来没生效
限流看起来没生效
先确认
control_plane.enabled: true,且 observability.metrics_bind 可访问。路由级限流只依赖本地 GCRA,不需要 Redis。集群级限流需要 Redis 可达且编译了 redis feature。可查看 arc_ratelimit_rejected_total 判断限流是否真的触发。SlowlorisGuard 误伤慢客户端
SlowlorisGuard 误伤慢客户端
该防护会对“请求头长期不完整”的连接触发。可以适当提高相关阈值,或在内网监听器不启用这类 L7 防护。
两级限流熔断器处于 open 状态
两级限流熔断器处于 open 状态
当
/metrics 中 arc_ratelimit_circuit_open 为 1,表示 Redis 后端不可达,Arc 已自动退化为 L1(每 worker)限流。请检查 Redis 连通性,并通过 control plane 查看熔断器的 open_until_ns。
