forked from pschmitt/pia-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pia-tools
executable file
·444 lines (403 loc) · 12.5 KB
/
pia-tools
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#!/bin/bash
# Description: Script to automate privateinternetacces port forwarding and
# starting/stopping transmission when connected/disconnected and other stuff
# Version: 0.9.7.3
# Author: Philipp Schmitt (philipp<at>schmitt.co)
# Documentation: cf. pia-tools.groff
# Dependencies: curl openvpn sudo systemd transmission-daemon unzip
# Source config file
test "$PIA_CONF" || PIA_CONF='/etc/pia-tools.conf'
[[ -r "$PIA_CONF" ]] && . $PIA_CONF
# Setup default config if not already set in pia-tools.conf
if [[ -z "$PIA_CONFIG_DIR" ]]; then
PIA_CONFIG_DIR='/etc/openvpn/pia'
fi
if [[ -z "$PIA_CONFIG_URL" ]]; then
PIA_CONFIG_URL='https://www.privateinternetaccess.com/openvpn/openvpn.zip'
fi
if [[ -z "$PIA_COMMON_CONFIG" ]]; then
PIA_COMMON_CONFIG="$PIA_CONFIG_DIR/pia_common"
fi
if [[ -z "$PIA_SERVERS_FILE" ]]; then
PIA_SERVERS_FILE="$PIA_CONFIG_DIR/piaservers"
fi
if [[ -z "$PIA_SERVERS_IP_FILE" ]]; then
PIA_SERVERS_IP_FILE="$PIA_CONFIG_DIR/piaserverips"
fi
if [[ -z "$PIA_PASSWD_FILE" ]]; then
PIA_PASSWD_FILE="$PIA_CONFIG_DIR/passwd"
fi
if [[ -z "$PIA_CLIENT_ID_FILE" ]]; then
PIA_CLIENT_ID_FILE="$PIA_CONFIG_DIR/clientid"
fi
if [[ -z "$TRANSMISSION_SETTINGS_FILE" ]]; then
TRANSMISSION_SETTINGS_FILE='/home/dl/.config/transmission-daemon/settings.json'
fi
if [[ -z "$PIA_OPEN_PORT_FILE" ]]; then
PIA_OPEN_PORT_FILE="$PIA_CONFIG_DIR/open_port"
fi
PIA_OPEN_PORT="$(cat $PIA_OPEN_PORT_FILE 2>/dev/null)"
if [[ -z "$NETWORK_DEVICES" ]]; then
NETWORK_DEVICES=$(ip route get "$(host privateinternetaccess.com | awk '/has address/ { print $4 }')" | awk '/dev/ { print $5 }')
fi
if [[ -z "$VIRT_NET_DEV" ]]; then
VIRT_NET_DEV='tun0'
fi
usage() {
echo "Usage: $1 [-p|r] [-a|d] [-u] [-c] [-h]"
echo "-p: Request new port"
echo "-r: Refresh (request port forwarding again) [default]"
echo "-a: Block non VPN traffic (iptables)"
echo "-d: Unblock non VPN traffic (iptables) [default]"
echo "-g: Use PIA DNS (updates resolv.conf)"
echo "-u: Update configuration files"
echo "-s: Run setup"
echo "-c: Ensure OpenVPN is running. If not stop transmission"
echo "-h: Display this message"
echo "-v: Verbose output"
}
# Checks if executed as root. If not reinvoke self with sudo
check_root() {
if [[ $EUID -ne 0 ]]; then
if test "$VERBOSE"; then
echo -e "This script must be run as root\nInvoking sudo -- $0 $*" 1>&2
fi
exec sudo -- "$0" "$@"
fi
}
check_transmission() {
systemctl is-active transmission > /dev/null 2>&1
}
# Checks if the OpenVPN service is running
check_ovpn() {
local ovpnd="$(systemctl -t service | grep 'pia@.* active')"
if [[ -z "$ovpnd" ]]; then
echo 'OpenVPN service not running !' >&2
if check_transmission; then
echo -n 'Stopping transmission... '
systemctl stop transmission
echo 'Done!'
else
echo "Transmissiond not running" >&2
fi
_ufw_delete_rule "$PIA_OPEN_PORT"
# ufw_unblock
return 1
fi
}
info() {
local vpn_exit="$(systemctl -t service | grep 'pia@.* active' \
| awk '{ print $NF }')"
if check_ovpn; then
echo "OpenVPN is running (Exit point: $vpn_exit)"
else
echo "OpenVPN stopped"
fi
if check_transmission; then
echo "Transmissiond is running"
else
echo "Transmissiond stopped"
fi
}
_ufw_port_allowed() {
ufw status | grep -E "^$1\s+ALLOW" > /dev/null
}
# Delete previous rule from ufw
_ufw_delete_rule() {
if test "$1" && _ufw_port_allowed "$1"; then
ufw delete allow "$1"
fi
}
# Add a new rule to ufw
_ufw_add_new_rule () {
if test "$1" && ! _ufw_port_allowed "$1"; then
ufw allow "$1"
fi
}
# Update ufw rules
ufw_update() {
# Check if ufw is running
systemctl is-active ufw > /dev/null 2>&1 || return 1
echo -n "Updating UFW rules... "
_ufw_delete_rule "$PIA_OPEN_PORT"
_ufw_add_new_rule "$PIA_OPEN_PORT_NEW"
ufw reload > /dev/null
echo 'Done!'
}
ufw_allow_non_vpn() {
echo -n 'Allowing non-VPN traffic ... '
for i in $NETWORK_DEVICES; do
ufw delete deny out on $i > /dev/null 2>&1
ufw delete deny in on $i > /dev/null 2>&1
done
echo 'Done!'
}
ufw_deny_non_vpn() {
echo -n 'Denying non-VPN traffic ... '
for i in $NETWORK_DEVICES; do
ufw deny out on $i > /dev/null 2>&1
ufw deny in on $i > /dev/null 2>&1
done
echo 'Done!'
}
transmission_peer_port_update() {
local transmission_peer_port="$(grep 'peer-port\"' $TRANSMISSION_SETTINGS_FILE | grep -Eo '[0-9]+')"
echo -n "Updating transmission's listening port... "
# Check if transmission is running
if check_transmission; then
# get current listening port
transmission_peer_port="$(transmission-remote -si | grep Listenport | grep -oE '[0-9]+')"
if [[ "$PIA_OPEN_PORT_NEW" != "$transmission_peer_port" ]]; then
transmission-remote -p "$PIA_OPEN_PORT_NEW"
# systemctl restart transmission
echo 'Checking port...'
# TODO The sleep timer may need to be adjusted
sleep 3 && transmission-remote -pt
fi
else
# write new listening port to config
if test "$PIA_OPEN_PORT_NEW" && \
[[ "$PIA_OPEN_PORT_NEW" != "$transmission_peer_port" ]]; then
echo "Writing new peer port to transmission's settings.json..."
sed -i 's/\(\"peer-port\":\).*,/\1 '"$PIA_OPEN_PORT_NEW"',/' "$TRANSMISSION_SETTINGS_FILE"
fi
check_ovpn && systemctl restart transmission
fi
echo 'Done!'
}
# Return a new client ID
new_client_id() {
head -n 100 /dev/urandom | md5sum | tr -d " -" | tee $PIA_CLIENT_ID_FILE
}
request_port() {
local username="$(head -1 $PIA_PASSWD_FILE)"
local passwd="$(tail -1 $PIA_PASSWD_FILE)"
local local_vpn_ip="$(ip addr show $VIRT_NET_DEV | grep inet | awk '{ print $2 }')"
local client_id="$1"
[[ -z "$local_vpn_ip" ]] && local_vpn_ip=$LOCAL_IP
echo -n "Updating port forwarding... "
if test "$VERBOSE"; then
echo "Username: $username"
echo "Client ID: $client_id"
echo "VPN local IP: $local_vpn_ip"
fi
PIA_OPEN_PORT_NEW="$(\
curl -Ld "user=$username&pass=$passwd&client_id=$client_id&local_ip=$local_vpn_ip" \
https://www.privateinternetaccess.com/vpninfo/port_forward_assignment \
| grep -oE "[0-9]+" 2>&1)"
if test "$PIA_OPEN_PORT_NEW"; then
echo "$PIA_OPEN_PORT_NEW" > "$PIA_OPEN_PORT_FILE"
echo "Done! Port: $PIA_OPEN_PORT_NEW"
if [[ "$PIA_OPEN_PORT_NEW" != "$PIA_OPEN_PORT" ]]; then
test "$PIA_OPEN_PORT" && echo "Previous: $PIA_OPEN_PORT"
fi
# Update firewall rules
ufw_update
transmission_peer_port_update # Update Transmission's peer port
else
echo 'Failed'
fi
}
setup() {
if [[ -e $PIA_PASSWD_FILE ]]; then
echo -en "$PIA_PASSWD_FILE exits.\nRemove it? (y|N) "
read delete
if [[ $delete == "y" ]]; then
rm -f "$PIA_PASSWD_FILE"
else
update_config
return
fi
fi
mkdir -p $PIA_CONFIG_DIR
echo -n "Username: "
read username
echo -ne "Password: "
read -s password
echo -e "${username}\n${password}" > $PIA_PASSWD_FILE
chmod 400 $PIA_PASSWD_FILE
echo
update_config
echo "Now you can connect to the VPN"
echo "# systemctl start pia@Sweden"
}
update_config() {
echo -n 'Updating configuration... '
local ovpn ovpn_spaceless
# Clean up
rm -f $PIA_CONFIG_DIR/ca.crt $PIA_CONFIG_DIR/*.ovpn
# Fetch server config files
curl -sL -o $PIA_CONFIG_DIR/openvpn.zip $PIA_CONFIG_URL
unzip -d $PIA_CONFIG_DIR -q $PIA_CONFIG_DIR/openvpn.zip
# Replace space by underscore in filenames
local ifs_bak=$IFS
IFS=$(echo -en "\n\b")
for ovpn in "$PIA_CONFIG_DIR"/*.ovpn; do
# Rename files so that do not contain spaces
ovpn_spaceless=$(sed 's/ /_/g' <<< "$ovpn")
if [[ "$ovpn" != "$ovpn_spaceless" ]]; then
mv "$ovpn" "$ovpn_spaceless"
fi
# Append up/down scripts to every ovpn file
cat "$PIA_COMMON_CONFIG" >> "$ovpn_spaceless"
done
IFS=$ifs_bak
# Extract server addresses and resolve hosts
grep -h "remote " "$PIA_CONFIG_DIR"/*.ovpn | cut -d ' ' -f 2 \
| sort -u > "$PIA_SERVERS_FILE"
cat "$PIA_SERVERS_FILE" | nslookup \
| sed -n 's/Address: \(.*\)/\1/gp' > "$PIA_SERVERS_IP_FILE"
# why is following dig cmd failing randomly ?
#dig -f /tmp/piaservers A +short | sort > $PIA_SERVERS_IP_FILE
echo 'Done!'
}
_dns() {
local resolv=/etc/resolv.conf
local resolv_bak=/etc/resolv.conf.orig
if [[ ! -e $resolv_bak ]]; then
if mv $resolv $resolv_bak; then
test "$VERBOSE" && echo "Backed up $resolv to $resolv_bak"
fi
fi
echo -n "Updating $resolv file... "
echo "# Generated by $(basename $0)" > "$resolv"
for dns in "$@"; do
echo "nameserver $dns" >> "$resolv"
done
echo 'Done!'
test "$VERBOSE" && echo -e "New $resolv:\n$(cat $resolv)"
}
pia_dns() {
_dns '209.222.18.222' '209.222.18.218'
}
google_dns() {
_dns '8.8.8.8' '8.8.4.4'
}
restore_dns() {
if [[ ! -f /etc/resolv.conf.orig ]]; then
echo "Could not find a resolv.conf.orig" >&2
return 1
fi
mv -f /etc/resolv.conf.orig /etc/resolv.conf
}
# If no option -> refresh
if [[ $# -eq 0 ]]; then
action_port=refresh
#action_fw=disallow
fi
# Every function except help needs root permissions
check_root "$*"
ARGS=$(getopt -o "adprfguscihv" \
-l "allow,disallow,\
port,refresh,pia-dns,google-dns,restore-dns,\
restore,force,\
update,setup,info,help,verbose" \
-n "$0" -- "$@")
[[ $? -ne 0 ]] && { usage "$(basename $0)"; exit 1; }
eval set -- "$ARGS"
while true; do
case "$1" in
-a|--allow)
test "$action_fw" && exit 1
action_fw=allow
shift
;;
-d|--disallow)
test "$action_fw" && exit 1
action_fw=disallow
shift
;;
-p|--port)
test "$action_port" && exit 1
action_port=portfwd
shift
;;
-r|--refresh)
test "$action_port" && exit 1
action_port=refresh
shift
;;
-g|--pia-dns)
test "$action_dns" && exit 1
action_dns=pia
shift
;;
--google-dns)
test "$action_dns" && exit 1
action_dns=google
shift
;;
--restore-dns)
test "$action_dns" && exit 1
action_dns=restore
shift
;;
--restore)
test "$action_dns" && exit 1
action_dns=restore
action_check=1
shift
;;
-f|--force)
FORCE=1
shift
;;
-c|--check)
action_check=1
shift
;;
-i|--info)
action_info=1
shift
;;
-s|--setup)
action_setup=1
shift
;;
-u|--update)
action_update=1
shift
;;
-h|--help)
action_help=1
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
--)
shift
break;;
esac
done
# When started by OpenVPN daemon (up script) this script gets called like this:
# $0 $@ tun0 1500 1542 10.185.1.6 10.185.1.5 init
[[ -n $2 ]] && VIRT_NET_DEV=$1
[[ -n $4 ]] && LOCAL_IP=$4
test "$action_help" && { usage "$(basename $0)"; exit $?; }
test "$action_info" && { info; exit $?; }
test "$action_setup" && { setup; exit $?; }
test "$action_update" && update_config
test "$action_check" && check_ovpn
case "$action_dns" in
google) google_dns ;;
restore) restore_dns ;;
pia) pia_dns ;;
esac
# Block/Unblock non-VPN traffic if requested
case "$action_fw" in
disallow) ufw_deny_non_vpn ;;
allow) ufw_allow_non_vpn;;
esac
# Request port forwarding if action_port is set or no other action is
if test "$action_port"; then
client_id="$(cat $PIA_CLIENT_ID_FILE 2>/dev/null)"
if [[ -z "$client_id" ]] || [[ "$action_port" == "portfwd" ]]; then
client_id=$(new_client_id)
fi
[[ -z "$FORCE" ]] && check_ovpn
request_port "$client_id"
unset client_id action_port
fi
exit 0