-
Notifications
You must be signed in to change notification settings - Fork 7
/
ipsec-vpn-connect
executable file
·239 lines (205 loc) · 5.73 KB
/
ipsec-vpn-connect
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#!/bin/sh
exec 2>&1
error() {
echo "$@" >&2
exit 1
}
# Default settings.
DEBUG=0
# Read settings in this file.
[ -z "$1" ] && error "Usage: $0 <configuration file>"
[ -r "$1" ] || error "Could not read configuration file $1."
cfgfile="`readlink -f $1`"
. $cfgfile
[ -z "$VPN_SERVER" ] && error "VPN_SERVER is not set"
[ -z "$TUNNEL_PSK" ] && error "TUNNEL_PSK is not set"
[ -z "$VPN_USERNAME" ] && error "VPN_USERNAME is not set"
[ -z "$VPN_PASSWORD" ] && error "VPN_PASSWORD is not set"
# Base the VPN name on a hash of the config file path.
xl2tpd_vpnname=tmpvpn_`echo $cfgfile | md5sum | cut -c1-8`
# Ensure we are root.
[ "`id -u`" = 0 ] || error "You must be root to run this program."
# Helper function to find the binaries we need.
check_prereqs() {
unsatisfied=
for i in "$@" ; do
command -v $i > /dev/null 2>&1 || unsatisfied="$unsatisfied $i"
done
echo $unsatisfied
[ -z "$unsatisfied" ]
}
# Helper function to kill a process, first giving it a chance.
graceful_kill() {
pid=$1
all=$2
tries=5
while [ $tries -gt 0 ] ; do
kill$all $pid > /dev/null 2>&1
tries=$(($tries-1))
sleep 0.5
kill$all -0 $pid > /dev/null 2>&1 || break
done
kill$all -9 $pid > /dev/null 2>&1
}
# Check for prerequisite binaries.
missing_prereqs=`check_prereqs ip racoon xl2tpd-control setkey killall` || \
error "Missing required utilities: $missing_prereqs"
# Ensure xl2tpd is running.
killall -0 xl2tpd >/dev/null 2>&1 || error "Did not detect xl2tpd running?"
# Translate hostname to IP address.
get_ip_address() {
host=$1
getent ahostsv4 $host | awk '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[ \t]/ { print $1 ; exit 0 }'
}
[ "$DEBUG" -ge 1 ] && \
echo -n "Looking up IP address for VPN server ($VPN_SERVER) ... "
vpn_ip=`get_ip_address $VPN_SERVER`
[ "$DEBUG" -ge 1 ] && echo "$vpn_ip"
[ -z "$vpn_ip" ] && \
error "Failed to resolve IP address of VPN server ($VPN_SERVER)."
# Create a temporary directory where we will do our work.
work_dir=`mktemp -d` || exit 1
[ -n "$work_dir" ] || exit 1
cd $work_dir
# Ensure cleanup is graceful. This is in theory the only way out of this
# script.
cleanup() {
xl2tpd-control disconnect $xl2tpd_vpnname
xl2tpd-control remove $xl2tpd_vpnname
[ -n "$racoon_pid" ] && graceful_kill $racoon_pid
[ "$SEND_ALL_TRAFFIC" = 1 ] && ip route delete $vpn_ip
[ -n "$work_dir" ] && rm -rf "$work_dir"
[ -n "$logger_pid" ] && graceful_kill $logger_pid
exit 0
}
trap cleanup INT HUP TERM QUIT
# Create a valid racoon.conf
racoon_debug_level="notify"
[ "$DEBUG" -ge 1 ] && racoon_debug_level="info"
[ "$DEBUG" -ge 2 ] && racoon_debug_level="debug"
cat <<EOT > racoon.conf
log $racoon_debug_level;
path pre_shared_key "psk.txt";
# Remote configuration based loosely on what OS X does.
remote $vpn_ip {
doi ipsec_doi;
situation identity_only;
exchange_mode main;
verify_identifier off;
initial_contact on;
support_proxy on;
nat_traversal on;
proposal_check obey;
generate_policy on;
proposal {
authentication_method pre_shared_key;
hash_algorithm sha1;
encryption_algorithm aes 256;
lifetime time 3600 sec;
dh_group 2;
}
proposal {
authentication_method pre_shared_key;
hash_algorithm md5;
encryption_algorithm aes 256;
lifetime time 3600 sec;
dh_group 2;
}
proposal {
authentication_method pre_shared_key;
hash_algorithm sha1;
encryption_algorithm aes;
lifetime time 3600 sec;
dh_group 2;
}
proposal {
authentication_method pre_shared_key;
hash_algorithm md5;
encryption_algorithm aes;
lifetime time 3600 sec;
dh_group 2;
}
proposal {
authentication_method pre_shared_key;
hash_algorithm sha1;
encryption_algorithm 3des;
lifetime time 3600 sec;
dh_group 2;
}
proposal {
authentication_method pre_shared_key;
hash_algorithm md5;
encryption_algorithm 3des;
lifetime time 3600 sec;
dh_group 2;
}
}
sainfo address 0.0.0.0/0 udp address ${vpn_ip} [1701] udp {
encryption_algorithm aes 256, aes, 3des;
authentication_algorithm hmac_sha1, hmac_md5;
compression_algorithm deflate;
lifetime time 3600 sec;
}
sainfo address ${vpn_ip} [1701] udp address 0.0.0.0/0 udp {
encryption_algorithm aes 256, aes, 3des;
authentication_algorithm hmac_sha1, hmac_md5;
compression_algorithm deflate;
lifetime time 3600 sec;
}
EOT
# Create pre-shared key file.
echo -n > psk.txt
chmod 600 psk.txt
cat <<EOT > psk.txt
* $TUNNEL_PSK
EOT
# Create options.xl2tpd
cat <<EOT > options.xl2tpd
noauth
EOT
[ "$ENABLE_IPV6" = "1" ] && echo '+ipv6' >> options.xl2tpd
if [ "$SEND_ALL_TRAFFIC" = "1" ] ; then
echo defaultroute >> options.xl2tpd
echo replacedefaultroute >> options.xl2tpd
fi
if [ "$DEBUG" -ge 1 ] ; then
echo debug >> options.xl2tpd
fi
# Start logging.
if [ "$DEBUG" -ge 1 ] ; then
tail --lines=0 -f /var/log/syslog |grep --line-buffered 'pppd\|racoon\|xl2tpd' &
logger_pid=$!
fi
# Fix a route to the VPN in case routing tables change.
ip route add `ip route get ${vpn_ip} | head -1`
# Set up IPSec policy
cat <<EOT | setkey -c
spddelete 0.0.0.0/0 ${vpn_ip}[l2tp] udp -P out ;
spddelete ${vpn_ip}[l2tp] 0.0.0.0/0 udp -P in ;
spdadd 0.0.0.0/0 ${vpn_ip}[l2tp] udp -P out ipsec
esp/transport//require;
spdadd ${vpn_ip}[l2tp] 0.0.0.0/0 udp -P in ipsec
esp/transport//require;
EOT
# Run racoon.
racoon -f racoon.conf -F &
racoon_pid=$!
# Is there a better way to find out if racoon is ready? Just give it a second.
sleep 1
# Create xl2tpd configuration
xl2tpd-control remove $xl2tpd_vpnname
xl2tpd-control add $xl2tpd_vpnname \
"lns=$vpn_ip" \
"redial=no" \
"require pap=no" \
"require chap = yes" \
"refuse pap = yes" \
"refuse chap = no" \
"pppoptfile = `readlink -f options.xl2tpd`"
# Send connect message.
xl2tpd-control connect $xl2tpd_vpnname $VPN_USERNAME $VPN_PASSWORD
# Do nothing forever, waiting for a Ctrl-C or other terminating signal.
# Only then will we cleanup().
while : ; do
read nothing
done