最後更新: 2024-08-23
目錄
- Clients
- Linux Installation
- Kernel Module
- 建立 keys
- Setup
- Options
- Scripts(PreUp, PostUp, PreDown, PostDown)
- Auto Start By systemd
- Summary
- Debug
- Other
WireGuard 簡介
WireGuard securely encapsulates IP packets over UDP.
核心
WireGuard interface
It works by adding a network interface (wg0, wg1, etc), like eth0 or wlan0, called.
Cryptokey Routing
Each network interface has a private key and a list of peers.
Each peer has a public key.
Public keys with a list of tunnel IP addresses that are allowed inside the tunnel.(AllowedIPs)
Public key must be unique between multiple peers on the same tunnel. Otherwise,
traffic to the conflicting networks will only be routed to the last peer in the list.
優點
Minimal Attack Surface
It is meant to be easily implemented in very few lines of code,
and easily auditable for security vulnerabilities.
High Performance
WireGuard lives inside the Linux kernel
Simple & Easy-to-use
At the heart of WireGuard is a concept called Cryptokey Routing
simply match on "is it from this IP? on this interface?
Ready for Containers
Known Limitations
- WireGuard does not focus on obfuscation
- WireGuard explicitly does not support tunneling over TCP
-
WireGuard uses ChaCha20Poly1305
(does not support hardware encryption devices)
Other Project
Clients
Windows 's client
https://download.wireguard.com/windows-client/
Linux Installation
# U22
apt install wireguard
apt install iptables # wg-quick 要用到 iptables-restore
Depends
- wireguard-modules / wireguard-dkms
- wireguard-tools
# RHEL(7,8)@EPEL: kmod-wireguard wireguard-tools
dnf install wireguard-tools
Kernel Module
# module 在 linux-modules-6.5.0-41-generic package 內
modprobe wireguard
U22
# 調用 dkms 去 compile kernel module
apt install wireguard-dkms
有機會遇到沒有 linux-headers 的情況
場景:
系統行緊的 Kernel 係 linux-image-5.15.0-58-generic, 但沒有對應的 linux-headers
原因係當前最新的 Kernel 是 linux-image-5.15.0-112-generic
它對應 linux-headers-5.15.0-112-generic
建立 keys
Private & Public key (PublicKey, PrivateKey)
wg genkey > private.key
chmod 640 private.key
wg pubkey < private.key > public.key
PSK (PresharedKey)
# 256 bits base64-encoded string (44 alphanumeric characters)
wg genpsk > psk.key
chmod 640 psk.key
Setup
1) 建立 NIC
ip link add dev wg0 type wireguard
2) 設定雙方 IP
ip address add dev wg0 192.168.2.1/24
OR
ip address add dev wg0 192.168.2.1 peer 192.168.2.2
3) Configure NIC
方式 A
Default Port: 51820/udp
wg set wg0 \
listen-port 51820 \
private-key /path/to/private-key \
peer R.R.R.R \
allowed-ips 192.168.88.0/24 \
endpoint R.R.R:R:51820
方式 B
wg setconf wg0 wg0.conf
方式 C
wg-quick up wg0
4) Checking
wg [show]
interface: wg0 public key: ... private key: (hidden) listening port: 48917 peer: ... preshared key: (hidden) endpoint: R.R.R.R:51820 allowed ips: 10.0.31.0/24
wg showconf <interface> # output 的是 config file 的內容. 可能保存成 config file
Options
必要的 settings
Address = Your.internal.IP.address
AllowedIPs
The Tunnel address, and any additional networks which should be routed across the VPN in a comma-separated list.
This could be a LAN subnet (e.g. 10.6.0.0/24) or
We use 0.0.0.0/0 to route all traffic, including Internet traffic, across the tunnel.
Optional Settings
PersistentKeepalive = 10
a keepalive packet is sent to the server endpoint once every interval seconds.
DNS = 10.0.31.1
Domain Name Server, used to resolve hostnames to IPs for VPN clients
用 internal dns server 可以防止 DNS 解釋漏出
MTU = 1440
Run Script
- PostUp =
- PostDown =
PresharedKey
PresharedKey = /path/to/file
A base64 preshared key generated by wg genpsk.
This option adds an additional layer of symmetric-key cryptography
to be mixed into the already existing public-key cryptography,
for post-quantum resistance.
Config File
[Interface] PrivateKey = ABCDE... Address = 10.0.31.11 SaveConfig = true ListenPort = 51820 [Peer] PublicKey = FGHIJ... PresharedKey = KLMNO... Endpoint = R.R.R.R:51820 AllowedIPs = 10.0.31.0/24, 192.168.31.0/24 PersistentKeepalive = 10
SaveConfig
true => the configuration is saved from the current state of the interface upon shutdown
ListenPort
如果沒有設定, 那會隨機 listen 一個 UDP port
Scripts(PreUp, PostUp, PreDown, PostDown)
Usage
- The script snippets which will be executed by bash
- The special string "%i" is expanded to INTERFACE
- Each one may be specified multiple times
e.g.
[Interface] PostUp = /etc/wireguard/%i/postup.sh %i PostDown = /etc/wireguard/w%i/postdown.sh %i
postup.sh
#!/bin/bash LAN=192.168.123.0/24 WG_SUBNET=10.0.31.0/24 MASQUERADE_IF=br0 WG_IF=$1 if [ -z $WG_IF ]; then echo "No WG_IF" && exit 1; fi iptables -t nat -I POSTROUTING -o $MASQUERADE_IF -j MASQUERADE -s $WG_SUBNET # Add a WIREGUARD_wg0 chain to the FORWARD chain CHAIN_NAME="WIREGUARD_$WG_IF" iptables -N $CHAIN_NAME iptables -A FORWARD -j $CHAIN_NAME # Accept related or established traffic iptables -A $CHAIN_NAME -o $WG_IF -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT # Accept traffic from any Wireguard IP address connected to the Wireguard server iptables -A $CHAIN_NAME -s $WG_SUBNET ! -d $LAN -i $WG_IF -j ACCEPT # Reject everything else coming through the Wireguard interface iptables -A $CHAIN_NAME -i $WG_IF -j REJECT # Return to FORWARD chain iptables -A $CHAIN_NAME -j RETURN
postdown.sh
#!/bin/bash WG_SUBNET=10.0.31.0/24 MASQUERADE_IF=br0 WG_IF=$1 if [ -z $WG_IF ]; then echo "No WG_IF" && exit 1; fi CHAIN_NAME="WIREGUARD_$WG_IF" iptables -t nat -D POSTROUTING -o $MASQUERADE_IF -j MASQUERADE -s $WG_SUBNET # Remove WG FORWARD CHAIN iptables -D FORWARD -j $CHAIN_NAME iptables -F $CHAIN_NAME iptables -X $CHAIN_NAME
Auto Start By systemd
/etc/wireguard/wg0.conf # 要有設定好的 config file
systemctl enable [email protected] --now
systemctl status wg-quick@wg0
Remove Service
systemctl disable [email protected] --now
find /etc/systemd/system -name wg-quick@*
rm -f /etc/systemd/system/multi-user.target.wants/[email protected]
systemctl daemon-reload
Summary
Diagram
LAN: 192.168.31.0/24 | Server <-51820/udp- Client 10.0.31.254 Tunnel 10.0.31.11
Client Config(wg0.conf)
[Interface] PrivateKey = ABCDE... Address = 10.0.31.11 [Peer] PublicKey = FGHIJ... PresharedKey = KLMNO... Endpoint = R.R.R.R:51820 AllowedIPs = 10.0.31.0/24, 192.168.31.0/24 PersistentKeepalive = 10
Debug
Server
tcpdump -n -i eth0 port 51820
Client
nc -u x.x.x.x 51820
Install wireguard on LXC CT
To install a package without installing its dependencies
由於 wireguard 依然 wireguard-modules / wireguard-dkms
但在 LXC 內它們是沒有用的 (因為它們係 Kernel Module 來)
所以我們可以使用 "--no-install-recommends" 略過
apt install --no-install-recommends wireguard-tools
ufw settings
# Forward traffic to LXC CT(192.168.200.18)
Internet <-> ens160[HOST]br0 <-> CT
ufw route allow in on br0 out on ens160 from 192.168.200.0/24 # LXC 上網
ufw route allow in on ens160 to 192.168.200.18 port 51820 proto udp # wireguard vpn traffic
/etc/ufw/before.rules
*nat :POSTROUTING ACCEPT [0:0] -F POSTROUTING -A POSTROUTING -s 192.168.200.0/24 -o ens160 -j MASQUERADE :PREROUTING ACCEPT [0:0] -F PREROUTING -A PREROUTING -i ens160 -p udp --dport 51820 -j DNAT --to-destination 192.168.200.18 COMMIT
Reload Settings
需要 "wg-quick strip" 與 "wg syncconf" 配合完成
wg-quick strip
output a configuration file with all wg-quick specific options removed,
應用: reloading configuration files without disrupting active sessions
e.g.
wg syncconf wg0 <(wg-quick strip wg0)
wg syncconf
wg syncconf wg0 wg0.conf
Like setconf, but reads back the existing configuration first and
only makes changes that are explicitly different between the configuration file and the interface.
Peer 互連
當 Peer1 及 Peer2 連通 Server 後, 它們就可以互通
Diagram
/-- Peer1 Server \-- Peer2
在 server 上的 wg0.conf
# Server [Interface] Address = 10.0.31.1 ListenPort = 51820 # Peer 1 [Peer] Endpoint = peer1.domain:51820 AllowedIPs = 10.0.31.11/32 # Peer 2 (mobile) [Peer] AllowedIPs = 10.0.31.12/32
* Server 必須有 ListenPort
* 由於 mobile 沒有 public 的 wan ip, 所以沒有 Endpoint 設定
Other