-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbestVPN.py
executable file
·146 lines (117 loc) · 4.37 KB
/
bestVPN.py
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
#!/usr/bin/python3
"""
TODO LIST:
- before testing with speedtest, verify vpn is actually connected.
"""
import os
import sys
import argparse
import subprocess
from random import choice
from time import sleep
COLOR_NORM = '\033[0m'
COLOR_SUCCESS = '\033[0;32m'
COLOR_FAILURE = '\033[0;31m'
VPN_TIMEOUT_SEC = 10
VPN_MIN_DL_SPEED_MBPS = 2
VPN_POOL = ['NL 1', 'CZ_1']
SPEED_UNIT_MAP = {'Gbit/s':0.001, 'Mbit/s':1, 'Kbit/s':1000, 'bit/s':1000000}
SPEEDTEST_CLI_PATH = '/home/thedp/speedtest-cli/speedtest_cli.py'
FNULL = open(os.devnull, 'w')
def exec_cmd_blocking(cmd):
output = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=FNULL, shell=True).communicate()
return output[0].decode('utf-8')
def exec_cmd_with_timeout(full_cmd, timeout_sec):
p = subprocess.Popen(full_cmd, stdout=subprocess.PIPE, stderr=FNULL, shell=True)
try:
p.wait(timeout=timeout_sec)
return True
except subprocess.TimeoutExpired:
p.terminate()
return False
def kill_vpn():
exec_cmd_blocking('sudo killall openvpn')
sleep(5)
def disconnect_vpn(vpn_id):
exec_cmd_blocking('sudo nmcli con down id "'+ vpn_id +'"')
sleep(4)
def connect_vpn(vpn_id, timeout_sec):
print('>> Connecting to "'+ vpn_id +'"... ', end='', flush=True)
cmd = 'sudo nmcli con up id "'+ vpn_id +'"'
status = exec_cmd_with_timeout(cmd, timeout_sec)
if not status:
print(COLOR_FAILURE +'it\'s crap'+ COLOR_NORM)
else:
print(COLOR_SUCCESS +'ok'+ COLOR_NORM)
sleep(3)
return status
def select_vpn(vpn_server_index):
if vpn_server_index > -1:
return VPN_POOL[vpn_server_index]
return choice(VPN_POOL)
def get_dl_speed_mbps(result):
""" result example:
Ping: 345.46 ms
Download: 8.97 bit/s
Upload: 7.31 Mbit/s"
"""
dl_line_list = ((result.split('\n'))[1].split(' '))
speed = float(dl_line_list[1])
unit = float(SPEED_UNIT_MAP[dl_line_list[2]])
return speed / unit
def test_vpn_connection(min_dl_speed_mbps):
print('>> Testing with speedtest... ', end='', flush=True)
result = exec_cmd_blocking(SPEEDTEST_CLI_PATH + ' --simple')
dl_speed_mbps = get_dl_speed_mbps(result)
status = (True, COLOR_SUCCESS) if min_dl_speed_mbps <= dl_speed_mbps else (False,
COLOR_FAILURE)
print(status[1] + str(dl_speed_mbps) +'Mbps'+ COLOR_NORM)
return status[0]
def show_vpn_servers_list():
print('Listing available VPN servers.')
print('Used with "--server <vpn_server_index>" flag.')
for i in range(0, len(VPN_POOL)):
print(str(i) +': '+ VPN_POOL[i])
###########
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='bestVPN 0.1 - Finds the best VPN server.')
parser.add_argument('--list', dest='list_vpn_servers',
action='store_true', help='List VPN servers, and exit')
parser.add_argument('--server', dest='vpn_server_index', default='-1',
help='vpn server index')
parser.add_argument('--mbps', dest='min_mbps',
default=VPN_MIN_DL_SPEED_MBPS,
help='Change min. Mbps. Default='+ str(VPN_MIN_DL_SPEED_MBPS))
parser.add_argument('--timeout', dest='timeout_sec',
default=VPN_TIMEOUT_SEC,
help='Change timeout in seconds. Default='+ str(VPN_TIMEOUT_SEC))
parser.add_argument('--quick', dest='no_test', action='store_true',
help='Just connect, no testing with speedtest')
parser.add_argument('--test', dest='do_test_connection',
action='store_true', help='Only tests existing connection with speedtest')
args = parser.parse_args()
vpn_server_index = int(args.vpn_server_index)
VPN_MIN_DL_SPEED_MBPS = int(args.min_mbps)
VPN_TIMEOUT_SEC = int(args.timeout_sec)
if args.list_vpn_servers:
show_vpn_servers_list()
sys.exit()
if args.do_test_connection:
test_vpn_connection(VPN_MIN_DL_SPEED_MBPS)
sys.exit()
while True:
try:
vpn_id = select_vpn(vpn_server_index)
if connect_vpn(vpn_id, VPN_TIMEOUT_SEC):
if not args.no_test:
if test_vpn_connection(VPN_MIN_DL_SPEED_MBPS):
break
else:
break
disconnect_vpn(vpn_id)
except KeyboardInterrupt:
print('\nOk.. Bye.')
sys.exit()
except:
raise