搭建属于你的Anycast任播网络

很早之前我就在好奇DNS是怎么做到全球访问同一个IP但是延迟都这么低,Serverless平台是怎么做到全球多地部署同一个应用共享同一个IP等问题。后来我申请下来了一个ASN和/44的IPv6地址段,开始了BGP之旅,终于亲手搭建了一个Anycast网络,并在全球四个地区部署了使用同一IP地址的相同应用。下面让我来分享一下如何搭建属于你的Anycast网络,关于如何申请ASN并且BGP广播出去可以参考我之前的文章:成为互联网自治系统之一

如果你有学习、研究、开发等用途,希望拿到一个免费的IPv6 /64任播地址并接入我的网络,欢迎联系我,免费提供给有正当需求(和我比较熟)的人。(●’◡’●)

Anycast tag on BGP.Tools

更新数据库

上篇文章我们讲到BGP后只简单提到了RPKI和ROA,后来在研究的过程中我发现我遗漏了IRR相关的内容。在拿到网段后,我们最好先去RIPE数据库中为我们的网段创建inet6num和route6对象,分别作为Whois和IRR。

inet6num

inet6num中我们可以填入IP段的名称、所属国家、维护者等信息,这些信息会在第三方查询工具中以Whois展示出来。IP地址库也会参考这里面的所属国家做定位。这也是为什么有些网上的人的IP地址会显示其他国家的原因。

route6

route6中我们需要填入网段和允许的ASN来源,这可以让其他人验证广播是否有效。

BGP

BGP这里也不做过多讲述,之前的文章介绍过怎么在Vultr上进行BGP,他们的官方文档(Configuring BGP on Vultr)中也有比较详细的教程。新手BGP一定记住:过滤、过滤、过滤!不要把不该export的路由给播出去了。

对于IPv6,我们想做到Anycast的话只需要在不同机器上广播同一网段即可,等到广播在互联网上传播开来就好。之后其他人访问你时会选择跳数最少的访问过去,正因为跳数最少所以不是延迟最低(缺乏考证)。

WireGuard

我们在不同国家地区都部署了PoP后,想接入服务器有两种方法:

  • 每个PoP都建立一个WireGuard链接到一台服务器,这些服务器使用同一个IPv6,那么我们需要n台服务器才行。
  • 接入至少一台服务器,让每个PoP都通过WireGuard连起来,然后通过动态路由协议更新它们的路由表。

是不是第二种看上去经济挺多?那我们就这么干!WireGuard的配置教程很多,我就不班门弄斧了。但是,代价是什么呢?

Babel

让我们用点新东西,Babel是近几年出来的动态路由协议,它能够快速收敛、避免环路。其不仅考虑到了有线网络,也对无线网络Mesh网络进行了思考,它可以用跳数、丢包率、延迟等作为指标,这允许了我们选择更加实用的指标来进行路由。

Babeld默认工作在6696端口,使用UDP作为传输层协议,默认的IPv6的组播地址是ff02::1:6。提到组播后有的人要头皮发麻了,是的,这意味着你得创建n(n-1)/2个Wireguard链接,当然你也可以选择牺牲健壮性,将几个关键节点成对连接起来,只要保证至少有一条通路可以走遍所有节点即可。

在Wg的配置文件中你需要加一个fe80::/64的本地地址,以便组播。

Babeld的配置文件在/etc/babeld.conf,我的样例配置文件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
default type tunnel # 表明链路类型是隧道,默认在Hello和IHU消息中发送时间戳便于计算RTT
default split-horizon true # 开启水平分割
default faraway true # 表明网络节点直接是“很远”的,其背后的网络和其之前的网络没有关系
default unicast true # 向所有邻居发送除Hello外的多份TLV

local-port 23333 # 提供给client连接的端口

interface wg0 # 工作在wg0 if上
interface wg1 # 工作在wg1 if上

in ip 2a0c:xxxx:xxxx::/48 eq 64 allow # 我们接收2a0c:xxxx:xxxx::/48段长度为64的prefix,根据metrics判断是否加入路由表
in ip fddc:xxxx:xxxx:xxxx::/64 eq 128 allow # 我们接收fddc:xxxx:xxxx:xxxx::/64段长度为128的prefix,根据metrics判断是否加入路由表
in deny # 其余prefix默认拒绝

redistribute ip 2a0c:xxxx:xxxx::/48 eq 64 allow # 我们会重播2a0c:xxxx:xxxx::/48段长度为64的prefix,告诉别人可以经过我们到达
redistribute ip fddc:xxxx:xxxx:xxxx::/64 eq 128 allow # 我们会重播fddc:xxxx:xxxx:xxxx::/64段长度为128的prefix,告诉别人可以经过我们到达
redistribute local deny # 其余prefix默认拒绝

babeld启动后,我们可以通过ncat看看其状态:ncat :: 23333

  • 输入dump并回车:查看当前的路由信息,可以观察每条prefix可以经过谁可达,指标的值是多少,是否加入了我们的路由表等等。
  • 输入monitor并回车:实时输出邻居和路由的变动信息,非常便于调试。

如果没有问题的话,这时候我们将一台服务器wg到任意一个PoP,其他人访问任意PoP终会走WireGuard跳到我们的服务器。