commit 58d70409b594c22a8acdda32498c3bffac560f9f Author: nocci Date: Sun Aug 10 15:34:34 2025 +0200 New branch diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3ecfd4e --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +# VPN Gateway Configuration Example +# Copy to .env and adjust + +# Network Configuration +LAN_INTERFACE=eth0 +LAN_NETWORK=192.168.1.0/24 + +# Provider Configuration +VPN_PROVIDER=mullvad +MULLVAD_ACCOUNT=1234567890123456 + +# Custom Server (if using custom provider) +WG_ENDPOINT=your-server.com:51820 +WG_SERVER_PUBKEY=your-server-public-key-here +WG_CLIENT_IP=10.0.0.2/32 + +# Security +ALERT_EMAIL=admin@example.com +CHECK_INTERVAL=10 + +# WebUI +WEBUI_PORT=5000 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..f2d4626 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +name: Test Installation + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test-install: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Test installer syntax + run: | + bash -n install.sh + for script in scripts/*.sh; do + bash -n "$script" + done + + - name: Test Python syntax + run: | + python3 -m py_compile backend/app.py + + - name: Security scan + run: | + pip install bandit + bandit -r backend/ || true + + - name: Shellcheck + run: | + sudo apt-get install -y shellcheck + shellcheck install.sh scripts/*.sh || true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8172c92 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 VPN Gateway Project + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..61ff94b --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +.PHONY: install uninstall update test health backup restore start stop status logs + +install: + @echo "Installing VPN Gateway..." + @sudo bash install.sh + +uninstall: + @echo "Uninstalling VPN Gateway..." + @sudo bash scripts/uninstall.sh + +update: + @echo "Updating VPN Gateway..." + @sudo bash scripts/update.sh + +test: + @echo "Testing installation..." + @bash -n install.sh + @for script in scripts/*.sh; do bash -n $$script; done + @python3 -m py_compile backend/app.py + @echo "All tests passed!" + +health: + @sudo bash scripts/health-check.sh + +backup: + @echo "Creating backup..." + @sudo tar czf vpn-gateway-backup-$$(date +%Y%m%d-%H%M%S).tar.gz \ + /opt/vpn-gateway \ + /etc/wireguard \ + /etc/systemd/system/vpn-*.service + +start: + @sudo systemctl start vpn-webui vpn-killswitch vpn-security-monitor + +stop: + @sudo systemctl stop vpn-webui vpn-security-monitor + +status: + @sudo systemctl status vpn-webui vpn-killswitch vpn-security-monitor + +logs: + @sudo journalctl -u vpn-webui -u vpn-killswitch -u vpn-security-monitor -f diff --git a/README.md b/README.md new file mode 100644 index 0000000..59f3a3d --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# πŸ”’ Mullvad VPN Gateway for LXC - Multi-Provider Edition + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Version](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://github.com/yourusername/vpn-gateway) +[![Security](https://img.shields.io/badge/security-hardened-green.svg)](https://github.com/yourusername/vpn-gateway) + +Secure VPN Gateway with **permanent killswitch** for LXC containers. Supports Mullvad, custom WireGuard servers, and imported configurations. + +## ⚑ Quick Start + +```bash +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/main/install.sh | bash +``` + +## 🎯 Features + +- βœ… **Multi-Provider Support** - Mullvad, Custom Servers, Import Configs +- βœ… **Permanent Killswitch** - No internet without VPN, ever +- 🌍 **Dynamic Server Selection** - Switch between countries/cities via WebUI +- πŸ›‘οΈ **Zero-Leak Protection** - DNS leak protection, IPv6 blocking +- 🎨 **Modern WebUI** - Beautiful, responsive control panel +- πŸ”„ **Auto-Reconnect** - Automatic recovery on connection drops +- πŸ“Š **Live Monitoring** - Real-time status and statistics + +## πŸ“‹ Requirements + +- LXC Container (Proxmox/LXD) +- Ubuntu 20.04+ or Debian 11+ +- Root access +- Mullvad account OR own WireGuard server + +## πŸš€ Installation + +```bash +# Clone repository +git clone https://github.com/yourusername/vpn-gateway.git +cd vpn-gateway + +# Run installer +sudo ./install.sh +``` + +## πŸ“– Documentation + +- [Quick Start Guide](docs/QUICKSTART.md) +- [Provider Configuration](docs/PROVIDERS.md) +- [Security Documentation](docs/SECURITY.md) +- [FAQ](docs/FAQ.md) + +## 🀝 Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## πŸ“„ License + +MIT License - see [LICENSE](LICENSE) file + +## ⚠️ Disclaimer + +The permanent killswitch will block ALL internet traffic when VPN is not connected. This is by design and cannot be disabled. diff --git a/backend/app.py b/backend/app.py new file mode 100644 index 0000000..553378e --- /dev/null +++ b/backend/app.py @@ -0,0 +1,648 @@ +#!/usr/bin/env python3 +""" +Multi-Provider VPN Gateway Backend +Supports: Mullvad, Custom WireGuard, Imported Configs +With permanent killswitch protection +""" + +from flask import Flask, request, jsonify, send_from_directory +from flask_cors import CORS +import subprocess +import json +import os +import re +import requests +import time +import yaml +import base64 +from datetime import datetime +import threading +import logging +from pathlib import Path +from typing import Dict, List, Optional + +app = Flask(__name__) +CORS(app) + +# Configuration +CONFIG_FILE = '/opt/vpn-gateway/config.json' +PROVIDERS_DIR = '/opt/vpn-gateway/providers' +WIREGUARD_DIR = '/etc/wireguard' + +# Setup logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler('/var/log/vpn-gateway.log'), + logging.StreamHandler() + ] +) + +class VPNProvider: + """Base class for VPN providers""" + + def __init__(self, name: str): + self.name = name + self.servers = {} + + def get_servers(self) -> Dict: + raise NotImplementedError + + def generate_config(self, server: str) -> str: + raise NotImplementedError + +class MullvadProvider(VPNProvider): + """Mullvad VPN provider""" + + def __init__(self): + super().__init__("mullvad") + self.api_url = "https://api.mullvad.net/www/relays/all/" + self.public_key = "g+9JNZp3SvLPvBb+PzXHyOPHhqNiUdATrz1YdNEPvWo=" + + def get_servers(self) -> Dict: + try: + response = requests.get(self.api_url, timeout=10) + servers = response.json() + + organized = {} + for server in servers: + if server.get('type') == 'wireguard' and server.get('active'): + country = server.get('country_name', 'Unknown') + city = server.get('city_name', 'Unknown') + + if country not in organized: + organized[country] = {} + if city not in organized[country]: + organized[country][city] = [] + + organized[country][city].append({ + 'hostname': server['hostname'], + 'ipv4': server['ipv4_addr_in'], + 'ipv6': server.get('ipv6_addr_in'), + 'type': 'WireGuard', + 'provider': 'Mullvad' + }) + + self.servers = organized + return organized + + except Exception as e: + logging.error(f"Failed to fetch Mullvad servers: {e}") + return {} + + def generate_config(self, server_hostname: str) -> str: + server_info = self._find_server(server_hostname) + if not server_info: + raise ValueError(f"Server {server_hostname} not found") + + private_key = self._get_or_generate_key() + + return f"""# Mullvad WireGuard Configuration +# Server: {server_hostname} +# Provider: Mullvad + +[Interface] +PrivateKey = {private_key} +Address = 10.64.0.2/32,fc00:bbbb:bbbb:bb01::2/128 +DNS = 100.64.0.1 + +# PERMANENT KILLSWITCH - CANNOT BE DISABLED +PreUp = iptables -F OUTPUT +PreUp = iptables -F FORWARD +PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostUp = iptables -I FORWARD -i eth0 -o %i -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE +PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE + +[Peer] +PublicKey = {self.public_key} +AllowedIPs = 0.0.0.0/0,::/0 +Endpoint = {server_info['ipv4']}:51820 +PersistentKeepalive = 25 +""" + + def _find_server(self, hostname: str) -> Optional[Dict]: + for country in self.servers.values(): + for city in country.values(): + for server in city: + if server['hostname'] == hostname: + return server + return None + + def _get_or_generate_key(self) -> str: + key_file = f"{WIREGUARD_DIR}/mullvad_private.key" + if os.path.exists(key_file): + with open(key_file, 'r') as f: + return f.read().strip() + else: + private_key = subprocess.check_output(['wg', 'genkey'], text=True).strip() + with open(key_file, 'w') as f: + f.write(private_key) + os.chmod(key_file, 0o600) + return private_key + +class CustomWireGuardProvider(VPNProvider): + """Custom WireGuard servers provider""" + + def __init__(self): + super().__init__("custom") + self.config_file = f"{PROVIDERS_DIR}/custom_servers.json" + self.load_servers() + + def load_servers(self): + """Load custom servers from config file""" + if os.path.exists(self.config_file): + try: + with open(self.config_file, 'r') as f: + self.servers = json.load(f) + except Exception as e: + logging.error(f"Failed to load custom servers: {e}") + self.servers = {} + else: + self.servers = {} + + def save_servers(self): + """Save custom servers to config file""" + os.makedirs(PROVIDERS_DIR, exist_ok=True) + with open(self.config_file, 'w') as f: + json.dump(self.servers, f, indent=2) + + def add_server(self, name: str, config: Dict) -> bool: + """Add a custom WireGuard server""" + try: + location = config.get('location', 'Custom') + + if location not in self.servers: + self.servers[location] = {} + + if 'Custom' not in self.servers[location]: + self.servers[location]['Custom'] = [] + + self.servers[location]['Custom'].append({ + 'hostname': name, + 'endpoint': config['endpoint'], + 'public_key': config['public_key'], + 'private_key': config.get('private_key'), + 'address': config.get('address', '10.0.0.2/32'), + 'dns': config.get('dns', '1.1.1.1,1.0.0.1'), + 'allowed_ips': config.get('allowed_ips', '0.0.0.0/0,::/0'), + 'keepalive': config.get('keepalive', 25), + 'type': 'WireGuard', + 'provider': 'Custom' + }) + + self.save_servers() + return True + + except Exception as e: + logging.error(f"Failed to add custom server: {e}") + return False + + def remove_server(self, name: str) -> bool: + """Remove a custom server""" + for location in self.servers.values(): + for city in location.values(): + for i, server in enumerate(city): + if server['hostname'] == name: + city.pop(i) + self.save_servers() + return True + return False + + def generate_config(self, server_name: str) -> str: + server_info = self._find_server(server_name) + if not server_info: + raise ValueError(f"Server {server_name} not found") + + private_key = server_info.get('private_key') + if not private_key: + private_key = self._get_or_generate_key(server_name) + + dns_servers = server_info.get('dns', '1.1.1.1,1.0.0.1') + + return f"""# Custom WireGuard Configuration +# Server: {server_name} +# Provider: Custom + +[Interface] +PrivateKey = {private_key} +Address = {server_info.get('address', '10.0.0.2/32')} +DNS = {dns_servers} + +# PERMANENT KILLSWITCH - CANNOT BE DISABLED +PreUp = iptables -F OUTPUT +PreUp = iptables -F FORWARD +PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostUp = iptables -I FORWARD -i eth0 -o %i -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE +PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE + +[Peer] +PublicKey = {server_info['public_key']} +AllowedIPs = {server_info.get('allowed_ips', '0.0.0.0/0,::/0')} +Endpoint = {server_info['endpoint']} +PersistentKeepalive = {server_info.get('keepalive', 25)} +""" + + def _find_server(self, name: str) -> Optional[Dict]: + for location in self.servers.values(): + for city in location.values(): + for server in city: + if server['hostname'] == name: + return server + return None + + def _get_or_generate_key(self, name: str) -> str: + key_file = f"{WIREGUARD_DIR}/custom_{name}_private.key" + if os.path.exists(key_file): + with open(key_file, 'r') as f: + return f.read().strip() + else: + private_key = subprocess.check_output(['wg', 'genkey'], text=True).strip() + with open(key_file, 'w') as f: + f.write(private_key) + os.chmod(key_file, 0o600) + return private_key + +class ImportedConfigProvider(VPNProvider): + """Provider for imported WireGuard configs""" + + def __init__(self): + super().__init__("imported") + self.configs_dir = f"{PROVIDERS_DIR}/imported" + os.makedirs(self.configs_dir, exist_ok=True) + self.load_configs() + + def load_configs(self): + """Load all imported configs""" + self.servers = {"Imported": {"Configs": []}} + + for config_file in Path(self.configs_dir).glob("*.conf"): + name = config_file.stem + self.servers["Imported"]["Configs"].append({ + 'hostname': name, + 'file': str(config_file), + 'type': 'WireGuard', + 'provider': 'Imported' + }) + + def import_config(self, name: str, config_content: str) -> bool: + """Import a WireGuard config""" + try: + # Validate config + if '[Interface]' not in config_content or '[Peer]' not in config_content: + raise ValueError("Invalid WireGuard configuration") + + # Add killswitch if not present + if 'PostUp' not in config_content: + config_content = self._add_killswitch(config_content) + + # Save config + config_file = f"{self.configs_dir}/{name}.conf" + with open(config_file, 'w') as f: + f.write(config_content) + os.chmod(config_file, 0o600) + + self.load_configs() + return True + + except Exception as e: + logging.error(f"Failed to import config: {e}") + return False + + def _add_killswitch(self, config: str) -> str: + """Add killswitch rules to imported config""" + killswitch_rules = """ +# PERMANENT KILLSWITCH - ADDED AUTOMATICALLY +PreUp = iptables -F OUTPUT +PreUp = iptables -F FORWARD +PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostUp = iptables -I FORWARD -i eth0 -o %i -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE +PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE +""" + + # Insert after [Interface] section + lines = config.split('\n') + for i, line in enumerate(lines): + if line.strip() == '[Interface]': + # Find next section or end + for j in range(i+1, len(lines)): + if lines[j].strip().startswith('['): + lines.insert(j, killswitch_rules) + break + else: + lines.insert(len(lines), killswitch_rules) + break + + return '\n'.join(lines) + + def generate_config(self, name: str) -> str: + for server in self.servers["Imported"]["Configs"]: + if server['hostname'] == name: + with open(server['file'], 'r') as f: + return f.read() + raise ValueError(f"Config {name} not found") + +# Global provider instances +PROVIDERS = { + 'mullvad': MullvadProvider(), + 'custom': CustomWireGuardProvider(), + 'imported': ImportedConfigProvider() +} + +# Current provider +CURRENT_PROVIDER = None + +# VPN Status +VPN_STATUS = { + 'connected': False, + 'provider': None, + 'server': None, + 'ip': None, + 'location': None, + 'start_time': None +} + +def load_config(): + """Load application configuration""" + global CURRENT_PROVIDER + + if os.path.exists(CONFIG_FILE): + try: + with open(CONFIG_FILE, 'r') as f: + config = json.load(f) + provider_name = config.get('provider', 'mullvad') + CURRENT_PROVIDER = PROVIDERS.get(provider_name) + logging.info(f"Loaded provider: {provider_name}") + except Exception as e: + logging.error(f"Failed to load config: {e}") + CURRENT_PROVIDER = PROVIDERS['mullvad'] + else: + CURRENT_PROVIDER = PROVIDERS['mullvad'] + +def save_config(): + """Save application configuration""" + try: + config = { + 'provider': CURRENT_PROVIDER.name if CURRENT_PROVIDER else 'mullvad', + 'timestamp': datetime.now().isoformat() + } + + os.makedirs(os.path.dirname(CONFIG_FILE), exist_ok=True) + with open(CONFIG_FILE, 'w') as f: + json.dump(config, f, indent=2) + + except Exception as e: + logging.error(f"Failed to save config: {e}") + +def check_vpn_status(): + """Check current VPN status""" + global VPN_STATUS + + try: + result = subprocess.run(['wg', 'show', 'wg0'], capture_output=True, text=True) + + if result.returncode == 0 and 'interface:' in result.stdout.lower(): + VPN_STATUS['connected'] = True + + # Get public IP and location + try: + # Try Mullvad API first + response = requests.get('https://am.i.mullvad.net/json', timeout=5) + data = response.json() + VPN_STATUS['ip'] = data.get('ip') + + if data.get('mullvad_exit_ip'): + VPN_STATUS['location'] = f"{data.get('city')}, {data.get('country')}" + else: + # Fallback to ipinfo + response = requests.get('https://ipinfo.io/json', timeout=5) + data = response.json() + VPN_STATUS['ip'] = data.get('ip') + VPN_STATUS['location'] = f"{data.get('city')}, {data.get('country')}" + except: + pass + else: + VPN_STATUS['connected'] = False + VPN_STATUS['server'] = None + VPN_STATUS['ip'] = None + VPN_STATUS['location'] = None + VPN_STATUS['provider'] = None + + except Exception as e: + logging.error(f"Status check error: {e}") + VPN_STATUS['connected'] = False + +# Flask Routes + +@app.route('/') +def index(): + return send_from_directory('/opt/vpn-gateway/static', 'index.html') + +@app.route('/api/providers') +def get_providers(): + """Get available providers""" + return jsonify({ + 'providers': list(PROVIDERS.keys()), + 'current': CURRENT_PROVIDER.name if CURRENT_PROVIDER else None + }) + +@app.route('/api/provider/', methods=['POST']) +def set_provider(provider_name): + """Switch provider""" + global CURRENT_PROVIDER + + if provider_name not in PROVIDERS: + return jsonify({'success': False, 'error': 'Invalid provider'}), 400 + + # Disconnect if connected + if VPN_STATUS['connected']: + subprocess.run(['wg-quick', 'down', 'wg0'], capture_output=True) + + CURRENT_PROVIDER = PROVIDERS[provider_name] + save_config() + + return jsonify({'success': True, 'provider': provider_name}) + +@app.route('/api/servers') +def get_servers(): + """Get servers for current provider""" + if not CURRENT_PROVIDER: + return jsonify({'servers': {}}) + + servers = CURRENT_PROVIDER.get_servers() + return jsonify({ + 'servers': servers, + 'provider': CURRENT_PROVIDER.name + }) + +@app.route('/api/custom/add', methods=['POST']) +def add_custom_server(): + """Add custom WireGuard server""" + if not isinstance(CURRENT_PROVIDER, CustomWireGuardProvider): + return jsonify({'success': False, 'error': 'Not in custom mode'}), 400 + + data = request.json + name = data.get('name') + config = { + 'endpoint': data.get('endpoint'), + 'public_key': data.get('public_key'), + 'private_key': data.get('private_key'), + 'address': data.get('address', '10.0.0.2/32'), + 'dns': data.get('dns', '1.1.1.1,1.0.0.1'), + 'allowed_ips': data.get('allowed_ips', '0.0.0.0/0,::/0'), + 'location': data.get('location', 'Custom') + } + + if CURRENT_PROVIDER.add_server(name, config): + return jsonify({'success': True}) + else: + return jsonify({'success': False, 'error': 'Failed to add server'}), 500 + +@app.route('/api/custom/remove/', methods=['DELETE']) +def remove_custom_server(name): + """Remove custom server""" + if not isinstance(CURRENT_PROVIDER, CustomWireGuardProvider): + return jsonify({'success': False, 'error': 'Not in custom mode'}), 400 + + if CURRENT_PROVIDER.remove_server(name): + return jsonify({'success': True}) + else: + return jsonify({'success': False, 'error': 'Server not found'}), 404 + +@app.route('/api/import', methods=['POST']) +def import_config(): + """Import WireGuard config""" + data = request.json + name = data.get('name') + config_content = data.get('config') + + if not name or not config_content: + return jsonify({'success': False, 'error': 'Missing name or config'}), 400 + + provider = PROVIDERS['imported'] + if provider.import_config(name, config_content): + return jsonify({'success': True}) + else: + return jsonify({'success': False, 'error': 'Failed to import config'}), 500 + +@app.route('/api/status') +def get_status(): + """Get VPN status""" + check_vpn_status() + + uptime = None + if VPN_STATUS['connected'] and VPN_STATUS['start_time']: + uptime_seconds = int(time.time() - VPN_STATUS['start_time']) + hours = uptime_seconds // 3600 + minutes = (uptime_seconds % 3600) // 60 + uptime = f"{hours}h {minutes}m" + + return jsonify({ + 'connected': VPN_STATUS['connected'], + 'provider': VPN_STATUS['provider'], + 'server': VPN_STATUS['server'], + 'ip': VPN_STATUS['ip'], + 'location': VPN_STATUS['location'], + 'uptime': uptime, + 'killswitch_active': True # Always true + }) + +@app.route('/api/connect', methods=['POST']) +def connect_vpn(): + """Connect to VPN""" + data = request.json + server = data.get('server') + + if not server or not CURRENT_PROVIDER: + return jsonify({'success': False, 'error': 'No server or provider selected'}), 400 + + try: + # Disconnect if connected + subprocess.run(['wg-quick', 'down', 'wg0'], capture_output=True) + time.sleep(1) + + # Generate config + config = CURRENT_PROVIDER.generate_config(server) + + # Write config + with open('/etc/wireguard/wg0.conf', 'w') as f: + f.write(config) + os.chmod('/etc/wireguard/wg0.conf', 0o600) + + # Add firewall exception for endpoint + endpoint_match = re.search(r'Endpoint = ([\d.]+):', config) + if endpoint_match: + subprocess.run([ + 'iptables', '-I', 'OUTPUT', '1', '-p', 'udp', + '--dport', '51820', '-d', endpoint_match.group(1), '-j', 'ACCEPT' + ]) + + # Connect + result = subprocess.run(['wg-quick', 'up', 'wg0'], + capture_output=True, text=True) + + if result.returncode == 0: + VPN_STATUS['start_time'] = time.time() + VPN_STATUS['server'] = server + VPN_STATUS['provider'] = CURRENT_PROVIDER.name + + logging.info(f"Connected to {server} via {CURRENT_PROVIDER.name}") + return jsonify({'success': True}) + else: + logging.error(f"Connection failed: {result.stderr}") + return jsonify({'success': False, 'error': result.stderr}), 500 + + except Exception as e: + logging.error(f"Connect error: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + +@app.route('/api/disconnect', methods=['POST']) +def disconnect_vpn(): + """Disconnect VPN""" + try: + result = subprocess.run(['wg-quick', 'down', 'wg0'], + capture_output=True, text=True) + + VPN_STATUS['start_time'] = None + VPN_STATUS['connected'] = False + VPN_STATUS['provider'] = None + + return jsonify({ + 'success': result.returncode == 0, + 'message': 'Disconnected - No internet (killswitch active)' + }) + + except Exception as e: + logging.error(f"Disconnect error: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + +@app.route('/api/keypair', methods=['GET']) +def generate_keypair(): + """Generate WireGuard keypair""" + try: + private_key = subprocess.check_output(['wg', 'genkey'], text=True).strip() + public_key = subprocess.check_output(['wg', 'pubkey'], input=private_key, text=True).strip() + + return jsonify({ + 'private_key': private_key, + 'public_key': public_key + }) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +if __name__ == '__main__': + # Load configuration + load_config() + + # Create directories + os.makedirs('/opt/vpn-gateway/static', exist_ok=True) + os.makedirs(PROVIDERS_DIR, exist_ok=True) + + # Start app + app.run(host='0.0.0.0', port=5000, debug=False) diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..669adfa --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,5 @@ +flask==2.3.3 +flask-cors==4.0.0 +requests==2.31.0 +gunicorn==21.2.0 +pyyaml==6.0.1 diff --git a/configs/iptables-save.conf b/configs/iptables-save.conf new file mode 100644 index 0000000..82ac93b --- /dev/null +++ b/configs/iptables-save.conf @@ -0,0 +1,54 @@ +# VPN Gateway IPTables Rules Template +# This is a template - actual rules are generated by killswitch.sh + +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT DROP [0:0] + +# Loopback +-A INPUT -i lo -j ACCEPT +-A OUTPUT -o lo -j ACCEPT + +# Established connections +-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + +# LAN (will be replaced with actual interface/network) +-A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT +-A OUTPUT -o eth0 -d 192.168.1.0/24 -j ACCEPT + +# DNS for root only (for initial VPN connection) +-A OUTPUT -p udp --dport 53 -m owner --uid-owner 0 -j ACCEPT +-A OUTPUT -p tcp --dport 53 -m owner --uid-owner 0 -j ACCEPT + +# VPN Forward +-A FORWARD -i eth0 -s 192.168.1.0/24 -j ACCEPT + +# Log dropped packets (optional) +# -A INPUT -j LOG --log-prefix "DROP-IN: " --log-level 4 +# -A OUTPUT -j LOG --log-prefix "DROP-OUT: " --log-level 4 +# -A FORWARD -j LOG --log-prefix "DROP-FWD: " --log-level 4 + +COMMIT + +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] + +# NAT will be added dynamically when VPN connects +# -A POSTROUTING -o wg0 -j MASQUERADE + +COMMIT + +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] + +COMMIT diff --git a/configs/logrotate.conf b/configs/logrotate.conf new file mode 100644 index 0000000..5976267 --- /dev/null +++ b/configs/logrotate.conf @@ -0,0 +1,30 @@ +# VPN Gateway Log Rotation +# Place in: /etc/logrotate.d/vpn-gateway + +/var/log/vpn-*.log { + daily + rotate 7 + compress + delaycompress + missingok + notifempty + create 640 root root + sharedscripts + postrotate + systemctl reload vpn-webui 2>/dev/null || true + endscript +} + +/var/log/nginx/vpn-gateway*.log { + daily + rotate 14 + compress + delaycompress + missingok + notifempty + create 640 www-data adm + sharedscripts + postrotate + systemctl reload nginx 2>/dev/null || true + endscript +} diff --git a/configs/nginx.conf b/configs/nginx.conf new file mode 100644 index 0000000..f01fc68 --- /dev/null +++ b/configs/nginx.conf @@ -0,0 +1,135 @@ +# VPN Gateway Nginx Configuration +# Place in: /etc/nginx/sites-available/vpn-gateway + +# Rate limiting zones +limit_req_zone $binary_remote_addr zone=vpn_general:10m rate=10r/s; +limit_req_zone $binary_remote_addr zone=vpn_api:10m rate=5r/s; +limit_conn_zone $binary_remote_addr zone=vpn_conn:10m; + +# Upstream backend +upstream vpn_backend { + server 127.0.0.1:5000 fail_timeout=10s; + keepalive 32; +} + +server { + listen 80; + listen [::]:80; + server_name _; + + # Access and error logs + access_log /var/log/nginx/vpn-gateway.access.log; + error_log /var/log/nginx/vpn-gateway.error.log; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:; font-src 'self' data:;" always; + + # Connection limits + limit_conn vpn_conn 10; + + # Client body size (for config uploads) + client_max_body_size 1M; + client_body_buffer_size 128k; + + # Timeouts + client_body_timeout 10s; + client_header_timeout 10s; + send_timeout 10s; + + # Root location - WebUI + location / { + limit_req zone=vpn_general burst=20 nodelay; + + proxy_pass http://vpn_backend; + proxy_http_version 1.1; + + # Headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeouts for proxy + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffering + proxy_buffering off; + proxy_request_buffering off; + } + + # API endpoints - stricter rate limiting + location /api/ { + limit_req zone=vpn_api burst=10 nodelay; + limit_conn vpn_conn 5; + + proxy_pass http://vpn_backend; + proxy_http_version 1.1; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # API specific timeouts + proxy_connect_timeout 30s; + proxy_send_timeout 30s; + proxy_read_timeout 30s; + } + + # Static files (if any) + location /static/ { + alias /opt/vpn-gateway/static/; + expires 1h; + add_header Cache-Control "public, immutable"; + } + + # Health check endpoint + location /health { + access_log off; + add_header Content-Type text/plain; + return 200 "healthy\n"; + } + + # Block sensitive paths + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # Block access to backup files + location ~ ~$ { + deny all; + } +} + +# HTTPS configuration (optional - uncomment if using SSL) +# server { +# listen 443 ssl http2; +# listen [::]:443 ssl http2; +# server_name vpn.yourdomain.com; +# +# ssl_certificate /etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/vpn.yourdomain.com/privkey.pem; +# +# # SSL configuration +# ssl_protocols TLSv1.2 TLSv1.3; +# ssl_ciphers HIGH:!aNULL:!MD5; +# ssl_prefer_server_ciphers on; +# ssl_session_cache shared:SSL:10m; +# ssl_session_timeout 10m; +# +# # HSTS +# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; +# +# # Rest of configuration same as above... +# } diff --git a/configs/systemd/vpn-auto-update.service b/configs/systemd/vpn-auto-update.service new file mode 100644 index 0000000..395c3ab --- /dev/null +++ b/configs/systemd/vpn-auto-update.service @@ -0,0 +1,12 @@ +[Unit] +Description=VPN Gateway Auto-Update Check +Documentation=https://github.com/yourusername/vpn-gateway +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/local/bin/vpn-update.sh --check-only +StandardOutput=journal +StandardError=journal diff --git a/configs/systemd/vpn-auto-update.timer b/configs/systemd/vpn-auto-update.timer new file mode 100644 index 0000000..9dcdff4 --- /dev/null +++ b/configs/systemd/vpn-auto-update.timer @@ -0,0 +1,13 @@ +[Unit] +Description=VPN Gateway Auto-Update Timer +Documentation=https://github.com/yourusername/vpn-gateway + +[Timer] +# Run daily at 3 AM +OnCalendar=daily +OnCalendar=*-*-* 03:00:00 +RandomizedDelaySec=1h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/configs/systemd/vpn-killswitch.service b/configs/systemd/vpn-killswitch.service new file mode 100644 index 0000000..7d7939f --- /dev/null +++ b/configs/systemd/vpn-killswitch.service @@ -0,0 +1,38 @@ +[Unit] +Description=VPN Killswitch - Permanent Network Protection +Documentation=https://github.com/yourusername/vpn-gateway +DefaultDependencies=no +Before=network-pre.target +Wants=network-pre.target + +# This service MUST start before networking +After=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes + +# Execute killswitch enable +ExecStart=/usr/local/bin/vpn-killswitch.sh enable + +# On reload, restart the killswitch +ExecReload=/usr/local/bin/vpn-killswitch.sh restart + +# On stop, we still keep killswitch active for security +ExecStop=/bin/echo "Killswitch remains active for security" + +# Logging +StandardOutput=journal +StandardError=journal + +# Security +User=root +Group=root + +# We want this to always succeed +SuccessExitStatus=0 1 + +[Install] +# Critical: Start at earliest possible stage +WantedBy=sysinit.target +RequiredBy=network.target diff --git a/configs/systemd/vpn-security-monitor.service b/configs/systemd/vpn-security-monitor.service new file mode 100644 index 0000000..c0cfc42 --- /dev/null +++ b/configs/systemd/vpn-security-monitor.service @@ -0,0 +1,40 @@ +[Unit] +Description=VPN Security Monitor - Continuous Protection Monitoring +Documentation=https://github.com/yourusername/vpn-gateway +After=vpn-killswitch.service network-online.target +Requires=vpn-killswitch.service +Wants=network-online.target + +[Service] +Type=simple +User=root +Group=root + +# Execute monitoring script +ExecStart=/usr/local/bin/vpn-security-monitor.sh + +# Restart policy +Restart=always +RestartSec=30 +StartLimitInterval=300 +StartLimitBurst=5 + +# Logging +StandardOutput=journal +StandardError=journal + +# Resource limits +CPUQuota=10% +MemoryLimit=100M + +# Security +NoNewPrivileges=true +PrivateTmp=true + +# Kill settings +KillMode=process +KillSignal=SIGTERM +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/configs/systemd/vpn-webui.service b/configs/systemd/vpn-webui.service new file mode 100644 index 0000000..2b8ffac --- /dev/null +++ b/configs/systemd/vpn-webui.service @@ -0,0 +1,60 @@ +[Unit] +Description=VPN Gateway WebUI Service +Documentation=https://github.com/yourusername/vpn-gateway +After=network-online.target vpn-killswitch.service +Wants=network-online.target +Requires=vpn-killswitch.service + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/opt/vpn-gateway + +# Environment +Environment="PATH=/opt/vpn-gateway/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +Environment="PYTHONPATH=/opt/vpn-gateway" +Environment="FLASK_APP=app.py" +Environment="FLASK_ENV=production" + +# Pre-start delay to ensure network is ready +ExecStartPre=/bin/bash -c 'sleep 5' + +# Start command with gunicorn +ExecStart=/opt/vpn-gateway/venv/bin/gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --threads 4 \ + --worker-class sync \ + --worker-connections 1000 \ + --max-requests 1000 \ + --max-requests-jitter 50 \ + --timeout 120 \ + --keepalive 5 \ + --access-logfile /var/log/vpn-gateway-access.log \ + --error-logfile /var/log/vpn-gateway-error.log \ + --log-level info \ + --capture-output \ + app:app + +# Restart policy +Restart=always +RestartSec=10 +StartLimitInterval=60 +StartLimitBurst=3 + +# Security settings +NoNewPrivileges=true +PrivateTmp=true + +# Resource limits +LimitNOFILE=65536 +LimitNPROC=4096 + +# Kill settings +KillMode=mixed +KillSignal=SIGTERM +TimeoutStopSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/create-configs-docs.sh b/create-configs-docs.sh new file mode 100755 index 0000000..785cd08 --- /dev/null +++ b/create-configs-docs.sh @@ -0,0 +1,2514 @@ +#!/bin/bash + +############################################################# +# CONFIG FILES # +############################################################# + +# Create configs directory +mkdir -p configs/systemd + +############################################################# +# configs/nginx.conf +############################################################# +cat > configs/nginx.conf << 'EOFNGINX' +# VPN Gateway Nginx Configuration +# Place in: /etc/nginx/sites-available/vpn-gateway + +# Rate limiting zones +limit_req_zone $binary_remote_addr zone=vpn_general:10m rate=10r/s; +limit_req_zone $binary_remote_addr zone=vpn_api:10m rate=5r/s; +limit_conn_zone $binary_remote_addr zone=vpn_conn:10m; + +# Upstream backend +upstream vpn_backend { + server 127.0.0.1:5000 fail_timeout=10s; + keepalive 32; +} + +server { + listen 80; + listen [::]:80; + server_name _; + + # Access and error logs + access_log /var/log/nginx/vpn-gateway.access.log; + error_log /var/log/nginx/vpn-gateway.error.log; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:; font-src 'self' data:;" always; + + # Connection limits + limit_conn vpn_conn 10; + + # Client body size (for config uploads) + client_max_body_size 1M; + client_body_buffer_size 128k; + + # Timeouts + client_body_timeout 10s; + client_header_timeout 10s; + send_timeout 10s; + + # Root location - WebUI + location / { + limit_req zone=vpn_general burst=20 nodelay; + + proxy_pass http://vpn_backend; + proxy_http_version 1.1; + + # Headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeouts for proxy + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffering + proxy_buffering off; + proxy_request_buffering off; + } + + # API endpoints - stricter rate limiting + location /api/ { + limit_req zone=vpn_api burst=10 nodelay; + limit_conn vpn_conn 5; + + proxy_pass http://vpn_backend; + proxy_http_version 1.1; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # API specific timeouts + proxy_connect_timeout 30s; + proxy_send_timeout 30s; + proxy_read_timeout 30s; + } + + # Static files (if any) + location /static/ { + alias /opt/vpn-gateway/static/; + expires 1h; + add_header Cache-Control "public, immutable"; + } + + # Health check endpoint + location /health { + access_log off; + add_header Content-Type text/plain; + return 200 "healthy\n"; + } + + # Block sensitive paths + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # Block access to backup files + location ~ ~$ { + deny all; + } +} + +# HTTPS configuration (optional - uncomment if using SSL) +# server { +# listen 443 ssl http2; +# listen [::]:443 ssl http2; +# server_name vpn.yourdomain.com; +# +# ssl_certificate /etc/letsencrypt/live/vpn.yourdomain.com/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/vpn.yourdomain.com/privkey.pem; +# +# # SSL configuration +# ssl_protocols TLSv1.2 TLSv1.3; +# ssl_ciphers HIGH:!aNULL:!MD5; +# ssl_prefer_server_ciphers on; +# ssl_session_cache shared:SSL:10m; +# ssl_session_timeout 10m; +# +# # HSTS +# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; +# +# # Rest of configuration same as above... +# } +EOFNGINX + +############################################################# +# configs/systemd/vpn-webui.service +############################################################# +cat > configs/systemd/vpn-webui.service << 'EOFWEBUI' +[Unit] +Description=VPN Gateway WebUI Service +Documentation=https://github.com/yourusername/vpn-gateway +After=network-online.target vpn-killswitch.service +Wants=network-online.target +Requires=vpn-killswitch.service + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/opt/vpn-gateway + +# Environment +Environment="PATH=/opt/vpn-gateway/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +Environment="PYTHONPATH=/opt/vpn-gateway" +Environment="FLASK_APP=app.py" +Environment="FLASK_ENV=production" + +# Pre-start delay to ensure network is ready +ExecStartPre=/bin/bash -c 'sleep 5' + +# Start command with gunicorn +ExecStart=/opt/vpn-gateway/venv/bin/gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --threads 4 \ + --worker-class sync \ + --worker-connections 1000 \ + --max-requests 1000 \ + --max-requests-jitter 50 \ + --timeout 120 \ + --keepalive 5 \ + --access-logfile /var/log/vpn-gateway-access.log \ + --error-logfile /var/log/vpn-gateway-error.log \ + --log-level info \ + --capture-output \ + app:app + +# Restart policy +Restart=always +RestartSec=10 +StartLimitInterval=60 +StartLimitBurst=3 + +# Security settings +NoNewPrivileges=true +PrivateTmp=true + +# Resource limits +LimitNOFILE=65536 +LimitNPROC=4096 + +# Kill settings +KillMode=mixed +KillSignal=SIGTERM +TimeoutStopSec=30 + +[Install] +WantedBy=multi-user.target +EOFWEBUI + +############################################################# +# configs/systemd/vpn-killswitch.service +############################################################# +cat > configs/systemd/vpn-killswitch.service << 'EOFKILLSWITCH' +[Unit] +Description=VPN Killswitch - Permanent Network Protection +Documentation=https://github.com/yourusername/vpn-gateway +DefaultDependencies=no +Before=network-pre.target +Wants=network-pre.target + +# This service MUST start before networking +After=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes + +# Execute killswitch enable +ExecStart=/usr/local/bin/vpn-killswitch.sh enable + +# On reload, restart the killswitch +ExecReload=/usr/local/bin/vpn-killswitch.sh restart + +# On stop, we still keep killswitch active for security +ExecStop=/bin/echo "Killswitch remains active for security" + +# Logging +StandardOutput=journal +StandardError=journal + +# Security +User=root +Group=root + +# We want this to always succeed +SuccessExitStatus=0 1 + +[Install] +# Critical: Start at earliest possible stage +WantedBy=sysinit.target +RequiredBy=network.target +EOFKILLSWITCH + +############################################################# +# configs/systemd/vpn-security-monitor.service +############################################################# +cat > configs/systemd/vpn-security-monitor.service << 'EOFSECMON' +[Unit] +Description=VPN Security Monitor - Continuous Protection Monitoring +Documentation=https://github.com/yourusername/vpn-gateway +After=vpn-killswitch.service network-online.target +Requires=vpn-killswitch.service +Wants=network-online.target + +[Service] +Type=simple +User=root +Group=root + +# Execute monitoring script +ExecStart=/usr/local/bin/vpn-security-monitor.sh + +# Restart policy +Restart=always +RestartSec=30 +StartLimitInterval=300 +StartLimitBurst=5 + +# Logging +StandardOutput=journal +StandardError=journal + +# Resource limits +CPUQuota=10% +MemoryLimit=100M + +# Security +NoNewPrivileges=true +PrivateTmp=true + +# Kill settings +KillMode=process +KillSignal=SIGTERM +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target +EOFSECMON + +############################################################# +# configs/systemd/vpn-auto-update.service (optional) +############################################################# +cat > configs/systemd/vpn-auto-update.service << 'EOFUPDATE' +[Unit] +Description=VPN Gateway Auto-Update Check +Documentation=https://github.com/yourusername/vpn-gateway +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/local/bin/vpn-update.sh --check-only +StandardOutput=journal +StandardError=journal +EOFUPDATE + +############################################################# +# configs/systemd/vpn-auto-update.timer (optional) +############################################################# +cat > configs/systemd/vpn-auto-update.timer << 'EOFTIMER' +[Unit] +Description=VPN Gateway Auto-Update Timer +Documentation=https://github.com/yourusername/vpn-gateway + +[Timer] +# Run daily at 3 AM +OnCalendar=daily +OnCalendar=*-*-* 03:00:00 +RandomizedDelaySec=1h +Persistent=true + +[Install] +WantedBy=timers.target +EOFTIMER + +############################################################# +# configs/logrotate.conf +############################################################# +cat > configs/logrotate.conf << 'EOFLOGROTATE' +# VPN Gateway Log Rotation +# Place in: /etc/logrotate.d/vpn-gateway + +/var/log/vpn-*.log { + daily + rotate 7 + compress + delaycompress + missingok + notifempty + create 640 root root + sharedscripts + postrotate + systemctl reload vpn-webui 2>/dev/null || true + endscript +} + +/var/log/nginx/vpn-gateway*.log { + daily + rotate 14 + compress + delaycompress + missingok + notifempty + create 640 www-data adm + sharedscripts + postrotate + systemctl reload nginx 2>/dev/null || true + endscript +} +EOFLOGROTATE + +############################################################# +# configs/iptables-save.conf +############################################################# +cat > configs/iptables-save.conf << 'EOFIPTABLES' +# VPN Gateway IPTables Rules Template +# This is a template - actual rules are generated by killswitch.sh + +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT DROP [0:0] + +# Loopback +-A INPUT -i lo -j ACCEPT +-A OUTPUT -o lo -j ACCEPT + +# Established connections +-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + +# LAN (will be replaced with actual interface/network) +-A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT +-A OUTPUT -o eth0 -d 192.168.1.0/24 -j ACCEPT + +# DNS for root only (for initial VPN connection) +-A OUTPUT -p udp --dport 53 -m owner --uid-owner 0 -j ACCEPT +-A OUTPUT -p tcp --dport 53 -m owner --uid-owner 0 -j ACCEPT + +# VPN Forward +-A FORWARD -i eth0 -s 192.168.1.0/24 -j ACCEPT + +# Log dropped packets (optional) +# -A INPUT -j LOG --log-prefix "DROP-IN: " --log-level 4 +# -A OUTPUT -j LOG --log-prefix "DROP-OUT: " --log-level 4 +# -A FORWARD -j LOG --log-prefix "DROP-FWD: " --log-level 4 + +COMMIT + +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] + +# NAT will be added dynamically when VPN connects +# -A POSTROUTING -o wg0 -j MASQUERADE + +COMMIT + +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] + +COMMIT +EOFIPTABLES + +############################################################# +# DOCUMENTATION FILES # +############################################################# + +# Create docs directory +mkdir -p docs + +############################################################# +# docs/README.md +############################################################# +cat > docs/README.md << 'EOFDOCSREADME' +# VPN Gateway Documentation + +## Overview + +This documentation covers the VPN Gateway multi-provider system with permanent killswitch protection. + +## Contents + +- [Quick Start Guide](QUICKSTART.md) - Get up and running in minutes +- [Provider Configuration](PROVIDERS.md) - Detailed provider setup +- [Security Documentation](SECURITY.md) - Security features and best practices +- [API Reference](API.md) - WebUI API endpoints +- [Troubleshooting](TROUBLESHOOTING.md) - Common issues and solutions +- [FAQ](FAQ.md) - Frequently asked questions + +## Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Client Devices β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ VPN Gateway Container β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ WebUI (Port 80/5000) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Flask Backend (Python) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ WireGuard Interface (wg0) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Killswitch (iptables) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ VPN Provider β”‚ + β”‚ β€’ Mullvad β”‚ + β”‚ β€’ Custom Server β”‚ + β”‚ β€’ Imported Configβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Key Components + +### 1. Killswitch +- Permanent firewall rules +- Blocks all non-VPN traffic +- Cannot be disabled via UI + +### 2. WebUI +- Modern responsive interface +- Real-time status monitoring +- Multi-provider support + +### 3. Backend +- Flask-based API +- Provider management +- Connection handling + +### 4. Security Monitor +- Continuous monitoring +- Leak detection +- Auto-recovery + +## Support + +- GitHub Issues: https://github.com/yourusername/vpn-gateway/issues +- Documentation: https://github.com/yourusername/vpn-gateway/wiki +EOFDOCSREADME + +############################################################# +# docs/QUICKSTART.md +############################################################# +cat > docs/QUICKSTART.md << 'EOFQUICKSTART' +# Quick Start Guide + +## Prerequisites + +- LXC Container with Ubuntu/Debian +- Root access +- Internet connection for initial setup + +## Installation + +### 1. One-Line Install + +```bash +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/main/install.sh | bash +``` + +### 2. Manual Install + +```bash +# Clone repository +git clone https://github.com/yourusername/vpn-gateway.git +cd vpn-gateway + +# Run installer +sudo ./install.sh +``` + +## Initial Setup + +### Step 1: Network Detection + +The installer will auto-detect your network configuration: +- Network interface (e.g., eth0) +- LAN subnet (e.g., 192.168.1.0/24) +- Container IP address + +Confirm or modify as needed. + +### Step 2: Choose Provider + +Select your VPN provider: + +#### Option 1: Mullvad VPN +``` +Select provider [1-3]: 1 +Enter your Mullvad account number: 1234567890123456 +``` + +#### Option 2: Custom WireGuard Server +``` +Select provider [1-3]: 2 +Server endpoint (IP:Port): 1.2.3.4:51820 +Server public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +``` + +#### Option 3: Import Configuration +``` +Select provider [1-3]: 3 +Path to WireGuard config: /path/to/config.conf +``` + +### Step 3: Complete Installation + +The installer will: +1. Install dependencies +2. Configure killswitch +3. Set up WebUI +4. Start services + +## Using the WebUI + +### Access the Interface + +Open your browser and navigate to: +``` +http:// +``` + +### Connect to VPN + +1. **Select Location** (Mullvad only) + - Choose country + - Choose city + - Choose server + +2. **Click Connect** + - Connection established in ~2-5 seconds + - Status indicator turns green + +3. **Verify Connection** + - Check public IP displayed + - Verify location shown + +### Disconnect from VPN + +1. Click **Disconnect** button +2. **WARNING**: No internet access after disconnect (killswitch active) + +## Client Configuration + +### Configure Your Devices + +Set on each client device: + +#### Windows +1. Network Settings β†’ IPv4 Properties +2. Default Gateway: `` +3. DNS Server: `` or `1.1.1.1` + +#### Linux +```bash +# Temporary +sudo ip route del default +sudo ip route add default via +echo "nameserver " | sudo tee /etc/resolv.conf + +# Permanent (NetworkManager) +nmcli connection modify ipv4.gateway +nmcli connection modify ipv4.dns +``` + +#### macOS +1. System Preferences β†’ Network +2. Advanced β†’ TCP/IP +3. Router: `` +4. DNS: `` + +## Quick Commands + +### Check Status +```bash +# Service status +sudo systemctl status vpn-webui + +# Connection status +curl http://localhost:5000/api/status + +# Health check +sudo /usr/local/bin/vpn-health-check.sh +``` + +### View Logs +```bash +# All logs +sudo journalctl -u vpn-webui -u vpn-killswitch -f + +# WebUI logs only +sudo journalctl -u vpn-webui -f +``` + +### Restart Services +```bash +sudo systemctl restart vpn-webui +sudo systemctl restart vpn-security-monitor +``` + +## Important Notes + +⚠️ **Killswitch Always Active** +- No internet without VPN connection +- This is intentional for security +- Local network still accessible + +⚠️ **After Disconnect** +- Internet blocked until reconnection +- WebUI remains accessible +- Connect to VPN to restore internet + +## Troubleshooting + +### WebUI Not Accessible +```bash +# Check if service is running +sudo systemctl status vpn-webui + +# Check if port is listening +sudo netstat -tlnp | grep 5000 + +# Restart service +sudo systemctl restart vpn-webui +``` + +### No Internet After Connect +```bash +# Check VPN status +sudo wg show + +# Check killswitch +sudo iptables -L -n -v + +# Check DNS +nslookup google.com +``` + +### Can't Connect to VPN +```bash +# Check logs +sudo journalctl -u vpn-webui -n 50 + +# Test killswitch +sudo /usr/local/bin/vpn-killswitch.sh verify + +# Manual connection test +sudo wg-quick up wg0 +``` + +## Next Steps + +- Read [Provider Configuration](PROVIDERS.md) for advanced setup +- Review [Security Documentation](SECURITY.md) for security features +- See [FAQ](FAQ.md) for common questions +EOFQUICKSTART + +############################################################# +# docs/PROVIDERS.md +############################################################# +cat > docs/PROVIDERS.md << 'EOFPROVIDERS' +# VPN Provider Configuration Guide + +## Overview + +The VPN Gateway supports three types of providers: +1. **Mullvad VPN** - Commercial VPN service +2. **Custom WireGuard** - Your own VPN server +3. **Import Config** - Existing WireGuard configurations + +## Mullvad VPN + +### Setup + +1. Get a Mullvad account at https://mullvad.net +2. Note your 16-digit account number +3. During installation, select "Mullvad" and enter your account number + +### Features + +- Automatic server list updates +- 40+ countries available +- Built-in DNS leak protection +- No logging policy + +### Server Selection + +Servers are organized by: +- **Country** (Sweden, Germany, USA, etc.) +- **City** (Stockholm, Berlin, New York, etc.) +- **Server** (se-sto-wg-001, de-ber-wg-002, etc.) + +### Configuration + +The system automatically: +- Fetches current server list +- Generates WireGuard keys +- Configures DNS (100.64.0.1) +- Sets up kill switch + +## Custom WireGuard Server + +### Prerequisites + +You need: +- A VPS or dedicated server +- WireGuard installed on the server +- Server public key +- Open port (usually 51820) + +### Server Setup (VPS Side) + +#### 1. Install WireGuard +```bash +# Ubuntu/Debian +sudo apt update +sudo apt install wireguard + +# CentOS/RHEL +sudo yum install wireguard-tools +``` + +#### 2. Generate Keys +```bash +cd /etc/wireguard +wg genkey | tee server_private.key | wg pubkey > server_public.key +``` + +#### 3. Configure Server +```bash +cat > /etc/wireguard/wg0.conf << EOF +[Interface] +PrivateKey = $(cat server_private.key) +Address = 10.0.0.1/24 +ListenPort = 51820 + +# Enable IP forwarding +PostUp = sysctl -w net.ipv4.ip_forward=1 +PostUp = iptables -A FORWARD -i wg0 -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -D FORWARD -i wg0 -j ACCEPT +PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + +# Peer (VPN Gateway) +[Peer] +PublicKey = +AllowedIPs = 10.0.0.2/32 +EOF +``` + +#### 4. Start WireGuard +```bash +sudo systemctl enable wg-quick@wg0 +sudo systemctl start wg-quick@wg0 +``` + +### Gateway Setup (Client Side) + +During installation, provide: +- **Endpoint**: Your server's IP:Port (e.g., 1.2.3.4:51820) +- **Server Public Key**: From server_public.key +- **Client IP**: Usually 10.0.0.2/32 +- **DNS**: 1.1.1.1,1.0.0.1 or your preferred DNS + +### Adding Multiple Servers + +Via WebUI: +1. Go to "Custom Server" tab +2. Click "Add New Server" +3. Fill in server details +4. Save configuration + +Via API: +```bash +curl -X POST http://gateway-ip/api/custom/add \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-vps-us", + "endpoint": "us.example.com:51820", + "public_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "location": "United States" + }' +``` + +## Import Existing Configuration + +### Supported Formats + +- Standard WireGuard .conf files +- Configs from any WireGuard provider +- Custom peer configurations + +### Import Methods + +#### Via WebUI +1. Select "Import Config" tab +2. Choose file or paste configuration +3. Provide a name for the config +4. Click "Import" + +#### Via CLI +```bash +# Copy config to gateway +scp myconfig.conf root@gateway-ip:/tmp/ + +# Import via API +curl -X POST http://gateway-ip/api/import \ + -H "Content-Type: application/json" \ + -d '{ + "name": "imported-config", + "config": "'"$(cat /tmp/myconfig.conf)"'" + }' +``` + +### Automatic Modifications + +The system automatically: +- Adds killswitch rules if missing +- Preserves original settings +- Validates configuration syntax + +### Example Configuration + +```ini +[Interface] +PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +Address = 10.8.0.2/32 +DNS = 1.1.1.1 + +[Peer] +PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +AllowedIPs = 0.0.0.0/0 +Endpoint = vpn.example.com:51820 +PersistentKeepalive = 25 +``` + +## Provider Switching + +### Via WebUI + +1. Click on provider tabs +2. System automatically switches backend +3. Previous provider settings are preserved + +### Via API + +```bash +# Switch to Mullvad +curl -X POST http://gateway-ip/api/provider/mullvad + +# Switch to Custom +curl -X POST http://gateway-ip/api/provider/custom + +# Switch to Imported +curl -X POST http://gateway-ip/api/provider/imported +``` + +## Advanced Configuration + +### Split Tunneling + +For custom servers, modify AllowedIPs: +```ini +# Route only specific subnets through VPN +AllowedIPs = 10.0.0.0/8, 192.168.0.0/16 + +# Route everything except local network +AllowedIPs = 0.0.0.0/1, 128.0.0.0/1 +``` + +### Multiple Peers (Failover) + +```ini +[Peer] +# Primary server +PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +AllowedIPs = 0.0.0.0/0 +Endpoint = primary.example.com:51820 + +[Peer] +# Backup server +PublicKey = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy= +AllowedIPs = 0.0.0.0/0 +Endpoint = backup.example.com:51820 +``` + +### Custom DNS + +Modify DNS in the configuration: +```ini +# CloudFlare +DNS = 1.1.1.1, 1.0.0.1 + +# Quad9 +DNS = 9.9.9.9, 149.112.112.112 + +# Custom/Local +DNS = 192.168.1.1 +``` + +## Performance Optimization + +### MTU Settings + +For optimal performance: +```ini +[Interface] +MTU = 1420 # Default, works for most connections +# MTU = 1380 # For problematic connections +# MTU = 1280 # Maximum compatibility +``` + +### Persistent Keepalive + +Adjust based on your needs: +```ini +# For stable connections +PersistentKeepalive = 25 + +# For NAT/firewall traversal +PersistentKeepalive = 10 + +# Disable for on-demand +# PersistentKeepalive = 0 +``` + +## Troubleshooting Providers + +### Mullvad Issues + +```bash +# Check account status +curl https://api.mullvad.net/www/accounts// + +# Test server connectivity +ping -c 1 + +# Verify WireGuard keys +wg show wg0 public-key +``` + +### Custom Server Issues + +```bash +# Test connectivity +nc -zv 51820 + +# Check server logs (on VPS) +sudo journalctl -u wg-quick@wg0 -f + +# Verify keys match +echo "" | base64 -d | wc -c # Should be 32 +``` + +### Import Issues + +```bash +# Validate config syntax +wg-quick strip /path/to/config.conf + +# Test config manually +sudo wg-quick up /tmp/test.conf +sudo wg-quick down /tmp/test.conf +``` + +## Security Considerations + +### Key Management + +- Never share private keys +- Rotate keys periodically +- Use unique keys per device/gateway + +### Server Hardening + +For custom servers: +```bash +# Firewall rules +ufw allow 51820/udp +ufw allow from 10.0.0.0/24 + +# Disable password auth +sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config + +# Enable automatic updates +apt install unattended-upgrades +``` + +### Monitoring + +```bash +# Connection status +wg show + +# Traffic statistics +wg show wg0 transfer + +# Active connections +netstat -tunlp | grep 51820 +``` +EOFPROVIDERS + +############################################################# +# docs/SECURITY.md +############################################################# +cat > docs/SECURITY.md << 'EOFSECURITY' +# Security Documentation + +## Overview + +The VPN Gateway implements multiple layers of security to ensure zero-leak protection and maintain privacy. + +## Core Security Features + +### 1. Permanent Killswitch + +The killswitch is the primary security mechanism that prevents any traffic leaks. + +#### Implementation + +- **Firewall Rules**: Default DROP policy for all chains +- **Boot Protection**: Activates before network initialization +- **Cannot be Disabled**: No UI or API endpoint to disable +- **Continuous Monitoring**: Verified every 10 seconds + +#### Technical Details + +```bash +# Default policies +iptables -P INPUT DROP +iptables -P FORWARD DROP +iptables -P OUTPUT DROP + +# Only allowed traffic: +# - Loopback (system operations) +# - LAN subnet (WebUI access) +# - Established connections +# - VPN tunnel (when active) +``` + +### 2. DNS Leak Protection + +#### Mechanisms + +1. **Forced VPN DNS**: All DNS queries routed through VPN +2. **System DNS Override**: /etc/resolv.conf locked +3. **IPv6 Disabled**: Prevents IPv6 DNS leaks +4. **DNS Filtering**: Only root can make DNS queries for VPN connection + +#### Configuration + +```bash +# DNS through VPN only +iptables -A OUTPUT -p udp --dport 53 -m owner --uid-owner root -j ACCEPT +iptables -A OUTPUT -p tcp --dport 53 -m owner --uid-owner root -j ACCEPT + +# Block all other DNS +iptables -A OUTPUT -p udp --dport 53 -j DROP +iptables -A OUTPUT -p tcp --dport 53 -j DROP +``` + +### 3. IPv6 Protection + +Complete IPv6 blocking to prevent leaks: + +```bash +# IPv6 firewall +ip6tables -P INPUT DROP +ip6tables -P FORWARD DROP +ip6tables -P OUTPUT DROP + +# Kernel level +sysctl -w net.ipv6.conf.all.disable_ipv6=1 +sysctl -w net.ipv6.conf.default.disable_ipv6=1 +``` + +### 4. Security Monitor + +Continuous monitoring daemon that: +- Verifies killswitch every 10 seconds +- Detects potential leaks +- Auto-recovers from failures +- Logs security events + +## Threat Model + +### Protected Against + +βœ… **IP Leaks** +- Killswitch blocks all non-VPN traffic +- No traffic possible without active tunnel + +βœ… **DNS Leaks** +- All DNS through VPN +- System DNS locked +- IPv6 DNS blocked + +βœ… **WebRTC Leaks** +- Blocked at firewall level +- No direct peer connections + +βœ… **IPv6 Leaks** +- IPv6 completely disabled +- Both firewall and kernel level + +βœ… **Connection Drops** +- Killswitch remains active +- No traffic during reconnection +- Auto-recovery available + +βœ… **Malicious Applications** +- Cannot bypass firewall rules +- All traffic subject to killswitch + +### Not Protected Against + +❌ **Compromised Container** +- If attacker gains root access +- Can modify firewall rules + +❌ **Host System Compromise** +- Container isolation breach +- Hypervisor vulnerabilities + +❌ **Traffic Analysis** +- VPN traffic patterns visible +- Timing correlation attacks + +❌ **VPN Provider Compromise** +- Malicious VPN server +- Provider logging (choose carefully) + +## Security Best Practices + +### 1. Installation Security + +```bash +# Verify installer integrity +sha256sum install.sh +# Compare with published hash + +# Review script before execution +less install.sh + +# Run with specific version +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/v1.0.0/install.sh | bash +``` + +### 2. Access Control + +#### WebUI Protection + +```nginx +# Restrict WebUI access to LAN only +location / { + allow 192.168.1.0/24; + deny all; + # ... proxy settings +} +``` + +#### SSH Hardening + +```bash +# Disable password authentication +PasswordAuthentication no + +# Key-only access +PubkeyAuthentication yes + +# Restrict to specific IPs +AllowUsers root@192.168.1.0/24 +``` + +### 3. Key Management + +#### WireGuard Keys + +```bash +# Generate new keys periodically +wg genkey | tee privatekey | wg pubkey > publickey + +# Secure storage +chmod 600 /etc/wireguard/*.key + +# Never share private keys +# Unique keys per gateway +``` + +#### Rotation Schedule + +- **Private Keys**: Every 3-6 months +- **Preshared Keys**: Every 1-3 months +- **API Keys**: Every 30 days + +### 4. Monitoring + +#### Security Logs + +```bash +# Monitor security events +journalctl -u vpn-security-monitor -f + +# Check for failures +grep "ALERT\|ERROR" /var/log/vpn-security-monitor.log + +# Audit firewall drops +iptables -L -n -v | grep DROP +``` + +#### Leak Testing + +```bash +# Regular leak tests +curl https://ipleak.net/json/ +curl https://am.i.mullvad.net/json + +# DNS leak test +nslookup example.com +dig example.com +``` + +### 5. Updates + +#### Security Updates + +```bash +# System updates (through VPN) +apt update && apt upgrade + +# VPN Gateway updates +/usr/local/bin/vpn-update.sh + +# Check for security advisories +``` + +#### Automatic Updates + +```bash +# Enable unattended upgrades +apt install unattended-upgrades +dpkg-reconfigure -plow unattended-upgrades +``` + +## Incident Response + +### 1. Leak Detected + +If a leak is detected: + +1. **Immediate Action** + ```bash + # Re-enable killswitch + /usr/local/bin/vpn-killswitch.sh enable + + # Disconnect VPN + wg-quick down wg0 + ``` + +2. **Investigation** + ```bash + # Check logs + journalctl -u vpn-security-monitor -n 100 + + # Verify firewall rules + iptables -L -n -v + ``` + +3. **Recovery** + ```bash + # Restart security services + systemctl restart vpn-killswitch + systemctl restart vpn-security-monitor + ``` + +### 2. Suspicious Activity + +Signs of compromise: +- Unexpected firewall rule changes +- Unknown processes with network access +- Unusual CPU/memory usage +- Modified system files + +Response: +```bash +# Check processes +netstat -tulpn +ps aux | grep -v grep | grep wg + +# Check file integrity +debsums -c +find /etc -type f -mtime -1 + +# Review auth logs +grep "Failed\|Invalid" /var/log/auth.log +``` + +### 3. Emergency Shutdown + +If immediate isolation needed: + +```bash +# Block ALL network traffic +iptables -P INPUT DROP +iptables -P OUTPUT DROP +iptables -P FORWARD DROP +iptables -F + +# Stop services +systemctl stop vpn-webui +systemctl stop wg-quick@wg0 + +# Preserve evidence +tar czf /tmp/evidence-$(date +%s).tar.gz \ + /var/log \ + /etc/wireguard \ + /opt/vpn-gateway/logs +``` + +## Security Hardening + +### 1. Container Hardening + +```bash +# Limit capabilities +lxc config set security.nesting false +lxc config set security.privileged false + +# Resource limits +lxc config set limits.memory 512MB +lxc config set limits.cpu 1 +``` + +### 2. Network Hardening + +```bash +# Rate limiting +iptables -A INPUT -p tcp --dport 5000 \ + -m conntrack --ctstate NEW \ + -m limit --limit 10/min --limit-burst 5 \ + -j ACCEPT + +# SYN flood protection +echo 1 > /proc/sys/net/ipv4/tcp_syncookies +echo 2048 > /proc/sys/net/ipv4/tcp_max_syn_backlog +``` + +### 3. Application Hardening + +```python +# Flask security headers +from flask import Flask +from flask_talisman import Talisman + +app = Flask(__name__) +Talisman(app, + force_https=False, # Handle at reverse proxy + strict_transport_security=True, + content_security_policy={ + 'default-src': "'self'" + } +) +``` + +## Compliance + +### GDPR Compliance + +- No personal data logging +- User control over data +- Right to deletion +- Transparent processing + +### Security Standards + +- CIS Benchmarks compliance +- NIST framework alignment +- Zero-trust architecture +- Defense in depth + +## Security Checklist + +### Daily +- [ ] Check service status +- [ ] Review security logs +- [ ] Verify killswitch active + +### Weekly +- [ ] Run leak tests +- [ ] Check for updates +- [ ] Review firewall rules + +### Monthly +- [ ] Rotate keys +- [ ] Audit access logs +- [ ] Update documentation + +### Quarterly +- [ ] Security assessment +- [ ] Penetration testing +- [ ] Disaster recovery test + +## Contact + +For security issues: +- **Email**: security@yourdomain.com +- **PGP Key**: [Public key] +- **Response Time**: < 24 hours for critical issues + +Please report security vulnerabilities responsibly. +EOFSECURITY + +############################################################# +# docs/FAQ.md +############################################################# +cat > docs/FAQ.md << 'EOFFAQ' +# Frequently Asked Questions + +## General Questions + +### Q: What is the VPN Gateway? +**A:** It's a secure VPN gateway solution that routes all network traffic through a VPN connection with a permanent killswitch to prevent leaks. + +### Q: Which VPN providers are supported? +**A:** +- Mullvad VPN (commercial service) +- Custom WireGuard servers (your own VPS) +- Any imported WireGuard configuration + +### Q: Can I use this with OpenVPN? +**A:** No, this gateway only supports WireGuard protocol for better performance and security. + +### Q: Is this free to use? +**A:** The software is free and open source. You need to provide your own VPN service (Mullvad account or custom server). + +## Installation + +### Q: What are the system requirements? +**A:** +- LXC container or Linux system +- Ubuntu 20.04+ or Debian 11+ +- 512MB RAM minimum +- 1GB disk space +- Root access + +### Q: Can I install on a Raspberry Pi? +**A:** Yes, as long as it runs a supported OS and has WireGuard kernel module support. + +### Q: Does it work in Docker? +**A:** It requires privileged mode and NET_ADMIN capability. LXC is recommended over Docker. + +### Q: Can I install on a VPS? +**A:** Yes, but be aware that the killswitch will block all traffic except through VPN, which might lock you out via SSH. + +## Usage + +### Q: No internet after disconnecting VPN? +**A:** This is correct behavior! The killswitch blocks all internet traffic when VPN is not connected. This prevents leaks. + +### Q: Can I disable the killswitch? +**A:** No, the killswitch cannot be disabled through normal means. This is a security feature. + +### Q: How do I access the WebUI? +**A:** Navigate to `http://` in your browser. The WebUI is always accessible from the local network. + +### Q: Can I use multiple VPN connections simultaneously? +**A:** No, only one VPN connection is active at a time. You can switch between servers/providers via the WebUI. + +## Security + +### Q: Is this really secure? +**A:** Yes, when properly configured: +- Permanent killswitch prevents leaks +- DNS leak protection enabled +- IPv6 completely disabled +- Continuous security monitoring + +### Q: What about WebRTC leaks? +**A:** WebRTC leaks are prevented at the firewall level. No direct peer connections are possible. + +### Q: Can applications bypass the VPN? +**A:** No, all traffic is forced through the VPN tunnel or blocked by the killswitch. + +### Q: Is my traffic logged? +**A:** The gateway itself doesn't log traffic. Logging depends on your VPN provider's policy. + +## Troubleshooting + +### Q: WebUI is not accessible +**A:** +```bash +# Check if service is running +sudo systemctl status vpn-webui + +# Restart the service +sudo systemctl restart vpn-webui + +# Check if port is open +sudo netstat -tlnp | grep 5000 +``` + +### Q: VPN won't connect +**A:** +1. Check your credentials/keys are correct +2. Verify the server is reachable +3. Check firewall allows outbound UDP 51820 +4. Review logs: `sudo journalctl -u vpn-webui -n 50` + +### Q: DNS not working +**A:** +```bash +# Check DNS configuration +cat /etc/resolv.conf + +# Test DNS resolution +nslookup google.com + +# Restart VPN connection +sudo wg-quick down wg0 +sudo wg-quick up wg0 +``` + +### Q: High CPU usage +**A:** +- Check security monitor: `sudo systemctl status vpn-security-monitor` +- Reduce monitoring frequency if needed +- Check for packet loops in firewall rules + +## Configuration + +### Q: How do I add a custom DNS server? +**A:** Edit the WireGuard configuration: +```bash +sudo nano /etc/wireguard/wg0.conf +# Change DNS = line to your preferred servers +``` + +### Q: Can I change the WebUI port? +**A:** Yes, edit the systemd service: +```bash +sudo nano /etc/systemd/system/vpn-webui.service +# Change --bind 0.0.0.0:5000 to your desired port +sudo systemctl daemon-reload +sudo systemctl restart vpn-webui +``` + +### Q: How do I backup my configuration? +**A:** +```bash +sudo tar czf vpn-backup.tar.gz \ + /opt/vpn-gateway \ + /etc/wireguard \ + /etc/systemd/system/vpn-*.service +``` + +### Q: How do I enable auto-reconnect? +**A:** Auto-reconnect is handled by the security monitor. Ensure it's running: +```bash +sudo systemctl enable vpn-security-monitor +sudo systemctl start vpn-security-monitor +``` + +## Advanced + +### Q: Can I use split tunneling? +**A:** Yes, for custom servers. Modify the AllowedIPs in your WireGuard config: +```ini +# Only specific subnets through VPN +AllowedIPs = 10.0.0.0/8, 172.16.0.0/12 +``` + +### Q: How do I set up failover? +**A:** Add multiple peers in the WireGuard configuration: +```ini +[Peer] +# Primary +PublicKey = xxx... +Endpoint = primary.example.com:51820 + +[Peer] +# Backup +PublicKey = yyy... +Endpoint = backup.example.com:51820 +``` + +### Q: Can I monitor traffic statistics? +**A:** +```bash +# WireGuard statistics +wg show wg0 transfer + +# Network statistics +vnstat -i wg0 + +# Real-time monitoring +iftop -i wg0 +``` + +### Q: How do I integrate with existing infrastructure? +**A:** +- Use as default gateway for network segments +- Configure via DHCP options +- Set up policy-based routing for specific clients + +## Updates + +### Q: How do I update the VPN Gateway? +**A:** +```bash +sudo /usr/local/bin/vpn-update.sh +``` + +### Q: Will updates break my configuration? +**A:** No, updates preserve your configuration. Backups are created automatically. + +### Q: How do I check for updates? +**A:** +```bash +# Check current version +cat /opt/vpn-gateway/version + +# Check for updates +curl -s https://raw.githubusercontent.com/yourusername/vpn-gateway/main/version +``` + +## Support + +### Q: Where can I get help? +**A:** +- GitHub Issues: https://github.com/yourusername/vpn-gateway/issues +- Documentation: https://github.com/yourusername/vpn-gateway/wiki +- Community Forum: [Link to forum] + +### Q: How do I report a bug? +**A:** Open an issue on GitHub with: +- System information +- Error messages +- Steps to reproduce +- Relevant logs + +### Q: Can I contribute? +**A:** Yes! Contributions are welcome: +- Submit pull requests +- Report bugs +- Improve documentation +- Share your setup + +## Legal + +### Q: Is this legal to use? +**A:** Yes, but check your local laws regarding VPN usage. Some countries restrict VPN use. + +### Q: Can I use this commercially? +**A:** Yes, under the MIT license terms. See LICENSE file for details. + +### Q: What about warranty? +**A:** This software is provided "as is" without warranty. Use at your own risk. +EOFFAQ + +############################################################# +# docs/TROUBLESHOOTING.md +############################################################# +cat > docs/TROUBLESHOOTING.md << 'EOFTROUBLE' +# Troubleshooting Guide + +## Common Issues and Solutions + +### Installation Issues + +#### Problem: Installation fails with dependency errors +```bash +E: Unable to locate package wireguard +``` + +**Solution:** +```bash +# Update package lists +sudo apt update + +# Enable backports (Debian) +echo "deb http://deb.debian.org/debian $(lsb_release -cs)-backports main" | \ + sudo tee /etc/apt/sources.list.d/backports.list +sudo apt update + +# Install kernel headers +sudo apt install linux-headers-$(uname -r) + +# Retry installation +sudo ./install.sh +``` + +#### Problem: WireGuard module not loading +```bash +modprobe: FATAL: Module wireguard not found +``` + +**Solution:** +```bash +# Install WireGuard kernel module +sudo apt install wireguard-dkms + +# Load module manually +sudo modprobe wireguard + +# Verify module loaded +lsmod | grep wireguard +``` + +### Connection Issues + +#### Problem: VPN won't connect +**Symptoms:** Connection timeout, no handshake + +**Solutions:** + +1. **Check server reachability:** +```bash +# Ping server (if ICMP allowed) +ping -c 3 + +# Check port connectivity +nc -zv 51820 + +# Trace route +traceroute +``` + +2. **Verify credentials:** +```bash +# Check keys format +wg show wg0 private-key +wg show wg0 public-key + +# Verify key length (should be 44 characters) +echo "" | wc -c +``` + +3. **Check firewall:** +```bash +# Ensure UDP 51820 outbound is allowed +sudo iptables -L OUTPUT -n -v | grep 51820 + +# Temporarily allow all outbound (testing only!) +sudo iptables -I OUTPUT 1 -j ACCEPT +``` + +4. **Review logs:** +```bash +# Check WebUI logs +sudo journalctl -u vpn-webui -n 100 + +# Check WireGuard logs +sudo dmesg | grep wireguard + +# Enable debug logging +echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control +``` + +#### Problem: Connection drops frequently +**Symptoms:** Intermittent connectivity, handshake failures + +**Solutions:** + +1. **Adjust keepalive:** +```bash +# Edit WireGuard config +sudo nano /etc/wireguard/wg0.conf + +# Reduce keepalive interval +PersistentKeepalive = 10 # Instead of 25 +``` + +2. **Check MTU:** +```bash +# Test different MTU values +sudo ip link set dev wg0 mtu 1380 + +# Find optimal MTU +ping -M do -s 1372 +# Increase/decrease -s value until it works +``` + +3. **Monitor connection:** +```bash +# Watch handshakes +watch -n 1 'wg show wg0 latest-handshakes' + +# Check for packet loss +mtr +``` + +### Network Issues + +#### Problem: No internet after connecting +**Symptoms:** VPN connected but can't browse + +**Solutions:** + +1. **Check routing:** +```bash +# Show routing table +ip route show + +# Verify default route through VPN +ip route | grep default + +# Add route manually if missing +sudo ip route add default dev wg0 +``` + +2. **Check DNS:** +```bash +# Test DNS resolution +nslookup google.com +dig google.com + +# Check DNS config +cat /etc/resolv.conf + +# Force DNS update +echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf +``` + +3. **Check NAT:** +```bash +# Verify NAT rules +sudo iptables -t nat -L POSTROUTING -n -v + +# Add NAT manually if missing +sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE +``` + +#### Problem: Local network not accessible +**Symptoms:** Can't reach LAN devices when VPN connected + +**Solution:** +```bash +# Add LAN route exception +sudo ip route add 192.168.1.0/24 dev eth0 + +# Or modify WireGuard AllowedIPs +# Change from: 0.0.0.0/0 +# To: 0.0.0.0/1, 128.0.0.0/1 +``` + +### WebUI Issues + +#### Problem: WebUI not loading +**Symptoms:** Connection refused, timeout + +**Solutions:** + +1. **Check service status:** +```bash +# Service status +sudo systemctl status vpn-webui + +# Restart service +sudo systemctl restart vpn-webui + +# Check if running +ps aux | grep gunicorn +``` + +2. **Check port binding:** +```bash +# Verify port is listening +sudo netstat -tlnp | grep 5000 +sudo ss -tlnp | grep 5000 + +# Check for port conflicts +sudo lsof -i :5000 +``` + +3. **Check Nginx (if used):** +```bash +# Test Nginx config +sudo nginx -t + +# Restart Nginx +sudo systemctl restart nginx + +# Check Nginx logs +sudo tail -f /var/log/nginx/error.log +``` + +#### Problem: Can't change settings +**Symptoms:** Changes don't save, errors on submit + +**Solutions:** + +1. **Check permissions:** +```bash +# Fix ownership +sudo chown -R root:root /opt/vpn-gateway + +# Fix permissions +sudo chmod 755 /opt/vpn-gateway +sudo chmod 644 /opt/vpn-gateway/app.py +``` + +2. **Check disk space:** +```bash +# Check available space +df -h /opt/vpn-gateway + +# Clean up if needed +sudo journalctl --vacuum-time=7d +sudo apt clean +``` + +### Security Issues + +#### Problem: Killswitch not working +**Symptoms:** Internet accessible without VPN + +**CRITICAL - Fix immediately:** + +1. **Re-enable killswitch:** +```bash +# Force enable +sudo /usr/local/bin/vpn-killswitch.sh enable + +# Verify rules +sudo iptables -L -n -v | grep DROP +``` + +2. **Check for rule conflicts:** +```bash +# List all rules +sudo iptables-save + +# Remove conflicting rules +sudo iptables -F OUTPUT +sudo iptables -P OUTPUT DROP +``` + +3. **Restart security monitor:** +```bash +sudo systemctl restart vpn-security-monitor +sudo systemctl status vpn-security-monitor +``` + +#### Problem: DNS leaks detected +**Symptoms:** DNS queries not going through VPN + +**Solutions:** + +1. **Force VPN DNS:** +```bash +# Lock resolv.conf +sudo chattr +i /etc/resolv.conf + +# Disable systemd-resolved +sudo systemctl stop systemd-resolved +sudo systemctl disable systemd-resolved +``` + +2. **Check firewall rules:** +```bash +# Block DNS except through VPN +sudo iptables -A OUTPUT -p udp --dport 53 ! -o wg0 -j DROP +sudo iptables -A OUTPUT -p tcp --dport 53 ! -o wg0 -j DROP +``` + +### Performance Issues + +#### Problem: Slow speeds +**Symptoms:** Poor throughput, high latency + +**Solutions:** + +1. **Optimize MTU:** +```bash +# Test optimal MTU +for mtu in 1420 1400 1380 1360; do + sudo ip link set dev wg0 mtu $mtu + echo "Testing MTU $mtu" + iperf3 -c -t 5 +done +``` + +2. **Check CPU usage:** +```bash +# Monitor CPU +top -n 1 | grep -E "wireguard|python" + +# Check interrupts +watch -n 1 'cat /proc/interrupts | grep -E "eth|wg"' +``` + +3. **Tune kernel parameters:** +```bash +# Optimize network stack +cat >> /etc/sysctl.conf << EOF +net.core.rmem_max = 134217728 +net.core.wmem_max = 134217728 +net.ipv4.tcp_rmem = 4096 87380 134217728 +net.ipv4.tcp_wmem = 4096 65536 134217728 +net.core.netdev_max_backlog = 30000 +net.ipv4.tcp_congestion_control = bbr +EOF + +sudo sysctl -p +``` + +### Diagnostic Commands + +#### Complete System Check +```bash +#!/bin/bash +echo "=== VPN Gateway Diagnostics ===" +echo "" +echo "1. Services Status:" +systemctl status vpn-webui --no-pager | head -n 10 +systemctl status vpn-killswitch --no-pager | head -n 10 +systemctl status vpn-security-monitor --no-pager | head -n 10 +echo "" +echo "2. VPN Status:" +wg show +echo "" +echo "3. Firewall Rules:" +iptables -L -n | head -n 20 +echo "" +echo "4. Network Configuration:" +ip addr show +ip route show +echo "" +echo "5. DNS Configuration:" +cat /etc/resolv.conf +echo "" +echo "6. Recent Logs:" +journalctl -u vpn-webui -n 20 --no-pager +echo "" +echo "7. Disk Usage:" +df -h /opt/vpn-gateway +echo "" +echo "8. Memory Usage:" +free -h +``` + +#### Export Debug Info +```bash +# Create debug archive +sudo tar czf vpn-debug-$(date +%s).tar.gz \ + /var/log/vpn-*.log \ + /var/log/syslog \ + /etc/wireguard/ \ + /opt/vpn-gateway/logs/ \ + <(iptables-save) \ + <(wg show) \ + <(ip addr) \ + <(ip route) \ + <(systemctl status vpn-*) +``` + +## Getting Help + +If problems persist: + +1. **Check logs thoroughly:** +```bash +sudo journalctl -xe +sudo dmesg | tail -50 +``` + +2. **Run health check:** +```bash +sudo /usr/local/bin/vpn-health-check.sh +``` + +3. **Create issue on GitHub** with: +- System info: `uname -a` +- Service status: `systemctl status vpn-*` +- Error messages +- Debug archive + +4. **Emergency recovery:** +```bash +# Disable killswitch (TEMPORARY!) +sudo iptables -P INPUT ACCEPT +sudo iptables -P OUTPUT ACCEPT +sudo iptables -P FORWARD ACCEPT +sudo iptables -F + +# Reinstall +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/main/install.sh | bash +``` +EOFTROUBLE + +############################################################# +# docs/API.md +############################################################# +cat > docs/API.md << 'EOFAPI' +# API Reference + +## Overview + +The VPN Gateway provides a RESTful API for managing VPN connections and configuration. + +Base URL: `http://:5000` + +## Authentication + +Currently, the API does not require authentication for local network access. For production use, consider implementing API keys or JWT tokens. + +## Endpoints + +### System Status + +#### GET /api/status +Get current VPN and system status. + +**Response:** +```json +{ + "connected": true, + "provider": "mullvad", + "server": "se-sto-wg-001", + "ip": "185.65.134.123", + "location": "Stockholm, Sweden", + "uptime": "2h 34m", + "killswitch_active": true +} +``` + +### Provider Management + +#### GET /api/providers +List available providers. + +**Response:** +```json +{ + "providers": ["mullvad", "custom", "imported"], + "current": "mullvad" +} +``` + +#### POST /api/provider/{provider} +Switch to a different provider. + +**Parameters:** +- `provider`: Provider name (mullvad|custom|imported) + +**Response:** +```json +{ + "success": true, + "provider": "custom" +} +``` + +### Server Management + +#### GET /api/servers +Get available servers for current provider. + +**Response:** +```json +{ + "servers": { + "Sweden": { + "Stockholm": [ + { + "hostname": "se-sto-wg-001", + "ipv4": "185.65.134.123", + "type": "WireGuard", + "provider": "Mullvad" + } + ] + } + }, + "provider": "mullvad" +} +``` + +### Connection Management + +#### POST /api/connect +Connect to VPN server. + +**Request Body:** +```json +{ + "server": "se-sto-wg-001" +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +#### POST /api/disconnect +Disconnect from VPN. + +**Response:** +```json +{ + "success": true, + "message": "Disconnected - No internet (killswitch active)" +} +``` + +### Custom Server Management + +#### POST /api/custom/add +Add a custom WireGuard server. + +**Request Body:** +```json +{ + "name": "my-vps", + "endpoint": "1.2.3.4:51820", + "public_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "private_key": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=", + "address": "10.0.0.2/32", + "dns": "1.1.1.1,1.0.0.1", + "allowed_ips": "0.0.0.0/0,::/0", + "location": "Germany" +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +#### DELETE /api/custom/remove/{name} +Remove a custom server. + +**Parameters:** +- `name`: Server name + +**Response:** +```json +{ + "success": true +} +``` + +### Import Configuration + +#### POST /api/import +Import a WireGuard configuration. + +**Request Body:** +```json +{ + "name": "imported-config", + "config": "[Interface]\nPrivateKey = xxx\n..." +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +### Utility + +#### GET /api/keypair +Generate a new WireGuard keypair. + +**Response:** +```json +{ + "private_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "public_key": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=" +} +``` + +#### GET /health +Health check endpoint. + +**Response:** +``` +healthy +``` + +## Error Responses + +All endpoints may return error responses: + +```json +{ + "success": false, + "error": "Error message here" +} +``` + +Common HTTP status codes: +- `200`: Success +- `400`: Bad request +- `404`: Not found +- `500`: Internal server error + +## WebSocket Events (Future) + +Planned WebSocket support for real-time updates: + +```javascript +const ws = new WebSocket('ws://gateway-ip:5000/ws'); + +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log('Event:', data.type, data.payload); +}; +``` + +Events: +- `status_change`: VPN connection status changed +- `server_update`: Server list updated +- `security_alert`: Security issue detected + +## Example Usage + +### cURL + +```bash +# Get status +curl http://gateway-ip:5000/api/status + +# Connect to server +curl -X POST http://gateway-ip:5000/api/connect \ + -H "Content-Type: application/json" \ + -d '{"server":"se-sto-wg-001"}' + +# Add custom server +curl -X POST http://gateway-ip:5000/api/custom/add \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-server", + "endpoint": "1.2.3.4:51820", + "public_key": "xxx..." + }' +``` + +### Python + +```python +import requests + +# API base URL +base_url = "http://gateway-ip:5000" + +# Get status +response = requests.get(f"{base_url}/api/status") +status = response.json() +print(f"Connected: {status['connected']}") + +# Connect to server +response = requests.post( + f"{base_url}/api/connect", + json={"server": "se-sto-wg-001"} +) +if response.json()["success"]: + print("Connected successfully") +``` + +### JavaScript + +```javascript +// Get status +fetch('http://gateway-ip:5000/api/status') + .then(response => response.json()) + .then(data => console.log('Status:', data)); + +// Connect to server +fetch('http://gateway-ip:5000/api/connect', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + server: 'se-sto-wg-001' + }) +}) +.then(response => response.json()) +.then(data => { + if (data.success) { + console.log('Connected'); + } +}); +``` + +## Rate Limiting + +API endpoints are rate-limited: +- General endpoints: 10 requests/second +- Connection endpoints: 5 requests/second + +Headers returned: +- `X-RateLimit-Limit`: Request limit +- `X-RateLimit-Remaining`: Remaining requests +- `X-RateLimit-Reset`: Reset timestamp + +## Future Enhancements + +Planned API features: +- JWT authentication +- GraphQL endpoint +- Metrics endpoint (Prometheus format) +- Bulk operations +- Configuration backup/restore +- Traffic statistics +- Connection history +EOFAPI + +echo "βœ“ All configuration and documentation files created!" +echo "" +echo "Files created in:" +echo " configs/ - Nginx, systemd, iptables, logrotate" +echo " configs/systemd/ - Service files" +echo " docs/ - Complete documentation" +echo "" +echo "Total files created:" +find configs docs -type f | wc -l diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..98c3ad6 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,320 @@ +# API Reference + +## Overview + +The VPN Gateway provides a RESTful API for managing VPN connections and configuration. + +Base URL: `http://:5000` + +## Authentication + +Currently, the API does not require authentication for local network access. For production use, consider implementing API keys or JWT tokens. + +## Endpoints + +### System Status + +#### GET /api/status +Get current VPN and system status. + +**Response:** +```json +{ + "connected": true, + "provider": "mullvad", + "server": "se-sto-wg-001", + "ip": "185.65.134.123", + "location": "Stockholm, Sweden", + "uptime": "2h 34m", + "killswitch_active": true +} +``` + +### Provider Management + +#### GET /api/providers +List available providers. + +**Response:** +```json +{ + "providers": ["mullvad", "custom", "imported"], + "current": "mullvad" +} +``` + +#### POST /api/provider/{provider} +Switch to a different provider. + +**Parameters:** +- `provider`: Provider name (mullvad|custom|imported) + +**Response:** +```json +{ + "success": true, + "provider": "custom" +} +``` + +### Server Management + +#### GET /api/servers +Get available servers for current provider. + +**Response:** +```json +{ + "servers": { + "Sweden": { + "Stockholm": [ + { + "hostname": "se-sto-wg-001", + "ipv4": "185.65.134.123", + "type": "WireGuard", + "provider": "Mullvad" + } + ] + } + }, + "provider": "mullvad" +} +``` + +### Connection Management + +#### POST /api/connect +Connect to VPN server. + +**Request Body:** +```json +{ + "server": "se-sto-wg-001" +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +#### POST /api/disconnect +Disconnect from VPN. + +**Response:** +```json +{ + "success": true, + "message": "Disconnected - No internet (killswitch active)" +} +``` + +### Custom Server Management + +#### POST /api/custom/add +Add a custom WireGuard server. + +**Request Body:** +```json +{ + "name": "my-vps", + "endpoint": "1.2.3.4:51820", + "public_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "private_key": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=", + "address": "10.0.0.2/32", + "dns": "1.1.1.1,1.0.0.1", + "allowed_ips": "0.0.0.0/0,::/0", + "location": "Germany" +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +#### DELETE /api/custom/remove/{name} +Remove a custom server. + +**Parameters:** +- `name`: Server name + +**Response:** +```json +{ + "success": true +} +``` + +### Import Configuration + +#### POST /api/import +Import a WireGuard configuration. + +**Request Body:** +```json +{ + "name": "imported-config", + "config": "[Interface]\nPrivateKey = xxx\n..." +} +``` + +**Response:** +```json +{ + "success": true +} +``` + +### Utility + +#### GET /api/keypair +Generate a new WireGuard keypair. + +**Response:** +```json +{ + "private_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "public_key": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=" +} +``` + +#### GET /health +Health check endpoint. + +**Response:** +``` +healthy +``` + +## Error Responses + +All endpoints may return error responses: + +```json +{ + "success": false, + "error": "Error message here" +} +``` + +Common HTTP status codes: +- `200`: Success +- `400`: Bad request +- `404`: Not found +- `500`: Internal server error + +## WebSocket Events (Future) + +Planned WebSocket support for real-time updates: + +```javascript +const ws = new WebSocket('ws://gateway-ip:5000/ws'); + +ws.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log('Event:', data.type, data.payload); +}; +``` + +Events: +- `status_change`: VPN connection status changed +- `server_update`: Server list updated +- `security_alert`: Security issue detected + +## Example Usage + +### cURL + +```bash +# Get status +curl http://gateway-ip:5000/api/status + +# Connect to server +curl -X POST http://gateway-ip:5000/api/connect \ + -H "Content-Type: application/json" \ + -d '{"server":"se-sto-wg-001"}' + +# Add custom server +curl -X POST http://gateway-ip:5000/api/custom/add \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-server", + "endpoint": "1.2.3.4:51820", + "public_key": "xxx..." + }' +``` + +### Python + +```python +import requests + +# API base URL +base_url = "http://gateway-ip:5000" + +# Get status +response = requests.get(f"{base_url}/api/status") +status = response.json() +print(f"Connected: {status['connected']}") + +# Connect to server +response = requests.post( + f"{base_url}/api/connect", + json={"server": "se-sto-wg-001"} +) +if response.json()["success"]: + print("Connected successfully") +``` + +### JavaScript + +```javascript +// Get status +fetch('http://gateway-ip:5000/api/status') + .then(response => response.json()) + .then(data => console.log('Status:', data)); + +// Connect to server +fetch('http://gateway-ip:5000/api/connect', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + server: 'se-sto-wg-001' + }) +}) +.then(response => response.json()) +.then(data => { + if (data.success) { + console.log('Connected'); + } +}); +``` + +## Rate Limiting + +API endpoints are rate-limited: +- General endpoints: 10 requests/second +- Connection endpoints: 5 requests/second + +Headers returned: +- `X-RateLimit-Limit`: Request limit +- `X-RateLimit-Remaining`: Remaining requests +- `X-RateLimit-Reset`: Reset timestamp + +## Future Enhancements + +Planned API features: +- JWT authentication +- GraphQL endpoint +- Metrics endpoint (Prometheus format) +- Bulk operations +- Configuration backup/restore +- Traffic statistics +- Connection history diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 0000000..6954a68 --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,241 @@ +# Frequently Asked Questions + +## General Questions + +### Q: What is the VPN Gateway? +**A:** It's a secure VPN gateway solution that routes all network traffic through a VPN connection with a permanent killswitch to prevent leaks. + +### Q: Which VPN providers are supported? +**A:** +- Mullvad VPN (commercial service) +- Custom WireGuard servers (your own VPS) +- Any imported WireGuard configuration + +### Q: Can I use this with OpenVPN? +**A:** No, this gateway only supports WireGuard protocol for better performance and security. + +### Q: Is this free to use? +**A:** The software is free and open source. You need to provide your own VPN service (Mullvad account or custom server). + +## Installation + +### Q: What are the system requirements? +**A:** +- LXC container or Linux system +- Ubuntu 20.04+ or Debian 11+ +- 512MB RAM minimum +- 1GB disk space +- Root access + +### Q: Can I install on a Raspberry Pi? +**A:** Yes, as long as it runs a supported OS and has WireGuard kernel module support. + +### Q: Does it work in Docker? +**A:** It requires privileged mode and NET_ADMIN capability. LXC is recommended over Docker. + +### Q: Can I install on a VPS? +**A:** Yes, but be aware that the killswitch will block all traffic except through VPN, which might lock you out via SSH. + +## Usage + +### Q: No internet after disconnecting VPN? +**A:** This is correct behavior! The killswitch blocks all internet traffic when VPN is not connected. This prevents leaks. + +### Q: Can I disable the killswitch? +**A:** No, the killswitch cannot be disabled through normal means. This is a security feature. + +### Q: How do I access the WebUI? +**A:** Navigate to `http://` in your browser. The WebUI is always accessible from the local network. + +### Q: Can I use multiple VPN connections simultaneously? +**A:** No, only one VPN connection is active at a time. You can switch between servers/providers via the WebUI. + +## Security + +### Q: Is this really secure? +**A:** Yes, when properly configured: +- Permanent killswitch prevents leaks +- DNS leak protection enabled +- IPv6 completely disabled +- Continuous security monitoring + +### Q: What about WebRTC leaks? +**A:** WebRTC leaks are prevented at the firewall level. No direct peer connections are possible. + +### Q: Can applications bypass the VPN? +**A:** No, all traffic is forced through the VPN tunnel or blocked by the killswitch. + +### Q: Is my traffic logged? +**A:** The gateway itself doesn't log traffic. Logging depends on your VPN provider's policy. + +## Troubleshooting + +### Q: WebUI is not accessible +**A:** +```bash +# Check if service is running +sudo systemctl status vpn-webui + +# Restart the service +sudo systemctl restart vpn-webui + +# Check if port is open +sudo netstat -tlnp | grep 5000 +``` + +### Q: VPN won't connect +**A:** +1. Check your credentials/keys are correct +2. Verify the server is reachable +3. Check firewall allows outbound UDP 51820 +4. Review logs: `sudo journalctl -u vpn-webui -n 50` + +### Q: DNS not working +**A:** +```bash +# Check DNS configuration +cat /etc/resolv.conf + +# Test DNS resolution +nslookup google.com + +# Restart VPN connection +sudo wg-quick down wg0 +sudo wg-quick up wg0 +``` + +### Q: High CPU usage +**A:** +- Check security monitor: `sudo systemctl status vpn-security-monitor` +- Reduce monitoring frequency if needed +- Check for packet loops in firewall rules + +## Configuration + +### Q: How do I add a custom DNS server? +**A:** Edit the WireGuard configuration: +```bash +sudo nano /etc/wireguard/wg0.conf +# Change DNS = line to your preferred servers +``` + +### Q: Can I change the WebUI port? +**A:** Yes, edit the systemd service: +```bash +sudo nano /etc/systemd/system/vpn-webui.service +# Change --bind 0.0.0.0:5000 to your desired port +sudo systemctl daemon-reload +sudo systemctl restart vpn-webui +``` + +### Q: How do I backup my configuration? +**A:** +```bash +sudo tar czf vpn-backup.tar.gz \ + /opt/vpn-gateway \ + /etc/wireguard \ + /etc/systemd/system/vpn-*.service +``` + +### Q: How do I enable auto-reconnect? +**A:** Auto-reconnect is handled by the security monitor. Ensure it's running: +```bash +sudo systemctl enable vpn-security-monitor +sudo systemctl start vpn-security-monitor +``` + +## Advanced + +### Q: Can I use split tunneling? +**A:** Yes, for custom servers. Modify the AllowedIPs in your WireGuard config: +```ini +# Only specific subnets through VPN +AllowedIPs = 10.0.0.0/8, 172.16.0.0/12 +``` + +### Q: How do I set up failover? +**A:** Add multiple peers in the WireGuard configuration: +```ini +[Peer] +# Primary +PublicKey = xxx... +Endpoint = primary.example.com:51820 + +[Peer] +# Backup +PublicKey = yyy... +Endpoint = backup.example.com:51820 +``` + +### Q: Can I monitor traffic statistics? +**A:** +```bash +# WireGuard statistics +wg show wg0 transfer + +# Network statistics +vnstat -i wg0 + +# Real-time monitoring +iftop -i wg0 +``` + +### Q: How do I integrate with existing infrastructure? +**A:** +- Use as default gateway for network segments +- Configure via DHCP options +- Set up policy-based routing for specific clients + +## Updates + +### Q: How do I update the VPN Gateway? +**A:** +```bash +sudo /usr/local/bin/vpn-update.sh +``` + +### Q: Will updates break my configuration? +**A:** No, updates preserve your configuration. Backups are created automatically. + +### Q: How do I check for updates? +**A:** +```bash +# Check current version +cat /opt/vpn-gateway/version + +# Check for updates +curl -s https://raw.githubusercontent.com/yourusername/vpn-gateway/main/version +``` + +## Support + +### Q: Where can I get help? +**A:** +- GitHub Issues: https://github.com/yourusername/vpn-gateway/issues +- Documentation: https://github.com/yourusername/vpn-gateway/wiki +- Community Forum: [Link to forum] + +### Q: How do I report a bug? +**A:** Open an issue on GitHub with: +- System information +- Error messages +- Steps to reproduce +- Relevant logs + +### Q: Can I contribute? +**A:** Yes! Contributions are welcome: +- Submit pull requests +- Report bugs +- Improve documentation +- Share your setup + +## Legal + +### Q: Is this legal to use? +**A:** Yes, but check your local laws regarding VPN usage. Some countries restrict VPN use. + +### Q: Can I use this commercially? +**A:** Yes, under the MIT license terms. See LICENSE file for details. + +### Q: What about warranty? +**A:** This software is provided "as is" without warranty. Use at your own risk. diff --git a/docs/PROVIDERS.md b/docs/PROVIDERS.md new file mode 100644 index 0000000..43da94c --- /dev/null +++ b/docs/PROVIDERS.md @@ -0,0 +1,339 @@ +# VPN Provider Configuration Guide + +## Overview + +The VPN Gateway supports three types of providers: +1. **Mullvad VPN** - Commercial VPN service +2. **Custom WireGuard** - Your own VPN server +3. **Import Config** - Existing WireGuard configurations + +## Mullvad VPN + +### Setup + +1. Get a Mullvad account at https://mullvad.net +2. Note your 16-digit account number +3. During installation, select "Mullvad" and enter your account number + +### Features + +- Automatic server list updates +- 40+ countries available +- Built-in DNS leak protection +- No logging policy + +### Server Selection + +Servers are organized by: +- **Country** (Sweden, Germany, USA, etc.) +- **City** (Stockholm, Berlin, New York, etc.) +- **Server** (se-sto-wg-001, de-ber-wg-002, etc.) + +### Configuration + +The system automatically: +- Fetches current server list +- Generates WireGuard keys +- Configures DNS (100.64.0.1) +- Sets up kill switch + +## Custom WireGuard Server + +### Prerequisites + +You need: +- A VPS or dedicated server +- WireGuard installed on the server +- Server public key +- Open port (usually 51820) + +### Server Setup (VPS Side) + +#### 1. Install WireGuard +```bash +# Ubuntu/Debian +sudo apt update +sudo apt install wireguard + +# CentOS/RHEL +sudo yum install wireguard-tools +``` + +#### 2. Generate Keys +```bash +cd /etc/wireguard +wg genkey | tee server_private.key | wg pubkey > server_public.key +``` + +#### 3. Configure Server +```bash +cat > /etc/wireguard/wg0.conf << EOF +[Interface] +PrivateKey = $(cat server_private.key) +Address = 10.0.0.1/24 +ListenPort = 51820 + +# Enable IP forwarding +PostUp = sysctl -w net.ipv4.ip_forward=1 +PostUp = iptables -A FORWARD -i wg0 -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -D FORWARD -i wg0 -j ACCEPT +PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + +# Peer (VPN Gateway) +[Peer] +PublicKey = +AllowedIPs = 10.0.0.2/32 +EOF +``` + +#### 4. Start WireGuard +```bash +sudo systemctl enable wg-quick@wg0 +sudo systemctl start wg-quick@wg0 +``` + +### Gateway Setup (Client Side) + +During installation, provide: +- **Endpoint**: Your server's IP:Port (e.g., 1.2.3.4:51820) +- **Server Public Key**: From server_public.key +- **Client IP**: Usually 10.0.0.2/32 +- **DNS**: 1.1.1.1,1.0.0.1 or your preferred DNS + +### Adding Multiple Servers + +Via WebUI: +1. Go to "Custom Server" tab +2. Click "Add New Server" +3. Fill in server details +4. Save configuration + +Via API: +```bash +curl -X POST http://gateway-ip/api/custom/add \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-vps-us", + "endpoint": "us.example.com:51820", + "public_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", + "location": "United States" + }' +``` + +## Import Existing Configuration + +### Supported Formats + +- Standard WireGuard .conf files +- Configs from any WireGuard provider +- Custom peer configurations + +### Import Methods + +#### Via WebUI +1. Select "Import Config" tab +2. Choose file or paste configuration +3. Provide a name for the config +4. Click "Import" + +#### Via CLI +```bash +# Copy config to gateway +scp myconfig.conf root@gateway-ip:/tmp/ + +# Import via API +curl -X POST http://gateway-ip/api/import \ + -H "Content-Type: application/json" \ + -d '{ + "name": "imported-config", + "config": "'"$(cat /tmp/myconfig.conf)"'" + }' +``` + +### Automatic Modifications + +The system automatically: +- Adds killswitch rules if missing +- Preserves original settings +- Validates configuration syntax + +### Example Configuration + +```ini +[Interface] +PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +Address = 10.8.0.2/32 +DNS = 1.1.1.1 + +[Peer] +PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +AllowedIPs = 0.0.0.0/0 +Endpoint = vpn.example.com:51820 +PersistentKeepalive = 25 +``` + +## Provider Switching + +### Via WebUI + +1. Click on provider tabs +2. System automatically switches backend +3. Previous provider settings are preserved + +### Via API + +```bash +# Switch to Mullvad +curl -X POST http://gateway-ip/api/provider/mullvad + +# Switch to Custom +curl -X POST http://gateway-ip/api/provider/custom + +# Switch to Imported +curl -X POST http://gateway-ip/api/provider/imported +``` + +## Advanced Configuration + +### Split Tunneling + +For custom servers, modify AllowedIPs: +```ini +# Route only specific subnets through VPN +AllowedIPs = 10.0.0.0/8, 192.168.0.0/16 + +# Route everything except local network +AllowedIPs = 0.0.0.0/1, 128.0.0.0/1 +``` + +### Multiple Peers (Failover) + +```ini +[Peer] +# Primary server +PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +AllowedIPs = 0.0.0.0/0 +Endpoint = primary.example.com:51820 + +[Peer] +# Backup server +PublicKey = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy= +AllowedIPs = 0.0.0.0/0 +Endpoint = backup.example.com:51820 +``` + +### Custom DNS + +Modify DNS in the configuration: +```ini +# CloudFlare +DNS = 1.1.1.1, 1.0.0.1 + +# Quad9 +DNS = 9.9.9.9, 149.112.112.112 + +# Custom/Local +DNS = 192.168.1.1 +``` + +## Performance Optimization + +### MTU Settings + +For optimal performance: +```ini +[Interface] +MTU = 1420 # Default, works for most connections +# MTU = 1380 # For problematic connections +# MTU = 1280 # Maximum compatibility +``` + +### Persistent Keepalive + +Adjust based on your needs: +```ini +# For stable connections +PersistentKeepalive = 25 + +# For NAT/firewall traversal +PersistentKeepalive = 10 + +# Disable for on-demand +# PersistentKeepalive = 0 +``` + +## Troubleshooting Providers + +### Mullvad Issues + +```bash +# Check account status +curl https://api.mullvad.net/www/accounts// + +# Test server connectivity +ping -c 1 + +# Verify WireGuard keys +wg show wg0 public-key +``` + +### Custom Server Issues + +```bash +# Test connectivity +nc -zv 51820 + +# Check server logs (on VPS) +sudo journalctl -u wg-quick@wg0 -f + +# Verify keys match +echo "" | base64 -d | wc -c # Should be 32 +``` + +### Import Issues + +```bash +# Validate config syntax +wg-quick strip /path/to/config.conf + +# Test config manually +sudo wg-quick up /tmp/test.conf +sudo wg-quick down /tmp/test.conf +``` + +## Security Considerations + +### Key Management + +- Never share private keys +- Rotate keys periodically +- Use unique keys per device/gateway + +### Server Hardening + +For custom servers: +```bash +# Firewall rules +ufw allow 51820/udp +ufw allow from 10.0.0.0/24 + +# Disable password auth +sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config + +# Enable automatic updates +apt install unattended-upgrades +``` + +### Monitoring + +```bash +# Connection status +wg show + +# Traffic statistics +wg show wg0 transfer + +# Active connections +netstat -tunlp | grep 51820 +``` diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md new file mode 100644 index 0000000..25e4b40 --- /dev/null +++ b/docs/QUICKSTART.md @@ -0,0 +1,211 @@ +# Quick Start Guide + +## Prerequisites + +- LXC Container with Ubuntu/Debian +- Root access +- Internet connection for initial setup + +## Installation + +### 1. One-Line Install + +```bash +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/main/install.sh | bash +``` + +### 2. Manual Install + +```bash +# Clone repository +git clone https://github.com/yourusername/vpn-gateway.git +cd vpn-gateway + +# Run installer +sudo ./install.sh +``` + +## Initial Setup + +### Step 1: Network Detection + +The installer will auto-detect your network configuration: +- Network interface (e.g., eth0) +- LAN subnet (e.g., 192.168.1.0/24) +- Container IP address + +Confirm or modify as needed. + +### Step 2: Choose Provider + +Select your VPN provider: + +#### Option 1: Mullvad VPN +``` +Select provider [1-3]: 1 +Enter your Mullvad account number: 1234567890123456 +``` + +#### Option 2: Custom WireGuard Server +``` +Select provider [1-3]: 2 +Server endpoint (IP:Port): 1.2.3.4:51820 +Server public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +``` + +#### Option 3: Import Configuration +``` +Select provider [1-3]: 3 +Path to WireGuard config: /path/to/config.conf +``` + +### Step 3: Complete Installation + +The installer will: +1. Install dependencies +2. Configure killswitch +3. Set up WebUI +4. Start services + +## Using the WebUI + +### Access the Interface + +Open your browser and navigate to: +``` +http:// +``` + +### Connect to VPN + +1. **Select Location** (Mullvad only) + - Choose country + - Choose city + - Choose server + +2. **Click Connect** + - Connection established in ~2-5 seconds + - Status indicator turns green + +3. **Verify Connection** + - Check public IP displayed + - Verify location shown + +### Disconnect from VPN + +1. Click **Disconnect** button +2. **WARNING**: No internet access after disconnect (killswitch active) + +## Client Configuration + +### Configure Your Devices + +Set on each client device: + +#### Windows +1. Network Settings β†’ IPv4 Properties +2. Default Gateway: `` +3. DNS Server: `` or `1.1.1.1` + +#### Linux +```bash +# Temporary +sudo ip route del default +sudo ip route add default via +echo "nameserver " | sudo tee /etc/resolv.conf + +# Permanent (NetworkManager) +nmcli connection modify ipv4.gateway +nmcli connection modify ipv4.dns +``` + +#### macOS +1. System Preferences β†’ Network +2. Advanced β†’ TCP/IP +3. Router: `` +4. DNS: `` + +## Quick Commands + +### Check Status +```bash +# Service status +sudo systemctl status vpn-webui + +# Connection status +curl http://localhost:5000/api/status + +# Health check +sudo /usr/local/bin/vpn-health-check.sh +``` + +### View Logs +```bash +# All logs +sudo journalctl -u vpn-webui -u vpn-killswitch -f + +# WebUI logs only +sudo journalctl -u vpn-webui -f +``` + +### Restart Services +```bash +sudo systemctl restart vpn-webui +sudo systemctl restart vpn-security-monitor +``` + +## Important Notes + +⚠️ **Killswitch Always Active** +- No internet without VPN connection +- This is intentional for security +- Local network still accessible + +⚠️ **After Disconnect** +- Internet blocked until reconnection +- WebUI remains accessible +- Connect to VPN to restore internet + +## Troubleshooting + +### WebUI Not Accessible +```bash +# Check if service is running +sudo systemctl status vpn-webui + +# Check if port is listening +sudo netstat -tlnp | grep 5000 + +# Restart service +sudo systemctl restart vpn-webui +``` + +### No Internet After Connect +```bash +# Check VPN status +sudo wg show + +# Check killswitch +sudo iptables -L -n -v + +# Check DNS +nslookup google.com +``` + +### Can't Connect to VPN +```bash +# Check logs +sudo journalctl -u vpn-webui -n 50 + +# Test killswitch +sudo /usr/local/bin/vpn-killswitch.sh verify + +# Manual connection test +sudo wg-quick up wg0 +``` + +## Next Steps + +- Read [Provider Configuration](PROVIDERS.md) for advanced setup +- Review [Security Documentation](SECURITY.md) for security features +- See [FAQ](FAQ.md) for common questions diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..4e4e567 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,77 @@ +# VPN Gateway Documentation + +## Overview + +This documentation covers the VPN Gateway multi-provider system with permanent killswitch protection. + +## Contents + +- [Quick Start Guide](QUICKSTART.md) - Get up and running in minutes +- [Provider Configuration](PROVIDERS.md) - Detailed provider setup +- [Security Documentation](SECURITY.md) - Security features and best practices +- [API Reference](API.md) - WebUI API endpoints +- [Troubleshooting](TROUBLESHOOTING.md) - Common issues and solutions +- [FAQ](FAQ.md) - Frequently asked questions + +## Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Client Devices β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ VPN Gateway Container β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ WebUI (Port 80/5000) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Flask Backend (Python) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ WireGuard Interface (wg0) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Killswitch (iptables) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ VPN Provider β”‚ + β”‚ β€’ Mullvad β”‚ + β”‚ β€’ Custom Server β”‚ + β”‚ β€’ Imported Configβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Key Components + +### 1. Killswitch +- Permanent firewall rules +- Blocks all non-VPN traffic +- Cannot be disabled via UI + +### 2. WebUI +- Modern responsive interface +- Real-time status monitoring +- Multi-provider support + +### 3. Backend +- Flask-based API +- Provider management +- Connection handling + +### 4. Security Monitor +- Continuous monitoring +- Leak detection +- Auto-recovery + +## Support + +- GitHub Issues: https://github.com/yourusername/vpn-gateway/issues +- Documentation: https://github.com/yourusername/vpn-gateway/wiki diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..e8b7745 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,404 @@ +# Security Documentation + +## Overview + +The VPN Gateway implements multiple layers of security to ensure zero-leak protection and maintain privacy. + +## Core Security Features + +### 1. Permanent Killswitch + +The killswitch is the primary security mechanism that prevents any traffic leaks. + +#### Implementation + +- **Firewall Rules**: Default DROP policy for all chains +- **Boot Protection**: Activates before network initialization +- **Cannot be Disabled**: No UI or API endpoint to disable +- **Continuous Monitoring**: Verified every 10 seconds + +#### Technical Details + +```bash +# Default policies +iptables -P INPUT DROP +iptables -P FORWARD DROP +iptables -P OUTPUT DROP + +# Only allowed traffic: +# - Loopback (system operations) +# - LAN subnet (WebUI access) +# - Established connections +# - VPN tunnel (when active) +``` + +### 2. DNS Leak Protection + +#### Mechanisms + +1. **Forced VPN DNS**: All DNS queries routed through VPN +2. **System DNS Override**: /etc/resolv.conf locked +3. **IPv6 Disabled**: Prevents IPv6 DNS leaks +4. **DNS Filtering**: Only root can make DNS queries for VPN connection + +#### Configuration + +```bash +# DNS through VPN only +iptables -A OUTPUT -p udp --dport 53 -m owner --uid-owner root -j ACCEPT +iptables -A OUTPUT -p tcp --dport 53 -m owner --uid-owner root -j ACCEPT + +# Block all other DNS +iptables -A OUTPUT -p udp --dport 53 -j DROP +iptables -A OUTPUT -p tcp --dport 53 -j DROP +``` + +### 3. IPv6 Protection + +Complete IPv6 blocking to prevent leaks: + +```bash +# IPv6 firewall +ip6tables -P INPUT DROP +ip6tables -P FORWARD DROP +ip6tables -P OUTPUT DROP + +# Kernel level +sysctl -w net.ipv6.conf.all.disable_ipv6=1 +sysctl -w net.ipv6.conf.default.disable_ipv6=1 +``` + +### 4. Security Monitor + +Continuous monitoring daemon that: +- Verifies killswitch every 10 seconds +- Detects potential leaks +- Auto-recovers from failures +- Logs security events + +## Threat Model + +### Protected Against + +βœ… **IP Leaks** +- Killswitch blocks all non-VPN traffic +- No traffic possible without active tunnel + +βœ… **DNS Leaks** +- All DNS through VPN +- System DNS locked +- IPv6 DNS blocked + +βœ… **WebRTC Leaks** +- Blocked at firewall level +- No direct peer connections + +βœ… **IPv6 Leaks** +- IPv6 completely disabled +- Both firewall and kernel level + +βœ… **Connection Drops** +- Killswitch remains active +- No traffic during reconnection +- Auto-recovery available + +βœ… **Malicious Applications** +- Cannot bypass firewall rules +- All traffic subject to killswitch + +### Not Protected Against + +❌ **Compromised Container** +- If attacker gains root access +- Can modify firewall rules + +❌ **Host System Compromise** +- Container isolation breach +- Hypervisor vulnerabilities + +❌ **Traffic Analysis** +- VPN traffic patterns visible +- Timing correlation attacks + +❌ **VPN Provider Compromise** +- Malicious VPN server +- Provider logging (choose carefully) + +## Security Best Practices + +### 1. Installation Security + +```bash +# Verify installer integrity +sha256sum install.sh +# Compare with published hash + +# Review script before execution +less install.sh + +# Run with specific version +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/v1.0.0/install.sh | bash +``` + +### 2. Access Control + +#### WebUI Protection + +```nginx +# Restrict WebUI access to LAN only +location / { + allow 192.168.1.0/24; + deny all; + # ... proxy settings +} +``` + +#### SSH Hardening + +```bash +# Disable password authentication +PasswordAuthentication no + +# Key-only access +PubkeyAuthentication yes + +# Restrict to specific IPs +AllowUsers root@192.168.1.0/24 +``` + +### 3. Key Management + +#### WireGuard Keys + +```bash +# Generate new keys periodically +wg genkey | tee privatekey | wg pubkey > publickey + +# Secure storage +chmod 600 /etc/wireguard/*.key + +# Never share private keys +# Unique keys per gateway +``` + +#### Rotation Schedule + +- **Private Keys**: Every 3-6 months +- **Preshared Keys**: Every 1-3 months +- **API Keys**: Every 30 days + +### 4. Monitoring + +#### Security Logs + +```bash +# Monitor security events +journalctl -u vpn-security-monitor -f + +# Check for failures +grep "ALERT\|ERROR" /var/log/vpn-security-monitor.log + +# Audit firewall drops +iptables -L -n -v | grep DROP +``` + +#### Leak Testing + +```bash +# Regular leak tests +curl https://ipleak.net/json/ +curl https://am.i.mullvad.net/json + +# DNS leak test +nslookup example.com +dig example.com +``` + +### 5. Updates + +#### Security Updates + +```bash +# System updates (through VPN) +apt update && apt upgrade + +# VPN Gateway updates +/usr/local/bin/vpn-update.sh + +# Check for security advisories +``` + +#### Automatic Updates + +```bash +# Enable unattended upgrades +apt install unattended-upgrades +dpkg-reconfigure -plow unattended-upgrades +``` + +## Incident Response + +### 1. Leak Detected + +If a leak is detected: + +1. **Immediate Action** + ```bash + # Re-enable killswitch + /usr/local/bin/vpn-killswitch.sh enable + + # Disconnect VPN + wg-quick down wg0 + ``` + +2. **Investigation** + ```bash + # Check logs + journalctl -u vpn-security-monitor -n 100 + + # Verify firewall rules + iptables -L -n -v + ``` + +3. **Recovery** + ```bash + # Restart security services + systemctl restart vpn-killswitch + systemctl restart vpn-security-monitor + ``` + +### 2. Suspicious Activity + +Signs of compromise: +- Unexpected firewall rule changes +- Unknown processes with network access +- Unusual CPU/memory usage +- Modified system files + +Response: +```bash +# Check processes +netstat -tulpn +ps aux | grep -v grep | grep wg + +# Check file integrity +debsums -c +find /etc -type f -mtime -1 + +# Review auth logs +grep "Failed\|Invalid" /var/log/auth.log +``` + +### 3. Emergency Shutdown + +If immediate isolation needed: + +```bash +# Block ALL network traffic +iptables -P INPUT DROP +iptables -P OUTPUT DROP +iptables -P FORWARD DROP +iptables -F + +# Stop services +systemctl stop vpn-webui +systemctl stop wg-quick@wg0 + +# Preserve evidence +tar czf /tmp/evidence-$(date +%s).tar.gz \ + /var/log \ + /etc/wireguard \ + /opt/vpn-gateway/logs +``` + +## Security Hardening + +### 1. Container Hardening + +```bash +# Limit capabilities +lxc config set security.nesting false +lxc config set security.privileged false + +# Resource limits +lxc config set limits.memory 512MB +lxc config set limits.cpu 1 +``` + +### 2. Network Hardening + +```bash +# Rate limiting +iptables -A INPUT -p tcp --dport 5000 \ + -m conntrack --ctstate NEW \ + -m limit --limit 10/min --limit-burst 5 \ + -j ACCEPT + +# SYN flood protection +echo 1 > /proc/sys/net/ipv4/tcp_syncookies +echo 2048 > /proc/sys/net/ipv4/tcp_max_syn_backlog +``` + +### 3. Application Hardening + +```python +# Flask security headers +from flask import Flask +from flask_talisman import Talisman + +app = Flask(__name__) +Talisman(app, + force_https=False, # Handle at reverse proxy + strict_transport_security=True, + content_security_policy={ + 'default-src': "'self'" + } +) +``` + +## Compliance + +### GDPR Compliance + +- No personal data logging +- User control over data +- Right to deletion +- Transparent processing + +### Security Standards + +- CIS Benchmarks compliance +- NIST framework alignment +- Zero-trust architecture +- Defense in depth + +## Security Checklist + +### Daily +- [ ] Check service status +- [ ] Review security logs +- [ ] Verify killswitch active + +### Weekly +- [ ] Run leak tests +- [ ] Check for updates +- [ ] Review firewall rules + +### Monthly +- [ ] Rotate keys +- [ ] Audit access logs +- [ ] Update documentation + +### Quarterly +- [ ] Security assessment +- [ ] Penetration testing +- [ ] Disaster recovery test + +## Contact + +For security issues: +- **Email**: security@yourdomain.com +- **PGP Key**: [Public key] +- **Response Time**: < 24 hours for critical issues + +Please report security vulnerabilities responsibly. diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md new file mode 100644 index 0000000..e9053ad --- /dev/null +++ b/docs/TROUBLESHOOTING.md @@ -0,0 +1,425 @@ +# Troubleshooting Guide + +## Common Issues and Solutions + +### Installation Issues + +#### Problem: Installation fails with dependency errors +```bash +E: Unable to locate package wireguard +``` + +**Solution:** +```bash +# Update package lists +sudo apt update + +# Enable backports (Debian) +echo "deb http://deb.debian.org/debian $(lsb_release -cs)-backports main" | \ + sudo tee /etc/apt/sources.list.d/backports.list +sudo apt update + +# Install kernel headers +sudo apt install linux-headers-$(uname -r) + +# Retry installation +sudo ./install.sh +``` + +#### Problem: WireGuard module not loading +```bash +modprobe: FATAL: Module wireguard not found +``` + +**Solution:** +```bash +# Install WireGuard kernel module +sudo apt install wireguard-dkms + +# Load module manually +sudo modprobe wireguard + +# Verify module loaded +lsmod | grep wireguard +``` + +### Connection Issues + +#### Problem: VPN won't connect +**Symptoms:** Connection timeout, no handshake + +**Solutions:** + +1. **Check server reachability:** +```bash +# Ping server (if ICMP allowed) +ping -c 3 + +# Check port connectivity +nc -zv 51820 + +# Trace route +traceroute +``` + +2. **Verify credentials:** +```bash +# Check keys format +wg show wg0 private-key +wg show wg0 public-key + +# Verify key length (should be 44 characters) +echo "" | wc -c +``` + +3. **Check firewall:** +```bash +# Ensure UDP 51820 outbound is allowed +sudo iptables -L OUTPUT -n -v | grep 51820 + +# Temporarily allow all outbound (testing only!) +sudo iptables -I OUTPUT 1 -j ACCEPT +``` + +4. **Review logs:** +```bash +# Check WebUI logs +sudo journalctl -u vpn-webui -n 100 + +# Check WireGuard logs +sudo dmesg | grep wireguard + +# Enable debug logging +echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control +``` + +#### Problem: Connection drops frequently +**Symptoms:** Intermittent connectivity, handshake failures + +**Solutions:** + +1. **Adjust keepalive:** +```bash +# Edit WireGuard config +sudo nano /etc/wireguard/wg0.conf + +# Reduce keepalive interval +PersistentKeepalive = 10 # Instead of 25 +``` + +2. **Check MTU:** +```bash +# Test different MTU values +sudo ip link set dev wg0 mtu 1380 + +# Find optimal MTU +ping -M do -s 1372 +# Increase/decrease -s value until it works +``` + +3. **Monitor connection:** +```bash +# Watch handshakes +watch -n 1 'wg show wg0 latest-handshakes' + +# Check for packet loss +mtr +``` + +### Network Issues + +#### Problem: No internet after connecting +**Symptoms:** VPN connected but can't browse + +**Solutions:** + +1. **Check routing:** +```bash +# Show routing table +ip route show + +# Verify default route through VPN +ip route | grep default + +# Add route manually if missing +sudo ip route add default dev wg0 +``` + +2. **Check DNS:** +```bash +# Test DNS resolution +nslookup google.com +dig google.com + +# Check DNS config +cat /etc/resolv.conf + +# Force DNS update +echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf +``` + +3. **Check NAT:** +```bash +# Verify NAT rules +sudo iptables -t nat -L POSTROUTING -n -v + +# Add NAT manually if missing +sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE +``` + +#### Problem: Local network not accessible +**Symptoms:** Can't reach LAN devices when VPN connected + +**Solution:** +```bash +# Add LAN route exception +sudo ip route add 192.168.1.0/24 dev eth0 + +# Or modify WireGuard AllowedIPs +# Change from: 0.0.0.0/0 +# To: 0.0.0.0/1, 128.0.0.0/1 +``` + +### WebUI Issues + +#### Problem: WebUI not loading +**Symptoms:** Connection refused, timeout + +**Solutions:** + +1. **Check service status:** +```bash +# Service status +sudo systemctl status vpn-webui + +# Restart service +sudo systemctl restart vpn-webui + +# Check if running +ps aux | grep gunicorn +``` + +2. **Check port binding:** +```bash +# Verify port is listening +sudo netstat -tlnp | grep 5000 +sudo ss -tlnp | grep 5000 + +# Check for port conflicts +sudo lsof -i :5000 +``` + +3. **Check Nginx (if used):** +```bash +# Test Nginx config +sudo nginx -t + +# Restart Nginx +sudo systemctl restart nginx + +# Check Nginx logs +sudo tail -f /var/log/nginx/error.log +``` + +#### Problem: Can't change settings +**Symptoms:** Changes don't save, errors on submit + +**Solutions:** + +1. **Check permissions:** +```bash +# Fix ownership +sudo chown -R root:root /opt/vpn-gateway + +# Fix permissions +sudo chmod 755 /opt/vpn-gateway +sudo chmod 644 /opt/vpn-gateway/app.py +``` + +2. **Check disk space:** +```bash +# Check available space +df -h /opt/vpn-gateway + +# Clean up if needed +sudo journalctl --vacuum-time=7d +sudo apt clean +``` + +### Security Issues + +#### Problem: Killswitch not working +**Symptoms:** Internet accessible without VPN + +**CRITICAL - Fix immediately:** + +1. **Re-enable killswitch:** +```bash +# Force enable +sudo /usr/local/bin/vpn-killswitch.sh enable + +# Verify rules +sudo iptables -L -n -v | grep DROP +``` + +2. **Check for rule conflicts:** +```bash +# List all rules +sudo iptables-save + +# Remove conflicting rules +sudo iptables -F OUTPUT +sudo iptables -P OUTPUT DROP +``` + +3. **Restart security monitor:** +```bash +sudo systemctl restart vpn-security-monitor +sudo systemctl status vpn-security-monitor +``` + +#### Problem: DNS leaks detected +**Symptoms:** DNS queries not going through VPN + +**Solutions:** + +1. **Force VPN DNS:** +```bash +# Lock resolv.conf +sudo chattr +i /etc/resolv.conf + +# Disable systemd-resolved +sudo systemctl stop systemd-resolved +sudo systemctl disable systemd-resolved +``` + +2. **Check firewall rules:** +```bash +# Block DNS except through VPN +sudo iptables -A OUTPUT -p udp --dport 53 ! -o wg0 -j DROP +sudo iptables -A OUTPUT -p tcp --dport 53 ! -o wg0 -j DROP +``` + +### Performance Issues + +#### Problem: Slow speeds +**Symptoms:** Poor throughput, high latency + +**Solutions:** + +1. **Optimize MTU:** +```bash +# Test optimal MTU +for mtu in 1420 1400 1380 1360; do + sudo ip link set dev wg0 mtu $mtu + echo "Testing MTU $mtu" + iperf3 -c -t 5 +done +``` + +2. **Check CPU usage:** +```bash +# Monitor CPU +top -n 1 | grep -E "wireguard|python" + +# Check interrupts +watch -n 1 'cat /proc/interrupts | grep -E "eth|wg"' +``` + +3. **Tune kernel parameters:** +```bash +# Optimize network stack +cat >> /etc/sysctl.conf << EOF +net.core.rmem_max = 134217728 +net.core.wmem_max = 134217728 +net.ipv4.tcp_rmem = 4096 87380 134217728 +net.ipv4.tcp_wmem = 4096 65536 134217728 +net.core.netdev_max_backlog = 30000 +net.ipv4.tcp_congestion_control = bbr +EOF + +sudo sysctl -p +``` + +### Diagnostic Commands + +#### Complete System Check +```bash +#!/bin/bash +echo "=== VPN Gateway Diagnostics ===" +echo "" +echo "1. Services Status:" +systemctl status vpn-webui --no-pager | head -n 10 +systemctl status vpn-killswitch --no-pager | head -n 10 +systemctl status vpn-security-monitor --no-pager | head -n 10 +echo "" +echo "2. VPN Status:" +wg show +echo "" +echo "3. Firewall Rules:" +iptables -L -n | head -n 20 +echo "" +echo "4. Network Configuration:" +ip addr show +ip route show +echo "" +echo "5. DNS Configuration:" +cat /etc/resolv.conf +echo "" +echo "6. Recent Logs:" +journalctl -u vpn-webui -n 20 --no-pager +echo "" +echo "7. Disk Usage:" +df -h /opt/vpn-gateway +echo "" +echo "8. Memory Usage:" +free -h +``` + +#### Export Debug Info +```bash +# Create debug archive +sudo tar czf vpn-debug-$(date +%s).tar.gz \ + /var/log/vpn-*.log \ + /var/log/syslog \ + /etc/wireguard/ \ + /opt/vpn-gateway/logs/ \ + <(iptables-save) \ + <(wg show) \ + <(ip addr) \ + <(ip route) \ + <(systemctl status vpn-*) +``` + +## Getting Help + +If problems persist: + +1. **Check logs thoroughly:** +```bash +sudo journalctl -xe +sudo dmesg | tail -50 +``` + +2. **Run health check:** +```bash +sudo /usr/local/bin/vpn-health-check.sh +``` + +3. **Create issue on GitHub** with: +- System info: `uname -a` +- Service status: `systemctl status vpn-*` +- Error messages +- Debug archive + +4. **Emergency recovery:** +```bash +# Disable killswitch (TEMPORARY!) +sudo iptables -P INPUT ACCEPT +sudo iptables -P OUTPUT ACCEPT +sudo iptables -P FORWARD ACCEPT +sudo iptables -F + +# Reinstall +curl -sSL https://raw.githubusercontent.com/yourusername/vpn-gateway/main/install.sh | bash +``` diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..37e0e48 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,975 @@ + + + + + + VPN Gateway Control - Multi Provider + + + +
+
+

πŸ” VPN Gateway Control Center

+

Multi-Provider Support with Permanent Killswitch

+
+ +
+

Select VPN Provider

+
+
+
🌍 Mullvad
+ Commercial VPN +
+
+
πŸ”§ Custom Server
+ Own VPS/Server +
+
+
πŸ“ Import Config
+ Existing WireGuard +
+
+
+ +
+
+
+
+ + Disconnected +
+ +
+ +
+
+
Provider
+
-
+
+
+
Server
+
-
+
+
+
Public IP
+
-
+
+
+
Location
+
-
+
+
+ +
+ πŸ›‘οΈ Security Status: PROTECTED
+ βœ“ Killswitch permanently active
+ βœ“ No internet without VPN
+ βœ“ DNS leak protection enabled +
+
+ +
+ +
+

Mullvad Server Selection

+ + + + + +
+ + + + + + + +
+ + +
+
+
+
+ + + + + + + diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..148b366 --- /dev/null +++ b/install.sh @@ -0,0 +1,1408 @@ +#!/bin/bash + +############################################################# +# # +# Mullvad VPN Gateway Installer for LXC # +# Secure VPN Gateway with Permanent Killswitch # +# # +# Usage: curl -sSL https://your-domain/install.sh | bash # +# # +############################################################# + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +# Configuration variables +INSTALL_DIR="/opt/vpn-gateway" +LOG_FILE="/var/log/vpn-gateway-install.log" +GITHUB_REPO="https://raw.githubusercontent.com/yourusername/vpn-gateway/main" +VERSION="1.0.0" + +# System variables (will be auto-detected) +LAN_INTERFACE="" +LAN_IP="" +LAN_NETWORK="" +CONTAINER_TYPE="" +MULLVAD_ACCOUNT="" + +# VPN Provider variables +VPN_PROVIDER="" +WG_CONFIG_PATH="" +WG_IMPORTED_CONFIG="" +WG_CUSTOM_LOCATION="" +WG_CUSTOM_NAME="" +WG_ENDPOINT="" +WG_SERVER_PUBKEY="" +WG_CLIENT_PRIVKEY="" +WG_CLIENT_IP="" +WG_DNS="" +WG_ALLOWED_IPS="" +BACKUP_SERVERS=() + +# ASCII Art Banner +show_banner() { + clear + echo -e "${CYAN}" + cat << "EOF" + __ __ _ _ _ __ ______ _ _ +| \/ | | | | | | \ \ / / _ \| \ | | +| \ / |_ _| | |_ ____ _ ___| | \ \ / /| |_) | \| | +| |\/| | | | | | \ \ / / _` |/ _ | | \ V / | __/| . ` | +| | | | |_| | | |\ V | (_| | __| | | | | | | |\ | +|_| |_|\__,_|_|_| \_/ \__,_|\___|_| |_| |_| |_| \_| + + Secure Gateway with Permanent Killswitch +EOF + echo -e "${NC}" + echo -e "${BOLD}Version:${NC} ${VERSION}" + echo -e "${BOLD}GitHub:${NC} github.com/yourusername/vpn-gateway" + echo "" +} + +# Logging functions +log() { + echo -e "${GREEN}[+]${NC} $1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +error() { + echo -e "${RED}[!]${NC} $1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE" +} + +warning() { + echo -e "${YELLOW}[*]${NC} $1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1" >> "$LOG_FILE" +} + +info() { + echo -e "${BLUE}[i]${NC} $1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1" >> "$LOG_FILE" +} + +# Progress spinner +spinner() { + local pid=$1 + local delay=0.1 + local spinstr='|/-\' + while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do + local temp=${spinstr#?} + printf " [%c] " "$spinstr" + local spinstr=$temp${spinstr%"$temp"} + sleep $delay + printf "\b\b\b\b\b\b" + done + printf " \b\b\b\b" +} + +# Check if running as root +check_root() { + if [[ $EUID -ne 0 ]]; then + error "This script must be run as root" + exit 1 + fi +} + +# Detect container type +detect_container() { + info "Detecting container type..." + + if [ -f /run/systemd/container ]; then + CONTAINER_TYPE=$(cat /run/systemd/container) + elif [ -f /proc/1/environ ]; then + if grep -q lxc /proc/1/environ; then + CONTAINER_TYPE="lxc" + elif grep -q docker /proc/1/environ; then + CONTAINER_TYPE="docker" + fi + fi + + if [ -n "$CONTAINER_TYPE" ]; then + log "Container type: $CONTAINER_TYPE" + else + warning "Could not detect container type, assuming LXC" + CONTAINER_TYPE="lxc" + fi +} + +# Auto-detect network configuration +detect_network() { + info "Auto-detecting network configuration..." + + # Find primary network interface (excluding lo and wg*) + LAN_INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n1) + + if [ -z "$LAN_INTERFACE" ]; then + # Fallback: find first UP interface + LAN_INTERFACE=$(ip link show | grep "state UP" | grep -v "lo:" | awk -F': ' '{print $2}' | head -n1) + fi + + if [ -z "$LAN_INTERFACE" ]; then + error "Could not detect network interface" + read -p "Please enter your network interface (e.g., eth0): " LAN_INTERFACE + fi + + # Get IP address + LAN_IP=$(ip -4 addr show "$LAN_INTERFACE" | grep inet | awk '{print $2}' | cut -d/ -f1) + + # Get network subnet + LAN_NETWORK=$(ip route | grep "$LAN_INTERFACE" | grep -v default | awk '{print $1}' | head -n1) + + if [ -z "$LAN_NETWORK" ]; then + # Calculate from IP + LAN_NETWORK=$(echo "$LAN_IP" | cut -d. -f1-3).0/24 + fi + + echo "" + echo -e "${CYAN}Detected Network Configuration:${NC}" + echo -e " Interface: ${BOLD}$LAN_INTERFACE${NC}" + echo -e " IP Address: ${BOLD}$LAN_IP${NC}" + echo -e " Network: ${BOLD}$LAN_NETWORK${NC}" + echo "" + + read -p "Is this correct? (Y/n): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]] && [ -n "$REPLY" ]; then + read -p "Enter network interface: " LAN_INTERFACE + read -p "Enter network subnet (e.g., 192.168.1.0/24): " LAN_NETWORK + LAN_IP=$(ip -4 addr show "$LAN_INTERFACE" | grep inet | awk '{print $2}' | cut -d/ -f1) + fi +} + +# Choose VPN provider +choose_vpn_provider() { + echo "" + echo -e "${CYAN}VPN Provider Selection${NC}" + echo "" + echo -e " ${BOLD}1)${NC} Mullvad VPN (Commercial Provider)" + echo -e " ${BOLD}2)${NC} Custom WireGuard (Own Server/VPS)" + echo -e " ${BOLD}3)${NC} Import existing WireGuard config" + echo "" + + while true; do + read -p "Select provider [1-3]: " VPN_PROVIDER_CHOICE + case $VPN_PROVIDER_CHOICE in + 1) + VPN_PROVIDER="mullvad" + get_mullvad_account + break + ;; + 2) + VPN_PROVIDER="custom" + get_custom_wireguard_details + break + ;; + 3) + VPN_PROVIDER="import" + import_wireguard_config + break + ;; + *) + error "Invalid choice. Please select 1, 2, or 3." + ;; + esac + done + + log "VPN provider selected: $VPN_PROVIDER" +} + +# Get Mullvad account +get_mullvad_account() { + echo "" + echo -e "${CYAN}Mullvad VPN Account Setup${NC}" + echo -e "You need a Mullvad account number to continue." + echo -e "Get one at: ${BOLD}https://mullvad.net${NC}" + echo "" + + while [ -z "$MULLVAD_ACCOUNT" ]; do + read -p "Enter your Mullvad account number: " MULLVAD_ACCOUNT + + # Validate format (16 digits) + if [[ ! "$MULLVAD_ACCOUNT" =~ ^[0-9]{16}$ ]]; then + error "Invalid account format. Should be 16 digits." + MULLVAD_ACCOUNT="" + fi + done + + log "Mullvad account configured" +} + +# Get custom WireGuard details +get_custom_wireguard_details() { + echo "" + echo -e "${CYAN}Custom WireGuard Configuration${NC}" + echo -e "Configure your own WireGuard server/VPS" + echo "" + + # Server endpoint + while [ -z "$WG_ENDPOINT" ]; do + read -p "Server endpoint (IP:Port or domain:port): " WG_ENDPOINT + if [[ ! "$WG_ENDPOINT" =~ ^[^:]+:[0-9]+$ ]]; then + error "Invalid format. Use IP:Port or domain:port (e.g., 1.2.3.4:51820)" + WG_ENDPOINT="" + fi + done + + # Server public key + while [ -z "$WG_SERVER_PUBKEY" ]; do + read -p "Server public key: " WG_SERVER_PUBKEY + if [[ ! "$WG_SERVER_PUBKEY" =~ ^[A-Za-z0-9+/]{43}=$ ]]; then + error "Invalid public key format" + WG_SERVER_PUBKEY="" + fi + done + + # Client private key (optional - generate if not provided) + read -p "Client private key (leave empty to generate): " WG_CLIENT_PRIVKEY + if [ -z "$WG_CLIENT_PRIVKEY" ]; then + WG_CLIENT_PRIVKEY=$(wg genkey) + WG_CLIENT_PUBKEY=$(echo "$WG_CLIENT_PRIVKEY" | wg pubkey) + echo -e "${GREEN}Generated keypair:${NC}" + echo -e " Private key: ${BOLD}$WG_CLIENT_PRIVKEY${NC}" + echo -e " Public key: ${BOLD}$WG_CLIENT_PUBKEY${NC}" + echo -e "${YELLOW}Add this public key to your server's peer configuration!${NC}" + read -p "Press Enter when you've added the key to your server..." + fi + + # Client IP in VPN + read -p "Client VPN IP (e.g., 10.0.0.2/32): " WG_CLIENT_IP + if [ -z "$WG_CLIENT_IP" ]; then + WG_CLIENT_IP="10.0.0.2/32" + fi + + # DNS servers + read -p "DNS servers (comma-separated, default: 1.1.1.1,1.0.0.1): " WG_DNS + if [ -z "$WG_DNS" ]; then + WG_DNS="1.1.1.1,1.0.0.1" + fi + + # Allowed IPs + read -p "Allowed IPs (default: 0.0.0.0/0): " WG_ALLOWED_IPS + if [ -z "$WG_ALLOWED_IPS" ]; then + WG_ALLOWED_IPS="0.0.0.0/0" + fi + + # Ask about kill switch bypass + echo "" + read -p "Allow direct access to server IP (bypass killswitch)? (Y/n): " -n 1 -r + echo "" + WG_DNS="1.1.1.1,1.0.0.1" + fi + + # AllowedIPs + read -p "Route all traffic through VPN? (Y/n): " -n 1 -r + echo "" + if [[ $REPLY =~ ^[Nn]$ ]]; then + read -p "Allowed IPs (comma-separated): " WG_ALLOWED_IPS + else + WG_ALLOWED_IPS="0.0.0.0/0,::/0" + fi + + # Optional: Multiple servers for failover + read -p "Add backup servers? (y/N): " -n 1 -r + echo "" + if [[ $REPLY =~ ^[Yy]$ ]]; then + BACKUP_SERVERS=() + while true; do + read -p "Backup server endpoint (or 'done' to finish): " BACKUP + if [ "$BACKUP" = "done" ] || [ -z "$BACKUP" ]; then + break + fi + BACKUP_SERVERS+=("$BACKUP") + done + fi + + # Save custom server name for later use + WG_CUSTOM_NAME="${WG_ENDPOINT%:*}_custom" + WG_CUSTOM_LOCATION="Custom Location" + + log "Custom WireGuard configuration complete" +} + +# Import existing WireGuard config +import_wireguard_config() { + echo "" + echo -e "${CYAN}Import WireGuard Configuration${NC}" + echo "" + + read -p "Path to WireGuard config file: " WG_CONFIG_PATH + + if [ ! -f "$WG_CONFIG_PATH" ]; then + error "File not found: $WG_CONFIG_PATH" + choose_vpn_provider + return + fi + + # Validate config + if ! grep -q "\[Interface\]" "$WG_CONFIG_PATH" || ! grep -q "\[Peer\]" "$WG_CONFIG_PATH"; then + error "Invalid WireGuard configuration file" + choose_vpn_provider + return + fi + + # Copy config + cp "$WG_CONFIG_PATH" /tmp/imported_wg.conf + WG_IMPORTED_CONFIG="/tmp/imported_wg.conf" + + log "WireGuard config imported successfully" +} + +# Choose VPN provider +choose_vpn_provider() { + echo "" + echo -e "${CYAN}Choose your VPN provider:${NC}" + echo "1) Mullvad VPN" + echo "2) Custom WireGuard Server" + echo "3) Import existing WireGuard config" + echo "" + + while true; do + read -p "Select option (1-3): " choice + case $choice in + 1) + VPN_PROVIDER="mullvad" + get_mullvad_account + break + ;; + 2) + VPN_PROVIDER="custom" + get_custom_wireguard_details + break + ;; + 3) + VPN_PROVIDER="import" + import_wireguard_config + break + ;; + *) + error "Invalid choice. Please select 1, 2, or 3." + ;; + esac + done +} + +# Check system requirements +check_requirements() { + info "Checking system requirements..." + + # Check OS + if [ -f /etc/os-release ]; then + . /etc/os-release + OS=$NAME + VER=$VERSION_ID + fi + + if [[ ! "$OS" =~ "Ubuntu" ]] && [[ ! "$OS" =~ "Debian" ]]; then + warning "This script is tested on Ubuntu/Debian. Continue at your own risk." + read -p "Continue anyway? (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi + + # Check kernel modules for WireGuard + if ! lsmod | grep -q wireguard; then + warning "WireGuard kernel module not loaded" + modprobe wireguard 2>/dev/null || true + fi + + log "System requirements checked" +} + +# Install dependencies +install_dependencies() { + log "Installing dependencies..." + + export DEBIAN_FRONTEND=noninteractive + + # Update package lists + apt-get update &>/dev/null & + spinner $! + + # Install required packages + local packages=( + wireguard + wireguard-tools + iptables + iptables-persistent + python3 + python3-pip + python3-venv + nginx + curl + wget + git + resolvconf + net-tools + jq + ) + + for package in "${packages[@]}"; do + echo -n " Installing $package..." + apt-get install -y "$package" &>/dev/null & + spinner $! + echo " βœ“" + done + + log "Dependencies installed successfully" +} + +# Create directory structure +create_directories() { + log "Creating directory structure..." + + mkdir -p "$INSTALL_DIR"/{scripts,config,static,logs} + mkdir -p /etc/wireguard + mkdir -p /var/log + + log "Directories created" +} + +# Install killswitch script +install_killswitch() { + log "Installing permanent killswitch..." + + # Create killswitch script + cat > /usr/local/bin/vpn-killswitch.sh << 'EOFSRIPT' +#!/bin/bash + +LAN_IF="__LAN_INTERFACE__" +LAN_NET="__LAN_NETWORK__" + +enable_killswitch() { + echo "ENABLING PERMANENT KILLSWITCH - NO INTERNET WITHOUT VPN" + + # Reset all rules + iptables -F + iptables -X + iptables -t nat -F + iptables -t nat -X + iptables -t mangle -F + iptables -t mangle -X + + # DEFAULT: BLOCK EVERYTHING + iptables -P INPUT DROP + iptables -P FORWARD DROP + iptables -P OUTPUT DROP + + # Allow loopback + iptables -A INPUT -i lo -j ACCEPT + iptables -A OUTPUT -o lo -j ACCEPT + + # Allow LAN communication + iptables -A INPUT -i $LAN_IF -s $LAN_NET -j ACCEPT + iptables -A OUTPUT -o $LAN_IF -d $LAN_NET -j ACCEPT + + # Allow DNS for initial connection (root only) + iptables -A OUTPUT -p udp --dport 53 -m owner --uid-owner root -j ACCEPT + iptables -A OUTPUT -p tcp --dport 53 -m owner --uid-owner root -j ACCEPT + + # Allow established connections + iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + + # Allow forwarding from LAN to VPN (when active) + iptables -A FORWARD -i $LAN_IF -s $LAN_NET -j ACCEPT + + # Block IPv6 completely + ip6tables -P INPUT DROP + ip6tables -P FORWARD DROP + ip6tables -P OUTPUT DROP + ip6tables -A INPUT -i lo -j ACCEPT + ip6tables -A OUTPUT -o lo -j ACCEPT + + # Save rules + iptables-save > /etc/iptables/rules.v4 + ip6tables-save > /etc/iptables/rules.v6 + + echo "KILLSWITCH ACTIVE - System is now protected" +} + +disable_killswitch() { + echo "WARNING: Killswitch cannot be disabled for security!" + enable_killswitch +} + +case "$1" in + enable|disable) + enable_killswitch + ;; + *) + echo "Usage: $0 {enable|disable}" + exit 1 + ;; +esac +EOFSCRIPT + + # Replace placeholders + sed -i "s|__LAN_INTERFACE__|$LAN_INTERFACE|g" /usr/local/bin/vpn-killswitch.sh + sed -i "s|__LAN_NETWORK__|$LAN_NETWORK|g" /usr/local/bin/vpn-killswitch.sh + + chmod +x /usr/local/bin/vpn-killswitch.sh + + # Create systemd service + cat > /etc/systemd/system/vpn-killswitch.service << 'EOF' +[Unit] +Description=VPN Killswitch - Block ALL traffic except through VPN +DefaultDependencies=no +Before=network-pre.target +Wants=network-pre.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/vpn-killswitch.sh enable + +[Install] +WantedBy=sysinit.target +EOF + + # Enable and start killswitch + systemctl daemon-reload + systemctl enable vpn-killswitch.service + systemctl start vpn-killswitch.service + + log "Killswitch installed and activated" +} + +# Install VPN provider specific components +install_vpn_provider() { + log "Installing VPN provider components..." + + case "$VPN_PROVIDER" in + mullvad) + install_mullvad + ;; + custom) + setup_custom_provider + ;; + import) + setup_import_provider + ;; + esac +} + +# Install Mullvad +install_mullvad() { + log "Installing Mullvad client..." + + # Download Mullvad signing key + curl -fsSL https://mullvad.net/media/mullvad-code-signing.asc | gpg --dearmor -o /usr/share/keyrings/mullvad-keyring.gpg + + # Add Mullvad repository + echo "deb [signed-by=/usr/share/keyrings/mullvad-keyring.gpg arch=$( dpkg --print-architecture )] https://repository.mullvad.net/deb/stable $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/mullvad.list + + # Update and install + apt-get update &>/dev/null + apt-get install -y mullvad-vpn &>/dev/null || { + warning "Could not install Mullvad client, using WireGuard directly" + } + + # Login to Mullvad + if command -v mullvad &>/dev/null; then + mullvad account login "$MULLVAD_ACCOUNT" &>/dev/null || { + warning "Could not login to Mullvad account" + } + fi + + # Generate WireGuard keys + if [ ! -f /etc/wireguard/mullvad_private.key ]; then + wg genkey | tee /etc/wireguard/mullvad_private.key | wg pubkey > /etc/wireguard/mullvad_public.key + chmod 600 /etc/wireguard/mullvad_private.key + fi + + # Save config + echo "mullvad" > "$INSTALL_DIR/provider.conf" + echo "$MULLVAD_ACCOUNT" > "$INSTALL_DIR/.mullvad_account" + chmod 600 "$INSTALL_DIR/.mullvad_account" + + log "Mullvad configuration complete" +} + +# Setup custom provider +setup_custom_provider() { + log "Setting up custom WireGuard provider..." + + # Create config file for custom servers + mkdir -p "$INSTALL_DIR/providers" + + # Save the custom server configuration + cat > "$INSTALL_DIR/providers/custom_servers.json" << EOF +{ + "$WG_CUSTOM_LOCATION": { + "Custom": [{ + "hostname": "$WG_CUSTOM_NAME", + "endpoint": "$WG_ENDPOINT", + "public_key": "$WG_SERVER_PUBKEY", + "private_key": "$WG_CLIENT_PRIVKEY", + "address": "$WG_CLIENT_IP", + "dns": "$WG_DNS", + "allowed_ips": "$WG_ALLOWED_IPS", + "type": "WireGuard", + "provider": "Custom" + }] + } +} +EOF + + # Save provider config + echo "custom" > "$INSTALL_DIR/provider.conf" + + # If backup servers were provided + if [ ${#BACKUP_SERVERS[@]} -gt 0 ]; then + log "Adding backup servers..." + # Additional logic for backup servers + fi + + log "Custom provider setup complete" +} + +# Setup import provider +setup_import_provider() { + log "Setting up import provider..." + + mkdir -p "$INSTALL_DIR/providers/imported" + + # Copy imported config + if [ -n "$WG_IMPORTED_CONFIG" ]; then + cp "$WG_IMPORTED_CONFIG" "$INSTALL_DIR/providers/imported/" + log "Imported configuration saved" + fi + + # Save provider config + echo "import" > "$INSTALL_DIR/provider.conf" + + log "Import provider setup complete" +} + +# Install VPN provider (unified function) +install_vpn_provider() { + case "$VPN_PROVIDER" in + "mullvad") + setup_mullvad_provider + ;; + "custom") + setup_custom_provider + ;; + "import") + setup_import_provider + ;; + *) + error "Unknown VPN provider: $VPN_PROVIDER" + exit 1 + ;; + esac +} + +# Install Python backend +install_backend() { + log "Installing VPN Gateway backend..." + + # Ensure install directory exists + mkdir -p "$INSTALL_DIR" + + # Create virtual environment + python3 -m venv "$INSTALL_DIR/venv" + source "$INSTALL_DIR/venv/bin/activate" + + # Install Python packages + pip install --upgrade pip &>/dev/null + pip install flask flask-cors requests gunicorn pyyaml &>/dev/null + + # Download or create the multi-provider backend + # For production, this would be downloaded from GitHub + # Here we create it inline for the complete solution + + log "Installing multi-provider backend..." + + # The backend app.py would be downloaded from GitHub in production: + # wget -O "$INSTALL_DIR/app.py" "$GITHUB_REPO/app.py" + + # For now, we use a simplified version that supports all providers + cat > "$INSTALL_DIR/app.py" << 'EOFAPP' +#!/usr/bin/env python3 +# Multi-Provider VPN Backend +# This is a placeholder - in production, use the full backend from the artifact +# Download from: https://github.com/yourusername/vpn-gateway/blob/main/backend/app.py + +from flask import Flask, request, jsonify, send_from_directory +from flask_cors import CORS +import subprocess +import json +import os +import logging + +app = Flask(__name__) +CORS(app) + +# ... (Full backend code would be here) +# For production, download the complete multi-provider backend + +@app.route('/') +def index(): + return send_from_directory('__INSTALL_DIR__/static', 'index.html') + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) +EOFAPP + + # Replace placeholders + sed -i "s|__INSTALL_DIR__|$INSTALL_DIR|g" "$INSTALL_DIR/app.py" + + log "Backend installed" +} +#!/usr/bin/env python3 + +from flask import Flask, request, jsonify, send_from_directory +from flask_cors import CORS +import subprocess +import json +import os +import re +import requests +import time +import logging +from pathlib import Path + +app = Flask(__name__) +CORS(app) + +# Setup logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler('/var/log/vpn-gateway.log'), + logging.StreamHandler() + ] +) + +MULLVAD_SERVERS = {} +LAST_SERVER_UPDATE = 0 +VPN_STATUS = { + 'connected': False, + 'server': None, + 'ip': None, + 'location': None, + 'start_time': None +} + +def update_mullvad_servers(): + global MULLVAD_SERVERS, LAST_SERVER_UPDATE + try: + response = requests.get('https://api.mullvad.net/www/relays/all/', timeout=10) + servers = response.json() + + organized = {} + for server in servers: + if server.get('type') == 'wireguard' and server.get('active'): + country = server.get('country_name', 'Unknown') + city = server.get('city_name', 'Unknown') + + if country not in organized: + organized[country] = {} + if city not in organized[country]: + organized[country][city] = [] + + organized[country][city].append({ + 'hostname': server['hostname'], + 'ipv4': server['ipv4_addr_in'], + 'type': 'WireGuard' + }) + + global MULLVAD_SERVERS + MULLVAD_SERVERS = organized + LAST_SERVER_UPDATE = time.time() + return True + except Exception as e: + logging.error(f"Failed to update servers: {e}") + return False + +def generate_wireguard_config(server_hostname): + try: + server_info = None + for country in MULLVAD_SERVERS.values(): + for city in country.values(): + for server in city: + if server['hostname'] == server_hostname: + server_info = server + break + + if not server_info: + return False + + with open('/etc/wireguard/mullvad_private.key', 'r') as f: + private_key = f.read().strip() + + # Mullvad public key + mullvad_pubkey = "g+9JNZp3SvLPvBb+PzXHyOPHhqNiUdATrz1YdNEPvWo=" + + config = f"""[Interface] +PrivateKey = {private_key} +Address = 10.64.0.2/32,fc00:bbbb:bbbb:bb01::2/128 +DNS = 100.64.0.1 + +PreUp = iptables -F OUTPUT +PreUp = iptables -F FORWARD +PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostUp = iptables -I FORWARD -i __LAN_INTERFACE__ -o %i -j ACCEPT +PostUp = iptables -t nat -A POSTROUTING -o %i -j MASQUERADE +PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT +PostDown = iptables -t nat -D POSTROUTING -o %i -j MASQUERADE + +[Peer] +PublicKey = {mullvad_pubkey} +AllowedIPs = 0.0.0.0/0,::/0 +Endpoint = {server_info['ipv4']}:51820 +PersistentKeepalive = 25 +""" + + # Add firewall exception for this server + subprocess.run([ + 'iptables', '-I', 'OUTPUT', '1', '-p', 'udp', + '--dport', '51820', '-d', server_info['ipv4'], '-j', 'ACCEPT' + ]) + + with open('/etc/wireguard/wg0.conf', 'w') as f: + f.write(config) + os.chmod('/etc/wireguard/wg0.conf', 0o600) + + return True + except Exception as e: + logging.error(f"Failed to generate config: {e}") + return False + +def check_vpn_status(): + global VPN_STATUS + try: + result = subprocess.run(['wg', 'show', 'wg0'], capture_output=True, text=True) + + if result.returncode == 0: + VPN_STATUS['connected'] = True + + # Get public IP + try: + response = requests.get('https://am.i.mullvad.net/json', timeout=5) + data = response.json() + VPN_STATUS['ip'] = data.get('ip') + VPN_STATUS['location'] = f"{data.get('city')}, {data.get('country')}" + except: + pass + else: + VPN_STATUS['connected'] = False + VPN_STATUS['server'] = None + VPN_STATUS['ip'] = None + VPN_STATUS['location'] = None + except: + VPN_STATUS['connected'] = False + +@app.route('/') +def index(): + return send_from_directory('__INSTALL_DIR__/static', 'index.html') + +@app.route('/api/servers') +def get_servers(): + global LAST_SERVER_UPDATE + if time.time() - LAST_SERVER_UPDATE > 3600: + update_mullvad_servers() + return jsonify({'servers': MULLVAD_SERVERS}) + +@app.route('/api/status') +def get_status(): + check_vpn_status() + uptime = None + if VPN_STATUS['connected'] and VPN_STATUS['start_time']: + uptime_seconds = int(time.time() - VPN_STATUS['start_time']) + hours = uptime_seconds // 3600 + minutes = (uptime_seconds % 3600) // 60 + uptime = f"{hours}h {minutes}m" + + return jsonify({ + 'connected': VPN_STATUS['connected'], + 'server': VPN_STATUS['server'], + 'ip': VPN_STATUS['ip'], + 'location': VPN_STATUS['location'], + 'uptime': uptime + }) + +@app.route('/api/connect', methods=['POST']) +def connect_vpn(): + data = request.json + server = data.get('server') + + try: + subprocess.run(['wg-quick', 'down', 'wg0'], capture_output=True) + + if not generate_wireguard_config(server): + return jsonify({'success': False, 'error': 'Failed to generate config'}) + + result = subprocess.run(['wg-quick', 'up', 'wg0'], capture_output=True, text=True) + + if result.returncode == 0: + VPN_STATUS['start_time'] = time.time() + VPN_STATUS['server'] = server + return jsonify({'success': True}) + else: + return jsonify({'success': False, 'error': result.stderr}) + except Exception as e: + return jsonify({'success': False, 'error': str(e)}) + +@app.route('/api/disconnect', methods=['POST']) +def disconnect_vpn(): + try: + result = subprocess.run(['wg-quick', 'down', 'wg0'], capture_output=True, text=True) + VPN_STATUS['start_time'] = None + return jsonify({'success': result.returncode == 0}) + except Exception as e: + return jsonify({'success': False, 'error': str(e)}) + +if __name__ == '__main__': + update_mullvad_servers() + app.run(host='0.0.0.0', port=5000) +EOFAPP + + # Replace placeholders + sed -i "s|__LAN_INTERFACE__|$LAN_INTERFACE|g" "$INSTALL_DIR/app.py" + sed -i "s|__INSTALL_DIR__|$INSTALL_DIR|g" "$INSTALL_DIR/app.py" + + log "Backend installed" +} + +# Setup nginx (placeholder function) +setup_nginx() { + log "Setting up nginx reverse proxy..." + # This would contain nginx configuration + # For now, we'll skip this as it's optional + log "Nginx setup skipped (optional)" +} + +# Finalize installation +finalize_installation() { + log "Finalizing installation..." + + # Set proper permissions + chown -R root:root "$INSTALL_DIR" + chmod +x "$INSTALL_DIR"/scripts/*.sh 2>/dev/null || true + + # Enable and start services + systemctl enable vpn-webui vpn-killswitch vpn-security-monitor + systemctl start vpn-killswitch + systemctl start vpn-security-monitor + systemctl start vpn-webui + + log "Installation finalized" +} + +# Show installation summary +show_summary() { + echo "" + echo -e "${GREEN}${BOLD}Installation Complete!${NC}" + echo "" + echo -e "${CYAN}Services Status:${NC}" + systemctl is-active vpn-webui && echo -e " WebUI: ${GREEN}Running${NC}" || echo -e " WebUI: ${RED}Stopped${NC}" + systemctl is-active vpn-killswitch && echo -e " Killswitch: ${GREEN}Active${NC}" || echo -e " Killswitch: ${RED}Inactive${NC}" + systemctl is-active vpn-security-monitor && echo -e " Security Monitor: ${GREEN}Running${NC}" || echo -e " Security Monitor: ${RED}Stopped${NC}" + echo "" + echo -e "${CYAN}Access Information:${NC}" + echo -e " WebUI URL: ${BOLD}http://$LAN_IP:5000${NC}" + echo -e " Install Dir: ${BOLD}$INSTALL_DIR${NC}" + echo -e " Log File: ${BOLD}$LOG_FILE${NC}" + echo "" + echo -e "${YELLOW}Important Notes:${NC}" + echo -e " β€’ The killswitch is ${BOLD}PERMANENTLY ACTIVE${NC}" + echo -e " β€’ No internet access without VPN connection" + echo -e " β€’ Use the WebUI to connect to VPN servers" + echo "" +} + +# Install WebUI +install_webui() { + log "Installing WebUI..." + + # Download WebUI from GitHub or create inline + cat > "$INSTALL_DIR/static/index.html" << 'EOFHTML' + + + + + + VPN Gateway Control + + + +
+

πŸ” VPN Gateway Control

+ +
+ πŸ›‘οΈ Security Status: PROTECTED
+ βœ“ Killswitch permanently active
+ βœ“ No internet without VPN +
+ +
+

Status: Checking...

+

IP: -

+

Location: -

+
+ + + + + + + + + +
+ + + + +EOFHTML + + log "WebUI installed" +} + +# Setup systemd services +setup_services() { + log "Setting up systemd services..." + + # VPN WebUI service + cat > /etc/systemd/system/vpn-webui.service << EOF +[Unit] +Description=VPN Gateway WebUI +After=network.target vpn-killswitch.service + +[Service] +Type=simple +User=root +WorkingDirectory=$INSTALL_DIR +Environment="PATH=$INSTALL_DIR/venv/bin" +ExecStart=$INSTALL_DIR/venv/bin/gunicorn --bind 0.0.0.0:5000 app:app +Restart=always + +[Install] +WantedBy=multi-user.target +EOF + + # Security monitor service + cat > /etc/systemd/system/vpn-security-monitor.service << 'EOF' +[Unit] +Description=VPN Security Monitor +After=vpn-killswitch.service + +[Service] +Type=simple +ExecStart=/usr/local/bin/vpn-security-monitor.sh +Restart=always + +[Install] +WantedBy=multi-user.target +EOF + + # Create security monitor script + cat > /usr/local/bin/vpn-security-monitor.sh << 'EOFMON' +#!/bin/bash +while true; do + # Check if killswitch is active + if ! iptables -L -n | grep -q "policy DROP"; then + /usr/local/bin/vpn-killswitch.sh enable + fi + sleep 10 +done +EOFMON + + chmod +x /usr/local/bin/vpn-security-monitor.sh + + # Reload and start services + systemctl daemon-reload + systemctl enable vpn-killswitch vpn-webui vpn-security-monitor + systemctl start vpn-killswitch vpn-webui vpn-security-monitor + + log "Services configured and started" +} + +# Configure Nginx +setup_nginx() { + log "Configuring Nginx..." + + cat > /etc/nginx/sites-available/vpn-gateway << EOF +server { + listen 80; + server_name _; + + location / { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + } +} +EOF + + ln -sf /etc/nginx/sites-available/vpn-gateway /etc/nginx/sites-enabled/ + rm -f /etc/nginx/sites-enabled/default + + nginx -t && systemctl restart nginx + + log "Nginx configured" +} + +# Final setup +finalize_installation() { + log "Finalizing installation..." + + # Set IP forwarding + echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf + echo "net.ipv6.conf.all.disable_ipv6=1" >> /etc/sysctl.conf + sysctl -p &>/dev/null + + # Save iptables rules + netfilter-persistent save &>/dev/null + + log "Installation complete!" +} + +# Show summary +show_summary() { + echo "" + echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}β•‘ VPN Gateway Installation Complete! β•‘${NC}" + echo -e "${GREEN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}" + echo "" + echo -e "${CYAN}Access WebUI:${NC}" + echo -e " Local: ${BOLD}http://$LAN_IP${NC}" + echo -e " Port: ${BOLD}5000${NC}" + echo "" + echo -e "${CYAN}VPN Provider:${NC}" + echo -e " Type: ${BOLD}$VPN_PROVIDER${NC}" + if [ "$VPN_PROVIDER" = "mullvad" ]; then + echo -e " Account: ${BOLD}Configured${NC}" + elif [ "$VPN_PROVIDER" = "custom" ]; then + echo -e " Server: ${BOLD}$WG_ENDPOINT${NC}" + elif [ "$VPN_PROVIDER" = "import" ]; then + echo -e " Config: ${BOLD}Imported${NC}" + fi + echo "" + echo -e "${CYAN}Security Status:${NC}" + echo -e " Killswitch: ${GREEN}βœ“ Active${NC}" + echo -e " Firewall: ${GREEN}βœ“ Configured${NC}" + echo -e " No Leaks: ${GREEN}βœ“ Protected${NC}" + echo "" + echo -e "${YELLOW}Important:${NC}" + echo -e " β€’ Killswitch is ${BOLD}permanently active${NC}" + echo -e " β€’ ${BOLD}No internet${NC} without VPN connection" + echo -e " β€’ Configure clients to use ${BOLD}$LAN_IP${NC} as gateway" + echo "" + echo -e "${CYAN}Commands:${NC}" + echo -e " Status: ${BOLD}systemctl status vpn-webui${NC}" + echo -e " Logs: ${BOLD}journalctl -u vpn-webui -f${NC}" + echo -e " Test: ${BOLD}curl http://localhost:5000/api/status${NC}" + echo "" +} + +# Cleanup on error +cleanup_on_error() { + error "Installation failed! Cleaning up..." + systemctl stop vpn-webui vpn-killswitch vpn-security-monitor 2>/dev/null + rm -rf "$INSTALL_DIR" + exit 1 +} + +# Main installation flow +main() { + trap cleanup_on_error ERR + + show_banner + check_root + detect_container + check_requirements + detect_network + choose_vpn_provider + + echo "" + echo -e "${CYAN}Ready to install with the following configuration:${NC}" + echo -e " Network Interface: ${BOLD}$LAN_INTERFACE${NC}" + echo -e " Network Subnet: ${BOLD}$LAN_NETWORK${NC}" + echo -e " Container Type: ${BOLD}$CONTAINER_TYPE${NC}" + echo -e " VPN Provider: ${BOLD}$VPN_PROVIDER${NC}" + + if [ "$VPN_PROVIDER" = "mullvad" ]; then + echo -e " Mullvad Account: ${BOLD}${MULLVAD_ACCOUNT:0:4}...${MULLVAD_ACCOUNT: -4}${NC}" + elif [ "$VPN_PROVIDER" = "custom" ]; then + echo -e " Custom Server: ${BOLD}$WG_ENDPOINT${NC}" + elif [ "$VPN_PROVIDER" = "import" ]; then + echo -e " Config File: ${BOLD}$WG_IMPORTED_CONFIG${NC}" + fi + + echo "" + read -p "Proceed with installation? (Y/n): " -n 1 -r + echo "" + + if [[ ! $REPLY =~ ^[Yy]$ ]] && [ -n "$REPLY" ]; then + echo "Installation cancelled" + exit 0 + fi + + install_dependencies + create_directories + install_killswitch + install_vpn_provider # Replaces install_mullvad + install_backend + install_webui + setup_services + setup_nginx + finalize_installation + + show_summary +} + +# Run main function +main "$@" diff --git a/scripts/health-check.sh b/scripts/health-check.sh new file mode 100755 index 0000000..3795f27 --- /dev/null +++ b/scripts/health-check.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +# VPN Gateway Health Check Script +# Comprehensive system health monitoring +# Version: 1.0.0 + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Scoring +TOTAL_SCORE=0 +MAX_SCORE=100 +ISSUES=() + +check_mark() { + echo -e "${GREEN}βœ“${NC}" +} + +x_mark() { + echo -e "${RED}βœ—${NC}" +} + +warning_mark() { + echo -e "${YELLOW}⚠${NC}" +} + +add_score() { + TOTAL_SCORE=$((TOTAL_SCORE + $1)) +} + +add_issue() { + ISSUES+=("$1") +} + +echo -e "${BLUE}=== VPN Gateway Health Check ===${NC}" +echo "" + +# 1. Check Services +echo -n "Checking services... " +services_ok=true +for service in vpn-webui vpn-killswitch vpn-security-monitor; do + if systemctl is-active $service >/dev/null 2>&1; then + add_score 10 + else + services_ok=false + add_issue "Service $service is not running" + fi +done +[ "$services_ok" = true ] && check_mark || x_mark + +# 2. Check Killswitch +echo -n "Checking killswitch... " +if iptables -L OUTPUT -n | grep -q "policy DROP"; then + add_score 20 + check_mark +else + add_issue "Killswitch not active!" + x_mark +fi + +# 3. Check VPN Connection +echo -n "Checking VPN connection... " +if wg show wg0 >/dev/null 2>&1; then + add_score 15 + check_mark +else + add_issue "VPN not connected" + warning_mark +fi + +# 4. Check for leaks +echo -n "Checking for leaks... " +if ! ping -c 1 -W 1 8.8.8.8 >/dev/null 2>&1; then + if wg show wg0 >/dev/null 2>&1; then + add_issue "VPN connected but no internet" + warning_mark + else + add_score 15 + check_mark + fi +else + if wg show wg0 >/dev/null 2>&1; then + add_score 15 + check_mark + else + add_issue "CRITICAL: Internet accessible without VPN!" + x_mark + fi +fi + +# 5. Check DNS +echo -n "Checking DNS configuration... " +dns_ok=true +while read -r dns; do + case "$dns" in + 127.0.0.1|10.*|172.*|192.168.*|100.64.*) + ;; + *) + dns_ok=false + add_issue "Public DNS detected: $dns" + ;; + esac +done < <(grep "^nameserver" /etc/resolv.conf | awk '{print $2}') +if [ "$dns_ok" = true ]; then + add_score 10 + check_mark +else + warning_mark +fi + +# 6. Check disk space +echo -n "Checking disk space... " +disk_usage=$(df /opt/vpn-gateway | tail -1 | awk '{print $5}' | sed 's/%//') +if [ "$disk_usage" -lt 80 ]; then + add_score 5 + check_mark +elif [ "$disk_usage" -lt 90 ]; then + add_issue "Disk usage high: ${disk_usage}%" + warning_mark +else + add_issue "Critical disk usage: ${disk_usage}%" + x_mark +fi + +# 7. Check WebUI accessibility +echo -n "Checking WebUI... " +if curl -s http://localhost:5000/api/status >/dev/null 2>&1; then + add_score 10 + check_mark +else + add_issue "WebUI not accessible" + x_mark +fi + +# Results +echo "" +echo -e "${BLUE}=== Health Score: $TOTAL_SCORE/$MAX_SCORE ===${NC}" +echo "" + +if [ $TOTAL_SCORE -ge 90 ]; then + echo -e "${GREEN}System Status: EXCELLENT${NC}" +elif [ $TOTAL_SCORE -ge 70 ]; then + echo -e "${GREEN}System Status: GOOD${NC}" +elif [ $TOTAL_SCORE -ge 50 ]; then + echo -e "${YELLOW}System Status: WARNING${NC}" +else + echo -e "${RED}System Status: CRITICAL${NC}" +fi + +if [ ${#ISSUES[@]} -gt 0 ]; then + echo "" + echo "Issues found:" + for issue in "${ISSUES[@]}"; do + echo " - $issue" + done +fi + +exit $((100 - TOTAL_SCORE)) diff --git a/scripts/killswitch.sh b/scripts/killswitch.sh new file mode 100755 index 0000000..8b28452 --- /dev/null +++ b/scripts/killswitch.sh @@ -0,0 +1,241 @@ +#!/bin/bash + +############################################################# +# scripts/killswitch.sh # +############################################################# + +cat > scripts/killswitch.sh << 'EOFKILLSWITCH' +#!/bin/bash + +# VPN Gateway Killswitch Script +# CRITICAL: This script ensures NO traffic leaks without VPN +# Version: 1.0.0 + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Get network configuration from install +if [ -f /opt/vpn-gateway/network.conf ]; then + source /opt/vpn-gateway/network.conf +else + # Fallback to auto-detection + LAN_IF=$(ip route | grep default | awk '{print $5}' | head -n1) + LAN_NET=$(ip route | grep "$LAN_IF" | grep -v default | awk '{print $1}' | head -n1) +fi + +# Logging +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> /var/log/vpn-killswitch.log + echo -e "${GREEN}[+]${NC} $1" +} + +error() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> /var/log/vpn-killswitch.log + echo -e "${RED}[!]${NC} $1" +} + +warning() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1" >> /var/log/vpn-killswitch.log + echo -e "${YELLOW}[*]${NC} $1" +} + +enable_killswitch() { + log "ENABLING PERMANENT KILLSWITCH - NO INTERNET WITHOUT VPN" + + # Backup current rules (just in case) + iptables-save > /tmp/iptables.backup.$(date +%s) 2>/dev/null || true + + # Reset all rules + iptables -F + iptables -X + iptables -t nat -F + iptables -t nat -X + iptables -t mangle -F + iptables -t mangle -X + iptables -t raw -F + iptables -t raw -X + + # DEFAULT POLICIES: DROP EVERYTHING + iptables -P INPUT DROP + iptables -P FORWARD DROP + iptables -P OUTPUT DROP + + log "Default policies set to DROP" + + # CRITICAL: Allow loopback (required for system operation) + iptables -A INPUT -i lo -j ACCEPT + iptables -A OUTPUT -o lo -j ACCEPT + + # Allow LAN communication (for WebUI and local clients) + if [ -n "$LAN_IF" ] && [ -n "$LAN_NET" ]; then + iptables -A INPUT -i $LAN_IF -s $LAN_NET -j ACCEPT + iptables -A OUTPUT -o $LAN_IF -d $LAN_NET -j ACCEPT + log "LAN communication allowed: $LAN_IF ($LAN_NET)" + fi + + # Allow DNS for initial VPN connection (root only, limited) + iptables -A OUTPUT -p udp --dport 53 -m owner --uid-owner root -m limit --limit 10/min -j ACCEPT + iptables -A OUTPUT -p tcp --dport 53 -m owner --uid-owner root -m limit --limit 10/min -j ACCEPT + + # Allow DHCP client (if needed) + iptables -A OUTPUT -p udp --sport 68 --dport 67 -j ACCEPT + iptables -A INPUT -p udp --sport 67 --dport 68 -j ACCEPT + + # Allow established/related connections + iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + + # Allow forwarding from LAN (will only work when VPN is up) + if [ -n "$LAN_IF" ] && [ -n "$LAN_NET" ]; then + iptables -A FORWARD -i $LAN_IF -s $LAN_NET -j ACCEPT + fi + + # Log dropped packets (optional, can be verbose) + # iptables -A INPUT -j LOG --log-prefix "INPUT-DROP: " --log-level 4 + # iptables -A OUTPUT -j LOG --log-prefix "OUTPUT-DROP: " --log-level 4 + + # IPv6: Complete blocking (unless you use IPv6 VPN) + ip6tables -P INPUT DROP + ip6tables -P FORWARD DROP + ip6tables -P OUTPUT DROP + ip6tables -A INPUT -i lo -j ACCEPT + ip6tables -A OUTPUT -o lo -j ACCEPT + + # Save rules for persistence + mkdir -p /etc/iptables + iptables-save > /etc/iptables/rules.v4 + ip6tables-save > /etc/iptables/rules.v6 + + # Ensure persistence across reboots + if ! systemctl is-enabled netfilter-persistent >/dev/null 2>&1; then + systemctl enable netfilter-persistent 2>/dev/null || true + fi + + log "KILLSWITCH ACTIVE - System is now protected" + log "Rules saved to /etc/iptables/" + + # Verify killswitch is working + verify_killswitch +} + +disable_killswitch() { + error "KILLSWITCH CANNOT BE DISABLED FOR SECURITY REASONS!" + warning "This is a security feature. The killswitch must remain active." + warning "If you really need to disable it, you must manually flush iptables rules." + warning "This would leave your system vulnerable to leaks!" + + # Re-enable killswitch immediately + enable_killswitch + + return 1 +} + +verify_killswitch() { + log "Verifying killswitch status..." + + # Check DROP policies + if iptables -L -n | grep -q "Chain INPUT (policy DROP)" && \ + iptables -L -n | grep -q "Chain OUTPUT (policy DROP)" && \ + iptables -L -n | grep -q "Chain FORWARD (policy DROP)"; then + log "βœ“ Killswitch policies verified: DROP" + else + error "βœ— Killswitch policies NOT active!" + enable_killswitch + return 1 + fi + + # Test that we cannot reach internet directly + if ping -c 1 -W 1 8.8.8.8 >/dev/null 2>&1; then + if wg show wg0 >/dev/null 2>&1; then + log "βœ“ Internet accessible (VPN is connected)" + else + error "βœ— LEAK DETECTED: Internet accessible without VPN!" + enable_killswitch + return 1 + fi + else + if wg show wg0 >/dev/null 2>&1; then + warning "VPN appears connected but internet not reachable" + else + log "βœ“ Internet blocked (VPN not connected)" + fi + fi + + log "Killswitch verification complete" +} + +status_killswitch() { + echo -e "${GREEN}=== VPN Killswitch Status ===${NC}" + echo "" + + # Check policies + echo "Firewall Policies:" + iptables -L -n | grep "Chain.*policy" | while read line; do + if echo "$line" | grep -q "DROP"; then + echo -e " ${GREEN}βœ“${NC} $line" + else + echo -e " ${RED}βœ—${NC} $line" + fi + done + + echo "" + echo "Active Rules Summary:" + echo " INPUT: $(iptables -L INPUT -n | grep -c ACCEPT) ACCEPT rules" + echo " OUTPUT: $(iptables -L OUTPUT -n | grep -c ACCEPT) ACCEPT rules" + echo " FORWARD: $(iptables -L FORWARD -n | grep -c ACCEPT) ACCEPT rules" + + echo "" + echo "VPN Status:" + if wg show wg0 >/dev/null 2>&1; then + echo -e " ${GREEN}βœ“${NC} WireGuard interface active" + echo " Endpoint: $(wg show wg0 endpoints | awk '{print $2}')" + else + echo -e " ${YELLOW}⚠${NC} WireGuard interface not active" + fi + + echo "" + echo "Leak Test:" + if ping -c 1 -W 1 8.8.8.8 >/dev/null 2>&1; then + if wg show wg0 >/dev/null 2>&1; then + echo -e " ${GREEN}βœ“${NC} Internet accessible via VPN" + else + echo -e " ${RED}βœ— LEAK: Internet accessible without VPN!${NC}" + fi + else + echo -e " ${GREEN}βœ“${NC} Internet blocked (killswitch working)" + fi +} + +# Main logic +case "${1:-enable}" in + enable|start) + enable_killswitch + ;; + disable|stop) + disable_killswitch + ;; + verify|check) + verify_killswitch + ;; + status) + status_killswitch + ;; + restart|reload) + enable_killswitch + ;; + *) + echo "Usage: $0 {enable|disable|verify|status|restart}" + echo " enable - Enable killswitch (default)" + echo " disable - Disable killswitch (blocked for security)" + echo " verify - Verify killswitch is working" + echo " status - Show detailed status" + echo " restart - Restart killswitch" + exit 1 + ;; +esac diff --git a/scripts/security-monitor.sh b/scripts/security-monitor.sh new file mode 100755 index 0000000..adc286a --- /dev/null +++ b/scripts/security-monitor.sh @@ -0,0 +1,258 @@ +############################################################# +# scripts/security-monitor.sh # +############################################################# + +cat > scripts/security-monitor.sh << 'EOFSECMON' +#!/bin/bash + +# VPN Security Monitor +# Continuous monitoring of killswitch and VPN status +# Version: 1.0.0 + +# Configuration +CHECK_INTERVAL=10 # seconds +ALERT_EMAIL="" # Set email for alerts +LOG_FILE="/var/log/vpn-security-monitor.log" +STATE_FILE="/var/run/vpn-monitor.state" + +# Source network config +if [ -f /opt/vpn-gateway/network.conf ]; then + source /opt/vpn-gateway/network.conf +fi + +# Logging functions +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +alert() { + local message="$1" + log "ALERT: $message" + + # Send email alert if configured + if [ -n "$ALERT_EMAIL" ]; then + echo "$message" | mail -s "VPN Security Alert" "$ALERT_EMAIL" 2>/dev/null || true + fi + + # System notification (if available) + if command -v notify-send >/dev/null 2>&1; then + notify-send "VPN Security Alert" "$message" -u critical + fi + + # Log to syslog + logger -t "vpn-security" -p auth.crit "$message" +} + +# Check functions +check_killswitch() { + # Verify DROP policies are active + local policies_ok=true + + for chain in INPUT OUTPUT FORWARD; do + if ! iptables -L $chain -n | grep -q "policy DROP"; then + alert "Killswitch policy missing for chain $chain!" + policies_ok=false + fi + done + + if [ "$policies_ok" = false ]; then + log "Reactivating killswitch..." + /usr/local/bin/vpn-killswitch.sh enable + return 1 + fi + + return 0 +} + +check_vpn_connection() { + if wg show wg0 >/dev/null 2>&1; then + # VPN interface exists, check if it's actually working + local endpoint=$(wg show wg0 endpoints | awk '{print $2}') + + if [ -z "$endpoint" ]; then + log "WARNING: VPN interface exists but no endpoint configured" + return 1 + fi + + # Check last handshake + local last_handshake=$(wg show wg0 latest-handshakes | awk '{print $2}') + local current_time=$(date +%s) + + if [ -n "$last_handshake" ] && [ "$last_handshake" -ne 0 ]; then + local time_diff=$((current_time - last_handshake)) + + # If last handshake was more than 3 minutes ago, connection might be dead + if [ $time_diff -gt 180 ]; then + log "WARNING: Last WireGuard handshake was ${time_diff} seconds ago" + return 2 + fi + fi + + return 0 + else + return 1 + fi +} + +check_dns_leaks() { + # Check if DNS is going through VPN + local dns_servers=$(cat /etc/resolv.conf | grep "^nameserver" | awk '{print $2}') + + for dns in $dns_servers; do + # Check if DNS server is in private range or VPN provider's DNS + case "$dns" in + 10.*|172.16.*|172.17.*|172.18.*|172.19.*|172.2*|172.30.*|172.31.*|192.168.*|100.64.*) + # Private IP, likely VPN DNS + ;; + 127.*) + # Localhost, check if it's a DNS proxy + if systemctl is-active systemd-resolved >/dev/null 2>&1; then + log "WARNING: systemd-resolved is active, checking for leaks" + # Additional checks for systemd-resolved + fi + ;; + *) + alert "Potential DNS leak detected! Public DNS server: $dns" + return 1 + ;; + esac + done + + return 0 +} + +check_leak_test() { + # Try to reach internet without VPN + local vpn_active=$(check_vpn_connection; echo $?) + + if [ $vpn_active -eq 1 ]; then + # VPN not active, internet should be blocked + if ping -c 1 -W 1 8.8.8.8 >/dev/null 2>&1; then + alert "CRITICAL: Internet accessible without VPN! Leak detected!" + # Immediately re-enable killswitch + /usr/local/bin/vpn-killswitch.sh enable + return 1 + fi + fi + + return 0 +} + +check_processes() { + # Check for processes that might bypass VPN + local suspicious_processes=$(netstat -tunp 2>/dev/null | grep -v "127.0.0.1\|::1\|$LAN_NET" | grep ESTABLISHED) + + if [ -n "$suspicious_processes" ]; then + log "WARNING: Detected network connections that might bypass VPN:" + echo "$suspicious_processes" >> "$LOG_FILE" + fi +} + +monitor_bandwidth() { + # Monitor bandwidth to detect unusual activity + if command -v vnstat >/dev/null 2>&1; then + local current_tx=$(vnstat --oneline | cut -d';' -f9) + local current_rx=$(vnstat --oneline | cut -d';' -f10) + + if [ -f "$STATE_FILE" ]; then + source "$STATE_FILE" + + # Compare with previous values + # Alert if sudden spike in traffic when VPN is down + if ! check_vpn_connection && [ -n "$LAST_TX" ]; then + # Calculate difference + # If significant traffic when VPN is down, alert + log "Bandwidth check: TX=$current_tx RX=$current_rx" + fi + fi + + # Save current state + echo "LAST_TX='$current_tx'" > "$STATE_FILE" + echo "LAST_RX='$current_rx'" >> "$STATE_FILE" + fi +} + +auto_recovery() { + local vpn_status=$(check_vpn_connection; echo $?) + + if [ $vpn_status -eq 2 ]; then + # Connection stale, try to reconnect + log "Attempting auto-recovery of VPN connection..." + + # Get last used server from config + if [ -f /etc/wireguard/wg0.conf ]; then + systemctl restart wg-quick@wg0 2>/dev/null || \ + wg-quick down wg0 2>/dev/null && wg-quick up wg0 2>/dev/null + + sleep 5 + + if check_vpn_connection; then + log "Auto-recovery successful" + return 0 + else + alert "Auto-recovery failed - manual intervention required" + return 1 + fi + fi + fi + + return 0 +} + +# Main monitoring loop +main() { + log "VPN Security Monitor started" + log "Check interval: ${CHECK_INTERVAL}s" + + # Initial checks + check_killswitch + check_vpn_connection + check_dns_leaks + + local error_count=0 + + while true; do + # Run all checks + local all_ok=true + + if ! check_killswitch; then + all_ok=false + ((error_count++)) + fi + + if ! check_leak_test; then + all_ok=false + ((error_count++)) + fi + + if ! check_dns_leaks; then + all_ok=false + ((error_count++)) + fi + + check_processes + monitor_bandwidth + + # Auto-recovery if needed + if [ $error_count -gt 3 ]; then + auto_recovery + error_count=0 + fi + + # Status indicator + if [ "$all_ok" = true ]; then + echo -n "." + error_count=0 + else + echo -n "!" + fi + + sleep "$CHECK_INTERVAL" + done +} + +# Signal handlers +trap 'log "Security monitor stopped"; exit 0' SIGTERM SIGINT + +# Run main loop +main diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh new file mode 100755 index 0000000..aa93279 --- /dev/null +++ b/scripts/uninstall.sh @@ -0,0 +1,156 @@ +#!/bin/bash + +# VPN Gateway Uninstall Script +# Completely removes VPN Gateway +# Version: 1.0.0 + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +INSTALL_DIR="/opt/vpn-gateway" + +log() { + echo -e "${GREEN}[+]${NC} $1" +} + +error() { + echo -e "${RED}[!]${NC} $1" +} + +warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +# Check root +if [[ $EUID -ne 0 ]]; then + error "This script must be run as root" + exit 1 +fi + +echo -e "${RED}=== VPN Gateway Uninstaller ===${NC}" +echo "" +warning "This will completely remove VPN Gateway and its components." +warning "The killswitch will be DISABLED, potentially exposing your traffic!" +echo "" +echo "The following will be removed:" +echo " - VPN Gateway application ($INSTALL_DIR)" +echo " - WireGuard configurations" +echo " - Systemd services" +echo " - Firewall rules (killswitch)" +echo " - Nginx configuration" +echo "" +read -p "Are you SURE you want to uninstall? Type 'YES' to confirm: " CONFIRM + +if [ "$CONFIRM" != "YES" ]; then + log "Uninstall cancelled" + exit 0 +fi + +# Create backup just in case +BACKUP_DIR="/root/vpn-gateway-final-backup-$(date +%Y%m%d-%H%M%S)" +log "Creating final backup at $BACKUP_DIR..." +mkdir -p "$BACKUP_DIR" + +# Backup configs +cp -r /etc/wireguard "$BACKUP_DIR/wireguard" 2>/dev/null || true +cp -r "$INSTALL_DIR" "$BACKUP_DIR/app" 2>/dev/null || true +iptables-save > "$BACKUP_DIR/iptables.rules" 2>/dev/null || true + +# Stop and disable services +log "Stopping services..." +systemctl stop vpn-webui vpn-killswitch vpn-security-monitor 2>/dev/null || true +systemctl disable vpn-webui vpn-killswitch vpn-security-monitor 2>/dev/null || true + +# Stop WireGuard +wg-quick down wg0 2>/dev/null || true +systemctl stop wg-quick@wg0 2>/dev/null || true +systemctl disable wg-quick@wg0 2>/dev/null || true + +# Remove systemd services +log "Removing systemd services..." +rm -f /etc/systemd/system/vpn-*.service +systemctl daemon-reload + +# Remove application files +log "Removing application files..." +rm -rf "$INSTALL_DIR" + +# Remove scripts +log "Removing scripts..." +rm -f /usr/local/bin/vpn-*.sh + +# Remove Nginx configuration +log "Removing Nginx configuration..." +rm -f /etc/nginx/sites-enabled/vpn-gateway +rm -f /etc/nginx/sites-available/vpn-gateway +systemctl reload nginx 2>/dev/null || true + +# Remove WireGuard configs (optional) +read -p "Remove WireGuard configurations? (y/N): " -n 1 -r +echo "" +if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -rf /etc/wireguard + log "WireGuard configurations removed" +fi + +# CRITICAL: Remove killswitch +warning "Removing killswitch - your traffic will no longer be protected!" +read -p "Remove killswitch firewall rules? (y/N): " -n 1 -r +echo "" +if [[ $REPLY =~ ^[Yy]$ ]]; then + # Reset firewall to default ACCEPT policies + iptables -P INPUT ACCEPT + iptables -P FORWARD ACCEPT + iptables -P OUTPUT ACCEPT + iptables -F + iptables -X + iptables -t nat -F + iptables -t nat -X + iptables -t mangle -F + iptables -t mangle -X + + # IPv6 + ip6tables -P INPUT ACCEPT + ip6tables -P FORWARD ACCEPT + ip6tables -P OUTPUT ACCEPT + ip6tables -F + ip6tables -X + + # Save clean rules + iptables-save > /etc/iptables/rules.v4 2>/dev/null || true + ip6tables-save > /etc/iptables/rules.v6 2>/dev/null || true + + warning "Firewall reset to ACCEPT all - System is no longer protected!" +else + warning "Killswitch still active - you may have no internet access!" +fi + +# Remove log files +read -p "Remove log files? (y/N): " -n 1 -r +echo "" +if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -f /var/log/vpn-*.log + log "Log files removed" +fi + +# Final cleanup +log "Cleaning up..." +rm -f /tmp/vpn-gateway* 2>/dev/null || true + +echo "" +echo -e "${GREEN}=== Uninstall Complete ===${NC}" +echo "" +echo "VPN Gateway has been removed." +echo "Backup saved at: $BACKUP_DIR" +echo "" +warning "IMPORTANT: Your system is no longer protected by the killswitch!" +warning "All traffic will now use your regular internet connection." +echo "" +echo "To reinstall, run:" +echo " curl -sSL https://your-domain/install.sh | bash" diff --git a/scripts/update.sh b/scripts/update.sh new file mode 100755 index 0000000..39814c0 --- /dev/null +++ b/scripts/update.sh @@ -0,0 +1,146 @@ +############################################################# +# scripts/update.sh # +############################################################# + +cat > scripts/update.sh << 'EOFUPDATE' +#!/bin/bash + +# VPN Gateway Update Script +# Updates the VPN Gateway installation +# Version: 1.0.0 + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +INSTALL_DIR="/opt/vpn-gateway" +BACKUP_DIR="/opt/vpn-gateway-backup-$(date +%Y%m%d-%H%M%S)" +GITHUB_REPO="https://github.com/yourusername/vpn-gateway" + +log() { + echo -e "${GREEN}[+]${NC} $1" +} + +error() { + echo -e "${RED}[!]${NC} $1" + exit 1 +} + +warning() { + echo -e "${YELLOW}[*]${NC} $1" +} + +# Check root +if [[ $EUID -ne 0 ]]; then + error "This script must be run as root" +fi + +echo -e "${BLUE}=== VPN Gateway Update ===${NC}" +echo "" + +# Check current version +if [ -f "$INSTALL_DIR/version" ]; then + CURRENT_VERSION=$(cat "$INSTALL_DIR/version") + log "Current version: $CURRENT_VERSION" +else + warning "Version file not found" + CURRENT_VERSION="unknown" +fi + +# Check for updates +log "Checking for updates..." +LATEST_VERSION=$(curl -s "$GITHUB_REPO/raw/main/version" 2>/dev/null || echo "") + +if [ -z "$LATEST_VERSION" ]; then + error "Could not fetch latest version" +fi + +if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then + log "Already running latest version: $LATEST_VERSION" + exit 0 +fi + +log "New version available: $LATEST_VERSION" +echo "" +read -p "Update to version $LATEST_VERSION? (y/N): " -n 1 -r +echo "" + +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + log "Update cancelled" + exit 0 +fi + +# Backup current installation +log "Creating backup at $BACKUP_DIR..." +cp -r "$INSTALL_DIR" "$BACKUP_DIR" + +# Backup WireGuard configs +cp -r /etc/wireguard "$BACKUP_DIR/wireguard-configs" + +# Backup iptables rules +iptables-save > "$BACKUP_DIR/iptables.rules" +ip6tables-save > "$BACKUP_DIR/ip6tables.rules" + +log "Backup complete" + +# Stop services +log "Stopping services..." +systemctl stop vpn-webui vpn-security-monitor 2>/dev/null || true + +# Download updates +log "Downloading updates..." +cd /tmp +rm -rf vpn-gateway-update +git clone "$GITHUB_REPO" vpn-gateway-update || \ + error "Failed to download updates" + +# Update backend +log "Updating backend..." +cp /tmp/vpn-gateway-update/backend/app.py "$INSTALL_DIR/app.py" + +# Update frontend +log "Updating frontend..." +cp /tmp/vpn-gateway-update/frontend/index.html "$INSTALL_DIR/static/index.html" + +# Update scripts +log "Updating scripts..." +cp /tmp/vpn-gateway-update/scripts/*.sh /usr/local/bin/ +chmod +x /usr/local/bin/vpn-*.sh + +# Update Python dependencies +log "Updating dependencies..." +source "$INSTALL_DIR/venv/bin/activate" +pip install --upgrade -r /tmp/vpn-gateway-update/backend/requirements.txt + +# Update version file +echo "$LATEST_VERSION" > "$INSTALL_DIR/version" + +# Restart services +log "Restarting services..." +systemctl daemon-reload +systemctl start vpn-webui vpn-security-monitor + +# Cleanup +rm -rf /tmp/vpn-gateway-update + +# Verify update +sleep 3 +if systemctl is-active vpn-webui >/dev/null 2>&1; then + log "Update successful!" + log "Version $LATEST_VERSION is now running" + echo "" + echo -e "${GREEN}Update complete!${NC}" + echo "Backup saved at: $BACKUP_DIR" +else + error "Services failed to start after update!" + echo "Restore from backup with:" + echo " rm -rf $INSTALL_DIR" + echo " mv $BACKUP_DIR $INSTALL_DIR" + echo " systemctl restart vpn-webui" +fi + diff --git a/version b/version new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/version @@ -0,0 +1 @@ +1.0.0