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 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 setup_user(self, user_data): ovpn_username = user_data['username'] ovpn_password = user_data['password'] user_tier = user_data['protonvpn_plan'] user_protocol = user_data['openvpn_protocol'] if not self.generate_user_pass_file(ovpn_username, ovpn_password): shutil.rmtree(CONFIG_DIR) return False gui_logger.debug("Passfile created") pull_server_data(force=True) if user_tier == 4: user_tier = 3 user_tier -= 1 set_config_value("USER", "username", ovpn_username) set_config_value("USER", "tier", user_tier) set_config_value("USER", "default_protocol", user_protocol) set_config_value("USER", "dns_leak_protection", 1) set_config_value("USER", "custom_dns", None) set_config_value("USER", "killswitch", 0) set_config_value("USER", "split_tunnel", 0) set_config_value("USER", "initialized", 1) return True
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 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 on_login(interface, username_field, password_field, messagedialog_label, user_window, login_window, messagedialog_window): """Function that initializes a user profile. """ server_list_object = interface.get_object("ServerListStore") populate_servers_dict = { "list_object": server_list_object, "servers": False } user_data = prepare_initilizer(username_field, password_field, interface) config = configparser.ConfigParser() config["USER"] = { "username": "******", "tier": "None", "default_protocol": "None", "initialized": "0", "dns_leak_protection": "1", "custom_dns": "None", "check_update_interval": "3", "killswitch": "0", "split_tunnel": "0", "autoconnect": "0" } config["metadata"] = { "last_api_pull": "0", "last_update_check": str(int(time.time())), } with open(CONFIG_FILE, "w") as f: config.write(f) change_file_owner(CONFIG_FILE) gui_logger.debug("pvpn-cli.cfg initialized") change_file_owner(CONFIG_DIR) ovpn_username = user_data['username'] ovpn_password = user_data['password'] user_tier = user_data['protonvpn_plan'] user_protocol = user_data['openvpn_protocol'] pull_server_data(force=True) make_ovpn_template() if user_tier == 4: user_tier = 3 user_tier -= 1 set_config_value("USER", "username", ovpn_username) set_config_value("USER", "tier", user_tier) set_config_value("USER", "default_protocol", user_protocol) set_config_value("USER", "dns_leak_protection", 1) set_config_value("USER", "custom_dns", None) set_config_value("USER", "killswitch", 0) set_config_value("USER", "split_tunnel", 0) set_config_value("USER", "autoconnect", "0") with open(PASSFILE, "w") as f: f.write("{0}\n{1}".format(ovpn_username, ovpn_password)) gui_logger.debug("Passfile created") os.chmod(PASSFILE, 0o600) gui_config = configparser.ConfigParser() gui_config["connections"] = {"display_secure_core": False} gui_config["general_tab"] = { "start_min": False, "start_on_boot": False, "show_notifications": False, } gui_config["tray_tab"] = { TRAY_CFG_DATA_TX: "0", TRAY_CFG_SERVENAME: "0", TRAY_CFG_TIME_CONN: "0", TRAY_CFG_SERVERLOAD: "0", } gui_config["conn_tab"] = { "autoconnect": "dis", "quick_connect": "dis", } with open(GUI_CONFIG_FILE, "w") as f: gui_config.write(f) change_file_owner(GUI_CONFIG_FILE) gui_logger.debug("pvpn-gui.cfg initialized") set_config_value("USER", "initialized", 1) load_on_start({ "interface": interface, "gui_enabled": True, "messagedialog_label": messagedialog_label })
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()