fix: probe v1.1 — critical fixes + new services
This commit is contained in:
402
probe.sh
402
probe.sh
@@ -1,9 +1,9 @@
|
|||||||
#!/data/data/com.termux/files/usr/bin/bash
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
# WHITELIST PROBE v1.0
|
# WHITELIST PROBE v1.1
|
||||||
# Определяет доступные методы обхода whitelist
|
# Определяет доступные методы обхода whitelist
|
||||||
# Платформа: Termux (Android) / Linux
|
# Платформа: Termux (Android) / Linux
|
||||||
# Зависимости: curl, nc (ncat), openssl, nslookup
|
# Зависимости: curl, nc (ncat), openssl, dig/nslookup
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
|
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
@@ -13,10 +13,9 @@ VPS_IP="194.87.245.138" # Ирландия (exit node)
|
|||||||
MOSCOW_IP="94.141.253.12" # Москва (relay)
|
MOSCOW_IP="94.141.253.12" # Москва (relay)
|
||||||
DNSTT_DOMAIN="t.chatsquad.ru"
|
DNSTT_DOMAIN="t.chatsquad.ru"
|
||||||
DNSTT_NS="ns-t.chatsquad.ru"
|
DNSTT_NS="ns-t.chatsquad.ru"
|
||||||
TIMEOUT=3 # секунд на каждый тест
|
TIMEOUT=5 # секунд на каждый тест
|
||||||
RESULT_DIR="./results"
|
RESULT_DIR="./results"
|
||||||
TIMESTAMP=$(date '+%Y-%m-%d_%H-%M-%S')
|
TIMESTAMP=$(date '+%Y-%m-%d_%H-%M-%S')
|
||||||
RESULT_FILE="${RESULT_DIR}/probe_${TIMESTAMP}.txt"
|
|
||||||
JSON_FILE="${RESULT_DIR}/probe_${TIMESTAMP}.json"
|
JSON_FILE="${RESULT_DIR}/probe_${TIMESTAMP}.json"
|
||||||
|
|
||||||
# ── Цвета ─────────────────────────────────────────────
|
# ── Цвета ─────────────────────────────────────────────
|
||||||
@@ -26,9 +25,10 @@ if [ -t 1 ]; then
|
|||||||
Y='\033[0;33m' # yellow
|
Y='\033[0;33m' # yellow
|
||||||
C='\033[0;36m' # cyan
|
C='\033[0;36m' # cyan
|
||||||
B='\033[1m' # bold
|
B='\033[1m' # bold
|
||||||
|
W='\033[0;37m' # white/dim
|
||||||
N='\033[0m' # reset
|
N='\033[0m' # reset
|
||||||
else
|
else
|
||||||
G='' R='' Y='' C='' B='' N=''
|
G='' R='' Y='' C='' B='' W='' N=''
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Счётчики ──────────────────────────────────────────
|
# ── Счётчики ──────────────────────────────────────────
|
||||||
@@ -36,19 +36,24 @@ declare -A RESULTS
|
|||||||
TOTAL=0
|
TOTAL=0
|
||||||
PASS=0
|
PASS=0
|
||||||
FAIL=0
|
FAIL=0
|
||||||
|
SKIP=0
|
||||||
|
|
||||||
|
# Список SNI, по которым обнаружена фильтрация
|
||||||
|
declare -a FILTERED_SNIS=()
|
||||||
|
|
||||||
# ── Утилиты ───────────────────────────────────────────
|
# ── Утилиты ───────────────────────────────────────────
|
||||||
ok() { echo -e " ${G}✓${N} $1"; RESULTS["$2"]="ok"; ((PASS++)); ((TOTAL++)); }
|
ok() { echo -e " ${G}✓${N} $1"; RESULTS["$2"]="ok"; ((PASS++)); ((TOTAL++)); }
|
||||||
fail() { echo -e " ${R}✗${N} $1"; RESULTS["$2"]="fail"; ((FAIL++)); ((TOTAL++)); }
|
fail() { echo -e " ${R}✗${N} $1"; RESULTS["$2"]="fail"; ((FAIL++)); ((TOTAL++)); }
|
||||||
skip() { echo -e " ${Y}—${N} $1"; RESULTS["$2"]="skip"; ((TOTAL++)); }
|
warn() { echo -e " ${Y}▲${N} $1"; RESULTS["$2"]="warn"; ((TOTAL++)); }
|
||||||
|
skip() { echo -e " ${Y}—${N} $1"; RESULTS["$2"]="skip"; ((SKIP++)); ((TOTAL++)); }
|
||||||
info() { echo -e " ${C}ℹ${N} $1"; }
|
info() { echo -e " ${C}ℹ${N} $1"; }
|
||||||
hdr() { echo -e "\n${B}[$1]${N}"; }
|
hdr() { echo -e "\n${B}[$1]${N}"; }
|
||||||
|
|
||||||
# Ping с таймаутом
|
# Ping с таймаутом (2 попытки, успех если хотя бы одна прошла)
|
||||||
do_ping() {
|
do_ping() {
|
||||||
local host=$1
|
local host=$1
|
||||||
local result
|
local result
|
||||||
result=$(ping -c 1 -W $TIMEOUT "$host" 2>/dev/null | grep -oP 'time=\K[0-9.]+')
|
result=$(ping -c 2 -W $TIMEOUT "$host" 2>/dev/null | grep -oP 'time=\K[0-9.]+' | tail -1)
|
||||||
if [ -n "$result" ]; then
|
if [ -n "$result" ]; then
|
||||||
echo "${result}ms"
|
echo "${result}ms"
|
||||||
return 0
|
return 0
|
||||||
@@ -63,35 +68,55 @@ do_tcp() {
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# UDP test (отправить пакет, ждать ответ)
|
# UDP — отправка WireGuard handshake initiation (тип 1)
|
||||||
do_udp() {
|
# WG отвечает cookie reply на невалидный handshake, что позволяет
|
||||||
|
# подтвердить прохождение UDP-пакетов
|
||||||
|
do_udp_wg() {
|
||||||
local host=$1 port=$2
|
local host=$1 port=$2
|
||||||
echo -n "test" | timeout $TIMEOUT nc -u -w $TIMEOUT "$host" "$port" 2>/dev/null
|
# WG handshake initiation: type=1(LE32), sender=0x12345678, rest zeros (148 байт)
|
||||||
# UDP "успех" если nc не вернул ошибку (не гарантирует доставку)
|
# Генерируем бинарный пакет через printf напрямую в pipe (без переменных — bash не хранит \x00)
|
||||||
|
{
|
||||||
|
printf '\x01\x00\x00\x00\x78\x56\x34\x12'
|
||||||
|
dd if=/dev/zero bs=1 count=140 2>/dev/null
|
||||||
|
} | timeout $TIMEOUT nc -u -w 2 "$host" "$port" 2>/dev/null | head -c 1 | grep -qP '.' 2>/dev/null
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTPS test
|
# HTTPS test — один запрос, возвращает "код HTTP/версия"
|
||||||
do_https() {
|
do_https() {
|
||||||
local host=$1
|
local host=$1
|
||||||
local code
|
local raw
|
||||||
code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) "https://$host" 2>/dev/null)
|
raw=$(curl -s -o /dev/null -w '%{http_code} %{http_version}' \
|
||||||
|
--connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) \
|
||||||
|
"https://$host" 2>/dev/null)
|
||||||
|
local code="${raw%% *}"
|
||||||
|
local ver="${raw##* }"
|
||||||
if [ "$code" -ge 100 ] 2>/dev/null && [ "$code" -lt 600 ] 2>/dev/null; then
|
if [ "$code" -ge 100 ] 2>/dev/null && [ "$code" -lt 600 ] 2>/dev/null; then
|
||||||
echo "$code"
|
echo "$code HTTP/$ver"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# DNS resolve
|
# DNS resolve — предпочитает dig, фолбэк на nslookup
|
||||||
do_resolve() {
|
do_resolve() {
|
||||||
local domain=$1 server=$2
|
local domain=$1 server=$2
|
||||||
local result
|
local result
|
||||||
|
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
if [ -n "$server" ]; then
|
if [ -n "$server" ]; then
|
||||||
result=$(nslookup "$domain" "$server" 2>/dev/null | grep -A1 "Name:" | grep "Address:" | head -1 | awk '{print $2}')
|
result=$(dig +short +time=$TIMEOUT +tries=1 "$domain" A "@$server" 2>/dev/null | grep -oP '^[0-9.]+' | head -1)
|
||||||
else
|
else
|
||||||
result=$(nslookup "$domain" 2>/dev/null | grep -A1 "Name:" | grep "Address:" | head -1 | awk '{print $2}')
|
result=$(dig +short +time=$TIMEOUT +tries=1 "$domain" A 2>/dev/null | grep -oP '^[0-9.]+' | head -1)
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
if [ -n "$server" ]; then
|
||||||
|
result=$(nslookup "$domain" "$server" 2>/dev/null | awk '/^Address:/{a=$2} /Name:/{found=1} found && /Address:/{print $2; exit}')
|
||||||
|
else
|
||||||
|
result=$(nslookup "$domain" 2>/dev/null | awk '/^Address:/{a=$2} /Name:/{found=1} found && /Address:/{print $2; exit}')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$result" ]; then
|
if [ -n "$result" ]; then
|
||||||
echo "$result"
|
echo "$result"
|
||||||
return 0
|
return 0
|
||||||
@@ -106,16 +131,6 @@ do_tls_sni() {
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP/2 check
|
|
||||||
do_h2() {
|
|
||||||
local host=$1
|
|
||||||
local proto
|
|
||||||
proto=$(curl -s -o /dev/null -w '%{http_version}' --connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) "https://$host" 2>/dev/null)
|
|
||||||
echo "$proto"
|
|
||||||
[ "$proto" = "2" ] && return 0
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
# УСТАНОВКА ЗАВИСИМОСТЕЙ
|
# УСТАНОВКА ЗАВИСИМОСТЕЙ
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
@@ -124,9 +139,13 @@ install_deps() {
|
|||||||
command -v curl >/dev/null || missing+=(curl)
|
command -v curl >/dev/null || missing+=(curl)
|
||||||
command -v nc >/dev/null || missing+=(nmap)
|
command -v nc >/dev/null || missing+=(nmap)
|
||||||
command -v openssl >/dev/null || missing+=(openssl-tool)
|
command -v openssl >/dev/null || missing+=(openssl-tool)
|
||||||
command -v nslookup >/dev/null || { command -v host >/dev/null || missing+=(dnsutils); }
|
|
||||||
command -v ping >/dev/null || missing+=(inetutils)
|
command -v ping >/dev/null || missing+=(inetutils)
|
||||||
|
|
||||||
|
# dig предпочтителен, но nslookup тоже подойдёт
|
||||||
|
if ! command -v dig >/dev/null 2>&1; then
|
||||||
|
command -v nslookup >/dev/null || missing+=(dnsutils)
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ${#missing[@]} -gt 0 ]; then
|
if [ ${#missing[@]} -gt 0 ]; then
|
||||||
echo -e "${Y}Установка: ${missing[*]}${N}"
|
echo -e "${Y}Установка: ${missing[*]}${N}"
|
||||||
if command -v pkg >/dev/null; then
|
if command -v pkg >/dev/null; then
|
||||||
@@ -177,6 +196,7 @@ test_provider() {
|
|||||||
|
|
||||||
test_icmp() {
|
test_icmp() {
|
||||||
hdr "ICMP (Ping)"
|
hdr "ICMP (Ping)"
|
||||||
|
info "2 попытки на хост, таймаут ${TIMEOUT}с"
|
||||||
|
|
||||||
local -A targets=(
|
local -A targets=(
|
||||||
["VPS Ирландия"]="$VPS_IP"
|
["VPS Ирландия"]="$VPS_IP"
|
||||||
@@ -212,7 +232,6 @@ test_icmp() {
|
|||||||
test_dns() {
|
test_dns() {
|
||||||
hdr "DNS RESOLUTION"
|
hdr "DNS RESOLUTION"
|
||||||
|
|
||||||
# Системный DNS
|
|
||||||
local r
|
local r
|
||||||
r=$(do_resolve "yandex.ru")
|
r=$(do_resolve "yandex.ru")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
@@ -221,7 +240,6 @@ test_dns() {
|
|||||||
fail "System DNS yandex.ru" "dns_system"
|
fail "System DNS yandex.ru" "dns_system"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Через разные DNS-серверы
|
|
||||||
local -A dns_servers=(
|
local -A dns_servers=(
|
||||||
["Yandex 77.88.8.8"]="77.88.8.8"
|
["Yandex 77.88.8.8"]="77.88.8.8"
|
||||||
["Yandex 77.88.8.1"]="77.88.8.1"
|
["Yandex 77.88.8.1"]="77.88.8.1"
|
||||||
@@ -243,15 +261,17 @@ test_dns() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# DNSTT домен
|
|
||||||
echo ""
|
echo ""
|
||||||
r=$(do_resolve "$DNSTT_DOMAIN")
|
r=$(do_resolve "$DNSTT_DOMAIN")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
ok "DNSTT domain $DNSTT_DOMAIN → $r" "dns_dnstt"
|
ok "DNSTT domain $DNSTT_DOMAIN → $r" "dns_dnstt"
|
||||||
else
|
else
|
||||||
# Попробуем NS запись
|
|
||||||
local ns_result
|
local ns_result
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
ns_result=$(dig +short +time=$TIMEOUT NS "$DNSTT_DOMAIN" 2>/dev/null)
|
||||||
|
else
|
||||||
ns_result=$(nslookup -type=NS "$DNSTT_DOMAIN" 2>/dev/null | grep -i "nameserver" | head -1)
|
ns_result=$(nslookup -type=NS "$DNSTT_DOMAIN" 2>/dev/null | grep -i "nameserver" | head -1)
|
||||||
|
fi
|
||||||
if [ -n "$ns_result" ]; then
|
if [ -n "$ns_result" ]; then
|
||||||
ok "DNSTT domain (NS) $DNSTT_DOMAIN → delegated" "dns_dnstt"
|
ok "DNSTT domain (NS) $DNSTT_DOMAIN → delegated" "dns_dnstt"
|
||||||
else
|
else
|
||||||
@@ -270,8 +290,8 @@ test_dns() {
|
|||||||
test_dns_tunnel() {
|
test_dns_tunnel() {
|
||||||
hdr "DNS TUNNEL VIABILITY"
|
hdr "DNS TUNNEL VIABILITY"
|
||||||
|
|
||||||
# DoH (DNS over HTTPS) — через Яндекс
|
|
||||||
local r
|
local r
|
||||||
|
# DoH Яндекс
|
||||||
r=$(curl -s --connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) \
|
r=$(curl -s --connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) \
|
||||||
-H 'Accept: application/dns-json' \
|
-H 'Accept: application/dns-json' \
|
||||||
"https://dns.yandex.net/dns-query?name=example.com&type=A" 2>/dev/null)
|
"https://dns.yandex.net/dns-query?name=example.com&type=A" 2>/dev/null)
|
||||||
@@ -318,7 +338,9 @@ test_tcp_our_servers() {
|
|||||||
|
|
||||||
local -A ports=(
|
local -A ports=(
|
||||||
["VPS:443 (VLESS)"]="$VPS_IP:443"
|
["VPS:443 (VLESS)"]="$VPS_IP:443"
|
||||||
|
["VPS:553 (OVPNCloak)"]="$VPS_IP:553"
|
||||||
["VPS:38246 (SS)"]="$VPS_IP:38246"
|
["VPS:38246 (SS)"]="$VPS_IP:38246"
|
||||||
|
["VPS:43781 (SOCKS5)"]="$VPS_IP:43781"
|
||||||
["VPS:8443 (Chisel)"]="$VPS_IP:8443"
|
["VPS:8443 (Chisel)"]="$VPS_IP:8443"
|
||||||
["VPS:22 (SSH)"]="$VPS_IP:22"
|
["VPS:22 (SSH)"]="$VPS_IP:22"
|
||||||
["VPS:53 (DNS)"]="$VPS_IP:53"
|
["VPS:53 (DNS)"]="$VPS_IP:53"
|
||||||
@@ -327,7 +349,18 @@ test_tcp_our_servers() {
|
|||||||
["Moscow:22 (SSH)"]="$MOSCOW_IP:22"
|
["Moscow:22 (SSH)"]="$MOSCOW_IP:22"
|
||||||
)
|
)
|
||||||
|
|
||||||
local order=("VPS:443 (VLESS)" "VPS:38246 (SS)" "VPS:8443 (Chisel)" "VPS:22 (SSH)" "VPS:53 (DNS)" "Moscow:2053 (relay)" "Moscow:443 (HTTPS)" "Moscow:22 (SSH)")
|
local order=(
|
||||||
|
"VPS:443 (VLESS)"
|
||||||
|
"VPS:553 (OVPNCloak)"
|
||||||
|
"VPS:38246 (SS)"
|
||||||
|
"VPS:43781 (SOCKS5)"
|
||||||
|
"VPS:8443 (Chisel)"
|
||||||
|
"VPS:22 (SSH)"
|
||||||
|
"VPS:53 (DNS)"
|
||||||
|
"Moscow:2053 (relay)"
|
||||||
|
"Moscow:443 (HTTPS)"
|
||||||
|
"Moscow:22 (SSH)"
|
||||||
|
)
|
||||||
|
|
||||||
for name in "${order[@]}"; do
|
for name in "${order[@]}"; do
|
||||||
local hp="${ports[$name]}"
|
local hp="${ports[$name]}"
|
||||||
@@ -344,35 +377,51 @@ test_tcp_our_servers() {
|
|||||||
test_udp() {
|
test_udp() {
|
||||||
hdr "UDP"
|
hdr "UDP"
|
||||||
|
|
||||||
local -A targets=(
|
# DNS (порт 53) — реальный DNS-запрос
|
||||||
["VPS:53 (DNSTT)"]="$VPS_IP:53"
|
info "DNS-запрос к VPS:53"
|
||||||
["VPS:443 (QUIC)"]="$VPS_IP:443"
|
|
||||||
["VPS:43742 (WG)"]="$VPS_IP:43742"
|
|
||||||
["VPS:47426 (AWG)"]="$VPS_IP:47426"
|
|
||||||
["VPS:48253 (AWG2)"]="$VPS_IP:48253"
|
|
||||||
)
|
|
||||||
|
|
||||||
local order=("VPS:53 (DNSTT)" "VPS:443 (QUIC)" "VPS:43742 (WG)" "VPS:47426 (AWG)" "VPS:48253 (AWG2)")
|
|
||||||
|
|
||||||
info "UDP-тесты ненадёжны без ответа сервера"
|
|
||||||
for name in "${order[@]}"; do
|
|
||||||
local hp="${targets[$name]}"
|
|
||||||
local host="${hp%%:*}"
|
|
||||||
local port="${hp##*:}"
|
|
||||||
# Для DNS порта — отправляем реальный DNS запрос
|
|
||||||
if [ "$port" = "53" ]; then
|
|
||||||
local dns_r
|
local dns_r
|
||||||
dns_r=$(do_resolve "yandex.ru" "$host")
|
dns_r=$(do_resolve "yandex.ru" "$VPS_IP")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
ok "$(printf '%-25s (DNS ответил: %s)' "$name" "$dns_r")" "udp_$name"
|
ok "$(printf '%-25s (DNS ответил: %s)' "VPS:53 (DNSTT)" "$dns_r")" "udp_VPS:53 (DNSTT)"
|
||||||
else
|
else
|
||||||
fail "$(printf '%-25s' "$name")" "udp_$name"
|
fail "$(printf '%-25s' "VPS:53 (DNSTT)")" "udp_VPS:53 (DNSTT)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# QUIC (порт 443) — через curl --http3 если поддерживается
|
||||||
|
info "QUIC к VPS:443"
|
||||||
|
local quic_ver
|
||||||
|
quic_ver=$(curl -s -o /dev/null -w '%{http_version}' \
|
||||||
|
--connect-timeout $TIMEOUT --max-time $((TIMEOUT+2)) \
|
||||||
|
--http3-only "https://$VPS_IP" 2>/dev/null)
|
||||||
|
if [ "$quic_ver" = "3" ]; then
|
||||||
|
ok "$(printf '%-25s HTTP/3 работает' "VPS:443 (QUIC)")" "udp_VPS:443 (QUIC)"
|
||||||
else
|
else
|
||||||
if do_udp "$host" "$port"; then
|
# Фолбэк: отправляем UDP-пакет, проверяем что nc не получил ICMP unreachable
|
||||||
skip "$(printf '%-25s (отправлено, ответ неизвестен)' "$name")" "udp_$name"
|
echo -n "test" | timeout 2 nc -u -w 1 "$VPS_IP" 443 >/dev/null 2>&1
|
||||||
|
skip "$(printf '%-25s (curl без HTTP/3, UDP отправлен)' "VPS:443 (QUIC)")" "udp_VPS:443 (QUIC)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# WireGuard / AmneziaWG — отправляем WG handshake init
|
||||||
|
info "WireGuard handshake init"
|
||||||
|
local -A wg_ports=(
|
||||||
|
["VPS:43742 (WG)"]="43742"
|
||||||
|
["VPS:47426 (AWG)"]="47426"
|
||||||
|
["VPS:48253 (AWG2)"]="48253"
|
||||||
|
)
|
||||||
|
local wg_order=("VPS:43742 (WG)" "VPS:47426 (AWG)" "VPS:48253 (AWG2)")
|
||||||
|
|
||||||
|
for name in "${wg_order[@]}"; do
|
||||||
|
local port="${wg_ports[$name]}"
|
||||||
|
if do_udp_wg "$VPS_IP" "$port"; then
|
||||||
|
ok "$(printf '%-25s (WG ответил)' "$name")" "udp_$name"
|
||||||
else
|
else
|
||||||
fail "$(printf '%-25s' "$name")" "udp_$name"
|
# nc не получил ICMP port unreachable — пакет, вероятно, дошёл
|
||||||
|
echo -n "test" | timeout 2 nc -u -w 1 "$VPS_IP" "$port" >/dev/null 2>&1
|
||||||
|
local nc_rc=$?
|
||||||
|
if [ $nc_rc -eq 0 ]; then
|
||||||
|
skip "$(printf '%-25s (отправлено, нет ответа)' "$name")" "udp_$name"
|
||||||
|
else
|
||||||
|
fail "$(printf '%-25s (UDP заблокирован)' "$name")" "udp_$name"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -413,45 +462,60 @@ test_https() {
|
|||||||
|
|
||||||
local order=(
|
local order=(
|
||||||
"yandex.ru" "ya.ru" "vk.com" "mail.ru" "ok.ru" "sber.ru" "gosuslugi.ru" "mos.ru" "rutube.ru"
|
"yandex.ru" "ya.ru" "vk.com" "mail.ru" "ok.ru" "sber.ru" "gosuslugi.ru" "mos.ru" "rutube.ru"
|
||||||
"---РУ/Зарубеж---"
|
"---"
|
||||||
"google.com" "cloudflare.com" "microsoft.com" "apple.com" "github.com" "telegram.org"
|
"google.com" "cloudflare.com" "microsoft.com" "apple.com" "github.com" "telegram.org"
|
||||||
"---CDN---"
|
"---"
|
||||||
"cdn.jsdelivr.net" "cdnjs.cloudflare.com" "unpkg.com"
|
"cdn.jsdelivr.net" "cdnjs.cloudflare.com" "unpkg.com"
|
||||||
"---Облака---"
|
"---"
|
||||||
"cloud.yandex.ru" "functions.yandexcloud.net" "cloud.vk.com" "dns.yandex.net"
|
"cloud.yandex.ru" "functions.yandexcloud.net" "cloud.vk.com" "dns.yandex.net"
|
||||||
)
|
)
|
||||||
|
|
||||||
for name in "${order[@]}"; do
|
for name in "${order[@]}"; do
|
||||||
if [[ "$name" == ---* ]]; then
|
if [[ "$name" == "---" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
local target="${sites[$name]}"
|
local target="${sites[$name]}"
|
||||||
local code
|
local result
|
||||||
code=$(do_https "$target")
|
result=$(do_https "$target")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
local h2
|
ok "$(printf '%-28s %s' "$name" "$result")" "https_$name"
|
||||||
h2=$(do_h2 "$target")
|
|
||||||
local proto_tag=""
|
|
||||||
[ "$h2" = "2" ] && proto_tag=" HTTP/2" || proto_tag=" HTTP/$h2"
|
|
||||||
ok "$(printf '%-28s %s%s' "$name" "$code" "$proto_tag")" "https_$name"
|
|
||||||
else
|
else
|
||||||
fail "$(printf '%-28s' "$name")" "https_$name"
|
fail "$(printf '%-28s' "$name")" "https_$name"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Кросс-валидация: ICMP ✗ но HTTPS ✓ → предупредить
|
||||||
|
test_icmp_crosscheck() {
|
||||||
|
hdr "ICMP КРОСС-ВАЛИДАЦИЯ"
|
||||||
|
info "Сайты с ICMP ✗ но HTTPS ✓ (блокируют ping, но работают)"
|
||||||
|
|
||||||
|
local found=0
|
||||||
|
local icmp_sites=("yandex.ru" "ya.ru" "vk.com" "mail.ru" "ok.ru" "sber.ru" "gosuslugi.ru" "mos.ru")
|
||||||
|
for name in "${icmp_sites[@]}"; do
|
||||||
|
if [ "${RESULTS[icmp_$name]}" = "fail" ] && [ "${RESULTS[https_$name]}" = "ok" ]; then
|
||||||
|
warn "$(printf '%-22s ICMP блокирован сервером, HTTPS работает' "$name")" "crosscheck_$name"
|
||||||
|
found=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$found" -eq 0 ]; then
|
||||||
|
info "Расхождений не найдено"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
test_sni() {
|
test_sni() {
|
||||||
hdr "SNI FILTERING"
|
hdr "SNI FILTERING"
|
||||||
info "TLS handshake к VPS ($VPS_IP:443) с разными SNI"
|
info "TLS handshake к VPS ($VPS_IP:443) с разными SNI"
|
||||||
|
|
||||||
local snis=("yandex.ru" "ya.ru" "vk.com" "mail.ru" "google.com" "$VPS_IP")
|
local snis=("yandex.ru" "ya.ru" "vk.com" "mail.ru" "google.com" "cloudflare.com" "telegram.org" "$VPS_IP")
|
||||||
|
|
||||||
for sni in "${snis[@]}"; do
|
for sni in "${snis[@]}"; do
|
||||||
if do_tls_sni "$VPS_IP" 443 "$sni"; then
|
if do_tls_sni "$VPS_IP" 443 "$sni"; then
|
||||||
ok "$(printf 'SNI=%-20s → TLS OK' "$sni")" "sni_$sni"
|
ok "$(printf 'SNI=%-20s → TLS OK' "$sni")" "sni_$sni"
|
||||||
else
|
else
|
||||||
fail "$(printf 'SNI=%-20s' "$sni")" "sni_$sni"
|
fail "$(printf 'SNI=%-20s → DPI фильтрует!' "$sni")" "sni_$sni"
|
||||||
|
FILTERED_SNIS+=("$sni")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -461,9 +525,17 @@ test_sni() {
|
|||||||
if do_tls_sni "$MOSCOW_IP" 2053 "$sni"; then
|
if do_tls_sni "$MOSCOW_IP" 2053 "$sni"; then
|
||||||
ok "$(printf 'SNI=%-20s → TLS OK' "$sni")" "sni_moscow_$sni"
|
ok "$(printf 'SNI=%-20s → TLS OK' "$sni")" "sni_moscow_$sni"
|
||||||
else
|
else
|
||||||
fail "$(printf 'SNI=%-20s' "$sni")" "sni_moscow_$sni"
|
fail "$(printf 'SNI=%-20s → DPI фильтрует!' "$sni")" "sni_moscow_$sni"
|
||||||
|
FILTERED_SNIS+=("$sni")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ ${#FILTERED_SNIS[@]} -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
info "${Y}⚠ Обнаружена SNI-фильтрация: ${FILTERED_SNIS[*]}${N}"
|
||||||
|
info "DPI провайдера блокирует TLS к чужим IP с этими SNI"
|
||||||
|
info "Для Reality/VLESS избегайте этих доменов как маскировочных"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
test_cdn() {
|
test_cdn() {
|
||||||
@@ -471,15 +543,23 @@ test_cdn() {
|
|||||||
|
|
||||||
# Cloudflare IP ranges
|
# Cloudflare IP ranges
|
||||||
local cf_ips=("104.16.0.1" "104.17.0.1" "172.64.0.1" "172.67.0.1")
|
local cf_ips=("104.16.0.1" "104.17.0.1" "172.64.0.1" "172.67.0.1")
|
||||||
|
local cf_ok=0
|
||||||
|
local cf_total=${#cf_ips[@]}
|
||||||
info "Cloudflare IP ranges"
|
info "Cloudflare IP ranges"
|
||||||
for ip in "${cf_ips[@]}"; do
|
for ip in "${cf_ips[@]}"; do
|
||||||
if do_tcp "$ip" 443; then
|
if do_tcp "$ip" 443; then
|
||||||
ok "$(printf '%-22s TCP:443' "$ip")" "cdn_cf_$ip"
|
ok "$(printf '%-22s TCP:443' "$ip")" "cdn_cf_$ip"
|
||||||
|
((cf_ok++))
|
||||||
else
|
else
|
||||||
fail "$(printf '%-22s' "$ip")" "cdn_cf_$ip"
|
fail "$(printf '%-22s' "$ip")" "cdn_cf_$ip"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$cf_ok" -gt 0 ] && [ "$cf_ok" -lt "$cf_total" ]; then
|
||||||
|
info "${Y}⚠ Частичная блокировка Cloudflare: $cf_ok/$cf_total диапазонов доступны${N}"
|
||||||
|
RESULTS["cf_partial_block"]="true"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
info "Yandex CDN"
|
info "Yandex CDN"
|
||||||
local ycdn
|
local ycdn
|
||||||
@@ -510,18 +590,20 @@ test_cdn() {
|
|||||||
test_advanced() {
|
test_advanced() {
|
||||||
hdr "ADVANCED"
|
hdr "ADVANCED"
|
||||||
|
|
||||||
# WebSocket upgrade test через доступные хосты
|
# WebSocket upgrade — тестируем к VPS, а не к Яндексу
|
||||||
info "WebSocket upgrade"
|
info "WebSocket upgrade к VPS ($VPS_IP:443)"
|
||||||
local ws_code
|
local ws_code
|
||||||
ws_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout $TIMEOUT \
|
ws_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout $TIMEOUT -k \
|
||||||
-H "Upgrade: websocket" -H "Connection: Upgrade" \
|
-H "Upgrade: websocket" -H "Connection: Upgrade" \
|
||||||
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
|
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
|
||||||
-H "Sec-WebSocket-Version: 13" \
|
-H "Sec-WebSocket-Version: 13" \
|
||||||
"https://yandex.ru" 2>/dev/null)
|
"https://$VPS_IP" 2>/dev/null)
|
||||||
if [ "$ws_code" = "101" ]; then
|
if [ "$ws_code" = "101" ]; then
|
||||||
ok "WebSocket yandex.ru → 101 Switching" "ws_yandex"
|
ok "WebSocket VPS → 101 Switching Protocols" "ws_vps"
|
||||||
|
elif [ "$ws_code" -ge 100 ] 2>/dev/null && [ "$ws_code" -lt 600 ] 2>/dev/null; then
|
||||||
|
warn "WebSocket VPS → $ws_code (сервер не поддерживает WS upgrade)" "ws_vps"
|
||||||
else
|
else
|
||||||
fail "WebSocket yandex.ru → $ws_code (не поддерживает)" "ws_yandex"
|
fail "WebSocket VPS → нет ответа (DPI или сервер)" "ws_vps"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# QUIC / HTTP3
|
# QUIC / HTTP3
|
||||||
@@ -539,13 +621,15 @@ test_advanced() {
|
|||||||
# ECH support
|
# ECH support
|
||||||
echo ""
|
echo ""
|
||||||
info "ECH (Encrypted Client Hello)"
|
info "ECH (Encrypted Client Hello)"
|
||||||
local ech
|
local ech_out
|
||||||
ech=$(echo | timeout $TIMEOUT openssl s_client -connect cloudflare.com:443 \
|
ech_out=$(echo | timeout $TIMEOUT openssl s_client -connect cloudflare.com:443 \
|
||||||
-ech grease 2>&1 | grep -i "ech")
|
-ech grease 2>&1)
|
||||||
if [ -n "$ech" ]; then
|
if echo "$ech_out" | grep -qi "ech.*accepted\|ECH.*status.*success"; then
|
||||||
ok "ECH → поддерживается" "ech"
|
ok "ECH → принят сервером" "ech"
|
||||||
|
elif echo "$ech_out" | grep -qi "ech"; then
|
||||||
|
warn "ECH → openssl знает ECH, но GREASE (не настоящий ECH)" "ech"
|
||||||
else
|
else
|
||||||
skip "ECH → не поддерживается данной версией openssl" "ech"
|
skip "ECH → openssl не поддерживает ECH" "ech"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,80 +640,106 @@ recommendations() {
|
|||||||
hdr "РЕКОМЕНДАЦИИ"
|
hdr "РЕКОМЕНДАЦИИ"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
local rec=()
|
|
||||||
local rec_detail=()
|
local rec_detail=()
|
||||||
|
local warnings=()
|
||||||
|
|
||||||
# S-тир: CDN tunnel
|
# Собираем предупреждения
|
||||||
if [ "${RESULTS[https_cloudflare.com]}" = "ok" ] || [ "${RESULTS[cdn_cf_104.16.0.1]}" = "ok" ]; then
|
if [ "${RESULTS[cf_partial_block]}" = "true" ]; then
|
||||||
rec+=("S")
|
warnings+=("⚠ Cloudflare частично заблокирован — CDN-туннели могут быть нестабильны")
|
||||||
rec_detail+=("${G}S-тир${N} │ VLESS + WebSocket + Cloudflare CDN │ CF доступен, быстро и надёжно")
|
fi
|
||||||
|
if [ ${#FILTERED_SNIS[@]} -gt 0 ]; then
|
||||||
|
warnings+=("⚠ SNI-фильтрация: ${FILTERED_SNIS[*]} — Reality должен использовать безопасные SNI")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Определяем безопасные SNI для Reality
|
||||||
|
local safe_sni_note=""
|
||||||
|
if [ ${#FILTERED_SNIS[@]} -gt 0 ]; then
|
||||||
|
local safe_snis=()
|
||||||
|
for sni in "yandex.ru" "ya.ru" "mail.ru" "google.com" "cloudflare.com"; do
|
||||||
|
local filtered=0
|
||||||
|
for f in "${FILTERED_SNIS[@]}"; do
|
||||||
|
[ "$sni" = "$f" ] && filtered=1 && break
|
||||||
|
done
|
||||||
|
[ "$filtered" -eq 0 ] && [ "${RESULTS[sni_$sni]}" = "ok" ] && safe_snis+=("$sni")
|
||||||
|
done
|
||||||
|
if [ ${#safe_snis[@]} -gt 0 ]; then
|
||||||
|
safe_sni_note=" (безопасные SNI: ${safe_snis[*]})"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# S-тир: CDN tunnel через Cloudflare
|
||||||
|
if [ "${RESULTS[https_cloudflare.com]}" = "ok" ] || [ "${RESULTS[cdn_cf_104.16.0.1]}" = "ok" ]; then
|
||||||
|
local cf_note="CF доступен, быстро и надёжно"
|
||||||
|
[ "${RESULTS[cf_partial_block]}" = "true" ] && cf_note="CF частично доступен, возможна нестабильность"
|
||||||
|
rec_detail+=("${G}S-тир${N} │ VLESS + WebSocket + Cloudflare CDN │ $cf_note")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# S-тир: CDN через jsDelivr
|
||||||
if [ "${RESULTS[https_cdn.jsdelivr.net]}" = "ok" ]; then
|
if [ "${RESULTS[https_cdn.jsdelivr.net]}" = "ok" ]; then
|
||||||
rec+=("S")
|
|
||||||
rec_detail+=("${G}S-тир${N} │ CDN-туннель через jsDelivr │ CDN доступен")
|
rec_detail+=("${G}S-тир${N} │ CDN-туннель через jsDelivr │ CDN доступен")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# S-тир: Direct VLESS
|
# S-тир: Direct VLESS + Reality
|
||||||
if [ "${RESULTS[tcp_VPS:443 (VLESS)]}" = "ok" ]; then
|
if [ "${RESULTS[tcp_VPS:443 (VLESS)]}" = "ok" ]; then
|
||||||
rec+=("S")
|
rec_detail+=("${G}S-тир${N} │ VLESS + XHTTP + Reality (прямой) │ TCP к VPS:443 открыт${safe_sni_note}")
|
||||||
rec_detail+=("${G}S-тир${N} │ VLESS + XHTTP + Reality (прямой) │ TCP к VPS:443 открыт")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# A-тир: Moscow relay
|
# A-тир: Moscow relay
|
||||||
if [ "${RESULTS[tcp_Moscow:2053 (relay)]}" = "ok" ]; then
|
if [ "${RESULTS[tcp_Moscow:2053 (relay)]}" = "ok" ]; then
|
||||||
rec+=("A")
|
|
||||||
rec_detail+=("${Y}A-тир${N} │ VLESS через Moscow relay │ TCP к Москве:2053 открыт")
|
rec_detail+=("${Y}A-тир${N} │ VLESS через Moscow relay │ TCP к Москве:2053 открыт")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# A-тир: Hysteria2
|
# A-тир: Shadowsocks
|
||||||
|
if [ "${RESULTS[tcp_VPS:38246 (SS)]}" = "ok" ]; then
|
||||||
|
rec_detail+=("${Y}A-тир${N} │ Shadowsocks │ TCP к VPS:38246 открыт")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A-тир: OpenVPN + Cloak
|
||||||
|
if [ "${RESULTS[tcp_VPS:553 (OVPNCloak)]}" = "ok" ]; then
|
||||||
|
rec_detail+=("${Y}A-тир${N} │ OpenVPN + Cloak │ TCP к VPS:553 открыт")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# B-тир: SOCKS5 proxy (без обфускации, легко детектится DPI)
|
||||||
|
if [ "${RESULTS[tcp_VPS:43781 (SOCKS5)]}" = "ok" ]; then
|
||||||
|
rec_detail+=("${C}B-тир${N} │ SOCKS5 proxy (без обфускации) │ TCP к VPS:43781 открыт")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A-тир: Hysteria2 / QUIC
|
||||||
if [ "${RESULTS[udp_VPS:443 (QUIC)]}" = "ok" ]; then
|
if [ "${RESULTS[udp_VPS:443 (QUIC)]}" = "ok" ]; then
|
||||||
rec+=("A")
|
rec_detail+=("${Y}A-тир${N} │ Hysteria2 + Salamander (UDP) │ UDP QUIC к VPS работает")
|
||||||
rec_detail+=("${Y}A-тир${N} │ Hysteria2 + Salamander (UDP) │ UDP к VPS работает")
|
fi
|
||||||
|
|
||||||
|
# B-тир: WireGuard / AmneziaWG
|
||||||
|
if [ "${RESULTS[udp_VPS:43742 (WG)]}" = "ok" ] || [ "${RESULTS[udp_VPS:47426 (AWG)]}" = "ok" ] || [ "${RESULTS[udp_VPS:48253 (AWG2)]}" = "ok" ]; then
|
||||||
|
rec_detail+=("${C}B-тир${N} │ AmneziaWG / WireGuard │ UDP к VPS работает")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# B-тир: Chisel
|
||||||
|
if [ "${RESULTS[tcp_VPS:8443 (Chisel)]}" = "ok" ]; then
|
||||||
|
rec_detail+=("${C}B-тир${N} │ Chisel (HTTP tunnel) │ TCP к VPS:8443 открыт")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# B-тир: Yandex Cloud Functions
|
# B-тир: Yandex Cloud Functions
|
||||||
if [ "${RESULTS[https_functions.yandexcloud.net]}" = "ok" ]; then
|
if [ "${RESULTS[https_functions.yandexcloud.net]}" = "ok" ]; then
|
||||||
rec+=("B")
|
|
||||||
rec_detail+=("${C}B-тир${N} │ Serverless proxy (YC Functions) │ Yandex Cloud доступен")
|
rec_detail+=("${C}B-тир${N} │ Serverless proxy (YC Functions) │ Yandex Cloud доступен")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# B-тир: DNSTT
|
# B-тир: DNSTT
|
||||||
if [ "${RESULTS[dns_dnstt]}" = "ok" ] || [ "${RESULTS[dns_system]}" = "ok" ]; then
|
if [ "${RESULTS[dns_dnstt]}" = "ok" ] || [ "${RESULTS[dns_system]}" = "ok" ]; then
|
||||||
rec+=("B")
|
|
||||||
rec_detail+=("${C}B-тир${N} │ DNSTT (DNS-туннель) │ DNS работает, ~50-100 Кбит/с")
|
rec_detail+=("${C}B-тир${N} │ DNSTT (DNS-туннель) │ DNS работает, ~50-100 Кбит/с")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# B-тир: DoH tunnel
|
|
||||||
if [ "${RESULTS[doh_yandex]}" = "ok" ]; then
|
|
||||||
rec+=("B")
|
|
||||||
rec_detail+=("${C}B-тир${N} │ DoH tunnel (dns.yandex.net) │ DNS-over-HTTPS через Яндекс")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# C-тир: ICMP tunnel
|
# C-тир: ICMP tunnel
|
||||||
local icmp_to_vps="${RESULTS[icmp_VPS Ирландия]}"
|
if [ "${RESULTS[icmp_VPS Ирландия]}" = "ok" ] || [ "${RESULTS[icmp_Москва relay]}" = "ok" ]; then
|
||||||
local icmp_to_moscow="${RESULTS[icmp_Москва relay]}"
|
rec_detail+=("${R}C-тир${N} │ ICMP tunnel (ptunnel-ng) │ Ping к серверу, очень медленно")
|
||||||
if [ "$icmp_to_vps" = "ok" ] || [ "$icmp_to_moscow" = "ok" ]; then
|
|
||||||
rec+=("C")
|
|
||||||
rec_detail+=("${R}C-тир${N} │ ICMP tunnel (ptunnel-ng) │ Ping к серверу работает, очень медленно")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Shadowsocks
|
# Вывод предупреждений
|
||||||
if [ "${RESULTS[tcp_VPS:38246 (SS)]}" = "ok" ]; then
|
if [ ${#warnings[@]} -gt 0 ]; then
|
||||||
rec+=("A")
|
for w in "${warnings[@]}"; do
|
||||||
rec_detail+=("${Y}A-тир${N} │ Shadowsocks │ TCP к VPS:38246 открыт")
|
echo -e " ${Y}$w${N}"
|
||||||
fi
|
done
|
||||||
|
echo ""
|
||||||
# Chisel
|
|
||||||
if [ "${RESULTS[tcp_VPS:8443 (Chisel)]}" = "ok" ]; then
|
|
||||||
rec+=("B")
|
|
||||||
rec_detail+=("${C}B-тир${N} │ Chisel (HTTP tunnel) │ TCP к VPS:8443 открыт")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# WireGuard / AmneziaWG
|
|
||||||
if [ "${RESULTS[udp_VPS:43742 (WG)]}" = "ok" ] || [ "${RESULTS[udp_VPS:47426 (AWG)]}" = "ok" ]; then
|
|
||||||
rec+=("B")
|
|
||||||
rec_detail+=("${C}B-тир${N} │ AmneziaWG / WireGuard │ UDP к VPS работает")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ${#rec_detail[@]} -eq 0 ]; then
|
if [ ${#rec_detail[@]} -eq 0 ]; then
|
||||||
@@ -648,27 +758,40 @@ recommendations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
# СОХРАНЕНИЕ РЕЗУЛЬТАТОВ
|
# СОХРАНЕНИЕ РЕЗУЛЬТАТОВ (безопасный JSON)
|
||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
save_results() {
|
save_results() {
|
||||||
mkdir -p "$RESULT_DIR"
|
mkdir -p "$RESULT_DIR"
|
||||||
|
|
||||||
# JSON
|
# Экранирование для JSON
|
||||||
echo "{" > "$JSON_FILE"
|
json_escape() {
|
||||||
echo " \"timestamp\": \"$TIMESTAMP\"," >> "$JSON_FILE"
|
local s="$1"
|
||||||
echo " \"results\": {" >> "$JSON_FILE"
|
s="${s//\\/\\\\}"
|
||||||
|
s="${s//\"/\\\"}"
|
||||||
|
s="${s//$'\n'/\\n}"
|
||||||
|
s="${s//$'\t'/\\t}"
|
||||||
|
echo -n "$s"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "{"
|
||||||
|
echo " \"version\": \"1.1\","
|
||||||
|
echo " \"timestamp\": \"$TIMESTAMP\","
|
||||||
|
echo " \"filtered_snis\": [$(printf '"%s",' "${FILTERED_SNIS[@]}" | sed 's/,$//' )],"
|
||||||
|
echo " \"results\": {"
|
||||||
local first=true
|
local first=true
|
||||||
for key in $(echo "${!RESULTS[@]}" | tr ' ' '\n' | sort); do
|
for key in $(echo "${!RESULTS[@]}" | tr ' ' '\n' | sort); do
|
||||||
if [ "$first" = true ]; then
|
if [ "$first" = true ]; then
|
||||||
first=false
|
first=false
|
||||||
else
|
else
|
||||||
echo "," >> "$JSON_FILE"
|
echo ","
|
||||||
fi
|
fi
|
||||||
printf ' "%s": "%s"' "$key" "${RESULTS[$key]}" >> "$JSON_FILE"
|
printf ' "%s": "%s"' "$(json_escape "$key")" "$(json_escape "${RESULTS[$key]}")"
|
||||||
done
|
done
|
||||||
echo "" >> "$JSON_FILE"
|
echo ""
|
||||||
echo " }" >> "$JSON_FILE"
|
echo " }"
|
||||||
echo "}" >> "$JSON_FILE"
|
echo "}"
|
||||||
|
} > "$JSON_FILE"
|
||||||
|
|
||||||
info "Результаты: $JSON_FILE"
|
info "Результаты: $JSON_FILE"
|
||||||
}
|
}
|
||||||
@@ -678,7 +801,7 @@ save_results() {
|
|||||||
# ══════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════
|
||||||
main() {
|
main() {
|
||||||
echo -e "${B}══════════════════════════════════════════${N}"
|
echo -e "${B}══════════════════════════════════════════${N}"
|
||||||
echo -e "${B} WHITELIST PROBE v1.0 — $(date '+%Y-%m-%d %H:%M')${N}"
|
echo -e "${B} WHITELIST PROBE v1.1 — $(date '+%Y-%m-%d %H:%M')${N}"
|
||||||
echo -e "${B}══════════════════════════════════════════${N}"
|
echo -e "${B}══════════════════════════════════════════${N}"
|
||||||
|
|
||||||
install_deps
|
install_deps
|
||||||
@@ -690,6 +813,7 @@ main() {
|
|||||||
test_tcp_our_servers
|
test_tcp_our_servers
|
||||||
test_udp
|
test_udp
|
||||||
test_https
|
test_https
|
||||||
|
test_icmp_crosscheck
|
||||||
test_sni
|
test_sni
|
||||||
test_cdn
|
test_cdn
|
||||||
test_advanced
|
test_advanced
|
||||||
@@ -698,7 +822,7 @@ main() {
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${B}══════════════════════════════════════════${N}"
|
echo -e "${B}══════════════════════════════════════════${N}"
|
||||||
echo -e " Тестов: $TOTAL ${G}✓ $PASS${N} ${R}✗ $FAIL${N}"
|
echo -e " Тестов: $TOTAL ${G}✓ $PASS${N} ${R}✗ $FAIL${N} ${Y}— $SKIP${N}"
|
||||||
echo -e "${B}══════════════════════════════════════════${N}"
|
echo -e "${B}══════════════════════════════════════════${N}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user