| """
|
| 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
|
|
|
|
|
| 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
|
|
|
|
|
| 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():
|
|
|
| process_lock = ProcessLock()
|
| if not process_lock.acquire():
|
| logger.error("Another instance of the VPN server is already running")
|
| sys.exit(1)
|
|
|
| try:
|
|
|
| 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,
|
| "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")
|
|
|
|
|
| with open(config_path, 'r') as f:
|
| config = json.load(f)
|
|
|
|
|
| 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}")
|
|
|
|
|
| if os.name != 'nt' and os.geteuid() != 0:
|
| logger.error("VPN server must be run with administrator/root privileges")
|
| sys.exit(1)
|
|
|
| server = OutlineServer(config)
|
| await server.start()
|
|
|
|
|
| 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())
|
|
|