Linux 容器/使用 VPN

出自 Arch Linux 中文维基


本文介紹如何設置 Linux_容器 來運行多個帶有「終止開關」的 VPN 協議,以實現安全/私隱的互聯網使用。 與使用 VirtualBox 或者 QEMU 等全套的虛擬化相比, 這樣做提供了更小的資源開銷和在低功耗設備上運行等明顯優勢。

配置容器[編輯 | 編輯原始碼]

需要對 Linux_容器 進行基本配置和了解。 本文假設讀者已經設置了可運行的基本LXC。

伺服器模式的OpenVPN[編輯 | 編輯原始碼]

本小節詳細介紹了在容器中提供 OpenVPN 服務所需的一些額外設置。 想要使用給出的 OpenVPN 配置文件的用户無需閱讀本小節。

主機設置[編輯 | 編輯原始碼]

  1. 主機作業系統需要網橋設置才能允許容器運行。請參考 Linux_容器#宿主機網絡配置
  2. 需要啟用數據包轉發。請參考 網絡分享#啟用包轉發
  3. 儘管不是必須的,但強烈建議使用防火牆。

客户端模式的 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 即可。 To v要驗證容器內的 OpenVPN 功能,請啟動 openvpn-client@foo.service 來開啟OpenVPN。一旦對當前配置感到滿意,啟用服務來實現系統啟動後自動開啟。

有關其他用例和設置,請參閱 OpenVPN

注意: 在「非特權」容器中運行 OpenVPN 的用户需要創建一個自定義 systemd 單元才能在容器中啟動它。在替換單元文件中註釋掉以下開頭的行:LimitNPROC...

WireGuard[編輯 | 編輯原始碼]

安裝wireguard-tools。用户將擁有由第三方 VPN 服務提供的 WireGuard 配置,或者自己設置好的WireGuard 對應的配置。 如果使用容器連接到 VPN 提供商, 只需將配置文件 foo.conf 放入 /etc/wireguard/

要驗證容器內的 WireGuard 功能,請通過啟動 wg-quick@foo.service 來開啟WireGuard。一旦對當前配置感到滿意, 啟用服務來實現系統啟動後自動開啟。

有關其他用例和設置,請參閱 WireGuard

容器內的防火牆配置[編輯 | 編輯原始碼]

強烈建議在容器內運行正確配置的 防火牆。容器內防火牆的作用有兩個:

  1. 提供「終止開關」,以便在 VPN 連接失敗時維護私隱。
  2. 把不想要東西拒之門外。

本指南使用易於配置的 ufw,當然也可以使用其他防火牆。

提示:要完全重置 ufw 的配置文件,使用reset: ufw reset.

設置「終止開關」的方法是通過設置一個拒絕政策然後只允許VPN設備上的特定服務和流量。這樣,如果該設備的連接中斷時不會出現本地政策回退。

注意: 下面顯示的方法的一個限制是 VPN 配置文件不得使用 www.myvpn.com 等域名,它們需要使用相應的 IP 地址。如上所述,當 VPN 未連接時,容器 DNS 解析將被禁用。因此,為了連接,必須提供數字 IP。

編輯 /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 的 peer 或者 OpenVPN 的伺服器的IP位址。它將在 VPN 提供商提供的相應配置文件中。
  • 「yyy」代表要進行通信的端口。同樣,這將位於配置文件中。
  • 「zzz」 代表要使用的協議,可以從 udp 或 tcp 中選擇。請注意,WireGuard 僅支持 udp,而 OpenVPN 兩者都支持。
ufw allow out to xxx port yyy proto zzz
注意: 如果預計使用多個伺服器,請對 VPN 提供商定義的每個 IP 地址 (xxx) 重複此操作。

啟動 ufw 並 啟用 ufw.service 以實現開機啟動。

在配置文件中使用 VPN 域名的一個非正式方法[編輯 | 編輯原始碼]

如果需要在 VPN 配置文件中使用域名,主機上的 shell 腳本可以將其預先解析為數字 IP,然後通過將該 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 以將遠程www.myvpnserver.org替換為@@@,例如:

remote @@@

最後,創建一個 附加配置片段, 以讀取 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
提示:通過 ssh 連接需要允許本地顯示接受連接。執行此操作 xhost +SI:localuser:yourusername 然後通過 ssh 連接到容器。

結果應該是主機的 X server 中出現一個標題為"Mozilla Firefox (playtime)" 的 Firefox 窗口。許多網站可用於驗證 IP 地址和 DNS 的狀態,例如 ipleak dot net.

此時,僅應顯示與配置文件中定義的條目相對應的 DNS 條目。