Linux 容器/使用 VPN
本文介绍如何设置 Linux 容器以运行多种 VPN 协议,并使用“kill switch”(终止开关)来确保安全/私密的互联网使用。 这样做相比于使用 VirtualBox 或 QEMU 等全功能虚拟化,具有明显的优势,因为资源开销相对较小,并且能够在低功耗设备上运行。
容器设置
需要 Linux 容器的基本设置和理解。 本文假设读者已具备基本的 LXC 设置并使其正常运行。
服务器模式下的 OpenVPN
本小节详细介绍了在容器中提供 OpenVPN 服务所需的一些额外设置。 希望使用提供的 OpenVPN 配置文件的用户无需阅读本小节。
主机设置
- 主机操作系统需要桥接以太网设置,以允许容器运行。 请参阅 Linux Containers#主机网络配置 获取相关信息。
- 需要启用数据包转发。 请参阅 Internet sharing#启用数据包转发 获取相关信息。
- 虽然不是严格必需,但强烈建议使用防火墙。
客户端模式下的 OpenVPN
需要修改容器的配置以使用 OpenVPN,如下所示:
/var/lib/lxc/playtime/config
... ## for OpenVPN lxc.mount.entry = /dev/net dev/net none bind,create=dir lxc.cgroup2.devices.allow = c 10:200 rwm
安装 openvpn。 如果使用容器连接到第三方 VPN 提供商,只需将配置文件 foo.conf
放置在 /etc/openvpn/client/foo.conf
中即可使用。 要验证容器内的 OpenVPN 功能,通过 openvpn-client@foo.service
启动 OpenVPN,并在满意后启用它以在启动时运行。
对于其他用例和设置,请参阅 OpenVPN。
LimitNPROC...
开头的行。WireGuard
安装 wireguard-tools。 用户要么拥有第三方 VPN 服务提供的 WireGuard 配置文件,要么将设置 WireGuard 以在此角色中提供服务。 如果使用容器连接到 VPN 提供商,只需将配置文件 foo.conf
放置在 /etc/wireguard/
中即可使用。
要验证容器内的 WireGuard 功能,通过 wg-quick@foo.service
启动 WireGuard,并在满意后启用它以在启动时运行。
对于其他用例,请参阅 WireGuard。
容器内的防火墙配置
强烈建议在容器内运行配置正确的防火墙。 容器内防火墙的作用有两个:
- 提供一个功能性的“kill switch”(终止开关),以在 VPN 连接失败时维护隐私。
- 阻止恶意内容进入。
本指南使用易于配置的 ufw,但当然也可以使用其他示例。
ufw reset
。功能性“kill switch”(终止开关)的策略很简单,就是设置拒绝策略,然后仅允许 VPN 设备上的特定服务和流量。 这样,如果该设备的连接中断,则不会有本地回退。
编辑 /etc/default/ufw
并将 DEFAULT_OUTPUT_POLICY 从 “ACCEPT” 更改为 “DROP”。
/etc/default/ufw
DEFAULT_OUTPUT_POLICY="DROP"
设置拒绝策略
ufw default deny outgoing ufw default deny incoming
可选地添加在文件中定义的任何预定义或自定义规则,例如 /etc/ufw/applications.d/custom
。
ufw allow ssh ufw allow from my-custom-app1 ufw allow from my-custom-app2
可选地进一步限制来自内部 LAN IP 范围甚至单个 IP 地址的访问。
ufw allow from 192.168.1.0/24
WireGuard 用户将创建一个接口,该接口的名称与相应的配置文件相同,例如 /etc/wireguard/foo.conf
,而 OpenVPN 用户可能正在使用 tun0。 在下面的行中,将 ‘foo’ 替换为 WireGuard 配置的名称(省略 .conf 后缀),或者如果使用 OpenVPN,则将 ‘foo’ 替换为 tun0 或正在使用的任何设备。
ufw allow out on foo from any to any
最后,允许访问 VPN 提供商的 IP 地址,使用预期的端口并定义预期的协议。 在下面的行中,有三个变量需要考虑,定义如下:
- ‘xxx’ 代表 WireGuard 对等方/OpenVPN 服务器的 IP 地址。 它将在 VPN 提供商提供的相应配置文件中定义。
- ‘yyy’ 代表通信将要发生的端口。 同样,这将位于配置文件中。
- ‘zzz’ 代表要使用的协议,可以从 udp 或 tcp 中选择。 请注意,WireGuard 仅支持 udp,而 OpenVPN 支持两者。
ufw allow out to xxx port yyy proto zzz
启动 ufw 并启用 ufw.service
以在启动时运行。
使用 VPN 域名在配置文件中的一种不太优雅的解决方法
如果希望在 VPN 配置文件中使用域名,主机上的 shell 脚本可以预先将其解析为数字 IP,然后通过将其存储在写入容器内文件的变量中,将该 IP 地址传递给容器。 然后,修改后的 VPN systemd 服务可以读取该文件。 它可以工作,但有点不太优雅。
编辑这两个变量以匹配您的用例的容器名称和服务器名称。
在主机上
安装 bind(dig 所需)并创建以下脚本:
/path/to/container-start.sh
#!/bin/bash # this script should be called as root container=foo server=www.myvpnserver.org if ! systemctl is-active lxc@"$container" &>/dev/null; then ToUse=$(dig +short "$server") [[ -d /var/lib/lxc/$container/rootfs/etc/conf.d ]] || mkdir -p /var/lib/lxc/$container/rootfs/etc/conf.d echo "SERVER=$ToUse" > /var/lib/lxc/$container/rootfs/etc/conf.d/server.hack.txt systemctl start lxc@"$container" fi
从现在开始,调用该脚本以启动容器。 它将使用 dig 从域名获取 IP 地址,然后启动容器。
从容器内部
修改启动 VPN 的 systemd 服务,并创建一个骨架配置文件,该文件可以使用我们刚刚创建的脚本在 /var/lib/lxc/$container/rootfs/etc/conf.d/server.hack.txt
中定义的 IP 地址进行修改。
要创建骨架配置文件,只需将实际使用的配置文件重命名为另一个名称。
例如,使用 WireGuard
mv /etc/wireguard/foo.conf /etc/wireguard/foo.skel
现在编辑 /etc/wireguard/foo.skel
以将 Endpoint = www.myvpnserver.org 替换为 @@@,例如。
Endpoint = @@@:51820
或者,如果使用 OpenVPN
mv /etc/openvpn/client/foo.conf /etc/openvpn/client/foo.skel
编辑 /etc/openvpn/client/foo.skel
以将 remote www.myvpnserver.org 替换为 @@@,例如。
remote @@@
最后,创建一个 drop-in 文件,以读取 IP 并将其替换为实际的配置文件。
使用 WireGuard 的示例
/etc/systemd/system/wg-quick@foo.service.d/override.conf
[Service] EnvironmentFile=-/etc/conf.d/server.hack.txt ExecStartPre=/bin/bash -ac "sed s/@@@/$SERVER/ </etc/wireguard/foo.skel >/etc/wireguard/foo.conf"
使用 OpenVPN 的示例
/etc/systemd/system/openvpn-client@foo.service.d/override.conf
[Service] EnvironmentFile=-/etc/conf.d/server.hack.txt ExecStartPre=/bin/bash -ac "sed s/@@@/$SERVER/ </etc/openvpn/client/foo.skel >/etc/openvpn/client/foo.conf"
测试服务
从正在运行的容器内(通过 ssh 或通过 lxc-attach -n playtime
连接),通过将浏览器导出到主机机器的 X server 来测试设置。
$ DISPLAY=:0 firefox
xhost +SI:localuser:yourusername
执行此操作,然后通过 ssh 连接到容器。结果应该是在主机 X server 中显示一个标题为 “Mozilla Firefox (playtime)” 的 firefox 窗口。 许多网站可用于验证 IP 地址和 DNS 条目的状态。 其中一个网站是 ipleak dot net。
此时,应仅显示与配置文件中定义的那些相对应的 DNS 条目。