关于设置 WireGuard VPN,他们不会告诉你的事
我们来弄个服务器吧!
设置 WireGuard 服务器
设置 WireGuard 客户端
更正
参考
WireGuard是一个相对较新的 VPN 实现,于 2020 年添加到 Linux 5.6 内核中,它比其他流行的 VPN 选项(如 IPsec 和 OpenVPN)更快、更简单。
我们将逐步讲解如何在 DigitalOcean 上设置仅支持 IPv4 的 WireGuard VPN 服务器,并重点介绍一些技巧、窍门和教育性的小知识,这些内容应该可以帮助您更深入地了解 WireGuard,最终节省您的时间,而无需像“只需复制这些代码块”的 WireGuard 教程那样费时费力。
我们来弄个服务器吧!
要设置 VPN,我们需要连接两台计算机。其中一台通常是您自己的台式机/笔记本电脑/手机。如果您希望远程访问公司内网站点和服务,另一台计算机可以是办公室服务器或公司云网络上的服务器。如果您希望远程访问自己的家庭网络、与家人/朋友进行私密网络连接,或加密所有互联网流量,那么另一台计算机可以是 DigitalOcean 或 AWS 等云服务提供商提供的个人服务器。
在本教程中,我们将使用 DigitalOcean 上的一个全新的 Ubuntu 20.04 服务器,当然您也可以使用其他云服务提供商按照类似的步骤操作。要创建新的 DigitalOcean 服务器,请按照他们的创建 Droplet 指南进行操作。“Droplet”是 DigitalOcean 对“服务器”、“虚拟机”或“实例”的统称。
VPC 和私有网络
DigitalOcean 服务器会自动创建在虚拟私有云 ( VPC)中(大多数云服务提供商都提供 VPC 或私有网络功能),这意味着它们eth1除了公共网络接口外,还拥有一个额外的网络接口eth0和一个额外的私有 IP 地址。在同一 VPC 中创建的所有服务器、数据库和负载均衡器都可以通过其私有 IP 地址相互通信,这大大提高了安全性,因为所有来自公共互联网(通过公共网络接口eth0)的入站流量都可以被防火墙阻止。
您可以将 VPN 服务器用作堡垒主机,通过其私有 IP 地址访问 VPC 内的其他资源。也就是说,您的 VPN 服务器可以将流量路由到 VPC 内的任何 IP 地址,而 VPC 中的所有服务器只能接受发往其私有 IP 地址的流量eth1,从而保护这些服务器及其运行的服务免受各种攻击。下面的服务器配置部分将介绍如何设置这种架构。
如何保证我的VPN服务器正常运行?
鉴于 VPN 正常运行时间的重要性——尤其是在它是访问 VPC 或远程公司网络中重要服务器的唯一途径时——值得考虑如何处理或避免服务中断。以下列出了一系列选项和权衡方案,并按复杂度/工作量递增的顺序排列:
- 什么都不要做!如果您在 DigitalOcean 上搭建服务器、安装并配置 VPN,然后不做任何其他操作,那么服务器宕机时,您的 VPN 也会停止服务。由于硬件问题,DigitalOcean 经常会在物理机之间迁移服务器实例,如果迁移过程需要停机,VPN 将会无法使用。如果更严重的问题导致服务中断(例如意外故障
rm -rf /、网络配置错误或遭受攻击),您需要从头开始搭建并配置一台新服务器才能恢复 VPN 服务。如果您没有将 VPN 服务器的私钥离线保存,则需要生成一个新的私钥,并重新配置所有 VPN 客户端才能连接到新的 VPN 服务器。 - 启用服务器备份。您可以额外支付服务器价格的 20% 来启用备份功能,该功能会每周对服务器进行快照。如果服务器出现严重故障或无响应,您可以恢复最新的备份,您的 VPN 即可恢复正常工作(对于 1GB 的服务器,大约需要 1 分钟)。
- 设置手动故障转移。设置 VPN 服务器并创建快照,然后将快照恢复到新的服务器实例。将浮动 IP 地址指向其中一台服务器,并在连接 VPN 时使用该 IP 地址。当主 VPN 服务器因任何原因宕机时,您可以将浮动 IP 地址更新为指向备用 VPN 服务器,VPN 即可恢复正常工作!
- 设置自动故障转移/高可用性。更进一步的复杂方案是:
- 检测 VPN 服务器何时宕机,并使用Pacemaker之类的工具自动切换到(指向浮动 IP 地址)健康的备用服务器。
- 在多个 VPN 服务器前面放置一个 UDP 负载均衡器,但是……你可能需要一些网络技巧来允许多个活动 VPN 服务器使用相同的 IP 地址,而且你可能还需要粘性会话,如果没有像 Cloudflare 为 WARP 所做的协议级更改,漫游客户端就会失效。
设置 WireGuard 服务器
服务器启动后,我们来安装和配置 WireGuard。对于非 Linux 平台,请按照WireGuard 网站上的说明和链接进行操作。本教程将以 Ubuntu 20.04 为例,首先介绍如何安装wireguard软件包:
sudo apt update
sudo apt install wireguard
WireGuard软件包会安装两个二进制文件:
wg— 用于管理 WireGuard 接口配置的工具wg-quick— 一个方便的脚本,用于轻松启动和停止 WireGuard 接口
我建议阅读手册页(man wg和man wg-quick),因为它们简洁明了、文笔流畅,并且包含许多在大多数 WireGuard 教程中被忽略的信息!
要加密和解密数据包,我们需要密钥。🔑
# Change to the root user
sudo -s
# Make sure files created after this point are accessible only to the root user
umask 077
# Generate keys in /etc/wireguard
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
现在我们有了私钥(只有服务器应该拥有和知道)和公钥(应该与所有连接到此服务器的 VPN 客户端共享)。
接下来,在以下位置创建配置文件/etc/wireguard/wg0.conf:
如果我们使用wg-quick(剧透:我们会用到)来启动/停止 VPN 接口,它会创建一个以 ` wg0<interface_name>` 为名称的接口。您可以创建其他名称的接口配置文件,例如wg1.conf` <interface_config_file> my-company-vpn.conf`、`<interface_config_file>` 或 ` <interface_config_file> us_east_1.conf`。只要名称符合 ` wg-quick<interface_config_file>` 中测试的正则表达式,脚本就会创建与配置文件名(去掉 `<interface_name>` 部分)匹配的接口。.conf/usr/bin/wg-quick
打印出你的私钥,cat /etc/wireguard/privatekey然后将以下内容添加到配置文件中:
# /etc/wireguard/wg0.conf on the server
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
# Use your own private key, from /etc/wireguard/privatekey
PrivateKey = WCzcoJZaxurBVM/wO1ogMZgg5O5W12ON94p38ci+zG4=
稍后我们会添加允许连接到 VPN 的客户端的公钥,但目前运行 VPN 服务器只需要以上信息。具体来说:
Address = 10.0.0.1/24— 服务器将在 VPN 中拥有一个 IP 地址10.0.0.1。IP/24地址末尾的 是CIDR 掩码,表示服务器会将该10.0.0.1-10.0.0.254范围内的其他流量转发给 VPN 中的对等方。ListenPort = 51820— WireGuard 将监听入站 UDP 数据包的端口。PrivateKey = ...— VPN 服务器的私钥,用于加密/解密。
此时,您可以启动 VPN 了!
# This will run a few commands with "ip" and "wg" to
# create the interface and configure it
wg-quick up wg0
# To see the WireGuard-specific details of the interface
wg
# To start the VPN on boot
systemctl enable wg-quick@wg0
请访问https://github.com/pirate/wireguard-docs#inspect查看更多用于检查接口的示例命令。
中继流量
回顾上文,这Address = 10.0.0.1/24意味着服务器会将流量转发给子网中的对等节点。也就是说,如果您连接到 VPN 并且ping 10.0.0.14VPN 上存在一个地址为该地址的服务器,那么您的 ping 请求将发送到 VPN 服务器,然后由该服务器10.0.0.1转发到目标机器10.0.0.14。但是,如果没有一项额外的配置,这将无法正常工作:IP 转发。
要启用 IP 转发,请打开/etc/sysctl.conf并取消注释或添加以下行:
net.ipv4.ip_forward=1
然后运行以下命令应用设置:
sysctl -p
现在,VPN 服务器应该能够将流量转发到其他 VPN 主机。据我理解,运行过程ping 10.0.0.14将遵循下图所示的从左到右的路径。图中没有显示从对等方 C 到对等方 A 的 ping 响应,但您可以想象一下所有箭头的反向,就能明白返回响应的路径是什么样的。
故障排除中继流量
很多地方都可能出错,尤其是在像上图所示那样在多台服务器之间转发流量时。当网络请求失败时,tcpdump使用 是一个查找故障源和配置错误的好工具。如果您想查看上图中的完整流量流程,可以tcpdump在每台机器上运行以下命令:
sudo tcpdump -nn -i wg0
sudo tcpdump -nn -i eth0 udp and port 51820
请注意,服务器上的时钟可能略有不同步,因此比较tcpdump不同服务器输出中的时间戳可能会产生误导!
如果您在台式机或笔记本电脑等带有显示器的机器上调试网络数据包,可以使用Wireshark,它是 Wireshark 的图形化、用户友好型替代方案tcpdump。
要更深入了解 WireGuard 本身,您可以按照https://www.wireguard.com/quickstart/#debug-info上的说明启用调试日志记录,然后运行tail -f /var/log/syslog以查看日志消息。
将流量转发到 VPC 或互联网
除了使用 VPN 服务器在 VPN 客户端之间中继流量外,您还可以使用 VPN 服务器访问 VPC(例如 DigitalOcean 或 AWS)中与公共互联网隔离的服务器。这种方法无需更改服务器上的 WireGuard 配置,但您需要启用地址伪装,以便将一个网络(例如 VPC)上的响应映射到另一个网络(例如 VPN)上的请求机器。如果您不熟悉地址伪装,请查看此简要说明。假设您的 VPN 服务器已通过其接口连接到 VPC eth1,您可以使用以下命令在 VPN 服务器上启用地址伪装:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth1 -j MASQUERADE
现在,像你的笔记本电脑这样的 VPN 客户端应该能够 ping 通 VPC 中的服务器,如下图所示。
如果您想通过 VPN 服务器将流量转发到互联网(在这种情况下,VPN 服务器通常被称为跳转服务器eth0),请在VPN 服务器的面向公共互联网的接口(例如)上启用伪装功能:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
现在,像你的笔记本电脑这样的 VPN 客户端可以通过你的 VPN 访问公共互联网网站——如果你使用的是不安全的咖啡店 Wi-Fi 连接,或者你不信任你的 ISP,他们看到的就只是一个加密的 VPN 连接。
防火墙规则
我们iptables上面用过它进行伪装,但iptables它对于管理 VPN 服务器的防火墙也很重要。你可以用ufw其他方法代替,但iptables如果你有时间,最好学习并使用——iptables它更基础也更强大。无论你如何管理防火墙(我喜欢这种方法),你都需要:
- 允许UDP流量流向WireGuard监听端口(在上面的示例服务器配置中为51820)。
- 允许转发到 WireGuard 接口或从 WireGuard 接口转发的流量
wg0
执行这些更改的命令iptables如下:
iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
许多 WireGuard 教程建议将这些iptables命令添加到PostUp服务器 WireGuard 配置中,这意味着这些命令将在wg0创建接口时运行。但请注意,根据您管理防火墙的方式,如果在 WireGuard 接口运行时重启防火墙,这些命令可能会被清除,从而导致 VPN 连接中断。建议您使用与管理其他防火墙规则相同的工具,在同一位置管理 WireGuard 防火墙规则。
设置 WireGuard 客户端
与服务器设置类似,安装 WireGuard(请按照WireGuard 网站上的说明和链接,针对非 Linux 平台进行操作):
sudo apt update
sudo apt install wireguard
生成密钥,类似于服务器设置:
# Change to the root user
sudo -s
# Make sure files created after this point are accessible only to the root user
umask 077
# Generate keys in /etc/wireguard
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
接下来,创建一个配置文件,/etc/wireguard/wg0.conf内容如下:
# /etc/wireguard/wg0.conf on the client
[Interface]
# The address your computer will use on the VPN
Address = 10.0.0.8/32
# Load your privatekey from file
PostUp = wg set %i private-key /etc/wireguard/privatekey
# Also ping the vpn server to ensure the tunnel is initialized
PostUp = ping -c1 10.0.0.1
[Peer]
# VPN server's wireguard public key (USE YOURS!)
PublicKey = CcZHeaO08z55/x3FXdsSGmOQvZG32SvHlrwHnsWlGTs=
# Public IP address of your VPN server (USE YOURS!)
# Use the floating IP address if you created one for your VPN server
Endpoint = 123.123.123.123:51820
# 10.0.0.0/24 is the VPN subnet
AllowedIPs = 10.0.0.0/24
# To also accept and send traffic to a VPC subnet at 10.110.0.0/20
# AllowedIPs = 10.0.0.0/24,10.110.0.0/20
# To accept traffic from and send traffic to any IP address through the VPN
# AllowedIPs = 0.0.0.0/0
# To keep a connection open from the server to this client
# (Use if you're behind a NAT, e.g. on a home network, and
# want peers to be able to connect to you.)
# PersistentKeepalive = 25
这里有很多值得讨论的话题!
Address = ...— 在 VPN 中设置此客户端的 IP 地址。发送到 VPN 服务器且目标地址为该地址的数据包将被发送到此客户端最后一次出现的公共 IP 地址(端点)。PostUp = wg set %i private-key ...— 接口启动后,从文件中加载私钥。如果您愿意,可以直接wg0将私钥文件的内容复制粘贴到一行中(就像在服务器配置中那样)。但我建议不要通过VPN 服务器配置加载私钥,因为重新加载配置(例如,在添加新客户端/对等节点后)不会重新运行命令,因此 VPN 将不再知道其私钥,从而导致 VPN 无法正常工作。PrivateKeyPostUpPostUpPostUp = ping -c1 10.0.0.1— 接口启动后,ping VPN 服务器以wg0测试 VPN 连接是否成功。如果 ping 失败,wg-quick则会关闭该接口。在我的测试中,从 VPN 服务器向客户端发送流量需要客户端向服务器发送一些数据才能正常工作——向服务器发送一个 ping 数据包PostUp即可解决问题。[Peer]— 配置中可以包含多个对等节点部分,每个部分对应一个您希望直接连接的 VPN 对等节点。通常,VPN 服务器是客户端配置文件中唯一的对等节点。[Peer]标题下的行定义了客户端如何以及从何处连接到对等节点。PublicKey = ...— VPN 服务器的公钥。EndPoint = ...— 您的 VPN 服务器的(通常是公开可访问的)IP 地址。如果您使用的是 DigitalOcean 或 AWS 等云服务提供商,则这可能是一个浮动 IP 地址。AllowedIPs = ...— 对于来自 VPN 服务器的入站数据包,其源 IP 地址必须与 `<addresses>` 中的地址或范围匹配AllowedIPs。对于出站数据包,`<addresses>`AllowedIPs是一个映射,它告诉 WireGuard 在加密和发送时应该使用哪个对等方(具体来说是其公钥和端点)。最后一个示例(`<addresses>AllowedIPs = 0.0.0.0/0`)将使 WireGuard 能够将发往任何IP 地址的流量发送到 VPN 服务器。使用`<addresses>`AllowedIPs = 0.0.0.0/0, WireGuardwg-quick up将方便地运行`<addresses>ip route` 和ip rule`<addresses>` 命令,将所有流量路由到 VPN(这在前面提到的不安全的咖啡店 Wi-Fi 或恶意 ISP 场景中非常有用)。有关 `<addresses>`AllowedIPs工作原理的更多信息,请参阅WireGuard 的文档。PersistentKeepalive = 25— 每 25 秒向 VPN 服务器发送一个数据包,以确保当客户端没有公网或稳定的 IP 地址时,服务器能够成功地将流量路由到客户端。如果没有此设置,客户端仍然可以向 VPN 服务器发送流量并接收响应,但客户端和服务器之间的路由器只会保留其 NAT/地址伪装映射几十秒。映射过期后,服务器将无法向客户端发送任何内容,直到客户端先发送内容为止。通常情况下,您无需启用此设置,除非您希望允许 VPN 上的其他设备建立新的连接——例如,如果您想在旅行时通过笔记本电脑或手机连接到您的家用台式机,则需要在家用台式机上启用此设置。
在客户端启动 VPN 之前,需要先配置 VPN 服务器以允许来自客户端的连接。/etc/wireguard/wg0.conf再次打开 VPN 服务器并更新其内容以匹配:
# /etc/wireguard/wg0.conf on the server
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
# Use your own private key, from /etc/wireguard/privatekey
PrivateKey = WCzcoJZaxurBVM/wO1ogMZgg5O5W12ON94p38ci+zG4=
[Peer]
# VPN client's public key
PublicKey = lIINA9aXWqLzbkApDsg3cpQ3m4LnPS0OXogSasNW5RY=
# VPN client's IP address in the VPN
AllowedIPs = 10.0.0.8/32
新增[Peer]部分使 VPN 服务器能够与客户端协调加密密钥,并验证客户端与服务器之间的流量是否畅通。要应用这些更改,您可以重启服务器上的 WireGuard 接口:
wg-quick down wg0 && wg-quick up wg0
如果不想中断或断开正在使用的 VPN 连接,请使用以下命令重新加载配置:
wg syncconf wg0 <(wg-quick strip wg0)
此时,您可以在客户端上启动 VPN!
# This will run a few commands with "ip" and "wg" to
# create the interface and configure it
wg-quick up wg0
# To see the WireGuard-specific details of the interface
wg
通过 Chromebook 连接
如果您要通过 Chromebook 连接 WireGuard VPN,我建议使用官方的 Android WireGuard 应用。我尝试在crouton下运行 WireGuard ,但失败了,因为 crouton 使用了 chroot 环境,所以我只能使用 Chromebook 的旧版 Linux 内核 (4.19),无法在 crouton 中添加内核模块或网络接口。同样,crostini也不允许更新或使用自定义内核模块,但它提供了一种很好的方式,可以在 Android WireGuard 应用运行时通过 SSH 连接到可通过 VPN 访问的服务器。
从其他设备连接
如果您想从没有 root 权限的设备连接到 VPN,您可以尝试安装 WireGuard 的用户空间实现,例如wireguard-go。
如果您想从您无法控制的设备(例如智能电视、物联网传感器)连接到 VPN,请考虑在您的路由器上设置 WireGuard(例如OpenWRT 的说明),以便您可以将所有这些设备的出站流量路由到 VPN。
感谢阅读!希望我分享的关于 WireGuard VPN 设置各个方面的一些见解和技巧能帮您节省时间。如果您有任何建议或更正,请告诉我或在推特上联系我们。如果您想了解更多关于我们如何改进感知传感器的信息,请访问Tangram Vision网站。
如果您正在设置多个 VPN 或多个 VPN 客户端,或者如果您有兴趣了解基础设施和配置自动化,请查看我写的下一个教程:通过设置 WireGuard VPN 探索 Ansible。
更正
- 2020年1月13日:之前我对VPN的作用
AllowedIPs以及如何将所有流量路由到VPN的解释不够完整/有误导性。感谢Twitter上的Chris Siebenmann指出了这一点!
参考
- https://www.wireguard.com/install/
- https://www.wireguard.com/papers/wireguard.pdf
- https://github.com/pirate/wireguard-docs
- https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/
- https://stanislas.blog/2019/01/how-to-setup-vpn-server-wireguard-nat-ipv6/


