日度归档:2025年5月15日

做了一个用来生成中国大陆路由的容器

背景

因为在研究BGP,也有中国大陆与其他地区进行路由选路的需求,所以在琢磨着要不在互联网上整一个bgp speaker,然后这个bgp speaker向所有连过来的对端通告全部的中国大陆路由,这样路由器就不需要配置大量的静态路由,减少配置量,而且更新的话也能够应用到所有出口路由器。

实时全球路由表?

某天,根据这篇文章试了一下,确实可行,但是吧……这效果强虽强,但是资源消耗也有点离谱。

这个容器实时从RIPE读取全球路由表的变更,一整天下来平均带宽有1.78Mbit/s,相当于一天就跑了18G的流量(单向)。要是放在vps上的话,一个月估计的流量500G。

我是放在家里出口的RouterOS上以容器的方式跑的,算上容器本身和加的路由表,需要吃掉大约400M的内存。我就想想,有没有一些更加轻量级的方案呢?

记得之前是见到过一个chnroute的东西,可以生成中国的路由表。然后灵机一动,要不我也用脚本写个差不多的玩意吧,看起来也不是很难。bgp软件话似乎可以用bird,可以直接重载,也不会闪断。

脑袋一拍,开干,结果就弄了个这样的玩意出来。

设计思路

github上的README也已经写了设计思路的,非常简单,以bird软件作为核心然后主要的配置有3个:

一个是手动写的需要配置的静态路由,比如说苹果的7.0.0.0/8,实测如果走VPN的话会遇到各种各样奇奇怪怪的问题,可能和我用的是自建的DNS递归服务器,然后我又用国区账号,部分苹果业务由云上贵州来负责的原因。反正就是会有这样的需求,先预留着。

一个是通过脚本生成中国的路由表,从网上搜一搜就找到类似的了,核心是从APNIC下载分发的资源表,过滤出属于中国的部分,然后通过文本处理格式化成bird能够读取的配置文件。然后定期重新加载就行了。

最后一个是协议的配置,我现在选择的是用bgp来输出,有其他需要的话可以考虑ospf或者isis之类的,不过bgp作为各ISP之间互联用的协议,又是我的学习目标,果断选择BGP来输出了。这块的配置我放在了custom.conf,有需要可以灵活修改。

最后,为了方便部署,选择了容器化,用docker打个包,就可以到处用了。现在是托管在dockerhub,未来可能放在其他地方。

如何使用

这里强烈推荐一下claw cloud的白嫖,只要有一个注册时间超过180天的github账号就可以使用他们的免费等级的服务,可以有5刀的credit,不绑信用卡也可以用。他们目前有新加坡,日本,美西岸,美东岸,德国几个区域。每个区域最高能放4个vcpu,8G内存,和10G的磁盘。(当然,如果拉满的话,价格是绝对会超5刀每月的),限制了每个月10G的流量。也限制了每个机器只能有1个端口(tcp或者udp)。

限制是挺多的,特别是流量,不过对于我这个拍脑袋整出来的东西,已经可以算得上是奢华了。从APNIC下载delegation的文件大概3.8M,每天一次,然后算上bgp的连接,一天估计跑不了10M。

于是,噔噔蹬蹬。

膨胀了啊,在k8s上直接replica 2!然而内存使用量还是太少了,都识别不出来。

下面贴一下过程:

先去注册,然后切换到需要部署的区域,然后点击App Launchpad。

在右上角点击create App进入部署的界面。

Application Name随便填,image选择public,然后填入ferrets/cn_route-bird。没错我已经预编译了一份并且上传到了dockerhub。

Usage里面CPU和RAM都拉到最低(为啥RAM不能选16M?)。Replica建议大于1,反正价格你也看到了,每天0.02刀,30天就是……0.6刀(手动狗头)。

Network里面Container Port写179,这是bgp的默认端口。打开互联网访问,完了之后会分配一个。

Advanced Configuration里面有一个需要填的,就是Configmaps。点击Add。

File Name写/etc/bird.d/custom.conf

File content就复制粘贴github上的内容就行,填完了之后confirm。

最后右上角Deploy Application就行。过一阵子,你就有了能够直接用bgp订阅的,能够自动更新的中国大陆路由表了。

考虑到高可用,和剩余的credit……找另外一个区域重复上述过程,避免一个区炸了之后就直接丢了路由。

配置订阅

下一步就是用出口路由器去连了这个bird。首先去App Launchpad,找到分配了啥网址和端口

然后,手动解析一下这个域名。(或者你的路由器可以直接填域名而不是ip地址来建立bgp会话,那就填域名)

从里面挑几个出来建立bgp会话,参考的mikrotik的配置脚本如下:

记得先写到中国大陆的静态路由。根据配置,bgp吐出来的ipv4的路由下一跳是114.114.114.114,ipv6的路由下一跳是240c::6666。必须先写静态路由以保证递归之后,从bgp会话收到的路由是从你想要的出口出口,避免路由震荡。或者你可以先在connection里面写上input.filter,先把路由全部过滤。搞好之后再取消过滤,应用到实际环境里面。

/ip route
add dst=114.114.114.114 gateway=wan
/ipv6 route
add dst=240c::6666 gateway=wan
/routing bgp template
add address-families=ip,ipv6 as=65000 cluster-id=192.168.0.0 disabled=no multihop=yes name=feed output.filter-chain=block .no-client-to-client-reflection=yes routing-table=main
/routing bgp connection
add template=feed connect=yes local.role=ibgp name=cn_route_feed-1 remote.address=[刚才解析出来的ip1] .as=65000 .port=[分配的端口]
add template=feed connect=yes local.role=ibgp name=cn_route_feed-1 remote.address=[刚才解析出来的ip2] .as=65000 .port=[分配的端口]
add template=feed connect=yes local.role=ibgp name=cn_route_feed-1 remote.address=[刚才解析出来的ip3] .as=65000 .port=[分配的端口]
add template=feed connect=yes local.role=ibgp name=cn_route_feed-1 remote.address=[刚才解析出来的ip4] .as=65000 .port=[分配的端口]

然后……为啥RouterOS不能去重路由……明明我都在bird上配置了cluster id。囧

如此一来,就有了相对稳定的,免费的,可以自动更新的,资源消耗相对低的中国路由表订阅了。

虽然订阅了8份之后,RouterOS里面的路由表数量高达85k+,都比实时全球路由表的数量(45k+)高一倍了。但……但这有高贵的ipv6啊!