WireGuard不仅可以连接特定远程网络,也可以配置为让所有流量经过VPN。这样做可能有多种原因,但主要与隐私有关。
本文假定本地网络“不可信”,希望尽量减少泄露上网行为的信息。这适用于机场、咖啡馆、会议、酒店或其他公共网络。
public untrusted ┌── wg0 10.90.90.2/24
10.90.90.1/24 network/internet │ VPN network
wg0│ xxxxxx ┌──────┴─┐
┌─┴──┐ xx xxxxx ──────┤ VPN gw │
│ ├─wlan0 xx xx eth0 └────────┘
│ │ xx x
│ │ xxx xxx
└────┘ xxxxxx
Laptop
要取得理想效果,需要一台能够通过互联网访问、并由自己控制的系统。通常可以是公有云上的小型虚拟机,也可以是家庭网络中的设备。本文假定使用一台全新系统,专门从零开始配置这一用途。
安装并配置WireGuard
先安装WireGuard并生成密钥。在客户端运行:
sudo apt install wireguard
umask 077
wg genkey > wg0.key
wg pubkey < wg0.key > wg0.pub
sudo mv wg0.key wg0.pub /etc/wireguard
在网关服务器上运行:
sudo apt install wireguard
umask 077
wg genkey > gateway0.key
wg pubkey < gateway0.key > gateway0.pub
sudo mv gateway0.key gateway0.pub /etc/wireguard
在客户端创建/etc/wireguard/wg0.conf:
[Interface]
PostUp = wg set %i private-key /etc/wireguard/wg0.key
ListenPort = 51000
Address = 10.90.90.1/24
[Peer]
PublicKey = <contents of gateway0.pub>
Endpoint = <public IP of gateway server>
AllowedIPs = 0.0.0.0/0
关键点如下:
-
WireGuard接口选择
10.90.90.1/24。可以使用任何不与当前网络冲突的私有IP地址,因此务必检查。若需要更改,也应同步更改网关服务器上的WireGuard接口地址。 -
AllowedIPs为0.0.0.0/0,表示所有IPv4地址。 -
这里通过
PostUp加载私钥,而非直接将私钥写入配置文件,因此不必将配置文件权限设为0600。
网关服务器对应的配置文件为/etc/wireguard/gateway0.conf,内容如下:
[Interface]
PostUp = wg set %i private-key /etc/wireguard/%i.key
Address = 10.90.90.2/24
ListenPort = 51000
[Peer]
PublicKey = <contents of wg0.pub>
AllowedIPs = 10.90.90.1/32
由于不知道远程对等端会从哪里连接,这里没有为它设置Endpoint,预期由该对等端主动发起VPN连接。
两端的WireGuard配置至此完成,但网关服务器还需要额外配置。
路由与地址伪装
目前的WireGuard配置足以将不可信网络中的客户端流量送到网关服务器,但之后如何到达互联网?网关还需要两项配置:
-
对来自
10.90.90.1/24的流量进行地址伪装,即应用源NAT规则。 -
启用IPv4转发,让网关服务器充当路由器。
要启用路由,创建/etc/sysctl.d/70-wireguard-routing.conf,内容如下:
net.ipv4.ip_forward = 1
然后运行:
sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf -w
只需一条简单规则,就可以对VPN流量进行地址伪装:
sudo iptables -t nat -A POSTROUTING -s 10.90.90.0/24 -o eth0 -j MASQUERADE
如果网关服务器的网络接口不叫eth0,请替换成实际接口名。
要让规则在重启后继续生效,可以将其加入/etc/rc.local;若文件不存在,创建它并赋予可执行权限:
#!/bin/sh
iptables -t nat -A POSTROUTING -s 10.90.90.0/24 -o eth0 -j MASQUERADE
网关服务器的配置至此完成。
测试
启动两端的WireGuard接口。在网关服务器上运行:
sudo wg-quick up gateway0
[#] ip link add gateway0 type wireguard
[#] wg setconf gateway0 /dev/fd/63
[#] ip -4 address add 10.90.90.2/24 dev gateway0
[#] ip link set mtu 1378 up dev gateway0
[#] wg set gateway0 private-key /etc/wireguard/gateway0.key
在客户端运行:
sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.90.90.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] nft -f /dev/fd/63
[#] wg set wg0 private-key /etc/wireguard/wg0.key
现在应能在客户端验证:访问互联网的流量通过WireGuard VPN经过网关服务器。例如:
mtr -r 1.1.1.1
Start: 2022-09-01T12:42:59+0000
HOST: laptop.lan Loss% Snt Last Avg Best Wrst StDev
1.|-- 10.90.90.2 0.0% 10 184.9 185.5 184.9 186.9 0.6
2.|-- 10.48.128.1 0.0% 10 185.6 185.8 185.2 188.3 0.9
(...)
7.|-- one.one.one.one 0.0% 10 186.2 186.3 185.9 186.6 0.2
原文输出中,第一跳是网关服务器的gateway0接口;随后10.48.128.1是该服务器的默认网关,接着是一些中间跳,最后到达目标。
不过,如果只看ip route输出,可能不容易看出WireGuard VPN已成为默认网关:
ip route
default via 192.168.122.1 dev enp1s0 proto dhcp src 192.168.122.160 metric 100
10.90.90.0/24 dev wg0 proto kernel scope link src 10.90.90.1
192.168.122.0/24 dev enp1s0 proto kernel scope link src 192.168.122.160 metric 100
192.168.122.1 dev enp1s0 proto dhcp scope link src 192.168.122.160 metric 100
这是因为WireGuard使用fwmark和策略路由。它不能简单地把wg0设为默认网关,因为承载隧道的流量本身必须在VPN之外到达指定端点的51000/UDP端口。
若要进一步理解工作原理,可检查ip rule list、ip route list table 51820,并查阅Linux策略路由文档。
DNS泄漏
流量现在经过VPN到达你控制的网关,再进入互联网。本地网络无法看到加密流量的内容,但你访问的网站信息仍可能通过DNS泄露。
笔记本从不可信本地网络取得IP时,通常也会获得DNS服务器地址。这些服务器可能属于本地网络,也可能是1.1.1.1或8.8.8.8等互联网服务。访问网站时,客户端向这些服务器发送DNS查询,以获取网站IP。即使查询经过VPN,它最终也会离开隧道,到达这些DNS服务器,因此服务器仍能知道你试图访问什么。
可以使用DNS泄漏检测服务,例如https://dnsleaktest.com,快速检查当前连接使用了哪些DNS服务器,再自行判断是否信任它们。你可能会发现,即使在会议网络中使用本文这种默认网关VPN,仍在使用会议设施提供的DNS服务器。也就是说,DNS流量离开设备时被加密,之后又以明文回到本地DNS服务器。
对此可以采取两种办法:为VPN连接选择特定DNS服务器,或者安装自己的DNS服务器。
选择DNS服务器
如果有可信或可以接受的DNS服务器,这通常是最简单的办法。很多人会先使用VPN网关服务器被分配的DNS服务器。在网关服务器的终端中运行以下命令即可查看地址:
resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (ens2)
Current Scopes: DNS
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.48.0.5
DNS Servers: 10.48.0.5
DNS Domain: openstacklocal
Link 5 (gateway0)
Current Scopes: none
Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
查找Current DNS Server。原文示例中是10.48.0.5。
修改WireGuard的wg0接口配置以使用该DNS服务器。编辑/etc/wireguard/wg0.conf,添加第二条PostUp,其中包含如下resolvectl命令:
[Interface]
PostUp = wg set %i private-key /etc/wireguard/wg0.key
PostUp = resolvectl dns %i 10.48.0.5; resolvectl domain %i \~.
ListenPort = 51000
Address = 10.90.90.1/24
[Peer]
PublicKey = <contents of gateway0.pub>
Endpoint = <public IP of gateway server>
AllowedIPs = 0.0.0.0/0
如果希望避免重启WireGuard VPN,也可以手动运行该resolvectl命令:
sudo resolvectl dns wg0 10.48.0.5; sudo resolvectl domain wg0 \~.
或者直接重启WireGuard接口:
sudo wg-quick down wg0; sudo wg-quick up wg0
再次检查DNS泄漏时,应当只看到你指定的DNS服务器。
安装自己的DNS服务器
如果连网关所在托管服务商的DNS也不想使用,还可以安装自己的DNS服务器。
有多种选择,bind9和unbound都很常见,也容易找到简明教程。
这里使用Ubuntu main仓库中的bind9。
在网关服务器安装bind9软件包:
sudo apt install bind9
服务器端的操作至此完成。
在客户端添加指定这个IP的PostUp行,或修改上一节加入的那一行:
[Interface]
PostUp = wg set %i private-key /etc/wireguard/wg0.key
PostUp = resolvectl dns %i 10.90.90.2; resolvectl domain %i \~.
ListenPort = 51000
Address = 10.90.90.1/24
[Peer]
PublicKey = <contents of gateway0.pub>
Endpoint = <public IP of gateway server>
AllowedIPs = 0.0.0.0/0
重启WireGuard接口。此后VPN客户端将使用网关服务器作为DNS服务器。
原文:将VPN用作默认网关;作者:Canonical与Ubuntu Server文档贡献者。版本或日期:以抓取时的官方版本为准。原文及源码权利归相应权利人所有。











暂无评论内容