convert nord.sh to nord-checker.py
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -160,3 +160,7 @@ cython_debug/
|
|||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
# env/configs
|
||||||
|
*.creds
|
||||||
|
ovpn_*
|
||||||
|
vpnlist.txt
|
||||||
140
nord-checker.py
Normal file
140
nord-checker.py
Normal file
@@ -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
|
||||||
@@ -33,13 +33,21 @@ try:
|
|||||||
|
|
||||||
# Read the file line by line
|
# Read the file line by line
|
||||||
with open('vpnlist.txt', 'r') as f:
|
with open('vpnlist.txt', 'r') as f:
|
||||||
for line in f:
|
for line_number, line in enumerate(f, start=1):
|
||||||
if line.startswith('#'):
|
if line.startswith('#'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
parts = line.strip().split(' # ')
|
if ' # ' not in line:
|
||||||
exit_ip = parts[0]
|
print(f"Skipping invalid line {line_number}: {line}")
|
||||||
file_name = parts[1].strip()
|
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
|
total_processed += 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user