将VPN用作默认网关

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文档贡献者。版本或日期:以抓取时的官方版本为准。原文及源码权利归相应权利人所有。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容