#!/usr/bin/env bash # ============================================================================= # WireGuard VPS Tunnel — точка входа сервера (VPS) # Генерирует конфигурацию wg0.conf из переменных окружения и поднимает туннель. # ============================================================================= set -euo pipefail # ── Значения по умолчанию ─────────────────────────────────────────────────── SERVER_WG_IP="${SERVER_WG_IP:-10.0.0.1}" SERVER_WG_PORT="${SERVER_WG_PORT:-51820}" FORWARD_PORTS="${FORWARD_PORTS:-80,443}" WG_CONF="/etc/wireguard/wg0.conf" # ── Логирование ───────────────────────────────────────────────────────────── log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$1] $*"; } # ── Автоопределение внешнего интерфейса и IP ──────────────────────────────── detect_network() { if [[ -z "${SERVER_PUBLIC_IFACE:-}" ]]; then SERVER_PUBLIC_IFACE=$(ip route get 8.8.8.8 2>/dev/null | awk '{print $5; exit}') if [[ -z "$SERVER_PUBLIC_IFACE" ]]; then log "ERROR" "Не удалось определить внешний сетевой интерфейс" exit 1 fi log "INFO" "Автоопределён внешний интерфейс: ${SERVER_PUBLIC_IFACE}" fi if [[ -z "${SERVER_PUBLIC_IP:-}" ]]; then SERVER_PUBLIC_IP=$(curl -4 -s ifconfig.me 2>/dev/null || curl -4 -s icanhazip.com 2>/dev/null || echo "") if [[ -z "$SERVER_PUBLIC_IP" ]]; then log "ERROR" "Не удалось определить публичный IP. Укажите SERVER_PUBLIC_IP" exit 1 fi log "INFO" "Автоопределён публичный IP: ${SERVER_PUBLIC_IP}" fi } # ── Генерация ключей ─────────────────────────────────────────────────────── generate_keys() { local private_key_file="/etc/wireguard/server_private.key" local public_key_file="/etc/wireguard/server_public.key" if [[ -f "$private_key_file" ]] && [[ -f "$public_key_file" ]]; then log "INFO" "Ключи сервера уже существуют" else log "INFO" "Генерация ключей сервера..." wg genkey | tee "$private_key_file" | wg pubkey > "$public_key_file" chmod 600 "$private_key_file" log "INFO" "Ключи сервера сгенерированы" fi SERVER_PRIVATE_KEY=$(cat "$private_key_file") SERVER_PUBLIC_KEY=$(cat "$public_key_file") } # ── Создание конфигурации WireGuard ──────────────────────────────────────── create_wg_config() { # Всегда пересоздаём конфиг — ключи или порты могли измениться if [[ -f "$WG_CONF" ]]; then log "INFO" "Обновление конфигурации ${WG_CONF}..." rm -f "$WG_CONF" fi if [[ -z "${CLIENT_PUBLIC_KEY:-}" ]]; then log "ERROR" "CLIENT_PUBLIC_KEY не задан. Укажите публичный ключ клиента." exit 1 fi local client_wg_ip="${CLIENT_WG_IP:-10.0.0.2}" # Формируем правила DNAT для каждого порта local dnat_rules="" local dnat_down_rules="" IFS=',' read -ra PORT_ARRAY <<< "$FORWARD_PORTS" for port in "${PORT_ARRAY[@]}"; do port=$(echo "$port" | xargs) dnat_rules+="iptables -t nat -A PREROUTING -d ${SERVER_PUBLIC_IP} -p tcp --dport ${port} -j DNAT --to-destination ${client_wg_ip}:${port}; " dnat_down_rules+="iptables -t nat -D PREROUTING -d ${SERVER_PUBLIC_IP} -p tcp --dport ${port} -j DNAT --to-destination ${client_wg_ip}:${port}; " done mkdir -p "$(dirname "$WG_CONF")" cat > "$WG_CONF" < /proc/sys/net/ipv4/ip_forward 2>/dev/null || true echo 1 > /proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || true # Удаляем старый интерфейс если остался от предыдущего запуска if ip link show wg0 &>/dev/null; then log "INFO" "Удаление старого интерфейса wg0..." ip link del wg0 2>/dev/null || true sleep 1 fi wg-quick up wg0 log "INFO" "WireGuard интерфейс wg0 запущен" log "INFO" "Публичный ключ сервера: ${SERVER_PUBLIC_KEY}" log "INFO" "Скопируйте его на клиент: SERVER_PUBLIC_KEY=${SERVER_PUBLIC_KEY}" } # ── Главная функция ──────────────────────────────────────────────────────── main() { log "INFO" "=== Запуск WireGuard VPS Tunnel (сервер) ===" log "INFO" "SERVER_WG_IP=${SERVER_WG_IP}" log "INFO" "SERVER_WG_PORT=${SERVER_WG_PORT}" log "INFO" "FORWARD_PORTS=${FORWARD_PORTS}" detect_network generate_keys create_wg_config start_wireguard log "INFO" "Сервер запущен. Ожидание..." exec sleep infinity } main