- Dockerfile с multi-stage сборкой для linux/amd64 и linux/arm64 - Gitea Actions CI/CD для автоматической сборки и пуша в registry - docker-compose с поддержкой multi-arch образов - install.sh с автоопределением архитектуры и выбором: pull vs build - uninstall.sh обновлён для Docker-деинсталляции - README.md обновлён: multi-arch, CI/CD, Gitea registry
151 lines
6.8 KiB
Bash
151 lines
6.8 KiB
Bash
#!/usr/bin/env bash
|
||
# =============================================================================
|
||
# WireGuard Watchdog — оптимизирован для Starlink
|
||
# Мониторит состояние туннеля и перезапускает при обрыве связи.
|
||
# Использует экспоненциальную отсрочку (backoff) при повторных сбоях.
|
||
# Запускается внутри Docker-контейнера клиента.
|
||
# =============================================================================
|
||
set -euo pipefail
|
||
|
||
# ── Настройки ───────────────────────────────────────────────────────────────
|
||
VPS_PUBLIC_IP="${VPS_PUBLIC_IP:-}"
|
||
SERVER_WG_IP="${SERVER_WG_IP:-10.0.0.1}"
|
||
WG_INTERFACE="wg0"
|
||
|
||
# ── Параметры экспоненциальной отсрочки ─────────────────────────────────────
|
||
INITIAL_BACKOFF=10
|
||
MAX_BACKOFF=120
|
||
BACKOFF_MULTIPLIER=2
|
||
STABLE_THRESHOLD=3
|
||
|
||
# ── Состояние ───────────────────────────────────────────────────────────────
|
||
consecutive_failures=0
|
||
consecutive_successes=0
|
||
current_backoff=$INITIAL_BACKOFF
|
||
|
||
# ── Логирование ─────────────────────────────────────────────────────────────
|
||
log() {
|
||
local level="$1"
|
||
shift
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*"
|
||
}
|
||
|
||
# ── Проверка интерфейса WireGuard ──────────────────────────────────────────
|
||
check_wg_interface() {
|
||
if ip link show "$WG_INTERFACE" &>/dev/null; then
|
||
return 0
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
# ── Проверка доступности VPS через туннель ──────────────────────────────────
|
||
check_vps_tunnel() {
|
||
if [[ -z "$SERVER_WG_IP" ]]; then
|
||
return 1
|
||
fi
|
||
if ping -c 3 -W 2 "$SERVER_WG_IP" &>/dev/null; then
|
||
return 0
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
# ── Проверка доступности VPS через интернет ─────────────────────────────────
|
||
check_vps_internet() {
|
||
if [[ -z "$VPS_PUBLIC_IP" ]]; then
|
||
return 1
|
||
fi
|
||
if ping -c 2 -W 3 "$VPS_PUBLIC_IP" &>/dev/null; then
|
||
return 0
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
# ── Перезапуск WireGuard ────────────────────────────────────────────────────
|
||
restart_wireguard() {
|
||
log "WARN" "Перезапуск wg-quick@${WG_INTERFACE}..."
|
||
wg-quick down "$WG_INTERFACE" 2>/dev/null || true
|
||
sleep 2
|
||
wg-quick up "$WG_INTERFACE"
|
||
sleep 3
|
||
}
|
||
|
||
# ── Сброс backoff после стабильной работы ──────────────────────────────────
|
||
reset_backoff() {
|
||
consecutive_failures=0
|
||
current_backoff=$INITIAL_BACKOFF
|
||
consecutive_successes=$((consecutive_successes + 1))
|
||
|
||
if [[ $consecutive_successes -eq $STABLE_THRESHOLD ]]; then
|
||
log "INFO" "Туннель стабилен (${STABLE_THRESHOLD} успешных проверок подряд)"
|
||
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_PUBLIC_IP}, VPS_WG=${SERVER_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 ${SERVER_WG_IP} недоступен через туннель"
|
||
|
||
if ! check_vps_internet; then
|
||
log "WARN" "VPS ${VPS_PUBLIC_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
|
||
}
|
||
|
||
# ── Точка входа ─────────────────────────────────────────────────────────────
|
||
if [[ -z "$VPS_PUBLIC_IP" ]]; then
|
||
log "ERROR" "VPS_PUBLIC_IP не задан. Watchdog не может работать."
|
||
exit 1
|
||
fi
|
||
|
||
main_loop
|