拉了两条不同运营商的宽带,想要有效利用两条线路的带宽,但是这时候单纯的负载均衡体验并不好,因为随机分配的出口并不一定速度最快。BGP全球路由表里正好有我们需要的信息——每个IP到哪个运营商距离最近(某种意义来说,速度也应当最快)。那么怎么利用它来优化网络的体验呢?
基线配置
拉了两条宽带,一条中国电信,一条中国移动,均接在一台IOS XE 16.9设备上,分别对应Dialer 0和Dialer 1。基础的双线备份配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
interface Dialer0 description China Telecom ip address negotiated ip nat outside encapsulation ppp ip tcp adjust-mss 1452 dialer pool 1 dialer-group 1 ppp authentication pap callin ppp pap sent-username xxxx password yyyy ! interface Dialer1 description CMCC ip address negotiated ip mtu 1480 ip nat outside encapsulation ppp ip tcp adjust-mss 1432 dialer pool 2 dialer-group 1 ppp authentication pap callin ppp chap hostname xxxx ppp chap password yyyy ppp pap sent-username xxxx password yyyy ! track 1 interface Dialer1 ip routing ! ip nat inside source route-map nat-ct-pppoe interface Dialer0 overload ip nat inside source route-map nat-cmcc-pppoe interface Dialer1 overload ip route 0.0.0.0 0.0.0.0 Dialer0 5 track 1 ip route 0.0.0.0 0.0.0.0 Dialer1 10 ! ip access-list standard nat-inside-ip permit 192.168.1.0 0.0.0.255 ! dialer-list 1 protocol ip permit ! route-map nat-cmcc-pppoe permit 10 match ip address nat-inside-ip match interface Dialer1 ! route-map nat-ct-pppoe permit 10 match ip address nat-inside-ip match interface Dialer0 |
两条线路只是用来做备份有些浪费,况且中国电信上国内网站快,中国移动出国速度快,各有长处。那么怎么才能妥善利用呢?让我们用BGP来做一个策略路由吧。
收一个BGP全球路由表
有很多服务提供商可以给你做免费的BGP会话,在其中选一个便宜又能提供全表的,要一份全表。我用Vultr比较多,那么这次也用它好了。接下来要考虑怎么把全表收回来。因为BGP要求两端IP固定(除非你想用listen-range功能,但是这个功能有潜在的安全性问题),那么要么我们在路由器和收全表的服务器之间打一个隧道,用这台服务器做路由控制,要么先想办法把表收到离路由器逻辑上比较近的服务器上,后者作为路由控制器(control plane),处理数据后再转发给路由器。考虑到中国特色的网络问题,这里使用后一种方法,路由控制器放在内网。
考虑到打隧道不是本文重点,我们就简单地用ZeroTier One无脑打一个隧道,配上IP,在Vultr的VPS上启动一个BGP daemon,和网关起一个eBGP会话,和内网的路由控制器起一个iBGP会话即可。如果不想打隧道,那么简单的TCP转发服务也可以用来解决BGP session两端固定IP的问题。
服务器配置:
- Vultr侧(下称feeder):5USD的虚拟机(1CPU/1G Memory),Ubuntu 18.04
- 本地侧(下称controller):J1900 ESXi服务器上的虚拟机(2CPU/2G Memory),Debian 10
Feeder配置很简单,我用的VPS上已经装了Bird 1作为BGP daemon,那么只需要写两组BGP会话即可。参考配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# Feeder (Bird 1) # /etc/bird/bird.conf router id <your-public-ipv4>; protocol device {} protocol direct {} protocol bgp bgp_vultr { local as <your-asn>; import all; export none; graceful restart on; multihop 2; neighbor 169.254.169.254 as 64515; password "hunter2"; } protocop bgp bgp_controller { local as <your-asn>; import none; export all; graceful restart on; neighbor <controller-ip> as <your-asn>; } |
Controller用Bird 2作为BGP daemon。首先要注意的一点是,我们需要在路由器上硬编码controller到feeder的路由,以防路由改变以后BGP断开造成路由震荡。
1 |
ip route <controller-ip> 255.255.255.0 Dialer0 |
Bird 2配置(先确认全表能收进来,路由策略暂时空着,下一节再讲):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# Controller (Bird 2) # /etc/bird/bird.conf log syslog all; router id <your-controller-ip>; # debug protocols all; watchdog warning 5 s; watchdog timeout 30 s; ipv4 table global_v4; ipv4 table policy_v4; protocol device {} protocol direct { ipv4; } template bgp bgp_feeder { local as 205610; neighbor as 205610; multihop; graceful restart on; rr client; ipv4 { table global_v4; import all; export none; }; } template bgp bgp_router { local as 205610; neighbor as 205610; multihop; graceful restart on; rr client; ipv4 { table policy_v4; import none; export all; next hop self; }; } protocol bgp bgp_feeder_0 from bgp_feeder { neighbor <feeder-ip>; } protocol bgp bgp_router_0 from bgp_router { neighbor <router-ip>; } filter policy_routing { reject; } protocol pipe global_to_policy { table global_v4; peer table policy_v4; export filter policy_routing; import none; } |
因为两边都是iBGP会话,为了让路由能在两边分发,需要把controller配成route reflector。
确定路由策略
先确定一个最简单的路由策略:
- 电信(AS4134、AS4809):走电信
- 移动(AS56041):走移动
- 其余走移动
那么首先我们在bird配置文件里面完善一下filter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
define cmcc_asn = [ 56041 ]; define chinanet_asn = [ 4809, 4134 ]; filter policy_routing { if source != RTS_BGP then reject; # CMCC if bgp_path.last ~ cmcc_asn then { bgp_community = -empty-; bgp_community.add((100,100)); accept; } # ChinaNet if bgp_path.last ~ chinanet_asn then { bgp_community = -empty-; bgp_community.add((200,200)); accept; } reject; } |
然后我们在路由器上配置策略路由规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
track 1 interface Dialer1 ip routing track 2 interface Dialer0 ip routing ! ip route 192.0.2.100 255.255.255.255 Dialer 1 10 track 1 ip route 192.0.2.100 255.255.255.255 Dialer 0 20 ip route 192.0.2.200 255.255.255.255 Dialer 0 10 track 2 ip route 192.0.2.200 255.255.255.255 Dialer 1 20 ! ip community-list standard PBR_CMCC permit 100:100 ip community-list standard PBR_CT permit 200:200 ! route-map PBR permit 10 match community PBR_CMCC set ip next-hop 192.0.2.100 ! route-map PBR permit 20 match community PBR_CT set ip next-hop 192.0.2.200 ! router bgp <your-asn> bgp log-neighbor-changes neighbor <controller-ip> remote-as <your-asn> neighbor <controller-ip> description BGP Controller ! address-family ipv4 neighbor <controller-ip> activate neighbor <controller-ip> allowas-in 10 neighbor <controller-ip> soft-reconfiguration inbound neighbor <controller-ip> route-map PBR in exit-address-family |
这里说明一点:IOS/IOS XE的route-map不支持在BGP in上用set interface,会报以下错误:
1 |
% "PBR" used as BGP inbound route-map, set interface not supported |
对动态IP的interface需要使用recursive方式设置路由,即用两个假的IP设置分别路由到两个interface,然后分别set ip next-hop到这两个IP上。
至于更复杂的路由策略,我在本系列的下一篇文章中会讲。
测试
分别找一个电信的IP和一个移动的IP看一下其路由即可。示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Router#show ip route 60.177.1.1 resolve Routing entry for 60.176.0.0/12 Known via "bgp 65001", distance 200, metric 0 Tag 64515, type internal Last update from 192.0.2.200 00:01:10 ago Routing Descriptor Blocks: * 192.0.2.200, from 100.97.1.9, 00:01:10 ago, via Dialer0 Route metric is 0, traffic share count is 1 AS Hops 5 Route tag 64515 MPLS label: none Router#show ip route 112.17.1.1 resolve Routing entry for 112.17.0.0/16 Known via "bgp 65001", distance 200, metric 0 Tag 64515, type internal Last update from 192.0.2.100 00:01:00 ago Routing Descriptor Blocks: * 192.0.2.100, from 100.97.1.9, 00:01:00 ago, via Dialer1 Route metric is 0, traffic share count is 1 AS Hops 7 Route tag 64515 MPLS label: none |
结论
整个系统的资源占用:
- controller内存占用大概在400MiB以下
- 需要分流的路由总计不到8000条,IOS XE可以轻松处理(如果给IOS XE发全表的话,4GiB内存是不够用的)
- BGP会话带来的流量消耗大概一天300MiB
感谢某匿名CCNP玩家在本文写作过程中提供的帮助。
参考:
Pingback引用通告: 在家也要玩BGP(1.5):我的双线分流规则 | Drown in Codes
Pingback引用通告: DN42入坑指南(五)DN42百宝箱 | 辣条部落格
Pingback引用通告: 如何大致使用AS判断回程ICMP、TCP大小包路由?-开心VPS测评
Pingback引用通告: 『无题』 » Blog Archive » How To Send Internet Route By BIRD?
666牛逼