def restart_network_manager(self):
		try:
			output = subprocess.run(["systemctl", "restart", "NetworkManager"], stdout=subprocess.PIPE)
			print("\nRestarted network manager\n")
			log.info(f"Sucessfully restarted Network Manager: \"{output.stdout.decode()}\"")
		except:
			log.warning(f"Unable to restart Network Manager.")
			print("Cant restart network manager")
	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}\"")
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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 is_vpn_running(self):
		openvpn_PID = self.check_for_running_ovpn_process()

		cmd = "cat /etc/resolv.conf"
		res = subprocess.run(["sudo", "bash", "-c", cmd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

		# log.info(f"PID is: {'NONE' if not openvpn_PID else openvpn_PID}")

		if openvpn_PID and (res.returncode == 0 and ("10.8.8.1" in res.stdout.decode() or "10.7.7.1" in res.stdout.decode())):
			print("VPN is running with custom DNS.")
			log.info(f"VPN is running\nOVPN PID:{openvpn_PID}\nDNF conf:\n{res.stdout.decode()}")
			return True
		elif openvpn_PID and not (res.returncode == 0 and ("10.8.8.1" in res.stdout.decode() or "10.7.7.1" in res.stdout.decode())):
			print("VPN is running, but there might be DNS leaks. Try modifying your DNS configurations.")
			log.warning(f"Resolv conf has original values, custom ProtonVPN DNS configuration not found: {res.stdout.decode()}")
			return True
		else:
			print("VPN is not running.")
			log.info("Could not find any OpenVPN processes.")
			return False
Ejemplo n.º 7
0
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
Ejemplo n.º 9
0
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