Wireguard over Vmess/Vless - 安全隐蔽且容易配置的VPN三层隧道

老早就有这个想法了,由于v2ray只是一个四层代理,相比VPN三层代理不够透明,所以有用VPN的倾向。

但是VPN协议早已被GFW摸得清清楚楚,断流、QoS管控绝对不会手软。所以肯定需要一个隧道来对接VPN协议。

原因

选用Wireguard单纯是因为Linux原生支持Wireguard,配置相比于别的VPN协议实在是方便太多而且性能相对最好,而且由于是三层协议,还可以在这上面再添加GRE套娃变成GRE over Wireguard over Vmess….

但是无论是GFW对于Wireguard的识别,还是ISP对于udp流量的QoS管控限制,都让裸Wireguard变得难以使用。所以这里还需要一个隧道,让数据包表层看起来安稳一些,不会受到ISP的特别关照。

在穿墙隧道这一方面,现阶段做的比较完善,且最高能以应用层穿隧的协议,估计V2ray的Vmess/Vless协议算是做的最为完善和成熟的了。

其实也有想过用GOST进行穿隧,据说性能更好。但GOST的配置方式我不熟悉,配置总是不成功。有时间研究一下再码一篇。

原理

先设定有两台机子,一台是Server,一台是Client。

Server的对外IP是10.100.0.1,Client的对外IP是10.100.0.2。

V2ray套件中有一个Dokodemo-door入站协议,可以监听任意端口进行转发,并且支持在V2ray中路由。

先在Server架设好V2ray服务端,为了演示方便先使用普通的Vmess TCP协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// vmess TCP
{
"inbounds": [
{
"port": 16823, // 服务器监听端口
"protocol": "vmess", // 主传入协议
"settings": {
"clients": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"alterId": 64
}
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}

然后在Server再架设一个Wireguard接口。

1
2
3
4
5
6
7
8
9
[Interface]
PrivateKey = 2GjqFPL8IXKs3fECd4/FO6M1XnLFw4N8uHSzT9i62mc=
Address = 10.101.0.1/32
ListenPort = 10000
#监听10000端口

[Peer]
PublicKey = EZ/WK+xSI5cIL3diRAI2K0LVWefMiky3a3MxYBaL5As=
AllowedIPs = 10.101.0.2/32

在Client里面安装V2ray,配置基础的Outbounds和Dokodemo-door转发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"inbounds": [
{
"tag":"wireguard",
"port":10000,
"protocol":"dokodemo-door",
"settings":{
"address":"127.0.0.1",
"port":10000,
"network":"udp"
}
}
],
"outbounds": [
{
"tag":"proxy",
"protocol": "vmess", // 出口协议
"settings": {
"vnext": [
{
"address": "10.100.0.1", // 服务器地址
"port": 16823, // 服务器端口
"users": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"alterId": 64
}
]
}
]
}
}
],
"routing":{
"rules":[
{
"type":"field",
"inboundTag":[
"wireguard"
],
"outboundTag":"proxy"
}
]
}
}

这样配置后,Client本机的10000端口便映射到Server的10000端口。接下来配置Client的Wireguard接口

1
2
3
4
5
6
7
8
[Interface]
PrivateKey = wAuG/N59IEqdQT42rTi8bfTP00ygLQMe6Rjl85aSE1k=
Address = 10.101.0.2/32

[Peer]
PublicKey = PpE7xyUVEXfccO3GrFUad36s8WG5frJQTNd499oceHI=
AllowedIPs = 10.101.0.1/32
Endpoint = 127.0.0.1:10000

配置完毕后,将Server和Client总共4个服务全部启动即可

实验

用Hyper-V开两台Ubuntu做实验,搭建虚拟机的过程就不记录了。设置好ip为上面规划的ip,搭完之后安装Wireguard与V2ray。

1
2
3
4
5
sudo su
apt update
apt install wireguard -y
curl https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh | bash
curl https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-dat-release.sh | bash

然后编辑文件,留意新版的v2ray配置文件路径是/usr/local/etc/v2ray/config.json,上面已经介绍过如何配置了,这里不再复述。

Wireguard over Vmess挂完之后安装个iperf测试一下速度吧。

1
2
3
4
5
6
# Server
apt install iperf
iperf -s
# Client
apt install iperf
iperf -c 10.101.0.1

实验测试结果

iperf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Direct
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.100.0.1 port 5001 connected with 10.100.0.2 port 53168
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 22.2 GBytes 19.0 Gbits/sec

# Wireguard only
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.101.0.1 port 5001 connected with 10.101.0.2 port 55878
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 2.33 GBytes 1.99 Gbits/sec

# Wireguard over Vmess-TCP
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.101.0.1 port 5001 connected with 10.101.0.2 port 55868
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 177 MBytes 148 Mbits/sec

# Wireguard over Vmess-WebSocket
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.101.0.1 port 5001 connected with 10.101.0.2 port 56038
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 147 MBytes 123 Mbits/sec

# Wireguard over Vmess-WebSocket-TLS
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.101.0.1 port 5001 connected with 10.101.0.2 port 56338
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 138 MBytes 116 Mbits/sec

# Wireguard over Vless-only
------------------------------------------------------------
Client connecting to 10.101.0.1, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[ 3] local 10.101.0.2 port 56032 connected with 10.101.0.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.1 sec 122 KBytes 98.5 Kbits/sec

# Wireguard over Vless-WebSocket
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
[ 4] local 10.101.0.1 port 5001 connected with 10.101.0.2 port 56016
[ ID] Interval Transfer Bandwidth
[ 4] 0.0- 7.8 sec 256 KBytes 268 Kbits/sec

# Wireguard over Vless-WebSocket-TLS
------------------------------------------------------------
Client connecting to 10.101.0.1, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[ 3] local 10.101.0.2 port 56330 connected with 10.101.0.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 33.1 MBytes 27.7 Mbits/sec
协议 iperf速度
Direct 19.0 Gbits/sec
Wireguard only 1.99 Gbits/sec
Wireguard over Vmess-TCP 148 Mbits/sec
Wireguard over Vmess-WebSocket 123 Mbits/sec
Wireguard over Vmess-WebSocket-TLS 116 Mbits/sec
Wireguard over Vless-Only 98.5 Kbits/sec
Wireguard over Vless-WebSocket 268 Kbits/sec
Wireguard over Vless-WebSocket-TLS 27.7 Mbits/sec

不知道为什么,一挂上Vless协议,iperf速度就急剧下降。正常使用没什么问题。

Ping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Direct
--- 10.100.0.1 ping statistics ---
89 packets transmitted, 89 received, 0% packet loss, time 90096ms
rtt min/avg/max/mdev = 0.251/0.325/0.417/0.041 ms

# Wireguard only
--- 10.101.0.1 ping statistics ---
86 packets transmitted, 86 received, 0% packet loss, time 87045ms
rtt min/avg/max/mdev = 0.348/0.471/0.664/0.061 ms

# Wireguard over Vmess-TCP
--- 10.101.0.1 ping statistics ---
59 packets transmitted, 59 received, 0% packet loss, time 58303ms
rtt min/avg/max/mdev = 0.818/0.994/1.427/0.103 ms

# Wireguard over Vmess-WebSocket
--- 10.101.0.1 ping statistics ---
57 packets transmitted, 57 received, 0% packet loss, time 56184ms
rtt min/avg/max/mdev = 0.875/1.092/4.503/0.464 ms

# Wireguard over Vmess-WebSocket-TLS
--- 10.101.0.1 ping statistics ---
58 packets transmitted, 58 received, 0% packet loss, time 57295ms
rtt min/avg/max/mdev = 0.821/1.037/1.775/0.158 ms

# Wireguard over Vless-Only
--- 10.101.0.1 ping statistics ---
58 packets transmitted, 50 received, 13.7931% packet loss, time 57710ms
rtt min/avg/max/mdev = 0.774/0.939/1.678/0.129 ms

# Wireguard over Vless-WebSocket
--- 10.101.0.1 ping statistics ---
56 packets transmitted, 55 received, 1.78571% packet loss, time 55390ms
rtt min/avg/max/mdev = 0.734/0.963/1.339/0.100 ms

# Wireguard over Vless-WebSocket-TLS
--- 10.101.0.1 ping statistics ---
58 packets transmitted, 58 received, 0% packet loss, time 57248ms
rtt min/avg/max/mdev = 0.830/1.024/1.252/0.090 ms
协议 延迟
Direct 0.325 ms
Wireguard only 0.471 ms
Wireguard over Vmess-TCP 0.994 ms
Wireguard over Vmess-WebSocket 1.092 ms
Wireguard over Vmess-WebSocket-TLS 1.037 ms
Wireguard over Vless-Only 0.939 ms
Wireguard over Vless-WebSocket 0.963 ms
Wireguard over Vless-WebSocket-TLS 1.024 ms

可以见到环回的延迟表现均可以接受。需要注意的是,第一个包延迟最高可以达到50ms,这可能是因为Vmess、Vless和Wireguard都需要握手后才能进行通讯。

本机环回测试效果一般,接下来实装到香港HKT家宽线路,尝试连接稳定性和速度。

实装测试结果

使用50M宽带与HKT千兆家宽测试

PING

协议 延迟
Direct 24.242 ms
Wireguard only 38.591 ms
Wireguard over Vmess-TCP 39.673 ms
Wireguard over Vmess-WebSocket 39.762 ms
Wireguard over Vmess-WebSocket-TLS 39.311 ms
Wireguard over Vless-Only 39.579 ms
Wireguard over Vless-WebSocket 39.865 ms
Wireguard over Vless-WebSocket-TLS 34.411 ms

Iperf测速

协议 iperf速度
Direct 6.24 Mbits/sec
Wireguard only 3.64 Mbits/sec
Wireguard over Vmess-TCP 3.32 Mbits/sec
Wireguard over Vmess-WebSocket 2.75 Mbits/sec
Wireguard over Vmess-WebSocket-TLS 2.39 Mbits/sec
Wireguard over Vless-Only 556 Kbits/sec
Wireguard over Vless-WebSocket 554 Kbits/sec
Wireguard over Vless-WebSocket-TLS 560 Kbits/sec

iperf怪怪的,有时间再做个speedtest测试吧

GRE over Wireguard over Vless-WebsocketSecurity-Web over Cloudflare CDN with Web

这行字和咒语一样……但是如此组合的隧道不但可以实现极为稳定的代理功能,由于GRE是二层代理还能实现传输广播包,实现内网的互联互通,甚至可以设置策略让所有接入的节点根据目的IP走不同的出口。而且由于使用了Web作为外层的伪装,符合现在应对GFW主动探测的主流方案。

这里先不说明如何设置OSPF实现自动路由,只关注如何实现GRE over Wireguard over Vless-WebsocketSecurity over Cloudflare CDN with Web

服务端

Vless-WebsocketSecurity over Cloudflare CDN with Web

由底层开始设置,先在Cloudflare里面把域名指向自己的VPS并且开启CDN代理,然后回到VPS里面安装V2ray与Caddy。上方原理说明已经描述如何安装V2ray

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 安装Caddy

wget -P /usr/local/bin "https://daofa.cyou/c1/caddy.tar" && \
tar -xvf /usr/local/bin/caddy.tar -C /usr/local/bin && \
rm /usr/local/bin/caddy.tar && \
chown root:root /usr/local/bin/caddy && \
chmod 755 /usr/local/bin/caddy && \
setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy && \
mkdir /etc/caddy && \
mkdir /etc/ssl/caddy && \
chown -R root:root /etc/caddy && \
chown -R root:www-data /etc/ssl/caddy && \
chmod 770 /etc/ssl/caddy && \
touch /var/log/caddy.log && \
chown root:www-data /var/log/caddy.log && \
chmod 770 /var/log/caddy.log && \
mkdir -p /var/www/html && \
chown -R www-data:www-data /var/www && \
touch /etc/caddy/Caddyfile

配置V2ray服务端,与上方原理说明的配置文件相似,只是将Vmess改成了Vless然后添加了WS协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"inbounds": [
{
"port": 16823, // 服务器监听端口
"protocol": "vless", // 主传入协议
"settings": {
"decryption": "none",
"clients": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
}
]
},
"streamSettings": {
"network": "ws"
"wsSettings": {
"path": "/test"
}
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}

配置Caddy转发Websocket请求到V2ray

1
2
3
4
5
6
7
8
9
10
echo "example.com { \
root /var/www/html \
gzip \
tls [email protected] \
log /var/log/caddy.log \
proxy /test localhost:16823 { \
websocket \
header_upstream -Origin \
} \
} " > /etc/caddy/Caddyfile

启动caddy和v2ray

1
systemctl restart v2ray && systemctl restart caddy

此时V2ray服务端搭建完毕。

Wireguard服务接口

这个部分和上面原理说明的完全没有区别,直接按照上面的方法配置就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /etc/wireguard/wg0.conf
-------------------------------
[Interface]
PrivateKey = 2GjqFPL8IXKs3fECd4/FO6M1XnLFw4N8uHSzT9i62mc=
Address = 10.101.0.1/32
ListenPort = 10000
#监听10000端口

[Peer]
PublicKey = EZ/WK+xSI5cIL3diRAI2K0LVWefMiky3a3MxYBaL5As=
AllowedIPs = 10.101.0.2/32
-------------------------------
# 启动接口
wg-quick up wg0

GRE接口

在服务器上配置新的接口。

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/sysconfig/network-scripts/ifcfg-tun0
-------------------------------
DEVICE=tun0
BOOTPROTO=none
ONBOOT=no
TYPE=GRE
PEER_OUTER_IPADDR=10.101.0.2 #对端IP
PEER_INNER_IPADDR=10.101.1.2
MY_INNER_IPADDR=10.101.1.1
-------------------------------

ifup tun0

此时所有的服务器端配置都设定完毕。

客户端

V2ray接入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{
"inbounds": [
{
"tag":"wireguard",
"port":10000,
"protocol":"dokodemo-door",
"settings":{
"address":"127.0.0.1",
"port":10000,
"network":"udp"
}
}
],
"outbounds": [
{
"tag":"proxy",
"protocol": "vless", // 出口协议
"settings": {
"vnext": [
{
"address": "example.com", // 服务器地址
"port": 443,
"users": [
{
"encryption": "none",
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
}
]
}
]
}
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"allowInsecure": true,
"serverName": "example.com"
},
"wsSettings": {
"path": "/test",
"headers": {
"Host": "example.com"
}
}
}
}
],
"routing":{
"rules":[
{
"type":"field",
"inboundTag":[
"wireguard"
],
"outboundTag":"proxy"
}
]
}
}

Wireguard接入

1
2
3
4
5
6
7
8
[Interface]
PrivateKey = wAuG/N59IEqdQT42rTi8bfTP00ygLQMe6Rjl85aSE1k=
Address = 10.101.0.2/32

[Peer]
PublicKey = PpE7xyUVEXfccO3GrFUad36s8WG5frJQTNd499oceHI=
AllowedIPs = 10.101.0.1/32
Endpoint = 127.0.0.1:10000

然后输入wg-quick up wg0启动接口

GRE接入

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/sysconfig/network-scripts/ifcfg-tun0
-------------------------------
DEVICE=tun0
BOOTPROTO=none
ONBOOT=no
TYPE=GRE
PEER_OUTER_IPADDR=10.101.0.1 #对端IP
PEER_INNER_IPADDR=10.101.1.1
MY_INNER_IPADDR=10.101.1.2
-------------------------------

ifup tun0

最后在客户端输入ping 10.101.1.1,如果ping通了则算是打通了GRE隧道。