diff --git a/nord-checker.py b/nord-checker.py index 78f6d4d..fc17160 100644 --- a/nord-checker.py +++ b/nord-checker.py @@ -24,7 +24,8 @@ def debug_print(message): if DEBUG_MODE: print(f"{datetime.datetime.now()} + [Debug Mode]:{message}") else: - log_file.flush() + # log_file.write(f"{datetime.datetime.now()} + [Debug Mode]:{message}\n") + log_file.flush() # Flush the buffer to ensure the message is written # Open the log file in append mode if not in debug mode log_file = None # Define log_file in the global scope @@ -34,7 +35,6 @@ if not DEBUG_MODE: sys.stdout = log_file sys.stderr = log_file - # Get current IP before starting (using get_external_ip) CURRENT_IP = get_external_ip() if CURRENT_IP is None: @@ -67,9 +67,8 @@ debug_print(f"{datetime.datetime.now()} [Main Script]: Downloading and extractin ovpn_files_to_check = download_and_extract_ovpn_configs(cursor, conn, debug_print=debug_print) total_files = len(ovpn_files_to_check) - debug_print(f"{datetime.datetime.now()} [Main Script]: Found {total_files} OVPN files to check.") -#debug_print(ovpn_files_to_check) # Print the list of OVPN files +print(f"{datetime.datetime.now()} [Main Script]: Found {total_files} OVPN files to check.") # Process each OVPN file FILE_NUM = 1 @@ -85,77 +84,17 @@ for OVPN_FILE in ovpn_files_to_check: print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Skipping, file not found and removed from database.") FILE_NUM += 1 continue - - # Read credentials - with open(CREDENTIAL_FILE, 'r') as f: - username = f.readline().strip() - password = f.readline().strip() - # Establish VPN connection (capture stdout and stderr) - max_retries = 3 - retry_count = 0 - while retry_count < max_retries: - openvpn_command = ["openvpn", "--config", f"{OVPN_DIR}/{OVPN_FILE}", - "--auth-user-pass", CREDENTIAL_FILE, "--daemon", - "--log-append", LOG_FILE, "--verb", "3"] + # Establish VPN connection + connection_successful, connection_message = establish_vpn_connection(f"{OVPN_DIR}/{OVPN_FILE}", CREDENTIAL_FILE, LOG_FILE, debug_print=debug_print) - debug_print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Executing OpenVPN command: {' '.join(openvpn_command)}") - process = subprocess.Popen(openvpn_command, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = process.communicate(input=password.encode()) - - # Check for errors and print output - if process.returncode != 0 or "Error opening configuration file" in stderr.decode() or "AUTH_FAILED" in stderr.decode(): - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Error starting OpenVPN connection or authentication failed:") - print(stderr.decode()) - - # Explicitly disconnect VPN if there was an error or auth failure - disconnect_vpn() - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN disconnected (due to error or auth failure).") - - if retry_count < max_retries - 1 and "Error opening configuration file" not in stderr.decode(): - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Retrying connection in 10 seconds...") - time.sleep(10) - retry_count += 1 - else: - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Max retries reached or config file error. Skipping this OVPN file.") - break - else: - break - - # Wait for connection to establish (with backoff for auth failure) - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Waiting for VPN connection to establish...") - max_attempts = 10 - attempt = 0 - backoff_time = 0 - with open(LOG_FILE, 'r') as f: - while attempt < max_attempts: - line = f.readline() - if not line: - time.sleep(1) - attempt += 1 - continue - - if "Initialization Sequence Completed" in line: - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection established.") - break - elif "AUTH: Received control message: AUTH_FAILED" in line: - backoff_time += 1 - if backoff_time >= 30: - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Authentication failed. Skipping this OVPN file.") - break - - if attempt == max_attempts or backoff_time >= 30: - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection failed to establish (timeout or auth failure).") - - # Disconnect VPN - disconnect_vpn() - print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN disconnected.") + if connection_successful: + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: {connection_message}") + if not connection_successful: + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Error starting OpenVPN connection:{connection_message}") # Wait for a random time between 1 and 4 seconds - sleep_time = random.randint(1, 4) + sleep_time = random.randint(8, 15) print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Waiting for {sleep_time} seconds before the next connection...") time.sleep(sleep_time) print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Resuming...") diff --git a/openvpn_manager.py b/openvpn_manager.py index a238288..35b9ac1 100644 --- a/openvpn_manager.py +++ b/openvpn_manager.py @@ -2,8 +2,9 @@ import subprocess import time import datetime import re +import sys -def establish_vpn_connection(ovpn_file, credential_file, log_file): +def establish_vpn_connection(ovpn_file, credential_file, log_file, debug_print=None, timeout=15): # Changed timeout to 15 """ Establishes a VPN connection using the provided OVPN file and credentials. Returns True if the connection is successful, False otherwise. @@ -15,22 +16,56 @@ def establish_vpn_connection(ovpn_file, credential_file, log_file): password = f.readline().strip() # Establish VPN connection (capture stdout and stderr) - openvpn_command = ["openvpn", "--config", ovpn_file, - "--auth-user-pass", credential_file, "--daemon", - "--log-append", log_file, "--verb", "0", "--flush-log"] # Added --flush-log + openvpn_command = ["openvpn", "--config", ovpn_file, + "--auth-user-pass", credential_file, + "--verb", "1"] - process = subprocess.Popen(openvpn_command, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, + if debug_print: + debug_print(f"OpenVPN command: {' '.join(openvpn_command)}") # Debug print + sys.stdout.flush() # Flush the output buffer + + process = subprocess.Popen(openvpn_command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = process.communicate(input=password.encode()) + + # Send the password to the process + process.stdin.write((password + '\n').encode()) + process.stdin.flush() - # Check for errors - if process.returncode != 0: - return False, stderr.decode() - else: - return True, stdout.decode() + start_time = time.time() + + while True: + # Check if the process has exited + if process.poll() is not None: + debug_print(f"OpenVPN exited with a non-zero return code: {process.returncode}") + return False, process.stderr.read().decode() + # Read a line from stdout (non-blocking) + line = process.stdout.readline().decode() + if line: + if debug_print: + debug_print(f"OpenVPN output: {line.strip()}") + if "Initialization Sequence Completed" in line: + debug_print("VPN Initialization Sequence Completed found in stdout.") + #print(f"{datetime.datetime.now()} [OpenVPN Manger]: VPN Initialization Sequence Completed found in stdout.") + return True, line + # Check for AUTH_FAILED message + if "AUTH: Received control message: AUTH_FAILED" in line: + debug_print("Authentication failed. Sleeping for 15 seconds.") + #print(f"{datetime.datetime.now()} [OpenVPN Manger]: AUTH: Received control message: AUTH_FAILED, sleeping for 15 seconds") + time.sleep(15) + return False, "AUTH: Received control message: AUTH_FAILED" + break + + # Check for timeout + if time.time() - start_time > timeout: + debug_print(f"VPN connection timed out after {timeout} seconds.") + # print(f"{datetime.datetime.now()} [OpenVPN Manger]: VPN connection timed out after {timeout} seconds.") + process.kill() + return False, "VPN connection timed out." + + time.sleep(0.1) # Small delay to avoid busy-waiting def is_vpn_active(ovpn_filename): """ Checks if the VPN connection associated with the given OVPN filename is active. @@ -69,5 +104,5 @@ def get_external_ip(): print(f"{datetime.datetime.now()} [Main Script]: Invalid response from {service}") except subprocess.CalledProcessError: print(f"{datetime.datetime.now()} [Main Script]: Error getting external IP from {service}") - - return None # Unable to get external IP \ No newline at end of file + + return None # Unable to get external IP