WireGuard - Arch Linux 中文维基

跳至內容

# WireGuard

出自 Arch Linux 中文维基

這篇文章或章節的翻譯質量不佳。

原因：翻譯已經過期，請閱讀英文頁面中的內容。（在 Talk:WireGuard# 中討論）

相關文章

- Linux Containers/Using VPNs

引用自 WireGuard 項目主頁：

  WireGuard 是一種極其簡單但快速且現代的 VPN，它利用了最先進的加密技術。它的目標是比 IPsec 更快、更簡單、更精簡和更有用，同時避免令人頭疼的問題。其旨在提供比 OpenVPN 更高的性能。WireGuard 被設計為在嵌入式接口和超級計算機等上運行的通用 VPN，適用於許多不同的環境。雖然最初僅支持 Linux，但現在可以跨平台（Windows、macOS、BSD、iOS、Android）廣泛部署。

本文中的主要概念在 WireGuard 項目主頁上有粗略的介紹。2019 年底以後，Linux 內核中包含 WireGuard。

## 安裝

安裝 wireguard-tools包，其提供了用戶空間實用程序。

另外，如果 Peer 公鑰可用，也可以藉助其他網絡管理器的 WireGuard 支持。詳見#持久化配置。

### 圖形客戶端

- wireguird — 一個運行在Linux上的GTK GUI WireGuard客戶端

  https://github.com/UnnoTed/wireguird || wireguirdAUR

- wireguard-gui — 一個使用nextauri製作的Wireguard Linux圖形化客戶端

  https://github.com/0xle0ne/wireguard-gui || wireguard-gui-binAUR

### 命令行工具

- wg_tool — 用於管理伺服器和用戶 wireguard 配置的工具。

  https://github.com/gene-git/wg_tool || wg_toolAUR

- wg-client — 一個同時具有圖形化界面和命令行的Linux客戶端

  https://github.com/gene-git/wg-client || wg-clientAUR

- wg2nd — 將 WireGuard 配置從 wg-quick(8) 格式轉換為 systemd-networkd 兼容的配置的工具。

  https://git.flu0r1ne.net/wg2nd/about || wg2ndAUR

## 使用

以下命令展示了如何在兩個對等節點之間建立一條使用以下設置的基本的隧道：

| 外部（公共）地址 | 內部 IP 地址 | 埠
--- | --- | --- | ---
域名 | IPv4 地址 | IPv6 地址 | IPv4 地址 | IPv6 地址
對等節點 A |  | 198.51.100.101 | 2001:db8:a85b:70a:ffd4:ec1b:4650:a001 | 10.0.0.1/24 | fdc9:281f:04d7:9ee9::1/64 | UDP/51871
對等節點 B | peer-b.example | 203.0.113.102 | 2001:db8:40f0:147a:80ad:3e88:f8e9:b002 | 10.0.0.2/24 | fdc9:281f:04d7:9ee9::2/64 | UDP/51902
對等節點 C |  | 動態（不固定） | 動態（不固定） | 10.0.0.3/24 | fdc9:281f:04d7:9ee9::3/64 | UDP/51993

提示：對等節點可使用相同的 UDP 埠。

外部地址應該已經存在。例如，如果 ICMP 回顯請求未被阻止，則對等節點 A 應該能夠通過 ping 通對等點 B 的公共 IP 地址，反之亦然。

內部地址將是使用 ip(8) 實用程序手動創建或通過網絡管理軟體創建的新地址，這些地址將在新的 WireGuard 網絡內部使用。以下示例使用 10.0.0.0/24 和 fdc9:281f:04d7:9ee9::/64 作為內部網絡。 IP 地址中的 `/24` 和 `/64` 是 CIDR。

### 生成密鑰

為每個對等節點創建公鑰和私鑰。如果要連接很多節點，可以考慮 vanity keypair 個性化 Base64 編碼的公鑰字符串，參見#Vanity keys。

生成私鑰：

    $ (umask 0077; wg genkey > peer_A.key)

注意：建議僅允許所有者讀寫。以上命令使用子 shell 臨時改變 umask，從而確保只有所有者可訪問（有讀寫權限）。

生成公鑰：

    $ wg pubkey < peer_A.key > peer_A.pub

或者，一次性生成公鑰和私鑰：

    $ wg genkey | (umask 0077 && tee peer_A.key) | wg pubkey > peer_A.pub

還可以生成預共享密鑰，以添加一層額外的對稱密鑰加密技術，將其混合到現有的公鑰加密技術中，以實現後量子抵抗。應為每個對等節點對生成預共享密鑰，且不應重複使用。例如，三個互連的對等節點 A、B 和 C 將需要三個單獨的預共享密鑰，每個對等節點對一個。

使用以下命令為每個對等節點對生成預共享密鑰（確保也使用 `umask 0077`）：

    $ wg genpsk > peer_A-peer_B.psk
    $ wg genpsk > peer_A-peer_C.psk
    $ wg genpsk > peer_B-peer_C.psk

#### Vanity keys

Currently, WireGuard does not support comments or attaching human-memorable names to keys. This makes identifying the key's owner difficult particularly when multiple keys are in use. One solution is to generate a public key that contains some familiar characters (perhaps the first few letters of the owner's name or of the hostname etc.), wireguard-vanity-addressAUR does this.

For example:

    $ wireguard-vanity-address --in 8 leslie

    searching for 'leslie' in pubkey[0..10], one of every 214748364 keys should match
    one core runs at 2.69e6 keys/s, CPU cores available: 16
    est yield: 5.0 seconds per key, 200.10e-3 keys/s
    hit Ctrl-C to stop
    private wEoVMj92P+E3fQXVf9IixWJqpCqcnP/4OfvrB1g3zmY=  public LEsliEny+aMcWcRbh8Qf414XsQHSBOAFk3TaEk/aSD0=
    private EAOwlGGqpHVbZ9ehaCspdBJt+lkMcCfkwiA5T5a4JFs=  public VlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XjoalC8=
    private UDWG4VWI+RzAGzNSnlC+0X4d3nk9goWPs/NRC5tX524=  public 9lESlieIFOlJFV6dG7Omao2WS+amWgshDdBYn8ahRjo=

這篇文章或章節的翻譯質量不佳。

原因：以下翻譯已經過期，請閱讀英文頁面中的內容。（在 Talk:WireGuard# 中討論）

在 peer 上生成公鑰和私鑰：

    $ wg genkey | tee privatekey | wg pubkey > publickey

下面的指令會演示如何以表中的配置建立一條兩個 peer 之間的隧道

| Peer A | Peer B
--- | --- | ---
公網地址 | 10.10.10.1/24 | 10.10.10.2/24
內網地址 | 10.0.0.1/24 | 10.0.0.2/24
wireguard 監聽埠 | UDP/4857 | UDP/3981

Peer 應當已經擁有公網地址。例如，peer A 應當能夠通過 `ping 10.10.10.2` ping 通 peer B，反之亦然。內部地址是由下文 `ip` 命令創建的新地址，並且將在 WireGuard 網絡中共享。IP位址中 `/24` 的含義詳見 CIDR

### Peer A 配置

這個 peer 將監聽 UDP 埠 48574，通過將 peer B 的公鑰與其內部和外部 IP 地址關聯，接受來自 peer B 的連接。

    # ip link add dev wg0 type wireguard
    # ip link set dev wg0 mtu 1420
    # ip addr add 10.0.0.1/24 dev wg0
    # wg set wg0 listen-port 4857 private-key ./privatekey
    # wg set wg0 peer [Peer B public key] persistent-keepalive 25 allowed-ips 10.0.0.2/32 endpoint 10.10.10.2:3981
    # ip link set wg0 up

`[Peer B public key]` 的格式應當如同 `EsnHH9m6RthHSs+sd9uM6eCHe/mMVFaRh93GYadDDnM=`。`allowed-ips` 是 peer A 能夠向之發送流量的地址列表。`allowed-ips 0.0.0.0/0` 將允許向任意地址發送流量。

### Peer B 配置

如同 Peer A，只不過 wireguard 守護監聽 UDP 埠 39814 並且只接受 peer A 的連接

    # ip link add dev wg0 type wireguard
    # ip link set dev wg0 mtu 1420
    # ip addr add 10.0.0.2/24 dev wg0
    # wg set wg0 listen-port 3981 private-key ./privatekey
    # wg set wg0 peer [Peer A public key] persistent-keepalive 25 allowed-ips 10.0.0.1/32 endpoint 10.10.10.1:4857
    # ip link set wg0 up

### 基本檢查

不帶任何參數使用 wg 命令可以快速查看當前的配置。

例如，當 peer A 配置好之後，我們可以看見它的身份和與之關聯的 peers。

     peer-a$ wg
     interface: wg0
       public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8=
       private key: (hidden)
       listening port: 4857

     peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw=
       endpoint: 10.10.10.2:3981
       allowed ips: 10.0.0.2/32

此時我們可以 ping 通隧道的另一端：

     peer-a$ ping 10.0.0.2

### 配置持久化

配置可以通過 `showconf` 來保存

    # wg showconf wg0 > /etc/wireguard/wg0.conf
    # wg setconf wg0 /etc/wireguard/wg0.conf

### 示例 peer 配置

    /etc/wireguard/wg0.conf

    [Interface]
    PrivateKey = [CLIENT PRIVATE KEY]
    MTU = 1420

    [Peer]
    PublicKey = [SERVER PUBLICKEY]
    AllowedIPs = 10.0.0.0/24, 10.123.45.0/24, 1234:4567:89ab::/48
    Endpoint = [SERVER ENDPOINT]:5182
    PersistentKeepalive = 25

## 配置一個 VPN 伺服器

WireGuard 自帶一個快速創建和銷毀 VPN 伺服器的工具，`wg-quick`。注意這裡使用的配置文件不是一個能被 `wg setconf` 有效的配置文件，並且你可能至少要把 `eth0` 改成你實際使用的。

### 伺服器

    /etc/wireguard/wg0server.conf

    [Interface]
    Address = 10.0.0.1/24  # This is the virtual IP address, with the subnet mask we will use for the VPN
    PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    ListenPort = 5182
    PrivateKey = [SERVER PRIVATE KEY]
    MTU = 1420

    [Peer]
    PublicKey = [CLIENT PUBLIC KEY]
    AllowedIPs = 10.0.0.2/32  # 這表示客戶端只有一個 IP。

要使 iptables 規則生效，啟用 IPv4 轉發：

    # sysctl net.ipv4.ip_forward=1

永久保留這項改變，向 `/etc/sysctl.d/99-sysctl.conf` 添加 `net.ipv4.ip_forward = 1`。

使用 `wg-quick up wg0server` 啟用 Interface，`wg-quick down wg0server` 用以關閉

### 客戶端 (轉發所有流量)

    /etc/wireguard/wg0.conf

    [Interface]
    Address = 10.0.0.2/24  # The client IP from wg0server.conf with the same subnet mask
    PrivateKey = [CLIENT PRIVATE KEY]
    DNS = 10.0.0.1
    MTU = 1420

    [Peer]
    PublicKey = [SERVER PUBLICKEY]
    AllowedIPs = 0.0.0.0/0, ::0/0
    Endpoint = [SERVER ENDPOINT]:5182
    PersistentKeepalive = 25

使用 `wg-quick up wg0` 來啟用 Interface, 使用 `wg-quick down wg0` 來關閉。

使用 `systemctl enable wg-quick@wg0` 來自動啟動。

如果你使用 NetworkManager, 可能有必要啟用 NetworkManager-wait-online.service `systemctl enable NetworkManager-wait-online.service`

或者你使用的是 systemd-networkd, 啟用 systemd-networkd-wait-online.service `systemctl enable systemd-networkd-wait-online.service`

等待所有設備就緒再嘗試 WireGuard 連接

## 使用技巧

### 以加密的形式存儲私鑰

以加密的形式存儲私鑰可能是可以實現的，例如通過使用 pass包。只需將配置文件中[Interface]下的 PrivateKey 一行替換為。

     PostUp = wg set %i private-key <(su user -c "export PASSWORD_STORE_DIR=/path/to/your/store/; pass WireGuard/private-keys/%i")

where user is your username. See the `wg-quick(8)` man page for more details.

將其中的user替換成你的用戶名。更多細節請參見 `wg-quick(8)` man 頁面。

## 疑難解答

本文或本節需要翻譯。要貢獻翻譯，請訪問簡體中文翻譯團隊。

附註： 請提供模板的第一個位置參數以更詳細的指示。（在 Talk:WireGuard# 中討論）

### 路由定期被重置

NetworkManager 用戶應確保其未管理 WireGuard 接口。例如，創建以下配置文件：

    /etc/NetworkManager/conf.d/unmanaged.conf

    [keyfile]
    unmanaged-devices=type:wireguard

### DNS 無法解析

When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon new connection. This could be caused by a network manager or DHCP client overwriting `/etc/resolv.conf`.

By default wg-quick uses resolvconf to register new DNS entries (from the `DNS` keyword in the configuration file). This will cause issues with network managers and DHCP clients that do not use resolvconf, as they will overwrite `/etc/resolv.conf` thus removing the DNS servers added by wg-quick.

The solution is to use networking software that supports resolvconf.

注意：Users of systemd-resolved should make sure that systemd-resolvconf包 is installed.

Users of NetworkManager should know that it does not use resolvconf by default. It is recommended to use systemd-resolved. If this is undesirable, install openresolv包 and configure NetworkManager to use it: NetworkManager#Use openresolv.

### MTU 過低

Due to too low MTU (lower than 1280), wg-quick may have failed to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client.

    foo.config

    [Interface]
    Address = 10.200.200.2/24
    MTU = 1420
    PrivateKey = PEER_FOO_PRIVATE_KEY
    DNS = 10.200.200.1

### 密鑰長度或格式錯誤

To avoid the following error, put the key value in the configuration file and not the path to the key file.

    # wg-quick up wg0

    [#] ip link add wg0 type wireguard
    [#] wg setconf wg0 /dev/fd/63
    Key is not the correct length or format: `/path/example.key'
    Configuration parsing error
    [#] ip link delete dev wg0

### 無法在 NAT 或防火牆後建立持久連接

By default, WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). Adding `PersistentKeepalive = 25` to the `[Peer]` settings of a peer located behind a NAT and/or firewall can ensure that the connection remains open.

To temporarily set the persistent-keepalive setting via command line, run the following command:

    # wg set wg0 peer public_key persistent-keepalive 25

### 循環路由

Adding the endpoint IP to the allowed IPs list, the kernel will attempt to send handshakes to said device binding, rather than using the original route. This results in failed handshake attempts.

As a workaround, the correct route to the endpoint needs to be manually added using

    # ip route add endpoint_ip via gateway dev network_interface

E.g. for peer B from above in a standard LAN setup:

    # ip route add 203.0.113.102 via 192.168.0.1 dev eth0

To make this route persistent, the command can be added as `PostUp = ip route ...` to the `[Interface]` section of `wg0.conf`. However, on certain setups (e.g. using `wg-quick@.service` in combination with NetworkManager) this might fail on resume. Furthermore, this only works for a static network setup and fails if gateways or devices change (e.g. using Ethernet or Wi-Fi on a laptop).

Using NetworkManager, a more flexible solution is to start WireGuard using a dispatcher script. As root, create

    /etc/NetworkManager/dispatcher.d/50-wg0.sh

    #!/bin/sh
    case $2 in
      up)
        wg-quick up wg0
        ip route add <endpoint ip> via $IP4_GATEWAY dev $DEVICE_IP_IFACE
        ;;
      pre-down)
        wg-quick down wg0
        ;;
    esac

If not already running, start and enable `NetworkManager-dispatcher.service`. Also make sure that NetworkManager is not managing routes for `wg0`, see #Routes are periodically reset.

### 使用 systemd-networkd 時睡眠導致連接丟失

本文或本章節可能需要合併到systemd-networkd。

附註： Might reach more people on the dedicated page.（在 Talk:WireGuard#Merge proposal of Connection lost after sleep using systemd-networkd 中討論）

systemd version 253 introduced a change in how network interfaces are reconfigured when resuming from a suspended state[1]. In doing so, network connections managed by systemd-networkd will lose connection to the wireguard interface. Unless a kill switch is configured, this risks exposing the public IP address after resuming from suspend. To fix this, uncomment and change the value to `no` for `ManageForeignRoutingPolicyRules` in `/etc/systemd/networkd.conf`. [2]

## 參見

- Wikipedia:WireGuard
- Jason Donenfeld 的演講
- 郵件列表
- 非官方 WireGuard 文檔
- Debian:Wireguard

分類：​

- VPN

隱藏分類：​

- 使用「模板:糟糕的翻譯」標記的頁面或章節
- 使用「模板:Translateme」標記的頁面或章節
- 使用「模板:合併」標記的頁面或章節

WireGuard
新增話題