def req_for_ovpn_file(server_id, user_protocol): """ Makes a request to ProtonVPN servers and returns with a OVPN template "file", returns False otherwise. """ url = f"https://api.protonmail.ch/vpn/config?Platform={OS_PLATFORM}&LogicalID={server_id}&Protocol={user_protocol}" try: log.info("Fetched request from ProtonVPN.") return requests.get(url, headers=(PROTON_HEADERS)) except: log.critical("Unable to fetch request from ProtonVPN.") return False
def copy_credentials(): cmds = [ f"mkdir /opt/{PROJECT_NAME}/", f"cp {USER_CRED_FILE} /opt/{PROJECT_NAME}/" ] try: if (not os.path.isdir("/opt/" + PROJECT_NAME + "/")): for cmd in cmds: subprocess.run(["sudo", "bash", "-c", cmd]) else: subprocess.run(["sudo", "bash", "-c", cmds[1]]) print("Copied credentials") log.info(f"Credentials were copied to: \"/opt/{PROJECT_NAME}\"") return True except: print("Unable to copy credentials") log.critical(f"Unable to copy credentials to: \"/opt/{PROJECT_NAME}\"") 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 openvpn_disconnect(self): openvpn_PID = self.check_for_running_ovpn_process() is_connected = False print("Disconnecting from vpn server...") log.info(f"PID is: {'NONE' if not openvpn_PID else openvpn_PID}") if not openvpn_PID: print("Unable to disconnect, no OpenVPN process was found.") log.warning("Could not find any OpenVPN processes.") return False try: is_connected = get_ip_info() except: is_connected = False log.info(f"Tested for internet connection: \"{is_connected}\"") if not manage_dns(action_type="restore"): log.critical("Unable to restore DNS prior to disconnecting from VPN, restarting NetworkManager might be needed.") if not manage_ipv6(action_type="restore"): log.warning("Unable to enable IPV6 prior to disconnecting from VPN.") # if not manage_killswitch(action_type="restore"): # 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("Unable to disconnecto from VPN.") log.critical(f"Unable to disconnecto from VPN, \"{output}\"") return False log.info("Disconnected from VPN.") print("You are disconnected from VPN.") 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