def fastest_country(self): if self.check_for_running_ovpn_process(): print("VPN already running.") return False server_feature_filter = [1, 2] server_collection = [] self.server_manager.cache_servers() country = input("Which country to connect to: ").strip().upper() file = country+SERVER_FILE_TYPE #load country configurations try: with open(os.path.join(CACHE_FOLDER, file)) as file: server_list = json.load(file) except TypeError: print("Servers are not cached.") log.warning("Servers are not cached.") return False #load user preferences try: user_pref = self.user_manager.read_user_data() except: print("Profile was not initialized.") log.warning("User profile was not initialized.") return False #filter by features and tier for server in server_list['serverList']: if server_list['serverList'][server]['features'] not in server_feature_filter and server_list['serverList'][server]['tier'] <= user_pref['tier']: server_collection.append(server_list['serverList'][server]) if not len(server_collection): print("Nothing") return False server_id, server_score, server_name, server_load = get_fastest_server(server_collection) user_pref['last_conn_server_id'] = server_id user_pref['last_conn_sever_name'] = server_name user_pref['last_conn_sever_protocol'] = user_pref['protocol'] server_req = req_for_ovpn_file(server_id, user_pref['protocol']) if not server_req: return False if not generate_ovpn_file(server_req): return False if not self.openvpn_connect(protocol=user_pref['protocol']): return False if not edit_file(USER_PREF_FILE, json.dumps(user_pref, indent=2), append=False): log.debug("Did not manage to save last connection preferences.") log.info(f"Updated user last connection data: \"{user_pref}\"")
def get_fastest_server(server_list): """ Returns the fastest server from the list. """ fastest_server = sorted(server_list, key=lambda server: server["score"]) log.debug(f"Connection information {fastest_server}") return (fastest_server[0]['id'], fastest_server[0]['score'], fastest_server[0]['name'], fastest_server[0]['load'])
def manage_dns(action_type, dns_addr=False): resolv_conf_path = walk_to_file("/etc/", "resolv.conf", is_return_bool=False) if not resolv_conf_path: print("The \"resolv.conf\" file was not found on your system.") log.warning("\"resolv.conf\" file was not found.") return False log.info(f"Path to original resolv.conf: \"{resolv_conf_path}\"") print("Modifying dns...") if action_type == "custom": log.info("Applying custom ProtonVPN DNS...") cmd = f"cat > /etc/resolv.conf <<EOF \n# Generated by openvpn-linux-gui for ProtonVPN\nnameserver {dns_addr}\nEOF" try: shutil.copy(resolv_conf_path, RESOLV_BACKUP_FILE) except: print("Unable to backup DNS configurations.") log.warning("Unable to backup DNS configurations.") return False output = subprocess.run(["sudo", "bash", "-c", cmd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not output.returncode == 0: print("Unable to update DNS configurations") log.warning("Unable to apply custom ProtonVPN DNS configurations.") print("DNS updated with new configurations.") log.debug(f"...custom ProtonVPN DNS applied: {output}") return True elif action_type == "restore": log.info("Restoring original DNS...") try: with open(RESOLV_BACKUP_FILE) as f: content = f.read() cmd = f"cat > /etc/resolv.conf <<EOF \n{content}\nEOF" subprocess.run(["sudo", "bash", "-c", cmd]) print("...DNS configurations were restored.") delete_file(RESOLV_BACKUP_FILE) log.info( f"Original configurations restored from: \"{RESOLV_BACKUP_FILE}\"" ) return True except: print( "Unable to restore original DNS configurations, try restarting the Network Manager." ) log.warning("Unable to restore original DNS configurations.") return False
def generate_ovpn_for_boot(server_req): original_req = server_req.text start_index = original_req.find("auth-user-pass") modified_request = original_req[:start_index + 14] + " /opt/" + PROJECT_NAME + "/" + USER_CRED_FILE.split( "/")[-1] + original_req[start_index + 14:] ovpn_file_created = False append_to_file = "cat > /etc/openvpn/client/" + OVPN_FILE.split( "/")[-1].split(".")[0] + ".conf <<EOF " + modified_request + "\nEOF" try: output = subprocess.run(["sudo", "bash", "-c", append_to_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) log.debug(f"Injection comand output: {output}") ovpn_file_created = True except: print("Unable to create configuration file in /openvpn/client/") log.critical(f"Could not generate/modify openVPN file.") return False print("Created new file in /openvpn/client/") log.info(f"\"Start on boot\" path to credentials injected.") if ovpn_file_created and walk_to_file( "/opt/", USER_CRED_FILE, in_dirs=True): log.critical( f"OVPN file for boot was NOT generated in: \"/etc/openvpn/client/\"" ) return False if not copy_credentials(): return False filename = OVPN_FILE.split("/")[-1].split(".")[0] log.info( f"OVPN file for boot was generated: \"/etc/openvpn/client/{filename}\"" ) return True
def manage_killswitch(action_type, protocol=None, port=None): # code to work with ufw # sudo ufw allow in to LAN_ADDR # sudo ufw allow out to LAN_ADDR # sudo ufw default deny outgoing # sudo ufw default deny incoming # sudo ufw allow out to VPN_PUBLIC_ADDR port VPN_PORT proto PROTOCOL # sudo ufw allow out on tun0 from any to any # tun0 should be fatched from opvn.log as TUN/TAP (someting) opened # sudo ufw allow in on tun0 from any to any # same as above, though to allow inbound traffic # sudo ufw enable # start on boot # sudo ufw disable # disable killswitch if action_type == "restore": if not os.path.isfile(IPTABLES_BACKUP_FILE): log.debug("No Backupfile found") return False log.debug("Restoring IPTables rules") subprocess.run(f"sudo iptables-restore < {IPTABLES_BACKUP_FILE}", shell=True, stdout=subprocess.PIPE) log.debug("iptables restored") delete_file(IPTABLES_BACKUP_FILE) log.debug("iptables.backup removed") return True elif action_type == "enable": if not os.path.isfile(IPTABLES_BACKUP_FILE): print("No backup file") # return False with open(OVPN_LOG_FILE, "r") as f: content = f.read() device = re.search(r"(TUN\/TAP device) (.+) opened", content) if not device: print("[!] Kill Switch activation failed." "Device couldn't be determined.") log.debug("Kill Switch activation failed. No device in logfile") return False device = device.group(2) log.debug("Backing up iptables rules") return_code, iptables_rules = cmd_command(["sudo", "iptables-save"], as_sudo=True) if "COMMIT" in iptables_rules: with open(IPTABLES_BACKUP_FILE, "w") as f: f.write(iptables_rules) else: with open(IPTABLES_BACKUP_FILE, "w") as f: f.write("*filter\n") f.write(":INPUT ACCEPT\n") f.write(":FORWARD ACCEPT\n") f.write(":OUTPUT ACCEPT\n") f.write("COMMIT\n") iptables_commands = [ "iptables -F", "iptables -P INPUT DROP", "iptables -P OUTPUT DROP", "iptables -P FORWARD DROP", "iptables -A OUTPUT -o lo -j ACCEPT", "iptables -A INPUT -i lo -j ACCEPT", f"iptables -A OUTPUT -o {device} -j ACCEPT", f"iptables -A INPUT -i {device} -j ACCEPT", f"iptables -A OUTPUT -o {device} -m state --state ESTABLISHED,RELATED -j ACCEPT", # noqa f"iptables -A INPUT -i {device} -m state --state ESTABLISHED,RELATED -j ACCEPT", # noqa f"iptables -A OUTPUT -p {protocol} -m {protocol} --dport {port} -j ACCEPT", # noqa f"iptables -A INPUT -p {protocol} -m {protocol} --sport {port} -j ACCEPT", # noqa ] log.debug(f"{device}, {protocol}, {port}") # return_code, change_iptables = cmd_command(iptables_commands) # if not return_code == 0: # log.debug("Unable to change iptables.") # log.debug(f"Command output:{return_code} || {change_iptables}") # return False, iptables_commands = [ "sudo " + command for command in iptables_commands ] # print(iptables_commands) for command in iptables_commands: command = command.split() subprocess.run(command) log.debug("Kill switch enabled") return True
def manage_ipv6(action_type): if action_type == "disable": #check for error default_route = subprocess.run("ip route show | grep default", shell=True, stdout=subprocess.PIPE) if not default_route.returncode == 0: print("Could not find any IPv6 configurations.") log.debug( "Could not find any IPv6 configurations prior to disabling it." ) return False # show all ipv6 interfaces and their status #all_interfaces = subprocess.run(["sudo sysctl --all | grep disable_ipv6"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) default_nic = default_route.stdout.decode().strip().split()[4] ipv6_info = subprocess.run( f"ip addr show dev {default_nic} | grep '\<inet6.*global\>'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not ipv6_info.returncode == 0: log.debug(f"Could not find ipv6 {ipv6_info}") return False ipv6_addr = ipv6_info.stdout.decode().strip().split()[1] if walk_to_file(USER_FOLDER, IPV6_BACKUP_FILE.split("/")[-1]): delete_file(IPV6_BACKUP_FILE) log.info(f"Backup file was deleted: \"{IPV6_BACKUP_FILE}\"") ipv6_disable = subprocess.run( f"sudo sysctl -w net.ipv6.conf.{default_nic}.disable_ipv6=1", shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) if not ipv6_disable.returncode == 0: log.debug(f"Unable to disable ipv6: {ipv6_disable}") return False try: with open(IPV6_BACKUP_FILE, "w") as file: file.write(default_nic + " " + ipv6_addr) except: print("Unable to save to file") return False print("Backup was made") return True elif action_type == "restore": log.info("Start IPV6 restore process.") try: with open(IPV6_BACKUP_FILE, "r") as file: content = file.read().split() default_nic = content[0].strip() ipv6_addr = content[1].strip() except: log.debug("Unable to open file.") return False ipv6_info = subprocess.run( f"ip addr show dev {default_nic} | grep '\<inet6.*global\>'", shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) if ipv6_info.returncode == 0: log.debug("IPv6 already present.") delete_file(IPV6_BACKUP_FILE) return True ipv6_enable = subprocess.run( f"sudo sysctl -w net.ipv6.conf.{default_nic}.disable_ipv6=0", shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) if not ipv6_enable.returncode == 0: print( "Unable to restore IPv6 configurations, restarting Network Manager might help." ) log.debug(f"IPv6 configuration restoration error: {ipv6_enable}") return False ipv6_restore_address = subprocess.run( f"sudo ip addr add {ipv6_addr} dev {default_nic}", shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) if not ipv6_restore_address.returncode == 0: print("Unable to restore IPv6.") log.debug(f"IPv6 restoration error: {ipv6_restore_address}") return False log.debug("Removing IPv6 backup file.") delete_file(IPV6_BACKUP_FILE) log.debug("IPv6 restored") print("IPv6 restored") return True
def start_on_boot_manager(self, action): enabled_on_boot = True #load user preferences try: user_pref = self.user_manager.read_user_data() except: print("Profile was not initialized.") log.warning("User profile was not initialized.") return False if action == "enable": success_msg = "\"Launch on boot\" service enabled." fail_msg = "Cant enable \"launch on boot\" service." self.server_manager.cache_servers() server_collection = [] user_inp_country = input("Which country do you want to start on boot ? ").strip().upper() server_list_file = user_inp_country+SERVER_FILE_TYPE #load country configurations try: with open(os.path.join(CACHE_FOLDER, server_list_file)) as file: server_list = json.load(file) except TypeError: print("Servers are not cached.") log.warning("Servers are not cached.") return False print("Server name|\tServer Load|\tFeatures|\tTier") for server in server_list['serverList']: if server_list['serverList'][server]['tier'] <= user_pref['tier']: server_collection.append(server_list['serverList'][server]) print( server_list['serverList'][server]['name']+"|\t\t\t"+str(server_list['serverList'][server]['load'])+"|\t"+ str(server_list['serverList'][server]['features'])+"|\t\t"+str(server_list['serverList'][server]['tier']) ) if len(server_collection) == 0: print("No servers were found") return False user_selected_server = int(input("Which server to connecto on boot: ")) selected_server = [server for server in server_collection if str(user_selected_server) in server['name']][0] user_pref['on_boot_server_id'] = selected_server['id'] user_pref['on_boot_server_name'] = selected_server['name'] user_pref['on_boot_protocol'] = user_pref['protocol'] server_req = req_for_ovpn_file(selected_server['id'], user_pref['protocol']) if not server_req: return False if not generate_ovpn_for_boot(server_req): return False elif action == "kill": openvpn_PID = self.check_for_running_ovpn_process() if not openvpn_PID: print("Not PID was found") log.debug("Attempted to kill \"openvpn start on boot\" process, none found.") return False output = subprocess.run(["sudo","kill", "-9", openvpn_PID], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # SIGTERM - Terminate opevVPN, ref: https://www.poftut.com/what-is-linux-sigterm-signal-and-difference-with-sigkill/ if output.returncode != 0: print(f"Unable to kill PID {openvpn_PID}.") log.critical(f"Unable to disconnecto from VPN, \"{output}\"") return False self.restart_network_manager() return True elif action == "disable": success_msg = "\"Launch on boot\" service is disabled." fail_msg = "Cant disable service \"launch on boot\"." enabled_on_boot = False #here it should kill all openvpn processes and disable service daemon elif action == "restart": success_msg = "\"Launch on boot\" service was restarted." fail_msg = "Cant restart service \"launch on boot\"." try: output = subprocess.run(["sudo", "systemctl", action, ON_BOOT_PROCESS_NAME], stdout=subprocess.PIPE, stderr=subprocess.PIPE) log.debug(f"Start on boot log: {output}") except: print("\n"+fail_msg+"\n") log.critical("Something went wrong, could not enable \"start on boot\"") return False if not delete_folder_recursive(CACHE_FOLDER): log.debug("Unable to delete cache folder recursively.") print("\n"+success_msg+"\n") user_pref['on_boot_enabled'] = enabled_on_boot if not edit_file(USER_PREF_FILE, json.dumps(user_pref, indent=2), append=False): log.debug("Unable to save on boot preferences.") log.info(f"Start on boot created: \"{output.stdout.decode()}\"")
def openvpn_connect(self, protocol=False): openvpn_PID = self.check_for_running_ovpn_process() pre_vpn_conn_ip = False port_types = {"udp": 1194, "tcp": 443} if openvpn_PID: print("Unable to connect, a OpenVPN process is already running.") log.info("Unable to connect, a OpenVPN process is already running.") return False try: pre_vpn_conn_ip, pre_vpn_conn_isp = get_ip_info() except: pre_vpn_conn_ip = False pre_vpn_conn_isp = False log.info(f"Tested for internet connection: \"{pre_vpn_conn_ip}\"") if not pre_vpn_conn_ip: print("There is no internet connection.") log.warning("Unable to connect, check your internet connection.") print("Connecting to vpn server...") if not protocol: protocol = "udp" # Needs to be worked on, new way to connect to VPN, might help with killswitch with open(OVPN_LOG_FILE, "w+") as log_file: subprocess.Popen( [ "sudo", "openvpn", "--config", OVPN_FILE, "--auth-user-pass", USER_CRED_FILE ], stdout=log_file, stderr=log_file ) with open(OVPN_LOG_FILE, "r") as log_file: while True: content = log_file.read() log_file.seek(0) if "Initialization Sequence Completed" in content: print("VPN established") #change DNS dns_dhcp_regex = re.compile( r"(dhcp-option DNS )" r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" ) dns_dhcp = dns_dhcp_regex.search(content) log.debug(f"DNS___RESULT: {dns_dhcp}") if dns_dhcp: dns_server = dns_dhcp.group(2) manage_dns(action_type="custom", dns_addr=dns_server) else: print("Could not apply custom DNS.") log.critical(f"Could not apply custom DNS: {dns_dhcp}") if not manage_ipv6(action_type="disable"): return False # if not manage_killswitch(action_type="enable", protocol=protocol, port=port_types[protocol]): # return False # compare old IP with new IP, if they are different the connection has succeded log.debug("Connected to the VPN.") return True elif "AUTH_FAILED" in content: print("Authentication failed") break