- Создаёт TUN-туннель через tun2socks до SOCKS5-прокси
- Маршрутизирует трафик клиентов WireGuard и OpenVPN через этот туннель
- Автоматически переключается между прокси при падении
- Возвращается на основной прокси при его восстановлении
- Отправляет алерты на почту при переключениях
🖥️ Системные требования:
Linux (Debian/Ubuntu)
systemd
tun2socks (v3)
curl, iptables, iproute2
Три SOCKS5-прокси (основной + два резервных)
📦 Установка:
1. Скачайте и установите tun2socks::
Код: Выделить всё
wget -O tun2socks.zip https://github.com/xjasonlyu/tun2socks/releases/latest/download/tun2socks-linux-amd64.zipКод: Выделить всё
unzip tun2socks.zipКод: Выделить всё
chmod +x tun2socks-linux-amd64Код: Выделить всё
mv tun2socks-linux-amd64 /usr/sbin/tun2socks-linux-amd64-v32. Создайте основной скрипт:
Код: Выделить всё
#!/usr/bin/env bash
set -uo pipefail
# =============================================
# НАСТРОЙКИ (измените под себя)
# =============================================
TUN_DEV="tun_out"
TUN_IP="10.99.99.1/24"
SOCKS_LIST="/etc/socks-list.txt"
TUN2SOCKS="/usr/sbin/tun2socks-linux-amd64-v3"
LOGFILE="/var/log/tun2socks-routing.log"
PIDFILE="/var/run/tun2socks-failover.pid"
TUN2SOCKS_PIDFILE="/var/run/tun2socks-process.pid"
MAIL_TO="admin@padonak.su" # Куда слать алерты
# Основной прокси (на него возвращаемся при восстановлении)
PRIMARY_PROXY="socks5://vps.padonak.su:3334"
# Подсети клиентов VPN
CLIENT_SUBNETS=(
"10.8.0.0/24" # OpenVPN
"10.11.12.0/24" # WireGuard
)
# Настройки мониторинга
HEALTHCHECK_URL="http://1.1.1.1"
HEALTHCHECK_INTERVAL=30 # Интервал проверки (сек)
HEALTHCHECK_TIMEOUT=5 # Таймаут проверки (сек)
HEALTHCHECK_RETRIES=2 # Провалов до переключения
PRIMARY_CHECK_INTERVAL=60 # Проверка основного прокси (сек)
LOG_TAG="[tun2socks]"
# =============================================
# ФУНКЦИИ
# =============================================
log() {
local msg="$*"
local line="$(date '+%Y-%m-%d %H:%M:%S') ${LOG_TAG} ${msg}"
echo "$line"
echo "$line" >> "$LOGFILE"
}
send_alert() {
local subject="$1"
local body="$2"
if command -v mail >/dev/null 2>&1; then
echo -e "$body" | mail -s "$subject" "$MAIL_TO" 2>/dev/null || true
fi
}
cleanup() {
log "Очистка..."
if [[ -f "$TUN2SOCKS_PIDFILE" ]]; then
local pid=$(cat "$TUN2SOCKS_PIDFILE" 2>/dev/null)
[[ -n "$pid" ]] && kill "$pid" 2>/dev/null || true
rm -f "$TUN2SOCKS_PIDFILE"
fi
pkill -f "tun2socks.*${TUN_DEV}" 2>/dev/null || true
sleep 1
# Удаляем правила SNAT
local snat_ip="${TUN_IP%/*}"
for subnet in "${CLIENT_SUBNETS[@]}"; do
ip rule del from "$subnet" lookup client_socks_table 2>/dev/null || true
iptables -t nat -D POSTROUTING -s "$subnet" -o "$TUN_DEV" -j SNAT --to-source "$snat_ip" 2>/dev/null || true
done
ip route flush table client_socks_table 2>/dev/null || true
iptables -D FORWARD -i "$TUN_DEV" -j ACCEPT 2>/dev/null || true
iptables -D FORWARD -o "$TUN_DEV" -j ACCEPT 2>/dev/null || true
if ip link show "$TUN_DEV" &>/dev/null; then
ip link set dev "$TUN_DEV" down 2>/dev/null || true
ip tuntap del mode tun dev "$TUN_DEV" 2>/dev/null || true
fi
rm -f "$PIDFILE"
log "Очистка завершена"
}
trap cleanup EXIT SIGINT SIGTERM
echo $$ > "$PIDFILE"
load_proxy_list() {
if [[ ! -f "$SOCKS_LIST" ]]; then
log "Ошибка: ${SOCKS_LIST} не найден"
exit 1
fi
mapfile -t PROXY_LIST < <(grep -v '^#' "$SOCKS_LIST" | grep -v '^$' | tr -d '\r')
if [[ ${#PROXY_LIST[@]} -eq 0 ]]; then
log "Ошибка: список прокси пуст"
exit 1
fi
log "Прокси загружено: ${#PROXY_LIST[@]}"
}
setup_network() {
log "Настройка сети..."
if ! ip link show "$TUN_DEV" &>/dev/null; then
ip tuntap add mode tun dev "$TUN_DEV"
fi
ip addr add "$TUN_IP" dev "$TUN_DEV" 2>/dev/null || true
ip link set dev "$TUN_DEV" mtu 1400 up
log "Интерфейс ${TUN_DEV} поднят (IP: ${TUN_IP}, MTU: 1400)"
ip route flush table client_socks_table 2>/dev/null || true
ip route add default dev "$TUN_DEV" table client_socks_table
local prio=100
for subnet in "${CLIENT_SUBNETS[@]}"; do
ip rule del from "$subnet" lookup client_socks_table 2>/dev/null || true
ip rule add from "$subnet" priority "$prio" lookup client_socks_table
((prio++))
done
# Используем SNAT вместо MASQUERADE (быстрее)
local snat_ip="${TUN_IP%/*}"
for subnet in "${CLIENT_SUBNETS[@]}"; do
if ! iptables -t nat -C POSTROUTING -s "$subnet" -o "$TUN_DEV" -j SNAT --to-source "$snat_ip" 2>/dev/null; then
iptables -t nat -A POSTROUTING -s "$subnet" -o "$TUN_DEV" -j SNAT --to-source "$snat_ip"
log "SNAT: ${subnet} -> ${snat_ip}"
fi
done
iptables -C FORWARD -i "$TUN_DEV" -j ACCEPT 2>/dev/null || iptables -A FORWARD -i "$TUN_DEV" -j ACCEPT
iptables -C FORWARD -o "$TUN_DEV" -j ACCEPT 2>/dev/null || iptables -A FORWARD -o "$TUN_DEV" -j ACCEPT
log "Сеть настроена"
}
start_tun2socks() {
local proxy="$1"
log "Запуск: ${proxy}"
pkill -f "tun2socks.*${TUN_DEV}" 2>/dev/null || true
sleep 1
$TUN2SOCKS \
--device "tun://${TUN_DEV}" \
--proxy "$proxy" \
--loglevel warn \
&>> "$LOGFILE" &
local pid=$!
echo "$pid" > "$TUN2SOCKS_PIDFILE"
sleep 3
if kill -0 "$pid" 2>/dev/null; then
log "tun2socks PID: ${pid}"
return 0
else
log "Ошибка запуска"
return 1
fi
}
check_health() {
local proxy="$1"
# Проверка напрямую через прокси
if curl --socks5-hostname "$proxy" --max-time "$HEALTHCHECK_TIMEOUT" -s -o /dev/null "$HEALTHCHECK_URL" 2>/dev/null; then
return 0
fi
# Запасной вариант — через TUN
if curl --interface "$TUN_DEV" --max-time "$HEALTHCHECK_TIMEOUT" -s -o /dev/null "$HEALTHCHECK_URL" 2>/dev/null; then
return 0
fi
return 1
}
# Проверка доступности основного прокси (напрямую, без TUN)
check_primary() {
if curl --socks5-hostname "$PRIMARY_PROXY" --max-time "$HEALTHCHECK_TIMEOUT" -s -o /dev/null "$HEALTHCHECK_URL" 2>/dev/null; then
return 0
fi
return 1
}
# Переключение на указанный прокси
switch_to_proxy() {
local proxy="$1"
local reason="$2"
log "Переключение на ${proxy} (${reason})..."
send_alert "tun2socks: переключение на ${proxy}" \
"Причина: ${reason}\nПереключаемся на ${proxy}"
pkill -f "tun2socks.*${TUN_DEV}" 2>/dev/null || true
sleep 1
if start_tun2socks "$proxy"; then
return 0
fi
return 1
}
# =============================================
# ГЛАВНЫЙ ЦИКЛ
# =============================================
main() {
log "=== СТАРТ ==="
load_proxy_list
setup_network
local current_proxy=""
local failures=0
local primary_check_counter=0
# Начинаем с основного прокси если он доступен
if check_primary; then
log "Основной прокси ${PRIMARY_PROXY} доступен, начинаем с него"
if start_tun2socks "$PRIMARY_PROXY"; then
current_proxy="$PRIMARY_PROXY"
fi
fi
while true; do
# Если нет текущего прокси — перебор списка
if [[ -z "$current_proxy" ]]; then
for proxy in "${PROXY_LIST[@]}"; do
log "Пробуем: ${proxy}"
if start_tun2socks "$proxy"; then
current_proxy="$proxy"
failures=0
break
fi
done
if [[ -z "$current_proxy" ]]; then
log "Все прокси недоступны. Пауза 30с..."
send_alert "tun2socks: все прокси недоступны" \
"Все прокси перебраны. Пауза 30с."
sleep 30
continue
fi
fi
# Мониторинг текущего прокси
while [[ -n "$current_proxy" ]]; do
sleep "$HEALTHCHECK_INTERVAL"
((primary_check_counter += HEALTHCHECK_INTERVAL))
# Периодическая проверка основного прокси
if [[ $primary_check_counter -ge $PRIMARY_CHECK_INTERVAL ]]; then
primary_check_counter=0
# Если мы не на основном — проверяем, не восстановился ли он
if [[ "$current_proxy" != "$PRIMARY_PROXY" ]]; then
if check_primary; then
log "Основной прокси ${PRIMARY_PROXY} снова доступен!"
switch_to_proxy "$PRIMARY_PROXY" "основной прокси восстановился"
current_proxy="$PRIMARY_PROXY"
failures=0
continue
fi
fi
fi
# Healthcheck текущего прокси
if ! check_health "$current_proxy"; then
((failures++))
log "Healthcheck FAIL (${failures}/${HEALTHCHECK_RETRIES}) для ${current_proxy}"
if [[ $failures -ge $HEALTHCHECK_RETRIES ]]; then
log "Прокси ${current_proxy} не отвечает, переключаем..."
send_alert "tun2socks: прокси недоступен" \
"Прокси ${current_proxy} не отвечает (${failures} провалов)"
pkill -f "tun2socks.*${TUN_DEV}" 2>/dev/null || true
sleep 1
current_proxy=""
failures=0
break
fi
else
[[ $failures -gt 0 ]] && log "Healthcheck восстановлен для ${current_proxy}"
failures=0
fi
done
done
}
main
Код: Выделить всё
chmod +x /usr/local/bin/tun2socks-failover.shКод: Выделить всё
vim /usr/local/bin/tun2socks-failover-cleanup.shКод: Выделить всё
#!/usr/bin/env bash
TUN_DEV="tun_out"
CLIENT_SUBNETS=("10.8.0.0/24" "10.11.12.0/24")
pkill -9 -f "tun2socks.*${TUN_DEV}" 2>/dev/null || true
sleep 1
for subnet in "${CLIENT_SUBNETS[@]}"; do
ip rule del from "$subnet" lookup client_socks_table 2>/dev/null || true
iptables -t nat -D POSTROUTING -s "$subnet" -o "$TUN_DEV" -j MASQUERADE 2>/dev/null || true
done
ip route flush table client_socks_table 2>/dev/null || true
iptables -D FORWARD -i "$TUN_DEV" -j ACCEPT 2>/dev/null || true
iptables -D FORWARD -o "$TUN_DEV" -j ACCEPT 2>/dev/null || true
ip link set dev "$TUN_DEV" down 2>/dev/null || true
ip tuntap del mode tun dev "$TUN_DEV" 2>/dev/null || true
rm -f /var/run/tun2socks-failover.pid /var/run/tun2socks-process.pid
echo "Очистка завершена"
Код: Выделить всё
chmod +x /usr/local/bin/tun2socks-failover-cleanup.sh
Код: Выделить всё
vim /etc/socks-list.txtКод: Выделить всё
socks5://1.padonak.su:333
socks5://2.padonak.su:333
socks5://3.padonak.su:333Код: Выделить всё
vim /etc/systemd/system/tun2socks-failover.serviceКод: Выделить всё
[Unit]
Description=tun2socks with automatic failover and alerting
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/tun2socks-failover.sh
ExecStop=/bin/bash -c 'pkill -9 -f tun2socks; sleep 1'
ExecStopPost=/usr/local/bin/tun2socks-failover-cleanup.sh
Restart=always
RestartSec=10s
StandardOutput=journal
StandardError=journal
LimitNOFILE=65536
KillMode=mixed
TimeoutStopSec=15
[Install]
WantedBy=multi-user.targetКод: Выделить всё
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -pКод: Выделить всё
systemctl daemon-reload
systemctl enable tun2socks-failover
systemctl start tun2socks-failover
systemctl status tun2socks-failoverКод: Выделить всё
# Статус сервиса
systemctl status tun2socks-failover
# Процессы
ps aux | grep tun2socks
# Логи
tail -f /var/log/tun2socks-routing.log
# Тест скорости через прокси
curl --socks5-hostname socks5://1.padonak.su:3334 \
-o /dev/null -w "Speed: %{speed_download} B/s\n" \
http://ipv4.download.thinkbroadband.com/10MB.zipВ скрипте измените:
Переменная Значение
- PRIMARY_PROXY Основной прокси
- CLIENT_SUBNETS Подсети ваших VPN
- MAIL_TO Почта для алертов
- HEALTHCHECK_INTERVAL Частота проверки
- HEALTHCHECK_RETRIES Провалов до переключения
📊 Оптимизация прокси-серверов:
Код: Выделить всё
cat >> /etc/sysctl.conf << 'EOF'
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
EOF
sysctl -p