Spaces:
Runtime error
Runtime error
| """ | |
| 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()) | |