feat: WireGuard VPS туннель — установка в 1 клик
- install.sh: интерактивный + неинтерактивный (--vps/--client) установщик - watchdog.sh: Starlink-оптимизированный мониторинг с backoff - uninstall.sh: полная очистка - README.md: документация на русском языке Архитектура: VPS (10.0.0.1) ←WireGuard UDP→ RPi (10.0.0.2) DNAT портов 80/443 с VPS на RPi через iptables PersistentKeepalive 21с для Starlink/NAT
This commit is contained in:
323
README.md
Normal file
323
README.md
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
# WireGuard VPS Tunnel — 1-Click Installer
|
||||||
|
|
||||||
|
Автоматическая настройка WireGuard-туннеля между VPS (с публичным IP) и домашним сервером за NAT (Raspberry Pi, Orange Pi, Starlink и т.д.).
|
||||||
|
|
||||||
|
## Архитектура
|
||||||
|
|
||||||
|
```
|
||||||
|
Интернет
|
||||||
|
│
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ VPS (сервер) │
|
||||||
|
│ Публичный IP │
|
||||||
|
│ например: │
|
||||||
|
│ 2.59.219.234 │
|
||||||
|
│ │
|
||||||
|
│ wg0: 10.0.0.1 │
|
||||||
|
│ :51820 (UDP) │
|
||||||
|
│ │
|
||||||
|
│ iptables DNAT: │
|
||||||
|
│ :80 → 10.0.0.2 │
|
||||||
|
│ :443 → 10.0.0.2 │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
╔═════════════╧═════════════╗
|
||||||
|
║ WireGuard UDP :51820 ║
|
||||||
|
║ (PersistentKeepalive=21)║
|
||||||
|
╚═════════════╤═════════════╝
|
||||||
|
│
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ Домашний сервер │
|
||||||
|
│ (за NAT/CGNAT) │
|
||||||
|
│ Raspberry Pi │
|
||||||
|
│ Starlink │
|
||||||
|
│ │
|
||||||
|
│ wg0: 10.0.0.2 │
|
||||||
|
│ │
|
||||||
|
│ Watchdog │
|
||||||
|
│ (мониторинг) │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ Nginx Proxy │
|
||||||
|
│ Manager :80,443│
|
||||||
|
│ → backend │
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Как это работает:**
|
||||||
|
|
||||||
|
1. VPS принимает входящие соединения на порты 80 и 443
|
||||||
|
2. iptables перенаправляет трафик через WireGuard-туннель на домашний сервер (10.0.0.2)
|
||||||
|
3. Домашний сервер (RPi) инициирует соединение с VPS — работает через любой NAT
|
||||||
|
4. `PersistentKeepalive = 21` секунда поддерживает туннель активным даже при отсутствии трафика
|
||||||
|
5. Watchdog на RPi мониторит состояние туннеля и перезапускает при обрыве
|
||||||
|
|
||||||
|
## Быстрый старт (1 команда)
|
||||||
|
|
||||||
|
### На VPS:
|
||||||
|
```bash
|
||||||
|
curl -sSL https://raw.githubusercontent.com/user/wireguard-vps-tunnel/main/install.sh | sudo bash
|
||||||
|
# Выбрать "1) VPS"
|
||||||
|
```
|
||||||
|
|
||||||
|
### На домашнем сервере (Raspberry Pi):
|
||||||
|
```bash
|
||||||
|
curl -sSL https://raw.githubusercontent.com/user/wireguard-vps-tunnel/main/install.sh | sudo bash
|
||||||
|
# Выбрать "2) Домашний сервер"
|
||||||
|
```
|
||||||
|
|
||||||
|
Или неинтерактивный режим:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# VPS
|
||||||
|
sudo ./install.sh --vps --ports 80,443
|
||||||
|
|
||||||
|
# Клиент
|
||||||
|
sudo ./install.sh --client --vps-ip 2.59.219.234 --keepalive 21
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ручная установка
|
||||||
|
|
||||||
|
### 1. Клонирование репозитория
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/user/wireguard-vps-tunnel.git
|
||||||
|
cd wireguard-vps-tunnel
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Установка на VPS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./install.sh --vps --vps-ip 2.59.219.234 --ports 80,443
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт автоматически:
|
||||||
|
- Установит `wireguard-tools`
|
||||||
|
- Сгенерирует ключи
|
||||||
|
- Настроит `wg0` интерфейс
|
||||||
|
- Настроит iptables (DNAT + FORWARD)
|
||||||
|
- Включит IP-форвардинг
|
||||||
|
- Запустит systemd-сервис
|
||||||
|
|
||||||
|
### 3. Установка на домашний сервер
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./install.sh --client --vps-ip 2.59.219.234 --keepalive 21
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт автоматически:
|
||||||
|
- Установит `wireguard-tools`
|
||||||
|
- Сгенерирует ключи
|
||||||
|
- Настроит `wg0` интерфейс
|
||||||
|
- Установит watchdog для мониторинга туннеля
|
||||||
|
- Запустит systemd-сервисы
|
||||||
|
|
||||||
|
### 4. Проверка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На VPS
|
||||||
|
ping 10.0.0.2
|
||||||
|
|
||||||
|
# На домашнем сервере
|
||||||
|
ping 10.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Конфигурация
|
||||||
|
|
||||||
|
Все настройки сохраняются в `/etc/wireguard-vps-tunnel/config`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MODE="vps" # vps или client
|
||||||
|
VPS_PUBLIC_IP="2.59.219.234"
|
||||||
|
CLIENT_WG_IP="10.0.0.2"
|
||||||
|
SERVER_WG_IP="10.0.0.1"
|
||||||
|
WG_PORT="51820"
|
||||||
|
PORTS="80,443"
|
||||||
|
KEEPALIVE="21"
|
||||||
|
```
|
||||||
|
|
||||||
|
Ключи хранятся в `/etc/wireguard-vps-tunnel/`:
|
||||||
|
- `server_private.key` / `server_public.key`
|
||||||
|
- `client_private.key` / `client_public.key`
|
||||||
|
|
||||||
|
## Опции командной строки
|
||||||
|
|
||||||
|
| Опция | Описание | По умолчанию |
|
||||||
|
|-------|----------|-------------|
|
||||||
|
| `--vps` | Режим VPS (сервер) | — |
|
||||||
|
| `--client` | Режим клиента (домашний сервер) | — |
|
||||||
|
| `--vps-ip IP` | Публичный IP VPS | автоопределение |
|
||||||
|
| `--client-wg-ip IP` | WireGuard IP клиента | `10.0.0.2` |
|
||||||
|
| `--ports PORT,...` | Порты для проброса (VPS) | `80,443` |
|
||||||
|
| `--wg-port PORT` | Порт WireGuard | `51820` |
|
||||||
|
| `--keepalive SEC` | PersistentKeepalive (сек) | `21` |
|
||||||
|
| `--help` | Справка | — |
|
||||||
|
|
||||||
|
## Watchdog (мониторинг туннеля)
|
||||||
|
|
||||||
|
Watchdog работает только на клиенте (домашний сервер) и выполняет:
|
||||||
|
|
||||||
|
1. Проверяет, что интерфейс `wg0` поднят
|
||||||
|
2. Проверяет доступность VPS через туннель (`ping 10.0.0.1`)
|
||||||
|
3. Проверяет доступность VPS через интернет (`ping VPS_IP`)
|
||||||
|
4. Если туннель не работает, но VPS доступен — перезапускает WireGuard
|
||||||
|
5. Использует экспоненциальную отсрочку при повторных сбоях:
|
||||||
|
- 10с → 20с → 40с → 80с → 120с (максимум)
|
||||||
|
6. После 3 успешных проверок подряд сбрасывает отсрочку
|
||||||
|
|
||||||
|
**Логи:** `/var/log/wg-watchdog.log` (авторотация при 10 МБ)
|
||||||
|
|
||||||
|
**Управление:**
|
||||||
|
```bash
|
||||||
|
systemctl status wg-watchdog # Статус
|
||||||
|
systemctl restart wg-watchdog # Перезапуск
|
||||||
|
tail -f /var/log/wg-watchdog.log # Логи в реальном времени
|
||||||
|
```
|
||||||
|
|
||||||
|
## Сравнение: WireGuard vs SSH Reverse Tunnel
|
||||||
|
|
||||||
|
| Критерий | WireGuard | SSH Reverse Tunnel |
|
||||||
|
|----------|-----------|-------------------|
|
||||||
|
| Протокол | UDP (kernel) | TCP (userspace) |
|
||||||
|
| Производительность | ~1 Gbps | ~100 Mbps |
|
||||||
|
| Задержка | Минимальная | TCP-over-TCP проблема |
|
||||||
|
| Starlink | ✅ Оптимально (UDP) | ❌ Плохо (TCP через TCP) |
|
||||||
|
| Переподключение | Мгновенное | Заметная задержка |
|
||||||
|
| NAT traversal | PersistentKeepalive | Autossh + мониторинг |
|
||||||
|
| Проброс портов | iptables DNAT | `ssh -R` |
|
||||||
|
| Отказоустойчивость | Встроенная | Требует autossh |
|
||||||
|
| Нагрузка на CPU | Минимальная (kernel) | Заметная (шифрование в userspace) |
|
||||||
|
|
||||||
|
**Вывод:** WireGuard превосходит SSH reverse tunnel по всем параметрам для production-использования, особенно на Starlink.
|
||||||
|
|
||||||
|
## Starlink: особенности
|
||||||
|
|
||||||
|
Starlink использует CGNAT (Carrier-Grade NAT), что означает:
|
||||||
|
|
||||||
|
- **Нет публичного IPv4** — домашний сервер недоступен из интернета напрямую
|
||||||
|
- **Высокая задержка** — 25-60 мс (спутниковая связь)
|
||||||
|
- **Кратковременные обрывы** — при переключении между спутниками
|
||||||
|
- **UDP работает лучше TCP** — меньше проблем с TCP congestion control
|
||||||
|
|
||||||
|
**Рекомендации для Starlink:**
|
||||||
|
|
||||||
|
1. `PersistentKeepalive = 21` — оптимальное значение (каждые 21 сек отправляет keepalive-пакет)
|
||||||
|
2. Watchdog обязателен — автоматически восстанавливает туннель после обрывов
|
||||||
|
3. Не используйте SSH reverse tunnel — TCP-over-TCP на спутниковом канале работает плохо
|
||||||
|
4. MTU = 1420 (стандартный для WireGuard) — не меняйте без необходимости
|
||||||
|
|
||||||
|
## Безопасность
|
||||||
|
|
||||||
|
- **Ключи**: приватные ключи хранятся с правами `600` (только root)
|
||||||
|
- **Фаервол**: iptables правила применяются атомарно через `PostUp`/`PostDown`
|
||||||
|
- **SSH**: парольная аутентификация **НЕ отключается** — скрипт не трогает sshd_config
|
||||||
|
- **Порты**: открываются только указанные порты (по умолчанию 80 и 443)
|
||||||
|
- **WireGuard**: использует современную криптографию (Curve25519, ChaCha20, BLAKE2s)
|
||||||
|
|
||||||
|
### Рекомендации по усилению безопасности:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На VPS: ограничить доступ к порту WireGuard только с IP клиента (если известен)
|
||||||
|
iptables -A INPUT -p udp --dport 51820 -s <IP_КЛИЕНТА> -j ACCEPT
|
||||||
|
iptables -A INPUT -p udp --dport 51820 -j DROP
|
||||||
|
|
||||||
|
# Или ограничить rate limiting:
|
||||||
|
iptables -A INPUT -p udp --dport 51820 -m limit --limit 10/sec -j ACCEPT
|
||||||
|
iptables -A INPUT -p udp --dport 51820 -j DROP
|
||||||
|
```
|
||||||
|
|
||||||
|
## Устранение неполадок
|
||||||
|
|
||||||
|
### Туннель не поднимается
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить статус
|
||||||
|
systemctl status wg-quick@wg0
|
||||||
|
|
||||||
|
# Проверить конфигурацию
|
||||||
|
wg show
|
||||||
|
|
||||||
|
# Проверить логи
|
||||||
|
journalctl -u wg-quick@wg0 -n 50
|
||||||
|
```
|
||||||
|
|
||||||
|
### Пинг не проходит
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить что интерфейс поднят
|
||||||
|
ip link show wg0
|
||||||
|
|
||||||
|
# Проверить IP-адреса
|
||||||
|
ip addr show wg0
|
||||||
|
|
||||||
|
# Проверить что порт открыт на VPS
|
||||||
|
# На клиенте:
|
||||||
|
nc -zvu <VPS_IP> 51820
|
||||||
|
```
|
||||||
|
|
||||||
|
### Порты не пробрасываются
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить правила iptables на VPS
|
||||||
|
iptables -t nat -L PREROUTING -n
|
||||||
|
iptables -L FORWARD -n
|
||||||
|
|
||||||
|
# Проверить IP-форвардинг
|
||||||
|
sysctl net.ipv4.ip_forward # Должно быть = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watchdog не запускается
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status wg-watchdog
|
||||||
|
journalctl -u wg-watchdog -n 50
|
||||||
|
cat /var/log/wg-watchdog.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Полный сброс и переустановка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Деинсталляция
|
||||||
|
sudo ./uninstall.sh
|
||||||
|
|
||||||
|
# Переустановка
|
||||||
|
sudo ./install.sh --vps --vps-ip <IP>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Деинсталляция
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./uninstall.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Опции:
|
||||||
|
- `--remove-package` — также удалить пакет `wireguard-tools`
|
||||||
|
|
||||||
|
Деинсталлятор:
|
||||||
|
- Останавливает и отключает сервисы
|
||||||
|
- Удаляет интерфейс `wg0`
|
||||||
|
- Очищает правила iptables
|
||||||
|
- Удаляет конфигурационные файлы и ключи
|
||||||
|
- **НЕ трогает** SSH-сервер и другие сервисы
|
||||||
|
|
||||||
|
## Поддерживаемые ОС
|
||||||
|
|
||||||
|
- Debian 11+ (Bullseye, Bookworm)
|
||||||
|
- Ubuntu 20.04+ (Focal, Jammy, Noble)
|
||||||
|
- Armbian (Orange Pi, Banana Pi, etc.)
|
||||||
|
- Raspberry Pi OS (Raspbian)
|
||||||
|
|
||||||
|
## Структура проекта
|
||||||
|
|
||||||
|
```
|
||||||
|
wireguard-vps-tunnel/
|
||||||
|
├── install.sh # Основной установщик
|
||||||
|
├── uninstall.sh # Деинсталлятор
|
||||||
|
├── watchdog.sh # Watchdog для мониторинга туннеля
|
||||||
|
└── README.md # Документация
|
||||||
|
```
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
MIT
|
||||||
530
install.sh
Normal file
530
install.sh
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# WireGuard VPS Tunnel — 1-Click Installer
|
||||||
|
# Автоматическая настройка туннеля между VPS (публичный IP) и домашним сервером
|
||||||
|
# (Raspberry Pi / Orange Pi за NAT, например Starlink)
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Цвета для вывода ────────────────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# ── Пути ────────────────────────────────────────────────────────────────────
|
||||||
|
CONFIG_DIR="/etc/wireguard-vps-tunnel"
|
||||||
|
CONFIG_FILE="$CONFIG_DIR/config"
|
||||||
|
WG_CONF="/etc/wireguard/wg0.conf"
|
||||||
|
WATCHDOG_BIN="/usr/local/bin/wg-watchdog.sh"
|
||||||
|
WATCHDOG_SERVICE="/etc/systemd/system/wg-watchdog.service"
|
||||||
|
WG_SERVICE="wg-quick@wg0"
|
||||||
|
|
||||||
|
# ── Значения по умолчанию ───────────────────────────────────────────────────
|
||||||
|
MODE="" # vps или client
|
||||||
|
VPS_PUBLIC_IP="" # Публичный IP VPS
|
||||||
|
CLIENT_WG_IP="10.0.0.2" # WireGuard IP клиента
|
||||||
|
SERVER_WG_IP="10.0.0.1" # WireGuard IP сервера
|
||||||
|
WG_PORT="51820" # Порт WireGuard
|
||||||
|
PORTS="80,443" # Порты для проброса (только VPS)
|
||||||
|
KEEPALIVE="21" # PersistentKeepalive (секунды)
|
||||||
|
INTERACTIVE=true
|
||||||
|
|
||||||
|
# ── Функции вывода ──────────────────────────────────────────────────────────
|
||||||
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||||
|
success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
||||||
|
header() { echo -e "\n${BOLD}${CYAN}═══ $* ═══${NC}\n"; }
|
||||||
|
|
||||||
|
# ── Баннер ──────────────────────────────────────────────────────────────────
|
||||||
|
banner() {
|
||||||
|
echo -e "${CYAN}${BOLD}"
|
||||||
|
echo "╔══════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ WireGuard VPS Tunnel — 1-Click Installer ║"
|
||||||
|
echo "║ VPS ↔ Домашний сервер (за NAT / Starlink) ║"
|
||||||
|
echo "╚══════════════════════════════════════════════════════════╝"
|
||||||
|
echo -e "${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Проверка прав ──────────────────────────────────────────────────────────
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "Скрипт должен выполняться от root. Используйте: sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Определение ОС ─────────────────────────────────────────────────────────
|
||||||
|
detect_os() {
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
. /etc/os-release
|
||||||
|
OS_ID="${ID}"
|
||||||
|
OS_NAME="${PRETTY_NAME:-$NAME}"
|
||||||
|
else
|
||||||
|
error "Не удалось определить операционную систему"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$OS_ID" in
|
||||||
|
debian|ubuntu|armbian|raspbian)
|
||||||
|
info "Обнаружена ОС: ${OS_NAME}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warn "ОС '$OS_ID' не тестировалась. Продолжаем, но возможны проблемы."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Установка зависимостей ─────────────────────────────────────────────────
|
||||||
|
install_deps() {
|
||||||
|
header "Установка зависимостей"
|
||||||
|
|
||||||
|
if command -v wg &>/dev/null; then
|
||||||
|
success "WireGuard уже установлен: $(wg --version 2>&1 | head -1)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Установка wireguard-tools..."
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq wireguard-tools iptables
|
||||||
|
|
||||||
|
if command -v wg &>/dev/null; then
|
||||||
|
success "WireGuard установлен успешно"
|
||||||
|
else
|
||||||
|
error "Не удалось установить WireGuard"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Включение IP-форвардинга ───────────────────────────────────────────────
|
||||||
|
enable_ip_forward() {
|
||||||
|
header "Включение IP-форвардинга"
|
||||||
|
|
||||||
|
local sysctl_conf="/etc/sysctl.d/99-wireguard-vps-tunnel.conf"
|
||||||
|
|
||||||
|
if [[ -f "$sysctl_conf" ]]; then
|
||||||
|
info "IP-форвардинг уже настроен"
|
||||||
|
else
|
||||||
|
cat > "$sysctl_conf" <<'SYSCTL'
|
||||||
|
# Включение IP-форвардинга для WireGuard VPS Tunnel
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
net.ipv6.conf.all.forwarding = 1
|
||||||
|
SYSCTL
|
||||||
|
sysctl --system &>/dev/null
|
||||||
|
success "IP-форвардинг включён"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Генерация ключей ───────────────────────────────────────────────────────
|
||||||
|
generate_keys() {
|
||||||
|
header "Генерация ключей WireGuard"
|
||||||
|
|
||||||
|
mkdir -p "$CONFIG_DIR"
|
||||||
|
|
||||||
|
if [[ -f "$CONFIG_DIR/server_private.key" ]] && [[ -f "$CONFIG_DIR/client_private.key" ]]; then
|
||||||
|
info "Ключи уже существуют, пропускаем генерацию"
|
||||||
|
else
|
||||||
|
# Генерируем ключи сервера
|
||||||
|
wg genkey | tee "$CONFIG_DIR/server_private.key" | wg pubkey > "$CONFIG_DIR/server_public.key"
|
||||||
|
chmod 600 "$CONFIG_DIR/server_private.key"
|
||||||
|
|
||||||
|
# Генерируем ключи клиента
|
||||||
|
wg genkey | tee "$CONFIG_DIR/client_private.key" | wg pubkey > "$CONFIG_DIR/client_public.key"
|
||||||
|
chmod 600 "$CONFIG_DIR/client_private.key"
|
||||||
|
|
||||||
|
success "Ключи сгенерированы"
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVER_PRIVATE_KEY=$(cat "$CONFIG_DIR/server_private.key")
|
||||||
|
SERVER_PUBLIC_KEY=$(cat "$CONFIG_DIR/server_public.key")
|
||||||
|
CLIENT_PRIVATE_KEY=$(cat "$CONFIG_DIR/client_private.key")
|
||||||
|
CLIENT_PUBLIC_KEY=$(cat "$CONFIG_DIR/client_public.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Загрузка существующей конфигурации ─────────────────────────────────────
|
||||||
|
load_config() {
|
||||||
|
if [[ -f "$CONFIG_FILE" ]]; then
|
||||||
|
info "Загружена существующая конфигурация из $CONFIG_FILE"
|
||||||
|
source "$CONFIG_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Сохранение конфигурации ────────────────────────────────────────────────
|
||||||
|
save_config() {
|
||||||
|
mkdir -p "$CONFIG_DIR"
|
||||||
|
cat > "$CONFIG_FILE" <<EOF
|
||||||
|
# WireGuard VPS Tunnel — конфигурация
|
||||||
|
# Создано: $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
MODE="$MODE"
|
||||||
|
VPS_PUBLIC_IP="$VPS_PUBLIC_IP"
|
||||||
|
CLIENT_WG_IP="$CLIENT_WG_IP"
|
||||||
|
SERVER_WG_IP="$SERVER_WG_IP"
|
||||||
|
WG_PORT="$WG_PORT"
|
||||||
|
PORTS="$PORTS"
|
||||||
|
KEEPALIVE="$KEEPALIVE"
|
||||||
|
EOF
|
||||||
|
chmod 600 "$CONFIG_FILE"
|
||||||
|
success "Конфигурация сохранена в $CONFIG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Интерактивный опрос ────────────────────────────────────────────────────
|
||||||
|
interactive_setup() {
|
||||||
|
header "Настройка параметров"
|
||||||
|
|
||||||
|
echo -e "${BOLD}Где запущен этот скрипт?${NC}"
|
||||||
|
echo " 1) VPS (сервер с публичным IP)"
|
||||||
|
echo " 2) Домашний сервер / Raspberry Pi (за NAT)"
|
||||||
|
echo
|
||||||
|
while true; do
|
||||||
|
read -r -p "Выберите [1/2]: " choice
|
||||||
|
case "$choice" in
|
||||||
|
1) MODE="vps"; break ;;
|
||||||
|
2) MODE="client"; break ;;
|
||||||
|
*) warn "Введите 1 или 2" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$MODE" == "vps" ]]; then
|
||||||
|
# Автоопределение публичного IP
|
||||||
|
local detected_ip
|
||||||
|
detected_ip=$(curl -4 -s ifconfig.me 2>/dev/null || curl -4 -s icanhazip.com 2>/dev/null || echo "")
|
||||||
|
if [[ -n "$detected_ip" ]]; then
|
||||||
|
echo -e "${BOLD}Публичный IP VPS:${NC} [${detected_ip}]"
|
||||||
|
read -r -p "Нажмите Enter для подтверждения или введите другой: " input
|
||||||
|
VPS_PUBLIC_IP="${input:-$detected_ip}"
|
||||||
|
else
|
||||||
|
read -r -p "Введите публичный IP VPS: " VPS_PUBLIC_IP
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -r -p "Порты для проброса (через запятую) [80,443]: " input
|
||||||
|
PORTS="${input:-80,443}"
|
||||||
|
|
||||||
|
read -r -p "WireGuard IP клиента [10.0.0.2]: " input
|
||||||
|
CLIENT_WG_IP="${input:-10.0.0.2}"
|
||||||
|
|
||||||
|
read -r -p "WireGuard порт [51820]: " input
|
||||||
|
WG_PORT="${input:-51820}"
|
||||||
|
else
|
||||||
|
read -r -p "Публичный IP VPS: " VPS_PUBLIC_IP
|
||||||
|
|
||||||
|
read -r -p "WireGuard IP этого сервера [10.0.0.2]: " input
|
||||||
|
CLIENT_WG_IP="${input:-10.0.0.2}"
|
||||||
|
|
||||||
|
read -r -p "WireGuard порт VPS [51820]: " input
|
||||||
|
WG_PORT="${input:-51820}"
|
||||||
|
|
||||||
|
read -r -p "PersistentKeepalive (сек) [21]: " input
|
||||||
|
KEEPALIVE="${input:-21}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Парсинг аргументов командной строки ────────────────────────────────────
|
||||||
|
parse_args() {
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--vps)
|
||||||
|
MODE="vps"
|
||||||
|
INTERACTIVE=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--client)
|
||||||
|
MODE="client"
|
||||||
|
INTERACTIVE=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--vps-ip)
|
||||||
|
VPS_PUBLIC_IP="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--client-wg-ip)
|
||||||
|
CLIENT_WG_IP="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--ports)
|
||||||
|
PORTS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--wg-port)
|
||||||
|
WG_PORT="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--keepalive)
|
||||||
|
KEEPALIVE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Использование: $0 [ОПЦИИ]"
|
||||||
|
echo ""
|
||||||
|
echo "Опции:"
|
||||||
|
echo " --vps Режим VPS (сервер с публичным IP)"
|
||||||
|
echo " --client Режим клиента (домашний сервер за NAT)"
|
||||||
|
echo " --vps-ip IP Публичный IP-адрес VPS"
|
||||||
|
echo " --client-wg-ip IP WireGuard IP клиента (по умолчанию: 10.0.0.2)"
|
||||||
|
echo " --ports PORT,... Порты для проброса (по умолчанию: 80,443)"
|
||||||
|
echo " --wg-port PORT Порт WireGuard (по умолчанию: 51820)"
|
||||||
|
echo " --keepalive SEC PersistentKeepalive в секундах (по умолчанию: 21)"
|
||||||
|
echo " --help, -h Показать эту справку"
|
||||||
|
echo ""
|
||||||
|
echo "Примеры:"
|
||||||
|
echo " # Интерактивный режим"
|
||||||
|
echo " sudo $0"
|
||||||
|
echo ""
|
||||||
|
echo " # Неинтерактивный режим (VPS)"
|
||||||
|
echo " sudo $0 --vps --vps-ip 2.59.219.234 --ports 80,443,8080"
|
||||||
|
echo ""
|
||||||
|
echo " # Неинтерактивный режим (клиент)"
|
||||||
|
echo " sudo $0 --client --vps-ip 2.59.219.234 --keepalive 21"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Неизвестный аргумент: $1"
|
||||||
|
echo "Используйте --help для справки"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Создание конфигурации WireGuard для VPS ────────────────────────────────
|
||||||
|
configure_vps() {
|
||||||
|
header "Настройка WireGuard (VPS — сервер)"
|
||||||
|
|
||||||
|
# Формируем правила iptables для каждого порта
|
||||||
|
local dnat_rules=""
|
||||||
|
local dnat_down_rules=""
|
||||||
|
IFS=',' read -ra PORT_ARRAY <<< "$PORTS"
|
||||||
|
|
||||||
|
for port in "${PORT_ARRAY[@]}"; do
|
||||||
|
port=$(echo "$port" | xargs) # trim whitespace
|
||||||
|
dnat_rules+="iptables -t nat -A PREROUTING -d ${VPS_PUBLIC_IP} -p tcp --dport ${port} -j DNAT --to-destination ${CLIENT_WG_IP}:${port}; "
|
||||||
|
dnat_down_rules+="iptables -t nat -D PREROUTING -d ${VPS_PUBLIC_IP} -p tcp --dport ${port} -j DNAT --to-destination ${CLIENT_WG_IP}:${port}; "
|
||||||
|
done
|
||||||
|
|
||||||
|
# Определяем внешний интерфейс
|
||||||
|
local ext_if
|
||||||
|
ext_if=$(ip route get 8.8.8.8 | awk '{print $5; exit}')
|
||||||
|
|
||||||
|
cat > "$WG_CONF" <<WGCONF
|
||||||
|
# WireGuard VPS Tunnel — конфигурация сервера (VPS)
|
||||||
|
# Создано: $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = ${SERVER_PRIVATE_KEY}
|
||||||
|
Address = ${SERVER_WG_IP}/24
|
||||||
|
ListenPort = ${WG_PORT}
|
||||||
|
|
||||||
|
# Правила проброса портов и форвардинга
|
||||||
|
PostUp = ${dnat_rules} iptables -t nat -A POSTROUTING -d ${CLIENT_WG_IP} -j MASQUERADE; iptables -I FORWARD 1 -i ${ext_if} -o wg0 -p tcp -m multiport --dports ${PORTS} -j ACCEPT; iptables -I FORWARD 2 -i wg0 -o ${ext_if} -m state --state ESTABLISHED,RELATED -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
|
||||||
|
PostDown = ${dnat_down_rules} iptables -t nat -D POSTROUTING -d ${CLIENT_WG_IP} -j MASQUERADE; iptables -D FORWARD -i ${ext_if} -o wg0 -p tcp -m multiport --dports ${PORTS} -j ACCEPT; iptables -D FORWARD -i wg0 -o ${ext_if} -m state --state ESTABLISHED,RELATED -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
# Клиент (домашний сервер / Raspberry Pi)
|
||||||
|
PublicKey = ${CLIENT_PUBLIC_KEY}
|
||||||
|
AllowedIPs = ${CLIENT_WG_IP}/32
|
||||||
|
WGCONF
|
||||||
|
|
||||||
|
chmod 600 "$WG_CONF"
|
||||||
|
success "Конфигурация WireGuard создана: $WG_CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Создание конфигурации WireGuard для клиента ────────────────────────────
|
||||||
|
configure_client() {
|
||||||
|
header "Настройка WireGuard (клиент — домашний сервер)"
|
||||||
|
|
||||||
|
cat > "$WG_CONF" <<WGCONF
|
||||||
|
# WireGuard VPS Tunnel — конфигурация клиента (домашний сервер)
|
||||||
|
# Создано: $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = ${CLIENT_PRIVATE_KEY}
|
||||||
|
Address = ${CLIENT_WG_IP}/24
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
# VPS (сервер)
|
||||||
|
PublicKey = ${SERVER_PUBLIC_KEY}
|
||||||
|
Endpoint = ${VPS_PUBLIC_IP}:${WG_PORT}
|
||||||
|
AllowedIPs = ${SERVER_WG_IP}/24
|
||||||
|
PersistentKeepalive = ${KEEPALIVE}
|
||||||
|
WGCONF
|
||||||
|
|
||||||
|
chmod 600 "$WG_CONF"
|
||||||
|
success "Конфигурация WireGuard создана: $WG_CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Запуск WireGuard ───────────────────────────────────────────────────────
|
||||||
|
start_wireguard() {
|
||||||
|
header "Запуск WireGuard"
|
||||||
|
|
||||||
|
# Останавливаем если уже запущен (идемпотентность)
|
||||||
|
if systemctl is-active --quiet "$WG_SERVICE" 2>/dev/null; then
|
||||||
|
info "WireGuard уже запущен, перезапускаем..."
|
||||||
|
systemctl stop "$WG_SERVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
systemctl enable "$WG_SERVICE" &>/dev/null
|
||||||
|
systemctl start "$WG_SERVICE"
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
if systemctl is-active --quiet "$WG_SERVICE"; then
|
||||||
|
success "WireGuard запущен и добавлен в автозагрузку"
|
||||||
|
else
|
||||||
|
error "Не удалось запустить WireGuard. Проверьте: systemctl status $WG_SERVICE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Показываем статус интерфейса
|
||||||
|
echo ""
|
||||||
|
wg show wg0 2>/dev/null || warn "Интерфейс wg0 не найден"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Установка watchdog (только для клиента) ────────────────────────────────
|
||||||
|
install_watchdog() {
|
||||||
|
header "Установка Watchdog (мониторинг туннеля)"
|
||||||
|
|
||||||
|
# Копируем watchdog из директории скрипта
|
||||||
|
local script_dir
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
if [[ -f "$script_dir/watchdog.sh" ]]; then
|
||||||
|
cp "$script_dir/watchdog.sh" "$WATCHDOG_BIN"
|
||||||
|
else
|
||||||
|
error "Файл watchdog.sh не найден в $script_dir"
|
||||||
|
error "Поместите watchdog.sh рядом с install.sh и запустите снова"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x "$WATCHDOG_BIN"
|
||||||
|
|
||||||
|
# Подставляем IP VPS в watchdog
|
||||||
|
sed -i "s/VPS_IP=\"\"/VPS_IP=\"${VPS_PUBLIC_IP}\"/" "$WATCHDOG_BIN" 2>/dev/null || true
|
||||||
|
sed -i "s/VPS_WG_IP=\"\"/VPS_WG_IP=\"${SERVER_WG_IP}\"/" "$WATCHDOG_BIN" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Создаём systemd-сервис для watchdog
|
||||||
|
cat > "$WATCHDOG_SERVICE" <<SYSTEMD
|
||||||
|
[Unit]
|
||||||
|
Description=WireGuard Watchdog — оптимизирован для Starlink
|
||||||
|
After=network-online.target wg-quick@wg0.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=${WATCHDOG_BIN}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=wg-watchdog
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SYSTEMD
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable wg-watchdog &>/dev/null
|
||||||
|
systemctl start wg-watchdog
|
||||||
|
|
||||||
|
if systemctl is-active --quiet wg-watchdog; then
|
||||||
|
success "Watchdog установлен и запущен"
|
||||||
|
else
|
||||||
|
warn "Watchdog установлен, но не запустился. Проверьте: systemctl status wg-watchdog"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Вывод итоговой информации ──────────────────────────────────────────────
|
||||||
|
print_summary() {
|
||||||
|
header "Установка завершена"
|
||||||
|
|
||||||
|
echo -e "${BOLD}Режим:${NC} ${MODE}"
|
||||||
|
echo -e "${BOLD}Публичный IP VPS:${NC} ${VPS_PUBLIC_IP}"
|
||||||
|
echo -e "${BOLD}WireGuard IP:${NC} ${CLIENT_WG_IP} (клиент) ↔ ${SERVER_WG_IP} (сервер)"
|
||||||
|
echo -e "${BOLD}Порт WG:${NC} ${WG_PORT}"
|
||||||
|
|
||||||
|
if [[ "$MODE" == "vps" ]]; then
|
||||||
|
echo -e "${BOLD}Проброс портов:${NC} ${PORTS} → ${CLIENT_WG_IP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}Полезные команды:${NC}"
|
||||||
|
echo " wg show — статус туннеля"
|
||||||
|
echo " systemctl status wg-quick@wg0 — статус сервиса"
|
||||||
|
echo " ping ${SERVER_WG_IP} — проверка туннеля"
|
||||||
|
|
||||||
|
if [[ "$MODE" == "client" ]]; then
|
||||||
|
echo " systemctl status wg-watchdog — статус watchdog"
|
||||||
|
echo " tail -f /var/log/wg-watchdog.log — логи watchdog"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}Конфигурация:${NC} ${CONFIG_FILE}"
|
||||||
|
echo -e "${BOLD}Ключи:${NC} ${CONFIG_DIR}/"
|
||||||
|
|
||||||
|
if [[ "$MODE" == "vps" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}${BOLD}⚠️ ВАЖНО:${NC} ${YELLOW}Скопируйте публичный ключ сервера на клиент:${NC}"
|
||||||
|
echo -e " ${BOLD}cat ${CONFIG_DIR}/server_public.key${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Затем запустите install.sh на клиенте:${NC}"
|
||||||
|
echo -e " ${BOLD}sudo ./install.sh --client --vps-ip ${VPS_PUBLIC_IP}${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Главная функция ────────────────────────────────────────────────────────
|
||||||
|
main() {
|
||||||
|
banner
|
||||||
|
check_root
|
||||||
|
parse_args "$@"
|
||||||
|
detect_os
|
||||||
|
load_config
|
||||||
|
|
||||||
|
if [[ "$INTERACTIVE" == true ]] && [[ -z "$MODE" ]]; then
|
||||||
|
interactive_setup
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$MODE" ]]; then
|
||||||
|
error "Не указан режим. Используйте --vps или --client, либо интерактивный режим."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MODE" == "client" ]] && [[ -z "$VPS_PUBLIC_IP" ]]; then
|
||||||
|
error "Не указан публичный IP VPS. Используйте --vps-ip IP"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Автоопределение публичного IP для VPS если не указан
|
||||||
|
if [[ "$MODE" == "vps" ]] && [[ -z "$VPS_PUBLIC_IP" ]]; then
|
||||||
|
VPS_PUBLIC_IP=$(curl -4 -s ifconfig.me 2>/dev/null || curl -4 -s icanhazip.com 2>/dev/null || echo "")
|
||||||
|
if [[ -z "$VPS_PUBLIC_IP" ]]; then
|
||||||
|
error "Не удалось определить публичный IP. Укажите вручную: --vps-ip IP"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "Автоопределён публичный IP: ${VPS_PUBLIC_IP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_deps
|
||||||
|
enable_ip_forward
|
||||||
|
generate_keys
|
||||||
|
|
||||||
|
if [[ "$MODE" == "vps" ]]; then
|
||||||
|
configure_vps
|
||||||
|
else
|
||||||
|
configure_client
|
||||||
|
fi
|
||||||
|
|
||||||
|
start_wireguard
|
||||||
|
save_config
|
||||||
|
|
||||||
|
if [[ "$MODE" == "client" ]]; then
|
||||||
|
install_watchdog
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_summary
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
240
uninstall.sh
Normal file
240
uninstall.sh
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# WireGuard VPS Tunnel — Деинсталлятор
|
||||||
|
# Полное удаление туннеля, сервисов и правил iptables
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||||
|
success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
||||||
|
|
||||||
|
CONFIG_DIR="/etc/wireguard-vps-tunnel"
|
||||||
|
CONFIG_FILE="$CONFIG_DIR/config"
|
||||||
|
WG_CONF="/etc/wireguard/wg0.conf"
|
||||||
|
WATCHDOG_BIN="/usr/local/bin/wg-watchdog.sh"
|
||||||
|
WATCHDOG_SERVICE="/etc/systemd/system/wg-watchdog.service"
|
||||||
|
SYSCTL_CONF="/etc/sysctl.d/99-wireguard-vps-tunnel.conf"
|
||||||
|
REMOVE_PACKAGE=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Использование: $0 [ОПЦИИ]"
|
||||||
|
echo ""
|
||||||
|
echo "Опции:"
|
||||||
|
echo " --remove-package Также удалить пакет wireguard-tools"
|
||||||
|
echo " --help, -h Показать эту справку"
|
||||||
|
echo ""
|
||||||
|
echo "Пример:"
|
||||||
|
echo " sudo $0"
|
||||||
|
echo " sudo $0 --remove-package"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args() {
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--remove-package) REMOVE_PACKAGE=true; shift ;;
|
||||||
|
--help|-h) usage ;;
|
||||||
|
*) error "Неизвестный аргумент: $1"; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "Скрипт должен выполняться от root. Используйте: sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_services() {
|
||||||
|
echo ""
|
||||||
|
info "Остановка сервисов..."
|
||||||
|
|
||||||
|
# Останавливаем watchdog
|
||||||
|
if systemctl is-active --quiet wg-watchdog 2>/dev/null; then
|
||||||
|
systemctl stop wg-watchdog
|
||||||
|
success "Watchdog остановлен"
|
||||||
|
else
|
||||||
|
info "Watchdog не запущен"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Отключаем watchdog
|
||||||
|
if systemctl is-enabled --quiet wg-watchdog 2>/dev/null; then
|
||||||
|
systemctl disable wg-watchdog &>/dev/null
|
||||||
|
success "Watchdog отключён из автозагрузки"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Останавливаем WireGuard
|
||||||
|
if systemctl is-active --quiet wg-quick@wg0 2>/dev/null; then
|
||||||
|
systemctl stop wg-quick@wg0
|
||||||
|
success "WireGuard остановлен"
|
||||||
|
else
|
||||||
|
info "WireGuard не запущен"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Отключаем WireGuard
|
||||||
|
if systemctl is-enabled --quiet wg-quick@wg0 2>/dev/null; then
|
||||||
|
systemctl disable wg-quick@wg0 &>/dev/null
|
||||||
|
success "WireGuard отключён из автозагрузки"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_interface() {
|
||||||
|
info "Удаление интерфейса wg0..."
|
||||||
|
|
||||||
|
if ip link show wg0 &>/dev/null; then
|
||||||
|
ip link delete wg0 2>/dev/null || true
|
||||||
|
success "Интерфейс wg0 удалён"
|
||||||
|
else
|
||||||
|
info "Интерфейс wg0 не существует"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_iptables_rules() {
|
||||||
|
info "Очистка правил iptables..."
|
||||||
|
|
||||||
|
# Удаляем правила DNAT и FORWARD, связанные с wg0
|
||||||
|
local rules_removed=0
|
||||||
|
|
||||||
|
# Удаляем DNAT правила
|
||||||
|
while iptables -t nat -L PREROUTING -n 2>/dev/null | grep -q "10\.0\.0\."; do
|
||||||
|
local rule_num
|
||||||
|
rule_num=$(iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep "10\.0\.0\." | head -1 | awk '{print $1}')
|
||||||
|
if [[ -n "$rule_num" ]]; then
|
||||||
|
iptables -t nat -D PREROUTING "$rule_num" 2>/dev/null || true
|
||||||
|
((rules_removed++)) || true
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Удаляем MASQUERADE правила
|
||||||
|
while iptables -t nat -L POSTROUTING -n 2>/dev/null | grep -q "10\.0\.0\."; do
|
||||||
|
local rule_num
|
||||||
|
rule_num=$(iptables -t nat -L POSTROUTING -n --line-numbers 2>/dev/null | grep "10\.0\.0\." | head -1 | awk '{print $1}')
|
||||||
|
if [[ -n "$rule_num" ]]; then
|
||||||
|
iptables -t nat -D POSTROUTING "$rule_num" 2>/dev/null || true
|
||||||
|
((rules_removed++)) || true
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Удаляем FORWARD правила для wg0
|
||||||
|
while iptables -L FORWARD -n 2>/dev/null | grep -q "wg0"; do
|
||||||
|
local rule_num
|
||||||
|
rule_num=$(iptables -L FORWARD -n --line-numbers 2>/dev/null | grep "wg0" | head -1 | awk '{print $1}')
|
||||||
|
if [[ -n "$rule_num" ]]; then
|
||||||
|
iptables -D FORWARD "$rule_num" 2>/dev/null || true
|
||||||
|
((rules_removed++)) || true
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $rules_removed -gt 0 ]]; then
|
||||||
|
success "Удалено правил iptables: ${rules_removed}"
|
||||||
|
else
|
||||||
|
info "Правила iptables не найдены"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_files() {
|
||||||
|
info "Удаление файлов..."
|
||||||
|
|
||||||
|
# Удаляем конфигурацию WireGuard
|
||||||
|
if [[ -f "$WG_CONF" ]]; then
|
||||||
|
rm -f "$WG_CONF"
|
||||||
|
success "Удалён: $WG_CONF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем watchdog
|
||||||
|
if [[ -f "$WATCHDOG_BIN" ]]; then
|
||||||
|
rm -f "$WATCHDOG_BIN"
|
||||||
|
success "Удалён: $WATCHDOG_BIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем systemd-сервис watchdog
|
||||||
|
if [[ -f "$WATCHDOG_SERVICE" ]]; then
|
||||||
|
rm -f "$WATCHDOG_SERVICE"
|
||||||
|
systemctl daemon-reload
|
||||||
|
success "Удалён: $WATCHDOG_SERVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем sysctl конфигурацию
|
||||||
|
if [[ -f "$SYSCTL_CONF" ]]; then
|
||||||
|
rm -f "$SYSCTL_CONF"
|
||||||
|
sysctl --system &>/dev/null
|
||||||
|
success "Удалён: $SYSCTL_CONF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем директорию с ключами и конфигом
|
||||||
|
if [[ -d "$CONFIG_DIR" ]]; then
|
||||||
|
rm -rf "$CONFIG_DIR"
|
||||||
|
success "Удалён: $CONFIG_DIR/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем лог watchdog
|
||||||
|
if [[ -f /var/log/wg-watchdog.log ]]; then
|
||||||
|
rm -f /var/log/wg-watchdog.log
|
||||||
|
success "Удалён: /var/log/wg-watchdog.log"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_package() {
|
||||||
|
if [[ "$REMOVE_PACKAGE" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
warn "Удаление пакета wireguard-tools..."
|
||||||
|
read -r -p "Вы уверены? Это удалит WireGuard полностью [y/N]: " confirm
|
||||||
|
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
apt-get remove -y --purge wireguard-tools 2>/dev/null || true
|
||||||
|
apt-get autoremove -y 2>/dev/null || true
|
||||||
|
success "Пакет wireguard-tools удалён"
|
||||||
|
else
|
||||||
|
info "Пакет wireguard-tools оставлен"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
echo -e "${RED}${BOLD}"
|
||||||
|
echo "╔══════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ WireGuard VPS Tunnel — ДЕИНСТАЛЛЯТОР ║"
|
||||||
|
echo "╚══════════════════════════════════════════════════════════╝"
|
||||||
|
echo -e "${NC}"
|
||||||
|
|
||||||
|
check_root
|
||||||
|
parse_args "$@"
|
||||||
|
|
||||||
|
warn "Этот скрипт полностью удалит WireGuard VPS Tunnel."
|
||||||
|
warn "Будут удалены: туннель, сервисы, правила iptables, ключи."
|
||||||
|
echo ""
|
||||||
|
read -r -p "Продолжить? [y/N]: " confirm
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
info "Отмена."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
stop_services
|
||||||
|
remove_interface
|
||||||
|
remove_iptables_rules
|
||||||
|
remove_files
|
||||||
|
remove_package
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
success "WireGuard VPS Tunnel полностью удалён."
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}${BOLD}Примечание:${NC} ${YELLOW}SSH-сервер и другие сервисы не были затронуты.${NC}"
|
||||||
|
echo -e "${YELLOW}PasswordAuthentication в sshd_config НЕ изменялся.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
190
watchdog.sh
Normal file
190
watchdog.sh
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# WireGuard Watchdog — оптимизирован для Starlink
|
||||||
|
# Мониторит состояние туннеля и перезапускает при обрыве связи.
|
||||||
|
# Использует экспоненциальную отсрочку (backoff) при повторных сбоях.
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Настройки ───────────────────────────────────────────────────────────────
|
||||||
|
VPS_IP="" # Публичный IP VPS (заполняется install.sh)
|
||||||
|
VPS_WG_IP="" # WireGuard IP VPS (заполняется install.sh)
|
||||||
|
WG_INTERFACE="wg0"
|
||||||
|
LOG_FILE="/var/log/wg-watchdog.log"
|
||||||
|
MAX_LOG_SIZE=$((10 * 1024 * 1024)) # 10 МБ
|
||||||
|
|
||||||
|
# ── Параметры экспоненциальной отсрочки ─────────────────────────────────────
|
||||||
|
INITIAL_BACKOFF=10 # Начальная задержка (сек)
|
||||||
|
MAX_BACKOFF=120 # Максимальная задержка (сек)
|
||||||
|
BACKOFF_MULTIPLIER=2 # Множитель
|
||||||
|
STABLE_THRESHOLD=3 # Кол-во успешных проверок для сброса backoff
|
||||||
|
|
||||||
|
# ── Состояние ───────────────────────────────────────────────────────────────
|
||||||
|
consecutive_failures=0
|
||||||
|
consecutive_successes=0
|
||||||
|
current_backoff=$INITIAL_BACKOFF
|
||||||
|
|
||||||
|
# ── Загрузка конфигурации ───────────────────────────────────────────────────
|
||||||
|
load_config() {
|
||||||
|
local config_file="/etc/wireguard-vps-tunnel/config"
|
||||||
|
if [[ -f "$config_file" ]]; then
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$config_file"
|
||||||
|
# Переопределяем из конфига если есть
|
||||||
|
VPS_IP="${VPS_PUBLIC_IP:-$VPS_IP}"
|
||||||
|
VPS_WG_IP="${SERVER_WG_IP:-$VPS_WG_IP}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Логирование ─────────────────────────────────────────────────────────────
|
||||||
|
log() {
|
||||||
|
local level="$1"
|
||||||
|
shift
|
||||||
|
local timestamp
|
||||||
|
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
echo "[$timestamp] [$level] $*" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Ротация лога при превышении размера
|
||||||
|
if [[ -f "$LOG_FILE" ]]; then
|
||||||
|
local size
|
||||||
|
size=$(stat -c%s "$LOG_FILE" 2>/dev/null || stat -f%z "$LOG_FILE" 2>/dev/null || echo 0)
|
||||||
|
if [[ $size -gt $MAX_LOG_SIZE ]]; then
|
||||||
|
mv "$LOG_FILE" "${LOG_FILE}.old"
|
||||||
|
echo "[$timestamp] [INFO] Лог ротирован (превышен лимит ${MAX_LOG_SIZE} байт)" > "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Проверка интерфейса WireGuard ──────────────────────────────────────────
|
||||||
|
check_wg_interface() {
|
||||||
|
if ip link show "$WG_INTERFACE" &>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Проверка доступности VPS через туннель ──────────────────────────────────
|
||||||
|
check_vps_tunnel() {
|
||||||
|
if [[ -z "$VPS_WG_IP" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# 3 пинга, таймаут 2 секунды
|
||||||
|
if ping -c 3 -W 2 "$VPS_WG_IP" &>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Проверка доступности VPS через интернет ─────────────────────────────────
|
||||||
|
check_vps_internet() {
|
||||||
|
if [[ -z "$VPS_IP" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# Проверяем, что интернет вообще работает
|
||||||
|
if ping -c 2 -W 3 "$VPS_IP" &>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Перезапуск WireGuard ────────────────────────────────────────────────────
|
||||||
|
restart_wireguard() {
|
||||||
|
log "WARN" "Перезапуск wg-quick@${WG_INTERFACE}..."
|
||||||
|
systemctl restart "wg-quick@${WG_INTERFACE}" 2>&1 | while read -r line; do
|
||||||
|
log "INFO" "systemctl: $line"
|
||||||
|
done
|
||||||
|
sleep 3
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Сброс backoff после стабильной работы ──────────────────────────────────
|
||||||
|
reset_backoff() {
|
||||||
|
consecutive_failures=0
|
||||||
|
current_backoff=$INITIAL_BACKOFF
|
||||||
|
consecutive_successes=$((consecutive_successes + 1))
|
||||||
|
|
||||||
|
if [[ $consecutive_successes -ge $STABLE_THRESHOLD ]]; then
|
||||||
|
# Логируем только при переходе в стабильное состояние
|
||||||
|
if [[ $consecutive_successes -eq $STABLE_THRESHOLD ]]; then
|
||||||
|
log "INFO" "Туннель стабилен (${STABLE_THRESHOLD} успешных проверок подряд)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Увеличение backoff при сбоях ───────────────────────────────────────────
|
||||||
|
increase_backoff() {
|
||||||
|
consecutive_successes=0
|
||||||
|
consecutive_failures=$((consecutive_failures + 1))
|
||||||
|
current_backoff=$((current_backoff * BACKOFF_MULTIPLIER))
|
||||||
|
if [[ $current_backoff -gt $MAX_BACKOFF ]]; then
|
||||||
|
current_backoff=$MAX_BACKOFF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Основной цикл ──────────────────────────────────────────────────────────
|
||||||
|
main_loop() {
|
||||||
|
log "INFO" "Watchdog запущен. VPS=${VPS_IP}, VPS_WG=${VPS_WG_IP}, интерфейс=${WG_INTERFACE}"
|
||||||
|
log "INFO" "Параметры backoff: начальный=${INITIAL_BACKOFF}с, макс=${MAX_BACKOFF}с, множитель=${BACKOFF_MULTIPLIER}"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
# Проверка 1: интерфейс поднят?
|
||||||
|
if ! check_wg_interface; then
|
||||||
|
log "ERROR" "Интерфейс ${WG_INTERFACE} не найден"
|
||||||
|
increase_backoff
|
||||||
|
log "INFO" "Ожидание ${current_backoff}с перед следующей проверкой..."
|
||||||
|
sleep "$current_backoff"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверка 2: VPS доступен через туннель?
|
||||||
|
if check_vps_tunnel; then
|
||||||
|
reset_backoff
|
||||||
|
sleep 10
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Туннель не работает — проверяем интернет
|
||||||
|
log "WARN" "VPS ${VPS_WG_IP} недоступен через туннель"
|
||||||
|
|
||||||
|
if ! check_vps_internet; then
|
||||||
|
# Интернет тоже не работает — перезапуск не поможет
|
||||||
|
log "WARN" "VPS ${VPS_IP} недоступен через интернет. Возможно, проблемы с сетью."
|
||||||
|
increase_backoff
|
||||||
|
log "INFO" "Ожидание ${current_backoff}с..."
|
||||||
|
sleep "$current_backoff"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Интернет работает, туннель нет — перезапускаем
|
||||||
|
log "ERROR" "Туннель не работает, но VPS доступен через интернет. Перезапуск WireGuard..."
|
||||||
|
restart_wireguard
|
||||||
|
|
||||||
|
# Проверяем после перезапуска
|
||||||
|
sleep 3
|
||||||
|
if check_vps_tunnel; then
|
||||||
|
log "INFO" "Туннель восстановлен после перезапуска"
|
||||||
|
reset_backoff
|
||||||
|
else
|
||||||
|
log "ERROR" "Туннель не восстановился после перезапуска"
|
||||||
|
increase_backoff
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "INFO" "Ожидание ${current_backoff}с перед следующей проверкой..."
|
||||||
|
sleep "$current_backoff"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Точка входа ─────────────────────────────────────────────────────────────
|
||||||
|
load_config
|
||||||
|
|
||||||
|
# Проверяем что IP заданы
|
||||||
|
if [[ -z "$VPS_IP" ]]; then
|
||||||
|
echo "ОШИБКА: VPS_IP не задан. Отредактируйте скрипт или файл конфигурации." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$VPS_WG_IP" ]]; then
|
||||||
|
echo "ОШИБКА: VPS_WG_IP не задан. Отредактируйте скрипт или файл конфигурации." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
main_loop
|
||||||
Reference in New Issue
Block a user