光阴冢 赛博空间的自留地

使用 WireGuard 配置一个 IPv6 Tunnel

WireGuard 可以用来建立安全的点对点的连接。INRIA 的研究人员于 2019 五月发表了对于该协议的一份机器证明

We contribute proofs for correctness, message secrecy, forward secrecy, mutual authentication, session uniqueness, and resistance against key compromise impersonation, identity mis-binding, and replay attacks.

更换了实验室(物理)以后,丧失了连接到教育网 IPv6 的能力,只能在寝室或者是使用跳板服务器,非常不方便。于是想通过 WireGuard 建立一个从实验室电脑到机房服务器的隧道,实现在本机上也能访问公网 IPv6。

安装

实验室电脑是 Arch Linux,内核用的是官方内核,因此装好 wireguard-toolswireguard-arch 即可。

在 Ubuntu 上则需要自己添加相应的源再安装:

1
2
sudo add-apt-repository ppa:wireguard/wireguard
sudo apt install wireguard

配置

配置的方法网络上已经有很多教程,比如 WireGuard 的官方教程,Linode 的教程和 Arch Linux Wiki 上的教程,都比较靠谱,并且大同小异。

另外,如果没有装 linux-headers 的话,在 ip link add dev wg0 type wireguard 时会报 Error: Unknown device type. 错误,务必装上自己内核版本对应的 headers 。

一个重要的地方

Peers 块中的 AllowedIPs 不能随意设置

  • 如果是 Server 端的配置,需要允许拥有对应公钥的设备 IP ,并且设置好掩码。
  • 如果是 Client 端的配置,看情况配置:
    • 只是为了异地组网,把不同机器连起来,则只需要填入该子网的 IP 段
    • 想要访问内(外)网络,Server 在内(外)网,则需要将要访问的对应的内(外)网 IP 段填入。
      • 经典的配置就是 0.0.0.0/0 , ::/0,本机上所有流量都被转发给服务器了。(服务器作为一个 VPN Server)
      • 如果想在外地连入校内网,则可以写 10.0.0.0/8

AllowIPs 这个字段通常仿佛都是人畜无害的(只是来个流量再判断一下 IP 决定是否 drop 嘛)。但是在 WireGuard 上是有副作用的:它会添加路由,以便能够使用 WireGuard 建立的那个网络。(当然了!)

所以,想象一下,如果在 Server 上设置了 AllowedIPs = 0.0.0.0, ::/0,会发生什么?

您好!我想借用一下机房的钥匙。

其实,某个时刻两台机器应该还是通过 wg 联通着的;但是服务器已经没办法通过别的方式正常连接到了。

当时走的弯路

  • 明明是要配置 NAT IPv6 路由的,可是一直没有给这俩分配 IPv6 地址。
  • 跑了一次机房。

最终配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Server
[Interface]
ListenPort = [PORT]
PrivateKey = <PrivateKey>
Address = 192.168.0.2/24, fd23:23:23::2/64
# 用 iptables 设置包转发,注意将 <dev-name> 替换为 Server 上对应的网卡设备名字
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o <dev-name> -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o <dev-name> -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o <dev-name> -j MASQUERADE; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o <dev-name> -j MASQUERADE

[Peer]
PublicKey = <PublicKey>
# 只允许一个 IP
AllowedIPs = 192.168.0.3/32, fd23:23:23::3/128
Endpoint = <IP>:[PORT]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Client
[Interface]
ListenPort = [PORT]
PrivateKey = <PrivateKey>
Address = 192.168.0.3/24, fd23:23:23::3/64

[Peer]
PublicKey = <PublicKey>
# IPv4 正常用就好了,目的只是 enable IPv6。
# 这里我偷了一下懒,把所有 IPv6 流量都指向服务器了,这样一来客户端本地链路上的 IPv6 就无法正常访问了(不过也通常没什么用)。
AllowedIPs = 192.168.0.2/32, ::/0
Endpoint = <IP>:[PORT]

最后终于:

WG IPv6