Linux 容器/使用 VPN
本文介绍如何设置 Linux 容器 以运行多种 VPN 协议,并使用“kill switch”(终止开关)来安全/私密地使用互联网。与使用像 VirtualBox 或 QEMU 这样的全功能虚拟化相比,这样做的一个显著优势是资源开销极小,并且能够在低功耗设备上运行。
容器设置
需要对 Linux 容器 的基本设置和理解。本文假设读者已经拥有基本的 LXC 设置并使其正常运行。
服务器模式下的 OpenVPN
本小节详细介绍了在容器中提供 OpenVPN 服务所需的一些额外设置。想要使用提供的 OpenVPN 配置文件的用户无需阅读本小节。
主机设置
- 主机操作系统需要桥接以太网设置,以允许容器运行。请参阅 Linux 容器#主机网络配置 以了解相关信息。
- 需要启用数据包转发。请参阅 Internet 共享#启用数据包转发 以了解相关信息。
- 虽然不是严格必需的,但强烈建议使用防火墙。
客户端模式下的 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,通过 openvpn-client@foo.service
,并在满意后 启用 它以在启动时运行。
对于其他用例和设置,请参阅 OpenVPN。
LimitNPROC...
开头的行。WireGuard
安装 wireguard-tools。用户将拥有第三方 VPN 服务提供的 WireGuard 配置文件,或者将设置 WireGuard 以在此角色中提供服务。如果使用容器连接到 VPN 提供商,只需将配置文件 foo.conf
放在 /etc/wireguard/
中即可使用。
要验证容器内的 WireGuard 功能,启动 WireGuard,通过 wg-quick@foo.service
,并在满意后 启用 它以在启动时运行。
对于其他用例,请参阅 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
的命令需要以 root 用户身份执行;以 “#” 符号为前缀的这些命令按照标准的 wiki 注释方式已被省略,以便于干净地复制/粘贴到终端。设置拒绝策略
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 服务器来测试设置
$ DISPLAY=:0 firefox
xhost +SI:localuser:yourusername
执行此操作,然后通过 ssh 连接到容器。结果应该是在主机的 X 服务器中出现一个标题为“Mozilla Firefox (playtime)”的 firefox 窗口。许多网站可用于验证 IP 地址和 DNS 条目的状态。其中一个网站是 ipleak dot net。
此时,应该只显示与配置文件中定义的条目相对应的 DNS 条目。