BGP 在独立运营的网络之间交换可达性,但互联网并不存在一张统一、权威的转发表。每台路由器都学习经过策略过滤的视图,选择路由,再尝试把可用下一跳安装进转发系统。两台路由器为同一个前缀选择不同路径,完全可能是正常情况。理解 BGP,需要把通告、选路策略和数据包转发分开,不能把它们合并成一个放之四海皆准的答案。
AS 路径同时承载历史与策略
普通 eBGP 场景中,路由器向外宣告时会在 AS 路径前加上自己的号码。接收方通常排除已经包含自己 AS 的路径,用于避免自治系统之间的环路,但存在显式配置的例外和协议扩展。自治系统内部的 iBGP 通常不再增加 AS 号码;它的转发通告限制及路由反射器规则处理的是另一类内部环路问题。
AS_PATH 还是过滤和选路的输入。重复前插可能让一条路由在看重路径长度的网络里吸引力下降,却不能推翻对方优先级更高的本地策略。也没有一条通用规则说,前插之后路由就会被过滤。必须结合真正的运营商策略、客户授权和接收条件,理解该字段在当前网络里的作用。
LOCAL_PREF 会作为属性分发给内部 BGP 对等体,通常不传给外部对等体。部分实现提供的 weight 则只属于本地路由器,也不是标准 BGP 路径属性。把两者都描述成不会进入更新报文,会掩盖关键区别:本地优先级可以影响自治系统内其他设备的决策,而 weight 的效果一般局限在一台路由器。
先比较同一个前缀
最佳路径过程比较的是同一前缀的多个候选路径。具体顺序取决于实现和配置,包括路径资格、本地策略、AS 路径长度、MED 比较范围及下一跳可达性。某个产品的 weight 优先列表并不是协议完整定义。MED 通常在来自相同邻居 AS 的路径之间比较,但实现可以提供改变这一行为的选项,不能把默认规则写成不可改变的限制。
之后,转发过程在已安装目的路由中做最长前缀匹配。一个 /25 与覆盖它的 /24,并不是通过同一套最佳路径平局规则互相竞争。只要两者均被接受并安装,前者就匹配那一半地址,即使后者的 AS 路径更短。策略路由或其他额外转发机制还需要分别检查,不能从这条普通查找规则推断全部设备行为。
路由表规模同样依赖观测点、地址族与时间。独立前缀数量、收到的全部候选路径以及硬件 FIB 表项,是不同统计口径。聚合可以减少部分通告,但多宿主和流量工程可能确实需要具体路由。仅按地址算出的可聚合数量,并不能证明相应的全部策略也能保留,因此不应把一个动态快照当作永久容量门槛。
坏掉的样子
未经授权的起源通告属于前缀劫持;路由泄漏则是把学到的可达性传播到预期策略范围之外。两者可能重叠,却不是同义词。下面假设的 /25 只展示查找效果,真实网络可能已经通过前缀长度、起源或客户过滤拒绝它。发现陌生更具体前缀值得调查,但不等于已经证明攻击正在生效。
RPKI 起源验证将通告前缀、允许的起源和最大长度,与验证过的记录进行匹配。它不认证整条 AS 路径,也不判断每一个出口关系是否合法。合法起源的路由仍可能发生泄漏。因此,需要将起源验证与适当的导入、导出策略配合,并监控变化,不能笼统声称所有更新都未经检查便向全球扩散。
健康会话也不能证明转发安装成功。硬件容量不足、下一跳无法解析,或设备编程失败,都可能使控制平面路由无法真正使用。失败后的行为取决于平台,不保证自动退回软件转发。容量规划要看设备实际分区、启用特性和安装遥测,而不是相信一个普遍适用的百万表项目标。排查时应保留相关错误和差异。
快速验证
用 Python 3 运行下面夹具,保持断言开启。前半段故意只模拟本地优先级和 AS 路径长度,其他选路条件视为相同;后半段则使用独立的转发表。代码采用文档专用地址,不创建会话、监听或网络通告,也不会接触任何真实路由器。
from ipaddress import ip_address, ip_network
paths = [
{"name": "policy-first", "localpref": 200, "path": [64501, 64502, 64503]},
{"name": "shorter", "localpref": 100, "path": [64504, 64503]},
]
def choose(candidates):
return min(candidates, key=lambda p: (-p["localpref"], len(p["path"])))
assert choose(paths)["name"] == "policy-first"
paths[1]["localpref"] = 200
assert choose(paths)["name"] == "shorter"
routes = {ip_network("198.51.100.0/24"): "legitimate",
ip_network("198.51.100.128/25"): "unexpected"}
def forward(address):
matches = [p for p in routes if ip_address(address) in p]
return routes[max(matches, key=lambda p: p.prefixlen)]
assert forward("198.51.100.20") == "legitimate"
assert forward("198.51.100.200") == "unexpected"
print("same prefix: local preference first, then path length")
print("different prefixes: lower half legitimate, upper half unexpected")
本地优先级还不相同时,较长路径获胜;将优先级调成一致后,才由较短路径获胜。另一个独立查找中,低地址命中合法 /24,高地址命中意外 /25。这些输出解释的是两个不同决策,不能宣称已经实现或者验证真实 BGP。实际诊断仍需关联接收和发出的路径、选中路由、硬件安装状态,以及获得授权的客户端探测结果。
来源
- RFC 4271 BGP-4,决策过程与 AS 路径环路检测,已核验 2026-09-16。
- RFC 6811 前缀起源校验,RPKI 校验能证明什么、不能证明什么,已核验 2026-09-16。
- RFC 7908 路由泄漏,泄漏通告的问题陈述,已核验 2026-09-16。
- CIDR Report,当前 IPv4 表规模与各 AS 的更具体前缀数量,已核验 2026-09-16。
- FRR BGP 路径选择,实现特定的选路控制与诊断,已核验 2026-10-15。