WireGuard on OpenWrt+IPv6 组网

之前在路由器上使用 Zerotier 组网,效果还是不错的。但是两台路由器都是通过打洞连接的,效果可能并不是特别稳定。恰好我的两台路由器都是有 IPv6 地址的,那么何不试试使用 IPv6 地址直连的方式来进行组网呢?

安装 WireGuard 依赖

在两台路由器上均安装相关的依赖,只需要安装 luci-i18n-wireguard-zh-cn 系统即可自动将所有依赖安装完毕,完成之后必须要重启路由器。

opkg update
opkg install luci-i18n-wireguard-zh-cn

重新登录路由器管理页面,就可以在 状态 – WireGuard 中看到 WireGuard 连接的状态。

配置 WireGuard 接口

若使用 N 台路由器互相连接,则需要在每台路由器上设置 N-1 个对端,这样可以确保任意两台路由器之间能互相连接。此处假设使用两台路由器来配置互相连接,每台路由器上均需要设置一个对端。

路由器 A 的网段为 192.168.1.0/24,路由器 B 的网段为 192.168.2.0/24,我们选择为 WireGuard 网络设置网段 172.16.0.0/16,路由器 A 在 WireGuard 网络中的地址为 172.16.1.1,路由器 B 在 WireGuard 网络中的地址为 172.16.2.1。

路由器 A

进入 网络 – 接口 页面中,添加新的接口,接口名称填入 wg,协议需要选择 WireGuard VPN。

在 常规设置 中,点击生成密钥按钮,私钥栏中会自动生成内容,监听端口填写 12000,IP 地址填入 172.16.1.1/16,注意此处最好是带上网段。

在 高级设置 中,MTU 填入 1280,此处如果填大了会让两端连接速度变慢。

在 防火墙设置 中,新建一个 vpn 区域。

保存并应用,创建端口。

在 状态 – WireGuard 中可以看到路由器 A 的公钥,复制下来,等下要填入路由器 B 的对端设置中。

回到 网络 – 接口 中,编辑 wg 接口,在 对端 中,添加一个对端,描述可以写 OpenWrt2,公钥中填入路由器 B 的公钥(参考本文后面路由器 B 的设置获得公钥),允许的 IP 中填入 172.16.2.1/32 和 192.168.2.0/24,勾选路由允许的 IP,端点主机填入对端路由器的公网地址,端点端口填入对端路由器的端口 12000,持续 Keep-Alive 中可以填入自己喜欢的大小,如 15,保存并应用所有设置。

进入 网络 – 防火墙 – 常规设置 – 区域 中,编辑 lan 区域,将允许转发到目标区域勾选上 vpn 区域,将允许来自源区域的转发也勾选上 vpn 区域,保存;将 vpn 区域的转发改为接受,保存并应用设置。

在 网络 – 防火墙 – 通信规则 页面中,新增一项规则。
在 常规设置 中,名称填写 Allow-WireGuard,协议保持默认 TCP+UDP 即可,源区域选择 wan,目标区域选择 设备(输入),目标端口调入 WireGuard 监听端口 12000,操作选择接受,保存防火墙设置。

回到 网络 – 接口 页面中,重启 wg 接口。

路由器 B

进入 网络 – 接口 页面中,添加新的接口,接口名称填入 wg,协议需要选择 WireGuard VPN。

在 常规设置 中,点击生成密钥按钮,私钥栏中会自动生成内容,监听端口填写 12000,IP 地址填入 172.16.2.1/16,注意此处最好是带上网段。

在 高级设置 中,MTU 填入 1280,此处如果填大了会让两端连接速度变慢。

在 防火墙设置 中,新建一个 vpn 区域。

保存并应用,创建端口。

在 状态 – WireGuard 中可以看到路由器 B 的公钥,复制下来,等下要填入路由器 A 的对端设置中。

回到 网络 – 接口 中,编辑 wg 接口,在 对端 中,添加一个对端,描述可以写 OpenWrt1,公钥中填入路由器 A 的公钥(参考本文前面路由器 A 的设置获得公钥),允许的 IP 中填入 172.16.1.1/32 和 192.168.1.0/24,勾选路由允许的 IP,端点主机填入对端路由器的公网地址,端点端口填入对端路由器的端口 12000,持续 Keep-Alive 中可以填入自己喜欢的大小,如 15,保存并应用所有设置。

进入 网络 – 防火墙 – 常规设置 – 区域 中,编辑 lan 区域,将允许转发到目标区域勾选上 vpn 区域,将允许来自源区域的转发也勾选上 vpn 区域,保存;将 vpn 区域的转发改为接受,保存并应用设置。

在 网络 – 防火墙 – 通信规则 页面中,新增一项规则。
在 常规设置 中,名称填写 Allow-WireGuard,协议保持默认 TCP+UDP 即可,源区域选择 wan,目标区域选择 设备(输入),目标端口调入 WireGuard 监听端口 12000,操作选择接受,保存防火墙设置。

回到 网络 – 接口 页面中,重启 wg 接口。

完成

此时,稍等片刻,在两台路由器的 状态 – WireGuard 中即可看到另外一台路由器的连接信息。

此时两端路由器下的设备就都可以访问另一端路由器下的设备了,就像是在同一个局域网中。

如果需要更省心的操作,可以选择参考以下内容。

配合 DDNS 使用

当其中一个路由器重新连接网络之后,公网地址可能会发生变化,此时可能会无法连接 WireGuard,不过我们可以配合 DDNS 使用。
两台路由器均配置好 DDNS 之后,可以在 WireGuard 的对端配置中将端点主机的地址由 IP 地址更换为域名。
DDNS 配置好之后,这样即使路由器更换了 IP 地址也可以重新连接上。

配合 IPv6 使用

WireGuard 可完美兼容 IPv6 使用,只需要 DDNS 的域名只有 IPv6 地址记录即可,在这种情况下,WireGuard 就使用 IPv6 与其他路由器连接。只需将上文图中 172.27.0.0/16 的地址替换为 DDNS 域名即可。

IPv6 DDNS 的配置可以参考另一篇文章:OpenWrt IPv6 DDNS

配合 WatchCat 使用

当出现问题无法连通对端路由器的时候,如果有自动化的操作可以直接重启接口,就很方便了,省去手动重启操作。

opkg update
opkg install watchcat luci-app-watchcat luci-i18n-watchcat-zh-cn

在 服务 – WatchCat 页面中,增加一项配置,模式选择“重启接口”(有些固件可能会翻译为“重启实例”),周期可以设置为 1m,在路由器 A 上安装的 WatchCat 就填写路由器 B 的地址 192.168.2.1,在路由器 B 上安装的 WatchCat 就填写路由器 A 的地址 192.168.1.1,检查间隔填写 10s,接口的话就选择 wg,其余保持不动,保存应用所有设置。

这样,在路由器发现无法 ping 通对端路由器 1 分钟之后将会自动重启 wg 接口,保证两台路由器之间持续连接。

WireGuard on OpenWrt+IPv6 组网》有22个想法

  1. greenice

    可否详细讲讲ipv6的配置?
    网上看到ipv6的配置是:外网ipv4地址 —> 进入wireguard客户端ipv6 —> ddns-ipv6 —> 家里路由器wireguard的ipv6 —> lan-ipv4
    如果不通过ipv4,就是纯ipv6的怎么配置呢?

    回复
    1. Neo 文章作者

      你的意思是,通过WireGuard来使得客户端获得家里网络的IPv6地址吗?

      回复
      1. greenice

        也可以这么说吧.
        就是通过wireguard访问家里的ipv6网络
        如: 外网ipv6 —> wireguard(ipv6) —> 家里 ipv6网络

        回复
        1. Neo 文章作者

          简要思路:
          1. 若外网设备与家中网络都具有公网 IPv6 地址,则可以配置家中路由器防火墙,不使用任何工具直接访问家中网络。
          2. 若家中只有 OpenWrt 路由器具有公网 IPv6 地址,或者不想暴露家中 IPv6 网络到公网环境中,则可以考虑以下配置:首先外网设备与家中 OpenWrt 都拥有公网 IPv6 地址,这一步是为了确认外网设备可以与 OpenWrt 相连接;然后家中网络需要定义一个范围在 fd00::/8 内的 IPv6 ULA,如 fd99::/64;其次 WireGuard 服务器与客户端之间需要定义另一个 IPv6 ULA,如 fd88::/64;OpenWrt 配置 WireGuard 时,将自己的地址定义为 fd88::1/64,添加外网设备为客户端,为其配置允许的地址为 fd88::2/128;外网设备配置 WireGuard 时,将自己的地址定义为 fd88::2/128,添加 OpenWrt 路由器作为服务器,连接地址为 OpenWrt 的公网 IPv6 地址,允许的地址为 fd88::/64,fd99::/64;最后回到 OpenWrt 路由器上来,在防火墙自定义规则中添加 ip6tables 关于 WireGuard 网卡的转发、NAT 规则。这样外网设备应该就可以使用 fd99::/64 的地址来访问家中 IPv6 网络了。其实原理与纯 IPv4 环境下并没什么不同。
          以上就是大致思路了,你可以尝试一下,如果有什么问题,也欢迎继续讨论。

          回复
          1. xiaopo

            可以只用openwrt的公网ipv6作为server用来连接吧,话说ipv6之上的udp不知道和ipv4一样会不会也有QoS

            回复
            1. Neo 文章作者

              我现在就是用 OpenWrt 的公网 IPv6 地址作为服务器地址来连接的。
              据我自己使用观察来看,IPv6 上的 UDP QoS 情况要比 IPv4 好一些,联通对于 IPv6 UDP QoS 的情况要比移动好一些:我在使用两台 OpenWrt 通过 IPv6 地址互联传输大量文件后,移动会触发 UDP QoS,直接阻断外部 UDP 的传入,而联通仍表现正常。

              回复
              1. greenice

                详细解说下,用 OpenWrt 的公网 IPv6 地址作为服务器地址来连接的情况

                回复
                1. Neo 文章作者

                  其实很简单,给 OpenWrt 防火墙打开端口的时候注意选择 IPv6,填服务器地址的时候照着上文,替换其中 172.27.0.0/16 的地址为公网 IPv6 地址或者 DDNS 域名即可。

                  回复
              2. xiaopo

                嗯,感谢回复,可惜我这客户端不知道为啥一直开启不了IPv6,我再试试,我目前是wg外面套一层udp2raw,aes加密,目前ping <10ms,感觉还行。

                回复
                1. Neo 文章作者

                  😂我是想用 udp2raw 却用不成,目前还没定位到问题,难搞。也许和我用 IPv6 连接有关吧。

                  至于你的客户端的问题,得排查一下客户端是否可能正常访问 IPv6 网站,能否通过 https://test-ipv6.com 的测试;再在 https://ping.pe 测试一下服务器的 IPv6 端口能否被外网访问。

                  回复
                  1. xiaopo

                    压根就开启不了IPv6,更别提访问网站测试了,可能公司的电脑有什么限制还是咋滴不清楚。
                    udp2raw你是遇到啥问题了,你可以尝试一下在udp2raw的服务端开启–lower-level auto这个参数,去github wiki上去看看,编译的windows exe下的udp2raw是没这个参数的,我直接连就行了,我的问题是握手失败,一直resent syn,后面服务端加上–lower-level auto就ok了,祝你成功。

                    回复
                    1. Neo 文章作者

                      好的我也试试这个参数,谢谢。

                      公司里多人共用的互联网一般情况下,都不会开 IPv6 的,这个没有办法的。

          2. greenice

            第一点,感觉安全性差些,所以想要有vpn来连接,例如wireguard

            回复
          3. greenice

            按照第2点配置了,对端是客户端是手机,用ddns域名解析,有加端口号,但显示dns解析错误,地址是域名,如果是ipv4这样设置是没有问题的.不知是哪里设置问题?

            回复
            1. Neo 文章作者

              建议使用一个只有 AAAA 记录的域名。提示解析错误的话,可能是你所在网络的 DNS 服务器关闭了 IPv6 的解析,移动网络一般没有这个问题。建议在移动设备上填写服务器的域名;服务器上不填写移动设备的域名,只填写 PublicKey 和允许的地址。

              回复
  2. skywing

    你好,请问你的luci-app-wireguard版本是什么,我使用lede最新的源码编译出来的wireguard功能和你相比简陋了好多

    回复
    1. Neo 文章作者

      我用的就是 OpenWrt 21.02.3 官方固件:

      wireguard-tools             1.0.20210223-2
      kmod-wireguard              5.4.188-1
      luci-app-wireguard          git-20.244.42172-21563a2
      luci-i18n-wireguard-zh-cn   git-22.163.60897-a037a14
      luci-proto-wireguard        git-21.243.21928-71fe35c
      
      回复
  3. 钓月

    看了您的文章,终于把两个异地的openwrt通过wireguard连起来了,谢谢!不过现在有个问题,A(wireguard地址192.168.131.1)和B(wireguard地址192.168.131.5)两个openwrt路由器连接没问题,现在外网手机(wireguard地址192.168.131.2)通过wireguard连接到A,能够访问A所在的子网(192.168.31.0/24),但手机不能ping通B的wireguard接口地址(192.168.131.5),也不能访问B所在的子网(192.168.11.0/24),请指导下是怎么回事?应该怎么设置才能解决,谢谢

    回复
    1. Neo 文章作者

      很高兴能帮到你😁
      在你的描述中,路由器A需要承担一个中转的功能,我目前暂时还没有研究过此类的情况;不过我下午试了一下,你可以尝试在 网络 – 防火墙 – 自定义规则 页面中,新增以下规则:

      iptables -A FORWARD -i wg -j ACCEPT
      iptables -A FORWARD -o wg -j ACCEPT
      iptables -t nat -A POSTROUTING -o wg -j MASQUERADE
      

      在尝试之前请确保有其他方式可以远程控制路由器,以便恢复。

      回复
      1. 钓月

        太感谢了,试了你的方法,成功了!我一开始尝试在路由器A上设置静态路由解决这个问题,可能设置方法不对一直不行,也许设置对了就可以。防火规则有些复杂没有研究过,用了你的设置成功解决,再次感谢!

        回复
  4. 张雪有

    大佬出个视频教程把,2台OP异地组网,疫情太需要了。

    回复
    1. Neo 文章作者

      不太会做视频,比较麻烦,我试试把目前这个文字版的丰富一下,补一些详细步骤的截图。

      回复

发表回复

您的电子邮箱地址不会被公开。