目錄
Wireguard筆記(一) 節點安裝配置和參數說明
Wireguard筆記(二) 命令行操作
Wireguard筆記(三) lan-to-lan子網穿透和多網段並存
簡介
虛擬子網軟件,類似於OpenWPN,使用虛擬網卡,但是只支持UDP協議連接,配置簡單。在Kernel 5.6之后已經內置。
中繼服務器
作為中繼服務器(Bounce Server),和普通的對等節點一樣,它能夠在 NAT 后面的客戶端之間充當中繼服務器,可以將收到的任何子網流量轉發到正確的對等節點,這個過程並非由WireGuard處理,而是由系統內核和iptables處理的。公網可達的子網不需要中繼服務器,只有當有節點位於 NAT 后面時才需要。
在WireGuard里客戶端和服務端的功能是平等的,差別只是誰主動連接誰而已。如果雙方都在監聽端口,誰主動連接,誰就是客戶端。主動連接的一方需要預知對方的公網地址和端口(Endpoint),被動連接的一方則不需要。如果雙方都位於NAT后面,則需要加一個中繼節點,雙方都以中繼服務器作為對等節點,它們的通信流量會先進入中繼服務器,然后再轉發給對方。
如果某一端同時連接了多個對端,當它想訪問某個IP時,如果有具體的路由可用,則優先使用具體的路由,否則就會將流量轉發到中繼服務器,中繼服務器再根據系統路由表進行轉發。可以通過檢查wg show wg0和route找到WireGuard對一個給定地址的路由方式。
安裝
服務器
參考
https://www.iplayio.cn/post/70750984
https://www.cnblogs.com/a5idc/p/13895146.html
https://yooooex.com/2019/05/23/wireguard-deploy/
ubuntu安裝
sudo apt install wireguard
centos7安裝
先升級Kernel到ml, 現在是5.11.x, 看看是否有wg模塊
lsmod|grep wireguard
# 沒有就modprobe一下再試試
modprobe wireguard
安裝wg工具
yum install epel-release
yum provides wg-quick
yum install wireguard-tools
打開轉發
sudo vi /etc/sysctl.conf
# 取消這行的注釋
net.ipv4.ip_forward=1
# 保存文件並應用更改
sudo sysctl -p
# 輸出:net.ipv4.ip_forward = 1
配置防火牆
Ubuntu: 如果啟用了UFW,需要添加規則,本例使用的端口是50004
# 添加端口
sudo ufw allow 50004/udp
# 查看
sudo ufw status verbose
Centos7
firewall-cmd --zone=public --add-port=50004/udp --permanent
firewall-cmd --reload
配置
# 生成公私鑰, 如果是對本機進行初始化, 先cd到/etc/wireguard目錄下
umask 077
wg genkey | tee private.key | wg pubkey > public.key
# 創建新文件wg0.conf, 這個是服務wg-quick@wg0默認使用的配置文件. 添加以下內容:
sudo vi /etc/wireguard/wg0.conf
# ==================== begin ===================
[Interface]
PrivateKey = [填入服務端私鑰]
Address = 10.253.0.1/24
ListenPort = 50004
# 規則說明:接受來源為%i的轉發;接受出口為%i的轉發;增加對出口為本機網卡的NAT映射
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens160 -j MASQUERADE
[Peer]
PublicKey = [填入客戶端公鑰]
# 允許客戶端使用的IP段,對於peer的隧道IP, 建議使用/32的固定IP, 以避免和其他peer重復導致無法連接
AllowedIPs = 10.253.0.2/32
# ===================== end ====================
# 啟動wg0
sudo wg-quick down wg0
# 停止wg0
sudo wg-quick up wg0
# 查看
sudo wg
# 查看單個
sudo wg show wg0
如果需要支持IPv6
# 啟動動作, 要把 ens160 替換成自己的網口名稱
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
# 關閉動作
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens160 -j MASQUERADE; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o ens160 -j MASQUERADE
設置為自啟動
systemctl enable wg-quick@wg0
多個wireguard服務並存
可以在/etc/wireguard/下創建多個配置文件, 例如wg0.conf, wg1.conf配置多個服務
- 使用systemctl enable/start wg-quick@wg0, systemctl enable/start wg-quick@wg1 啟動
- 使用wg show能同時看到這些wiguard服務的連接情況
- 各配置使用不同的隧道網段, 會體現到route上
- 各配置當中, peer中的allowedIP會影響route規則, 如果相同會產生沖突
對於非服務端, 配置文件的例子為
[root@vm_ci01 ~]# more /etc/wireguard/wg0.conf
[Interface]
PrivateKey = [填入私鑰]
Address = 10.253.0.3/32
ListenPort = 50004
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT; ip6tables -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; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = [填入服務端的公鑰]
AllowedIPs = 10.253.0.0/24,192.168.116.0/24
Endpoint = 1.123.45.67:50004(服務端的IP端口)
PersistentKeepalive = 25
客戶端(命令行)
先生成公私鑰,然后使用配置文件
[Interface]
PrivateKey = [客戶端私鑰]
Address = 10.253.0.2/24
DNS = 114.114.114.114
[Peer]
PublicKey = [服務端公鑰]
# 允許通過的IP段,如果設為0.0.0.0/0則攔截本機所有流量
AllowedIPs = 192.168.116.0/24,10.253.0.0/24
Endpoint = [服務器的IP]:50004
PersistentKeepalive = 25
注意
- 如果這個客戶端是作為逆向穿透的節點
- [Interface]中增加PostUp, PostDown, 但是不需要DNS;
- [Interface]中Address掩碼可以使用/24也可以使用/32
- [Peer]中增加PersistentKeepalive
- 如果這是Windows Wireguard客戶端
- [Interface]中不需要PostUp, PostDown, 可以不需要DNS;
- [Interface]中Address掩碼使用/24, 否則會出現連接不上服務端的情況(本地顯示已連接, 但是服務端看不到, 並且接收字節為0)
- [Peer]中只需要PublicKey, AllowedIPs, Endpoint
Ubuntu20.04客戶端(通過NetworkManager)
NetworkManager界面對Wireguard的支持, 要到版本1.26之后, 如果是Ubuntu20.04, 需要自己編譯.
sudo apt install wireguard git dh-autoreconf libglib2.0-dev intltool build-essential libgtk-3-dev libnma-dev libsecret-1-dev network-manager-dev resolvconf
從Github clone對應的項目
git clone https://github.com/max-moser/network-manager-wireguard
cd network-manager-wireguard
./autogen.sh --without-libnm-glib
./configure --without-libnm-glib --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib/x86_64-linux-gnu --libexecdir=/usr/lib/NetworkManager --localstatedir=/var
make
sudo make install
然后在網絡配置界面的WPN中點擊+號, 就能看到Wireguard的選項了. 配置說明
- Identity
- Name: 可以使用wg0之類的名稱, 這個會被用於網口名稱, 所以不要太長太復雜
- Interface:
- Address(IPv4): 10.253.0.4/32 這個是開啟wg之后本機的隧道IP
- Address(IPv6): 可以留空
- Listen Port: 可以留空, 也可以指定為50004
- Private Key: 本機的私鑰
- 其他都可以留空
- Peer
- Public Key: 服務端的公鑰
- Allow IPs: 需要走隧道的IP段, 一般包含隧道自身IP段, 以及要借道隧道的IP段, 但是這里設置並不會產生對應的route
- Endpoint: 服務端的IP和端口
- Persis.Keepalive: 25 保持活動的時間間隔
- 其他都可以留空
- IPv4
- IPv4 method: Automatic (DHCP) 實際產生的IP還是之前在Identity->Interface中配置的IP地址
- DNS: Automatic
- Routes: 取消Automatic, 添加
- 10.253.0.0, 255.255.255.0, 10.253.0.102, 5 將10.253.0.0/24這個段的路由, 設置到10.253.0.102(即本機的隧道網口)上
- 192.168.13.0, 255.255.255.0, 10.253.0.102, 5 將192.168.13.0/24這個段的路由也設置到本機隧道網口上
- 如果還有其他需要走隧道的IP段, 則繼續添加.
- 不勾選Use this connection only for resources on its network
注意: 如果不手動添加路由, 在啟動此wg網口后, 本機路由沒有變化, 訪問不生效, 但是通過ping 10.253.0.1 -I wg0可以ping通服務端隧道IP, 說明僅是路由的問題.
配置說明
關於AllowedIPs
Wireguard的AllowedIPs因為涉及服務端和客戶端的允許IP范圍,需要理清一下這個設置的含義
- 首先,AllowedIPs會影響當前機器的路由設置,在AllowedIPs配置的每一段IP,都會在路由表里指向這個wireguard網卡
那么在A節點,如果你要訪問B節點后面的網絡,你就要把B節點后面網絡的IP段,配到Peer.B下面去 - 其次,提供轉發的節點,不需要關心從各個節點到來的流量要訪問何處,不需要為自身轉發的目標網段配置AllowedIPs
比如A節點處於5.5.5.0/24網段,A已經提供了轉發,那么A不需要在自己節點下面的Peer的AllowedIPs中配置5.5.5.0/24
服務端和客戶端的[Peer]中配置的AllowedIPs
- 無論哪一端,AllowedIPs的IP段都會加入路由表
- AllowedIPs需要包含對方節點的隧道IP
- AllowedIPs需要包含對方節點提供轉發的IP網段,這將通過增加路由規則攔截本機對這些IP范圍的訪問流量
- 當配置的AllowedIPs為0.0.0.0/0時,會將虛擬網卡的Default Gateway設為0.0.0.0,而不是通過路由表
公網中繼的AllowedIPs配置問題
使用公網中繼節點進行穿透時(例如R為公網中繼, A為工作區內網節點, B為個人接入),
如果AllowedIPs配置不正確, 會導致B->R, R->A都能訪問, 但是B->A就無法訪問的問題. 需要檢查A節點的配置, 檢查其中R這個節點的[Peer]配置中AllowedIPs是否未包含B節點的隧道IP.
舉例:
R節點 有公網IP, 提供前往192.168.116.x和192.168.117.x的中轉
[Interface]
Address = 10.253.0.1/32
...
[Peer]
AllowedIPs = 10.253.0.3/32,192.168.117.0/24
A節點 處於192.168.117.0/24的內網
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/32,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
B節點 個人外網接入, 需要訪問192.168.117.0/24網段
[Interface]
Address = 10.253.0.101/24
[Peer]
AllowedIPs = 192.168.116.0/24, 10.253.0.0/24, 192.168.117.0/24
Endpoint = xx.xx.xx.xx:10004
這時候就會出現前面提到的情況, B->R和R->A訪問都通但是B->A訪問不通, 需要將A配置中R的AllowedIPs改為10.253.0.1/24才行, 如下所示.
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/24,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
或者更進一步, 僅僅將B節點和R節點的IP放入, 如下所示, 這樣就只允許B->R->A, 其他節點連接到R之后, 無法訪問A
[Interface]
Address = 10.253.0.3/32
[Peer]
AllowedIPs = 10.253.0.1/32,10.253.0.101/32,192.168.116.0/24
Endpoint = xx.xx.xx.xx:10004
關於PresharedKey
即PSK 預共享密鑰,節點可以給連接自己的每一個peer都分配一個PSK,這個PSK會設置在每對節點的[Peer]中,連接時檢查是否一致
# 生成(每個peer一個)
wg genpsk > presharedkey
# 配置格式
[Peer]
PublicKey = P556VVMhhBb+kc2Gm7JV46jh1oRv75YscK8q131iSnM=
PresharedKey = oZ33KPYBwo7aFyxewm5Eutlelztz9lXQ2Z8tyouc7TM=
AllowedIPs = 10.253.0.0/24
Endpoint = 123.123.123.123:31231
...
關於PersistentKeepAlive
這個參數用於內網節點定期發送報文以保持連接。默認情況下WG盡量保持沉默以避免發送太多數據,但是如果連接中一些節點處於內網或防火牆后,在長時間無數據后連接可能被防火牆關閉,此時如果外網節點需要發送數據,會發現連接不可用。這種情況下就需要內網節點定期主動發送數據以保持連接。
注意:這個參數與最后握手時間是不一樣的。一次握手會建立一個約三分鍾長度的會話時間,在這個會話時間內,發送keep-alive報文不需要再次建立會話。在實際使用中,如果發送報文時會話時間已經剩余不到1分鍾,會在此會話到期前就創建一個新的會話。正常情況下,如果PersistentKeepAlive設為了25,握手時間基本上不會超過3分鍾,除非處於移動設備上,因為設備節電等原因導致發送時間滯后等情況。
關於DNS
客戶端如果配置為全流量攔截(0.0.0.0/0),則必須設置DNS項,如果不配置DNS,在連接后會不能正確解析域名
關於子網間穿透
Wireguard可以配置通過一個公共服務器同時連接多個子網。這時候需要在服務器和每個子網節點上,都配置同一個網段的隧道IP和相應的路由,可以參考
https://anyisalin.github.io/2018/11/21/fast-flexible-nat-to-nat-vpn-wireguard/ 主要的設置有三處:
- 服務器和子網節點: 在sysctl中開啟ip forward
- 服務器和子網節點: 在[Interface]中增加PostUp和PostDown的路由設置
- 服務器: 需要設置一下端口號,並在防火牆中打開此端口
- 服務器和子網節點如果安裝了firewalld, 還需要在firewalld中開啟masquerade
firewall-cmd --permanent --zone=public --add-masquerade
firewall-cmd --reload
Windows節點
windows做這個穿透會比較復雜,因為windows不像linux那樣有iptables可以配置,需要設置的可以參考這篇 https://www.henrychang.ca/how-to-setup-wireguard-vpn-server-on-windows/
使用TCP來避免防火牆的UDP規則影響
可以使用udptunnel
https://gist.github.com/insdavm/90cbeffe76ba4a51251d83af604adf94
或者udp2raw-tunnel
https://github.com/wangyu-/udp2raw-tunnel
以及TunSafe
https://github.com/TunSafe/TunSafe
后兩者有支持windows和android的客戶端
實現思路是在服務端運行一個TCP隧道, 代理wg的端口, 在客戶端運行TCP隧道的客戶端, 連接到服務端的TCP隧道, 客戶端的wg連接本地端口
iptables規則
單包驗證SPA規則
# 清空iptables
iptables -F
# 已經建立的tcp連接允許通過 -m state --state ESTABLISHED 只針對tcp
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
# 允許訪問udp 62201端口
iptables -A INPUT -p udp --dport 62201 -j ACCEPT
# 允許22端口通過
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允許入包回環
iptables -A INPUT -i lo -j ACCEPT
# 出包的tcp
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
# 出包的udp
iptables -A OUTPUT -p udp -j ACCEPT
# 允許出包回環
iptables -A OUTPUT -o lo -j ACCEPT
# 允許建立的FORWARD通過
iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
# 最后一步 關閉IMPUT,OUTPUT,FORWARD
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
其他
提供內核支持的發行版
在Ubuntu20.04最近的更新中, Kernel已經升級到5.8.0, 自帶了wireguard
~$ uname -a
Linux milton-t550 5.8.0-43-generic #49~20.04.1-Ubuntu SMP Fri Feb 5 09:57:56 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
~$ sudo modprobe wireguard
[sudo] password for milton:
~$ lsmod
Module Size Used by
wireguard 86016 0
curve25519_x86_64 49152 1 wireguard
libchacha20poly1305 16384 1 wireguard
chacha_x86_64 28672 1 libchacha20poly1305
poly1305_x86_64 28672 1 libchacha20poly1305
libblake2s 16384 1 wireguard
blake2s_x86_64 20480 1 libblake2s
ip6_udp_tunnel 16384 1 wireguard
udp_tunnel 16384 1 wireguard
對於Centos7, 可以升級內核至5.11.x: Centos7 和 Centos8 升級內核
Debug日志
啟用WireGuard debug
echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
Disable WireGuard debug
echo 'module wireguard -p' | sudo tee /sys/kernel/debug/dynamic_debug/control
查看輸出
dmesg
# or
journalctl -f
性能測試
https://www.reddit.com/r/linux/comments/9bnowo/wireguard_benchmark_between_two_servers_with_10/
對Wireguard性能的測試, 比較的對象是直接傳輸和OpenVPN. 用netperf在MTU8500~9000的情況下, 三者的速度對比是44:23:1
netperf -t TCP_STREAM -l 600 -H 10.0.9.11
