| """ |
| Main ISP Application |
| |
| Integrates all core modules and provides the main application entry point |
| """ |
|
|
| import os |
| import sys |
| import json |
| import threading |
| import time |
| from flask import Flask |
| from flask_cors import CORS |
|
|
| |
| sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) |
|
|
| |
| from routes.isp_api import isp_api, init_engines |
|
|
|
|
| def load_config(): |
| """Load configuration from file or use defaults""" |
| config_file = os.path.join(os.path.dirname(__file__), 'config.json') |
| |
| default_config = { |
| "dhcp": { |
| "network": "10.0.0.0/24", |
| "range_start": "10.0.0.10", |
| "range_end": "10.0.0.100", |
| "lease_time": 3600, |
| "gateway": "10.0.0.1", |
| "dns_servers": ["8.8.8.8", "8.8.4.4"] |
| }, |
| "nat": { |
| "port_range_start": 10000, |
| "port_range_end": 65535, |
| "session_timeout": 300, |
| "host_ip": "0.0.0.0" |
| }, |
| "firewall": { |
| "default_policy": "ACCEPT", |
| "log_blocked": True, |
| "log_accepted": False, |
| "max_log_entries": 10000, |
| "rules": [ |
| { |
| "rule_id": "allow_dhcp", |
| "priority": 1, |
| "action": "ACCEPT", |
| "direction": "BOTH", |
| "dest_port": "67,68", |
| "protocol": "UDP", |
| "description": "Allow DHCP traffic", |
| "enabled": True |
| }, |
| { |
| "rule_id": "allow_dns", |
| "priority": 2, |
| "action": "ACCEPT", |
| "direction": "BOTH", |
| "dest_port": "53", |
| "protocol": "UDP", |
| "description": "Allow DNS traffic", |
| "enabled": True |
| } |
| ] |
| }, |
| "tcp": { |
| "initial_window": 65535, |
| "max_retries": 3, |
| "timeout": 300, |
| "time_wait_timeout": 120, |
| "mss": 1460 |
| }, |
| "router": { |
| "router_id": "virtual-isp-router", |
| "default_gateway": "10.0.0.1", |
| "interfaces": [ |
| { |
| "name": "virtual0", |
| "ip_address": "10.0.0.1", |
| "netmask": "255.255.255.0", |
| "enabled": True, |
| "mtu": 1500 |
| } |
| ], |
| "static_routes": [] |
| }, |
| "socket_translator": { |
| "connect_timeout": 10, |
| "read_timeout": 30, |
| "max_connections": 1000, |
| "buffer_size": 8192 |
| }, |
| "packet_bridge": { |
| "websocket_host": "0.0.0.0", |
| "websocket_port": 8765, |
| "tcp_host": "0.0.0.0", |
| "tcp_port": 8766, |
| "max_clients": 100, |
| "client_timeout": 300 |
| }, |
| "session_tracker": { |
| "max_sessions": 10000, |
| "session_timeout": 3600, |
| "cleanup_interval": 300, |
| "metrics_retention": 86400 |
| }, |
| "logger": { |
| "log_level": "INFO", |
| "log_to_file": True, |
| "log_file_path": "/tmp/virtual_isp.log", |
| "log_file_max_size": 10485760, |
| "log_file_backup_count": 5, |
| "log_to_console": True, |
| "structured_logging": True, |
| "max_memory_logs": 10000 |
| }, |
| "openvpn": { |
| "server_config_path": "/etc/openvpn/server/server.conf", |
| "ca_cert_path": "/etc/openvpn/server/ca.crt", |
| "server_cert_path": "/etc/openvpn/server/server.crt", |
| "server_key_path": "/etc/openvpn/server/server.key", |
| "dh_path": "/etc/openvpn/server/dh.pem", |
| "vpn_network": "10.8.0.0/24", |
| "vpn_server_ip": "10.8.0.1", |
| "vpn_port": 1194, |
| "protocol": "udp", |
| "auto_start": False, |
| "client_to_client": False, |
| "push_routes": [ |
| "redirect-gateway def1 bypass-dhcp", |
| "dhcp-option DNS 8.8.8.8", |
| "dhcp-option DNS 8.8.4.4" |
| ] |
| } |
| } |
| |
| if os.path.exists(config_file): |
| try: |
| with open(config_file, 'r') as f: |
| file_config = json.load(f) |
| |
| |
| def merge_config(default, override): |
| result = default.copy() |
| for key, value in override.items(): |
| if key in result and isinstance(result[key], dict) and isinstance(value, dict): |
| result[key] = merge_config(result[key], value) |
| else: |
| result[key] = value |
| return result |
| |
| return merge_config(default_config, file_config) |
| |
| except Exception as e: |
| print(f"Error loading config file: {e}") |
| print("Using default configuration") |
| return default_config |
| else: |
| |
| try: |
| with open(config_file, 'w') as f: |
| json.dump(default_config, f, indent=2) |
| print(f"Created default configuration file: {config_file}") |
| except Exception as e: |
| print(f"Could not save default config: {e}") |
| |
| return default_config |
|
|
|
|
| def create_app(): |
| """Create and configure Flask application""" |
| app = Flask(__name__, static_folder=os.path.join(os.path.dirname(__file__), 'static')) |
| |
| |
| CORS(app, origins="*", allow_headers=["Content-Type", "Authorization"]) |
| |
| |
| config = load_config() |
| app.config['ISP_CONFIG'] = config |
| |
| |
| app.register_blueprint(isp_api, url_prefix='/api') |
| |
| |
| init_engines(config) |
| |
| |
| @app.route('/', defaults={'path': ''}) |
| @app.route('/<path:path>') |
| def serve_static(path): |
| static_folder_path = app.static_folder |
| if static_folder_path is None: |
| return "Static folder not configured", 404 |
| |
| if path != "" and os.path.exists(os.path.join(static_folder_path, path)): |
| return app.send_static_file(path) |
| else: |
| index_path = os.path.join(static_folder_path, 'index.html') |
| if os.path.exists(index_path): |
| return app.send_static_file('index.html') |
| else: |
| return """ |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>Virtual ISP Stack</title> |
| <style> |
| body { font-family: Arial, sans-serif; margin: 40px; } |
| .container { max-width: 800px; margin: 0 auto; } |
| .status { background: #f0f0f0; padding: 20px; border-radius: 5px; } |
| .api-link { color: #0066cc; text-decoration: none; } |
| .api-link:hover { text-decoration: underline; } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <h1>Virtual ISP Stack</h1> |
| <div class="status"> |
| <h2>System Status</h2> |
| <p>The Virtual ISP Stack is running successfully!</p> |
| <p><strong>API Endpoint:</strong> <a href="/api/status" class="api-link">/api/status</a></p> |
| <p><strong>System Stats:</strong> <a href="/api/stats" class="api-link">/api/stats</a></p> |
| </div> |
| |
| <h2>Available API Endpoints</h2> |
| <ul> |
| <li><a href="/api/config" class="api-link">GET /api/config</a> - System configuration</li> |
| <li><a href="/api/status" class="api-link">GET /api/status</a> - System status</li> |
| <li><a href="/api/stats" class="api-link">GET /api/stats</a> - System statistics</li> |
| <li><a href="/api/dhcp/leases" class="api-link">GET /api/dhcp/leases</a> - DHCP leases</li> |
| <li><a href="/api/nat/sessions" class="api-link">GET /api/nat/sessions</a> - NAT sessions</li> |
| <li><a href="/api/firewall/rules" class="api-link">GET /api/firewall/rules</a> - Firewall rules</li> |
| <li><a href="/api/tcp/connections" class="api-link">GET /api/tcp/connections</a> - TCP connections</li> |
| <li><a href="/api/router/routes" class="api-link">GET /api/router/routes</a> - Routing table</li> |
| <li><a href="/api/bridge/clients" class="api-link">GET /api/bridge/clients</a> - Bridge clients</li> |
| <li><a href="/api/sessions" class="api-link">GET /api/sessions</a> - Session tracking</li> |
| <li><a href="/api/logs" class="api-link">GET /api/logs</a> - System logs</li> |
| </ul> |
| |
| <h2>WebSocket Bridge</h2> |
| <p>WebSocket server running on port 8765 for packet bridge connections.</p> |
| <p>TCP server running on port 8766 for packet bridge connections.</p> |
| </div> |
| </body> |
| </html> |
| """, 200 |
| |
| return app |
|
|
|
|
| def main(): |
| """Main application entry point""" |
| print("Starting Virtual ISP Stack...") |
| |
| |
| app = create_app() |
| |
| |
| print("Virtual ISP Stack started successfully!") |
| print("API available at: http://0.0.0.0:5000/api/") |
| print("WebSocket bridge at: ws://0.0.0.0:8765") |
| print("TCP bridge at: tcp://0.0.0.0:8766") |
| |
| |
| app.run(host='0.0.0.0', port=5000, debug=False, threaded=True) |
|
|
|
|
| if __name__ == '__main__': |
| main() |
|
|
|
|