DN11 是受 DN42 启发而搭建的一个实验性网络,目前用于杭电范围内,对网络感兴趣的同学学习使用,DN11和DN42非常相似,他们之间的经验都有广泛借鉴意义。

背景

建 dn11 的时候遇到了一些小问题,在 fullmesh 的网络拓扑的情况下偶尔会出现几个节点连不上的情况,连不上了就直接连不上了,没有后话了。

实际上是可以通过绕路的方式联通的,这就要引入一些路由协议了,最早的构想是引入 BGP 协议的但是考虑了一下觉得这些东西的体量还是太大了,最后决定引入 ospf 协议,并且采取单一 area 的方式。

本文章将使用 bird2 配置 ospf over WireGuard,目的是给 dn11 成员提供一个 嘴对嘴的 ospf over WireGuard 配置教程。对于其他人可以忽略 dn11 规范部分来参考本教程进行配置。

OSPF 配置

先配置OSPF

这里我们选择 bird2 提供 ospf 支持,先配置 bird2

opkg install bird2
opkg install bird2c

在 openwrt 上,bird2 的配置文件默认地址在/etc/bird.conf

bird2 的默认配置文件很长,算是一个 all config 先给他放到一边去

mv /etc/bird.conf /etc/bird.conf.bak

然后我们新建一个自己的 bird.conf

vim /etc/bird.conf

给各位准备了配置文件模板,粘贴进去再改改就好了

log syslog all;
debug protocols all;

router id 172.16.255.4;

protocol device{
}

protocol kernel{
    ipv4 {
        export where proto = "wg";
    };
}

protocol ospf v2 wg {
    ipv4 {
        export all;
        import where net !~ 172.16.4.0/24;
    };
    area 0.0.0.0 {
        interface "wg*" {
            cost 5;
        };
    };
    area 0.0.0.4 {
        interface "br-lan";
    };
}
  • 每个路由设备的route id都是唯一的,route id本质上是一个 int32, 只是为了方便识别被.分割成了四段,需要提前约定。为了方便记忆和配置,这里随便取了一个网段将这个网段下的 ip 对应的 int 作为route id,dn11 对于route id有规范,起始 id 为 172.16.255.1,请按顺序往下申请
  • import where net !~ 172.16.4.0/24;这一行指定的网段的路由不会从 ospf 中学习,一般需要把这里配置成你的lan的网段,因为lan的路由早已由系统定义,不需要也不能由ospf来指定
  • export all;这一行指定了由 ospf 导出给其他路由学习的网段,如果你由 ospf 管理的接口中有不愿意导出的网段可以修改这里,这里导出全部
  • 后面紧跟着两个 area,每个 area 也有自己的 id,这两个 id 和 route id 一样仅仅是一个 int32 并不代表任何网络含义,仅仅是个名字,0.0.0.0是骨干 area ,在这里必须统一使用area 0.0.0.0
  • 在下一行我们用interface "wg*"指定了一些接口, 这里的*是通配符,这种写法指定了所有名字以 wg 开头的接口在这个area内,后续建立 wg 接口的时候要遵循这里的配置,如果你想使用其他名称也可以修改这里的配置
  • 在下一行,指定了一个cost,事实上即使不配置costospf 也会自动地指定一个cost,cost默认的值为 $\frac{100Mbps}{连接速度}$
  • area 0.0.0.4用于你的 lan,这里其实是可以省略的,只要你将你得 lan 接口加入area 0.0.0.0就行了,但是 dn11 目前定义每个人的 lan 都单独占用一个 area, 因此,需要一个唯一的 area 用于 lan, 请在文档中申请
  • 下一行的 interface 里指定了 lan 接口,对于 openwrt 旁路由,这里一般就是 br-lan,主路由一般就是 lan

编辑完配置文件后,就可以启动bird2了

service bird start

WireGuard 配置

下面建立 WireGuard 点对点连接,均在 openwrt 的 web 页面里操作

在要建立 WireGuard 连接的两个路由上要进行相对应的操作,操作的流程一致

新建接口

网络-接口-添加新接口...中新建一个 WireGuard 接口,以 wg* 的格式命名,作为示例,这里新建一个 wg0 add_interface

配置 WireGuard 接口

  • 私钥填写你自己的私钥,如果没有,可以使用wg genkey命令生成一个, 下面给出示例
  • 监听端口最好使用一个比较高的端口,可以随意指定,但是不同 WireGuard 接口监听的端口不能重复
  • IP 地址可以随意指定,这是 WireGuard 隧道中你的 IP 地址,dn11 对 WireGuard 隧道地址有规范,起始地址为172.16.128.0,每个人每次可以在文档中申请一个 /28 的网段,而每次使用一个 /32,例如172.16.128.16/32

记住这个值,在配置静态路由时会使用

先保存上述配置,点击连接重连该 WireGuard接口,此时接口公钥可以在状态-WireGuard状态里获取,下面继续配置这个接口,先添加一个peer

  • 公钥是建立点对点 WireGuard 连接的对方的公钥,对方在完成上述配置后就能获取到接口公钥,将对方的公钥填写在这里
  • 允许的 IP 填写0.0.0.0/0让 WireGuard 放通所有流量(如果你真的不想填这个,可以填你要访问的网段和组播地址,不推荐)
  • 路由允许的 IP 不要勾选,路由将由 OSPF 管理,不要让 WireGuard 来配置路由
  • 端点主机填对方主机地址,请实现配置好 DDNS
  • 端点端口填对方的 WireGuard 监听地址
  • 持续 Keep-Alive 仅当你的路由位于nat后,对方无法直连时勾选

配置完成后保存

config_interface

配置防火墙

对于 dn11 老成员,只需将这个新建的 WireGuard 接口分配到原先用于 WireGuard 的防火墙区域即可,然后就可以跳过这一步

没有配置过的话需要在 WireGuard 接口的配置中修改防火墙设置为“不指定或新建”,然后填写新的防火墙区域名称,保存配置,以创建一个新的防火墙区域

接下来转到 “网络-防火墙”,配置新建的防火墙区域。基本设置中,入站出站转发均改为接受,端口触发中,lan 到 WireGuard 接口和 WireGuard 接口到 lan 的转发均改为接受,保存并应用

配置静态路由

由于没有让 WireGuard 配置路由,在隧道IP地址中又选取了/32的网段,以至于没有到对面的隧道地址的路由,需要手动配置静态路由。

进入 Openwrt 的网络-静态路由页面添加静态 IPv4 路由

接口选择你正在配置的 WireGuard 接口,目标填写对方在 WireGuard 隧道的 IP,网关填写自己在 WireGuard 隧道的 IP,其他留空或保持默认,应用配置即可

static_route


!!!2023年4月25日更新

很遗憾上面的配置会出现一点问题

在 openwrt 手动添加的静态路由并不会被 bird 的 import all 读取到,以至于这几条静态路由并不会被发送给其他人。

这在大多数情形下是不会产生问题的,毕竟最关键的是对对方子网的访问,这里走对接口就没什么问题了。根本不需要关心到其他人的隧道的 隧道IP 的连通性。

不过最近出现了一点特殊情况,dn11 有一个成员内网服务比较复杂,暂时并不想共享到 dn11。于是他做了一个 nat,这个 nat 后的 ip 他又选择了隧道 ip。按照我们原来的方案,静态路由是手动在 op 的 uci 面板里添加的,bird 不会处理这个路由,结果就是没广播出去。

解决方案很简单,将所有原先添加在 uci 的静态路由转移到 bird 的 static 协议里再 import all;

示例:

protocol static {
    ipv4 {
        import all;
        export none;
    };
    route 172.16.128.2/32 via "wg0";
    route 172.16.128.32/32 via "wg1";
}

样例里的 ip (其实应该叫CIDR) 是对端的 ip


现在恭喜你完成了所有配置,没有意外的话稍等片刻应该就能访问到对面的网络了

如果仍然无法访问请转到故障排查

连接到更多路由

对每一个连接都需要一个独立的 WireGuard 接口,每个接口都会存在于一个独立的 WireGuard 子网。因此需要新建一个 WireGuard 接口来连接到第二个路由(比如说 wg1 )

  1. 配置 WireGuard

    与配置第一个 WireGuard 接口无异,注意监听端口和 IP 地址不能和其他接口重复

  2. 配置静态路由

    与配置第一个静态路由无异,注意网关和目标地址不能和前一个重复,且与 WireGuard 配置里的 IP 保持一致

故障排查

排查步骤

  1. 检查 WireGuard 连接是否连上,查看“状态-WireGuard状态”中对应接口的对端是否成功握手,图标是否亮起,如果没有说明 WireGuard 有问题
  2. 检查 OSPF 是否连上,查看“状态-系统日志”,拉到最新,如果 OSPF 卡在 Init 状态,说明静态路由配置有问题
  3. 上面两项都过了之后应该能 ping 通对面的路由,否则就是疑难杂症
  4. 能 ping 通对面路由但是 ping 不通对面 lan 的主机,转到配置防火墙

FAQ

  • Q: 没有公网 IPv4 能不能用 IPv6

    A: 可以,两边端点主机的 DDNS 都要做 AAAA 解析,不要上 A 解析,其他配置依然可以使用 IPv4

参考文档