import logging import ipaddress from flask import Blueprint, request, jsonify logger = logging.getLogger('picell') bp = Blueprint('wireguard', __name__) @bp.route('/api/wireguard/keys', methods=['GET']) def get_wireguard_keys(): try: from app import wireguard_manager keys = wireguard_manager.get_keys() return jsonify({ 'public_key': keys.get('public_key', ''), 'has_private_key': bool(keys.get('private_key')), }) except Exception as e: logger.error(f"Error getting WireGuard keys: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/keys/peer', methods=['POST']) def generate_peer_keys(): try: from app import wireguard_manager data = request.get_json(silent=True) or {} name = data.get('name') or data.get('peer_name') if not name: return jsonify({"error": "Missing peer name"}), 400 return jsonify(wireguard_manager.generate_peer_keys(name)) except Exception as e: logger.error(f"Error generating peer keys: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/config', methods=['GET']) def get_wireguard_config(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_config()) except Exception as e: logger.error(f"Error getting WireGuard config: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers', methods=['GET']) def get_wireguard_peers(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_peers()) except Exception as e: logger.error(f"Error getting WireGuard peers: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers', methods=['POST']) def add_wireguard_peer(): try: from app import wireguard_manager data = request.get_json(silent=True) or {} result = wireguard_manager.add_peer( name=data.get('name', ''), public_key=data.get('public_key', ''), endpoint_ip=data.get('endpoint', data.get('endpoint_ip', '')), allowed_ips=data.get('allowed_ips', ''), persistent_keepalive=data.get('persistent_keepalive', 25) ) return jsonify({"success": result}) except Exception as e: logger.error(f"Error adding WireGuard peer: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers', methods=['DELETE']) def remove_wireguard_peer(): try: from app import wireguard_manager data = request.get_json(silent=True) or {} public_key = data.get('public_key') or data.get('name', '') return jsonify({"success": wireguard_manager.remove_peer(public_key)}) except Exception as e: logger.error(f"Error removing WireGuard peer: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/status', methods=['GET']) def get_wireguard_status(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_status()) except Exception as e: logger.error(f"Error getting WireGuard status: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/connectivity', methods=['POST']) def test_wireguard_connectivity(): try: from app import wireguard_manager data = request.get_json(silent=True) if data is None: return jsonify({"error": "No data provided"}), 400 return jsonify(wireguard_manager.test_connectivity(data)) except Exception as e: logger.error(f"Error testing WireGuard connectivity: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers/ip', methods=['PUT']) def update_peer_ip(): try: from app import wireguard_manager data = request.get_json(silent=True) or {} result = wireguard_manager.update_peer_ip( data.get('public_key', data.get('peer', '')), data.get('ip', '') ) return jsonify({"success": result}) except Exception as e: logger.error(f"Error updating peer IP: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers/status', methods=['POST']) def get_peer_status(): try: from app import wireguard_manager data = request.get_json(silent=True) or {} public_key = data.get('public_key', '') if not public_key: return jsonify({"error": "Missing public_key"}), 400 return jsonify(wireguard_manager.get_peer_status(public_key)) except Exception as e: logger.error(f"Error getting peer status: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers/statuses', methods=['GET']) def get_all_peer_statuses(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_all_peer_statuses()) except Exception as e: logger.error(f"Error getting peer statuses: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/network/setup', methods=['POST']) def setup_network(): try: from app import wireguard_manager success = wireguard_manager.setup_network_configuration() if success: return jsonify({"message": "Network configuration setup completed successfully"}) return jsonify({"error": "Failed to setup network configuration"}), 500 except Exception as e: logger.error(f"Error setting up network configuration: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/network/status', methods=['GET']) def get_network_status(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_network_status()) except Exception as e: logger.error(f"Error getting network status: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/peers/config', methods=['POST']) def get_peer_config(): try: from app import wireguard_manager, peer_registry data = request.get_json(silent=True) or {} peer_name = data.get('name', data.get('peer', '')) peer_ip = data.get('ip', '') peer_private_key = data.get('private_key', '') registered = peer_registry.get_peer(peer_name) if peer_name else {} if peer_name and (not peer_ip or not peer_private_key): if registered: peer_ip = peer_ip or registered.get('ip', '') peer_private_key = peer_private_key or registered.get('private_key', '') server_endpoint = data.get('server_endpoint', '') if not server_endpoint: srv = wireguard_manager.get_server_config() server_endpoint = srv.get('endpoint') or '' allowed_ips = data.get('allowed_ips') or None if not allowed_ips and registered: internet_access = registered.get('internet_access', True) route_via = registered.get('route_via') # Full tunnel when internet is allowed OR when route_via is set # (route_via exits via a remote cell — all traffic must go through the tunnel) use_full = internet_access or bool(route_via) allowed_ips = wireguard_manager.FULL_TUNNEL_IPS if use_full else wireguard_manager.get_split_tunnel_ips() result = wireguard_manager.get_peer_config( peer_name=peer_name, peer_ip=peer_ip, peer_private_key=peer_private_key, server_endpoint=server_endpoint, allowed_ips=allowed_ips, ) return jsonify({"config": result}) except Exception as e: logger.error(f"Error getting peer config: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/server-config', methods=['GET']) def get_server_config(): try: from app import wireguard_manager return jsonify(wireguard_manager.get_server_config()) except Exception as e: logger.error(f"Error getting server config: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/refresh-ip', methods=['GET', 'POST']) def refresh_external_ip(): try: from app import wireguard_manager ip = wireguard_manager.get_external_ip(force_refresh=True) port = wireguard_manager._get_configured_port() return jsonify({ 'external_ip': ip, 'port': port, 'endpoint': f'{ip}:{port}' if ip else None, }) except Exception as e: logger.error(f"Error refreshing external IP: {e}") return jsonify({"error": str(e)}), 500 @bp.route('/api/wireguard/apply-enforcement', methods=['POST']) def apply_wireguard_enforcement(): try: from app import (peer_registry, wireguard_manager, firewall_manager, cell_link_manager, _configured_domain, COREFILE_PATH) peers = peer_registry.list_peers() try: _wg_addr = wireguard_manager._get_configured_address() _wg_subnet = str(ipaddress.ip_network(_wg_addr, strict=False)) if _wg_addr else '10.0.0.0/24' except Exception: _wg_subnet = '10.0.0.0/24' _cell_links = cell_link_manager.list_connections() _cell_subnets = [l['vpn_subnet'] for l in _cell_links if l.get('vpn_subnet')] firewall_manager.apply_all_peer_rules(peers, wg_subnet=_wg_subnet, cell_subnets=_cell_subnets) firewall_manager.apply_all_dns_rules(peers, COREFILE_PATH, _configured_domain(), cell_links=_cell_links) return jsonify({'ok': True, 'peers': len(peers)}) except Exception as e: return jsonify({'error': str(e)}), 500 @bp.route('/api/wireguard/check-port', methods=['GET', 'POST']) def check_wireguard_port(): try: from app import wireguard_manager port_open = wireguard_manager.check_port_open() return jsonify({'port_open': port_open, 'port': wireguard_manager._get_configured_port()}) except Exception as e: return jsonify({"error": str(e)}), 500