#!/usr/bin/env bash # WireGuard Setup Script # This script guides users through creating WireGuard keys and configuration files set -euo pipefail # Exit on error, undefined vars, pipe failures # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration file for Zion settings ZION_CONFIG_FILE="$(dirname "$0")/CURRENT_WORKING/zion.conf" # Function to print colored output print_status() { echo -e "${GREEN}[INFO]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_header() { echo -e "${BLUE}================================${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}================================${NC}" } # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to validate IP address with subnet validate_ip() { local ip=$1 # Check if input contains subnet if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then return 1 fi # Extract IP and subnet parts local ip_part="${ip%/*}" local subnet="${ip#*/}" # Validate subnet if [[ ! $subnet =~ ^[0-9]+$ ]] || [ "$subnet" -lt 1 ] || [ "$subnet" -gt 32 ]; then return 1 fi # Validate each octet IFS='.' read -ra OCTETS <<< "$ip_part" if [ ${#OCTETS[@]} -ne 4 ]; then return 1 fi for octet in "${OCTETS[@]}"; do if [[ ! $octet =~ ^[0-9]+$ ]] || [ "$octet" -lt 0 ] || [ "$octet" -gt 255 ]; then return 1 fi done return 0 } # Function to validate port number validate_port() { local port=$1 if [[ ! $port =~ ^[0-9]+$ ]]; then return 1 fi if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then return 1 fi # Check for common reserved ports if [ "$port" -le 1024 ]; then print_warning "Port $port is in privileged range (1-1024). You may need root access." fi return 0 } # Function to validate WireGuard public key validate_public_key() { local key=$1 # WireGuard keys are base64 encoded and exactly 44 characters long if [[ ! $key =~ ^[A-Za-z0-9+/]{43}=$ ]]; then return 1 fi return 0 } # Function to detect network interface detect_network_interface() { # Try to detect the main network interface local interface # Check for common interface names for name in eth0 ens33 ens160 enp0s3 eno1; do if ip link show "$name" >/dev/null 2>&1; then interface="$name" break fi done # Fallback to first non-loopback interface if [ -z "$interface" ]; then interface=$(ip route | grep default | awk '{print $5}' | head -1) fi echo "$interface" } # Function to load Zion configuration load_zion_config() { if [[ -f "$ZION_CONFIG_FILE" ]]; then print_status "Found Zion configuration file: $ZION_CONFIG_FILE" return 0 else print_warning "Zion configuration file not found: $ZION_CONFIG_FILE" print_warning "Using hardcoded Zion configuration" return 1 fi } # Function to create safe filename safe_filename() { local name="$1" # Replace invalid characters with underscores echo "$name" | sed 's/[^a-zA-Z0-9._-]/_/g' } # Main setup function main() { print_header "WireGuard Configuration Setup" echo "This script will help you create WireGuard keys and configuration files." echo "Based on the CURRENT_WORKING configuration with Zion as central server." echo "" # Check if wg command exists if ! command_exists wg; then print_error "WireGuard tools not found. Please install WireGuard first:" echo " Ubuntu/Debian: sudo apt install wireguard" echo " CentOS/RHEL: sudo yum install wireguard-tools" echo " Arch: sudo pacman -S wireguard-tools" echo " Fedora: sudo dnf install wireguard-tools" exit 1 fi # Create output directory OUTPUT_DIR="wireguard_configs" mkdir -p "$OUTPUT_DIR" print_status "Created output directory: $OUTPUT_DIR" # Step 1: Generate keys print_header "Step 1: Generate WireGuard Keys" echo "Generating private and public keys..." PRIVATE_KEY=$(wg genkey) PUBLIC_KEY=$(echo "$PRIVATE_KEY" | wg pubkey) print_status "Keys generated successfully!" echo "Private Key: $PRIVATE_KEY" echo "Public Key: $PUBLIC_KEY" echo "" # Step 2: Get configuration details print_header "Step 2: Configuration Details" # Get node name local node_name while true; do read -p "Enter node name (e.g., aza, cth, galaxy): " node_name node_name=$(safe_filename "$node_name") if [ -n "$node_name" ]; then break else print_error "Node name cannot be empty" fi done # Check if configuration file already exists CONFIG_FILE="$OUTPUT_DIR/${node_name}.conf" if [ -f "$CONFIG_FILE" ]; then print_warning "Configuration file '$CONFIG_FILE' already exists." read -p "Do you want to overwrite it? (y/n): " OVERWRITE_FILE if [[ ! $OVERWRITE_FILE =~ ^[Yy]$ ]]; then print_error "Operation cancelled. Please choose a different node name or remove the existing file." exit 1 fi print_status "Will overwrite existing configuration file." fi # Get IP address local ip_address while true; do read -p "Enter IP address with subnet (e.g., 10.8.0.2/24): " ip_address if validate_ip "$ip_address"; then break else print_error "Invalid IP address format. Use format: x.x.x.x/y" fi done # Ask if this is a server (listening) or client read -p "Is this a server that will listen for connections? (y/n): " IS_SERVER local listen_port if [[ $IS_SERVER =~ ^[Yy]$ ]]; then while true; do read -p "Enter listen port (1-65535): " listen_port if validate_port "$listen_port"; then break else print_error "Invalid port number. Must be between 1-65535" fi done fi # Step 3: Create configuration file print_header "Step 3: Create Configuration File" # Create the configuration file cat > "$CONFIG_FILE" << EOF [Interface] PrivateKey = $PRIVATE_KEY Address = $ip_address EOF # Add listen port if it's a server if [[ $IS_SERVER =~ ^[Yy]$ ]]; then echo "ListenPort = $listen_port" >> "$CONFIG_FILE" fi # Add PostUp/PostDown rules for server (Zion-like configuration) if [[ $IS_SERVER =~ ^[Yy]$ ]]; then local network_interface network_interface=$(detect_network_interface) if [ -n "$network_interface" ]; then print_status "Detected network interface: $network_interface" else print_warning "Could not detect network interface, using 'eth0'" network_interface="eth0" fi echo "" >> "$CONFIG_FILE" echo "# Server configuration - enable IP forwarding" >> "$CONFIG_FILE" echo "PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o $network_interface -j MASQUERADE; ip route add 10.8.0.0/24 dev wg0 2>/dev/null || true" >> "$CONFIG_FILE" echo "PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o $network_interface -j MASQUERADE; ip route del 10.8.0.0/24 dev wg0 2>/dev/null || true" >> "$CONFIG_FILE" fi print_status "Configuration file created: $CONFIG_FILE" # Step 4: Add peers print_header "Step 4: Add Peers" # Zion default peer information (from CURRENT_WORKING/zion.conf) local ZION_PUBLIC_KEY="2ztJbrN1x1NWanzPGLiKL19ZkdOhm5Y7WeKEWBT5cyg=" local ZION_ENDPOINT="ugh.im:51820" local ZION_ALLOWED_IPS="10.8.0.0/24" # Try to load Zion config, fall back to hardcoded if not available if ! load_zion_config; then print_warning "Using hardcoded Zion configuration" fi # Ask if user wants to add Zion as default peer (unless this IS Zion) if [[ "$node_name" != "zion" ]]; then echo "Zion is the central server for this network." read -p "Do you want to add Zion as a peer? (y/n, default: y): " ADD_ZION ADD_ZION=${ADD_ZION:-y} if [[ $ADD_ZION =~ ^[Yy]$ ]]; then echo "" echo "Adding Zion as peer with default settings:" echo " Public Key: $ZION_PUBLIC_KEY" echo " Endpoint: $ZION_ENDPOINT" echo " Allowed IPs: $ZION_ALLOWED_IPS" echo " Persistent Keepalive: 25" echo "" # Add Zion peer to configuration echo "" >> "$CONFIG_FILE" echo "# Zion (central server)" >> "$CONFIG_FILE" echo "[Peer]" >> "$CONFIG_FILE" echo "PublicKey = $ZION_PUBLIC_KEY" >> "$CONFIG_FILE" echo "AllowedIPs = $ZION_ALLOWED_IPS" >> "$CONFIG_FILE" echo "Endpoint = $ZION_ENDPOINT" >> "$CONFIG_FILE" echo "PersistentKeepalive = 25" >> "$CONFIG_FILE" print_status "Added Zion as default peer" fi fi # Add additional peers while true; do read -p "Do you want to add additional peers? (y/n): " ADD_PEER if [[ ! $ADD_PEER =~ ^[Yy]$ ]]; then break fi echo "" local peer_name read -p "Enter peer name (e.g., aza, cth, galaxy): " peer_name peer_name=$(safe_filename "$peer_name") local peer_public_key while true; do read -p "Enter peer public key: " peer_public_key if validate_public_key "$peer_public_key"; then break else print_error "Invalid WireGuard public key format" fi done local peer_allowed_ips while true; do read -p "Enter allowed IPs for this peer (e.g., 10.8.0.1/32 or 10.8.0.0/24): " peer_allowed_ips if validate_ip "$peer_allowed_ips"; then break else print_error "Invalid IP address format. Use format: x.x.x.x/y" fi done # Ask if this peer has an endpoint (for clients connecting to servers) read -p "Does this peer have an endpoint? (y/n): " HAS_ENDPOINT if [[ $HAS_ENDPOINT =~ ^[Yy]$ ]]; then read -p "Enter endpoint (host:port): " PEER_ENDPOINT local peer_keepalive read -p "Enter persistent keepalive (seconds, default 25): " peer_keepalive peer_keepalive=${peer_keepalive:-25} fi # Add peer to configuration echo "" >> "$CONFIG_FILE" echo "# $peer_name" >> "$CONFIG_FILE" echo "[Peer]" >> "$CONFIG_FILE" echo "PublicKey = $peer_public_key" >> "$CONFIG_FILE" echo "AllowedIPs = $peer_allowed_ips" >> "$CONFIG_FILE" if [[ $HAS_ENDPOINT =~ ^[Yy]$ ]]; then echo "Endpoint = $PEER_ENDPOINT" >> "$CONFIG_FILE" echo "PersistentKeepalive = $peer_keepalive" >> "$CONFIG_FILE" fi print_status "Added peer: $peer_name" done # Set proper file permissions chmod 600 "$CONFIG_FILE" print_status "Set file permissions to 600 (owner read/write only)" # Step 5: Display results print_header "Step 5: Setup Complete" print_status "Configuration file created: $CONFIG_FILE" print_status "Your public key: $PUBLIC_KEY" echo "" # Zion update instructions print_header "IMPORTANT: Update Zion Server Configuration" echo "" print_warning "You MUST add this peer to Zion's configuration file:" echo " /etc/wireguard/wg0.conf" echo "" echo "Add the following peer section to Zion's config:" echo "----------------------------------------" echo "# $node_name" echo "[Peer]" echo "PublicKey = $PUBLIC_KEY" echo "AllowedIPs = ${ip_address%/*}/32" echo "----------------------------------------" echo "" # Show Zion's current configuration structure if ! load_zion_config; then echo "Zion's current configuration structure:" echo "----------------------------------------" echo "[Interface]" echo "Address = 10.8.0.1/24" echo "ListenPort = 51820" echo "PrivateKey = " echo "PostUp = " echo "PostDown = " echo "" echo "#Cth" echo "[Peer]" echo "PublicKey = NBktXKy1s0n2lIlIMODvOqKNwAtYdoZH5feKt5P43i0=" echo "AllowedIPs = 10.8.0.10/32" echo "" echo "#Aza" echo "[Peer]" echo "PublicKey = qmTKA257DLOrfhk5Zw8RyRmBSonmm6epbloT0P0ZWDc=" echo "AllowedIPs = 10.8.0.2/32" echo "" echo "# Add your peer section here:" echo "# $node_name" echo "# [Peer]" echo "# PublicKey = $PUBLIC_KEY" echo "# AllowedIPs = ${ip_address%/*}/32" echo "----------------------------------------" fi echo "" print_warning "After updating Zion's config:" echo "1. Save the file" echo "2. Restart Zion's WireGuard: sudo systemctl restart wg-quick@wg0" echo "3. Then start this node's WireGuard: sudo wg-quick up ${node_name}" echo "" # Show the configuration file echo "Your configuration file contents:" echo "----------------------------------------" cat "$CONFIG_FILE" echo "----------------------------------------" # Create a summary file SUMMARY_FILE="$OUTPUT_DIR/${node_name}_summary.txt" if [ -f "$SUMMARY_FILE" ]; then print_warning "Summary file '$SUMMARY_FILE' already exists and will be overwritten." fi cat > "$SUMMARY_FILE" << EOF WireGuard Configuration Summary for $node_name =============================================== Node Name: $node_name IP Address: $ip_address $(if [[ $IS_SERVER =~ ^[Yy]$ ]]; then echo "Listen Port: $listen_port"; fi) Your Public Key: $PUBLIC_KEY Your Private Key: $PRIVATE_KEY Configuration File: $CONFIG_FILE Commands to use: - Start: sudo wg-quick up ${node_name} - Stop: sudo wg-quick down ${node_name} - Status: sudo wg show ZION SERVER UPDATE REQUIRED: =========================== You MUST add this peer to Zion's configuration file (/etc/wireguard/wg0.conf): # $node_name [Peer] PublicKey = $PUBLIC_KEY AllowedIPs = ${ip_address%/*}/32 After updating Zion's config: 1. Save the file 2. Restart Zion's WireGuard: sudo systemctl restart wg-quick@wg0 3. Then start this node's WireGuard: sudo wg-quick up ${node_name} Remember to: 1. Keep your private key secure 2. Update Zion's configuration with your public key 3. Set proper file permissions: chmod 600 $CONFIG_FILE 4. Restart both Zion and this node after configuration changes EOF print_status "Summary saved to: $SUMMARY_FILE" } # Function to show usage show_usage() { echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" echo " -h, --help Show this help message" echo " -d, --dir DIR Set output directory (default: wireguard_configs)" echo " -c, --config Use custom Zion config file" echo "" echo "This script will interactively guide you through creating WireGuard" echo "keys and configuration files." } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_usage exit 0 ;; -d|--dir) OUTPUT_DIR="$2" shift 2 ;; -c|--config) ZION_CONFIG_FILE="$2" shift 2 ;; *) print_error "Unknown option: $1" show_usage exit 1 ;; esac done # Run main function main "$@"