baicai

白菜

一个勤奋的代码搬运工!

通过 WireGuard 建立 VPN 访问家中内网

家裡網路沒有公網 IP,因此需要一台具有公網 IP 的伺服器作為 WireGuard 網路的 “server”。家中需要有一台設備作為 WireGuard 網路中的節點。我們將使用手機,在 4G 網路下檢查 VPN 是否搭建成功。

IP 段選擇#

WireGuard 組網需要使用一個不與你的任何設備的網路相衝突的 IP 地址段。像 192.0.2.0/24 、198.51.100.0/24 、203.0.113.0/24 這些分配為用於文件和示例中的 “TEST-NET”,這些地址段通常不會被你需要連接的其他網路所使用。

在下面的配置中,我會分別將 192.0.2.1、192.0.2.2、192.0.2.3 分配給公網伺服器、家中的 Mac 和 iPhone。

在伺服器上配置 WireGuard#

要使用 WireGuard,首先需要確保 Linux 內核支持。可使用 modinfo wireguard 命令檢查是否內置了 WireGuard。也可用過 uname -r 檢查內核版本是否為 5.6 以上。

安裝 wireguard#

Debian

apt install wireguard

其他系統參考:install

完成伺服器端的配置#

在正確安裝 wireguard 後,你可以通過如下命令快速創建一組公鑰和私鑰。

$ wg genkey | tee peer_A.key | wg pubkey > peer_A.pub && cat peer_A.key && cat peer_A.pub

創建 /etc/wireguard/wg0.conf 並填配置

[Interface]
PrivateKey = (your server private key here)
Address = 192.0.2.1/24
ListenPort = 51820

[Peer]
# 家中的 Mac
PublicKey = (Mac public key here)
AllowedIPs = 192.0.2.2/32, 192.168.1.0/24

[Peer]
# iPhone
PublicKey = (iPhone public key here)
AllowedIPs = 192.0.2.3/32

在 WireGuard 中,你需要手動給各個設備分配 IP,並確保每個設備都有唯一的 IP。Interface 包含了當前設備的設置,對於 “伺服器” 來說,ListenPort 是必須的。下面的每一個 Peer 段代表了能連接到本設備的另一個設備。

配置文件保存後,我們可以使用 wg-quick up wg0 來啟用配置文件。wg-quick 會自動配置路由表,無需我們手動設置。

記得放行 51820 UDP 端口。

家中 Mac 端的配置#

創建 /etc/wireguard/wg0.conf 並填配置

[Interface]
PrivateKey = (private key of Mac)
Address = 192.0.2.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = (public key of server)
AllowedIPs = 192.0.2.0/24
Endpoint = (server ip address):51820
PersistentKeepalive = 10

在這裡,我們將公網伺服器作為唯一的 Peer,通過設置 PersistentKeepalive 來進行連接的保活。這裡 AllowedIPs 的作用是確保來自於我們 WireGuard 子網網段的流量能被本機的 WireGuard 虛擬網卡進行處理。

iPhone 配置#

安裝 WireGuard  Download from App Store

這個配置可以參考應用商店的截屏。

附註#

保留地址段#

保留 IP 地址

小插曲#

當遇到錯誤提示:

/usr/bin/wg-quick: line 31: resolvconf: command not found [WireGuard | Debian]

可以創建軟鏈接解決

ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf

當遇到錯誤提示:

[SELF-SOLVED] Unit dbus-org.freedesktop.resolve1.service not found

可以通過啟動 systemd-resolved 服務解決

systemctl start systemd-resolved.service
systemctl enable systemd-resolved.service

配置詳解#

WireGuard 使用 INI 語法作為其配置文件格式。配置文件可以放在任何路徑下,但必須通過絕對路徑引用。默認路徑是 /etc/wireguard/wg0.conf

配置文件的命名形式必須為 ${WireGuard 接口的名稱}.conf。通常情況下 WireGuard 接口名稱以 wg 為前綴,並從 0 開始編號,但你也可以使用其他名稱,只要符合正則表達式 ^[a-zA-Z0-9_=+.-]{1,15}$ 就行。

你可以選擇使用 wg 命令來手動配置 VPN,但一般建議使用 wg-quick,它提供了更強大和用戶友好的配置體驗,可以通過配置文件來管理配置。

[Interface]#

定義本地 VPN 配置。例如:

1. 本地節點是客戶端,只路由自身的流量,只暴露一個 IP。

[Interface]
# Name = phone.example-vpn.dev
Address = 192.0.2.5/32
PrivateKey = <private key for phone.example-vpn.dev>

本地節點是中繼伺服器,它可以將流量轉發到其他對等節點(peer),並公開整個 VPN 子網的路由。

[Interface]
# Name = public-server1.example-vpn.tld
Address = 192.0.2.1/24
ListenPort = 51820
PrivateKey = <private key for public-server1.example-vpn.tld>
DNS = 1.1.1.1

# Name#

這是 INI 語法中的標準註釋,用於展示該配置部分屬於哪個節點。這部分配置會被 WireGuard 完全忽略,對 VPN 的行為沒有任何影響。

Address#

定義本地節點應該對哪個地址範圍進行路由。如果是常規的客戶端,則將其設置為節點本身的單個 IP(使用 CIDR 指定,例如 192.0.2.3/32);如果是中繼伺服器,則將其設置為可路由的子網範圍。
例如:

常規客戶端,只路由自身的流量:

Address = 192.0.2.3/32

中繼伺服器,可以將流量轉發到其他對等節點(peer):

Address = 192.0.2.1/24

也可以指定多個子網或 IPv6 子網:

Address = 192.0.2.1/24,2001:DB8::/64

ListenPort#

當本地節點是中繼伺服器時,需要通過該參數指定端口來監聽傳入 VPN 連接,默認端口號是 51820。常規客戶端不需要此選項。

PrivateKey#

本地節點的私鑰,所有節點(包括中繼伺服器)都必須設置。不可與其他伺服器共用。

私鑰可通過命令 wg genkey > example.key 來生成。

DNS#

通過 DHCP 向客戶端宣告 DNS 伺服器。客戶端將會使用這裡指定的 DNS 伺服器來處理 VPN 子網中的 DNS 請求,但也可以在系統中覆蓋此選項。例如:

#如果不配置則使用系統默認 DNS
#可以指定單個 DNS:
DNS = 1.1.1.1
#也可以指定多個 DNS:
DNS = 1.1.1.1,8.8.8.8

Table#

定義 VPN 子網使用的路由表,默認不需要設置。該參數有兩個特殊的值需要注意:

    Table = off : 禁止創建路由
    Table = auto(默認值) : 將路由添加到系統默認的 table 中,並啟用對默認路由的特殊處理。

例如:Table = 1234

MTU#

定義連接到對等節點(peer)的 MTU(Maximum Transmission Unit,最大傳輸單元),默認不需要設置,一般由系統自動確定。

PreUp#

啟動 VPN 接口之前運行的命令。這個選項可以指定多次,按順序執行。

例如:
添加路由:

    PreUp = ip rule add ipproto tcp dport 22 table 1234

PostUp#

啟動 VPN 接口之後運行的命令。這個選項可以指定多次,按順序執行。

例如:

從文件或某個命令的輸出中讀取配置值:
    PostUp = wg set %i private-key /etc/wireguard/wg0.key <(some command here)
添加一行日誌到文件中:
    PostUp = echo "$(date +%s) WireGuard Started" >> /var/log/wireguard.log
呼叫 WebHook:
    PostUp = curl https://events.example.dev/wireguard/started
添加路由:
    PostUp = ip rule add ipproto tcp dport 22 table 1234
添加 iptables 規則,啟用數據包轉發:
    PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
強制 WireGuard 重新解析對端域名的 IP 地址:
    PostUp = resolvectl domain %i "~."; resolvectl dns %i 192.0.2.1; resolvectl dnssec %i yes

PreDown#

停止 VPN 接口之前運行的命令。這個選項可以指定多次,按順序執行。
例如:

添加一行日誌到文件中:
    PreDown = echo "$(date +%s) WireGuard Going Down" >> /var/log/wireguard.log

PostDown#

停止 VPN 接口之後運行的命令。這個選項可以指定多次,按順序執行。
例如:

添加一行日誌到文件中:
PostDown = echo "$(date +%s) WireGuard  Down" >> /var/log/wireguard.log

[Peer]#

定義能夠為一個或多個地址路由流量的對等節點(peer)的 VPN 設置。對等節點(peer)可以是將流量轉發到其他對等節點(peer)的中繼伺服器,也可以是通過公網或內網直連的客戶端。

中繼伺服器必須將所有的客戶端定義為對等節點(peer),除了中繼伺服器之外,其他客戶端都不能將位於 NAT 後面的節點定義為對等節點(peer),因為路由不可達。對於那些只為自己路由流量的客戶端,只需將中繼伺服器作為對等節點(peer),以及其他需要直接訪問的節點。

配置示例:

對等節點(peer)是路由可達的客戶端,只為自己路由流量

[Peer]
# Name = public-server2.example-vpn.dev
Endpoint = public-server2.example-vpn.dev:51820
PublicKey = <public key for public-server2.example-vpn.dev>
AllowedIPs = 192.0.2.2/32

對等節點(peer)是位於 NAT 後面的客戶端,只為自己路由流量

[Peer]
# Name = home-server.example-vpn.dev
Endpoint = home-server.example-vpn.dev:51820
PublicKey = <public key for home-server.example-vpn.dev>
AllowedIPs = 192.0.2.3/32

對等節點(peer)是中繼伺服器,用來將流量轉發到其他對等節點(peer)

[Peer]
# Name = public-server1.example-vpn.tld
Endpoint = public-server1.example-vpn.tld:51820
PublicKey = <public key for public-server1.example-vpn.tld>
# 路由整個 VPN 子網的流量
AllowedIPs = 192.0.2.1/24
PersistentKeepalive = 25

Endpoint#

指定遠端對等節點(peer)的公網地址。如果對等節點(peer)位於 NAT 後面或者沒有穩定的公網訪問地址,就忽略這個字段。通常只需要指定中繼伺服器的 Endpoint,當然有穩定公網 IP 的節點也可以指定。例如:

通過 IP 指定:

Endpoint = 123.124.125.126:51820

通過域名指定:

Endpoint = public-server1.example-vpn.tld:51820

AllowedIPs#

允許該對等節點(peer)發送過來的 VPN 流量中的源地址範圍。同時這個字段也會作為本機路由表中 wg0 綁定的 IP 地址範圍。如果對等節點(peer)是常規的客戶端,則將其設置為節點本身的單個 IP;如果對等節點(peer)是中繼伺服器,則將其設置為可路由的子網範圍。可以使用,來指定多個 IP 或子網範圍。該字段也可以指定多次。

當決定如何對一個數據包進行路由時,系統首先會選擇最具體的路由,如果不匹配再選擇更寬泛的路由。例如,對於一個發往 192.0.2.3 的數據包,系統首先會尋找地址為 192.0.2.3/32 的對等節點(peer),如果沒有再尋找地址為 192.0.2.1/24 的對等節點(peer),以此類推。

例如:

對等節點(peer)是常規客戶端,只路由自身的流量:

AllowedIPs = 192.0.2.3/32

對等節點(peer)是中繼伺服器,可以將流量轉發到其他對等節點(peer):

AllowedIPs = 192.0.2.1/24

對等節點(peer)是中繼伺服器,可以轉發所有的流量,包括外網流量和 VPN 流量:

AllowedIPs = 0.0.0.0/0,::/0

對等節點(peer)是中繼伺服器,可以路由其自身和其他對等節點(peer)的流量:

AllowedIPs = 192.0.2.3/32,192.0.2.4/32

對等節點(peer)是中繼伺服器,可以路由其自身的流量和它所在的內網的流量:

AllowedIPs = 192.0.2.3/32,192.168.1.1/24

PublicKey#

對等節點(peer)的公鑰,所有節點(包括中繼伺服器)都必須設置。可與其他對等節點(peer)共用同一個公鑰。

公鑰可通過命令 wg pubkey < example.key > example.key.pub 來生成,其中 example.key 是上面生成的私鑰。

PersistentKeepalive#

如果連接是從一個位於 NAT 後面的對等節點(peer)到一個公網可達的對等節點(peer),那麼 NAT 後面的對等節點(peer)必須定期發送一個出站 ping 包來檢查連通性,如果 IP 有變化,就會自動更新 Endpoint。

例如:

本地節點與對等節點(peer)可直連:該字段不需要指定,因為不需要連接檢查。

對等節點(peer)位於 NAT 後面:該字段不需要指定,因為維持連接是客戶端(連接的發起方)的責任。

本地節點位於 NAT 後面,對等節點(peer)公網可達:需要指定該字段 PersistentKeepalive = 25,表示每隔 25 秒發送一次 ping 來檢查連接。

共享一個 peers.conf 文件#

如果某個 peer 的公鑰與本地接口的私鑰能夠配對,那麼 WireGuard 會忽略該 peer。利用這個特性,我們可以在所有節點上共用同一個 peer 列表,每個節點只需要單獨定義一個 [Interface] 就行了,即使列表中有本節點,也會被忽略。具體方式如下:

每個對等節點(peer)都有一個單獨的 /etc/wireguard/wg0.conf 文件,只包含 [Interface] 部分的配置。

每個對等節點(peer)共用同一個 /etc/wireguard/peers.conf 文件,其中包含了所有的 peer。

Wg0.conf 文件中需要配置一個 PostUp 鉤子,內容為

PostUp = wg addconf /etc/wireguard/peers.conf
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。