Pages

Thursday, 3 August 2017

DN42 - 一个大型的 VPN 网络

简介

DN42 是一个大型的 VPN 网络,通过 GRE, OpenVPN, Tinc, IPsec 等隧道将不同地区的用户连接在一起,同时使用 BGP 协议宣告自己的网段,实现用户之间的互联互通。
DN42 有一套完整的 AS 号的申请、IP 地址块的申请以及 .dn42 域名的申请系统,IP 地址块的分配不会于公网上的产生冲突,因为使用的是 172.20.0.0/14 以及 fd00::/8 这些私网地址。
那么,在 DN42 中我们能玩些什么呢?

路由协议

正如上面所说,DN42 使用 BGP 协议来让各个用户宣告自己的网段,从而实现用户之间的互联互通,因此 BGP 协议是十分重要的一个环节。当前 DN42 大概有 300 多个 AS 在线,有大概 580 条路由,应该足够我们进行研究的了。
在我实际的操作中,使用到了 iBGP 、 eBGP 以及路由反射器,相信在以后进一步深入的话还会学习到很多好玩的东西,例如 Anycast 。
可能你会想说,eNSP 和 Cisco Packet Tracer 也同样可以做到类似的模拟,事实上的确如此,但是,有什么比在实际的网络上进行操作更加有趣的呢?而且,你不必成为 APNIC 的会员就可以拿到 AS 号,也不用交纳年费来买一个 IP 地址块,同时,也不用怕弄坏了实际的网络然后被上级责备。

连接到 Hacker Spaces

如今没有多少人有公网 IP ,就连宽带也逐渐开始分配 100.64.0.0/16 的 IP 地址,如果我们家里有一台树莓派什么的想要在外面访问,将自己的路由器加入到 DN42 也是一个不错的选择。我们可以随时随地连接上 DN42 网络,然后可以访问到自己的树莓派,也可以用树莓派给其他人提供各种各样的服务。
说人话就是,DN42 在一定程度上解决了 NAT 设备的访问问题,如果有担心安全问题的话,也可以设置一些访问控制进行访问的过滤。

加入 DN42 网络

请参考官方的入门文档:https://dn42.net/howto/Getting-started

体验

大概一个星期之前我就拿着我的几台VPS 入了坑,在 http://io.nixnodes.net/ 中注册了一个 AS 号:4242421888 ,然后 ALLOCATED 了几个 IP 段给这几台不同地区的 VPS 使用。
一切就绪之后,我在 https://dn42.us/peers 中联系到了 Chris Moons ,通过和他做 peer ,我成功地将自己的 VPS 连接到了 DN42 网络中。
不得不说,DN42 和真实的互联网真的很相似。

BGP

我目前使用的是 Bird 作为 BGP 宣告工具,之前是使用 Quagga 的,但是他对 IPv6 协议上不是很支持,在我的操作中遇到了不少问题,虽然他的使用方法很像是在操作 Cisco 设备,但是后来我还是把他撤掉换成了 Bird
Bird 的语法虽然不像 Quagga 那样有 Cisco 设备操作经验就可以上手,但是他的配置及其简单明了。
如果想要了解的话可以去 DN42 的 Wiki 了解:https://dn42.net/howto/Bird
下面是我在 Bird 中运行 show protocols all chrismoos 的结果
Preference:     100
  Input filter:   (unnamed)
  Output filter:  (unnamed)
  Import limit:   10000
    Action:       block
  Routes:         468 imported, 0 filtered, 560 exported, 16 preferred
  Route change stats:     received   rejected   filtered    ignored   accepted
    Import updates:        4657978          0      46297    1252694    3358987
    Import withdraws:        14184          0        ---      43809       7162
    Export updates:        9025262     284456          0        ---    8740806
    Export withdraws:         9173        ---        ---        ---     275578
  BGP state:          Established
    Neighbor address: 172.20.162.86
    Neighbor AS:      4242421588
    Neighbor ID:      172.20.16.133
    Neighbor caps:    refresh AS4
    Session:          external AS4
    Source address:   172.22.68.1
    Route limit:      468/10000
    Hold timer:       179/240
    Keepalive timer:  46/80

DNS

DN42 不仅仅实现了域名的注册,也实现了根域名服务器以及下面的分级域名服务器
下面是反向查询我的一个 ip 地址,可以看出他和我们的实际网络上的 DNS 查询是十分相似的.
root@cn-can01:~# dig @172.23.0.53 -x 172.22.68.8 +trace

; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> @172.23.0.53 -x 172.22.68.8 +trace
; (1 server found)
;; global options: +cmd
.                       67      IN      NS      t.root-servers.dn42.
.                       67      IN      NS      a.root-servers.dn42.
.                       67      IN      NS      x.root-servers.dn42.
.                       67      IN      NS      m.root-servers.dn42.
;; Received 225 bytes from 172.23.0.53#53(172.23.0.53) in 1628 ms

22.172.in-addr.arpa.    7200    IN      NS      x.in-addr-servers.dn42.
22.172.in-addr.arpa.    7200    IN      NS      m.in-addr-servers.dn42.
22.172.in-addr.arpa.    7200    IN      NS      c.in-addr-servers.dn42.
;; Received 121 bytes from 172.23.67.67#53(m.root-servers.dn42) in 1319 ms

68.22.172.in-addr.arpa. 7200    IN      NS      d.dn42-servers.dn42.
68.22.172.in-addr.arpa. 7200    IN      NS      x.dn42-servers.dn42.
;; Received 162 bytes from 172.23.67.53#53(m.in-addr-servers.dn42) in 1059 ms

8.68.22.172.in-addr.arpa. 7200  IN      CNAME   8.0/27.68.22.172.in-addr.arpa.
0/27.68.22.172.in-addr.arpa. 7200 IN    NS      ns2.imlonghao.dn42.
0/27.68.22.172.in-addr.arpa. 7200 IN    NS      ns1.imlonghao.dn42.
;; Received 124 bytes from fdea:a15a:77b9:4444::3#53(x.dn42-servers.dn42) in 349 ms

Peers

最后,如果你想加入的话,可以去到 dn42@hackint 这个 IRC 频道寻求帮助.
---------------

DN42去中心化网络入门教程

什么是DN42?

dn42 is a big dynamic VPN, which employs Internet technologies (BGP, whois database, DNS, etc). Participants connect to each other using network tunnels (GRE, OpenVPN, Tinc, IPsec) and exchange routes thanks to the Border Gateway Protocol. Network addresses are assigned in the 172.20.0.0/14 range and private AS numbers are used (see registry) as well as IPv6 addresses from the ULA-Range (fd00::/8).
上面的是DN42官方(或者说社区)对DN42的描述。简单地说DN42就是一个大的虚拟内网,你可以自由的跟别人进行点对点的VPN连接(当然对方要同意,但与现实世界有区别的是DN42的互联一般不会有任何费用),建立类似于真实世界中的物理网络。这个网络主要是用于提供网络新手一个自由练习BGP、OSCP、WHOIS、DNS等网络技术的平台。在DN42中,你可以随便测试你路由器的配置而不用担心搞炸别的网络(但如果你是提供DN42网络中继点的话还是要注意一点),你可以照着书本一步步尝试你的配置。进入DN42的世界你只需要一个能接上互联网的电脑,甚至不需要一台Legit的物理路由器。
为了与公网区分开来,DN42内部使用172.20.0.0/14(4个B段)、fd00::/8和私有AS地址(比如我的AS4242420199)作为地址域。当然部分VPS(比如阿里云)会使用这些地址作为VPC地址,这时候就需要配置你服务商的VPC尽可能绕开这些地址以避免路由上的冲突。
顺带一提,国际VPN(国外服务器与国内服务器进行P2P连接)这种东西在国内是违法的,因为大陆政府将VPN认定为非法国际信道。Use At Your Own Risk,本博客只在技术层面对DN42进行讲解。
本教程使用OpenVPN(使用静态密匙)作为点对点的对接方案,Quagga作为BGP的程序。其余方案(比如TincWireguardGREIPSec w/ PK、 Bird)不在本博文讲解范围内,请自行参考Wiki(因为我很Noob自己也不懂所以没法写教程)
特别警告:虽然同为去中心化网络,DN42并不是匿名的。如果你需要完全匿名化的网络,请使用Tor

DN42入门资料参考

因为这篇文章可能会更新得非常非常非常慢,所以你有兴趣的话可以先自行读这些资料进行参考:
官方维基:https://wiki.dn42.us/Home
剩余自行谷歌。因为这个东西比较小众所以资料并不多。

第一步:注册DN42的各种对象

这里的对象指的是Object别想歪了
Registry地址:https://io.nixnodes.net/
提醒:Registry使用了StarCom的证书,这个证书的根被部分浏览器(比如谷歌)给吊销了,所以可能会有安全警告,直接点击允许即可。
参考资料(英文):https://wiki.dn42.us/howto/Getting-started

    • 右上角那个输入框(我输入了IXNET-MNT的地方)是搜索框,你在里面输入你的Maintainer对象名,就可以看到你自己所有的资源。
    • 下面所有的对象你都可以参考我的配置。
    • 所有对象如果保存成功右边的信息栏都会有类似于saved object: 172.20.165.0_29 | inetnum的提示。
  1. 注册一个Maintainer(维护者)对象
    • 点击右上角的Create Object,选择mntner
    • 左边mntner字段填写你喜欢的名字,比如IXNET-MNT。通常全大写,以-MNT结尾
    • descr填写这个维护者的描述,比如IX Network Studio DN42 Network Maintainer
    • sha512-pw填写这个维护者的明文密码。这个密码非常重要,不建议使用常用密码,但是一定不能忘记,不然的话你所有的对象的配置你都将会无法访问
    • admin-ctech-c填上DUMMY-DN42。这个以后会改,不用担心
    • mnt-by填上和mntner同样的内容,比如IXNET-MNT,表示自己管理自己
    • Save保存。这相当于创建了你在DN42世界中的网管帐号
    • 在右边信息框上面那个输入框里面输入你刚才的密码,然后点+来登陆系统
  2. 创建一个Person(个人)对象
    • 步骤类似于上面
    • person填写名字,比如Howard Liu
    • contact里面填写你自己的电子邮箱地址。建议填写你PGP密匙里面的邮箱,大家在进行加密数据交流的时候可以验证来源
    • nic-hdl填写这个人的代号,比如HOWARD-DN42。通常全大写,以-DN42结尾
    • mnt-by填写你的维护者对象名,比如IXNET-MNT
    • 保存
    • 重新编辑你的维护者对象,把里面的admin-ctech-c改为你的Person对象的代号(比如HOWARD-DN42),保存
    • 从现在开始,接下来你所有创建的对象admin-ctech-c都是你Person对象的代号,mnt-by都是你维护者对象名
  3. 注册一个AS号
    • 要实现外部BGP互联与别人交换路由数据,一个AS号是必须的
    • 可注册的AS号为42424200004242423999,即424242XXXXXXXX > 4000)
    • 这里查询你喜欢的号码是否已经被注册
    • 创建一个aut-num对象
    • aut-num字段填写AS号,比如AS4242420199,注意前面有个大写的AS
    • as-name字段随意,比如IXNET-AS
    • 剩下几个字段不需要解释了,填完保存
  4. 注册一(多)个IPv4前缀
    • 注意:整个DN42只有4个B段,而且一部分地址还在保留中,请只注册你需要的前缀大小,一般新手/27足矣,永远不要注册超过/24(1个C段)
    • 你可以在这里找到还没被别人注册的IPv4前缀
    • 创建一个inetnum对象
    • inetnum填写格式如:172.20.165.0-172.20.165.7(开始地址-结束地址,这个是127.20.165.0/29的示例,我用与阿里云VPC避免路由干扰)
    • status填写ALLOCATED(区分大小写,一个字都不能错)
    • netname字段随意,比如IXNET-INTERNAL
    • country填写两位字母的国家代号,比如SG
    • 剩余的都不需要解释了,填完保存
  5. 注册一(多)个IPv6前缀
    • 因为DN42使用RF4193规定的ULA地址范围(fd00::/8)作为IPv6的地址域,所以你在这里面随便挑一个前缀就行(当然不能跟别人的重复)
    • 想查是否重复的话只需要在注册局搜索框输入你喜欢的前缀(比如fdc9:9999:9999),看看有没有人注册了就行。IPv6地址前缀这么多,一般跟别人重复的几率很小
    • 如果没有人注册的话,你可以创建一个inet6num对象
    • inet6num填写格式如:fdc9:9999:9999:0000:0000:0000:0000:0000 - fdc9:9999:9999:ffff:ffff:ffff:ffff:ffff(这个是我的IP段,即fdc9:9999:9999::/48
    • 剩余的跟上面注册IPv4的一样
    • 填完保存
  6. 决定你想使用的IP段,并创建路由(route)对象
    如果你决定把你上面注册的IP段全部用于同一个网络,请跳过这个引用框
    如果你只想用你步骤5和6注册的IP段的一部分的话,请看这个:
    • 首先你需要创建一个子IPv4(6)前缀,步骤与上面5/6完全相同,除了status那里写ASSIGNED
    • 比如我要在我的172.21.88.128/25中分出一个172.21.88.128/28作为骨干路由地址,我创建了一个inetnum字段为172.21.88.128 - 172.21.88.143的对象,然后状态那填ASSIGNED
    • 分IPv6块同理
    • 某些互联的网络可能开了严格的IP前缀筛选,如果你不注册route对象或者route对象与BGP宣告的前缀不相符的话(比如掩码不相符)你的Peer(或者他们的上/下游)可能会Reject掉你的前缀宣告
    • 决定你要用的IP段(步骤5/6注册的一整个或者上面引用框内说明的子IP段)与AS号(上面第4步注册)
    • 创建一个route对象(如果是IPv6就创建一个route6对象,剩下步骤类似)
    • route字段填你的IP前缀,比如172.21.88.128/28或者fdc9:9999:9999:9900::/64route6对象)(注意一下,这里与上面的`inetnum/inet6num填写的不同,这里只需要写IP+掩码)
    • origin填写你的AS号,比如AS4242420199AS开头,不仅仅是数字)
    • mnt-by不解释了,填完保存.
-------------------------------------------------------

接入 dn42 及 NeoNetwork

LibreHouse 建立以来的第一件大事——接入 dn42(还有 NeoNetwork),经过五个月的努力,终于有了一定的成果
BTW,欢迎来 peer :-)

本文作者对网络工程并没有什么了解。因此,以下内容可能有不准确甚至完全错误的地方。如果你发现了文中不准确的地方,欢迎通过评论或其它方式告诉我!

在按照本文执行操作时,请务必做好相关备份工作。


什么是 dn42?

dn42 是一个私有互联网络。你可以把它理解成基于现有互联网之上,许多设备通过 VPN 方式互相连接的一个小型「互联网」。作为(大概是)世界最大的私有互联网络,目前的 dn42 (及与其互联的其它网络,例如 ChaosVPN、还有上面提到的,最近由 Neo Chen 发起的 NeoNetwork 等等)有超过三百个互相连接的 AS [1]。这些 AS 中的设备通过 Tinc/Wireguard/GRE 等方式互相连接,并通过 BGP 等协议交换彼此的路由,形成一个节点众多的网络。

它跟 Tor 这样的深网 (deepnet) 有什么不同?

与能让用户匿名访问互联网和/或深网的 TorI2PZeroNet 等不同,dn42 不是匿名网络。由于网络中的每一个 IP 地址都属于一个 AS,而所有的 AS 在 Registry 都有记录,dn42 并不能提供匿名性。在互联网 (Internet) 上也是一样。如果你用家中的光纤连接通过从百度网盘上下载了一份电影的话,百度可以通过你的 IP 知道你所使用的网络运营商 (ISP)(例如中国电信)。

为什么要连接到 dn42?

为了好玩。

如果你想尝试路由技术,dn42 可能适合你。在 dn42,你不必担心自己的路由配置错误会干掉半个互联网。要知道路由泄露或劫持已经让半个互联网爆炸    了。如果是在 dn42 上,你的配置错误最多干掉整个 dn42 网络,不过 dn42 的 NOC 们相对互联网的 NOC 大概对路由泄露也有更强的抵御能力吧(因为见多了)。至少你不需要担心一条路由配坏,身边昨天能连上 Google 的用户,一夜之间都上不去 Google 了(嘛,中国大陆用户本来也上不去 Google 的说)。

如果你想做 BGP Player,但是不喜欢繁琐的 ASN 注册过程,或者不想花钱买 ASN 或者 IP 地址,dn42 可能适合你。搞过公网 BGP 的人都明白(然而我没搞过),注册一个 ASN,买个 IP 段通常是挺麻烦的事。然而在 dn42 上,注册一个 ASN 和申请一段 IP 只需要一个 Pull Request,而且不花钱。

如果你想让路由器后面的电脑有个属于自己的 IP 地址,dn42 可能适合你。通过和别的节点 peer,你就可以接入 dn42 网络,广播自己(在 dn42 网络内)的 IP,这甚至不要求你有公网 IP 地址。当然,随着 IPv6 的普及,许多中国大陆的 ISP 也开始给用户提供全球单播 (global unicast) IPv6 地址(通常以 2001: 开头),你就不需要为了一个公网 IP 而大费周章了。

总之还是为了好玩。(笑)

如何连接到 dn42(或者 NeoNetwork 什么的)?

由于现在 dn42 和 NeoNetwork 已经互通,你只需要在这两个网络之一得到一个 AS 号,并且拿到一段 IP,就可以成为整个网络中的一部分。配置好你的 AS 号和要广播的 IP 段,并且和至少一个节点 peer,你就能接入整个网络中,访问这个网络中的任何一个节点。

那么大体上的步骤就确定了。

  1. 申请一个 ASN 和一段 IP
  2. 寻找一个可以 peer 的节点
  3. 联系节点所在 AS 的 NOC,和这个节点 peer
  4. 在欲与这个节点 peer 的设备上配置 peer 所使用的 VPN 方案及路由
  5. 确认 peer 可以通过 peer 的地址连通
  6. 确认所使用的路由协议(通常是 BGP)可以建立连接
  7. 配置 DNS

需要什么?

  1. 至少一台能保持长期在线的设备。不一定要有公网 IP,但是有的话自然更好。
  2. 这台设备的 root 权限。
  3. 时间 :-)

开始我们的路由战争

笔者最近在看 Date A Live,这中二气息满满的标题还请各位不要介意。

本章节会详细介绍如何完成这一系列过程。各位亦可参考 dn42 的 Getting Started 页面。

申请 ASN 和 IP 段

这里我们将对 dn42 和 NeoNetwork 的注册方法均进行介绍。不过,你只需要在与 dn42 互联的网络中的其中一个网络有 AS 号和 IP(甚至不一定要是同一个网络中的),就可以和所有网络互通。

对于 dn42…

本段部分内容来自 这里

dn42 的 registry 在这里。你需要在这个 Gogs 实例上注册一个帐号,并向 registry 所在的 repo 发送一个 Pull Request。

你需要在以下位置各添加一个条目( <ITEM>处的内容根据你的喜好自行填写):

  • maintainer,也就是 data/mntner/<YOURNAME>-MNT
  • person,也就是 data/person/<YOURNAME>-DN42
  • AS 号,也就是 data/aut-num/AS<YOURASN>
    • dn42 目前使用的 AS 号范围是 4242420000-4242423999。
  • IP 段,也就是data/inetnum/<PREFIX>_<LENGTH> (IPv4) 和 data/inet6num/<PREFIX>_<LENGTH> (IPv6)
    • 对于 IPv6,dn42 目前使用的地址范围是 fd00::/8,这是 RFC4193 中的本地单播地址 (ULA)。 一般申请一个 /48 段即可(形如 fd00:dead:beef::/48)。dn42 建议随机生成一个(这是 RFC4193 里的规范),不过也许你也可以自定义一个,只要不冲突的话 :-)
    • 对于 IPv4,你可以在这里找到尚未被占用的 IP 段。一般申请一个 /27 或 /28 段即可。你也可以选择像 LibreHouse 一样不在 dn42 申请 IPv4,而是在 NeoNetwork 申请 IPv4 来用。

内部文件格式可以参考相同文件夹的其它条目,亦可参考 LibreHouse 当时的 Pull Request

对于 NeoNetwork…

NeoNetwork 的 registry 在这里。你需要在 GitHub 上注册一个帐号,并向 registry 所在的 repo 发送一个 Pull Request。

类似于 dn42,你需要在以下位置各添加一个条目:

  • entity,也就是 entity/<YOURNAME>
  • AS 号,也就是 asn/AS<YOURASN>
    • 你也可以沿用在 dn42 得到的 AS 号。
  • 节点信息,也就是 node/<NODENAME>
  • IP 段,也就是 route/<PREFIX>.<LENGTH> (IPv4) 和 route6/<PREFIX>.<LENGTH> (IPv6)
    • 对于 IPv6,NeoNetwork 目前使用的地址范围是 fd10:127::/16
    • 对于 IPv4,NeoNetwork 目前使用的地址范围是 10.127.0.0/16

寻找可以 peer 的节点

为了连接到网络上,你需要和网络内的至少一个节点 peer。ping 延迟更低的节点自然更好。dn42 有一个 peerfinder 可以帮助你找到离你的服务器较近的一些节点。NeoNetwork 的话,去找各个 NOC 问一下吧。LibreHouse 是在 dn42 和 burble(dn42 内最大 AS 吧,大概算是)peer 了,在 NeoNetwork 也和数个节点有 peer。

和这个节点 peer

找到节点之后,要商量具体的 peer 方式。目前比较流行的有以下几种:

  • Wireguard - 今年早些时候进了内核,被 Linus Torvalds 盛赞 “It’s a work of art” 的 VPN。配置也比较舒服。
  • GRE - 配置超级简单(甚至不需要预共享密钥)。不过请注意部分云服务提供商(例如 Google Cloud)会屏蔽 GRE 连接。
  • Tinc - 过去比较常用的 VPN 方案。不过逐渐被上两种所替代了。

选择其中比较方便的一个就好。

然后,你们还需要得到以下的信息:

  • 双方的 AS 号
  • 双方使用的路由协议(通常是 BGP)
  • 双方端点所使用的 IP。
    • 有时候会直接使用你在 dn42/NeoNetwork 的 IP,有时候则是使用一组 link-local address(或者其它的地址)。这里其实可以使用任意的 IP,但考虑到防止冲突的原则通常会使用前二者。
    • 如果不支持 MBGP 的话(例如 bird 1.6),对于 IPv4 和 IPv6 要分别协商 IP,如果支持的话,IPv4 和 IPv6 选一个就好。当然,如果只需要 IPv4(或 IPv6)的 peer 的话,只协商 IPv4(或 IPv6)的 IP 就好。
  • 双方在互联网 (Internet) 上的公网 IP(有时候可能只需要一方的 IP)
  • peer 方案的相关信息
    • 对于 Wireguard,双方所监听的端口及 Wireguard 公钥
    • 对于 GRE,什么都不需要(是的,什么都不需要)
    • 对于其它方案,则可能需要其它的资讯

配置 peer 方案

这里介绍 Wireguard 和 GRE 配置的方法之一。许多其它方式亦可达到同样效果,这里不再赘述。

示例设备的信息如下:

  • 操作系统 Debian 10.4
  • 公网域名 me.example.com (非必须,对方需要知道)
  • 公网 IP 39.39.39.39 (对方需要知道,不过通常可以从域名拿到)
  • AS 号 4242424239 (对方需要知道)
  • 使用的 dn42 IP:
    • 10.127.39.39 (IPv4)
    • fd00:3939:3939:3939::1 (IPv6)
  • 使用的端点 IP: (对方需要知道)
    • 169.254.39.39/32
    • fe80::3939/64
    • (这里 /32 和 /64 的含义,请见下文 FAQ)

欲 peer 节点的信息如下:

  • 公网域名 it.example.com
  • 公网 IP 73.73.73.73
  • AS 号 4242424273
  • 使用的端点 IP:
    • 169.254.73.73/32
    • fe80::7373/64

我们决定把和它 peer 所使用的 interface 叫做 myfirstint.

使用 systemd-networkd 配置 Wireguard

首先安装 Wireguard 并启用此内核模块(sudo modprobe wireguard)。

为了配置 Wireguard,我们需要:

  • 一个用于监听连接的端口
  • 一组用于 Wireguard 的公钥/私钥

我们需要对方告知自己的:

  • 监听连接的端口
  • Wireguard 的公钥

在示例中,我们使用 40001 作为 Wireguard 的连接监听端口,对方使用 40002 作为 Wireguard 的连接监听端口,公钥为 rcPNWjI0tPAVRr09TNxC8B+PhqSHRPnD3lPOxgkW01U=

使用 wg genkey(由软件包 wireguard-tools 提供)生成一个用于 Wireguard 的私钥:

$ wg genkey
qJRZlE1QreqHNokgpmaFdkKALUxXthTmpmzbewFv53k=
sh

再算出它的公钥:

$ echo qJRZlE1QreqHNokgpmaFdkKALUxXthTmpmzbewFv53k= | wg pubkey
2XAkuvLmBH1SB+G6o0v4OuUC4N34pB9848s/sL5ciCA=
sh

把这个公钥(2XA...CA=)和监听端口(40001)提供给对方。

之后就是 systemd-networkd 的配置时间了:

# /etc/systemd/network/myfirstint.netdev
[NetDev]
Name=myfirstint
Kind=wireguard
Description=My first peer

[WireGuard]
PrivateKey = qJRZlE1QreqHNokgpmaFdkKALUxXthTmpmzbewFv53k=
ListenPort = 40001

[WireGuardPeer]
PublicKey = rcPNWjI0tPAVRr09TNxC8B+PhqSHRPnD3lPOxgkW01U=
Endpoint = it.example.com:40002
AllowedIPs = 0.0.0.0/0,::/0
toml
# /etc/systemd/network/myfirstint.network
[Match]
Name=myfirstint

[Address]
Address=169.254.39.39/32
Peer=169.254.73.73/32

[Address]
Address=fe80::3939/64

# 如果地址在同一个网段中则不必写 Peer= 一行
toml

然后 systemctl restart systemd-networkd 即可。

使用 /etc/network/interfaces 配置 GRE

其实 GRE 也可以用 systemd-networkd 配置。至于为什么这里没有那么做,是因为如果要用 systemd-networkd 配置 GRE 的话,需要修改当前连接到互联网所用 interface 的配置文件(例如 eth0.network),而对它进行修改容易导致网络中断。如果是在本机可能还好,对于那些没有正经 VNC,只能通过 SSH 连接的 VPS 服务商,断网就是灾难。

除了对方的 IP 之外,我们还需要一条在前文中没有提到的内容:

  • 本机连接到互联网所用 interface(例如 eth0)的本地地址。在家庭网络中通常是 192.168.x.x,在大型企业网络中通常是 10.x.x.x,在 VPS 上则有可能是 172.x.x.x 等。这里我们假设它是 172.39.3.9

这大概也是 systemd-networkd 需要修改 eth0.network 这类文件的原因。

在 /etc/network/interfaces 插入如下内容:

# /etc/network/interfaces
auto myfirstint
iface myfirstint inet tunnel
        address 169.254.39.39
        dstaddr 169.254.73.73
        mode gre
        netmask 32
        endpoint 73.73.73.73
        local 172.39.3.9
        ttl 255
iface myfirstint inet6 manual
        up ip addr add fe80::3939 peer fd80::7373 dev $IFACE
apache

确认 peer 可以连通

首先启动我们所设置的 VPN:

  • 如果用 systemd-networkd 配置,运行 systemctl restart systemd-networkd
  • 如果用 /etc/network/interface 配置,运行 ifup myfirstint

查看 interface 是否被创建:

ip link
nginx

然后试着 ping 就好:

ping 169.254.73.72 -I myfirstint
nginx

配置路由:bird.conf

这里的配置只需要进行一次。在后续的 peer 过程中可跳过此步骤。

bird、FRRouting 及 Cisco 相关套件均可用于路由配置。这里我们使用 bird 2.0。为什么用了 Bird 2 呢?基于以下原因:

  • 试过 FRRouting,坑太多,文档太少,印象不好。
  • bird 2.0 支持 M-BGP

总之首先:

apt-get install bird2
apache

对于 bird.conf ,各位可以直接抄 dn42 wiki 提供的配置文件。相对 bird 1.6 把 IPv4 和 IPv6 放在一起写的情况,bird 2 将 IPv4 和 IPv6 分开,所以稍微要长一些。

基本上后面照抄,修改开头的几行就可以:

define OWNAS =  <OWNAS>;               # AS 号
define OWNIP =  <OWNIP>;               # IPv4 地址
define OWNIPv6 = <OWNIPv6>;            # IPv6 地址
define OWNNET = <OWNNET>;              # 欲广播的 IPv4 网络段
define OWNNETv6 = <OWNNETv6>;          # 欲广播的 IPv6 网络段
define OWNNETSET = [<OWNNET>+];        # 欲广播的 IPv4 网络段,集合格式
define OWNNETSETv6 = [<OWNNETv6>+];    # 欲广播的 IPv6 网络段,集合格式
toml

几件注意事项:

关于 ROA

ROA (Route Origin Validation),这里暂译为「路由来源认证」。它可以指定一个 IP 段只能由特定 AS 广播(这时,由其它 AS 广播的此段 IP 信息会被忽略),以及只能广播到特定的前缀长度(这时,过于具体的广播就会被忽略)。BGP 是相当依赖于信任的协议。如果没有 ROA 的保护,恶意的或失误的 BGP 广播可能会造成中间人攻击或严重的网络中断。

dn42 提供的 bird2 配置默认开启了 ROA。为了应用 ROA,你需要下载相关的数据(例如由 burble 生成的 dn42 ROA 文件,在这里)并且定期更新。

你也可以不使用 ROA。如果这样的话,记得把配置文件中与 ROA 相关的地方删除(大概有三处)。

如果你只广播 IPv4 / IPv6…

如果只需要 IPv4 或 IPv6 的广播,可以把不需要的地方删除掉,不过 router id 一行需要保留(即使你只广播 IPv6),并且应该填入一个 IPv4 地址(不一定必须是你所使用的地址)。

配置路由:/etc/bird/peers

如果是 BGP 协议,dn42 提供的配置模板依旧可用,照抄即可:

# /etc/bird/peers/myfirstpeer
protocol bgp myfirstpeer from dnpeers {
        neighbor 169.254.73.73%myfirstint as 4242424273;
}

protocol bgp myfirstpeer_v6 from dnpeers {
        neighbor fe80::7373%myfirstint as 4242424273;
}
conf

如果双方都启用了 M-BGP,这里只填写一个即可建立 IPv4 + IPv6 的路由会话。如果 VPN 是按照上述配置进行的,那么 %myfirstint 部分通常是可以省略的。

确认所使用的路由协议(通常是 BGP)可以建立连接

(请切换到 root。)

首先,重新加载路由配置:

birdc configure   # 或 birdc c
sh

通过以下命令,可以查看各个路由配置的状态:

birdc show protocol  # 或 birdc s p
Name       Proto      Table      State  Since         Info
device1    Device     ---        up     2020-05-13
kernel1    Kernel     master6    up     2020-05-13
kernel2    Kernel     master4    up     2020-05-13
static1    Static     master4    up     2020-05-13
static2    Static     master6    up     2020-05-13
myfirstpeer BGP        ---        up     2020-05-13    Established
myfirstpeer_v6 BGP        ---        up     2020-05-13    Established
sh

如果你看到新加入的 peer 右侧显示的是 “Established”,那么恭喜!你的 peer 已经完成并且双方可以通讯。如果不是 Established,可能代表路由或 VPN 配置出现了问题。请根据 bird 的提示信息进行错误排查。

通过以下命令,可以查看某条路由配置的详细信息:

birdc show protocol all myfirstpeer # 或 birdc s p a myfirstpeer
sh

FAQ

IP 后面的 /32 是什么意思?

这种类似 1.2.3.4/16 的条目出于 CIDR。它可以表示一个地址以及包括此地址在内的一个网络段。在设置 IP 地址时,这个地址代表欲设置的 IP,这个网络段则表示此 IP 所在的网络。 举个例子。如果在上文中你设置的地址是:

192.168.1.3/25
apache

这代表这么几件事:

  • 你设置的 IP 是 192.168.1.3
  • 这个 IP 所在的网络是 192.168.1.0 - 192.168.1.127,共 2^(32-25) = 2 ^ 7 = 128 个地址。

同时,系统会设置一条 scope link 的路由使得到达这些地址的包使用这个 IP 作为默认源 IP(为什么是默认?因为它可能会被覆盖),从这个 interface 发出。于是,ip route 的执行结果会有一行大概长这样:

192.168.1.3/25 dev this-interface proto kernel scope link src 192.168.1.3
apache

而 peer 也相当于加了一条特别的路由。例如上文的示例配置会产生这样的一条路由,把所有目标为 169.254.73.73 的包从 myfirstint 这个 interface 发出,源 IP 默认是 169.254.39.39ip route 中会出现大概这个样子的一行:

169.254.73.73 dev myfirstint proto kernel scope link src 169.254.39.39
apache

为什么上文 IPv4 要写一行 peer?因为 169.254.39.39/32 所在的网络(169.254.39.39 - 169.254.39.39)不包含 169.254.73.73。所以需要添加一行 peer 告诉系统如何到达这个 IP。为什么上文 IPv6 配置时没有写 peer?因为 fe80::3939/64 指代的网络(fe80:0:0:0:0:0:0:0 - fe80:0:0:0:ffff:ffff:ffff:ffff)包括 fe80::7373/64,所以系统已经知道如何到达 fe80::7373

结语

在第一个 peer 完成后,不久这个新的 AS 就会出现在这里这里或者许多 dn42/NeoNetwork NOC 的 looking glass 上。

这篇很长的 peering 教程到这里大概就告一段落了。六月又要到了,中国大陆的网络服务又到了一年好几度的维护期,希望各位的网络连接安好。

参考来源

  1. https://map42.0x7f.cc/

No comments:

Post a Comment