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 "$@"