From f1e5e81a7ba303c8e9386374da1d5e244cdb9780 Mon Sep 17 00:00:00 2001 From: b3nw Date: Wed, 4 Sep 2024 14:45:59 -0500 Subject: [PATCH] convert nord.sh to nord-checker.py --- .gitignore | 4 ++ nord-checker.py | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ update-nord.py | 16 ++++-- 3 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 nord-checker.py diff --git a/.gitignore b/.gitignore index 5d381cc..d39a14f 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,7 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +# env/configs +*.creds +ovpn_* +vpnlist.txt \ No newline at end of file diff --git a/nord-checker.py b/nord-checker.py new file mode 100644 index 0000000..94140bf --- /dev/null +++ b/nord-checker.py @@ -0,0 +1,140 @@ +import os +import subprocess +import random +import time +import datetime +import re +import sys + +# Variables +CREDENTIAL_FILE = "nord.creds" +OVPN_DIR = "/root/nordvpn/ovpn_configs/ovpn_tcp" +LOG_FILE = "/root/nordvpn/openvpn.log" +RESULT_FILE = "vpnlist.txt" +OVPN_ZIP_URL = "https://downloads.nordcdn.com/configs/archives/servers/ovpn.zip" + +# Check for debug flag +DEBUG_MODE = False +if len(sys.argv) > 1 and sys.argv[1] == "-d": + DEBUG_MODE = True + +def debug_print(message): + if DEBUG_MODE: + print(message) + +# Get current IP before starting +CURRENT_IP = subprocess.check_output(["curl", "-s", "ifconfig.me"]).decode().strip() +print(f"{datetime.datetime.now()} [Main Script]: Current IP before VPN connections: {CURRENT_IP}") + +# Terminate any existing OpenVPN connections +try: + result = subprocess.run(["pgrep", "openvpn"], check=True, capture_output=True) + pids = result.stdout.decode().strip().split('\n') + for pid in pids: + subprocess.run(["kill", pid]) + print(f"{datetime.datetime.now()} [Main Script]: Existing OpenVPN connections terminated.") +except subprocess.CalledProcessError: + pass # No openvpn process found + +# Download and extract OVPN configurations +debug_print(f"{datetime.datetime.now()} [Main Script]: Downloading and extracting OVPN configurations...") +if not os.path.exists(OVPN_DIR): + os.makedirs(OVPN_DIR) + +subprocess.run(["curl", "-s", "-L", "-o", f"{OVPN_DIR}/ovpn.zip", OVPN_ZIP_URL]) +subprocess.run(["unzip", "-q", "-o", f"{OVPN_DIR}/ovpn.zip", "-d", OVPN_DIR]) +os.remove(f"{OVPN_DIR}/ovpn.zip") + +# Find all OVPN files +ovpn_files = [f for f in os.listdir(OVPN_DIR) if f.endswith(".ovpn")] + +total_files = len(ovpn_files) + +debug_print(f"{datetime.datetime.now()} [Main Script]: Found {total_files} OVPN files to process.") +debug_print(ovpn_files) # Print the list of OVPN files + +# Process each OVPN file +FILE_NUM = 1 +for OVPN_FILE in ovpn_files: + OVPN_FILENAME = os.path.basename(OVPN_FILE) + + debug_print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Processing OVPN file...") + + # Read credentials + with open(CREDENTIAL_FILE, 'r') as f: + username = f.readline().strip() + password = f.readline().strip() + + debug_print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Read credentials from {CREDENTIAL_FILE}") + + # Establish VPN connection (capture stdout and stderr) + openvpn_command = ["openvpn", "--config", f"{OVPN_DIR}/{OVPN_FILE}", + "--auth-user-pass", CREDENTIAL_FILE, "--daemon", + "--log-append", LOG_FILE, "--verb", "3"] + + 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: + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Error starting OpenVPN connection:") + print(stderr.decode()) + else: + debug_print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: OpenVPN output:") + debug_print(stdout.decode()) + + # Wait for connection to establish + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Waiting for VPN connection to establish...") + time.sleep(10) + + # Check if the VPN connection is active + try: + subprocess.run(["pgrep", "-f", OVPN_FILENAME], check=True, capture_output=True) + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection established.") + + # Check external IP (with validation and retries) + external_ip = subprocess.check_output(["curl", "-s", "ifconfig.me"]).decode().strip() + + if not re.match(r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", external_ip): + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Invalid response from ifconfig.me, retrying with ifconfig.co") + external_ip = subprocess.check_output(["curl", "-s", "ifconfig.co"]).decode().strip() + + if not re.match(r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", external_ip): + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Invalid response from ifconfig.co, retrying with ipinfo.io/ip") + external_ip = subprocess.check_output(["curl", "-s", "ipinfo.io/ip"]).decode().strip() + + if not re.match(r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", external_ip): + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Unable to get external IP. Skipping this OVPN file.") + continue + + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: External IP via VPN: {external_ip}") + + # Append result to file + with open(RESULT_FILE, 'a') as f: + f.write(f"{external_ip} # {OVPN_FILENAME}\n") + + except subprocess.CalledProcessError: + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection failed to establish.") + + # Disconnect VPN (replace killall with pgrep and kill) + try: + result = subprocess.run(["pgrep", "openvpn"], check=True, capture_output=True) + pids = result.stdout.decode().strip().split('\n') # Get PIDs as a list + for pid in pids: + subprocess.run(["kill", pid]) + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN disconnected.") + except subprocess.CalledProcessError: + print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: No openvpn process found.") + + # Wait for a random time between 8 and 30 seconds + sleep_time = random.randint(1, 8) + 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...") + + # Increment file number + FILE_NUM += 1 \ No newline at end of file diff --git a/update-nord.py b/update-nord.py index a7c4184..f85a4c9 100644 --- a/update-nord.py +++ b/update-nord.py @@ -33,13 +33,21 @@ try: # Read the file line by line with open('vpnlist.txt', 'r') as f: - for line in f: + for line_number, line in enumerate(f, start=1): if line.startswith('#'): continue - parts = line.strip().split(' # ') - exit_ip = parts[0] - file_name = parts[1].strip() + if ' # ' not in line: + print(f"Skipping invalid line {line_number}: {line}") + continue + + try: + parts = line.strip().split(' # ') + exit_ip = parts[0] + file_name = parts[1].strip() + except IndexError: + print(f"Error parsing line {line_number}: {line}") + continue total_processed += 1