Linux 容器/使用 VPN - Arch Linux 中文维基

跳至內容

# Linux 容器/使用 VPN

出自 Arch Linux 中文维基
< Linux 容器
翻譯狀態：

- 本文（或部分內容）譯自 Linux Containers/Using VPNs，最近一次同步於 2024-4-17，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- OpenVPN
- PeerGuardian_Linux
- ufw
- WireGuard

本文介紹如何設置 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 條目。

分類：​

- VPN
- 虛擬化

Linux 容器/使用 VPN
新增話題