非常简洁、优雅的 VPN 实现。Linux 版本的 WireGuard 是在 kernel 层级实现的,没有使用 tun。其支持封装任何二层流量。
WireGuard 使用 UDP 协议。协议 overhead 是 1.5 RTT。WireGuard 本身不支持 obfuscation,其数据包有固定特征(例如:WireGuard UDP数据包内容的第1个字节固定是 0x1-0x4 其中之一),通过 Wireshark 可以分析出来。
安装:
apt install wireguard
CLI
wg
Quick Start
以下搭建2个节点的 WireGuard (1服务器端 + 1 客户端)
WireGuard 服务器端 VPN IP: 192.168.10.1
WireGuard 服务器端 Internet IP: 1.2.3.4 / VPN 监听 udp/12345 端口
Wireguard 客户端 VPN IP: 192.168.10.2
客户端可以没有公网 IP,也可以是动态 IP。
首先在服务器端和客户端的各个节点上创建 wg 公私密对 pubkey / privatekey:
mkdir -p /root/files/appdata/wireguard & cd $_
wg genkey | tee privatekey | wg pubkey > publickey
服务器端配置 wireguard.conf
# server (self): 192.168.10.1
[Interface]
PrivateKey = <server privatekey>
ListenPort = 12345
# client
[Peer]
PublicKey = <client publicKey>
AllowedIPs = 192.168.10.2/32
客户端配置 wireguard.conf
# client (self): 192.168.10.2
[Interface]
PrivateKey = <client privatekey>
ListenPort = 21841 # 客户端监听端口可以随意指定
# server
[Peer]
PublicKey = <server publicKey>
AllowedIPs = 0.0.0.0/0
Endpoint = 1.2.3.4:12345
PersistentKeepAlive = 25
服务器端启动脚本
#!/bin/bash
cd "${0%/*}"
ip link add dev wg0 type wireguard
ip address add dev wg0 192.168.10.1/24
wg setconf wg0 wireguard.conf
ip link set dev wg0 up
客户端启动脚本相同,把 wg0 interface 的 IP 改为客户端的 192.168.10.2/24 即可。
注意 wg setconf 后 interface 状态会变为 down,所以需要重新启动接口。
Routing
如果客户端(以及客户端所属子网通过客户端作为本地网关)需要将网络流量通过服务器端路由(传统 VPN 应用场景) : (参考 这里)
服务器和客户端的配置:
sysctl net.ipv4.ip_forward=1
iptables -A FORWARD -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
然后在客户端 ip route 添加路由指定 dev wg0 即可。
配合 udp2raw 使用
udp2raw 将 udp 流量封装为 Encrypted Fake-TCP / ICMP,并且能够穿越 NAT。项目提供 amd64 / mipsel (OpenWrt) 等环境预编译好的二进制文件
Server: (为方便管理,这里 udp2raw 监听的本地 tcp 端口 -l 同样设为 12345)
udp2raw -s -l0.0.0.0:12345 -r 127.0.0.1:12345 -k "password" --raw-mode faketcp -a
Client:
udp2raw -c -l0.0.0.0:3333 -r1.2.3.4:12345 -k "password" --raw-mode faketcp -a
然后修改 Client 的 wireguard.conf,将 Server peer 配置里的的 endpoint 改为 127.0.0.1:3333 即可。