def fastest_sc_by_country(self, country, protocol=None): """Connect to the fastest Secure Core server in a specific country.""" pvpncli_logger.logger.debug("Starting fastest SC country connect") if not protocol: protocol = pvpncli_utils.get_config_value("USER", "default_protocol") country_code = self.get_country_code(country) self.exec_cmd('protonvpn d') pvpncli_utils.pull_server_data(force=True) servers = pvpncli_utils.get_servers() # ProtonVPN Features: 1: SECURE-CORE, 2: TOR, 4: P2P server_pool = [] for server in servers: if server["Features"] == 1 \ and server["ExitCountry"] == country_code: server_pool.append(server) fastest_server = pvpncli_utils.get_fastest_server(server_pool) cmd = f'protonvpn c {fastest_server} -p {protocol}' Clock.schedule_once(partial(self.exec_cmd, cmd), 0.1)
def update_labels_server_list(interface, server_tree_list_object=False, conn_info=False): """Function that updates dashboard labels and server list. """ if not server_tree_list_object: server_tree_list_obj = interface.get_object("ServerTreeStore") else: server_tree_list_obj = server_tree_list_object gui_logger.debug( ">>> Running \"update_labels_server_list\" getting servers.") servers = get_servers() if not servers: servers = False update_labels_dict = { "interface": interface, "servers": servers, "disconnecting": False, "conn_info": conn_info if conn_info else False } populate_servers_dict = { "tree_object": server_tree_list_obj, "servers": servers } # Update labels gobject.idle_add(update_labels_status, update_labels_dict) # Populate server list gobject.idle_add(populate_server_list, populate_servers_dict)
def get_server_list(self): """Build list of servers by Country.""" # Check for latest data. pvpncli_utils.pull_server_data(force=True) # Get server details from raw server data. servers_data = pvpncli_utils.get_servers() # Compile dictionary of countries and server details; key=country name. unsorted_countries = {} for server in servers_data: country = pvpncli_utils.get_country_name(server['ExitCountry']) if country not in unsorted_countries.keys(): unsorted_countries[country] = [] server_details = {} server_name = server['Name'] server_details[server_name] = {} for k, v in server.items(): server_details[server_name][k] = v unsorted_countries[country].append(server_details) # Alphabetize countries by country name. sorted_countries = sorted(unsorted_countries.keys()) servers_by_country = {} for country in sorted_countries: servers_by_country[country] = unsorted_countries[country] return servers_by_country
def update_serverload(self, _): """Updates server load. """ gui_logger.debug("TRAY >>> Updating server load in update_serverload.") connected_server = False load = False try: connected_server = get_config_value("metadata", "connected_server") except KeyError: gui_logger.debug("[!] Could not find specified key: ".format(KeyError)) return True # force_pull servers try: pull_server_data(force=True) except: gui_logger.debug("[!] Could not pull from servers, possible due to unstable connection.") return True # get_servers servers = get_servers() # get server load try: load = get_server_value(connected_server, "Load", servers) except: gui_logger.debug("[!] Unable to get server load.") return True self.serverload_msg = "Load: {}%".format(load) return True
def generate_autoconnect_list(self): countries = {} servers = get_servers() autoconnect_alternatives = ["dis", "fast", "rand", "p2p", "sc", "tor"] for server in servers: country = get_country_name(server["ExitCountry"]) if country not in countries.keys(): countries[country] = [] countries[country].append(server["Name"]) for country in sorted(countries): autoconnect_alternatives.append(country) return autoconnect_alternatives
def populate_autoconnect_list(interface, return_list=False): """Function that populates autoconnect dropdown list. """ autoconnect_liststore = interface.get_object("AutoconnectListStore") countries = {} servers = get_servers() other_choice_dict = { "dis": "Disabled", "fast": "Fastest", "rand": "Random", "p2p": "Peer2Peer", "sc": "Secure Core (Plus/Visionary)", "tor": "Tor (Plus/Visionary)" } autoconnect_alternatives = ["dis", "fast", "rand", "p2p", "sc", "tor"] # return_values = collections.OrderedDict() return_values = collections.OrderedDict() for server in servers: country = get_country_name(server["ExitCountry"]) if country not in countries.keys(): countries[country] = [] countries[country].append(server["Name"]) for country in sorted(countries): autoconnect_alternatives.append(country) for alt in autoconnect_alternatives: if alt in other_choice_dict: # if return_list: return_values[alt] = other_choice_dict[alt] # else: autoconnect_liststore.append([alt, other_choice_dict[alt], alt]) else: for k, v in country_codes.items(): if alt.lower() == v.lower(): # if return_list: return_values[k] = v # else: autoconnect_liststore.append([k, v, k]) if return_list: return return_values
def update_labels_status(update_labels_dict): """Function prepares data to update labels. """ gui_logger.debug(">>> Running \"update_labels_status\" getting servers, is_connected and connected_server.") if not update_labels_dict["servers"]: servers = get_servers() else: servers = update_labels_dict["servers"] protonvpn_conn_check = is_connected() is_vpn_connected = True if protonvpn_conn_check else False try: connected_server = get_config_value("metadata", "connected_server") except: connected_server = False update_labels(update_labels_dict["interface"], servers, is_vpn_connected, connected_server, update_labels_dict["disconnecting"], conn_info=update_labels_dict["conn_info"])
def update_current_connection(self, *dt): """Update the current connection info.""" # Check for active connection self.vpn_connected = self.is_connected() if self.vpn_connected: # Cancel scheduled events, if they exist. if self.data_trans: self.data_trans.cancel() if self.cnxn_time: self.cnxn_time.cancel() servers = pvpncli_utils.get_servers() ip = None while not ip: try: ip = pvpncli_utils.get_ip_info()[0] # except Exception as e: except SystemExit: print( 'Exception from update_current_connection(): SystemExit' ) # noqa print('reconnect cmd sent') self.exec_cmd('protonvpn reconnect') self.ids.main_screen.ids.exit_server_ip.text = f'IP: {ip}' connected_server = None try: connected_server = pvpncli_utils.get_config_value( "metadata", "connected_server", ) self.last_known_connection = connected_server except KeyError: self.last_known_connection = None # Set Secure Core switch if app newly initialized. Otherwise the # switch state is determined by User interaction afterwards. if self.app_newly_initialized: feature = pvpncli_utils.get_server_value( connected_server, "Features", servers, ) if feature == 1: self.secure_core.state = 'down' else: self.secure_core.state = 'normal' self.app_newly_initialized = False country_code = pvpncli_utils.get_server_value( connected_server, "ExitCountry", servers, ) cnxn_window = self.ids.main_screen.ids.connection_window flag = f'./images/flags/large/{country_code.lower()}-large.jpg' cnxn_window.img_source = flag country = pvpncli_utils.get_country_name(country_code) exit_server_info = f'{country} >> {connected_server}' self.ids.main_screen.ids.exit_server.text = exit_server_info self.ids.main_screen.ids.exit_server.color = [1, 1, 1, 1] connected_protocol = pvpncli_utils.get_config_value( "metadata", "connected_proto", ) self.ids.main_screen.ids.protocol.text = ( f'OpenVPN ({connected_protocol.upper()})') load = pvpncli_utils.get_server_value( connected_server, "Load", servers, ) self.ids.main_screen.ids.exit_server_load.text = f'{load}% Load' down = self.ids.main_screen.ids.bitrate_down_arrow down.source = './images/bitrate-download-arrow.png' up = self.ids.main_screen.ids.bitrate_up_arrow up.source = './images/bitrate-upload-arrow.png' # Make text visible. self.ids.main_screen.ids.data_received.color = [1, 1, 1, 1] self.ids.main_screen.ids.data_sent.color = [1, 1, 1, 1] # Set connection window button as 'Disconnect' self.cnxn_wndw_btn.normal_img = './images/disconnect.png' self.cnxn_wndw_btn.hover_img = './images/disconnect_hover.png' self.cnxn_wndw_btn.source = './images/disconnect.png' # Schedule events self.data_trans() self.cnxn_time() else: # VPN isn't connected, so clear the conneciton info on screen. self.set_disconnected()
def status(self) -> str: """ Return the current VPN status. Showing connection status (connected/disconnected), current IP, server name, country, server load """ if not self._check_configs(): return 'Settings problem. Please run "protonvpn init".' killswitch_active = is_killswitch_active(CONFIG_DIR) if not is_connected(): msgs = ['Not connected'] if killswitch_active: msgs.append('Kill Switch is currently active.') ip, isp = get_ip_info() msgs.extend((f'IP: {ip}', f'ISP: {isp}')) return '\n'.join(msgs) pull_server_data() metadata = self.config.get('metadata', {}) current_server = metadata.get("connected_server", None) current_protocol = metadata.get("connected_proto", None) dns_server = metadata.get("dns_server", None) if not metadata or \ not all((current_server, current_protocol, dns_server)): return 'Please connect with "protonvpn connect" first.' if not is_server_reachable(dns_server): msgs = ('Could not reach VPN server', 'You may want to reconnect with "protonvpn reconnect"') return '\n'.join(msgs) servers = get_servers() subs = [s["Servers"] for s in servers if s["Name"] == current_server] server_ips = [subserver["ExitIP"] for subserver in subs[0]] ip, isp = get_ip_info() all_features = {0: "Normal", 1: "Secure-Core", 2: "Tor", 4: "P2P"} country_code = get_server_value(current_server, "ExitCountry", servers) country = get_country_name(country_code) city = get_server_value(current_server, "City", servers) load = get_server_value(current_server, "Load", servers) feature = get_server_value(current_server, "Features", servers) last_connection = metadata.get("connected_time") connection_time = time.time() - int(last_connection) killswitch_status = "Enabled" if killswitch_active else "Disabled" connection_time = str(datetime.timedelta( seconds=connection_time)).split(".")[0] msgs = ( "Status: Connected", f"Time: {connection_time}", f"IP: {ip}", f"Server: {current_server}", f"Features: {all_features[feature]}", f"Protocol: {current_protocol.upper()}", f"Kill Switch: {killswitch_status}", f"Country: {country}", f"City: {city}", f"Load: {load}", ) return '\n'.join(msgs)
def populate_server_list(populate_servers_dict): """Function that updates server list. """ pull_server_data(force=True) only_secure_core = True if get_gui_config( "connections", "display_secure_core") == "True" else False if not populate_servers_dict["servers"]: servers = get_servers() else: servers = populate_servers_dict["servers"] if servers: populate_servers_dict["tree_object"].clear() country_servers = get_country_servers(servers) images_dict = create_features_img() for country in country_servers: # Get average load and highest feature avrg_load, country_feature = get_country_avrg_features( country, country_servers, servers, only_secure_core) flag = GdkPixbuf.Pixbuf.new_from_file_at_size( get_flag_path(country), 15, 15) # Check plus servers if country_feature == "normal" or country_feature == "p2p": plus_feature = images_dict["empty_pix"] else: plus_feature = images_dict["plus_pix"] # Check correct feature if country_feature == "normal" or country_feature == "secure-core": feature = images_dict["empty_pix"] elif country_feature == "p2p": feature = images_dict["p2p_pix"] elif country_feature == "tor": feature = images_dict["tor_pix"] if country_feature == "secure-core" and only_secure_core: country_row = populate_servers_dict["tree_object"].append( None, [flag, country, plus_feature, feature, avrg_load]) elif not only_secure_core: country_row = populate_servers_dict["tree_object"].append( None, [flag, country, plus_feature, feature, avrg_load]) for servername in country_servers[country]: servername, plus_feature, feature, load, secure_core = set_individual_server( servername, images_dict, servers, feature) if secure_core and only_secure_core: populate_servers_dict["tree_object"].append( country_row, [ images_dict["empty_pix"], servername, plus_feature, feature, load ]) elif not secure_core and not only_secure_core: populate_servers_dict["tree_object"].append( country_row, [ images_dict["empty_pix"], servername, plus_feature, feature, load ])
def update_labels_status(update_labels_dict): """Function prepares data to update labels. """ gui_logger.debug( ">>> Running \"update_labels_status\" getting servers, is_connected and connected_server." ) if not update_labels_dict["servers"]: servers = get_servers() else: servers = update_labels_dict["servers"] interface = update_labels_dict["interface"] disconnecting = update_labels_dict["disconnecting"] conn_info = update_labels_dict["conn_info"] is_vpn_connected = True if is_connected() else False country_cc = False load = False time_connected_label = interface.get_object("time_connected_label") protocol_label = interface.get_object("protocol_label") conn_disc_button_label = interface.get_object( "main_conn_disc_button_label") ip_label = interface.get_object("ip_label") server_load_label = interface.get_object("server_load_label") country_label = interface.get_object("country_label") isp_label = interface.get_object("isp_label") data_received_label = interface.get_object("data_received_label") data_sent_label = interface.get_object("data_sent_label") background_large_flag = interface.get_object("background_large_flag") protonvpn_sign_green = interface.get_object("protonvpn_sign_green") try: connected_server = get_config_value("metadata", "connected_server") except (KeyError, IndexError): connected_server = False # Get and set server load label try: load = get_server_value(connected_server, "Load", servers) except (KeyError, IndexError): gui_logger.debug("[!] Could not find server load information.") load = "{0}% Load".format(load) if load and is_vpn_connected else "" server_load_label.set_markup('<span>{0}</span>'.format(load)) # Get and set IP labels. Get also country and ISP if not conn_info: result = custom_get_ip_info() if result: ip, isp, country = result else: ip = "None" isp = "None" country = "None" else: ip, isp, country = conn_info for k, v in country_codes.items(): if k == country: if is_vpn_connected: flag_path = LARGE_FLAGS_BASE_PATH + "{}.jpg".format(k.lower()) background_large_flag.set_from_file(flag_path) country_cc = v protonvpn_sign_green.hide() country_server = country_cc if is_vpn_connected: try: country_server = country_server + " >> " + connected_server except TypeError: country_server = country_server + " >> " protonvpn_sign_green.show() ip_label.set_markup(ip) isp_label.set_markup(isp) # Get and set server name connected_server = connected_server if connected_server and is_vpn_connected else "" country_label.set_markup(country_server if country_server else "") # Update sent and received data gobject.timeout_add_seconds( 1, update_sent_received_data, { "is_vpn_connected": is_vpn_connected, "received_label": data_received_label, "sent_label": data_sent_label }) # Check and set VPN status label. Get also protocol status if vpn is connected protocol = "No VPN Connection" conn_disc_button = "Quick Connect" if is_vpn_connected and not disconnecting: try: connected_to_protocol = get_config_value("metadata", "connected_proto") protocol = '<span>OpenVPN >> {0}</span>'.format( connected_to_protocol.upper()) except (KeyError, IndexError): pass conn_disc_button = "Disconnect" conn_disc_button_label.set_markup(conn_disc_button) # Check and set DNS status label dns_enabled = get_config_value("USER", "dns_leak_protection") # Update time connected label gobject.timeout_add_seconds(1, update_connection_time, { "is_vpn_connected": is_vpn_connected, "label": time_connected_label }) # Check and set protocol label protocol_label.set_markup(protocol)
def populate_server_list(populate_servers_dict): """Function that updates server list. """ only_secure_core = True if get_gui_config("connections", "display_secure_core") == "True" else False pull_server_data(force=True) features = {0: "Normal", 1: "Secure-Core", 2: "Tor", 4: "P2P"} server_tiers = {0: "Free", 1: "Basic", 2: "Plus/Visionary"} if not populate_servers_dict["servers"]: servers = get_servers() else: servers = populate_servers_dict["servers"] # Country with respective servers, ex: PT#02 countries = {} if servers: for server in servers: country = get_country_name(server["ExitCountry"]) if country not in countries.keys(): countries[country] = [] countries[country].append(server["Name"]) country_servers = {} # Order server list by country alphabetically countries = collections.OrderedDict(sorted(countries.items())) for country in countries: country_servers[country] = sorted(countries[country], key=lambda s: get_server_value(s, "Load", servers)) populate_servers_dict["tree_object"].clear() CURRDIR = os.path.dirname(os.path.abspath(__file__)) flags_base_path = CURRDIR+"/resources/img/flags/small/" features_base_path = CURRDIR+"/resources/img/utils/" # Create empty image empty_path = features_base_path+"normal.png" empty_pix = empty = GdkPixbuf.Pixbuf.new_from_file_at_size(empty_path, 15,15) # Create P2P image p2p_path = features_base_path+"p2p-arrows.png" p2p_pix = empty = GdkPixbuf.Pixbuf.new_from_file_at_size(p2p_path, 15,15) # Create TOR image tor_path = features_base_path+"tor-onion.png" tor_pix = empty = GdkPixbuf.Pixbuf.new_from_file_at_size(tor_path, 15,15) # Create Plus image plus_server_path = features_base_path+"plus-server.png" plus_pix = GdkPixbuf.Pixbuf.new_from_file_at_size(plus_server_path, 15,15) for country in country_servers: for k,v in country_codes.items(): if country == v: flag_path = flags_base_path+"{}.png".format(v) break else: flag_path = flags_base_path+"Unknown.png" # Get average load and highest feature avrg_load, country_feature = get_country_avrg_features(country, country_servers, servers, features) flag = GdkPixbuf.Pixbuf.new_from_file_at_size(flag_path, 15,15) # Check plus servers if country_feature == "normal" or country_feature == "p2p": plus_feature = empty_pix else: plus_feature = plus_pix # Check correct feature if country_feature == "normal" or country_feature == "secure-core": feature = empty_pix elif country_feature == "p2p": feature = p2p_pix elif country_feature == "tor": feature = tor_pix if country_feature == "secure-core" and only_secure_core: country_row = populate_servers_dict["tree_object"].append(None, [flag, country, plus_feature, feature, avrg_load]) elif not only_secure_core: country_row = populate_servers_dict["tree_object"].append(None, [flag, country, plus_feature, feature, avrg_load]) for servername in country_servers[country]: secure_core = False load = str(get_server_value(servername, "Load", servers)).rjust(3, " ") load = load + "%" tier = server_tiers[get_server_value(servername, "Tier", servers)] if not "Plus/Visionary".lower() == tier.lower(): plus_feature = empty_pix else: plus_feature = plus_pix server_feature = features[get_server_value(servername, 'Features', servers)].lower() if server_feature == "Normal".lower(): feature = empty_pix elif server_feature == "P2P".lower(): feature = p2p_pix elif server_feature == "Tor".lower(): feature = tor_pix else: # Should be secure core secure_core = True if secure_core and only_secure_core: populate_servers_dict["tree_object"].append(country_row, [empty_pix, servername, plus_feature, feature, load]) elif not secure_core and not only_secure_core: populate_servers_dict["tree_object"].append(country_row, [empty_pix, servername, plus_feature, feature, load])
def update_available_servers(self): utils.pull_server_data() return utils.get_servers()