From 437a4b14af7bf0bbf9950141a0cb5f367edddc21 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 10 Aug 2025 14:54:27 +0000 Subject: [PATCH] Remove duplicate functions --- install.sh | 100 --- install.sh.backup | 1200 +++++++++++++++++++++++++++++ install.sh.backup.20250810_144644 | 1200 +++++++++++++++++++++++++++++ 3 files changed, 2400 insertions(+), 100 deletions(-) create mode 100644 install.sh.backup create mode 100644 install.sh.backup.20250810_144644 diff --git a/install.sh b/install.sh index 62d2aee..d3ee8b6 100644 --- a/install.sh +++ b/install.sh @@ -178,42 +178,6 @@ detect_network() { 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() { @@ -584,23 +548,6 @@ EOF 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..." @@ -771,53 +718,6 @@ EOFAPP 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..." diff --git a/install.sh.backup b/install.sh.backup new file mode 100644 index 0000000..62d2aee --- /dev/null +++ b/install.sh.backup @@ -0,0 +1,1200 @@ +#!/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 "" + + # 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..." + warning "⚠️ KILLSWITCH WILL BLOCK ALL INTERNET ACCESS AFTER ACTIVATION!" + warning "⚠️ Only VPN connections will be allowed!" + echo "" + read -p "Activate killswitch now? This cannot be undone! (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + warning "Killswitch installation skipped. System is NOT protected!" + warning "Run 'systemctl start vpn-killswitch' to activate later." + return + fi + + # Create killswitch script + cat > /usr/local/bin/vpn-killswitch.sh << 'EOFSCRIPT' +#!/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") + install_mullvad + ;; + "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" +} + +# 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_vpn_provider # Install VPN first (needs internet) + install_killswitch # Then activate killswitch (blocks internet) + install_backend + install_webui + setup_services + setup_nginx + finalize_installation + + show_summary +} + +# Run main function +main "$@" diff --git a/install.sh.backup.20250810_144644 b/install.sh.backup.20250810_144644 new file mode 100644 index 0000000..62d2aee --- /dev/null +++ b/install.sh.backup.20250810_144644 @@ -0,0 +1,1200 @@ +#!/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 "" + + # 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..." + warning "⚠️ KILLSWITCH WILL BLOCK ALL INTERNET ACCESS AFTER ACTIVATION!" + warning "⚠️ Only VPN connections will be allowed!" + echo "" + read -p "Activate killswitch now? This cannot be undone! (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + warning "Killswitch installation skipped. System is NOT protected!" + warning "Run 'systemctl start vpn-killswitch' to activate later." + return + fi + + # Create killswitch script + cat > /usr/local/bin/vpn-killswitch.sh << 'EOFSCRIPT' +#!/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") + install_mullvad + ;; + "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" +} + +# 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_vpn_provider # Install VPN first (needs internet) + install_killswitch # Then activate killswitch (blocks internet) + install_backend + install_webui + setup_services + setup_nginx + finalize_installation + + show_summary +} + +# Run main function +main "$@"