自己在家开运营商 Part.4 - 建立自己的 Anycast 网络

 

前言

我们暂且跳过上一 part 结尾提到的一系列拓展内容 (IGP/iBGP/DN42等), 这些内容在一个小型的 AS 内并不是必须的, 有兴趣的读者可以自行探索.

让我们先来看一些别的 —— Anycast 网络. 很多国外的产品已经用上了这项技术, 例如 Cloudflare/Azure/Google 的 CDN 产品, 1.1.1.1/8.8.8.8 这类 DNS. (只有国内因为三大运营商的不作为, 还在使用传统的 DNS 分流)

目前我们的 AS 内只有一台德国的 v.ps 节点, 从之前的 ping.pe 测试结果也可以看出: 我们的服务在欧洲地区访问延迟很低, 但在美洲/亚太地区的延迟就比较高了.

所以让我们来尝试给我们的 AS 加入另外一些无状态的节点, 构建一个全球的 Anycast 网络.

再找上游

其实要构建一个 Anycast 网络真的十分简单: 只要再找一些上游, 宣告同样的地址段即可. 本文完.(x)

为了多样性和防止单点故障, 让我们这次换一家商家 - Vultr, 他们家会时不时提供短时大额的新人试用额度, 我注册的时候只需要 Paypal 充值 $5 (或绑银行卡)就得到了 30 天 $250 的试用额度. 我们就来用这些额度进行实验.

先注册 Vultr 账号, 打开 Dashboard 中的 BGP 选项卡, 在其中可以自助上传 LOA 并完成邮箱验证, 完成验证后会自动创建一个工单, 等待人工审核通过后, 就可以看到已经添加的后缀了.

接下来我们就能创建 vps 并宣告我们的地址段了, 步骤几乎和本系列 part2 的一致, 关于一些 Vultr 特有的信息在他们的文档上.

Vultr 这里我选择了 Full table 模式要求其提供完整的 Internet 路由表, 这里有个问题是 multihop 可能会导致全部路由都变成 unreachable, 这个问题在 Vultr 的文档中没有提到, 需要自己添加一条 static route 到默认网关.

最后我写出的配置大概是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 其余部分同 part2, 此处省略
protocol static static_v6 {
ipv6;
route 2a14:7c0:4d00::/40 unreachable;
route 2001:19f0:ffff::1/128 via fe80::fc00:5ff:fe17:ba85%enp1s0; # 需要手动指定 ip -6 route 看到的默认网关
}

protocol bgp bgp_vultr_v6 {
local 2001:19f0:6001:58ee:5400:05ff:fe17:ba85 as ASN;
neighbor 2001:19f0:ffff::1 as 64515;
ipv6 {
import filter import_filter_v6;
export filter export_filter_v6;
export limit 10;
};
multihop 2; # Vultr 要求设置 multihop
password "114514"; # 这是你可以自行设置的 MD5 密码
graceful restart;
}

我创建了美国洛杉矶和新加坡的两台 VPS, 进行了配置和宣告. (p.s. 如果你有更多主机或者更复杂的应用部署需求, 可以考虑 Ansible 之类的运维工具, 我这里就偷懒, 纯手动配置了一下)

同样是等待一段时间让路由收敛, 我们可以在 BGP Tools 中看到新的上游:

AS20473 是我们新增的上游AS20473 是我们新增的上游

Anycast 之低延迟

我们现在使用 ping.pe 再次 ping 2a14:7c0:4d00::1, 我们可以看到美国和新加坡地区的延迟显著下降了, 欧洲内的延迟仍然表现良好, MTR 也能直观的显现出路由的差异.

使用 Anycast 前的 ping.pe 测试结果(来自本系列 part2)使用 Anycast 前的 ping.pe 测试结果(来自本系列 part2)

使用 Anycast 后的 ping.pe 测试结果使用 Anycast 后的 ping.pe 测试结果

San Francisco 的 MTR 追踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0.  localhost                   Loss%  Snt   Last  Avg   Best  Wrst  StDev AS Name                         PTR
1 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
2 fd00:0:9::26a 0.0% 20 0.6 0.6 0.4 2.5 0.4 -
3 2604:a880:ffff:8::1:34 0.0% 20 2.3 3.1 0.8 38.7 8.4 -
4 2a03:b0c0:fffd::44 0.0% 20 0.4 0.5 0.3 0.8 0.0 -
5 2a03:b0c0:fffe::14e 0.0% 20 1.4 1.2 1.1 1.6 0.0 -
6 2a03:b0c0:fffe::131 0.0% 20 0.9 1.1 0.8 3.4 0.5 -
7 2001:418:0:5000::56c 0.0% 20 1.1 3.1 0.9 22.4 4.9 2914 US NTT-LTD-2914 ae-38.a04.snjsca04...
8 2001:418:0:2000::260 0.0% 20 1.7 12.7 1.1 47.9 15.8 2914 US NTT-LTD-2914 ae-0.r24.snjsca04...
9 2001:418:0:2000::112 50.0% 20 10.4 14.8 10.0 35.2 8.7 2914 US NTT-LTD-2914 ae-3.r25.lsanca07...
10 2001:418:0:2000::c5 0.0% 20 9.8 10.4 9.8 19.1 2.0 2914 US NTT-LTD-2914 ae-1.a03.lsanca07...
11 2001:418:0:5000::1012 0.0% 20 10.9 13.8 10.1 41.9 9.5 2914 US NTT-LTD-2914 xe-3-5-0-1.a03.lsa...
12 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
13 2001:19f0:6000::a44:c2 0.0% 20 11.5 11.5 11.3 11.9 0.0 20473 US CHOOPA
14 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
15 2a14:7c0:4d00::1 0.0% 20 11.3 11.3 11.2 12.1 0.0 214775 CN

Paris 的 MTR 追踪:

1
2
3
4
5
6
7
8
9
10
0.  localhost                   Loss%  Snt   Last  Avg   Best  Wrst  StDev AS Name                         PTR
1 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
2 2a00:dd80:3e:10::32 0.0% 20 0.3 1.3 0.2 19.7 4.3 36236 US NETACTUATE
3 2001:7f8:43::6939:1 25.0% 20 1.3 2.0 1.3 5.4 0.9 -
4 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
5 ??? 100.0 20 0.0 0.0 0.0 0.0 0.0 -
6 2001:470:0:52e::2 0.0% 20 12.5 13.3 12.0 26.7 3.1 6939 US HURRICANE e0-36.core2.dus1.h...
7 2001:7f8:9e::c8e:0:2 0.0% 20 12.1 12.1 11.9 13.0 0.0 -
8 2a09:0:1337:c0c0::2 0.0% 20 12.5 12.1 12.0 12.5 0.0 -
9 2a14:7c0:4d00::1 0.0% 20 12.7 12.6 12.4 13.0 0.0 214775 CN

在我们 AS 内的三台主机上均执行 tcpdump icmp6, 也能看到来自不同地区的 ping 请求. 由于 ping.pe 提供了 PTR 记录, 我们可以很清楚的看到流量具体来自哪里.

例如新加坡 Vultr 收到了来自新加坡 digitalocean 的 ping:

1
2
06:57:07.542784 IP6 sg-digitalocean.ping.pe > 2a14:7c0:4d00::1: ICMP6, echo request, id 45771, seq 48123, length 64
06:57:07.542845 IP6 2a14:7c0:4d00::1 > sg-digitalocean.ping.pe: ICMP6, echo reply, id 45771, seq 48123, length 64

美国 Vultr 收到了来自印度, 美国等地区的 ping:

1
2
3
4
07:11:23.955198 IP6 ping-pe-us-ca-sf-digitalocean-do.localdomain > 2a14:7c0:4d00::1: ICMP6, echo request, id 50875, seq 48123, length 64
07:11:23.955213 IP6 2a14:7c0:4d00::1 > ping-pe-us-ca-sf-digitalocean-do.localdomain: ICMP6, echo reply, id 50875, seq 48123, length 64
07:11:24.340371 IP6 ping-pe-netactuate-chennai-india.localdomain > 2a14:7c0:4d00::1: ICMP6, echo request, id 11214, seq 48123, length 64
07:11:24.340410 IP6 2a14:7c0:4d00::1 > ping-pe-netactuate-chennai-india.localdomain: ICMP6, echo reply, id 11214, seq 48123, length 64

此时我们只要在这三台主机上提供一致的服务, 就能让全球各地的用户都享受到低延迟高带宽的稳定服务了. 例如在所有服务器上同时安装 nginx, 然后 host 我这个静态博客. (结果发现还不如白嫖 Cloudflare) 如果此时我们在主机上配置一个 nginx 反代 / DNS 服务器, 我们就搭建了我们自己的简易 Anycast CDN / Anycast DNS.


不过我们也注意到, 我们新加坡 Vultr 收到的流量最少, 几乎只有来自新加坡本地的流量, 其他亚太地区的流量更倾向于去美国. 这是因为我们的上游 ISP 在决定路由时并不是完全依据网络跳数/物理距离这些因素决定的, 也会考虑线路优先级/线路拥堵情况/线路成本.

亚太地区的网络连通性情况不如欧美, 亚太地区运营商网间结算的价格也普遍远超美国运营商, 带宽还小容易拥堵, 这种情况下, 就很可能出现绕路的情况(数据包舍近求远去美国转一圈). 所以, 连通性差的地区宣告的路由更难以向周围地区传播.

要解决亚太地区的连通性问题, 要么继续加钱在各个地区增加服务器, 要么向上游加钱购买优先级更高的线路 (比如国内大名鼎鼎的 “CN2 GIA”), 这也解释了为什么为国内或其他亚太地区提供 “优化线路” 的 vps 普遍价格昂贵且会限制更低的带宽和流量.

Anycast 之高可用

Anycast 不仅能降低延迟, 也同时提供了高可用性 - 任何一个节点掉线的话, BGP 会话断开, 宣告的路由被撤回, 流量自然会被重新路由到其他节点, 继续提供服务. 对于无状态服务, 只要有任意一个节点在线, 我们就能正常提供服务.

我们来实际尝试一下: 我们从苏州移动 ping 2a14:7c0:4d00::1 地址, ping 请求会命中德国的 v.ps 节点, 从上海联通 ping 这个地址会命中美国 Vultr 节点. 我们保持 ping 的同时直接 hard reset 美国 Vultr 节点, 模拟机器出现故障掉线的情况, 上海联通 ping 记录如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
2024/9/12 21:21:52 - 来自 2a14:7c0:4d00::1 的回复: 时间=348ms
2024/9/12 21:21:53 - 来自 2a14:7c0:4d00::1 的回复: 时间=551ms
2024/9/12 21:21:54 - 来自 2a14:7c0:4d00::1 的回复: 时间=595ms
2024/9/12 21:21:55 - 来自 2a14:7c0:4d00::1 的回复: TTL 传输中过期。
2024/9/12 21:21:56 - 来自 2a14:7c0:4d00::1 的回复: TTL 传输中过期。
2024/9/12 21:21:57 - 来自 2a14:7c0:4d00::1 的回复: TTL 传输中过期。
2024/9/12 21:21:58 - 无法访问目标网。
2024/9/12 21:22:00 - 来自 2a14:7c0:4d00::1 的回复: 时间=500ms
2024/9/12 21:22:01 - 来自 2a14:7c0:4d00::1 的回复: 时间=479ms
2024/9/12 21:22:02 - 来自 2a14:7c0:4d00::1 的回复: 时间=631ms
2024/9/12 21:22:03 - 来自 2a14:7c0:4d00::1 的回复: 时间=498ms
2024/9/12 21:22:04 - 来自 2a14:7c0:4d00::1 的回复: 时间=411ms
2024/9/12 21:22:05 - 来自 2a14:7c0:4d00::1 的回复: 时间=552ms

可以发现在 5s 内流量就完成了切换, 我尝试了几次, 不可用的时间都在 5s 左右. 而原本就路由到德国 v.ps 的苏州移动的 ping 则不会受到任何影响.

上海联通切换之前的路由:

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
1   2408:84e2:440:a210::70    AS17621  中国 上海 上海  chinaunicom.cn
2.51 ms / 200.58 ms / 251.75 ms
2 *
3 fc00:1000::61 * RFC4193
37.79 ms / * ms / * ms
4 *
5 *
6 *
7 2408:8000:2:38b:: AS4837 中国 北京 chinaunicom.cn 联通
169.25 ms / 67.16 ms / 117.78 ms
8 2408:8000:2:8044::1 AS4837 中国 北京 chinaunicom.cn 联通
253.78 ms / * ms / * ms
9 *
10 *
11 2001:1900:2100:32::29 AS3356 美国 加利福尼亚 洛杉矶 lumen.com
6-1-2.ear1.LosAngeles6.Level3.net 386.38 ms / 333.42 ms / 281.89 ms
12 2001:1900:2100::40da AS3356 美国 路易斯安那州 门罗 lumen.com
CHOOPA-LLC.ear1.LosAngeles6.Level3.net 696.69 ms / 748.12 ms / 646.49 ms
13 2001:19f0:fc00::a44:10e * 美国 加利福尼亚 洛杉矶
ethernetae5-sr2.lax3.constant.com 544.16 ms / 489.78 ms / 425.65 ms
14 2001:19f0:fc00::a44:a6 * 美国 加利福尼亚 洛杉矶
ethernetswp55-ds1-m1-r0305-a.lax3.constant.com 651.93 ms / 705.55 ms / 583.08 ms
15 *
16 2a14:7c0:4d00::1 AS214775 欧洲
389.20 ms / 525.20 ms / 936.49 ms

上海联通 Vultr 掉线之后自动切换的新路由:

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
1   2408:84e2:440:a210::70    AS17621  中国 上海 上海  chinaunicom.cn
83.69 ms / 34.61 ms / 200.55 ms
2 *
3 fc00:1000::61 * RFC4193
132.71 ms / 248.39 ms / 198.26 ms
4 2408:8000:9000:408f::d4 AS17621 中国 上海 上海 chinaunicom.cn
2.54 ms / 217.61 ms / 154.24 ms
5 2408:8000:9000:20e6::52 AS17621 中国 上海 上海 chinaunicom.cn
42.33 ms / 202.64 ms / 133.66 ms
6 2408:8000:9000:20e6::2b2 AS17621 中国 上海 chinaunicom.cn 联通
30.97 ms / * ms / * ms
7 2408:8000:2:38b:: AS4837 中国 北京 chinaunicom.cn 联通
558.28 ms / 505.24 ms / * ms
8 *
9 *
10 *
11 *
12 *
13 *
14 *
15 *
16 *
17 *
18 *
19 *
20 *
21 2001:470:0:52e::2 AS6939 德国 北莱茵-威斯特法伦州 杜塞尔多夫 he.net
e0-36.core2.dus1.he.net 338.38 ms / 274.45 ms / 242.29 ms
22 2001:7f8:8::c8e:0:1 AS3214 德国 北莱茵-威斯特法伦州 杜塞尔多夫 MegaIX Dusseldorf - xTom GmbH - 10Gbps xtom.com
262.57 ms / 250.95 ms / 462.66 ms
23 2a09:0:1337:c0c0::2 * 德国 北莱茵-威斯特法伦州 杜塞尔多夫
r1dus.v.ps 346.01 ms / 296.37 ms / 244.45 ms
24 2a14:7c0:4d00::1 AS214775 欧洲
245.00 ms / 446.79 ms / 391.97 ms

小结

至此, 我们已经实现了自己的 Anycast 网络!

我们 Anycast 网络与传统 AS 的横向扩张不同, 我们一个 AS 内的主机没有相互连接, 不使用 IGP 等方式在网内做路由, 而是各自独立的组成 Anycast 网络提供无状态的服务. 用户会访问到哪台主机完全取决于用户的网络环境, 所以要注意的是, 我们无法保证同一个用户一定会访问到同一台主机, 如果需要提供有状态服务, 我们需要自己想办法在所有节点间同步这些状态 (例如分布式数据库), 不过这些都是后话了, 不再展开.

写了好多… 这个系列应该还剩最后一个 part 就要完结了, 敬请期待.

本文采用 CC BY-NC-SA 4.0 许可协议发布.

作者: lyc8503, 文章链接: https://blog.lyc8503.net/post/asn-4-anycast-network/
如果本文给你带来了帮助或让你觉得有趣, 可以考虑赞助我¬_¬