WireGuard 没有服务端和客户端的区别,每个设备都叫做端点(Peer),端点之间通过公钥互相验证后才能建立连接,安全性很高。
在云服务器配置 WireGuard
安装 WireGuard,根据你的系统参考官方的安装方法:
sudo apt install wireguard
生成密钥对的方法:
生成一个私钥,务必保存好不能泄露:
$ wg genkey
iKREcYbZMsJTbRecTO4yw3ObPWeROzyzaNjXXBPW2H0=
使用上一步的私钥生成公钥:
$ echo iKREcYbZMsJTbRecTO4yw3ObPWeROzyzaNjXXBPW2H0= | wg pubkey
FCvk8Z+ilYzu/eMbSzzjxJx8wKv+60R1ceCNfMD8tTo=
WireGuard 是创建一个 tun 设备(简单理解为虚拟网卡也可以)进行网络连接,所以需要使用一个和当前局域网内不一样的网段,如果不小心使用了相同的网段,会无法和局域网联通的故障。
创建一个网络配置文件,可以命名为 wg0.conf
:
[Interface]
PrivateKey = iKREcYbZMsJTbRecTO4yw3ObPWeROzyzaNjXXBPW2H0=
Address = 172.16.1.1, fd01:72:16:1::1
ListenPort = 55189
MTU = 1280
172.16.1.1
就是云服务器的虚拟内网地址,这个地址段不能和系统中的 eth0
等网卡相同,否则会造成网络问题,推荐 wg0
使用一个完全不同类别的局域网段。
fd01:72:16:1::1
是虚拟的 IPv6 地址,如果当前的网络不支持 IPv6 就只使用 IPv4 的网络就行。
当然,也可以配置多个不同的网段,使用逗号隔开就行,比如 Address = 10.64.1.1, 172.16.1.1/24, fd01:72:16:1::1/64
MTU
设置为 1280
,如果不配置默认就是 1420
,CloudFlare 的 WARP 配置也是 1280
。
关于 MTU 的值,对于 IPv6 网络会有一个 PMTU 黑洞的问题,如果 MTU 设置过大会造成 TCP 超时重传,现象就是在 IPv6 下网络访问慢,详情信息可以参考 CloudFlare 的这篇文章 Fixing an old hack - why we are bumping the IPv6 MTU。
加载这个配置文件,会自动创建一个 WireGuard 专用的虚拟网卡 wg0
:
$ sudo wg-quick up wg0.conf
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 172.16.1.1/24 dev wg0
[#] ip -6 address add fd01:72:16:1::1/64 dev wg0
[#] ip link set mtu 1280 up dev wg0
到这里,云服务器上就配置好了一个 Peer 。
还需要开启转发 /etc/sysctl.d/10-ip-forward.conf
:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
执行 sysctl -p /etc/sysctl.d/10-ip-forward.conf
使得配置生效。
在局域网终端配置 WireGuard
如果终端机器是 Mac ,那么可以直接从 App Store 下载到官方的 WireGuard 客户端
安装好 WireGuard 客户端后,同样需要先创建一个密钥对,然后编辑配置文件,添加云服务器的 Peer
[Interface]
PrivateKey = 6PIoPNSZkMYp9dneVks4aZxYKoXK0yjEapcAgMDUEHU=
Address = 172.16.1.2
[Peer]
PublicKey = FCvk8Z+ilYzu/eMbSzzjxJx8wKv+60R1ceCNfMD8tTo=
AllowedIPs = 172.16.1.1/24
Endpoint = 12.12.12.12:55189
PersistentKeepalive = 15
这里的 172.16.1.2
就是 Mac 端使用的虚拟内网地址,和云服务器同一个网段。
底下的 Peer 就是云服务器的公钥和它的虚拟内网地址,这里多了一个 Endpoint
配置,必须是云服务器的公网 IP 和 wg0
监听的端口号,这样在 Mac 上连接 172.16.1.1
的时候,就等同于连接到 Endpoint
指向的 IP 和端口,当然 Endpoint
也可以是域名,当使用域名的时候,需要在 Interface 里设置 DNS
地址。
PersistentKeepalive
是保持心跳的时间间隔,这里设置为 15s ,避免长时间没有连接导致连接断开。
在云服务器配置 Peer
在云服务器的 wg0.conf
里,还需要增加 Mac 端的 Peer,这样才可以互相访问:
[Interface]
PrivateKey = iKREcYbZMsJTbRecTO4yw3ObPWeROzyzaNjXXBPW2H0=
Address = 172.16.1.1
ListenPort = 55189
[Peer]
PublicKey = s5ZkNXzMblHnPWb3mRIbcNtnDzMqapJisbVaLL1ERGo=
AllowedIPs = 172.16.1.2/24
PersistentKeepalive = 15
Peer 的配置就是 Mac 端的公钥和虚拟内网 IP ,这里没有 Endpoint
的信息,因为 Mac 端没有固定 IP 和域名。
因为没有 Endpoint
,所以只能由 Mac 端主动发起连接到云服务器,然后云服务器才能和 Mac 端通讯。
多个 Peer 端的配置
如果还有第三、第四个 Peer 端,就需要在云服务器的 wg0.conf
里增加多个 [Peer]
区段。
...
[Peer]
PublicKey = AD9Jn6xokLmTBLSSkduUDir7OSJHN7egBjkLJANAGGs=
AllowedIPs = 172.16.1.3
[Peer]
PublicKey = AjhflDGDSk9a6jw/HE4dZBfCyKkN/NOYllRaag5BeAs=
AllowedIPs = 172.16.1.4
AllowedIPs
需要写成 172.16.1.4/32
而不能是 172.16.1.4/24
,否则同一个局域网内的不同 Peer 会连不上云服务器。
常见问题
确保云服务器的防火墙放行了 wg0
的监听端口,WireGuard 使用的是 UDP 协议,设置端口放行规则的时候需要注意。
每个 Peer 的 [Interface]
MTU 配置需要一致。
如果使用 IPv6 连接,需要确保云服务器和局域网内都已经正确配置了 IPv6 的支持。
关于安全性
使用 psk
可以提高和端点之间的连接安全性。
生成一个预共享密钥:
$ wg genpsk
JRGdWhHESe7MPDkwZDYZg3J5loOYo4bn9CPwfhMaQcw=
在端点的 [Peer]
中添加生成的 psk
:
[Peer]
PresharedKey = JRGdWhHESe7MPDkwZDYZg3J5loOYo4bn9CPwfhMaQcw=
两边的端点都使用一样的 psk
才能正常连接。
https://www.wireguard.com/protocol/
通过中转实现异地局域网内机器互相访问
- Peer C:一台云服务器,有公网 IP
- Peer A:局域网机器,没有公网 IP
- Peer B:局域网机器,没有公网 IP
Peer A 和 Peer B 是两台异地局域网内的机器并且不可能有公网 IP,现在需要它们可以互相访问。
这个场景需要通过 Peer C 做流量中转,才可以让 Peer A 和 Peer B 互相通讯。
关于 [Interface]
中的 Address
:
- 掩码使用
/32
或者直接指定明确的 IP 地址
关于 [Peer]
中的 AllowedIPs
:
- 用于指定哪些 IP 或者地址段可以通过这个 Peer
- 对于终端端点,配置里的 Peer 是中转服务器,应该指定一个地址段,才能通过这个 Peer 中转访问到其他 Peer
- 对于中转服务器,配置里面的 Peer 是单独的终端端点,应该指定它的虚拟 IP 地址,掩码是
/32
或者不写掩码
具体例子看下面的配置:
Peer C 是作为中转服务器,虚拟 IP 是 172.16.1.1
:
[Interface]
PrivateKey = {PRIVATE_KEY}
Address = 172.16.1.1
ListenPort = 55189
MTU = 1280
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = {PUBLIC_KEY}
AllowedIPs = 172.16.1.2
[Peer]
PublicKey = {PUBLIC_KEY}
AllowedIPs = 172.16.1.3
Peer A 是终端端点,虚拟 IP 是 172.16.1.2
[Interface]
PrivateKey = {PRIVATE_KEY}
Address = 172.16.1.2
MTU = 1280
[Peer]
PublicKey = {PUBLIC_KEY}
AllowedIPs = 172.16.1.0/24
Endpoint = {PEER_C_PUBLIC_IP}:55189
PersistentKeepalive = 15
Peer B 是终端端点,虚拟 IP 是 172.16.1.3
[Interface]
PrivateKey = {PRIVATE_KEY}
Address = 172.16.1.3
MTU = 1280
[Peer]
PublicKey = {PUBLIC_KEY}
AllowedIPs = 172.16.1.0/24
Endpoint = {PEER_C_PUBLIC_IP}:55189
PersistentKeepalive = 15
配置要点
- Peer C 的
[Interface]
需要配置 IP 伪装,把wg0
发出的流量都伪装成eth0
的流量,才能达到中转的效果。 - Peer A 和 Peer B 的
AllowedIPs
,必须都是172.16.1.0/24
才能保证流量可以转发到 Peer C。
当 Peer A 在连接 Peer B 的时候,因为目标 IP 地址属于 172.16.1.0/24
的范围,所以流量会被转发给 Peer C,这样就实现了异地局域网的互相访问。
Peer A 在本地开启一个监听 HTTP 服务 0.0.0.0:1313
,在 Peer B 就可以通过 http://172.16.1.2:1313
访问到 Peer A 开启的 HTTP 服务。
使用 systemd 创建自启动服务
适用于 Debain 以及使用 systemd 作为服务管理的 Linux 发行版。
创建一个
wg0
的服务配置:$ sudo systemctl enable [email protected] Created symlink /etc/systemd/system/multi-user.target.wants/[email protected] -> /lib/systemd/system/[email protected].
创建
wg0.conf
配置文件:wg0.conf
必须放在/etc/wireguard/
,因为wireguard-tools
是读取这个路径下的wgX.conf
配置。设置配置文件的访问权限为
600
:sudo chmod 600 /etc/wireguard/wg0.conf
使修改后的配置文件后生效:
sudo systemctl daemon-reload
启动
wg0
:sudo systemctl start wg-quick@wg0