自己在家开运营商 Part.2 - 向世界宣告 IP 段 (BGP Session & BIRD)

 

前言

上一篇 Blog 中我们已经请 LIR 帮我们注册好了自己的 ASN, 并租用(或获赠)了一段 IPv6 地址.

这篇文章中, 我们要让全世界接入互联网的计算机都能访问到这段 IP 地址.

BGP 会话

理论上, 我们要通过 BGP 协议与其他 AS 内的边界网关连接, 建立 BGP 会话 (BGP Session), 互相交换自己的 IP 段.

但作为新晋的迷你”运营商”, 我们并没有任何物理的基础设施. 要知道正经运营商的主要工作就是全世界到处拉网线, 其他运营商自然没有让我们白嫖的道理.

事实上, 根据对方处理导入/导出路由的行为进行区分, BGP 会话两方的关系可以分三种: 上游, 下游和对等(peer)互连

  1. 上游: 向我们提供整个 Internet 所有其他 AS 的路由, 并将我们导出的路由告诉它的所有上游及 peer
  2. 下游: 与上游恰好相反, 我们将我们所有已知的路由告知下游, 并替下游将其导出路由的告诉我们的 peer 和上游
  3. peer: 仅仅向我们提供自己 AS 内的路由, 也只会将我们导出的路由限制在其 AS 内

一般情况下, 下游需要向其上游支付一些费用(按带宽计算), 作为租借上游物理基础设施的费用, 这种连接也被称为 transit. peer 之间则是同级运营商之间的友好合作, 一般被称为 peering, 免收结算费用.

所以为了达成本文的目标, 最可行的方法就是寻找一个现成的上游, 上游会将我们导出的路由继续传递给上游或 peer, 直到 Tier 1 ISP, 它们之间则会通过 peer 交换所有的路由, 最终连接起整个 Internet.

至于如何和他人 peer, 出于篇幅考虑, 让我们下篇 blog 再研究.

寻找上游

各大运营商常在托管机房有接入点, 如果你有托管在机房的独立服务器, 你应该可以直接联系运营商签约购买带宽及 IP transit 服务. 当然, 这一套流程自然是价格不菲.(想想国内专线宽带的惊人价格, 或是想想把独立服务器搞到国外机房的繁琐流程和开销)

但还好有一些 VPS 厂家也为我们提供了 BGP Session 的服务 (其实就是 IP transit 只是名字不同), 例如 Vultr, v.ps 或 BuyVM. 也有一些 BGP Tunnel 的服务, 通过隧道建立 BGP Session 后进行 transit, 甚至还有部分 BGP Tunnel 是免费的.

你也可以试试在 BGP Services 网站上寻找更多相关服务的提供商.


各个服务商的配置方法都不完全一致, 在这里以我目前使用的 v.ps 为例: 至少需要购买三个月或以上的 Düsseldorf 地区的 VPS (共 22.95 EUR), 可以附赠免费的 LocIX 接入和 BGP Session. (这家不同地区的 BGP Session 价格不一样, 有些地区不能免费, 只有德国有免费 LocIX 接入)

发送工单联系客服后, 按照客服要求注册了 PeeringDB, 且向指定邮箱发送 LoA (Letter of Authorization) 就可以设置好 BGP Session 和 LocIX 了.

宣告地址

目前, 你应该已经从你的上游处得到了这些信息:

  • 上游的 ASN
  • 上游的 IP
  • (可选的) MD5 密码

找到上游之后, 我们现在开始配置我们的客户端 —— BIRD. BIRD 是一个实现了 BGP 协议的客户端, 具体配置可以看这份来自 Soha的很详细的 BGP 教程.

我使用的发行版是 Debian Bookworm, 相对较新, 我就直接使用 apt 安装了 BIRD: apt install bird2. 较旧的发行版还是建议按照 BIRD 文档编译安装.

我的 ASN 为 214775, 要宣告 2a14:7c0:4d00::/40.
上游 xTom 的 ASN 为 3204, IPv6 为 2a03:d9c0:2000::5, 我们的 vps 本身的 IPv6 地址为 2a03:d9c0:2000::1f7, MD5 密码为 114514, 所以我的配置文件如下:

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
log syslog all;

router id 185.254.74.126; # vps 的公网 IPv4 地址
define ASN=214775; # 我的 ASN
define OWNIPv6s=[2a14:7c0:4d00::/40]; # 我的 IPv6 地址段

# device 协议必须有, 否则 BIRD 不会自动从内核获取比如网络接口的信息, direct 协议和寻找下一跳的时候就挂了
protocol device {}

# kernel 协议用于导出路由表到内核
protocol kernel {
ipv6 {
export all; # 将所有 IPv6 路由都导入系统路由表
};
}

# static 定义静态路由
protocol static static_v6 {
ipv6;
route 2a14:7c0:4d00::/40 unreachable; # 宣告 2a14:7c0:4d00::/40 这段 IP, 暂时设置为 unreachable
}

filter export_filter_v6 {
if net ~ OWNIPv6s then accept; # 如果前缀包括在OWNIPv6s内则放出
reject; # 否则全部拒绝
}

filter import_filter_v6 {
if net ~ [::/0] then reject; # 如果为默认路由则拒绝
accept; # 接收所有其他路由
}

protocol bgp bgp_xtom_v6 {
local 2a03:d9c0:2000::1f7 as ASN; # 指定本端地址与ASN
neighbor 2a03:d9c0:2000::5 as 3204; # 指定对端地址与ASN
ipv6 { # 指定要在该BGP邻居上跑的协议
import filter import_filter_v6; # 指定导入过滤器
export filter export_filter_v6; # 指定导出过滤器
export limit 10; # 限制导出前缀数量, 根据需要调整, 防止过滤器配糊导致 session 爆炸
};
password "114514"; # 不是我夹带私货, 是 v.ps 给我的 password 真的是 114514... 如果没有 password 删除这行即可
graceful restart; # 平滑重启, 防止重启bird的时候造成路由撤回导致服务中断
}

你可以直接按着我的配置文件修改(当然还是建议你看一下 Soha 的教程再改), 改好后写入 /etc/bird/bird.conf, 重启 BIRD systemctl restart bird.

你可以运行 birdc show protocols all 查看当前所有协议的状态, 可以看到 BGP 会话已经建立, 导入了全网的 204923 条 IPv6 路由, 导出了我们自己的 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
bgp_xtom_v6 BGP        ---        up     08:00:21.885  Established   
BGP state: Established
Neighbor address: 2a03:d9c0:2000::5
Neighbor AS: 3204
Local AS: 214775
Neighbor ID: 62.133.35.43
Local capabilities
Multiprotocol
AF announced: ipv6
Route refresh
Graceful restart
Restart time: 120
AF supported: ipv6
AF preserved:
4-octet AS numbers
Enhanced refresh
Long-lived graceful restart
Neighbor capabilities
Multiprotocol
AF announced: ipv6
Route refresh
Graceful restart
4-octet AS numbers
Enhanced refresh
Long-lived graceful restart
Session: external AS4
Source address: 2a03:d9c0:2000::1f7
Hold timer: 218.652/240
Keepalive timer: 17.453/80
Channel ipv6
State: UP
Table: master6
Preference: 100
Input filter: import_filter_v6
Output filter: export_filter_v6
Export limit: 10
Action: disable
Routes: 204923 imported, 1 exported, 204923 preferred
Route change stats: received rejected filtered ignored accepted
Import updates: 206278 0 0 63 206215
Import withdraws: 170 0 --- 27 143
Export updates: 206216 206215 0 --- 1
Export withdraws: 143 --- --- --- 0
BGP Next hop: 2a03:d9c0:2000::1f7 fe80::12b8:55ff:fe21:8e9

现在运行 birdc show route 可以看到 BIRD 内部的路由, 运行 ip -6 route 应该也能看到 BIRD 已经将所有 IPv6 路由加入了系统路由表 (会输出非常多路由).

宣告的 IP 段在全球范围内的传播和收敛可能需要一点时间, 你现在可以稍微干点别的事, 站起来活动一下————

半个小时后, 我们可以打开 BGP Tools 这个网站. 搜索我们刚刚宣告的 IP 段 2a14:7c0:4d00::/40, 在 Connectivity 标签下可以用可视化的方式看到目前的连接性状态. 如果你是初次添加 AS, 不同上游更新过滤器的速度可能不同, 实际的传播时间可能长达 24 小时.

实时的 Connectivity, xTom 是我们的上游, 还能看到上游的上游实时的 Connectivity, xTom 是我们的上游, 还能看到上游的上游

配置网卡

目前我们已经成功地把 2a14:7c0:4d00::/40 宣告出去了.

我们可以尝试 ping 一下其中的 IP, 按照我们 BIRD 文件中的配置, 服务器会直接返回 ICMP destination unreachable (p.s. 我测试时发现 Mac 上的 ping6 没能正确处理这里的 Destination unreachable, Linux 上的 ping -6 是可以显示 Destination unreachable: no route, Windows 上的 ping 也会正常显示”无法访问目标网”)

此时全球访问 2a14:7c0:4d00::/40 的流量就已经被路由到我们这台 vps 上了, 不过我们的 vps 现在被配置为什么都不做, 直接返回 unreachable. 我们现在只需要在 vps 上做一些小小的配置就能为全球提供服务了:

1
2
3
4
5
6
# 创建一个 dummy 网卡
ip link add dev dummy0 type dummy
ip link set dummy0 up

# 选一个喜欢的 IP 地址配置给它
ip addr add dev dummy0 2a14:7c0:4d00::1

完成后, 我们就可以从自己的电脑上 ping 到 2a14:7c0:4d00::1 这个地址了.

ping.pe 的全球测试结果ping.pe 的全球测试结果

自然, 此时我们已经可以在 vps 上架设任何需要的服务, 并让别人通过 2a14:7c0:4d00::1 访问, 我这里使用 python3 -m http.server -b :: 80 启动一个简单的 HTTP 服务器.

能访问到架设的 HTTP 服务器能访问到架设的 HTTP 服务器

在 vps 上我们也可以使用 2a14:7c0:4d00::1 去访问别的网站实现实名上网:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@s39230 ~ # curl --interface 2a14:7c0:4d00::1 -6 www.cloudflare.com/cdn-cgi/trace
fl=910f33
h=www.cloudflare.com
ip=2a14:7c0:4d00::1
ts=1725599416.24
visit_scheme=http
uag=curl/7.88.1
colo=DUS
sliver=none
http=http/1.1
loc=IL
tls=off
sni=off
warp=off
gateway=off
rbi=off
kex=none

小结

本篇 blog 中完成了 IP 段的宣告, 让整个 Internet 都知道了我们这个自治系统的存在~

下一篇应该会来讲讲如何和他人 peer.

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

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