1. 为什么BGP属性值得单独拉出来做验证
刚接触BGP的时候,很多人会把注意力全放在邻居建立、路由通告这些"看得见"的环节上,觉得邻居起来了、路由学到了,事情就结束了。但真正在现网里待过一段时间就会发现,邻居起来只是万里长征第一步,路由选路对不对、流量走向符不符合预期、故障切换快不快,这些才是决定网络质量的关键。而决定这些行为的,恰恰是BGP那一堆看起来枯燥的属性。
BGP属性验证分析这件事,说白了就是:把每条属性的行为逻辑,从"书本上写的"变成"我在实验环境里亲眼看到的"。因为BGP的选路规则虽然有一套标准顺序,但不同厂商、不同版本、不同配置组合下,实际表现可能和你想的不一样。比如Local Preference和MED,一个影响出方向一个影响入方向,方向搞反了整条路径就全错了;再比如AS Path的预处理机制,很多人不知道它在选路之前会先做一轮"筛选",导致后面比较的时候结果和预期对不上。
这篇内容适合谁看?如果你正在准备网络方向的认证考试,或者刚接手一个多出口的BGP网络,又或者你已经在运维BGP但总觉得选路"玄学",那这篇东西应该能帮你把很多模糊的地方理清楚。我会按照"先搭环境、再逐条验证、最后做故障模拟"的思路,把每条属性的验证方法、观察要点、常见坑都过一遍。整套实验用模拟器就能完成,不需要真实设备,成本几乎为零。
需要提前说明的是,BGP属性验证不是把命令敲一遍看输出就完事了,关键在于你要能解释"为什么是这个结果"。所以每一组验证我都会先讲清楚这条属性的作用机制,再设计对应的拓扑和配置,最后分析输出结果。这样你做完一遍,脑子里留下的不是零散的命令,而是一套完整的判断逻辑。
2. 实验环境搭建与拓扑设计思路
2.1 拓扑结构的选择与理由
做BGP属性验证,拓扑不能太简单也不能太复杂。太简单了(比如就两台路由器直连)很多属性根本体现不出差异;太复杂了又容易干扰观察,出了问题不好定位。我一般推荐用四到五台路由器组成一个"双出口+双AS"的结构,这样既能体现多路径选路,又能验证各种属性的传递和影响。
具体来说,我设计的拓扑是这样的:中间一个核心AS(假设AS 100),它有两个出口分别连到两个不同的上游AS(AS 200和AS 300)。核心AS内部有两台边界路由器,分别对接两个上游。另外再挂一台内部路由器用来观察iBGP的行为。这样一共五台设备,用模拟器跑起来资源占用也不大。
为什么选这个结构?因为BGP属性验证的核心场景就是"多条路径选一条",而这个拓扑天然提供了至少两条到达同一目的网段的路径。你可以通过调整属性值,观察选路结果如何变化。同时,两个上游AS的存在让你可以验证AS Path长度、MED传递、Community传递等跨AS的行为。
提示:模拟器选择上,EVE-NG或者GNS3都可以,镜像用常见的路由器镜像就行。如果资源紧张,用容器化的网络模拟方案也能跑,但要注意某些高级属性在简化镜像上可能支持不全。
2.2 基础配置与邻居建立
环境搭好之后,第一步是把IGP跑起来(核心AS内部用OSPF或者IS-IS都行),确保内部互通。然后配置iBGP全互联或者用路由反射器,再配置eBGP邻居。这里有个细节:iBGP邻居建议用Loopback地址建立,eBGP用物理接口地址,这样更贴近真实网络的做法。
基础配置里最容易出问题的地方是Router ID的规划。如果Router ID重复,BGP邻居可能起不来,或者起来了但行为异常。我一般习惯把Router ID和Loopback地址保持一致,规划的时候就把每台设备的Loopback地址定好,比如10.0.0.1到10.0.0.5这样。
邻居建立之后,先别急着配属性,先用show ip bgp summary确认所有邻居都是Established状态,再用show ip bgp看一下路由表里有没有预期的路由。如果路由没学到,先排查网络层可达性和BGP配置,别在属性上浪费时间。
2.3 验证前的基线记录
这一步很多人会跳过,但我强烈建议做。在调整任何属性之前,先把当前的选路结果记录下来:哪条路径被选中了,为什么被选中(用show ip bgp <prefix>看详细的属性对比)。这个基线就是你后续所有对比的参照物。
记录的内容包括:每条路径的Next Hop、AS Path、Local Preference、MED、Origin、Weight(如果用了的话),以及最终哪条被标记为best。把这些信息整理成一张表,后面每调整一个属性,就更新这张表,这样你能非常清晰地看到每条属性对选路的影响。
3. 核心属性逐条验证与结果分析
3.1 Weight属性的验证与观察
Weight是BGP选路规则里优先级最高的属性之一(在Cisco体系里),但它有个重要特点:只在本路由器有效,不传递。这意味着你在一台路由器上设了Weight,它只影响这台路由器自己的选路决策,不会告诉邻居。
验证方法很简单:在核心AS的一台边界路由器上,针对某个目的网段,给两条路径分别设置不同的Weight值。比如路径A设Weight 200,路径B设Weight 100,然后观察选路结果。预期是路径A被选中,因为Weight高的优先。
但这里有个容易踩的坑:Weight的默认值是0,如果你只给一条路径设了非零值,另一条保持默认0,那结果是很明确的。但如果你给两条都设了值,就要注意数值大小关系。另外,Weight是本地有效的,所以你在R1上设了Weight,R2的选路不会受影响。验证的时候一定要在设了Weight的那台设备上看结果,别跑到别的设备上去看,否则会以为配置没生效。
我实际验证时还发现一个细节:当你用route-map来设置Weight时,route-map的匹配条件如果写得不严谨,可能会匹配到不该匹配的路由。比如你用ACL匹配网段,ACL写错了通配符掩码,结果把默认路由也匹配进去了,Weight就设到了错误的路由上。所以每次设完Weight,都要用show ip bgp <prefix>确认一下到底哪条路由的Weight被改了。
3.2 Local Preference的验证与方向性
Local Preference(本地优先级)是iBGP之间传递的属性,用来告诉AS内部的其它路由器"从哪个出口出去更好"。它的默认值是100,数值越大越优先。和Weight不同,Local Preference会在整个AS内部传递,所以你在边界路由器上设了之后,内部路由器也会跟着改变选路。
验证Local Preference的时候,关键是要理解它的方向性:它影响的是出方向的流量。也就是说,你在AS 100的边界路由器上设Local Preference,决定的是AS 100内部的流量从哪个出口离开AS 100。很多人会把它和MED搞混,MED影响的是入方向,这个后面会详细说。
实验设计上,我在两台边界路由器上分别针对同一目的网段设置不同的Local Preference。比如R1上设150,R2上设200,然后在内部路由器上看选路结果。预期是内部路由器会选择R2作为出口,因为R2通告的Local Preference更高。
这里有个值得注意的现象:Local Preference只在iBGP邻居之间传递,eBGP邻居收到的Local Preference会被重置为默认值。所以如果你的AS内部有多台路由器,Local Preference的设置点应该在边界路由器上,通过iBGP传递给内部路由器。如果你在内部路由器上设Local Preference,它不会影响边界路由器的选路,因为iBGP是单向传递的(从边界到内部)。
注意:不同厂商对Local Preference的默认值可能不同,有的默认100,有的默认空。做实验前先确认一下设备的默认行为,否则对比的时候基准不一致。
3.3 MED属性的验证与入方向影响
MED(Multi-Exit Discriminator)是eBGP之间传递的属性,用来影响入方向的流量。它的逻辑是:当一个AS有多个入口点时,通过MED告诉上游AS"从哪个入口进来更好"。MED值越小越优先,这点和Local Preference正好相反。
验证MED的时候,拓扑设计要稍微调整一下。你需要让两个上游AS都能到达同一个目的网段,然后在本AS的边界路由器上设置不同的MED值,观察上游AS的选路变化。比如AS 100通过R1和R2分别向AS 200通告网段时,R1设MED 50,R2设MED 100,那么AS 200应该优先从R1进入AS 100。
MED验证里最容易出错的地方是比较条件。MED只有在两条路径来自同一个相邻AS时才会被比较。如果两条路径来自不同的AS,MED默认不参与比较(除非配置了bgp always-compare-med)。这个细节非常关键,很多人在实验里发现MED设了没生效,就是因为两条路径来自不同AS,MED根本没被拿来比较。
另外,MED的传递范围也有限制。默认情况下,MED只传递给直连的eBGP邻居,不会再往下传。如果你想让MED传递更远,需要配置bgp deterministic-med或者相关的传播策略。我在验证时一般会先确认MED是否被正确接收,用show ip bgp <prefix>看MED字段的值,确认收到了再分析选路结果。
3.4 AS Path的验证与预处理机制
AS Path是BGP选路里最直观的属性之一:路径越短越优先。但它的行为比表面上看起来复杂,因为BGP在比较AS Path之前会先做一轮预处理。
预处理的核心逻辑是:BGP会把所有路径的AS Path拿出来,去掉重复的AS号(防止环路),然后按长度排序。但这里有个细节:如果两条路径的AS Path长度相同,但AS号序列不同,BGP会比较AS号的数值大小,数值小的优先。这个规则在实际中很少触发,但在实验里可以刻意构造出来验证。
验证AS Path最直接的方法就是做AS Path Prepending:在一条路径上重复添加自己的AS号,人为加长AS Path,然后观察选路是否切换到另一条路径。比如在R1上对某个网段做prepend,加上三个自己的AS号,那么AS Path长度从1变成4,另一条路径长度还是1,选路自然就切过去了。
但要注意,AS Path Prepending只影响入方向的选路,因为它是通告给上游AS的。你在本AS内部做prepend,影响的是上游AS怎么选路进来,不影响本AS内部的出方向选路。这个方向性问题和MED类似,验证的时候要想清楚你观察的是哪个方向的流量。
还有一个容易忽略的点:iBGP内部传递路由时,AS Path不会改变(因为iBGP不添加AS号)。所以你在边界路由器上看到的AS Path,和内部路由器上看到的是一样的。但eBGP就不一样了,每经过一个AS,AS Path就会加上那个AS的号。验证的时候要区分清楚你是在iBGP还是eBGP上观察。
3.5 Origin属性的验证与优先级
Origin属性表示路由的来源,有三种类型:IGP(用i表示)、EGP(用e表示)、Incomplete(用?表示)。优先级顺序是IGP > EGP > Incomplete。这个属性在实际网络中很少被用来做选路决策,因为大多数路由都是IGP类型的,大家起点一样。
但验证Origin还是有意义的,因为它能帮你理解BGP选路的完整顺序。你可以通过route-map把某条路由的Origin改成Incomplete,然后观察选路是否切换到Origin为IGP的路径。实验里这个切换是很明显的,因为Origin的优先级差异直接决定了选路结果。
需要注意的是,Origin属性在传递过程中一般不会改变,除非中间有设备用route-map修改了它。所以你在源头设了Origin,下游收到的就是什么。验证的时候在源头设好,然后在下游用show ip bgp <prefix>看Origin字段确认。
3.6 Community属性的验证与传递控制
Community严格来说不是选路属性,而是一个"标签"属性,用来给路由打标记,然后基于标记做策略。但它在BGP属性验证里非常重要,因为很多高级选路策略都是靠Community来实现的。
Community的验证重点是传递性。标准Community是32位,格式是AS号:数值。它默认会传递给eBGP邻居,但不会自动传递给iBGP邻居(除非配置了send-community)。这个细节很容易踩坑:你在边界路由器上给路由打了Community,结果内部路由器收不到,策略就没法基于Community来做。
验证方法:在R1上给某条路由设置Community 100:100,然后在R2(eBGP邻居)和R3(iBGP邻居)上分别用show ip bgp <prefix>看Community字段。预期是R2能看到,R3默认看不到(需要额外配置)。这个对比实验能让你非常清楚地记住Community的传递规则。
另外,Community还可以用来做路由过滤和属性修改。比如你可以匹配Community 100:100的路由,然后统一设置Local Preference或者MED。这种"打标签+基于标签做策略"的模式在实际网络中非常常见,验证的时候可以顺便把这个流程走一遍。
4. 属性组合场景与选路顺序验证
4.1 多条属性同时作用时的优先级
单独验证每条属性之后,下一步是把多条属性放在一起,验证BGP的选路顺序。BGP的选路顺序是固定的:Weight > Local Preference > 本地起源 > AS Path长度 > Origin > MED > eBGP优于iBGP > IGP度量 > Router ID。这个顺序必须记牢,因为实际网络中多条路径往往在多个属性上都有差异,最终选哪条取决于优先级最高的那个差异点。
我设计了一个组合验证场景:两条路径在Weight、Local Preference、AS Path长度上都有差异。比如路径A的Weight更高但AS Path更长,路径B的Local Preference更高但Weight更低。按照选路顺序,Weight优先级最高,所以路径A应该被选中,即使它的AS Path更长。
这个验证的价值在于:它能帮你确认自己对选路顺序的理解是否正确。很多人背了顺序但没实际验证过,遇到真实场景时就会犹豫。做一遍组合验证,看到结果和预期一致,心里就有底了。
4.2 属性冲突时的排查思路
属性冲突是实际运维中最头疼的情况:你设了Local Preference想让流量走A路径,结果流量还是走B路径。这时候排查思路应该是从高优先级属性往低优先级属性逐条检查。
首先看Weight,确认两条路径的Weight值。如果Weight有差异,那选路结果就是Weight决定的,你设的Local Preference根本没机会参与比较。然后看Local Preference,确认值是否正确设置和传递。接着看AS Path长度,确认有没有意外的prepend。最后看MED和Origin。
我踩过的一个坑是:在边界路由器上设了Local Preference,但忘了确认iBGP邻居有没有收到。结果内部路由器上的Local Preference还是默认值,选路自然没变。后来用show ip bgp <prefix>在内部路由器上一看,Local Preference字段根本没变,才发现是iBGP传递的问题。
提示:排查属性冲突时,养成"从高到低逐条确认"的习惯,不要跳着看。BGP选路是严格按顺序来的,高优先级属性一旦有差异,低优先级属性就不会被比较。
4.3 属性验证中的常见误区
第一个误区是方向搞反。Local Preference影响出方向,MED影响入方向,AS Path Prepending影响入方向。很多人设了属性发现没效果,就是因为方向搞反了。验证的时候一定要想清楚:你观察的是哪个方向的流量,这个属性影响的是哪个方向。
第二个误区是传递范围没搞清楚。Weight不传递,Local Preference只在iBGP内传递,MED只在直连eBGP之间比较,Community需要显式配置才传给iBGP。这些传递规则如果不清楚,实验做出来全是"意外结果"。
第三个误区是默认值不一致。不同厂商、不同版本的默认值可能不同。比如Local Preference有的默认100有的默认空,MED有的默认0有的默认空。做实验前先用show ip bgp <prefix>确认一下默认值,否则对比基准就是错的。
第四个误区是忽略了预处理。BGP在选路之前会做一轮预处理,包括AS Path去重、MED的确定性比较等。这些预处理会改变属性的实际值,导致你看到的选路结果和"理论值"对不上。验证的时候要意识到预处理的存在,必要时用调试命令看预处理后的结果。
5. 故障模拟与属性相关的排查实录
5.1 邻居震荡对属性传递的影响
BGP邻居震荡是实际网络中最常见的故障之一。邻居一断,通过它学到的路由全部撤销,属性自然也就没了。但这里有个细节:如果邻居反复震荡(flapping),BGP会启用阻尼机制(dampening),对反复震荡的路由进行惩罚,惩罚值超过阈值后路由会被抑制,即使邻居恢复了路由也不会立即生效。
验证这个场景的方法是:手动关闭再开启eBGP邻居,观察路由的撤销和恢复过程。然后用show ip bgp dampening看惩罚值的变化。如果配置了dampening,你会看到惩罚值累积、路由被抑制、然后逐渐恢复的过程。这个验证能帮你理解为什么有时候邻居恢复了但路由迟迟不回来。
5.2 属性配置错误导致的选路异常
属性配置错误导致的选路异常有很多种,我挑几个典型的来说。
第一种是route-map匹配错误。比如你想匹配某个网段设Local Preference,结果ACL写错了,匹配到了所有路由,导致所有路由的Local Preference都被改了。这种错误的影响面很大,排查的时候要用show route-map看匹配计数,确认到底匹配了多少条路由。
第二种是Community设置错误。比如你想设100:100,结果设成了100:1,下游基于Community的策略就匹配不上了。这种错误比较隐蔽,因为路由本身是通的,只是策略没生效。排查的时候要在上下游都看Community字段,确认值是否一致。
第三种是AS Path Prepending做错了方向。比如你想让入方向流量走A路径,结果在A路径上做了prepend,反而把流量推到了B路径。这种错误源于对方向的理解不清,排查的时候要重新确认属性的作用方向。
5.3 属性验证速查表
| 属性 | 作用方向 | 传递范围 | 优先级 | 常见坑 |
|---|---|---|---|---|
| Weight | 本地 | 不传递 | 最高 | 只在本地有效,别在别的设备上看结果 |
| Local Preference | 出方向 | iBGP内传递 | 高 | eBGP收到的会被重置,设置点应在边界 |
| AS Path | 入方向 | eBGP逐跳传递 | 中 | Prepending只影响入方向,iBGP内不变 |
| Origin | 入方向 | 一般不变 | 中低 | 实际网络中很少用来选路 |
| MED | 入方向 | 直连eBGP间比较 | 低 | 不同AS来的路径默认不比较MED |
| Community | 标签 | 需显式配置传递 | 不参与选路 | 默认不传给iBGP,容易漏配 |
这张表建议在做实验的时候放在旁边,每验证一条属性就对照一下,确认自己的观察结果和表格里的规则一致。如果发现不一致,要么是配置有问题,要么是遇到了特殊情况(比如预处理机制),需要进一步排查。
6. 验证完成后的经验沉淀
整套验证做下来,我最大的体会是:BGP属性这东西,光看文档是记不住的,必须亲手做一遍,看到选路结果随着属性变化而切换,才能真正理解。而且做一遍还不够,最好把每条属性单独做一遍,再做一遍组合场景,最后做一遍故障模拟,这样三轮下来,脑子里就有一套完整的判断逻辑了。
另外一个建议是:做实验的时候一定要做记录。每条属性的验证过程、配置命令、观察结果、遇到的问题和解决方法,都记下来。这些记录在你以后排查真实网络问题的时候,就是最好的参考。我自己的习惯是用一个表格,左边是属性名,右边是验证结论和注意事项,积累多了之后就是一份非常实用的速查手册。
最后分享一个小技巧:如果你在实验里发现某条属性的行为和文档描述不一致,先别急着怀疑文档,先检查自己的配置和观察方法。大多数"不一致"都是因为配置细节没注意到,比如默认值不同、传递范围没搞清、方向搞反了。把这些细节都排除之后,如果还是不一致,那可能是厂商实现差异,这时候再去查厂商的文档或者做更细致的对比实验。