如何在香港服务器运行 Debian 时,用 FRR 配 BGP 路由策略,把跨境网络“稳”下来

半夜 2 点,我蹲在 42U 机柜前,盯着那台刚上架的香港节点——HK-EDGE-03。白天投诉的跨境丢包还在,我的微信监控群里,用户时不时冒出一句“又卡了”。那一刻我下了决心:把 BGP 策略重新梳理,用 FRR 把路选稳,把跨境这口气接顺。下面是一整晚到清晨的实操记录,也是后来多次复用的标准落地方案。
1. 目标与约束(说清楚我们要“稳”什么)
目标
- 香港边缘节点通过 两家上游(Upstream-A / Upstream-B) 出口,稳定承载跨境(CN ↔ HK ↔ Global)业务。
- 基于 BGP 路由策略(local-pref、AS-PATH prepend、MED、Community、RPKI、BFD、ECMP 等)实现 首选线路、自动降级 和 快速收敛。
- 解决跨境链路常见的 MTU/PMTUD、对称性、路由泄露、会话抖动 等问题。
约束
- 系统使用 Debian 12(bookworm),路由栈采用 FRRouting(FRR)。
- 单机双口/四口 10G,和上游通过 eBGP 邻接。
- 需要兼顾 新手可复制 与 老手可扩展:把“能跑通”与“跑稳、跑好”一次讲透。
2. 现场拓扑与硬件清单(真实货)
2.1 逻辑拓扑(简化)
拓扑:
[用户/分支/IDC]
|
(公网/专线)
|
┌─────────────────┐
│ HK-EDGE-03 │ Debian + FRR
│ AS 64512 │
│ 203.0.113.2 │ loopback(router-id)
└───┬───────────┬─┘
| |
eBGP #1| |eBGP #2
192.0.2.2 | | 198.51.100.2
AS64501 AS64502
Upstream-A Upstream-B
(跨境优) (全球覆盖更广)
2.2 硬件/链路参数(现场登记表)
| 项 | 型号/参数 | 说明 |
|---|---|---|
| 机型 | 1U 定制 | 前置双 NVMe,双电热插 |
| CPU | Intel Xeon Silver 4310 ×1 | 12C/24T |
| 内存 | 64GB ECC | FRR 占用不高,但留够缓存 |
| 系统盘 | 960GB NVMe | FRR 配置与日志 |
| 网卡 | Intel X710 10G ×2(bond 可选) | 与两家上游直连 |
| 上游 A | AS64501(标注:跨境质量更优) | 物理 10G,延迟/丢包佳 |
| 上游 B | AS64502(标注:全球 reach 更强) | 物理 10G,带宽余量大 |
| 内网 | VXLAN/传统三层 | 视现网而定 |
| 路由 ID | 203.0.113.2 | TEST-NET 样例地址 |
3. 系统与网络前置准备(把坑先填一半)
目的:让 FRR 与内核网络栈处于“可用于承载 BGP 的稳态”。
3.1 Debian 基础与时间同步
apt update && apt -y upgrade
apt -y install chrony ethtool tcpdump mtr iperf3 jq
systemctl enable --now chrony
生产上 NTP/Chrony 必开,BFD/RPKI 超时与 BGP 退避都跟时钟相关。
3.2 网卡与内核参数(减少非必要不稳定因素)
# 关闭会“抖”的 offload(按需,不是一刀切;X710 一般稳)
ethtool -K eth0 gso off tso off gro off
ethtool -K eth1 gso off tso off gro off
# 避免不对称路由被反射拒绝
cat >/etc/sysctl.d/99-edge.conf <<'EOF'
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
# PMTUD/跨境链路 MTU 不一致时的自适应
net.ipv4.tcp_mtu_probing = 1
# 降低 ICMP 重定向/源路由等风险
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# 提高邻居表与路由容量
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
EOF
sysctl --system
经验:跨境经常 MTU 不一致(GRE、IPSec、第三方网关),tcp_mtu_probing=1 和 MSS Clamp 能救急。
MSS Clamp(iptables 版):
apt -y install iptables-persistent
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
netfilter-persistent save
3.3 安装 FRR
Debian 12 的自带版本常够用;追新可加 FRR 官方仓库。以下演示通用装法:
apt -y install frr frr-pythontools
sed -i 's/bgpd=no/bgpd=yes/' /etc/frr/daemons
sed -i 's/bfdd=no/bfdd=yes/' /etc/frr/daemons
systemctl enable --now frr
4. 策略先行:BGP 设计蓝图
4.1 我们希望路由长这样
入站(学到的路):
- 来自 Upstream-A 的前缀 → local-pref=200(更优先)
- 来自 Upstream-B 的前缀 → local-pref=150
- 对短时抖动做 轻量 damping(避免打死)
- RPKI 验证 拒绝 invalid,记录未知/unknown
出站(我们通告的路):
- 对 Upstream-A:不做 AS-PATH prepend(作为首选出口)
- 对 Upstream-B:prepend 两次,并可设置较高 MED(作为备选/次优)
- 支持 Blackhole 社区 与 地理偏好(上游是否支持以合同为准)
会话层:
- BFD 加速失效检测(200ms×3 探测)
- Graceful Restart 与 GTSM(TTL Security)
- Maximum-Prefix 防路由泄露
ECMP 打开,但开启 multipath-relax,在路径相近时并行分担
4.2 社区与优先策略对照表(示例)
| 名称 | 社区/属性 | 用途 |
|---|---|---|
| 优先走 A | local-pref=200(入站) |
偏爱 A 的来路 |
| 次优走 B | local-pref=150(入站) |
A 不可用时切 B |
| 出站对 B 降优 | as-path prepend 2次(出站) |
让外界更倾向选 A |
| 地区引流 | 64512:100/200(出站) |
让上游在特定区域优选/降级(需上游支持) |
| 黑洞 | 65535:666(出站) |
DDoS 黑洞(需上游启用) |
5. FRR 基础配置(从 0 到能起 BGP)
我习惯用 集成配置(/etc/frr/frr.conf)+ vtysh。以下配置以 IPv4 单播 为主,IPv6 同理。
vtysh
configure terminal
!
frr defaults traditional
service integrated-vtysh-config
!
hostname HK-EDGE-03
username netop nopassword
!
log syslog informational
!
ip prefix-list PFX-ORIGIN seq 5 permit 203.0.113.0/24 le 24
!
# ---------- 入站策略 ----------
route-map IN-A permit 10
set local-preference 200
set weight 50
!
route-map IN-B permit 10
set local-preference 150
set weight 10
!
# ---------- 出站策略 ----------
route-map OUT-A permit 10
match ip address prefix-list PFX-ORIGIN
set community 64512:100 additive
# 对 A 不做 prepend,保持“更好看”的 AS-PATH
!
route-map OUT-B permit 10
match ip address prefix-list PFX-ORIGIN
set community 64512:200 additive
set as-path prepend 64512 64512
set metric 50
!
# ---------- 轻量抑制(可选) ----------
bgp dampening half-life 15 reuse 750 suppress 2000 max-suppress-time 45
!
router bgp 64512
bgp router-id 203.0.113.2
bgp bestpath as-path multipath-relax
maximum-paths 2
bgp graceful-restart
timers bgp 10 30
no bgp default ipv4-unicast
!
neighbor 192.0.2.1 remote-as 64501
neighbor 192.0.2.1 description Upstream-A
neighbor 192.0.2.1 timers 5 15
neighbor 192.0.2.1 bfd
neighbor 192.0.2.1 ttl-security hops 2
!
neighbor 198.51.100.1 remote-as 64502
neighbor 198.51.100.1 description Upstream-B
neighbor 198.51.100.1 timers 5 15
neighbor 198.51.100.1 bfd
neighbor 198.51.100.1 ttl-security hops 2
!
address-family ipv4 unicast
network 203.0.113.0/24
neighbor 192.0.2.1 activate
neighbor 192.0.2.1 route-map IN-A in
neighbor 192.0.2.1 route-map OUT-A out
neighbor 192.0.2.1 maximum-prefix 200000 90 restart 5
neighbor 198.51.100.1 activate
neighbor 198.51.100.1 route-map IN-B in
neighbor 198.51.100.1 route-map OUT-B out
neighbor 198.51.100.1 maximum-prefix 200000 90 restart 5
exit-address-family
!
# ---------- BFD ----------
bfd
peer 192.0.2.1
detect-multiplier 3
required-min-rx 200
desired-min-tx 200
!
peer 198.51.100.1
detect-multiplier 3
required-min-rx 200
desired-min-tx 200
!
end
write memory
解释要点
- 入站用 local-pref/weight 影响我们“学到的”路由优先级;出站再用 AS-PATH prepend/MED/Community 影响“别人如何走向我们”。
- maximum-prefix 是防误操作的保险丝。
- multipath-relax + maximum-paths 2:当两条 eBGP 路的 AS-PATH 代价相近时并行转发,减震。
- bfd:百毫秒级失效检测,比纯 BGP Keepalive 快。
6. RPKI 验证(防“脏路由”)
生产建议部署本地 RTR Cache(如 Routinator、rpki-client)后让 FRR 进行实时验证。下面给出常见写法(注意按你的 cache 服务实际 IP/端口调整)。
configure terminal
router bgp 64512
bgp rpki server tcp 127.0.0.1 3323
bgp rpki retry 60
bgp rpki timeout 600
bgp rpki cache-time 900
bgp rpki allow-invalid off
end
write memory
验证:
vtysh -c "show bgp rpki"
vtysh -c "show bgp ipv4 uni 203.0.113.0/24 json" | jq .
经验:把 allow-invalid off 打开,invalid 的路 不要学,unknown 记录并持续观察(有些小网段还没 ROA)。
7. 跨境稳定性“必修课”
- GTSM(TTL Security):上面已启用 ttl-security hops 2,减少会话被远端伪造探测的风险。
- Graceful Restart:路由器/进程短时重启时,转发表可暂存,不至于黑一片。
- BFD:强烈推荐 对跨境 eBGP 邻居打开。
- 对称性:rp_filter=0 + 合理的 入站 local-pref 与 出站 prepend,尽可能让去来一致,至少业务关键段一致。
- MTU/MSS:tcp_mtu_probing + MSS Clamp,大多数“海外看视频时不时卡一下”的玄学问题都能被这俩解决一半。
- 黑洞社区:当单点遭受 DDoS,先导向上游黑洞,恢复后再解除,避免牵连整体。
- 最大前缀:防止内部路由泄露到上游(你不想凌晨背锅)。
8. 监控与自愈(“看得见”才算稳)
8.1 快速观测命令
vtysh -c "show ip bgp summary"
vtysh -c "show ip bgp neighbors 192.0.2.1"
vtysh -c "show ip route 203.0.113.0/24"
vtysh -c "show bfd peers"
8.2 指标采集(Telegraf exec 简单抓)
/etc/telegraf/telegraf.d/frr.conf:
[[inputs.exec]]
commands = ["vtysh -c 'show ip bgp summary json'"]
data_format = "json"
name_override = "frr_bgp"
interval = "10s"
可在监控面板里做以下 SLO 看板:
| 指标 | 期望 | 告警线 |
|---|---|---|
| eBGP 邻居会话数 | 2 | <2 |
| BFD 状态 | Up | 非 Up |
| 路由收敛耗时 | < 1s(BFD 触发) | > 3s |
| 丢包(mtr 到关键地域) | < 0.5% | > 2% |
| RTT 95 分位(CN 节点) | < 40ms(HK↔南方) | > 80ms |
9. 验证与对比(把“稳”量化)
我在现场用了 iperf3 + mtr 做前后对比,摘录关键数据如下(样例):
| 场景 | 调整前 | 调整后 |
|---|---|---|
| CN ↔ HK(高峰 RTT) | 54ms / 抖动 12ms | 39ms / 抖动 5ms |
| CN ↔ HK 丢包(10 分钟) | 1.8% | 0.3% |
| BGP 收敛(上游 A 短断 1s) | 3.5s | <1s(BFD 触发) |
| 出口对称性(会话采样) | 62% | 91% |
10. 常见坑与现场解法(都是泪)
邻居起不来
ttl-security 开了但跳数不对 → 与上游确认直连还是跨交换设备,合理设置 hops。
ACL/防火墙挡住 179/TCP 或 BFD → 机房边界检查 mangle/filter 表。
学到奇怪的“全球全表”,路爆了
你本来只想默认路,但上游给了全表 → maximum-prefix 触发 + 沟通只要 default-originate。
或者加 route-map 限制入站前缀数量/长度。
跨境特定 APP 卡顿
大多是 PMTUD 被墙/丢弃:开启 MSS Clamp、tcp_mtu_probing。
也可能是 回程绕路:分析 traceroute -T 与流日志,调整 出站 prepend 或跟上游协商 社区策略。
RPKI 配好后业务断
部分自有/合作前缀没有及时注册 ROA → unknown 先不拦,invalid 才拦,并在变更窗口逐步收紧。
ECMP 开了但没生效
需要 bgp bestpath as-path multipath-relax + 两路代价接近;还要注意内核 fib_multipath_hash_policy(Debian 默认 flow 哈希基本够用)。
11. 变更与回滚(要写在手边的小纸条)
上线顺序:
先 IN 策略(不影响外界) → 2) 开 BFD → 3) 开 RPKI(allow-invalid on,观察) → 4) 开 OUT 策略(小流量时段) → 5) 逐步收紧 RPKI。
回滚最小化:
- 只对 OUT 做了 prepend/社区?先 no neighbor X route-map OUT-* out。
- 入站 local-pref 导致异常?no route-map IN-* in 先回默认。
- BFD 误报?no neighbor X bfd 暂时关掉,用 BGP keepalive 顶住。
12. 附:一份最小可用清单(Checklist)
- Debian 升级、时间同步 OK
- rp_filter=0、tcp_mtu_probing=1、MSS Clamp 就位
- FRR 安装,bgpd、bfdd 已启用
- eBGP 邻居建立,show ip bgp summary 为 Establ
- 入站 local-pref:A=200、B=150
- 出站 prepend:B 两次,A 不加
- BFD Up,收敛 < 1s
- RPKI 连接正常,invalid 已拒
- ECMP 生效,关键流量对称
- 监控面板、告警规则上线
天色亮起来时,机房的玻璃已经有了微微的灰。show ip bgp summary 里两个邻居都稳稳地 Estab,BFD peer 一片绿色。我刷了眼监控,CN→HK 的 95 分位 RTT 比昨晚好了近 20ms。
台风天、节假日、直播秒杀……这些日子我都见过。跨境网络从来不是“配一次就万无一失”,而是用 正确的策略 和 适当的冗余,在不确定里找确定。
如果你也在香港的机房里熬过一个夜班,希望这篇手记能帮你少踩几个坑。我们不追玄学,只追“可复现的稳定”