forked from sakai135/wsl-vpnkit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wsl-vpnkit
executable file
·168 lines (143 loc) · 5.02 KB
/
wsl-vpnkit
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/bin/sh
set -x
# hardcoded in gvisor-tap-vsock
VPNKIT_GATEWAY_IP=${VPNKIT_GATEWAY_IP:-192.168.127.1}
VPNKIT_HOST_IP=${VPNKIT_HOST_IP:-192.168.127.254}
VPNKIT_LOCAL_IP=${VPNKIT_LOCAL_IP:-192.168.127.2}
TAP_MAC_ADDR=${TAP_MAC_ADDR:-5a:94:ef:e4:0c:ee}
# overrideable with env
VMEXEC_PATH=${VMEXEC_PATH:-/app/wsl-vm}
GVPROXY_PATH=${GVPROXY_PATH:-/app/wsl-gvproxy.exe}
TAP_NAME=${TAP_NAME:-wsltap}
CHECK_HOST=${CHECK_HOST:-example.com}
CHECK_DNS=${CHECK_DNS:-1.1.1.1}
DEBUG=${DEBUG:-0}
set +x
# WSL2 default values
WSL2_TAP_NAME=${WSL2_TAP_NAME:-eth0}
WSL2_RESOLVCONF_DEFAULT="/mnt/wsl/resolv.conf"
if [ ! -f "$WSL2_RESOLVCONF_DEFAULT" ]; then
WSL2_RESOLVCONF_DEFAULT="/etc/resolv.conf"
fi
WSL2_RESOLVCONF=${WSL2_RESOLVCONF:-$WSL2_RESOLVCONF_DEFAULT}
WSL2_GATEWAY_IP_FROM_RESOLVCONF="$(cat $WSL2_RESOLVCONF | awk '/^nameserver/ {print $2}')"
WSL2_GATEWAY_IP=${WSL2_GATEWAY_IP:-$WSL2_GATEWAY_IP_FROM_RESOLVCONF}
set -x
# show values
WSL2_TAP_NAME=$WSL2_TAP_NAME
WSL2_GATEWAY_IP=$WSL2_GATEWAY_IP
if [ "$DEBUG" -eq 0 ]; then
set +x
fi
# replace calls to iptables if iptables-legacy exists
command -v iptables-legacy >/dev/null && alias iptables=iptables-legacy
run () {
echo "starting vm and gvproxy..."
$VMEXEC_PATH \
-url="stdio:$GVPROXY_PATH?listen-stdio=accept&debug=$DEBUG" \
-iface="$TAP_NAME" \
-stop-if-exist="" \
-preexisting=1 \
-debug=$DEBUG &
sleep 1 # wait to establish connection
echo "started vm and gvproxy"
}
wsl2tap_down () {
# remove WSL2 default route
ip route del default
# setup wsl-vpnkit tap
ip tuntap add $TAP_NAME mode tap
ip link set dev $TAP_NAME address $TAP_MAC_ADDR
ip link set dev $TAP_NAME up
ip addr add $VPNKIT_LOCAL_IP/255.255.255.0 dev $TAP_NAME
ip route add default via $VPNKIT_GATEWAY_IP dev $TAP_NAME
}
wsl2tap_up () {
# take down wsl-vpnkit tap
ip link set dev $TAP_NAME down 2>/dev/null
ip tuntap del $TAP_NAME mode tap
# add WSL2 default route
ip route add default via $WSL2_GATEWAY_IP dev $WSL2_TAP_NAME 2>/dev/null
}
iptables_set () {
iptables -t nat -$1 PREROUTING -d $WSL2_GATEWAY_IP/32 -p udp -m udp --dport 53 -j DNAT --to-destination $VPNKIT_GATEWAY_IP:53
iptables -t nat -$1 PREROUTING -d $WSL2_GATEWAY_IP/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination $VPNKIT_GATEWAY_IP:53
iptables -t nat -$1 PREROUTING -d $WSL2_GATEWAY_IP/32 -j DNAT --to-destination $VPNKIT_HOST_IP
iptables -t nat -$1 OUTPUT -d $WSL2_GATEWAY_IP/32 -p udp -m udp --dport 53 -j DNAT --to-destination $VPNKIT_GATEWAY_IP:53
iptables -t nat -$1 OUTPUT -d $WSL2_GATEWAY_IP/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination $VPNKIT_GATEWAY_IP:53
iptables -t nat -$1 OUTPUT -d $WSL2_GATEWAY_IP/32 -j DNAT --to-destination $VPNKIT_HOST_IP
iptables -t nat -$1 POSTROUTING -o $TAP_NAME -j MASQUERADE
}
check_ping () {
ping -$1 -c 1 $3 >/dev/null && \
echo "check: ✔️ ping success to IPv$1 $2 ($3)" || \
echo "check: $([ $1 = '6' ] && echo '➖' || echo '❌') ping fail to IPv$1 $2 ($3)"
}
check_dns () {
TYPE=$([ "$1" = "4" ] && echo 'A' || echo 'AAAA')
nslookup -type=$TYPE $2 $3 >/dev/null && \
echo "check: ✔️ nslookup success for $2 $TYPE using $3" || \
echo "check: ❌ nslookup fail for $2 $TYPE using $3"
}
check_https () {
wget --spider -q $1 && \
echo "check: ✔️ wget success for $1" || \
echo "check: ❌ wget fail for $1"
}
check () {
check_ping 4 'WSL 2 gateway / Windows host' $WSL2_GATEWAY_IP
check_ping 4 'Windows host' $VPNKIT_HOST_IP
check_ping 4 'gateway' $VPNKIT_GATEWAY_IP
check_dns 4 $CHECK_HOST $VPNKIT_GATEWAY_IP
check_dns 4 $CHECK_HOST $WSL2_GATEWAY_IP
check_dns 4 $CHECK_HOST $CHECK_DNS
check_ping 4 'external host domain' $CHECK_HOST
check_ping 4 'external host IP' $CHECK_DNS
check_dns 6 $CHECK_HOST $VPNKIT_GATEWAY_IP
check_dns 6 $CHECK_HOST $WSL2_GATEWAY_IP
check_dns 6 $CHECK_HOST $CHECK_DNS
check_ping 6 'external host' $CHECK_HOST
check_https "http://$CHECK_HOST"
check_https "https://$CHECK_HOST"
}
cleanup () {
iptables_set D 2>/dev/null
wsl2tap_up
}
close () {
echo "cleaning up..."
cleanup
echo "stopped wsl-vpnkit"
kill 0
}
if [ ${EUID:-$(id -u)} -ne 0 ]; then
echo "Please run this script as root"
exit 1
fi
if [ ! -f "$VMEXEC_PATH" ]; then
echo "VMEXEC_PATH [$VMEXEC_PATH] does not exist"
exit 1
fi
if [ ! -f "$GVPROXY_PATH" ]; then
echo "GVPROXY_PATH [$GVPROXY_PATH] does not exist"
exit 1
fi
cat $WSL2_RESOLVCONF | grep "automatically generated by WSL" >/dev/null
if [ $? -eq 1 ]; then
echo "resolv.conf has been modified without setting generateResolvConf"
fi
$GVPROXY_PATH -help 2>/dev/null
if [ $? -eq 1 ]; then
echo "$GVPROXY_PATH is not executable due to WSL interop settings or Windows permissions"
exit 1
fi
# trap first so close runs even if the rest of the commands fail
trap close exit
trap exit int term
# run cleanup to restore any leftover configuration changes
cleanup
wsl2tap_down
run
iptables_set A
check
wait