WireGuard 的 API 參考指南,包括設定、配置和使用,以及範例。
所有功勞均歸於 WireGuard 專案、zx2c4 和原始軟體的開源貢獻者,
這是我個人的非正式嘗試,旨在提供更全面的文件、API 參考和範例。
這些文件、範例程式碼和問題追蹤器的來源:https://github.com/pirate/wireguard-docs 更好的 HTML 頁面版本:https://docs.sweeting.me/s/wireguard
WireGuard 是由 Jason Donenfeld 等人以 C 語言編寫的開源 VPN 解決方案,旨在解決困擾其他現代伺服器到伺服器 VPN 產品(如 IPSec/IKEv2、OpenVPN 或 L2TP)的許多問題。它與 Tinc 和 MeshBird 等其他現代 VPN 產品有一些相似之處,即良好的密碼套件和最小的配置。截至 2020 年 1 月,它已合併到 Linux 核心 5.6 版本中,這意味著它將隨大多數 Linux 系統開箱即用。
官方連結
wg
、 wg-quick
WireGuard 目標
有關範例程式碼和文件來源,請參閱 https://github.com/pirate/wireguard-docs。
無論是生活在中國的長城後面,還是只是想在伺服器之間建立一個網絡,WireGuard 都是一個不錯的選擇,並且可以用作構建網絡的“樂高積木”(與ZFS 是用於構建文件系統的樂高積木非常相似) )。
WireGuard 不做的事情:
但是您可以在背景使用 WireGuard(例如 Tailscale 或 AltheaNet)為這些問題編寫自己的解決方案。
這些是文件和範例配置中使用的示範主機名稱、網域名稱、IP 位址和範圍。在進行您自己的設定時,將它們替換為您的首選值。
example-vpn.dev
可以替換為您控制的任何可公開存取的網域public-server1
、 public-server2
、 home-server
、 laptop
、 phone
可以更改為您的裝置主機名192.0.2.1/24
、 192.0.2.3
、 192.0.2.3/32
、 2001:DB8::/64
可以替換為您首選的子網路和位址(例如192.168.5.1/24
)無論您在下面的何處看到這些字串,它們都只是用作佔位符值來說明範例,沒有特殊含義。
確保更改配置中的 IP 位址!這些文件中使用的區塊由 IETF 保留用於範例目的,並且永遠不應在實際網路設定中使用。
192.0.2.0/24
(TEST-NET-1) IPv4 範例範圍 RFC57372001:DB8::/32
IPv6 範例範圍 RFC3849您可以使用您自己的設定所需的任何私有範圍,例如10.0.44.0/24
,只需確保它們不會與您的對等方所在的任何 LAN 子網路範圍衝突。
連接VPN的主機為自己註冊一個VPN子網路位址,如192.0.2.3
。它還可以選擇透過以逗號分隔的 CIDR 表示法指定子網路範圍來路由超出其自身位址的流量。
一個可公開存取的對等點/節點,充當 NAT 後面其他 VPN 對等點中繼流量的後備。反彈伺服器不是一種特殊類型的伺服器,它是一個普通的對等點,就像所有其他伺服器一樣,唯一的區別是它具有公共 IP 並打開了內核級 IP 轉發,這允許它透過 VPN 反彈流量給其他客戶。
查看更多資訊:https://tailscale.com/blog/how-nat-traversal-works/(Tailscale 在底層使用 Wireguard)
一組獨立於公共網際網路的 IP,例如 192.0.2.1-255 或 192.168.1.1/24。通常位於路由器提供的 NAT 後面,例如在辦公室互聯網 LAN 或家庭 Wi-Fi 網路中。
一種使用「遮罩」定義子網路及其大小的方法,較小的遮罩=子網路可用的更多位址位元以及範圍內的更多IP。最常見的:
192.0.2.1/32
(單一 IP 位址, 192.0.2.1
)網路遮罩 = 255.255.255.255
192.0.2.1/24
- 192.0.2.255
192.0.2.0
255 個 IP)網路遮罩 = 255.255.255.0
192.0.2.1/16
- 192.0.255.255
192.0.0.0
65,536 個 IP)網路遮罩 = 255.255.0.0
192.0.2.1/8
- 192.255.255.255
192.0.0.0
16,777,216 個 IP)網路遮罩 = 255.0.0.0
0.0.0.1/0
- 255.255.255.255
之間的0.0.0.0
個 IP)網路遮罩 = 0.0.0.0
2001:DB8::/64
https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
對於剛開始使用的人來說, 192.0.2.1/32
可能看起來是一種奇怪且令人困惑的引用單一 IP 的方式。不過,這種設計很好,因為它允許對等方在需要時公開多個 IP,而不需要多個符號。只要知道在任何地方看到類似192.0.2.3/32
東西,它實際上就意味著192.0.2.3
。
具有私有 IP 的子網路由位於其前面的路由器提供,進行網路位址轉換,各個節點不能從互聯網公開訪問,而是由路由器追蹤傳出連接並將回應轉發到正確的內部 IP(例如標準辦公室網路) 、家庭Wi-Fi 網路、免費公共Wi-Fi 網路等)
節點的可公開存取的位址:端口,例如123.124.125.126:1234
或some.domain.tld:1234
(必須可透過公共互聯網訪問,通常不能是像192.0.2.1
或192.168.1.1
這樣的私有 IP,除非同一子網路上的其他對等方可以使用該位址直接存取它)。
單一節點的 WireGuard 私鑰,透過以下方式產生: wg genkey > example.key
(永遠不會離開產生它的節點)
單一節點的 WireGuard 公鑰,透過以下方式產生: wg pubkey < example.key > example.key.pub
(與其他對等點共用)
網域名稱伺服器,用於將 VPN 用戶端的主機名稱解析為 IP,而不是允許 DNS 請求洩漏到 VPN 外部並洩漏流量。洩漏可透過 http://dnsleak.com 進行測試。
公共中繼只是普通的VPN 對等點,能夠充當NAT 後面的任何VPN 用戶端之間的中間中繼伺服器,它們可以將收到的任何VPN 子網路流量轉送到系統層級的正確對等點(WireGuard不關心這是如何發生的) ,它由核心net.ipv4.ip_forward = 1
和 iptables 路由規則處理)。
如果所有對等點均可公開訪問,則您不必擔心將其中一個對等點設定為中繼伺服器的特殊處理,只有當您有任何對等點從 NAT 後面連接時才需要這樣做。
每個客戶端只需在其配置中定義可公開存取的伺服器/對等點,綁定到 NAT 後面其他對等點的任何流量都將進入公共中繼AllowedIPs
路由中的包羅萬象的 VPN 子網路(例如192.0.2.1/24
),並相應地轉送一旦到達中繼伺服器。
總之:只應配置客戶端之間的直接連接,任何需要退回的連接不應定義為對等方,因為它們應首先前往退回伺服器,然後從那裡通過 VPN 路由回正確的客戶端。
更複雜的拓撲肯定是可以實現的,但以下是典型 WireGuard 設定中使用的基本路由方法:
Endpoint
位址和連接埠定義可直接存取的節點,以便 WireGuard 可以直接連接到開放連接埠並路由 UDP 封包,無需中間躍點。public-server2
時),定義具有硬Endpoint
的公共可存取節點和不具有硬編碼端點的 NAT 節點。連線將從 NAT 用戶端 -> 公用用戶端打開,然後只要透過來自 NAT 用戶端的傳出PersistentKeepalive
ping 保持連線保持活動狀態,流量就會在它們之間雙向直接路由。public-server1
連接,並且只要連接有效,流量就會通過中間反彈伺服器轉送都保持活著。當可用時,其他對等方提供的更具體(通常也更直接)的路由將優先,否則流量將回退到最不具體的路由,並使用192.0.2.1/24
包羅萬象將流量轉送到反彈伺服器,該流量將在其中然後由中繼伺服器的系統路由表 ( net.ipv4.ip_forward = 1
) 路由回 VPN 到接受該流量路由的特定對等方。如果尚未定義,WireGuard 不會自動查找最快的路由或嘗試在對等點之間形成直接連接,它只是從[Peers]
中最具體的路由到最不具體的路由。
您可以透過測量 ping 時間來確定每個躍點的唯一長度,並檢查以下輸出,從而確定 WireGuard 對給定位址使用哪種路由方法:
wg show wg0
WireGuard 對所有流量使用加密的 UDP 封包,它不提供封包傳送或排序的保證,因為這是由加密隧道內的 TCP 連線處理的。
延伸閱讀:
WireGuard 聲稱其效能比大多數其他競爭 VPN 解決方案更快,但具體數字有時存在爭議,並且可能取決於硬體級加速是否可用於某些加密密碼。
WireGuard 的效能提升是透過在核心層級處理路由以及使用在所有核心上運行的現代密碼套件來加密流量來實現的。 WireGuard 也透過使用沒有交付/訂購保證的 UDP 獲得了顯著優勢(與透過 TCP 運作或實現自己的保證交付機制的 VPN 相比)。
延伸閱讀:
WireGuard 使用以下協定和原語來保護流量:
WireGuard 的密碼學本質上是 Trevor Perrin 的噪音框架的實例。它既現代又簡單。其他所有 VPN 選項都是一團混亂的協商、握手和複雜的狀態機。 WireGuard 就像是 VPN 中的 Signal/Axolotl,只不過它比雙棘輪訊息協定更簡單、更容易推理(在本例中是加密的)。基本上就是VPN軟體的qmail。大約有 4000 行程式碼。它比競爭對手小多個數量級。
https://news.ycombinator.com/item?id=14599834
延伸閱讀:
雙向身分驗證是透過每個對等點的簡單公鑰/私鑰對來實現的。每個對等點在設定階段產生這些金鑰,並僅與其他對等點共用公鑰。
除了每個節點的公鑰/私鑰之外,不需要其他憑證或預先共用金鑰。
可以使用 Ansible 或 Kubernetes Secrets 等單獨的服務在大型部署中處理金鑰產生、分發和撤銷。
一些有助於金鑰分發和部署的服務:
如果您不想在wg0.conf
中對密鑰進行硬編碼,您還可以從檔案或透過命令讀取密鑰,這使得透過第 3 方服務管理密鑰變得更加容易:
[Interface]
...
PostUp = wg set %i private-key /etc/wireguard/wg0.key <(cat /some/path/%i/privkey)
從技術上講,只要客戶端沒有同時使用相同的金鑰連接到兩個伺服器,多個伺服器就可以共享相同的私鑰。這是合理設定的場景範例是,如果您使用循環 DNS 來平衡假裝為單一伺服器的兩個伺服器之間的連接負載。然而,大多數時候,每個對等點都應該有自己的公鑰/私鑰對,以便對等點無法讀取彼此的流量,並且可以單獨撤銷。
大致流程概述:
apt install wireguard
或pkg/brew install wireguard-tools
wg genkey
+ wg pubkey
wg0.conf
WireGuard 設定檔[Interface]
在定義伺服器接受位址Address = 192.0.2.1/24
路由的位址時,請確保指定整個 VPN 子網路的 CIDR 範圍[Peer]
使用對應的遠端公鑰為每個加入 VPN 的用戶端建立一個對等部分wg0.conf
[Interface]
確保為不中繼流量的客戶端對等方僅指定一個 IP Address = 192.0.2.3/32
。[Peer]
為不在 NAT 後面的每個公共對等點建立一個對等點部分,請確保在定義充當退回伺服器的遠端對等點時指定整個 VPN 子網路的 CIDR 範圍AllowedIPs = 192.0.2.1/24
。確保為不中繼流量且僅充當簡單客戶端的遠端對等點指定單獨的 IP AllowedIPs = 192.0.2.3/32
。wg-quick up /full/path/to/wg0.conf
在主中繼伺服器上啟動 WireGuardwg-quick up /full/path/to/wg0.conf
在所有客戶端上啟動 WireGuardping 192.0.2.3
首先檢查到AllowedIPs = 192.0.2.3/32
的對等點的直接路由,然後回退到接受IP 的中繼伺服器在整個子網路中 # install on Ubuntu
sudo add-apt-repository ppa:wireguard/wireguard
apt install wireguard
# install on macOS
brew install wireguard-tools
# install on FreeBSD
pkg install wireguard
# install on iOS/Android using Apple App Store/Google Play Store
# install on other systems using https://www.wireguard.com/install/#installation
# to enable the kernel relaying/forwarding ability on bounce servers
echo " net.ipv4.ip_forward = 1 " | sudo tee -a /etc/sysctl.conf
echo " net.ipv4.conf.all.proxy_arp = 1 " | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf
# to add iptables forwarding rules on bounce servers
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.0.2.0/24 -o eth0 -j MASQUERADE
nano wg0.conf # can be placed anywhere, must be referred to using absolute path (usually placed in /etc/wireguard/wg0.conf on most Linux systems)
# generate private key
wg genkey > example.key
# generate public key
wg pubkey < example.key > example.key.pub
wg-quick up /full/path/to/wg0.conf
wg-quick down /full/path/to/wg0.conf
# Note: you must specify the absolute path to wg0.conf, relative paths won't work
# If wg0.conf is in /etc/wireguard you can use the simpler:
wg-quick up wg0
# start/stop VPN network interface
ip link set wg0 up
ip link set wg0 down
# register/unregister VPN network interface
ip link add dev wg0 type wireguard
ip link delete dev wg0
# register/unregister local VPN address
ip address add dev wg0 192.0.2.3/32
ip address delete dev wg0 192.0.2.3/32
# register/unregister VPN route
ip route add 192.0.2.3/32 dev wg0
ip route delete 192.0.2.3/32 dev wg0
# show system LAN and WAN network interfaces
ip address show
# or if ip is not available:
ifconfig
# show system VPN network interfaces
ip link show wg0
# or
ifconfig wg0
# show WireGuard VPN interfaces
wg show all
wg show wg0
# show public IP address
ip address show eth0
# or
ifconfig eth0
# or
dig -4 +short myip.opendns.com @resolver1.opendns.com
# show VPN IP address
ip address show wg0
# show WireGuard routing table and peer connections
wg show
wg show wg0 allowed-ips
# show system routing table
ip route show table main
ip route show table local
# show system route to specific address
ip route get 192.0.2.3
若要啟用額外的日誌記錄,請執行:
modprobe wireguard
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
要追蹤日誌:
dmesg -wH
具有現代核心和安全啟動的系統可能需要停用安全啟動 DKMS 簽名驗證以允許存取核心日誌。
mokutil --disable-verification
reboot
# check that the main relay server is accessible directly via public internet
ping public-server1.example-vpn.dev
# check that the main relay server is available via VPN
ping 192.0.2.1
# check that public peers are available via VPN
ping 192.0.2.2
# check that remote NAT-ed peers are available via VPN
ping 192.0.2.3
# check that NAT-ed peers in your local LAN are available via VPN
ping 192.0.2.4
# install iperf using your preferred package manager
apt/brew/pkg/opkg install iperf
# check bandwidth over public internet to relay server
iperf -s # on public relay server
iperf -c public-server1.example-vpn.dev # on local client
# check bandwidth over VPN to relay server
iperf -s # on public relay server
iperf -c 192.0.2.1 # on local client
# check bandwidth over VPN to remote public peer
iperf -s # on remote public peer
iperf -c 192.0.2.2 # on local client
# check bandwidth over VPN to remote NAT-ed peer
iperf -s # on remote NAT-ed peer
iperf -c 192.0.2.3 # on local client
# check bandwidth over VPN to local NAT-ed peer (on same LAN)
iperf -s # on local NAT-ed peer
iperf -c 192.0.2.4 # on local client
使用 http://dnsleak.com 檢查 DNS 洩漏,或透過檢查尋找解析器:
dig example.com A
WireGuard 配置採用 INI 語法,在通常稱為wg0.conf
的檔案中定義。它可以放置在系統上的任何位置,但通常放置在/etc/wireguard/wg0.conf
中。
運行任何wg-quick
命令時,配置路徑被指定為參數,例如:
wg-quick up /etc/wireguard/wg0.conf
(總是指定完整的絕對路徑)
設定檔名的格式必須為${name of the new WireGuard interface}.conf
。 WireGuard 介面名稱通常以wg
為前綴,並從0
開始編號,但您可以使用與正規表示式^[a-zA-Z0-9_=+.-]{1,15}$
相符的任何名稱。
設定檔可以選擇使用有限的wg
配置選項集,或更擴展的wg-quick
選項,具體取決於啟動 WireGuard 的首選命令。這些文件建議堅持使用wg-quick
,因為它提供了更強大且用戶友好的配置體驗。
跳到定義:
¶ [Interface]
¶ # Name = node1.example.tld
¶ Address = 192.0.2.3/32
¶ ListenPort = 51820
¶ PrivateKey = localPrivateKeyAbcAbcAbc=
¶ DNS = 1.1.1.1,8.8.8.8
¶ Table = 12345
¶ MTU = 1500
¶ PreUp = /bin/example arg1 arg2 %i
¶ PostUp = /bin/example arg1 arg2 %i
¶ PreDown = /bin/example arg1 arg2 %i
¶ PostDown = /bin/example arg1 arg2 %i
¶ [Peer]
¶ # Name = node2-node.example.tld
¶ AllowedIPs = 192.0.2.1/24
¶ Endpoint = node1.example.tld:51820
¶ PublicKey = remotePublicKeyAbcAbcAbc=
¶ PersistentKeepalive = 25
[Interface]
定義本地節點的 VPN 設定。
範例
[Interface]
# Name = phone.example-vpn.dev
Address = 192.0.2.5/32
PrivateKey = <private key for phone.example-vpn.dev>
[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 行為沒有影響。
注意:某些操作和應用程式會從 .conf 檔案中刪除所有註釋,包括# Name
。如果您需要識別對等方,請考慮使用wireguard vanity key產生器,例如wireguard-vanity-keygen或wireguard-vanity-address,它允許您將主機名稱包含在主機的公鑰中。金鑰產生可能需要幾分鐘(4 個字元)、幾小時(5 個字元)或更長時間,因此請考慮對名稱較長的主機使用縮寫。
Address
定義本地節點應路由流量的位址範圍。根據節點是加入 VPN 子網路的簡單客戶端還是在多個客戶端之間中繼流量的反彈伺服器,可以將其設定為節點本身的單一 IP(使用 CIDR 表示法指定),例如 192.0.2.3/32 ),或節點可以為其路由流量的一系列IPv4/IPv6 子網路。
範例
節點是一個只為自己路由流量的客戶端Address = 192.0.2.3/32
節點是一個公共反彈伺服器,可以將流量中繼到其他對等點
當節點充當公共反彈伺服器時,它應該將其設定為可以路由流量的整個子網,而不僅僅是其自身的單一 IP。
Address = 192.0.2.1/24
Address = 192.0.2.1/24,2001:DB8::/64
ListenPort
當節點充當公共反彈伺服器時,它應該對連接埠進行硬編碼以偵聽來自公共互聯網的傳入 VPN 連線。不充當中繼的客戶端不應設定此值。
範例
ListenPort = 51820
ListenPort = 7000
PrivateKey
這是本地節點的私鑰,永遠不會與其他伺服器共用。所有節點都必須有一個私鑰集,無論它們是中繼流量的公共反彈伺服器,還是加入 VPN 的簡單用戶端。
此金鑰可以使用wg genkey > example.key
生成
範例
PrivateKey = somePrivateKeyAbcdAbcdAbcdAbcd=
DNS
透過 DHCP 向 VPN 用戶端通告的 DNS 伺服器,大多數用戶端將使用此伺服器透過 VPN 進行 DNS 請求,但用戶端也可以在其節點上本機覆寫此值
範例
DNS = 1.1.1.1
DNS = 1.1.1.1,8.8.8.8
Table
(可選)定義用於 WireGuard 路由的路由表,大多數設定無需配置。
有兩個特殊值:「off」完全禁用路由的創建,「auto」(預設值)將路由添加到預設表並啟用對預設路由的特殊處理。
https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
範例
Table = 1234
MTU
可選擇定義連接到對等方時使用的最大傳輸單元(MTU,又稱資料包/幀大小),大多數設定無需配置。
MTU 是根據端點位址或系統預設路由自動決定的,這通常是明智的選擇。
https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
範例
MTU = 1500
PreUp
可以選擇在啟動介面之前執行命令。可以多次指定此選項,命令會按照它們在檔案中出現的順序執行。
範例
PreUp = ip rule add ipproto tcp dport 22 table 1234
PostUp
可以選擇在介面啟動後運行命令。這個選項可以出現多次,就像 PreUp 一樣
範例
從檔案或某些命令的輸出讀取設定值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/?key=abcdefg
新增一條路由到系統路由表PostUp = ip rule add ipproto tcp dport 22 table 1234
新增 iptables 規則以在 WireGuard 介面上啟用封包轉發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
(可選)在介面關閉之前運行命令。這個選項可以出現多次,就像 PreUp 一樣
範例
將一行記錄到文件中PostDown = echo "$(date +%s) WireGuard Going Down" >> /var/log/wireguard.log
訪問另一台伺服器上的 webhook
PostDown = curl https://events.example.dev/wireguard/stopping/?key=abcdefg
PostDown
可以選擇在介面關閉後執行命令。這個選項可以出現多次,就像 PreUp 一樣
範例
將一行記錄到文件中PostDown = echo "$(date +%s) WireGuard Stopped" >> /var/log/wireguard.log
訪問另一台伺服器上的 webhook
PostDown = curl https://events.example.dev/wireguard/stopped/?key=abcdefg
刪除在 WireGuard 介面上轉送封包的 iptables 規則PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
定義能夠為一個或多個位址(自身和/或其他對等點)路由流量的遠端對等點的 VPN 設定。對等點可以是將流量中繼到其他對等點的公共反彈伺服器,也可以是透過 LAN/網際網路直接存取的用戶端,該用戶端不在 NAT 後方且僅為自身路由流量。
所有用戶端都必須定義為公共退回伺服器上的對等方。僅為自己路由流量的簡單客戶端,只需為公共中繼定義對等點,以及可直接存取的任何其他節點。位於單獨 NAT 後面的節點不應定義為公共伺服器配置之外的對等點,因為單獨 NAT 之間沒有可用的直接路由。相反,NAT 後面的節點應僅將公共中繼伺服器和其他公共客戶端定義為其對等方,並且應在接受路由並將 VPN 子網路的流量反彈到遠端 NAT 的公共伺服器上指定AllowedIPs = 192.0.2.1/24
同行。
總之,所有節點都必須在主退回伺服器上定義。在客戶端伺服器上,只有可從節點直接存取的對等點才應定義為該節點的對等點,必須由退回伺服器中繼的任何對等點都應排除在外,並由中繼伺服器的包羅萬象的路由進行處理。
在下方文件中概述的配置中,單一伺服器public-server1
可作為可公開存取和 NAT 用戶端混合的中繼反彈伺服器,並且對等點在每個節點上進行相應配置:
在public-server1
wg0.conf
(退回伺服器)
[peer]
清單: public-server2
、 home-server
、 laptop
、 phone
在public-server2
wg0.conf
(簡單的公共客戶端)
[peer]
列表: public-server1
在home-server
wg0.conf
中(NAT 後面的簡單客戶端)
[peer]
清單: public-server1
、 public-server2
在laptop
wg0.conf
中(NAT 後面的簡單客戶端)
[peer]
清單: public-server1
、 public-server2
在phone
wg0.conf
中(NAT 後面的簡單客戶端)
[peer]
清單: public-server1
、 public-server2
範例
[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]
# 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]
# Name = public-server1.example-vpn.tld
Endpoint = public-server1.example-vpn.tld:51820
PublicKey = <public key for public-server1.example-vpn.tld>
# routes traffic to itself and entire subnet of peers as bounce server
AllowedIPs = 192.0.2.1/24
PersistentKeepalive = 25
# Name
這只是 INI 語法中的一個標準註釋,用於幫助追蹤哪個配置部分屬於哪個節點,它完全被 WireGuard 忽略,並且對 VPN 行為沒有影響。
Endpoint
定義遠端對等點的可公開存取的位址。對於 NAT 後面的對等點或沒有穩定的可公開存取的 IP:PORT 對的對等點,應忽略此操作。通常,這只需要在主反彈伺服器上定義,但也可以在具有穩定 IP 的其他公共節點上定義,例如下面範例配置中的public-server2
。
範例
Endpoint = 123.124.125.126:51820
(也支援 IPv6)Endpoint = public-server1.example-vpn.tld:51820
AllowedIPs
這定義了對等方將路由流量的 IP 範圍。在簡單客戶端上,這通常是單一位址(簡單客戶端本身的 VPN 位址)。對於退回伺服器,這將是中繼伺服器能夠為其路由流量的 IP 或子網路範圍。可以使用逗號分隔的 IPv4 或 IPv6 CIDR 表示法指定多個 IP 和子網路(從單一 /32 或 /128 位址,一直到0.0.0.0/0
和::/0
以指示發送所有內容的預設路由)通過該對等點的互聯網和VPN 流量)。此選項可以指定多次。
在決定如何路由資料包時,系統會先選擇最具體的路由,然後再選擇更廣泛的路由。因此,對於發送到192.0.2.3
的資料包,系統將首先專門查找對等廣告192.0.2.3/32
,然後回退到對等廣告192.0.2.1/24
或更大的範圍(如0.0.0.0/0
)最後的手段。
範例
對等體是一個簡單的客戶端,只接受來自/自身的流量AllowedIPs = 192.0.2.3/32
對等體是一個中繼伺服器,可以將 VPN 流量反彈到所有其他對等體AllowedIPs = 192.0.2.1/24
Peer 是中繼伺服器,可轉送所有網際網路和 VPN 流量(如代理程式),包括 IPv6
AllowedIPs = 0.0.0.0/0,::/0
對等體是一個中繼伺服器,路由到它自己和僅一個其他對等體AllowedIPs = 192.0.2.3/32,192.0.2.4/32
對等體是一個中繼伺服器,路由到其自身及其本地 LAN 上的所有節點AllowedIPs = 192.0.2.3/32,192.168.1.1/24
PublicKey
這是遠端節點的公鑰,可與所有對等點共用。所有節點都必須有一個公鑰集,無論它們是中繼流量的公共反彈伺服器,還是加入 VPN 的簡單用戶端。
此金鑰可以使用wg pubkey < example.key > example.key.pub
產生。 (有關如何產生私鑰example.key
的信息,請參閱上文)
範例
PublicKey = somePublicKeyAbcdAbcdAbcdAbcd=
PersistentKeepalive
如果連線是從 NAT 化對等方到公共對等方,則 NAT 後面的節點必須定期發送傳出 ping,以便在 NAT 路由器的連線表中保持雙向連線處於活動狀態。
範例
本地公共節點到遠端公共節點
該值應保持未定義,因為不需要持久 ping。
本地公共節點到遠端 NAT 節點
該值應保持未定義,因為保持連線活動是客戶端的責任,因為如果逾時,伺服器無法重新開啟與客戶端的死連線。
本地 NAT 節點到遠端公共節點PersistentKeepalive = 25
這將每 25 秒發送一次 ping,以保持本地 NAT 路由器連接表中的連接處於開啟狀態。
這些文件中的範例主要使用 IPv4,但 WireGuard 本身支援 IPv6 CIDR 表示法和它支援 IPv4 的所有位置的位址,只需像新增任何其他子網路範圍或位址一樣新增它們即可。
例子
[Interface]
Address = 192.0.2.3/24, 2001:DB8::/64
[Peer]
...
AllowedIPs = 0.0.0.0/0, ::/0
如果您想透過 VPN 轉送所有Internet 流量,而不僅僅是將其用作伺服器到伺服器子網,則可以將0.0.0.0/0, ::/0
新增至要透過管道傳輸的對等點的AllowedIPs
定義中您的流量通過。
即使僅轉送 IPv4 流量,請確保指定 IPv6 包羅萬象,以避免在 VPN 外部洩漏 IPv6 封包,請參閱:
https://www.reddit.com/r/WireGuard/comments/b0m5g2/ipv6_leaks_psa_for_anyone_here_using_wireguard_to/
例子
[Interface]
# Name = phone.example-vpn.dev
Address = 192.0.2.3/32
PrivateKey = <private key for phone.example-vpn.dev>
[Peer]
# Name = public-server1.example-vpn.dev
PublicKey = <public key for public-server1.example-vpn.dev>
Endpoint = public-server1.example-vpn.dev:51820
AllowedIPs = 0.0.0.0/0, ::/0
WireGuard 有時可以在 NAT 後面的兩個客戶端之間本機建立連接,而無需公共中繼伺服器,但在大多數情況下這是不可能的。只有當至少一台主機具有穩定、可公開存取的IP 位址:可提前硬編碼的連接埠對時,NAT 到NAT 連線才可能實現,無論是使用透過動態DNS 更新的FQDN,還是使用透過動態DNS 更新的靜態公共IP由傳出資料包打開的非隨機 NAT 端口,只要所有對等方都可以事先進行通信,一旦連接啟動,它就不會改變,任何東西都可以工作。
需要事先配置已知的連接埠和位址,因為 WireGuard 沒有可用於動態搜尋其他主機的訊號層或公共 STUN 伺服器。 WebRTC 是一個可以動態配置兩個 NAT 之間連接的協定範例,但它是透過使用帶外訊號伺服器來偵測每個主機的 IP:連接埠組合來實現這一點的。 WireGuard 沒有這個功能,因此它只能與硬編碼的Endpoint
+ ListenPort
一起使用(以及PersistentKeepalive
因此它在不活動後不會丟失)。
從 Tailscale 的 NAT 穿越聖經了解更多資訊:https://tailscale.com/blog/how-nat-traversal-works/
Endpoint
。如果它們都位於 NAT 後面且沒有穩定的 IP 位址,那麼您需要使用動態 DNS 或其他解決方案來為至少一個對等方擁有穩定的、可公開存取的網域/IPListenPort
,且其 NAT 路由器不得進行 UDP 來源連接埠隨機化,否則傳回封包將被傳送至硬編碼的ListenPort
並被路由器丟棄,而不是使用由路由器分配的隨機連接埠對傳出資料包進行 NATPersistentKeepalive
,以便它們不斷發送傳出 ping 來保持連接在其 NAT 路由表中持久存在發送被拒絕的初始資料包,然後利用路由器現在建立的轉送規則來接受回應的過程稱為「UDP 打洞」。
當您傳送 UDP 封包時,路由器(通常)會建立一條臨時規則,將來源位址和連接埠對應到目標位址和端口,反之亦然。從目標位址和連接埠(而不是其他)返回的 UDP 封包將傳遞到原始來源位址和連接埠(而不是其他)。這就是大多數 UDP 應用程式在 NAT 後面運行的方式(例如 BitTorrent、Skype 等)。此規則將在幾分鐘不活動後逾時,因此 NAT 後面的用戶端必須定期發送傳出資料包以保持其開啟狀態(請參閱PersistentKeepalive
)。
當兩個端點都位於 NAT 或防火牆後面時,要使其發揮作用,需要兩個端點大約同時向對方發送資料包。這意味著雙方需要事先知道彼此的公共 IP 位址和連接埠號,在 WireGuard 的情況下,這是透過在wg0.conf
中對雙方的預定義連接埠進行硬編碼來實現的。
截至 2019 年,許多過去有效的舊打孔方法不再有效。一個例子是 pwnat 首創的一種新穎方法,該方法從 NAT 外部偽造 ICMP 逾時響應,以將封包返回到經過 NAT 處理的對等方,從而洩漏其自己的來源連接埠。 NAT 到 NAT 連接兩側的硬編碼 UDP 連接埠和公共 IP(如上所述)仍然適用於一小部分網路。一般來說,網路越“企業化”,就越不可能對公共 UDP 連接埠進行打孔(例如,商業公共 Wi-Fi 和蜂窩數據 NAT 通常不起作用)。
如果所有端點都位於 NAT 後面且具有嚴格的 UDP 來源連接埠隨機化(例如大多數蜂窩數據網路),則 NAT 到 NAT 連接是不可能的。由於雙方都無法對ListenPort
進行硬編碼並保證其 NAT 在傳出 ping 後接受該端口上的流量,因此您無法協調對等方之間的初始打洞的端口,並且連接將失敗。因此,您通常無法在 LTE/3g 網路上進行電話到電話的連接,但您也許可以在辦公室或家庭擁有穩定的公共 IP 並且沒有網路連接的情況下進行電話到辦公室或電話到家庭的連接。進行來源埠隨機化。
來自 NAT 後面的 NAT 到 NAT 連線具有嚴格的來源連接埠隨機化是可能的,您只需要一個訊號伺服器來告訴每一方對方的 IP:連接埠元組。以下是使用 WireGuard 實現此目的的一些實作:
許多使用者報告每當動態 IP 變更時都必須重新啟動 WireGuard,因為它僅在啟動時解析主機名稱。若要強制 WireGuard 更頻繁地重新解析動態 DNS Endpoint
主機名,您可能需要使用PostUp
掛鉤每隔幾分鐘或幾小時重新啟動 WireGuard。
您可以透過在客戶端和伺服器上使用 netcat 來查看打孔設定是否可行,以查看哪些連接埠和連線順序可以開啟雙向連線:執行nc -v -u -p 51820 <address of peer2> 51820
(在peer1上)和nc -v -u -l 0.0.0.0 51820
(在peer2上),然後在兩個視窗中鍵入以查看是否可以進行雙向流量。如果無論哪個對等方發送初始資料包都不起作用,則 WireGuard 將無法在沒有公共中繼伺服器的對等方之間工作。
NAT 到 NAT 連線通常更不穩定,並且有其他限制,這就是為什麼仍然建議使用後備公共中繼伺服器。
例子
對等1:
[Interface]
...
ListenPort 12000
[Peer]
...
Endpoint = peer2.example-vpn.dev:12000
PersistentKeepalive = 25
對等2:
[Interface]
...
ListenPort 12000
[Peer]
...
Endpoint = peer1.example-vpn.dev:12000
PersistentKeepalive = 25
注意:本節涉及 VPN 子網路內的動態對等 IP,而不是動態公共Endpoint
位址。
對等 IP 的動態分配(而不是僅具有固定對等點)正在開發中,WIP 實作可在此處取得:https://github.com/WireGuard/wg-dynamic
您也可以透過使用PostUp
在運行時從檔案中讀取 IP 值來自行建立動態分配系統(請參閱下文)。
例子
[Interface]
...
PostUp = wg set %i allowed-ips /etc/wireguard/wg0.key <(some command)
https://git.zx2c4.com/wireguard-go/about/
用 Go 編寫的兼容用戶層 WireGuard 實作。
https://git.zx2c4.com/wireguard-rs/about/
用 Rust 編寫的 WireGuard 的不完整、不安全的使用者空間實作(尚未準備好供公眾使用)。
https://git.zx2c4.com/wireguard-hs/about/
用 Haskell 編寫的 WireGuard 的不完整、不安全的使用者空間實作(未準備好供公眾使用)。
https://github.com/cloudflare/boringtun
用 Rust 編寫的不合規的獨立 WireGuard 實作(由 CloudFlare 編寫的單獨分支)。請參閱 https://blog.cloudflare.com/boringtun-userspace-wireguard-rust/
特定於平台的 WireGuard 應用程式
https://git.zx2c4.com/wireguard-ios/about/
https://git.zx2c4.com/wireguard-android/about/
https://git.zx2c4.com/wireguard-windows/about/
所有使用者空間實作都比在核心空間中執行的本機 C 版本慢,但透過在使用者空間中運行提供了其他好處(例如更容易的容器化、相容性等)。
這些是一些 GUI 和 CLI 工具,它們包裝 WireGuard 以協助配置、部署、金鑰管理和連接。
這些捷徑的功勞在於:https://www.ericlight.com/new-things-i-didnt-know-about-wireguard.html
WireGuard 將忽略其公鑰與介面私鑰相符的對等點。因此,您可以在任何地方分發單一對等點列表,並且僅在每個伺服器上單獨定義[Interface]
。
請參閱:https://lists.zx2c4.com/pipermail/wireguard/2018-December/003703.html
您可以將其與wg addconf
結合使用,如下所示:
每個對等點都有自己的/etc/wireguard/wg0.conf
文件,該文件僅包含其[Interface]
部分。
每個對等點還有一個共用的/etc/wireguard/peers.conf
文件,其中包含所有對等點。
wg0.conf
檔案還有一個PostUp
掛鉤: PostUp = wg addconf /etc/wireguard/peers.conf
。
由您決定如何分享peers.conf
,無論是透過適當的編排平台、像Dropbox這樣更簡單的平台,還是像Ceph這樣有點狂野的平台。我不知道,但是你可以隨意地亂扔一個對等部分,而不用擔心它是否與介面相同,這真是太棒了。
您可以透過任意命令或從檔案中讀取值來設定設定值,這使得金鑰管理和部署變得更加容易,因為您可以在運行時從 Kubernetes Secrets 或 AWS KMS 等第三方服務讀取金鑰。
請參閱:https://lists.zx2c4.com/pipermail/wireguard/2018-December/003702.html
例子
您可以透過執行以下操作來讀取檔案作為PrivateKey
:
PostUp = wg set %i private-key /etc/wireguard/wg0.key <(some command)
WireGuard 可以在不同程度上輕鬆地在 Docker 中運作。在最簡單的情況下,可以將--privileged
和--cap-add=all
參數新增至 docker 命令以啟用核心模組的載入。
設定可能會變得有些複雜,並且高度依賴您想要實現的目標。您可以讓 WireGuard 本身在容器中運行並向主機公開網路接口,也可以讓 WireGuard 在主機上運行以向特定容器公開接口。
請參閱下面的 Docker 容器vpn_test
透過 WireGuard 中繼伺服器路由其所有流量的範例。
version : ' 3 '
services :
wireguard :
image : linuxserver/wireguard
ports :
- 51820:51820/udp
cap_add :
- NET_ADMIN
- SYS_MODULE
volumes :
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro
wg0.conf
:
[Interface]
# Name = relay1.wg.example.com
Address = 192.0.2.1/24
ListenPort = 51820
PrivateKey = oJpRt2Oq27vIB5/ UVb7BRqCwad2YMReQgH5tlxz8YmI =
DNS = 1.1.1.1,8.8.8.8
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT ; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT ; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# Name = peer1.wg.example.com
PublicKey = I+hXRAJOG/UE2IQvIHsou2zTgkUyPve2pzvHTnd/ 2Gg =
AllowedIPs = 192.0.2.2/32
在此範例中,來自speedtest
容器內部的所有流量都將通過wireguard VPN。若要僅路由某些流量,請將下方wg0.conf
中的0.0.0.0/0
替換為您想要透過 VPN 路由的子網路範圍。
docker-compose.yml
:
version : ' 3 '
services :
wireguard :
image : linuxserver/wireguard
cap_add :
- NET_ADMIN
- SYS_MODULE
volumes :
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro
vpn_test :
image : curlimages/curl
entrypoint : curl -s http://whatismyip.akamai.com/
network_mode : ' service:wireguard '
wg0.conf
:
[Interface]
# Name = peer1.wg.example.com
Address = 192.0.2.2/32
PrivateKey = YCW76edD4W7nZrPbWZxPZhcs32CsBLIi1sEhsV/ sgk8 =
DNS = 1.1.1.1,8.8.8.8
[Peer]
# Name = relay1.wg.example.com
Endpoint = relay1.wg.example.com:51820
PublicKey = zJNKewtL3gcHdG62V3GaBkErFtapJWsAx+ 2um0c0B1s =
AllowedIPs = 192.0.2.1/24,0.0.0.0/0
PersistentKeepalive = 21
有關更多詳細信息,請參閱下面的進一步閱讀:Docker 部分。
有關更詳細的說明,請參閱上面的快速入門指南和 API 參考。您也可以在此處下載完整的範例設定:https://github.com/pirate/wireguard-example。
建議更改:https://github.com/pirate/wireguard-docs/issues