WireGuard 搭建方法与使用教程

2019-04-11 8352点热度 35人点赞

最近有朋友推荐我一款工具 WireGuard ,不得不说这个工具的确非常好用,作为 OpenVPN 的咸鱼使用者用这个实在太轻松了。所以在此推荐并记录


1 、 WireGuard 简介

WireGuard 是一个利用现有社会最先进的加密技术而产生的非常简单和快捷的 VPN 工具。它的目标是比 IPsec 更快,更简单,更精简,更易用,同时避免大规模配置 IPsec 的麻烦事。同时 WireGuard 也打算比 OpenVPN 更高效。 WireGuard 设计为通用 VPN,可在嵌入式设备和常见计算机上运行,适用于多种不同情况。 WireGuard 最初是为 Linux 内核发布的,而现在 WireGuard 已经可广泛部署并且跨平台支持。 WireGuard 目前正在大力发展,但 WireGuard 已经被认为是业内最安全,最易用和最简单的 VPN 解决方案。

官网链接 [ 链接 ]
Arch Wiki [ 链接 ]


2 、 WireGuard 基本概念

首先使用 WireGuard 你需要在系统中创建一块虚拟网卡,并配置好这个虚拟网卡的 IP 地址,掩码,网关不需要配置(可以使用 wg-quick@ 自动化)

然后你使用 WireGuard 连接另一台设备,两台互相 peer 对方并验证各自的公钥私钥是否正确,全部正确后成功建立 peer(可以使用 wg-quick@ 自动化)

建立成功后,所有前往虚拟网卡的流量都将被重新封装后发往另一台设备,由另一台设备解封装然后得到数据报文并在内部查找路由并匹配报文目的地。(可以使用 wg-quick@ 自动化)

以上为建立一个 WireGuard VPN 链接的过程,建立好后,A 设备与 B 设备互相需要保证虚拟网卡的 IP 在相同网络位的地址段中,并且这个地址段被 WireGuard 的配置文件 AllowedIPs 所允许通过

如果你试图从 A 设备下属子网访问 B 设备的对端子网,你需要在 A 设备上配置系统路由,将系统三层网络的路由目的地指向对端虚拟 IP 地址,出接口为虚拟网卡,并且这个地址段必须被对方 WireGuard 的配置文件 AllowedIPs 所允许通过
(当然你也可以使用 SNAT 进行地址伪装,通常来说防火墙配置 masquerade 即可,还需要 ip_forward)

最后,在 WireGuard 中的所有数据报文,都采用 UDP 的方式发送。

(个人观感:OSPF Area = WG Config | OSPF Peer = WG Peer | OSPF route = WG AllowedIPs)


3 、 WireGuard 安装

官方的安装教程为 [ 链接 ]

注意 windows 没有官方程序 官方工具 Windows 版本建议下载 MSI,本例使用第三方制作的 TunSafe 程序 [ 链接 ]

TunSafe 在 Windows 环境中安装时,需要安装 TunSafe Client 与 TunSafe-TAP Ethernet Adapter (GPL) 两个程序
前者是 GUI 界面,后者是程序所必需的 TAP 网卡(并且需要翻墙下载安装包)

安装好后可以设置成自动开启,并配置为系统服务

如果是 IOS / Android 系统,可以使用应用商店主动获取,应用 WireGuard 的图标为官网图标,也可以使用 TunSafe 客户端。

而 Linux 部分,官方有明确的安装说明。唯一注意 CentOS 7 和 Ubuntu 14 等版本的默认内核版本不支持自定义网卡 type 所以必须升级内核到 4.18 及更高版本。

Ubuntu 20 的安装很简单

sudo apt install -y wireguard

4 、 WireGuard 主端配置

关于如何配置,官方其实有快速安装说明 [ 链接 ]
但由于官方说明实在是很模糊,所以我还是重新强调一些关键点

首先你需要一个文件夹存放 WireGuard 的配置文件,本文路径为 /etc/wireguard/ 这个文件夹(默认安装就生成)

然后你需要知道如何生成一对公钥与私钥,命令可以使用下面这个
(私钥为 privatekey 公钥为 publickey)

wg genkey | tee privatekey | wg pubkey > publickey && cat privatekey && cat publickey

以及本文的配置环境如下,括号中携带的是对应主机拥有的其他网段

主机 192.168.0.100 <---> 192.168.0.200

虚拟 172.16.1.11:8001 ( 172.16.11.0/24 ) <---> 172.16.1.12:8002 ( 172.16.12.0/24 )

建议练习手动步骤来理解 Wireguard 如何工作,如果懒人想直接使用自动方案,跳过本章节下拉从 6 开始


4.1 、 WireGuard 的主端配置

开始前,为了方便,我们创建一个 WireGuard 配置文件(等价参考,可以纯手动命令启动同等配置服务)

vim /etc/wireguard/wg0.conf
[Interface]
Address = 172.16.1.11/24
ListenPort = 8001
PrivateKey = eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=

[Peer]
PublicKey = YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=    #对端 Publickey
AllowedIPs = 172.16.1.12/32,172.16.12.0/24
Endpoint = 192.168.0.200:8002
PersistentKeepalive = 25

首先我们需要创建一个网卡配置文件(此配置名 wg0,等价参考上方 文件名)

ip link add dev wg0 type wireguard
检查效果
root@localhost:~# ip link add dev wg0 type wireguard

root@localhost:~# ip address
******
3: wg0: <POINTOPOINT,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 1000
    link/none

然后我们需要给这个网络接口配上 IP 地址(此配置 172.16.1.11/24,等价参考上方 Address)

ip address add dev wg0 172.16.1.11/24
检查效果
root@localhost1:~# ip address add dev wg0 172.16.1.11/24

root@localhost1:~# ip address
******
3: wg0: <POINTOPOINT,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 1000
    link/none
    inet 172.16.1.11/24 scope global wg0
       valid_lft forever preferred_lft forever

其次我们创建一个私钥,用于 Wireguard 使用,并配置权限禁止他人访问
(默认 /etc/wireguard/ 其实就已经 700 权限了)

wg genkey | tee /tmp/private-key
chmod 600 /tmp/private-key
wg set wg0 private-key /tmp/private-key listen-port 8001
检查效果
root@localhost1:~# wg genkey | tee /tmp/private-key
eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=

root@localhost1:~# ll /tmp/private-key
-rw------- 1 root root 45 Oct 20 08:00 /tmp/private-key

root@localhost1:~# wg
interface: wg0
root@localhost1:~# wg set wg0 private-key /tmp/private-key listen-port 8001
root@localhost1:~# wg
interface: wg0
  public key: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  private key: eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=
  listening port: 8001

接着我们启动该网络接口,使之正式可用

ip link set wg0 up
检查效果
root@localhost1:~# ip link set wg0 up

root@localhost1:~# ip address
******
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 56:00:03:a5:b1:96 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic enp1s0
       valid_lft 84928sec preferred_lft 84928sec
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 172.16.1.11/24 scope global wg0
       valid_lft forever preferred_lft forever

root@localhost1:~# wg
interface: wg0
  public key: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  private key: eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=
  listening port: 8001

此时我们创建好了本地节点,还需要宣告哪些节点是我们的邻居,才能建立网络连接。

同时注意在查看 Wireguard 信息时,主端的 Publickey 为 OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=


4.2 、 WireGuard 的对端配置

在对端设备的配置和主端一致,所以在此依然创建一个 WireGuard 配置文件用于参考

vim /etc/wireguard/wg0-peer.conf
[Interface]
Address = 172.16.1.12/24
ListenPort = 8002
PrivateKey = OO6/vtQB83h2/1XcwfZ0OpPr9ATfWviEqdQyWdtjE0c=

[Peer]
PublicKey = OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=    #主端 Publickey
AllowedIPs = 172.16.1.11/32,172.16.11.0/24
Endpoint = 192.168.0.100:8001
PersistentKeepalive = 25

这里直接快速创建

ip link add dev wg0 type wireguard
ip address add dev wg0 172.16.1.12/24
wg genkey | tee /tmp/private-key
chmod 600 /tmp/private-key
wg set wg0 private-key /tmp/private-key listen-port 8002
ip link set wg0 up

现在我们创建好了对端的配置,检查一下 Wireguard 信息

root@localhost2:~# wg
interface: wg0
public key: YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=
private key: OO6/vtQB83h2/1XcwfZ0OpPr9ATfWviEqdQyWdtjE0c=
listening port: 8002

4.3 、邻居关系的建立

我们现在有了两个 Wireguard 服务,分别在两台服务器上

主端
root@localhost1:~# ip address
******
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 56:00:03:a5:b1:96 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic enp1s0
       valid_lft 84928sec preferred_lft 84928sec
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 172.16.1.11/24 scope global wg0
       valid_lft forever preferred_lft forever

root@localhost1:~# wg
interface: wg0
  public key: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  private key: eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=
  listening port: 8001
对端
root@localhost2:~# ip address
******
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 56:00:03:a5:b1:96 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.200/24 brd 192.168.0.255 scope global dynamic enp1s0
       valid_lft 84928sec preferred_lft 84928sec
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 172.16.1.12/24 scope global wg0
       valid_lft forever preferred_lft forever

root@localhost2:~# wg
interface: wg0
  public key: YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=
  private key: OO6/vtQB83h2/1XcwfZ0OpPr9ATfWviEqdQyWdtjE0c=
  listening port: 8002

对于主端,我们需要填写 对端 Publickey 进行配置,反之对端则使用 主端 Publickey 进行配置。

主端
wg set wg0 peer YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI= allowed-ips 172.16.1.11/32,172.16.11.0/24 endpoint 192.168.0.200:8002 persistent-keepalive 25

查看效果
root@localhost1:~# wg
interface: wg0
  public key: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  private key: eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=
  listening port: 8001

peer: YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=
  endpoint: 192.168.0.200:8002
  allowed ips: 172.16.1.12/32, 172.16.12.0/24
  transfer: 0 B received, 148 B sent
  persistent keepalive: every 25 seconds
对端
wg set wg0 peer OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk= allowed-ips 172.16.1.11/32,172.16.11.0/24 endpoint 192.168.0.100:8001 persistent-keepalive 25

查看效果
root@localhost2:~# wg
interface: wg0
  public key: YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=
  private key: OO6/vtQB83h2/1XcwfZ0OpPr9ATfWviEqdQyWdtjE0c=
  listening port: 8002

peer: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  endpoint: 192.168.0.100:8001
  allowed ips: 172.16.1.11/32, 172.16.11.0/24
  transfer: 0 B received, 148 B sent
  persistent keepalive: every 25 seconds

两侧创建完毕后,我们离实现 Wireguard 的互联互通只差两步 路由 和 防火墙

对两侧的主机添加对端路由,路由为临时规则,重启消失

主端
ip route add 172.16.12.0/24 dev wg0
对端
ip route add 172.16.11.0/24 dev wg0

对两侧的相关端口均需要放行,配置并保存即可。

主端
ufw allow 8001/udp
ufw reload

对端
ufw allow 8002/udp
ufw reload

创建完毕后,如果涉及到本地路由映射则需要开启转发(本例存在 172.16.11.0/24 和 172,16.12.0/24)

sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
sed -i "s/DEFAULT_FORWARD_POLICY=\"DROP\"/DEFAULT_FORWARD_POLICY="ACCEPT"/g" /etc/default/ufw
ufw disable
ufw enable
#额外记得你还需要将防火墙两侧端口的流量放通,相关用户的网关路由也需要打通
#如果是子网上网,还需要额外配置 NAT 对源地址进行修改。

现在我们就算配置完毕了,检查一下网络连通性,和服务状态(任意哪端查看都可)

root@localhost1:~# ip address
******
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether 56:00:03:a5:b1:96 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic enp1s0
       valid_lft 84928sec preferred_lft 84928sec
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 172.16.1.11/24 scope global wg0
       valid_lft forever preferred_lft forever

root@localhost1:~# wg
interface: wg0
  public key: OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=
  private key: eDAKXVHliMhTsbAeodifK8insJNM633MwMyYWl8FHFw=
  listening port: 8001

peer: YJsN6XOCY+9nTFXuTjtKHnh/Xxq6bLEtH8iI9s3TEzI=
  endpoint: 192.168.0.200:8002
  allowed ips: 172.16.1.12/32, 172.16.12.0/24
  latest handshake: 1 minute, 50 seconds ago
  transfer: 1.23 KiB received, 1.14 KiB sent
  persistent keepalive: every 25 seconds

root@localhost1:~# ping 172.16.1.12
PING 172.16.1.12 (172.16.1.12) 56(84) bytes of data.
64 比特,来自 172.16.1.12: icmp_seq=1 ttl=64 时间=5.0 毫秒
^C
--- 172.16.1.12 ping 统计 ---
已发送 1 个包, 已接收 1 个包, 0% 包丢失, 耗时 0 毫秒
rtt min/avg/max/mdev = 5.023/5.023/5.023/0.000 ms

root@localhost1:~# ping 172.16.12.1
PING 172.16.12.1 (172.16.12.1) 56(84) bytes of data.
64 比特,来自 172.16.12.1: icmp_seq=1 ttl=64 时间=5.0 毫秒
^C
--- 172.16.12.1 ping 统计 ---
已发送 1 个包, 已接收 1 个包, 0% 包丢失, 耗时 0 毫秒
rtt min/avg/max/mdev = 5.016/5.016/5.016/0.000 ms

root@localhost1:~# route -n
内核 IP 路由表
目标            网关            子网掩码        标志  跃点   引用  使用 接口
0.0.0.0         192.168.0.1     0.0.0.0         UG    100    0        0 enp1s0
172.16.1.12     0.0.0.0         255.255.255.255 UH    0      0        0 wg1
172.16.12.0     0.0.0.0         255.255.255.0   U     0      0        0 wg1

你还可通过 iproute2 来控制不同的系统路由表,查看方式如下(系统默认 table 255)

root@localhost1:~# ip route list table 255

broadcast 172.16.1.0 dev wg0 proto kernel scope link src 172.16.1.11
local 172.16.1.11 dev wg0 proto kernel scope host src 172.16.1.11
broadcast 172.16.1.255 dev wg0 proto kernel scope link src 172.16.1.11
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 192.168.0.0 dev enp1s0 proto kernel scope link src 192.168.0.100
local 192.168.0.100 dev enp1s0 proto kernel scope host src 192.168.0.100
broadcast 192.168.0.255 dev enp1s0 proto kernel scope link src 192

其他和 fwmark table 相关的建议阅读 [ 链接 ]
其他和 Ubuntu 路由转发 相关的建议阅读 [ 链接 ]


4.4 、 CentOS 7 的 Wireguard 主端网络配置

题外话,CentOS 7 相关部分操作可能还会麻烦一点,如下所示。

vim /etc/sysconfig/network-scripts/ifcfg-wg0
DEVICE=wg0
TYPE=wireguard
IPADDR=172.16.1.11
NETMASK=255.255.255.0
ONBOOT=yes
NAME=wg0
ZONE=public

接着我们需要创建一个网卡路由文件(由于对方存在 172.16.12.0/24 这个 IP 地址段的前提下)

vim /etc/sysconfig/network-scripts/route-wg0
172.16.12.0/24 via 172.16.1.12 dev wg0

最后我们需要允许本机的 NAT 转换,并允许系统进行 IPV4 转发

firewall-cmd --add-port=8001/udp --zone=public --permanent
firewall-cmd --add-masquerade --zone=public --permanent
firewall-cmd --reload

5 、 WireGuard 配置说明

[Interface]
Address = 172.16.11.0/24  #本机地址与掩码位数 (IPV4)
Address = fec0:1234::1/24  #本机地址与掩码位数 (IPV6)
ListenPort = 8002  #本机监听 WireGuard 端口
PrivateKey = 填写本机的 privatekey 内容  #本机加密私钥
DNS = 1.1.1.1  #强制本机使用 DNS 服务器
MTU = 1280  #强制本机使用指定 MTU 值 
#Table = 100 #强制本机 将要注入系统的 路由条目 的 table 指定为 100 ( 系统默认为 255 和 254 )
#PreUp =     #启动前操作
#PostUp = ip rule add from 10.10.1.0/24 table 100 ; ip rule add from 10.10.2.0/24 table 100
#PreDown = ip rule delete from 10.10.1.0/24 table 100 ; ip rule delete from 10.10.2.0/24 table 100
#PreDown =    #停止后操作

[Peer]
PublicKey = 填写对端的 publickey 内容  #本机加密的对端公钥(加密后数据仅对端可以解密)
AllowedIPs = 172.16.1.11/32  #本机允许的对端设备的 IP 地址段,其实就是在本机中这个虚拟网卡接收到对端发来的源地址都允许有哪些设备 IP 地址(多 peer 不可重复)
Endpoint = another.domain.name:8001  #对端 WireGuard 的外部 IP(可以有一侧的 IP 地址是虚假的公网 IP)
PersistentKeepalive = 25   #当会话存在一端 IP 地址为 NAT 地址或虚假公网 IP 地址时,由该方阶段性每 25 秒发送 keepalive 报文保持会话的可用性,防止被设备终止。

在上方基础上,额外要注意的是

1 、如果你存在多个 [Peer] ,则在下面直接增加一个新的 [Peer] 栏目

2 、如果多个 Peer 存在不同的 IP,请不要让 AllowedIPs 存在重叠的 IP 地址段(比如配置多个相同/24 只有一个生效)

3 、 Endpoint 既支持以域名的方式访问,也支持以 IP 的方式访问。

4 、会话链接的建立只要保证两端数据在一台设备上成功协商,即使动态 IP 地址变更也不会影响 VPN 的稳定性。

5 、 ListenPort 不添加会自动生成高位端口用来 peer,以及主从结构下,从端不填写 listenport 。

6 、 Table 参数可以使用 auto 和 off,两者分别对应 自动注入路由 和 禁止注入。不配置采用 auto

7 、如果你是主从结构,需要让 从端 在配置中将 从端 的 "AllowedIPs =" 补写一条内容 0.0.0.0/0,::0 以允许所有流量

8 、前面标注 # 的五条内容,其中有内容的三条作为 iproute2 独立路由表的使用方式,通过指定路由条目的 table 与 ip rule 联动控制策略流量转发。

9 、 PreUp,PostUp,PreDown,PostDown 这四个命令参数,是作为 wg-quick 快速设置/删除接口之前/之后由 bash(1)执行的四条命令,常用于配置自定义 DNS 或防火墙规则。 特殊字符串 %i 作为变量替代所控制的 INTERFACE 配置名。 每个命令参数都支持多条命令,参数内的多条命令将按前后顺序依次执行,分隔符为 ; 分号。


6 、 WireGuard 的快速启动配置文件

上面的操作做完发现太繁琐了么,Wireguard 是有提供一个标准的 Systemd 服务文件来提供启动护航的

对于 [email protected] 服务文件来说,它会调用 /usr/bin/wg-quick 读取 /etc/wireguard/*.conf 后启动

服务/命令/配置文件/网卡虚拟接口名 对应关系如下

服务: [email protected]
命令: /usr/bin/wg-quick up myserver
配置: /etc/wireguard/myserver.conf
接口: myserver

而且平时使用的常见方案就是写好配置文件,通过官方的服务配置文件直接启动(自动模式推荐)
配置文件中的 %i 为 Systemd 默认参数,指代服务名 wg-quick@ 后的变量

vim /etc/wireguard/myserver.conf
[Interface]
Address = 172.16.1.12/24
ListenPort = 8002
PrivateKey = OO6/vtQB83h2/1XcwfZ0OpPr9ATfWviEqdQyWdtjE0c=

#PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
#PreDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE

[Peer]
PublicKey = OPC1/cVCnvbw3wQg6CPJB5IC0ZZLf+JwRD3V3MqFYFk=    #主端 Publickey
AllowedIPs = 172.16.1.11/32,172.16.11.0/24
Endpoint = 192.168.0.100:8001
PersistentKeepalive = 25

此配置完毕后 配置文件名为 myserver ,可以直接输入 wg-quick up myserver 测试启动进程
(如果启动失败可以先 down 一次再 up 一次)
(如果你是 iptables 则使用两条 iptables 命令来配置防火墙允许转发的规则,去掉前面的#并记得修改 enp1s0 为当前系统公网网卡即可)

注意 Firewalld 这样启动后网卡本身是没有防火墙区域的,你需要手动绑定一个区域

firewall-cmd --zone=external --add-interface=myserver --permanent
firewall-cmd --zone=external --add-masquerade --permanent
firewall-cmd --reload

而后涉及开机启动时,直接配置开机启动即可(注意本例调度了网络等待服务,同时修改了默认等待时间)

systemctl enable wg-quick@myserver
systemctl start wg-quick@myserver

有时候可能你的开机启动失败了,这可能是因为没有成功找到对端地址(比如网卡未启动),所以需要额外配置网络等待服务

systemctl enable NetworkManager-wait-online.service
sed -i 's/--timeout=30/--timeout=10/g' /usr/lib/systemd/system/NetworkManager-wait-online.service && systemctl daemon-reload

7 、常见的小问题

7.1 、路由写入冲突

很多人可能在 配置文件 中放进去多个 peer ,而放进去 peer 时使用了相同或相似的 AllowedIPs 如下例
(比如为了方便使用更短网络位的路由条目)

[Peer]
AllowedIPs=172.16.1.0/24,172.16.11.0/24

[Peer]
AllowedIPs=172.16.1.0/24,172.16.12.0/24

此时 Wireguard 在读取配置文件时,会发现路由表已经存在 172.16.1.0/255.255.255.0 条目,如果新增第二个 peer 会产生冲突。
(不同配置文件会产生两条路由,因为下一跳不一致)

目标            网关            子网掩码        标志  跃点   引用  使用 接口
172.16.1.0      0.0.0.0         255.255.255.0     U     0      0      0 myserver

所以我们在查看时,会出现只有一个 peer 配置正常的情况,同时因为 AllowedIPs 参数失败的原因,会导致链路不通

peer: 
  endpoint: 192.168.1.11:26001
  allowed ips: 172.16.1.0/24,172.16.11.0/24

peer: 
  endpoint: 192.168.1.12:26002
  allowed ips: 172.16.12.0/24

而对此的方式,建议是分拆成两个配置文件,或者细分具体主机内容,比如修改成如下方案,可以让网络恢复正常

[Peer]
AllowedIPs=172.16.1.11/32,172.16.11.0/24

[Peer]
AllowedIPs=172.16.1.12/32,172.16.12.0/24

还可以不使用 配置文件 与 wg-quick 的方式,使用 纯命令行 的方式启动
此时可以自定义 AllowedIPs 和 Route,AllowedIPs 的效果等同于 AccessList 规则策略 ,route 的效果则等同于 主机路由(即 wg-quick 启动时识别 allowedIPs 并依此自动添加路由,如添加失败则启动失败)
例如我们可以 AllowedIPs = 0.0.0.0/0 但 Route 使用 ip route add 172.16.11.0/24 dev wg0
但仍然不可以让 单实例 的 两个 Peer 使用重叠的 AllowedIPs

对于一些特殊操作,比如尝试 Wireguard + OSPF/BGP 等方式使用的用户,则需要利用 Table 分割不同 Peer AllowedIPs 的路由,同时因为 AllowedIPs 放行了相关路由,所以可以顺利通过虚拟网卡。


7.2 、 Wireguard 会话保持

Wireguard 默认的运行模式是 对等体(双方身份地位一致)

此时双方均需要指定 [peer] Endpoint= 参数,保证离线后可以自行连接对方。

当一方 缺乏稳定的公网端口 时,无法让对端主动连接过来,此时则需要变成 主从结构 来使用

主端配置 ListenPort ,移除 Endpoint ,从端不配置 ListenPort,并配置 keepalive

此时解决方案主要有两种。

1 、客户端 侧额外配置 [peer] keepalive= 参数,主动提交新 IP 给服务端,同时服务端注释该客户端的 [peer] Endpoint=
2 、服务端 侧额外配置 DDNS 动态域名,并以域名的方式填写 [peer] Endpoint=

前者是常用办法,尤其是客户端 存在 NAT 情况时,无法提供公网端口。
但是额外注意 Wireguard 虽然会根据动态客户端新的数据包而更新,但如果动态客户端更新报文丢失,会导致连接中断

后者是则是 DDNS 的解决办法,额外多的内容是使用系统 dns 解析域名,同时使用解析后的 IP 地址进行访问。
但是额外注意 域名解析 虽然 Linux 没有缓存解析结果,但是 wireguard 解析后,除非动态客户端有新地址的数据包上联,否则存在一段时间的等待,甚至一直卡顿。这里就需要给 服务端 配置 [peer] keepalive= 参数,让服务端周期对客户端发送数据报文尝试,在某个时间周期后,服务端将重新解析 DNS 。

额外一条,运营商可能会对家宽的 UDP 进行限制,导致 即使拨号拥有公网 IP 但 仍需使用动态端口


7.3 、 IPV6 路由消失

通常来说,我们做了端口转发,是使用三条参数修改
修改后我们就可以正常使用了,大多出现的情况是 NAT 相关。

net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

而有时候我们会遇到 IPV6

root@drive:~# ping6 2400:3200::1
ping6: connect: network is unreachable

此时我们查看路由检查网络问题

root@localhost:~# ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2408:8002:2008:2882::/64 via fe80::1 dev enp1s0 proto ra metric 100 pref high
fe80::/64 dev enp1s0 proto kernel metric 100 pref medium

oot@localhost:~# route -n6 | grep enp1s0
Destination                    Next Hop                   Flag  Met Ref Use If
2408:8002:2008:2882::/64       fe80::1                    UG    100 1     0 enp1s0
fe80::/64                      ::                         U     100 5     0 enp1s0
2408:8002:2008:2882::/128      ::                         Un    0   3     0 enp1s0
2408:8002:2008:2882::2882/128  ::                         Un    0   5     0 enp1s0
fe80::/128                     ::                         Un    0   3     0 enp1s0
fe80::222/128                  ::                         Un    0   5     0 enp1s0
fe80::2408:8002:2008:2882/128  ::                         Un    0   2     0 enp1s0

对比正常情况下的路由,我们可以发现少了两条路由,并且主要缺少一条 default 路由

root@localhost:~# ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2408:8002:2008:2882::/64 via fe80::1 dev enp1s0 proto ra metric 100 pref high
2408:8002:2008:2882::/64 dev enp1s0 proto kernel metric 256 expires 3210sec pref medium
fe80::/64 dev enp1s0 proto kernel metric 100 pref medium
default via fe80::1 dev enp1s0 proto ra metric 1024 expires 1210sec hoplimit 64 pref low

root@localhost:~# route -n6 | grep enp1s0
Destination                    Next Hop                   Flag  Met  Ref Use If
2408:8002:2008:2882::/64       fe80::1                    UG    100  2     0 enp1s0
fe80::/64                      ::                         U     100  6     0 enp1s0
2408:8002:2008:2882::/64       ::                         UAe   256  1     0 enp1s0
::/0                           fe80::1                    UGDAe 1024 5     0 enp1s0
2408:8002:2008:2882::/128      ::                         Un    0    3     0 enp1s0
2408:8002:2008:2882::2882/128  ::                         Un    0    2     0 enp1s0
fe80::/128                     ::                         Un    0    3     0 enp1s0
fe80::222/128                  ::                         Un    0    7     0 enp1s0
fe80::2408:8002:2008:2882/128  ::                         Un    0    2     0 enp1s0

可以发现,在默认路由,存在一个过期时间 1210s ,等到超时后会自动清除这条。

default via fe80::1 dev enp1s0 proto ra metric 1024 expires 1210sec hoplimit 64 pref low

按道理,像 IPV4 的网关默认是长时间保持的,IPV6 应当也可以保持。
究其原因,这条路由的学习则是由路由器的 RA 广播维护的,而系统默认是 禁止接收 RA 广播
(出于服务安全的考虑,主要考虑避免因为 路由器 RA 广播攻击而出现路由和地址均产生变化的情况)

检查系统参数,可以看到均为默认的 0

root@localhost:~# cat /proc/sys/net/ipv6/conf/enp1s0/accept_ra
0
root@localhost:~# cat /proc/sys/net/ipv6/conf/all/accept_ra
0
root@localhost:~# cat /proc/sys/net/ipv6/conf/default/accept_ra
0

对于值代表的含义如下

0 Do not accept Router Advertisements
1 Accept Router Advertisements if forwarding is disabled
2 Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled

0 不接受路由器 RA 广播
1 如果转发被禁用,则接受路由器 RA 广播
2 无视转发行为,即使启用了转发,也接受路由器 RA 广播 

而我们想保证 RA 广播正常被系统接收,我们可以配置为 2
通常来说,如果未启用 net.ipv6.conf.all.forwarding 则可以配置为 1
如果由于某些原因不希望其他端口接收 RA 广播,则可以指定端口而不使用全体端口

# Accept IPv6 advertisements when forwarding is enabled
net.ipv6.conf.all.accept_ra = 2
net.ipv6.conf.default.accept_ra = 2
net.ipv6.conf.enp1s0.accept_ra = 2

改过后运行的路由表如下

root@localhost:~# ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2408:8002:2008:2882::/64 via fe80::1 dev enp1s0 proto ra metric 100 pref high
fe80::/64 dev enp1s0 proto kernel metric 100 pref medium
default via fe80::1 dev enp1s0 proto static metric 20100 pref medium

root@localhost:~# route -n6 | grep enp1s0
Destination                    Next Hop                   Flag  Met   Ref Use If
2408:8002:2008:2882::/64       fe80::1                    UG    100   1     0 enp1s0
fe80::/64                      ::                         U     100   7     0 enp1s0
::/0                           fe80::1                    UG    20100 5     0 enp1s0
2408:8002:2008:2882::/128      ::                         Un    0     3     0 enp1s0
2408:8002:2008:2882::2882/128  ::                         Un    0     7     0 enp1s0
fe80::/128                     ::                         Un    0     4     0 enp1s0
fe80::222/128                  ::                         Un    0     6     0 enp1s0
fe80::2408:8002:2008:2882/128  ::                         Un    0     7     0 enp1s0
ff00::/8                       ::                         U     256   7     0 enp1s0

如果不需要临时 IPV6 地址,还可以使用 sysctl 直接禁止获取

root@localhost:~# cat /etc/sysctl.d/10-ipv6-privacy.conf
# IPv6 Privacy Extensions (RFC 4941)
# ---
# IPv6 typically uses a device's MAC address when choosing an IPv6 address
# to use in autoconfiguration. Privacy extensions allow using a randomly
# generated IPv6 address, which increases privacy.
#
# Acceptable values:
#    0 - don’t use privacy extensions.
#    1 - generate privacy addresses
#    2 - prefer privacy addresses and use them over the normal addresses.
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2

将默认的 2 改为 0 即可禁用 IPV6 临时地址

其他相关的 IPV6 参数如下

net.ipv6.conf.enp1s0.accept_dad = 1
net.ipv6.conf.enp1s0.max_addresses = 16
net.ipv6.conf.enp1s0.accept_ra = 0
net.ipv6.conf.enp1s0.temp_prefered_lft = 86400
net.ipv6.conf.enp1s0.temp_valid_lft = 604800
net.ipv6.conf.enp1s0.use_oif_addrs_only = 0

建议修改如下所示减少临时地址的数量

net.ipv6.conf.enp1s0.accept_dad = 1
net.ipv6.conf.enp1s0.max_addresses = 10
net.ipv6.conf.enp1s0.accept_ra = 2
net.ipv6.conf.enp1s0.temp_prefered_lft = 86400
net.ipv6.conf.enp1s0.temp_valid_lft = 259200
net.ipv6.conf.enp1s0.use_oif_addrs_only = 0

7.4 、 Cloudflare Warp

Cloudflare Warp 使用 Wireguard 提供免费的 VPN 服务

因为 Cloudflare Warp 提供 IPV4/IPV6 双栈支持,所以可以用来解决 VPS 的 IP 被 网站禁止 的情况

Cloudflare [ 链接 ] / 第三方客户端 wgcf [ 链接 ] / 用户自制脚本 [ 脚本 ]

Ubuntu 的安装流程如下

curl https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
apt update
apt install cloudflare-warp
#清空 warp 信息
#warp-cli delete

#注册 warp 信息
warp-cli register

#设置为 Sock5 代理模式
warp-cli set-mode proxy

#设置 Sock5 代理接口
warp-cli set-proxy-port 3100

#设置自动连接 warp 服务器(非开机启动)
warp-cli enable-always-on

#连接 warp 服务器(一定要配好再连,否则会断网)
warp-cli connect

#查看当前配置
warp-cli settings

上述是安装 warp-cli 的步骤,如果想提取配置文件手动操作,可以通过 wgcf 或 用户自制脚本 处理

注册 Warp 并生成配置文件

#!/bin/bash
# Source https://github.com/ViRb3/wgcf
/work/service/wireguard/wgcf/wgcf_v2.2.15 register
/work/service/wireguard/wgcf/wgcf_v2.2.15 generate

生成好的文件如下所示

[Interface]
PrivateKey = XXXXXXXXXXXX
Address = 172.16.0.2/32
Address = 2606::/128
DNS = 1.1.1.1
MTU = 1280
[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0
AllowedIPs = ::/0
Endpoint = engage.cloudflareclient.com:2408

处理 wgcf-profile.conf 文件为 通过 Warp 实现 IPV4 上网(注意看替换方式)(一次性命令小心断网)

#!/bin/bash
sed -i '/AllowedIPs = ::/d'  wgcf-profile.conf
sed -i 's/'engage.cloudflareclient.com'/'[2606:4700:d0::a29f:c001]'/g' wgcf-profile.conf

处理 wgcf-profile.conf 文件为 通过 Warp 实现 IPV6 上网(注意看替换方式)(一次性命令)

#!/bin/bash
sed -i '/AllowedIPs = 0.0.0.0/d'  wgcf-profile.conf
sed -i 's/'engage.cloudflareclient.com'/'162.159.192.1'/g' wgcf-profile.conf

移动 wgcf-profile.conf 文件并启动服务

#!/bin/bash
mv /work/service/wireguard/wgcf/wgcf-profile.conf /etc/wireguard/
chmod 400 /etc/wireguard/wgcf-profile.conf
systemctl enable --now wg-quick@wgcf-profile

测试 IPV4 和 IPV6 连接情况

#!/bin/bash
echo "--- IPV4 TEST ---"
curl -4 https://icanhazip.com/
echo "--- IPV6 TEST ---"
curl -6 https://icanhazip.com/

StarryVoid

Have a good time