1. 实验背景与整体设计思路
BGP属性是路由策略的灵魂,也是HCIA/HCIP考试里最容易让人头大的部分。很多同行在学BGP的时候,路径属性背得滚瓜烂熟,一到真机或者模拟器上做策略,就分不清哪个属性该在什么方向改、改了之后会不会被邻居传出去。我自己当初啃这块内容的时候,也是反复在eNSP里搭拓扑、抓包、看路由表,才慢慢把四类属性的行为逻辑摸清楚。
这篇内容围绕一个综合实验展开,目标是在eNSP里用几台路由器跑通BGP,把公认必遵、公认任意、可选过渡、可选非过渡这四类属性的典型代表全部验证一遍。具体涉及到的属性包括:Origin、AS_Path、Next_Hop、Local_Preference、MED、Community、Originator_ID、Cluster_List等。实验的核心不是把命令敲一遍就完事,而是要搞清楚每一类属性在BGP选路中的位置、传递规则、以及在不同场景下应该怎么用。
为什么选eNSP而不是其他模拟器?原因很直接:eNSP对华为VRP的命令支持最完整,BGP属性的相关命令和真实设备几乎一致,而且抓包方便,可以直接在接口上抓Wireshark报文看属性字段。对于备考HCIA/HCIP的同行来说,eNSP就是最贴近考试环境的工具。拓扑设计上,我采用了一个典型的双AS互联结构,中间加一个过渡AS,这样既能验证AS_Path的传递,也能观察可选过渡属性在跨AS时的表现。
整个实验的设计思路是:先跑通基础BGP邻居和路由通告,然后逐类属性做修改和验证,每改一个属性就观察路由表的变化和邻居的接收情况。这样做的好处是变量可控,不会因为同时改多个属性导致排查困难。下面我会把每个环节的操作、原理和踩过的坑都展开讲清楚。
2. BGP四类属性核心原理拆解
2.1 公认必遵属性的行为逻辑
公认必遵,英文叫Well-known Mandatory,意思是所有BGP实现都必须能识别,而且每条BGP路由的Update报文里都必须携带。这类属性只有三个:Origin、AS_Path、Next_Hop。它们的特点是“走到哪带到哪”,不管经过多少个AS,都不会被丢弃。
Origin属性标记路由的来源,有三个取值:IGP(i)、EGP(e)、Incomplete(?)。i表示路由由IGP协议产生,比如network命令宣告的直连路由;e表示从EGP学到的,现在基本不用了;?表示来源不确定,比如从IGP引入到BGP的路由。选路时i优于e优于?,这个顺序在华为设备上是固定的。
AS_Path记录路由经过的AS号序列,每经过一个AS,边界路由器就会把自己的AS号加在最前面。它的作用有两个:防环和选路。防环很好理解,路由器收到一条AS_Path里包含自己AS号的路由,直接丢弃。选路时AS_Path越短越优先,这是BGP选路规则里比较靠前的一条。
Next_Hop是下一跳地址,这个属性最容易出问题。EBGP邻居之间,Next_Hop默认是发送方的接口地址;IBGP邻居之间,从EBGP学到的路由传给IBGP邻居时,Next_Hop默认不变。这就导致IBGP邻居可能没有到达Next_Hop的路由,需要通过next-hop-local命令修改。我在实验里会专门验证这个场景。
2.2 公认任意属性的操作要点
公认任意,英文是Well-known Discretionary,所有BGP实现都必须能识别,但不要求每条Update都携带。这类属性的代表就是Local_Preference,简称Local_Pref。它只在IBGP邻居之间传递,不会传给EBGP邻居。默认值是100,值越大越优先。
Local_Pref的典型用法是在IBGP内部指定出口路由器。比如一个AS有两条出口,想让流量走其中一条,就在对应的边界路由器上把Local_Pref调高。需要注意的是,Local_Pref只能在IBGP邻居之间传,如果从EBGP学到的路由想影响本AS的选路,需要在边界路由器上设置Local_Pref后再传给IBGP邻居。
这里有个容易混淆的点:Local_Pref和MED都是影响选路的,但方向不同。Local_Pref是“我要从哪个门出去”,影响的是本AS内部的出站流量;MED是“你从哪个门进来”,影响的是相邻AS的入站流量。这个区别在实验里会通过对比来验证。
2.3 可选过渡属性的传递规则
可选过渡,英文是Optional Transitive,这类属性不是所有BGP实现都必须支持,但如果路由器不认识它,仍然会把它传递给其他邻居。代表属性是Community和Originator_ID、Cluster_List。
Community是一组32位的标记,格式是AS:NN,用来给路由打标签。它的强大之处在于可以配合路由策略做批量匹配,比如把所有打上100:1标签的路由统一设置Local_Pref。Community的传递需要手动开启,华为设备上默认不传递,需要在邻居或对等体组下配置peer advertise-community。
Originator_ID和Cluster_List是路由反射器场景下用的。Originator_ID记录路由发起者的Router ID,防止反射环路;Cluster_List记录经过的Cluster ID,也是防环用的。这两个属性在路由反射器实验里会重点验证。
2.4 可选非过渡属性的丢弃行为
可选非过渡,英文是Optional Non-transitive,路由器如果不认识这类属性,不仅自己不处理,也不会传给其他邻居。代表属性是MED,也叫Multi-Exit Discriminator。
MED用于向相邻AS建议入站流量的入口,值越小越优先。默认值是0,只在相邻AS之间传递,收到后不会再传给第三个AS。MED的传递范围很有限,而且默认情况下只在同一个AS的邻居之间比较,不同AS传来的MED不比较,除非配置了always-compare-med。
MED和Local_Pref的配合使用是BGP选路的经典场景:本AS内部用Local_Pref决定出站,相邻AS用MED建议入站。实验里我会模拟两个AS之间的双链路,通过调整MED来观察流量走向的变化。
3. eNSP综合实验拓扑与基础配置
3.1 拓扑设计与地址规划
实验拓扑我设计了四个路由器,分别命名为R1、R2、R3、R4。AS规划如下:R1在AS 100,R2和R3在AS 200,R4在AS 300。R1和R2之间是EBGP,R2和R3之间是IBGP,R3和R4之间是EBGP。R2和R3之间跑OSPF保证IBGP邻居的底层可达。
地址规划方面,R1的Loopback0是1.1.1.1/32,R2的Loopback0是2.2.2.2/32,R3的Loopback0是3.3.3.3/32,R4的Loopback0是4.4.4.4/32。互联接口用10.0.X.X/30的网段,X对应路由器编号。比如R1和R2之间用10.0.12.0/30,R1是10.0.12.1,R2是10.0.12.2。
为什么用Loopback做BGP源地址?因为Loopback接口永远UP,不会因为物理接口抖动导致BGP邻居断开。这是生产环境的标准做法,考试里也建议这么配。配置命令是peer X.X.X.X connect-interface Loopback0。
3.2 基础BGP邻居配置
先配R1和R2之间的EBGP。R1上执行:
bgp 100 router-id 1.1.1.1 peer 10.0.12.2 as-number 200 network 1.1.1.1 255.255.255.255R2上执行:
bgp 200 router-id 2.2.2.2 peer 10.0.12.1 as-number 100 peer 3.3.3.3 as-number 200 peer 3.3.3.3 connect-interface Loopback0R3上执行:
bgp 200 router-id 3.3.3.3 peer 2.2.2.2 as-number 200 peer 2.2.2.2 connect-interface Loopback0 peer 10.0.34.4 as-number 300R4上执行:
bgp 300 router-id 4.4.4.4 peer 10.0.34.3 as-number 200 network 4.4.4.4 255.255.255.255配完之后用display bgp peer检查邻居状态,必须是Established。如果卡在Active或者Connect,先检查底层IP可达性和ACL是否放行了TCP 179端口。
3.3 OSPF底层互通配置
R2和R3之间需要跑OSPF,让3.3.3.3和2.2.2.2互相可达。R2上:
ospf 1 router-id 2.2.2.2 area 0 network 2.2.2.2 0.0.0.0 network 10.0.23.0 0.0.0.3R3上:
ospf 1 router-id 3.3.3.3 area 0 network 3.3.3.3 0.0.0.0 network 10.0.23.0 0.0.0.3这里有个细节:R2和R3之间的IBGP邻居用Loopback建立,所以OSPF必须宣告Loopback地址。如果不宣告,IBGP邻居起不来。我当初就在这里卡了半小时,后来display ospf peer才发现邻居根本没建立。
提示:IBGP邻居的底层可达性必须由IGP保证,OSPF或IS-IS都可以。eNSP里OSPF收敛很快,但要注意区域划分,跨区域的话需要骨干区域连续。
4. 四类属性逐项验证与实操记录
4.1 Origin属性验证与路由引入对比
先看Origin的默认行为。R1上用network宣告1.1.1.1,这条路由的Origin是i。在R2上display bgp routing-table 1.1.1.1,可以看到Origin字段显示为i。
然后在R1上做路由引入,把一条静态路由引入BGP:
ip route-static 192.168.1.0 255.255.255.0 NULL0 bgp 100 import-route static这条192.168.1.0/24的路由Origin就是?。在R2上查看,Origin显示为?。如果同时存在i和?的两条路由去往同一个目的网段,BGP会优先选i的。这个在实验里可以构造一下:R1上同时network和import-route同一条路由,观察R2选哪条。
实测下来,华为设备上如果同一条路由既被network又被import-route,Origin取i。这个细节在考试里可能会考,但实际项目中很少有人这么干,因为容易造成策略混乱。
4.2 AS_Path防环与选路验证
AS_Path的防环功能很好验证。在R4上把4.4.4.4宣告进BGP,R3学到后传给R2,R2再传给R1。R1上display bgp routing-table 4.4.4.4,AS_Path是300 200。如果此时在R1上配置peer 10.0.12.2 allow-as-loop,就可以让R1接收包含自己AS号的路由,但这是危险操作,生产环境千万别这么干。
选路方面,AS_Path越短越优先。我构造了一个场景:R1到4.4.4.4有两条路径,一条经过AS 200,一条经过AS 200 300。正常情况下R1选AS_Path短的那条。如果要人为影响选路,可以用as-path-limit或者apply as-path命令在出方向追加AS号。
这里有个实操心得:AS_Path的修改一定要在出方向做,入方向改不了。因为AS_Path是逐跳累加的,你在入方向改,下一跳又会加回来。我当初在入方向用apply as-path,结果发现邻居收到的AS_Path根本没变,后来才想明白这个逻辑。
4.3 Local_Preference的IBGP传递实验
Local_Pref的验证需要两条路径。我在R2和R3上分别配置到R4的EBGP邻居,但实际拓扑里R2和R4没有直连,所以这个场景需要调整拓扑。为了简化,我直接在R2上配置Local_Pref,观察R3是否收到。
R2上:
bgp 200 peer 3.3.3.3 route-policy LP import route-policy LP permit node 10 apply local-preference 200然后在R3上display bgp routing-table 1.1.1.1,可以看到Local_Pref变成了200。注意,Local_Pref只在IBGP邻居之间传递,R4是EBGP邻居,收不到这个属性。在R4上查看同一条路由,Local_Pref还是默认的100。
这个实验说明了一个关键点:Local_Pref的作用范围是本AS内部。如果你想让相邻AS的流量走某个入口,得用MED,不能用Local_Pref。
4.4 MED的跨AS传递与比较规则
MED的验证需要R2和R3同时向R4发送路由。我在R2和R3上都配置了到R4的EBGP邻居,然后R2上设置MED为50,R3上设置MED为100。R4上display bgp routing-table 1.1.1.1,会看到从R2学到的路由MED是50,从R3学到的MED是100,R4优先选MED小的,也就是走R2。
但这里有个坑:MED默认只在同一个AS的邻居之间比较。如果R2和R3属于不同的AS,R4不会比较它们的MED。实验里R2和R3都在AS 200,所以R4会比较。如果R2在AS 200,R3在AS 300,就需要在R4上配置compare-different-as-med,否则MED不生效。
MED的传递范围也有限。R4把从R2学到的路由传给其他EBGP邻居时,MED默认不带出去。如果想让MED继续传递,需要配置peer X.X.X.X advertise-med。这个在跨多个AS的场景里要注意。
4.5 Community属性的标记与匹配
Community的配置稍微复杂一点。先在R2上开启Community传递:
bgp 200 peer 3.3.3.3 advertise-community然后在R2上给路由打标签:
route-policy COMM permit node 10 apply community 200:100R3收到后display bgp routing-table 1.1.1.1,可以看到Community字段显示200:100。接下来在R3上用Community匹配做策略:
community-filter 1 permit 200:100 route-policy COMM-MATCH permit node 10 if-match community-filter 1 apply local-preference 300这样R3就把打了200:100标签的路由的Local_Pref调到了300。Community的强大之处在于可以批量操作,不用逐条路由匹配。生产环境里经常用Community来做流量工程,比如给所有VoIP流量打标签,然后统一调整优先级。
4.6 Originator_ID与Cluster_List验证
这两个属性需要路由反射器场景。我在R2上配置R3为反射器客户端:
bgp 200 peer 3.3.3.3 reflect-clientR3从R2学到路由后,Originator_ID是2.2.2.2,Cluster_List是空。如果R3再反射给其他客户端,Cluster_List会加上R3的Cluster ID。这两个属性的作用是防环:Originator_ID防止路由回到发起者,Cluster_List防止在反射器集群内循环。
实验里我构造了一个三角反射场景,R2反射给R3,R3反射给R4,R4再反射给R2。如果没有Originator_ID和Cluster_List,路由会在三个路由器之间无限循环。有了这两个属性,R2收到自己发起的路由时会检查Originator_ID,发现是自己的Router ID,直接丢弃。
5. 常见问题排查与避坑经验
5.1 BGP邻居起不来的排查思路
邻居起不来是最常见的问题,排查顺序我总结了一个表:
| 排查项 | 检查命令 | 常见原因 |
|---|---|---|
| 底层可达性 | ping -a 源地址 目的地址 | 路由缺失或ACL拦截 |
| TCP 179端口 | display tcp status | 防火墙或ACL未放行 |
| BGP配置 | display bgp peer | AS号配错或peer地址写错 |
| 更新源 | display current-configuration | connect-interface未配 |
| 认证 | display bgp peer verbose | 密码不匹配 |
我踩过最坑的一次是R2和R3的IBGP邻居,底层OSPF通了,ping也能通,但BGP就是起不来。后来display bgp peer verbose发现是connect-interface没配,BGP用物理接口地址去建邻居,但对方只认Loopback地址。加上connect-interface Loopback0就好了。
5.2 路由不优选的排查方法
路由收到了但不优选,通常是属性比较的结果。BGP选路规则有十几条,我整理了一个速查表:
| 选路顺序 | 比较属性 | 优先级 |
|---|---|---|
| 1 | Local_Pref | 越大越优 |
| 2 | AS_Path长度 | 越短越优 |
| 3 | Origin | i > e > ? |
| 4 | MED | 越小越优 |
| 5 | EBGP优于IBGP | EBGP优先 |
| 6 | IGP度量 | 越小越优 |
| 7 | Router ID | 越小越优 |
排查的时候从第一条开始比,找到第一条不同的属性,就知道为什么选这条不选那条了。比如两条路由Local_Pref都是100,AS_Path长度也一样,Origin都是i,MED都是0,那就看是EBGP还是IBGP学来的。这个顺序一定要背熟,考试和实际项目都用得上。
5.3 属性传递范围搞混的典型场景
Local_Pref和MED的传递范围最容易搞混。我列一个对比:
| 属性 | 传递范围 | 默认值 | 选路方向 |
|---|---|---|---|
| Local_Pref | IBGP邻居之间 | 100 | 出站流量 |
| MED | EBGP邻居之间 | 0 | 入站流量 |
| Community | 需手动开启 | 无 | 标记用 |
| AS_Path | 所有BGP邻居 | 逐跳累加 | 防环和选路 |
Local_Pref不会传给EBGP邻居,MED不会传给第三个AS。这两个规则如果记反了,策略怎么配都不生效。我当初就是把Local_Pref配在EBGP邻居上,结果对方根本收不到,排查了半天才发现是传递范围的问题。
5.4 eNSP模拟器的特殊注意事项
eNSP虽然好用,但有几个坑要注意。第一,路由器的CPU占用率高了之后BGP邻居会闪断,建议把不用的接口shutdown,减少不必要的报文。第二,eNSP的Wireshark抓包有时候会丢包,重要验证建议多抓几次。第三,保存配置的时候用save命令,eNSP不会自动保存,重启后配置全丢。
还有一个细节:eNSP里BGP的Router ID如果没手动配置,会自动选接口地址最大的那个。如果接口地址变了,Router ID也会变,可能导致BGP邻居重置。所以生产环境和实验里都建议手动指定Router ID。
6. 属性综合运用与策略设计思路
6.1 出站流量控制:Local_Pref实战
假设一个场景:本AS有两个出口,R2走电信线路,R3走联通线路。平时想让流量走R2,R2故障时切到R3。配置思路是在R2上把Local_Pref调到200,R3保持默认100。这样IBGP内部所有路由器都会优先选R2作为出口。
但这里有个问题:如果R2的EBGP邻居断了,R2上的路由会撤销,IBGP邻居会重新选R3。这个切换时间取决于BGP的收敛速度,通常需要几十秒。如果要加快切换,可以配置BGP的BFD联动,或者调整Keepalive和Holdtime时间。生产环境里一般用BFD,检测时间可以降到毫秒级。
6.2 入站流量控制:MED与AS_Path配合
入站流量的控制比出站复杂,因为主动权在对方手里。MED是建议值,对方可以不接受。如果MED不生效,可以用AS_Path追加来影响。比如想让对方走R2进来,就在R2的出方向追加几个AS号,让对方看到R2的AS_Path更长,从而选R3。
但AS_Path追加有个副作用:会影响所有经过这条路径的路由,不仅仅是目标网段。所以更精细的做法是用Community标记,让对方根据Community来做策略。这需要双方协商好Community的语义,属于跨域流量工程的范畴。
6.3 路由反射器场景下的属性处理
路由反射器里Originator_ID和Cluster_List是自动处理的,不需要手动配置。但有一个点要注意:反射器从客户端学到的路由,反射给非客户端时,Next_Hop默认不变。如果非客户端没有到达Next_Hop的路由,需要配置next-hop-local。
另外,反射器场景下Local_Pref的传递不受影响,因为反射器不改变IBGP的属性。但AS_Path在反射器上不会追加,因为反射器不改变AS号。这个和EBGP邻居不一样,EBGP邻居每经过一个AS都会追加AS号。
6.4 大型网络中属性策略的规划建议
在大型网络里,属性策略要有统一的规划。我的经验是:Local_Pref用三位数,100以下保留,100到200表示正常出口,200以上表示备份出口。MED用两位数,0到50表示主线路,50到100表示备线路。Community用AS:功能编号的格式,比如65001:100表示VoIP,65001:200表示视频。
这样规划的好处是策略清晰,排查问题的时候一眼就能看出意图。而且不同管理员之间可以共享Community语义,跨团队协作的时候不会乱。我见过一个网络,Community随便打,结果策略冲突,流量乱走,排查了一周才找到原因。
7. 实验总结与个人实操体会
这个实验我反复做了三遍,每一遍都有新的收获。第一遍主要是验证命令能不能跑通,第二遍开始关注属性的传递范围和选路顺序,第三遍才真正理解每个属性在设计上的意图。BGP属性不是孤立的,它们之间有优先级、有配合、有冲突,只有把整个选路流程串起来,才能在遇到问题的时候快速定位。
我个人在实际操作中的体会是:先抓包,再看路由表,最后查配置。抓包能看到邻居实际发了什么属性,路由表能看到本地选了什么路由,配置能看到策略有没有生效。这三步走下来,90%的问题都能定位。剩下的10%通常是模拟器的bug或者底层路由的问题,重启一下或者检查IGP就能解决。
最后分享一个小技巧:在eNSP里做BGP实验的时候,把每个路由器的display bgp routing-table输出保存下来,对比修改属性前后的变化。这样能直观地看到哪个属性变了、哪个路由被优选了。我习惯用文本文件记录每次修改的命令和结果,时间长了就是一本自己的排错手册。