Files
ai-setup/tests/test_network.sh
Виталий Никитенко 398e57c648 fix: kill switch не блокировал не-.ru трафик + Amnezia не могла подключиться
- ru-bypass.sh: добавлен ufw default deny outgoing (раньше нигде не выполнялся)
- ru-bypass.sh: добавлен ufw allow out on amn0 (разрешён трафик через VPN)
- ru-bypass.sh: поддержка AMNEZIA_SERVER — IP добавляется в ipset и маршруты
- ks-on.sh: default deny + allow amn0 при восстановлении kill switch
- setup.sh: меню запрашивает/сохраняет/передаёт AMNEZIA_SERVER
- test_network.sh: DEV читается из конфига вместо жёсткого wl[pi]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 06:51:48 +03:00

119 lines
5.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Тесты сетевой настройки: Amnezia + ru-bypass + kill switch
# Запускать без sudo (проверяет что доступно обычному пользователю)
RED='\033[0;31m'
GRN='\033[0;32m'
YEL='\033[0;33m'
CLR='\033[0m'
pass=0 fail=0
check() {
local desc="$1" expected="$2"
local actual
actual=$(eval "$3" 2>&1)
if echo "$actual" | grep -qE "$expected"; then
echo -e "${GRN}${CLR} $desc"
pass=$((pass+1))
else
echo -e "${RED}${CLR} $desc"
echo " ожидалось: $expected"
echo " получено: $(echo "$actual" | head -3)"
fail=$((fail+1))
fi
}
echo "=== 1. Проверка окружения ==="
check "Amnezia интерфейс (amn0) существует" "amn0" "ip link show amn0 2>/dev/null"
# Определяем DEV из конфига или из default route
if [ -f "$HOME/.config/ai-setup/network_$(hostname).conf" ]; then
source "$HOME/.config/ai-setup/network_$(hostname).conf"
fi
DEV="${DEV:-$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')}"
echo " DEV=$DEV (из конфига)"
IPSET_INFO=$(sudo ipset list ru-direct 2>/dev/null)
if [ -n "$IPSET_INFO" ]; then
echo -e "${GRN}${CLR} ipset ru-direct существует"
IPSET_COUNT=$(echo "$IPSET_INFO" | grep -c '/')
if [ "$IPSET_COUNT" -gt 100 ]; then
echo -e "${GRN}${CLR} ipset не пуст ($IPSET_COUNT блоков)"
else
echo -e "${RED}${CLR} ipset слишком мал ($IPSET_COUNT блоков)"
fi
RU_IP=$(echo "$IPSET_INFO" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1)
else
echo -e "${YEL}?${CLR} ipset — проверь с sudo"
RU_IP=$(dig +short ya.ru A | head -1)
fi
echo ""
echo "=== 2. Маршрутизация .ru vs не-.ru ==="
check ".ru IP ($RU_IP) → НЕ через amn0" "$DEV" "ip route get $RU_IP 2>/dev/null"
check "8.8.8.8 → через amn0" "amn0" "ip route get 8.8.8.8 2>/dev/null"
check "1.1.1.1 → через amn0" "amn0" "ip route get 1.1.1.1 2>/dev/null"
echo ""
echo "=== 3. DNS резолвинг ==="
check "ozon.ru резолвится" "185\.73\." "dig +short ozon.ru A 2>/dev/null"
check "google.com резолвится" "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" "dig +short google.com A 2>/dev/null | head -1"
check "gosuslugi.ru резолвится" "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" "dig +short gosuslugi.ru A 2>/dev/null | head -1"
echo ""
echo "=== 4. Связность (Amnezia вкл) ==="
check "google.com отвечает (VPN)" "HTTP" "curl -sI --max-time 5 https://google.com 2>&1 | head -1"
check "ozon.ru отвечает (прямо)" "HTTP" "curl -sI --max-time 5 https://ozon.ru 2>&1 | head -1"
check "gosuslugi.ru отвечает (прямо)" "HTTP" "curl -sI --max-time 5 https://gosuslugi.ru 2>&1 | head -1"
echo ""
echo "=== 5. Инфраструктура (нужен sudo) ==="
UFW_STATUS=$(sudo ufw status 2>/dev/null)
if echo "$UFW_STATUS" | grep -qE "активен|active"; then
echo -e "${GRN}${CLR} UFW активен"
else
echo -e "${YEL}?${CLR} UFW — запусти с sudo: sudo ufw status"
fi
check "ru-bypass сервис есть" "ru-bypass" "systemctl list-unit-files 2>/dev/null | grep ru-bypass || echo 'OK (проверить с sudo)'"
check "NM dispatcher есть" "99-ru-bypass" "ls -la /etc/NetworkManager/dispatcher.d/99-ru-bypass 2>/dev/null"
echo ""
echo "=== 6. Краевые случаи ==="
check "api.anthropic.com → amn0" "amn0" "ip route get $(dig +short api.anthropic.com A | head -1) 2>/dev/null"
check "ya.ru → НЕ через amn0 (прямо)" "$DEV" "ip route get $(dig +short ya.ru A | head -1) 2>/dev/null"
echo ""
echo "=== 7. Geo: внешние IP ==="
DEV_DIRECT=$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')
ip_vpn=$(curl -s --max-time 10 https://ipinfo.io/ip 2>/dev/null)
ip_direct=$(curl -s --interface "$DEV_DIRECT" --max-time 5 https://ipinfo.io/ip 2>/dev/null)
echo " VPN IP (через amn0): ${ip_vpn:-недоступно}"
if [ -n "$ip_direct" ]; then
echo " Прямой IP (через ${DEV_DIRECT:-?}): $ip_direct"
if [ "$ip_direct" != "$ip_vpn" ]; then
echo -e " ${GRN}${CLR} IP разные — .ru идёт напрямую, остальное через VPN"
pass=$((pass+1))
else
echo -e " ${YEL}!${CLR} IP одинаковые — проверь маршрутизацию"
fail=$((fail+1))
fi
else
# Kill switch блокирует прямой доступ к ipinfo.io (не-.ru IP) — это штатное поведение.
# Вместо этого проверяем что ya.ru маршрутизируется через прямой интерфейс.
ya_ip=$(dig +short ya.ru A 2>/dev/null | head -1)
ya_dev=$(ip route get "$ya_ip" 2>/dev/null | awk '/dev/ {for(i=1;i<=NF;i++) if ($i=="dev") {print $(i+1); exit}}')
echo " Прямой IP: недоступен (UFW kill switch блокирует не-.ru трафик через ${DEV_DIRECT:-?})"
if [ "$ya_dev" = "$DEV_DIRECT" ]; then
echo -e " ${GRN}${CLR} .ru (ya.ru $ya_ip) → $ya_dev (напрямую, не через VPN)"
pass=$((pass+1))
else
echo -e " ${YEL}!${CLR} .ru (ya.ru $ya_ip) → ${ya_dev:-?} (ожидался $DEV_DIRECT)"
fail=$((fail+1))
fi
fi
echo ""
echo "========================================="
echo -e "Итого: ${GRN}$pass пройдено${CLR}, ${RED}$fail провалено${CLR}"
[ "$fail" -eq 0 ] && echo -e "${GRN}ВСЁ ОК${CLR}" || echo -e "${RED}ЕСТЬ ПРОБЛЕМЫ${CLR}"