forked from ethack/docker-vpn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvpn.sh
163 lines (143 loc) · 5.6 KB
/
vpn.sh
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
#!/bin/bash
openvpn() {
local vpnName="$1"; shift
if [ -z "$vpnName" ]; then
echo "VPN name must be provided"
return
fi
# listen on localhost by default
local bindIf="${BIND_INTERFACE:-127.0.0.1}"
local socksPort="${SOCKS_PORT:-1080}"
local sshPort="${SSH_PORT:-2222}"
local authorizedKeys="${AUTHORIZED_KEYS}"
local vpnConfig="$HOME/.vpn"
local dockerImage="ethack/vpn"
# AUTHORIZED_KEYS not specified. Use some defaults.
if [ -z "$authorizedKeys" ]; then
# add any key allowed to ssh in as the current user
if [ -f "$HOME/.ssh/authorized_keys" ]; then
printf -v authorizedKeys "$(cat "$HOME/.ssh/authorized_keys")\n"
fi
# add all keys currently registered with ssh-agent
if command -v ssh-add >/dev/null; then
printf -v authorizedKeys "$(ssh-add -L)\n"
fi
# append any public key files found in the user's .ssh directory
authorizedKeys+=$(find "$HOME/.ssh/" -type f -name '*.pub' -exec cat {} \;)
fi
local dockerCmd=("docker" "run")
local vpnCmd=("openvpn")
dockerCmd+=("--rm" "--name" "vpn-$vpnName")
dockerCmd+=("--hostname" "vpn-$vpnName")
dockerCmd+=("--interactive" "--tty")
dockerCmd+=("--cap-add" "NET_ADMIN")
dockerCmd+=("--device" "/dev/net/tun")
dockerCmd+=("--publish" "$bindIf:$sshPort:22")
dockerCmd+=("--publish" "$bindIf:$socksPort:1080")
dockerCmd+=("--env" "AUTHORIZED_KEYS=$authorizedKeys")
if [ -f "$vpnConfig/$vpnName.ovpn" ]; then
dockerCmd+=("--mount" "type=bind,src=$vpnConfig/$vpnName.ovpn,dst=/vpn/config,readonly=true")
vpnCmd+=("--config" "/vpn/config")
fi
if [ -f "$vpnConfig/$vpnName.creds" ]; then
dockerCmd+=("--mount" "type=bind,src=$vpnConfig/$vpnName.creds,dst=/vpn/creds,readonly=true")
vpnCmd+=("--auth-user-pass" "/vpn/creds")
vpnCmd+=("--auth-retry" "interact")
fi
dockerCmd+=("$dockerImage")
# append any extra args provided
vpnCmd+=($@)
# display help if there are no arguments at this point
if [ ${#vpnCmd[@]} -eq 1 ]; then
vpnCmd+=("--help")
fi
setup-ssh-config.d
ssh-config "$vpnName" "$sshPort" > "$HOME/.ssh/config.d/vpn-$vpnName"
echo "============================================"
echo "SSH Port: $sshPort (customize with SSH_PORT)"
echo "SOCKS Proxy Port: $socksPort (customize with SOCKS_PORT)"
echo "Use: ssh $vpnName"
echo "============================================"
"${dockerCmd[@]}" "${vpnCmd[@]}"
}
openconnect() {
local vpnName="$1"; shift
if [ -z "$vpnName" ]; then
echo "VPN name must be provided"
return
fi
# listen on localhost by default
local bindIf="${BIND_INTERFACE:-127.0.0.1}"
local socksPort="${SOCKS_PORT:-1080}"
local sshPort="${SSH_PORT:-2222}"
local authorizedKeys="${AUTHORIZED_KEYS}"
local vpnConfig="$HOME/.vpn"
local dockerImage="ethack/vpn"
# AUTHORIZED_KEYS not specified. Use some defaults.
if [ -z "$authorizedKeys" ]; then
# add any key allowed to ssh in as the current user
if [ -f "$HOME/.ssh/authorized_keys" ]; then
printf -v authorizedKeys "$(cat "$HOME/.ssh/authorized_keys")\n"
fi
# add all keys currently registered with ssh-agent
if command -v ssh-add >/dev/null; then
printf -v authorizedKeys "$(ssh-add -L)\n"
fi
# append any public key files found in the user's .ssh directory
authorizedKeys+=$(find "$HOME/.ssh/" -type f -name '*.pub' -exec cat {} \;)
fi
local dockerCmd=("docker" "run")
local vpnCmd=("openconnect")
dockerCmd+=("--rm" "--name" "vpn-$vpnName")
dockerCmd+=("--hostname" "vpn-$vpnName")
dockerCmd+=("--interactive" "--tty")
dockerCmd+=("--cap-add" "NET_ADMIN")
dockerCmd+=("--device" "/dev/net/tun")
dockerCmd+=("--publish" "$bindIf:$sshPort:22")
dockerCmd+=("--publish" "$bindIf:$socksPort:1080")
dockerCmd+=("--env" "AUTHORIZED_KEYS=$authorizedKeys")
if [ -f "$vpnConfig/$vpnName.xml" ]; then
dockerCmd+=("--mount" "type=bind,src=$vpnConfig/$vpnName.xml,dst=/vpn/config,readonly=true")
vpnCmd+=("--xmlconfig" "/vpn/config")
fi
dockerCmd+=("$dockerImage")
# append any extra args provided
vpnCmd+=($@)
# display help if there are no arguments at this point
if [ ${#vpnCmd[@]} -eq 1 ]; then
vpnCmd+=("--help")
fi
setup-ssh-config.d
ssh-config "$vpnName" "$sshPort" > "$HOME/.ssh/config.d/vpn-$vpnName"
chmod 600 "$HOME/.ssh/config.d/vpn-$vpnName"
echo "============================================"
echo "SSH Port: $sshPort (customize with SSH_PORT)"
echo "SOCKS Proxy Port: $socksPort (customize with SOCKS_PORT)"
echo "Use: ssh $vpnName"
echo "============================================"
"${dockerCmd[@]}" "${vpnCmd[@]}"
}
# Create and configure the .ssh/config.d directory if it's not already
setup-ssh-config.d() {
if ! grep -qFi -e 'Include config.d/*' -e 'Include ~/.ssh/config.d/*' "$HOME/.ssh/config"; then
echo >> "$HOME/.ssh/config"
# This allows the Include to be at the end of the file (i.e. not nested in a Host directive)
echo 'Match all' >> "$HOME/.ssh/config"
echo 'Include config.d/*' >> "$HOME/.ssh/config"
fi
mkdir -p "$HOME/.ssh/config.d/"
}
# Print the SSH config entry for the given name and port
ssh-config() {
local name="$1"
local sshPort="$2"
local user="root"
local host="127.0.0.1"
cat << EOF
Host vpn-$name $name
Hostname $host
User $user
Port $sshPort
NoHostAuthenticationForLocalhost yes
EOF
}