Wireguard
简介¶
- WireGuard 是由 Jason Donenfeld 等人用 C 语言编写的一个开源 VPN 协议,被视为下一代 VPN 协议,旨在解决许多困扰 IPSec/IKEv2、OpenVPN 或 L2TP 等其他 VPN 协议的问题。它与 Tinc 和 MeshBird 等现代 VPN 产品有一些相似之处,即加密技术先进、配置简单。
- 从 2020 年 1 月开始,它已经并入了 Linux 内核的 5.6 版本,这意味着大多数 Linux 发行版的用户将拥有一个开箱即用的 WireGuard。
- WireGuard 作为一个更先进、更现代的 VPN 协议,比起传统的 IPSec、OpenVPN 等实现,效率更高,配置更简单,并且已经合并入 Linux 内核,使用起来更加方便。
常见VPN方法比较¶
- wireguard 精簡、速度極快:
- 只有 4000 行程式碼,是最精簡的 VPN 協議。对比下 OpenVPN,大约有 10 万行代码。
- WireGuard 利用内核空间处理来提升性能(更高吞吐和更低延迟),同时避免了不必要的内核和用户空间频繁上下文切换开销。
Wireguard客户端连接Debug¶
- 首先,服务端的ip或者域名能ping通
- 其次端口确定开放
> nc -z -v -u 4.shaojiemike.top 51822
,wg是udp - 修改wg客户端配置文件,限制ip为wg设置的内网段,
AllowedIPs = 192.168.31.0/24,10.0.233.1/24
.然后ping 192.168.31.1
测试 - 如果还不行,判断为wg的VPN包被中间网关识别并丢弃
配置文件¶
配置详解参考中文文档
PersistentKeepalive¶
- 一端位于 NAT 后面,另一端直接通过公网暴露
- 这种情况下,最简单的方案是:通过公网暴露的一端作为服务端,另一端指定服务端的公网地址和端口,然后通过 persistent-keepalive 选项维持长连接,让 NAT 记得对应的映射关系。
[peer]
里设定字段PersistentKeepalive = 25
,表示每隔 25 秒发送一次 ping 来检查连接。
AllowedIPs¶
虽然AllowedIPs = 0.0.0.0/0
与AllowedIPs = 0.0.0.0/1, 128.0.0.0/1
包含的都是全部的ip。
但是前者在iptable里为default dev wg1
,后者为两条0.0.0.0/1 dev wg1
和128.0.0.0/1 dev wg1
。
由于路由的ip匹配遵循最长前缀匹配规则,如果路由表里原本有一条efault dev eth0
。使用前者会导致混乱。但是使用后者,由于两条的优先级会更高,会屏蔽掉原本的default规则。
前者的iptable修改如下:(macbook上)
> ip route
default via link#18 dev utun3
default via 192.168.233.1 dev en0
10.0.233.5/32 via 10.0.233.5 dev utun3
224.0.0.0/4 dev utun3 scope link
224.0.0.0/4 dev en0 scope link
255.255.255.255/32 dev utun3 scope link
255.255.255.255/32 dev en0 scope link
后者的iptable修改如下
> ip route
0.0.0.0/1 dev utun3 scope link
default via 192.168.233.1 dev en0
default via link#18 dev utun3
10.0.233.5/32 via 10.0.233.5 dev utun3
128.0.0.0/1 dev utun3 scope link
224.0.0.0/4 dev en0 scope link
224.0.0.0/4 dev utun3 scope link
255.255.255.255/32 dev en0 scope link
255.255.255.255/32 dev utun3 scope link
原理¶
建议看WireGuard 教程:WireGuard 的工作原理 和WireGuard 基础教程:wg-quick 路由策略解读,详细解释了wg是如何修改路由表规则的。
wireguard 运行原理以及配置文件¶
默认会产生51840的路由table,ip rule
优先级较高。可以通过配置文件中添加PostUp
来修改最后一个default的路由规则。
root@snode6:/etc/wireguard# cat wg0.conf
[Interface]
Address = 192.168.253.5/32,fd00::aaaa:5/128
PrivateKey = eGj5skRAGJu8d………………1PVfu0lY=
# PublicKey = VWe0wBVztgX………………xd7/kZ2CVJlEvS51c=
#Table必须有,不然默认的还是会修改ip rule
Table = 51820
#DNS = 1.1.1.1 #指定DNS服务器
#启动时运行: %i 是指wg的路由, 默认修改default, metric 一般不用指定
PostUp = /sbin/ip -4 route replace default dev %i table default metric 1
PostUp = /sbin/ip -6 route replace default dev %i table default metric 1
#down后运行
PostDown = /sbin/ip -4 route delete default dev %i table default metric 1
PostDown = /sbin/ip -6 route delete default dev %i table default metric 1
PostUp
会产生下面的规则
OpenVPN原理¶
OpenVPN原理通过在main添加all规则来实现
# shaojiemike @ node5 in ~ [22:29:05]
$ ip route show table main
0.0.0.0/1 via 192.168.255.5 dev tun1
clash TUN模式¶
Macbook上的应用上的ClashX Pro的增强模式类似, 会添加如下配置,将基本所有流量代理(除开0.0.0.0/8
)
> ip route
1.0.0.0/8 via 198.18.0.1 dev utun3
2.0.0.0/7 via 198.18.0.1 dev utun3
4.0.0.0/6 via 198.18.0.1 dev utun3
8.0.0.0/5 via 198.18.0.1 dev utun3
16.0.0.0/4 via 198.18.0.1 dev utun3
32.0.0.0/3 via 198.18.0.1 dev utun3
64.0.0.0/2 via 198.18.0.1 dev utun3
128.0.0.0/1 via 198.18.0.1 dev utun3 #前面接受所有的ip,然后转换成198.18.0.1
198.18.0.1/32 via 198.18.0.1 dev utun3 #接受转换后的198.18.0.1,由于最长前缀匹配
明显有代理死循环问题,如何解决???
shaojiemike@shaojiemikedeMacBook-Air ~/github/hugoMinos (main*) [10:59:32]
> ip route get 198.18.0.42
198.18.0.42 via 198.18.0.1 dev utun3 src 198.18.0.1
shaojiemike@shaojiemikedeMacBook-Air ~/github/hugoMinos (main*) [10:59:38]
> ip route get 198.18.0.1
198.18.0.1 dev utun3 src 198.18.0.1
Wireguard 环境配置¶
wireguard-go: 安装客户端 wg-quick up config wireguard-tools: 安装服务端 wg
Wireguard 常见命令¶
- 启动
wg-quick up wg1
- 关闭
wg-quick down wg1
- 查看状态
wg
显示全部,或者wg show wg1
显示wg1
wireguard开机启动¶
使用wireguard 代理ipv6请求¶
- WireGuard 也支持 IPv6。OpenWRT 服务端,当然要allowed ip
fd00::aaaa:5/128
、 - 注意:这是伪需求,为什么ipv6的流量需要走ipv6,不走wg,每个机器可以获得独立的公网ipv6,对于PT做种是很好的。
brainiac1# cat wg-tsj.conf
[Interface]
PrivateKey = xxx
ListenPort = 51828
Address = 10.0.233.7/32, fd00::aaaa:5/128
Table = 51820
#DNS = 1.1.1.1
# 使用iptable修改ipv6的路由规则
PostUp = /sbin/ip -4 route replace default dev %i table default metric 1
PostUp = /sbin/ip -6 route replace default dev %i table default metric 1
PostDown = /sbin/ip -4 route delete default dev %i table default metric 1
PostDown = /sbin/ip -6 route delete default dev %i table default metric 1
[Peer]
#AllowedIPs = 0.0.0.0/0,::/0
PublicKey = xxx
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1
Endpoint = 4.shaojiemike.top:51822
PersistentKeepalive = 30
两次wireguard上网¶
修改sysctl.conf
文件的net.ipv4.ip_forward
参数。其值为0,说明禁止进行IP转发;如果是1,则说明IP转发功能已经打开。
需要执行指令sysctl -p
后新的配置才会生效。
两台机器的wireguard配置¶
注意中间需要NAT转换, 相当于把kunpeng机器的请求,隐藏成snode6的请求。在后一次wireguard转发时,就不会被过滤掉。
PostUp = iptables -t nat -A POSTROUTING -s 10.1.0.0/24 ! -o %i -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.1.0.0/24 ! -o %i -j MASQUERADE || true
机器(Nas)使用Wireguard上网¶
问题场景¶
由于换了wg服务端,导致nas变成闭环的网络了。最后是通过群晖助手(Synology Assistant / Web Assistant)的设置静态ip才连接上机器,但是iptable被设置乱了。
Synology Assistant can not find nas
静态连接上机器,首先在网页管理页面切换成DHCP(静态ip的DNS解析有误),iptable变成如下
sh-4.4# ip ro
default via 222.195.90.254 dev eth0 src 222.195.90.2
10.0.233.0/24 dev wg1 proto kernel scope link src 10.0.233.3
222.195.90.0/24 dev eth0 proto kernel scope link src 222.195.90.2
sh-4.4# ip ro s t eth0-table
222.195.90.0/24 via 222.195.90.2 dev eth0
注意iptable的修改是实时生效的。
思路¶
为了让nas上网我们需要满足两点
- 本地ssh eth0的222.195.90.2能访问机器(优先级更高)
- 其余网络走wg
# 重要项如下
sh-4.4# ip rule
3: from 222.195.90.2 lookup eth0-table (ping 和 ssh ip 222.195.90.2的会使用这个规则)
32766: from all lookup main (ping 和 ssh 其余ip 比如wg的10.0.233.3的会使用这个规则)
# 1. 设置本地ssh eth0的222.195.90.2的高优先级,不至于开启wg断开ssh
# 使用命令添加: ip ro add default via 222.195.90.254 dev eth0 table eth0-table
sh-4.4# ip route show table eth0-table
default via 222.195.90.254 dev eth0
222.195.90.0/24 via 222.195.90.2 dev eth0
# 2. 为了使得除开本地ssh网络走wg,需要删除屏蔽default的wg的DHCP(如果提前删,导致机器ssh连接不上了,重新插拔网线,让DHCP重新配置):
# 使用命令添加:ip ro d default via 222.195.90.254 dev eth0 src 222.195.90.2 table main,
# 3. 防止服务端重启,Nas的wg客户端失联
# 使用命令添加:ip ro a 114.214.233.0/24 via 222.195.90.254 dev eth0 src 222.195.90.2 table main
# 4. 测试: ping域名能正常运行
# 其余方法:为了使得除开本地ssh网络走wg,也可以不删除,在DHCP的前面添加wg的网络通路
# 使用命令添加: ip ro add default dev wg1 proto kernel scope link src 10.0.233.3 table main
sh-4.4# ip r s t main
default dev wg1 proto kernel scope link src 10.0.233.3
使用wg1配置如下:
sh-4.4# cat /etc/wireguard/wg1.conf
[Interface]
PrivateKey = xxx
ListenPort = xxx
Address = 10.0.xxx.xxx/24
Table = 51820
PostUp = /sbin/ip -4 route replace default dev %i table default metric 1
PostDown = /sbin/ip -4 route delete default dev %i table default metric 1
[Peer]
PublicKey = xxx
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1
Endpoint = 114.xxx.xxx.xxx:xxx
PersistentKeepalive = 25
问题:服务端重启,Nas的wg客户端失联¶
要保留没有wg的时候访问服务端的eth0(114.214.233.xxx)的通路
来自eth0的ssh与ping请求原路返回¶
源地址为自身IP的包走学校的路由器¶
目的:需要ssh和ping ipv4成功
修改netplan
的配置文件
# shaojiemike @ node5 in ~ [22:29:11]
$ cat /etc/netplan/acsa.yaml
network:
version: 2
renderer: networkd
ethernets:
eno0:
dhcp4: false
dhcp6: false
accept-ra: false
addresses:
- 202.38.73.217/24
- 2001:da8:d800:730::217/64
gateway4: 202.38.73.254
gateway6: 2001:da8:d800:730::1
nameservers:
addresses:
- 202.38.64.1
routing-policy:
- from: 202.38.73.217
table: 1
priority: 2
routes:
- to: 0.0.0.0/0
via: 202.38.73.254
table: 1
$netplan apply
routing-policy
会产生
# shaojiemike @ node5 in ~ [22:30:33]
$ ip rule
0: from all lookup local
2: from 202.38.73.217 lookup 1
32766: from all lookup main
32767: from all lookup default
# 也可以手动添加
ip rule add from 202.38.73.217 table 1 pref 2
或者
ip rule add from 202.38.73.217 lookup 1 pref 2
由于2优先级高,使得ping和ssh的返回信包(源地址为自身机器IP的包)走table1 规则,而不是走
routes
使得所有的table1都会走学校的路由器(202.38.73.254)
$ ip route show table 1
default via 202.38.73.254 dev eno0 proto static
# 也可以通过`ip route add`
$ ip route add default via 202.38.73.254 dev eno0 proto static table 1
衍生问题:网络请求的源地址不是自己吗?怎么确定的¶
开启wg后,网络请求源地址变成了10.0.33.2
。不是202.38.73.217
但是外界ping的是202.38.73.217
。返回包交换所以会产生源地址为202.38.73.217
的包
wireguard 实现翻墙¶
- WireGuard 在国内网络环境下会遇到一个致命的问题:UDP 封锁/限速。虽然通过 WireGuard 可以在隧道内传输任何基于 IP 的协议(TCP、UDP、ICMP、SCTP、IPIP、GRE 等),但 WireGuard 隧道本身是通过 UDP 协议进行通信的,而国内运营商根本没有能力和精力根据 TCP 和 UDP 的不同去深度定制不同的 QoS 策略,几乎全部采取一刀切的手段:对 UDP 进行限速甚至封锁。
- 虽然对 UDP 不友好,但却无力深度检测 TCP 连接的真实性。
- 将 UDP 连接伪装成 TCP 连接不就蒙混过关了。目前支持将 UDP 流量伪装成 TCP 流量的主流工具是 udp2raw,但是有一款更强大的新工具: Phantun。
需要进一步的研究学习¶
暂无
遇到的问题¶
暂无
开题缘由、总结、反思、吐槽~~¶
参考文献¶
WireGuard 基础教程:使用 Phantun 将 WireGuard 的 UDP 流量伪装成 TCP