159 lines
6.8 KiB
Python
159 lines
6.8 KiB
Python
import os
|
|
import subprocess
|
|
import random
|
|
import time
|
|
import datetime
|
|
import re
|
|
import sys
|
|
from psql_utils import connect_to_database, should_skip_file, update_or_insert_ip
|
|
from ovpn_downloader import download_and_extract_ovpn_configs
|
|
from openvpn_manager import establish_vpn_connection, is_vpn_active, disconnect_vpn, get_external_ip
|
|
|
|
# Variables
|
|
CREDENTIAL_FILE = "nord.creds"
|
|
OVPN_DIR = "/root/nordvpn/ovpn_configs/ovpn_tcp"
|
|
LOG_FILE = "/root/nordvpn/openvpn.log"
|
|
RESULT_FILE = "vpnlist.txt"
|
|
|
|
# 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') # Get PIDs as a list
|
|
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 (using the function from ovpn_downloader.py)
|
|
debug_print(f"{datetime.datetime.now()} [Main Script]: Downloading and extracting OVPN configurations...")
|
|
ovpn_files = download_and_extract_ovpn_configs()
|
|
|
|
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
|
|
|
|
# Connect to PostgreSQL database
|
|
conn, cursor = connect_to_database()
|
|
|
|
# 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...")
|
|
|
|
# Check if file exists in database and if last check is older than 3 days
|
|
skip_file = should_skip_file(cursor, OVPN_FILENAME)
|
|
debug_print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: should_skip_file returned: {skip_file}")
|
|
|
|
if skip_file:
|
|
print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Skipping, last check was less than 3 days ago.")
|
|
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)
|
|
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())
|
|
|
|
# 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
|
|
while attempt < max_attempts:
|
|
try:
|
|
last_lines = subprocess.check_output(["tail", "-n", "10", LOG_FILE]).decode().strip()
|
|
if "Initialization Sequence Completed" in last_lines:
|
|
print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection established.")
|
|
break
|
|
elif "AUTH: Received control message: AUTH_FAILED" in last_lines:
|
|
backoff_time += 1 # Increment backoff time
|
|
if backoff_time >= 30: # If backoff reaches 30 seconds, skip
|
|
print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: Authentication failed. Skipping this OVPN file.")
|
|
continue # Skip to the next OVPN file
|
|
except subprocess.CalledProcessError:
|
|
pass
|
|
time.sleep(1)
|
|
attempt += 1
|
|
else:
|
|
print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection failed to establish (timeout).")
|
|
continue
|
|
|
|
# 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 = get_external_ip()
|
|
|
|
if external_ip is None:
|
|
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}")
|
|
|
|
# Update or insert into database
|
|
update_or_insert_ip(cursor, conn, OVPN_FILENAME, external_ip)
|
|
|
|
except subprocess.CalledProcessError:
|
|
print(f"{datetime.datetime.now()} [{FILE_NUM}/{total_files}] [{OVPN_FILENAME}]: VPN connection failed to establish.")
|
|
|
|
# Disconnect VPN
|
|
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()} [{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 5 and 8 seconds
|
|
sleep_time = random.randint(5, 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
|
|
|
|
# Close the database connection
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
# Close the log file
|
|
log_file.close() |