{"repo": "bitr1ft/securevpn", "files": {"README.md": {"cc4e0f0c929be2443d3565120dd44dba2ab47239": {"t": 1785596430.9932742, "n": 11813, "h": "cdbeebf98a84fa2c", "c": "# SecureVPN\n\n**Post-Quantum WireGuard VPN — CS325 Network Security Project** \nBy: Muhammad Adeel Haider (BitR1ft) \nAir University · National Centre for Cyber Security (NCSA) \n\n\n---\n\n## What is this?\n\nSecureVPN is a full-stack VPN system built on top of WireGuard. It extends classical WireGuard with a **post-quantum hybrid key exchange** — combining Kyber-512 (a lattice-based KEM selected by NIST for standardization) with X25519, using HKDF-SHA3-256 to derive the WireGuard Pre-Shared Key. This means the tunnel is protected against both classical and quantum adversaries.\n\nThe system has two main components:\n\n- **Client** — Windows GUI + CLI application that manages the WireGuard tunnel\n- **Server** — Linux Flask API that provisions and manages WireGuard peers\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────┐\n│ WINDOWS CLIENT │\n│ │\n│ GUI (tkinter) ──► VPN Core ──► WireGuard │\n│ │ │\n│ Crypto Engine │\n│ (Kyber-512 + X25519 + HKDF) │\n└────────────────────────┬────────────────────────────┘\n │ HTTPS (signed requests)\n ▼\n┌─────────────────────────────────────────────────────┐\n│ LINUX SERVER │\n│ │\n│ Nginx (TLS) ──► Gunicorn ──► Flask API │\n│ │ │\n│ WG Manager │\n│ (wg0 peer lifecycle) │\n│ │ │\n│ WireGuard (wg0) │\n└─────────────────────────────────────────────────────┘\n```\n\n---\n\n## Post-Quantum Key Exchange Protocol\n\n```\nClient Server\n────── ──────\n1. Generate WireGuard keypair (classical)\n2. Generate Kyber-512 keypair (PQ)\n3. POST /api/v1/add-peer\n { public_key, kyber_public_key }\n ─────────────────────────►\n 4. Encapsulate to client's Kyber PK:\n ciphertext, shared_secret = KEM.encaps(pk)\n 5. Derive PSK:\n PSK = HKDF-SHA3-256(shared_secret)\n 6. Add peer to wg0 with PSK\n ◄─────────────────────────\n { kem_ciphertext, server_pub, ... }\n\n7. Decapsulate:\n shared_secret = KEM.decaps(ciphertext, sk)\n8. Derive same PSK:\n PSK = HKDF-SHA3-256(shared_secret)\n9. Write WireGuard .conf and connect\n```\n\nThe PSK never crosses the network. Both sides independently derive the same key from the KEM shared secret. This provides **IND-CCA2** security against quantum adversaries.\n\n---\n\n## Features\n\n### Security\n- **Kyber-512 KEM** — Post-quantum key encapsulation (NIST PQC Round 4 selection)\n- **Hybrid key exchange** — X25519 + Kyber-512, fail-safe against both classical and quantum attacks\n- **HKDF-SHA3-256** — Key derivation with domain-separated info string\n- **WireGuard PSK** — Per-tunnel pre-shared key for layered encryption\n- **HMAC-SHA256 request signing** — All mutating API calls are signed with timestamp and body hash\n- **Replay attack protection** — ±300 second timestamp window enforced server-side\n- **TOFU key pinning** — Server public key is pinned on first use; mismatch raises a `SecurityError`\n- **Kill switch** — Windows Firewall rules block all traffic if the tunnel drops\n- **IND-CCA2 decapsulation** — Re-encapsulation integrity check prevents reaction attacks\n\n### Client\n- Simple, clean GUI built with standard tkinter (no external UI frameworks)\n- CLI with full command coverage\n- Profile import and generation\n- Bandwidth monitoring (RX/TX rates and totals)\n- Leak test (IP + DNS verification)\n- PSK rotation\n- Connection logging and anomaly log\n\n### Server\n- Flask REST API with Gunicorn + Nginx in production\n- Redis-backed rate limiting (shared across Gunicorn workers)\n- Atomic peer provisioning with `fcntl.flock` (no duplicate IP assignment)\n- Live peer removal without interface restart (`wg set ... peer remove`)\n- Peer lifecycle audit with configurable TTL\n- Systemd service with `ProtectSystem=strict`\n- Docker support\n\n---\n\n## Project Structure\n\n```\nSecureVPN/\n├── client/\n│ ├── securevpn/\n│ │ ├── gui/\n│ │ │ └── app.py # tkinter GUI application\n│ │ ├── core/\n│ │ │ ├── vpn_engine.py # Tunnel management, kill switch, bandwidth\n│ │ │ └── crypto_engine.py # Kyber-512 KEM, X25519, HKDF, DPAPI storage\n│ │ ├── tools/\n│ │ │ └── traffic_analyzer.py # Scapy-based traffic analysis\n│ │ └── cli.py # CLI entry point\n│ ├── requirements.txt\n│ └── SecureVPN_GUI.spec # PyInstaller build spec\n│\n└── server/\n ├── wg-api/\n │ ├── app.py # Flask application\n │ ├── config.py # Server configuration\n │ ├── services/\n │ │ ├── wg_manager.py # WireGuard peer lifecycle\n │ │ ├── auth.py # API key + HMAC-SHA256 auth decorators\n │ │ └── monitor.py # Anomaly detection\n │ ├── crypto/\n │ │ └── pq_crypto.py # Server-side Kyber KEM\n │ └── utils/\n │ ├── validators.py # Input validation\n │ └── logger.py # Structured JSON logging\n ├── scripts/ # WireGuard sudoers wrapper scripts\n ├── systemd/ # wg-api systemd service unit\n ├── Dockerfile\n ├── docker-compose.yml\n └── install.sh # Automated server setup script\n```\n\n---\n\n## Quick Start\n\n### Prerequisites\n\n**Client (Windows)**\n- Windows 10/11 64-bit\n- [WireGuard for Windows](https://www.wireguard.com/install/) installed\n- Python 3.10+ (or use the prebuilt `SecureVPN.exe`)\n- Run as **Administrator** (required for WireGuard tunnel service and firewall rules)\n\n**Server (Linux — Ubuntu 22.04/24.04)**\n- WireGuard (`apt install wireguard`)\n- Python 3.10+\n- Redis (`apt install redis-server`)\n- Nginx (optional, recommended for production)\n\n---\n\n### Server Setup\n\n```bash\n# Clone the repo\ngit clone https://github.com/BitR1ft/SecureVPN.git\ncd SecureVPN/server\n\n# Run the automated installer (sets up WireGuard, API, systemd, firewall)\nsudo bash install.sh IP\n```\n\nThe installer will:\n1. Install WireGuard and generate server keys\n2. Create `wg0` interface with the VPN subnet\n3. Install the Flask API as a systemd service (`wg-api`)\n4. Configure Nginx reverse proxy with TLS\n5. Set up Redis for rate limiting\n6. Configure UFW firewall rules\n\n**Manual configuration** — edit `/opt/wg-api/config.py`:\n```python\nAPI_KEY = \"your-secret-api-key-here\"\nSERVER_ENDPOINT = \"your.server.ip.or.domain\"\nLISTEN_PORT = 51820\nVPN_SUBNET = \"10.77.0.0/24\"\nSERVER_IP = \"10.77.0.1\"\nPQ_ENABLED = True\n```\n\n---\n\n### Client Setup (Python)\n\n```bash\ncd SecureVPN/client\n\n# Create virtualenv and install dependencies\npython -m venv venv\nvenv\\Scripts\\activate\n\npip install -r requirements.txt\n\n# Launch GUI (run as Administrator)\npython securevpn_gui.py\n\n# Or use the CLI\npython securevpn_cli.py --help\n```\n\n### Client Setup (Prebuilt EXE)\n\nRight-click `client/dist/SecureVPN.exe` → **Run as administrator**\n\n---\n\n### Generating a Profile (GUI)\n\n1. Launch SecureVPN as Administrator\n2. Click **Profiles** in the sidebar\n3. Click **Generate Keys**\n4. Fill in:\n - Profile Name (e.g. `home`)\n - Server URL (e.g. `https://20.29.133.180`)\n - API Key (from your server's `config.py`)\n5. Click **Generate Keys** — the client performs the full PQ KEM handshake\n6. Switch to **Connect**, select the profile, click **Connect**\n\n---\n\n### CLI Usage\n\n```bash\n# List profiles\npython securevpn_cli.py list\n\n# Generate post-quantum profile\npython securevpn_cli.py keygen myprofile \\\n --server https://your-server:443 \\\n --api-key YOUR_API_KEY\n\n# Connect\npython securevpn_cli.py up --profile myprofile\n\n# Status\npython securevpn_cli.py status\n\n# Leak test\npython securevpn_cli.py verify\n\n# Disconnect\npython securevpn_cli.py down\n\n# Rotate PSK\npython securevpn_cli.py rotate-psk --profile myprofile\n\n# View logs\npython securevpn_cli.py logs --tail 50\n```\n\n---\n\n## API Reference\n\nAll mutating endpoints require HMAC-SHA256 signed requests.\n\n**Signature scheme:**\n```\ncanonical = f\"{METHOD}:{path}:{timestamp}:{hex(sha256(body))}\"\nsignature = HMAC-SHA256(api_key, canonical)\n\nHeaders:\n X-API-Key: \n X-Timestamp: \n X-Signature: \n```\n\n| Endpoint | Method | Auth | Description |\n|---|---|---|---|\n| `/api/v1/health` | GET | None | Health check |\n| `/api/v1/status` | GET | API Key | WireGuard interface status |\n| `/api/v1/server-stats` | GET | API Key | Peer count, uptime, memory |\n| `/api/v1/add-peer` | POST | Signed | Provision new peer (PQ KEM) |\n| `/api/v1/revoke-peer` | POST | Signed | Remove peer (live, no restart) |\n| `/api/v1/rotate-psk` | POST | Signed | Rotate pre-shared key |\n| `/api/v1/audit-peers` | GET | API Key | Peer lifecycle audit report |\n| `/api/v1/pq-keygen` | POST | API Key | Standalone KEM encapsulation |\n| `/api/v1/anomalies` | GET | API Key | Security anomaly log |\n\n---\n\n## Kill Switch\n\nWhen enabled, the kill switch installs Windows Firewall rules that block **all outbound traffic** except:\n- Traffic through the WireGuard tunnel adapter\n- UDP to the VPN server's endpoint IP (for handshake)\n- Loopback (127.0.0.1)\n- DHCP (UDP 68→67)\n- VPN subnet (10.77.0.0/24)\n\nIf the tunnel drops, all internet traffic is blocked until the VPN reconnects. Rules are automatically removed on disconnect.\n\n---\n\n## Building the EXE\n\n```bash\ncd client\n\n# Install PyInstaller\npip install pyinstaller\n\n# Build\npyinstaller SecureVPN_GUI.spec --noconfirm\n\n# Output: client/dist/SecureVPN.exe\n```\n\n---\n\n## Docker (Server)\n\n```bash\ncd server\ndocker-compose up -d\n```\n\nThe compose file runs the Flask API + Redis. Configure `server/wg-api/config.py` before building.\n\n---\n\n## Security Notes\n\n- **WireGuard `.conf` files are excluded from git** (they contain private keys). See `.gitignore`.\n- The server API key is in `config.py` — never commit it. Use environment variables in production.\n- The kill switch is enabled by default. Disable in Settings if you have issues.\n- TOFU key pinning means if the server rotates its WireGuard keypair, the client will raise a `SecurityError`. Use `update_pinned_key()` in `vpn_engine.py` after verifying the new key out-of-band.\n\n---\n\n## Tech Stack\n\n| Layer | Technology |\n|---|---|\n| VPN Protocol | WireGuard |\n| PQ KEM | Kyber-512 (custom numpy implementation) |\n| Classical KE | X25519 |\n| KDF | HKDF-SHA3-256 |\n| API | Flask 3.0 + Gunicorn + Nginx |\n| Rate Limiting | Flask-Limiter + Redis |\n| Auth | HMAC-SHA256 + API key |\n| GUI | Python tkinter |\n| Key Storage | Windows DPAPI / AES-GCM fallback |\n| OS Keyring | python-keyring |\n| Build | PyInstaller 6.x |\n\n---\n\n## Academic Context\n\n> **Course:** CS325 — Network Security \n> **Institution:** Air University, Islamabad, Pakistan \n> **Lab:** National Centre for Cyber Security (NCSA) \n\nThis project demonstrates:\n- WireGuard tunnel management at the OS level (Windows service API)\n- Post-quantum cryptography integration into an existing classical protocol\n- Hybrid forward-secrecy key exchange\n- Secure API design (HMAC signing, replay protection, rate limiting)\n- OS-level network security controls (Windows Firewall kill switch)\n\n---\n\n## License\n\nThis project is for academic purposes. All rights reserved.\n"}}, "server/wg-api/config.py": {"cc4e0f0c929be2443d3565120dd44dba2ab47239": {"t": 1785596450.4493413, "n": 2421, "h": "c7fbf39f8ea4d720", "c": "\"\"\"\nSecureVPN Server Configuration\n==============================\nCentralized configuration with secure defaults.\n\"\"\"\n\nimport os\nimport json\nimport secrets\nfrom pathlib import Path\n\n# Base paths\nBASE_DIR = Path('/opt/wg-api')\nCONFIG_DIR = BASE_DIR / 'config'\nLOG_DIR = BASE_DIR / 'logs'\nPEER_DIR = Path('/etc/wireguard/peers')\nWG_CONF = Path('/etc/wireguard/wg0.conf')\n\n# Ensure directories exist (only those writable by wg-api user)\n# PEER_DIR (/etc/wireguard/peers) is created by install.sh as root.\n# Do NOT try to mkdir /etc paths — ProtectSystem=strict blocks it.\nfor d in [CONFIG_DIR, LOG_DIR]:\n try:\n d.mkdir(parents=True, exist_ok=True)\n except PermissionError:\n pass # Directory may already exist with root ownership\n\n# Network configuration\nVPN_SUBNET = \"10.77.0.0/24\"\nSERVER_IP = \"10.77.0.1/24\"\nLISTEN_PORT = 51820\nWAN_INTERFACE = \"eth0\"\n\n# API Security - BIND TO 0.0.0.0 TO ACCEPT EXTERNAL CONNECTIONS\nAPI_HOST = \"0.0.0.0\"\nAPI_PORT = 5000\nAPI_KEY_FILE = CONFIG_DIR / 'api_key.secret'\n\n# Post-Quantum settings\nPQ_ENABLED = True\nPQ_KEM_K = 2\n\n# Rate limiting\nRATE_LIMIT_PEER_ADD = \"10 per hour\"\nRATE_LIMIT_STATUS = \"100 per minute\"\nRATE_LIMIT_PSK_ROTATE = \"5 per hour\"\n\n# Logging\nLOG_LEVEL = \"INFO\"\nLOG_FILE = LOG_DIR / 'wg-api.log'\nANOMALY_LOG = LOG_DIR / 'anomaly.log'\nROTATION_LOG = LOG_DIR / 'psk-rotations.log'\n\n# Monitoring\nANOMALY_THRESHOLD_HANDSHAKE = 60\nANOMALY_THRESHOLD_RECONNECT = 3\nBRUTE_FORCE_THRESHOLD = 10\n\n\ndef load_or_create_api_key() -> str:\n \"\"\"Load existing API key or generate cryptographically secure one.\"\"\"\n if API_KEY_FILE.exists():\n return API_KEY_FILE.read_text().strip()\n\n api_key = secrets.token_urlsafe(32)\n API_KEY_FILE.write_text(api_key)\n os.chmod(API_KEY_FILE, 0o600)\n return api_key\n\n\ndef get_server_public_key() -> str:\n \"\"\"Read server WireGuard public key.\"\"\"\n pub_key_file = Path('/etc/wireguard/server_public.key')\n if pub_key_file.exists():\n return pub_key_file.read_text().strip()\n return \"\"\n\n\ndef get_server_private_key() -> str:\n \"\"\"Read server WireGuard private key.\"\"\"\n priv_key_file = Path('/etc/wireguard/server_private.key')\n if priv_key_file.exists():\n return priv_key_file.read_text().strip()\n return \"\"\n\n\n# Load configuration\nAPI_KEY = load_or_create_api_key()\nSERVER_PUBLIC_KEY = get_server_public_key()\nSERVER_ENDPOINT = os.environ.get('SERVER_ENDPOINT', 'your-server-ip')\n"}}}}