""" Main entry point for Outline/IKEv2 VPN server """ import os import sys import asyncio import logging import json import socket from pathlib import Path from contextlib import closing # Add project root to path project_root = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, project_root) from core.outline_server import OutlineServer from core.ikev2_server import IKEv2Server as IPsecManager from core.process_lock import ProcessLock # Setup logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(), logging.FileHandler('vpn_server.log') ] ) logger = logging.getLogger(__name__) def find_available_port(start_port: int, end_port: int = 65535) -> int: """Find an available port in the given range""" for port in range(start_port, end_port + 1): with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: try: sock.bind(('', port)) return port except socket.error: continue raise RuntimeError(f"No available ports in range {start_port}-{end_port}") async def main(): # Initialize process lock process_lock = ProcessLock() if not process_lock.acquire(): logger.error("Another instance of the VPN server is already running") sys.exit(1) try: # Load configuration config_path = os.path.join(project_root, 'config', 'server_config.json') if not os.path.exists(config_path): default_config = { "server": { "host": "0.0.0.0", "port": 8388, # Default Shadowsocks port "virtual_network": "10.0.0.0/24", "dns_servers": ["8.8.8.8", "8.8.4.4"], "fallback_ports": [8389, 8390, 8391, 8392] } } os.makedirs(os.path.dirname(config_path), exist_ok=True) with open(config_path, 'w') as f: json.dump(default_config, f, indent=4) logger.info("Created default configuration") # Load configuration with open(config_path, 'r') as f: config = json.load(f) # Find available port try: port = config["server"]["port"] with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: sock.bind(('', port)) except socket.error: logger.warning(f"Default port {port} is in use, finding alternative...") port = find_available_port(8388) config["server"]["port"] = port logger.info(f"Using alternative port: {port}") # Start Outline server with elevated privileges check if os.name != 'nt' and os.geteuid() != 0: # Not running as root on Unix logger.error("VPN server must be run with administrator/root privileges") sys.exit(1) server = OutlineServer(config) await server.start() # Keep running until interrupted while True: await asyncio.sleep(1) except KeyboardInterrupt: logger.info("Shutting down VPN server...") if 'server' in locals(): await server.stop() except Exception as e: logger.error(f"Server error: {e}") sys.exit(1) finally: process_lock.release() if __name__ == "__main__": asyncio.run(main())