在 Debian 9 上安装 WireGuard VPN

  1. 1. WireGuard 是什么
  2. 2. 在开始之前
  3. 3. 安装 WireGuard
  4. 4. 配置 WireGuard 服务端
    1. 4.1. 配置防火墙规则
    2. 4.2. 启动 WireGuard 服务
  5. 5. 配置 WireGuard 客户端
  6. 6. 连接客户端与服务器
    1. 6.1. 测试连接
  7. 7. 后续步骤
  8. 8. 可能遇到的问题

本教程主要为从Linode文档Set Up WireGuard VPN on Debian处翻译搬运的版本,其中加入了一些个人的经验和见解和修改,如果您有任何疑惑,欢迎您随时与我们联系。

本实例使用的是 Debian GNU/Linux 9.13 (stretch) ,如果您使用的包管理软件并不相同,或是您的系统版本并不完全一致,则可能会有不一样的表现。

WireGuard 的网卡名未必必须为 wg0 的格式,您可以自行修改命名。只要记得同时调整相关的防火墙规则即可。客户端与服务器的网卡名也未必必须一致,您只要能确认分辨即可。

重要提醒
  1. 除非您知道您在做什么,否则不要轻易改动IPv4地址中关于 /24 和 /32 的掩码配置。特别地,根据我的无数次翻车测试,一般仅主服务器保留 /24 的地址分配、其他的请保留 /32 的配置,防止地址冲突找不到路由。原作者显然没有测试过多节点的情况,否则是绝对不可能用一套/24带走的。
  2. 除非您知道 WireGuard 服务端会对您的配置文件做什么,否则请删除SaveConfig = true这一行。已经被坑害过好多次了。
  3. 请尽量使用dkms来构建 WireGuard ,虽然需要保证内核头文件的正确安装在上古的 CentOS 系统上需要离谱的第三方本地安装,但这样一般能保证版本最新、bug最少。
  4. 此教程同样也适用于 Debian 10.

2021/02/20 修正一个说法问题:

WireGuard 是一个节点间相互对等的 P2P 的协议,没有客户端与服务器的区分,所有的节点之间通过彼此配置的 Peer 来建立连接。
由于没有中心,因而没法 DHCP ,所有的 IP 均为手动静态分配,如果出现路由异常的情况,您可以尝试分配给每个 IPv4 均为 /32 的地址(即完全锁定的无子网地址),我现在就是通过这种方式建立起无中心的点对点网络的。


WireGuard 是什么

WireGuard®是一个简单,快速且安全的,使用了最先进加密技术的 VPN (注:Virtual Private Network, 虚拟私有网络,不是翻墙使用的代理工具,概念不能混淆)。使用了短小精悍的源码脚本的它,致力于成为比其他 VPN 协议,例如 OpenVPN 或是 IPSec ,更加精简与快速。 WireGuard 目前仍处于开发阶段,但就连它的还未优化的状态,甚至都已经比主流的 OpenVPN 协议更加快速了。

WireGuard 会设置标准的网络接口(例如wg0或是wg1,用户可以自定义命名),所以它的表现更像是常见的 eth0 接口。这使它能通过一些标准工具,例如ifconfig或是ip提供了可能。目前,WireGuard已经能在所有的平台上使用。

配置WireGuard就如同配置SSH一样简单。一个连接通过服务器与客户端间交换公钥来确定,只有当一个客户端在它对应的服务器配置文件中包含了它的公钥时,它才会被允许进行连接。一份 WireGuard 服务器的配置文件会以类似如下的样式来呈现:

/etc/wireguard/wg0.conf
1
2
3
4
5
6
7
8
9
10
11
[Interface]
PrivateKey = <Private Key>
Address = 10.0.0.1/24, fd86:ea04:1115::/64
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
SaveConfig = true

[Peer]
PublicKey = <Client Public Key>
AllowedIPs = 10.0.0.2/32, fd86:ea04:1116::/64

在这份教程中,您将会学到:

  • 在一台 Debian 9 系统的 VPS 上配置 WireGuard 的服务端
  • 在您的本地计算机,或是另一台 VPS 上配置 WireGuard 的客户端
  • 在 WireGuard 的服务端与客户端间轻松地建立一个连接

请避免在关键的应用中使用WireGuard。这个项目目前还在进行严格性测试,并很有可能会在未来收到频繁的大升级。


在开始之前

  • 寻找一台运行着 Debian 9 的服务器
  • 寻找一位拥有 sudo 权限的用户(其实root就可以)
  • 设置系统的主机名(hostname,但其实无所谓)

请注意,如果您以root权限运行,那么是不需要执行sudo操作的。并且 apt-get install 操作会被逐渐淘汰,因而建议您直接使用 apt install 进行方便简洁的管理。

这份教程需要配合使用了GRUB 2内核的系统使用。默认情况下新开出来的机器应当都是启用了。但如果您运行的是一个旧的版本,您需要检查您运行的是哪个内核。如果可以的话,您也许需要升级内核,并在管理面板处设置使用GRUB 2引导启动。

安装 WireGuard

  1. 将 WireGuard 的仓库加入到您的 apt 源列表中。apt 会自动更新包缓存。

    1
    2
    echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable-wireguard.list
    printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' > /etc/apt/preferences.d/limit-unstable
  2. 更新您的包,并且安装 WireGuard 和 WireGuard 相关的工具。 DKMS (Dynamic Kernel Module Support,动态内核模组支持)会构建 WireGuard 内核模组。

    1
    2
    apt update
    apt install wireguard-dkms wireguard-tools

    成功后,您将看到类似这样的输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    wireguard.ko:
    Running module version sanity check.
    - Original module
    - No original module exists within this kernel
    - Installation
    - Installing to /lib/modules/4.19.0-13-amd64/updates/dkms/

    depmod....

    DKMS: install completed.

    配置 WireGuard 服务端

  3. 切换至 /etc/wireguard 目录,并为 WireGuard 服务器生成一对公私钥:

    1
    2
    sudo umask 077
    sudo wg genkey | tee privatekey | wg pubkey > publickey

    这将会同时保存公钥与私钥。它们可以通过 cat privatekeycat publickey 来分别查看。

  4. 创建文件 /etc/wireguard/wg0.conf 并且添加如下的内容。您需要在PrivateKey配置项处输入您服务器的私钥,并在Address配置项处输入它的私有地址。您可以参阅配置样例下方的解释表来获取更多的细节。

    /etc/wireguard/wg0.conf
    1
    2
    3
    4
    5
    6
    7
    [Interface]
    PrivateKey = <Private Key>
    Address = 10.0.0.1/24, fd86:ea04:1115::/64
    ListenPort = 51820
    PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    SaveConfig = true
    • PrivateKey 之前生成的服务器的私钥
    • Address 定义了WireGuard服务器的私有IPv4和IPv6地址。每一个VPN网络中的节点在这个设置项中都应当拥有一个独立的值。典型的值有10.0.0.1/24192.168.1.1/24,或是192.168.2.1/24。这和您的私有IP地址应当不重复。特别的,请检查您的网卡与已经分配的IP地址,该子域不应当与任何子域重复。
    • ListenPort 指定了WireGuard应当使用哪一个接口作为入站的连接。默认值为51820,您在此处设置的值会影响到之后您对应防火墙规则的设置。
    • PostUpPostDown 分别定义了开启或是关闭网关时需要执行的步骤。在本实例中,使用iptables用来设置 Linux IP 伪装规则,来允许客户端共享服务端的IPv4地址和IPv6地址。当通道关闭时,这些规则会被清理。
    • SaveConfig 当服务正在运行时,新添加的节点会自动更新至配置文件中去。

配置防火墙规则

我们推荐使用iptables一套带走,但出于对于原文的尊重,我们将ufw的相关操作翻译并放置于此。

  1. 安装UFW

    1
    sudo apt-get install ufw
  2. 添加SSH连接和WireGuard的VPN端口(请注意根据您的具体情况进行调整)

    1
    2
    3
    sudo ufw allow 22/tcp
    sudo ufw allow 51820/udp
    sudo ufw enable
  3. 验证您的设置

    1
    sudo ufw status verbose
使用 iptables 的配置方案
  1. 安装 ipset ,为 iptables 提供一个方便的批量地址管理工具

    1
    apt install ipset
  2. 新建一个 ip 集合,添加会用到的客户端的公网 IP

    1
    2
    ipset create wgclients hash:ip
    ipset add wgclients 1.2.3.4 # WireGuard的客户端公网IP
  3. 编写 iptables 防火墙规则,仅允许可信客户端连接,丢弃所有非可信的数据包

    1
    2
    iptables -A INPUT -m set --match-set wgclients src -p udp --dport 51820 -j ACCEPT
    iptables -A INPUT -p udp -m multiport --dport 51820 -j DROP
  4. 保存防火墙规则

    1
    iptables-save

启动 WireGuard 服务

  1. 启动 WireGuard

    1
    sudo wg-quick up wg0

    wg-quickwg中许多常用功能的封装。您可以使用wg-quick down wg0来关闭 wg0 接口。

  2. 设置 WireGuard 服务为开机自启

    1
    sudo systemctl enable [email protected]
  3. 用下列两条指令来检查 VPN 隧道是否已经正确运行

    1
    sudo wg show

    您应该会看到类似的输出:

    1
    2
    3
    4
    5
    [email protected]:/# wg show
    interface: wg0
    public key: Nrl2nVQxSwrKrvz6jQcrsziuVRPWT9N1Q8/yaQkAXUg=
    private key: (hidden)
    listening port: 51820

    您可能需要安装 net-tools 来运行ifconfig。如有必要的话,您可以使用sudo apt-get install net-tools

    或者我们推荐使用更强大的 ip 指令,后文会有补充提及。出于对原文的尊重,此处是 ifconfig 指令的翻译。

    1
    sudo ifconfig wg0

    您的输出应当看上去像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [email protected]:/# ifconfig wg0
    wg0: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1420
    inet 10.0.0.1 netmask 255.255.255.0 destination 10.0.0.1
    inet6 fd86:ea04:1115::1 prefixlen 64 scopeid 0x0<global>
    unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1 (UNSPEC)
    RX packets 0 bytes 0 (0.0 B)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 0 bytes 0 (0.0 B)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
    使用 ip 的测试方案
    1
    ip addr show wg0

    您的输出应当看上去像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    [email protected]:~# ip addr show wg0
    35021: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1
    link/none
    inet 10.0.0.1/32 scope global wg0
    valid_lft forever preferred_lft forever
    inet6 fd86:ea04:1115::1/64 scope global
    valid_lft forever preferred_lft forever

配置 WireGuard 客户端

设置 WireGuard 客户端的过程与设置服务端的过程非常相似。当使用 Debian 作为您的客户端操作系统时,客户端与服务端间唯一的区别在于配置文件。在这个模块中,您将会了解到如何在 Debian 9 上配置一个 WireGuard 客户端。

您可以参阅 WireGuard 文档 以获取在其他平台上的安装指引。

  1. 参阅本教程中的 安装 WireGuard 段来完成安装工作。 WireGuard 的客户端与服务端是对等的。

  2. 当您完成安装后,您可以参阅 配置 WireGuard 服务端 段来完成客户端的配置工作。只需要将样例的配置文件题欢成如下的样例即可。

    /etc/wireguard/wg0.conf
    1
    2
    3
    [Interface]
    PrivateKey = <Client Private Key>
    Address = 10.0.0.2/32, fd86:ea04:1116::/64

    客户端与服务端的区别在于配置文件 wg0.conf,该文件包含了本网卡自己的IP地址,并且不包含 ListenPortPostUPPostDown,或是 SaveConfig 段的内容。

  3. 在您的 WireGuard 客户端上 配置防火墙规则

  4. 启动 WireGuard 服务

连接客户端与服务器

  1. 在服务器和客户端上使用 sudo wg-quick down wg0 来停止接口。

  2. 编辑客户端上的 wg0.conf 文件,添加服务器的公钥、公网 IP 地址、端口和该段分配的 IP CIDR 地址块(修正了原文中不够优雅的的写法)

    /etc/wireguard/wg0.conf
    1
    2
    3
    4
    [Peer]
    PublicKey = <Server Public key>
    Endpoint = <Server Public IP>:51820
    AllowedIPs = 10.0.0.1/32, fd86:ea04:1115::/64
  3. 编辑服务器上的 wg0.conf 文件,添加客户端的公钥和该段分配的 IP CIDR 地址块

    /etc/wireguard/wg0.conf
    1
    2
    3
    [Peer]
    PublicKey = <Client Public Key>
    AllowedIPs = 10.0.0.2/32, fd86:ea04:1116::/64
  4. 在服务器和客户端上分别启动 WireGuard 服务

    1
    sudo wg-quick up wg0
  5. 您也可以使用命令行将节点加入至服务器。由于配置文件中开启了 SaveConfig 选项,这些信息会被自动加入到配置文件中。

    在服务器运行以下指令,使用预计分配给客户端的 IP 地址来替换样例中的内容:

    1
    sudo wg set wg0 peer <Client Public Key> allowed-ips 10.0.0.2/32,fd86:ea04:1116::/64
  6. 验证连接。以下的指令在客户端和服务器上均可运行。

    1
    sudo wg

    无论您使用哪种方式添加节点信息,当您运行 sudo wg 指令时, Peer 部分都应当会出现在输出中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [email protected]:/# sudo wg
    interface: wg0
    public key: vD2blmqeKsV0OU0GCsGk7NmVth/+FLhLD1xdMX5Yu0I=
    private key: (hidden)
    listening port: 51820

    peer: iMT0RTu77sDVrX4RbXUgUBjaOqVeLYuQhwDSU+UI3G4=
    endpoint: 10.0.0.2:51820
    allowed ips: 10.0.0.2/32, fd86:ea04:1115::/64

    当服务进程重启时,这个节点会被自动添加到 wg0.conf 中。如果您希望立刻将这信息添加到配置文件,您可以运行以下指令:

    1
    sudo wg-quick save wg0

    额外的客户端可以被使用同样的过程来加入。

测试连接

回到客户端并使用 ping 来向服务器发起请求:

1
ping 10.0.0.1

当您成功建立连接并从客户端访问到服务端时,您可以运行如下的命令:

1
sudo wg

wg 命令输出的最后两行应当看起来像这样:

1
2
latest handshake: 1 minute, 17 seconds ago
transfer: 98.86 KiB received, 43.08 KiB sent

这证明了您已经建立了一条服务器与客户端的私密链接。如果您无法成功从客户端 ping 到服务端(前提是您的服务端允许 ping ),您将不会看到这些行。您也可以从服务端 ping 客户端,来证明这条连接在两边都能工作。

后续步骤

这篇教程中使用的步骤可以拓展,以便构建网络的拓补结构。如同上文提及的, WireGuard 是一种仍在发展中的技术。如果您使用 WireGuard, 您应当注意官方文档计划清单,以便为关键的升级和新的特性做好准备。

WireGuard 是Jason A. Donenfeld的注册商标。


原文链接:Set Up WireGuard VPN on Debian | Linode,翻译时有补充修改内容,修复了一些写法上的错误。

可能遇到的问题

  • RTNETLINK answers: Permission denied

    请检查您的内核是否关闭了 IPv6 的支持:

    1
    sysctl -a | grep disable_ipv6

    如果看到有 = 1 的项,说明是存在禁用了 IPv6 的情况。
    修改 /etc/sysctl.conf 文件,将所有 disable_ipv6 后 = 1 的全都改成 0 。

  • RTNETLINK answers: Operation not supported

    您的系统可能缺失必要的 Kernel Headers ,您可以使用apt补充安装:

    1
    apt install linux-headers-$(uname -r)