Fix ping: port before probe (TCP fallback works), show [ICMP]/[TCP] method, SSH command after timeout

Made-with: Cursor
This commit is contained in:
anten-ka
2026-03-07 15:38:44 +03:00
parent 770d32f35d
commit 41ff2a9c41

View File

@@ -199,7 +199,7 @@ geoip_lookup() {
} }
probe_server_cli() { probe_server_cli() {
local ip="$1" local ip="$1" port="${2:-}"
echo -e "\n${CYAN}━━━ Проверка сервера $ip ━━━${NC}" echo -e "\n${CYAN}━━━ Проверка сервера $ip ━━━${NC}"
echo -e "${YELLOW}[*] GeoIP...${NC}" echo -e "${YELLOW}[*] GeoIP...${NC}"
@@ -228,13 +228,13 @@ probe_server_cli() {
local plost=0 local plost=0
for n in 1 2 3; do for n in 1 2 3; do
local ms local ms
ms=$(ping -c 1 -W 3 "$ip" 2>/dev/null | sed -n 's/.*time=\([0-9.]*\).*/\1/p') ms=$(smart_ping "$ip" 3 "$port")
if [ -n "$ms" ]; then if [ -n "$ms" ]; then
pings+=("$ms") pings+=("$ms")
echo -e " #$n: ${GREEN}${ms}ms${NC}" echo -e " #$n: ${GREEN}${ms}ms${NC} ${CYAN}[${_PING_METHOD}]${NC}"
else else
((plost++)) ((plost++))
echo -e " #$n: ${RED}timeout${NC}" echo -e " #$n: ${RED}timeout${NC} ${WHITE}[ICMP fail$([ -n "$port" ] && echo ", TCP:$port fail")]${NC}"
fi fi
[ "$n" -lt 3 ] && sleep 1 [ "$n" -lt 3 ] && sleep 1
done done
@@ -261,14 +261,14 @@ probe_server_cli() {
[ -n "$_RET_NOTE" ] && set_alias_note "$ip" "$_RET_NOTE" [ -n "$_RET_NOTE" ] && set_alias_note "$ip" "$_RET_NOTE"
if [ ${#pings[@]} -eq 0 ]; then if [ ${#pings[@]} -eq 0 ]; then
echo -e "${YELLOW}━━━ Сервер не ответил на ICMP ping ━━━${NC}" echo -e "\n${YELLOW}━━━ Сервер не ответил ━━━${NC}"
echo -e "${WHITE}Это нормально для VLESS / XRay / Reality — они часто блокируют ICMP.${NC}" echo -e "${WHITE}ICMP заблокирован$([ -n "$port" ] && echo " и TCP:$port не удался").${NC}"
echo -e "${WHITE}После добавления правила ping будет работать через TCP.${NC}"
echo "" echo ""
echo -e "${CYAN}Если хотите включить ICMP на удалённом сервере:${NC}" echo -e "${CYAN}Чтобы включить ping на удалённом сервере:${NC}"
echo -e " ${WHITE}ssh root@${ip}${NC}" echo -e " ${WHITE}ssh root@${ip}${NC}"
echo -e " ${GREEN}sysctl -w net.ipv4.icmp_echo_ignore_all=0${NC}" echo -e " ${GREEN}sysctl -w net.ipv4.icmp_echo_ignore_all=0${NC}"
echo -e " ${GREEN}echo 'net.ipv4.icmp_echo_ignore_all=0' >> /etc/sysctl.conf${NC}" echo -e " ${GREEN}echo 'net.ipv4.icmp_echo_ignore_all=0' >> /etc/sysctl.conf${NC}"
echo -e " ${GREEN}iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT${NC}"
echo "" echo ""
read -p "Продолжить добавление? (y/n): " ans read -p "Продолжить добавление? (y/n): " ans
[[ "$ans" != "y" ]] && return 1 [[ "$ans" != "y" ]] && return 1
@@ -277,7 +277,7 @@ probe_server_cli() {
} }
probe_server_tg() { probe_server_tg() {
local ip="$1" local ip="$1" port="${2:-}"
local result="" local result=""
local geo local geo
geo=$(geoip_lookup "$ip") geo=$(geoip_lookup "$ip")
@@ -298,10 +298,10 @@ probe_server_tg() {
local plost=0 local plost=0
for n in 1 2 3; do for n in 1 2 3; do
local ms local ms
ms=$(ping -c 1 -W 3 "$ip" 2>/dev/null | sed -n 's/.*time=\([0-9.]*\).*/\1/p') ms=$(smart_ping "$ip" 3 "$port")
if [ -n "$ms" ]; then if [ -n "$ms" ]; then
pings+=("$ms") pings+=("$ms")
result+=" #$n: ${ms}ms\n" result+=" #$n: ${ms}ms [${_PING_METHOD}]\n"
else else
((plost++)) ((plost++))
result+=" #$n: timeout\n" result+=" #$n: timeout\n"
@@ -313,9 +313,9 @@ probe_server_tg() {
pavg=$(printf '%s\n' "${pings[@]}" | awk '{s+=$1} END {printf "%.2f", s/NR}') pavg=$(printf '%s\n' "${pings[@]}" | awk '{s+=$1} END {printf "%.2f", s/NR}')
result+="<b>Среднее: ${pavg}ms</b> | Потеряно: $plost/3\n" result+="<b>Среднее: ${pavg}ms</b> | Потеряно: $plost/3\n"
else else
result+="<b>Сервер не отвечает на ICMP</b>\n" result+="<b>Сервер не ответил</b>\n"
result+="(Нормально для XRay/VLESS)\n" result+="Включите ping:\n<code>sysctl -w net.ipv4.icmp_echo_ignore_all=0</code>\n"
result+="TCP-ping заработает после добавления.\n" result+="<code>iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT</code>\n"
fi fi
echo "$result" echo "$result"
} }
@@ -428,14 +428,19 @@ tcp_ping() {
echo "$ms" echo "$ms"
} }
_PING_METHOD=""
smart_ping() { smart_ping() {
local ip="$1" tout="${2:-3}" port="${3:-}" local ip="$1" tout="${2:-3}" port="${3:-}"
_PING_METHOD=""
local ms local ms
ms=$(ping -c 1 -W "$tout" "$ip" 2>/dev/null | sed -n 's/.*time=\([0-9.]*\).*/\1/p') ms=$(ping -c 1 -W "$tout" "$ip" 2>/dev/null | sed -n 's/.*time=\([0-9.]*\).*/\1/p')
if [ -n "$ms" ]; then echo "$ms"; return 0; fi if [ -n "$ms" ]; then _PING_METHOD="ICMP"; echo "$ms"; return 0; fi
[ -z "$port" ] && port=$(get_port_for_ip "$ip") [ -z "$port" ] && port=$(get_port_for_ip "$ip")
[ -z "$port" ] && return 1 [ -z "$port" ] && return 1
tcp_ping "$ip" "$port" "$tout" ms=$(tcp_ping "$ip" "$port" "$tout")
if [ -n "$ms" ]; then _PING_METHOD="TCP:${port}"; echo "$ms"; return 0; fi
return 1
} }
remove_rules_for_port() { remove_rules_for_port() {
@@ -480,10 +485,9 @@ configure_rule() {
echo -e "\n${CYAN}--- Настройка $name ($proto) ---${NC}" echo -e "\n${CYAN}--- Настройка $name ($proto) ---${NC}"
read_validated_ip "Введите IP адрес назначения:" read_validated_ip "Введите IP адрес назначения:"
local target_ip="$_RET_IP" local target_ip="$_RET_IP"
probe_server_cli "$target_ip" || return
read_validated_port "Введите Порт (одинаковый для входа и выхода):" read_validated_port "Введите Порт (одинаковый для входа и выхода):"
local port="$_RET_PORT" local port="$_RET_PORT"
probe_server_cli "$target_ip" "$port" || return
echo -e "\n${YELLOW}Будет создано правило:${NC}" echo -e "\n${YELLOW}Будет создано правило:${NC}"
echo -e " $proto: ${MY_IP:-*}:$port -> $(fmt_ip_short "$target_ip"):$port" echo -e " $proto: ${MY_IP:-*}:$port -> $(fmt_ip_short "$target_ip"):$port"
read -p "Применить? (y/n): " confirm read -p "Применить? (y/n): " confirm
@@ -503,12 +507,11 @@ configure_custom_rule() {
done done
read_validated_ip "Введите IP адрес назначения:" read_validated_ip "Введите IP адрес назначения:"
local target_ip="$_RET_IP" local target_ip="$_RET_IP"
probe_server_cli "$target_ip" || return
read_validated_port "Введите ${YELLOW}ВХОДЯЩИЙ Порт${NC} (на этом сервере):" read_validated_port "Введите ${YELLOW}ВХОДЯЩИЙ Порт${NC} (на этом сервере):"
local in_port="$_RET_PORT" local in_port="$_RET_PORT"
read_validated_port "Введите ${YELLOW}ИСХОДЯЩИЙ Порт${NC} (на конечном сервере):" read_validated_port "Введите ${YELLOW}ИСХОДЯЩИЙ Порт${NC} (на конечном сервере):"
local out_port="$_RET_PORT" local out_port="$_RET_PORT"
probe_server_cli "$target_ip" "$out_port" || return
echo -e "\n${YELLOW}Будет создано правило:${NC}" echo -e "\n${YELLOW}Будет создано правило:${NC}"
echo -e " $proto: ${MY_IP:-*}:$in_port -> $(fmt_ip_short "$target_ip"):$out_port" echo -e " $proto: ${MY_IP:-*}:$in_port -> $(fmt_ip_short "$target_ip"):$out_port"
read -p "Применить? (y/n): " confirm read -p "Применить? (y/n): " confirm
@@ -794,7 +797,7 @@ ping_live() {
results+=("$ms") results+=("$ms")
local bar local bar
bar=$(make_ping_bar "$ms") bar=$(make_ping_bar "$ms")
printf " ${GREEN}#%-4d %7sms${NC} %b\n" "$count" "$ms" "$bar" printf " ${GREEN}#%-4d %7sms${NC} ${CYAN}[%s]${NC} %b\n" "$count" "$ms" "$_PING_METHOD" "$bar"
else else
((lost++)) ((lost++))
printf " ${RED}#%-4d ------${NC} " "$count" printf " ${RED}#%-4d ------${NC} " "$count"
@@ -1376,45 +1379,52 @@ bot_handle_message() {
fi fi
local proto name custom local proto name custom
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME"); custom=$(bot_get_state "$chat_id" "CUSTOM") proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME"); custom=$(bot_get_state "$chat_id" "CUSTOM")
local probe_msg; probe_msg=$(tg_send "$chat_id" "🔍 Проверяю <code>$text</code>..." "")
local probe_mid; probe_mid=$(echo "$probe_msg" | jq -r '.result.message_id // empty')
local probe_result; probe_result=$(probe_server_tg "$text")
local info_text="IP: <code>$text</code> ✅\n${probe_result}\nВведите имя сервера (или <code>-</code> — пропустить):"
if [ -n "$probe_mid" ]; then
tg_edit "$chat_id" "$probe_mid" "$info_text" "$(kbd_back)" > /dev/null
else
tg_send "$chat_id" "$info_text" "$(kbd_back)" > /dev/null
fi
bot_set_state "$chat_id" "STATE=awaiting_name" "PROTO=$proto" "NAME=$name" "CUSTOM=$custom" "TARGET_IP=$text"
;;
awaiting_name)
local proto name custom target_ip
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME")
custom=$(bot_get_state "$chat_id" "CUSTOM"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP")
if [ "$text" != "-" ] && [ -n "$text" ]; then set_alias "$target_ip" "$text"; fi
bot_set_state "$chat_id" "STATE=awaiting_note" "PROTO=$proto" "NAME=$name" "CUSTOM=$custom" "TARGET_IP=$target_ip"
tg_send "$chat_id" "Примечание (или <code>-</code> — пропустить):" "$(kbd_back)" > /dev/null
;;
awaiting_note)
local proto name custom target_ip
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME")
custom=$(bot_get_state "$chat_id" "CUSTOM"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP")
if [ "$text" != "-" ] && [ -n "$text" ]; then set_alias_note "$target_ip" "$text"; fi
if [ "$custom" = "1" ]; then if [ "$custom" = "1" ]; then
bot_set_state "$chat_id" "STATE=awaiting_in_port" "PROTO=$proto" "NAME=$name" "CUSTOM=1" "TARGET_IP=$target_ip" bot_set_state "$chat_id" "STATE=awaiting_in_port" "PROTO=$proto" "NAME=$name" "CUSTOM=1" "TARGET_IP=$text"
tg_send "$chat_id" "Сервер: <b>$(fmt_ip_short "$target_ip")</b>\n\n<b>ВХОДЯЩИЙ</b> порт:" "$(kbd_back)" > /dev/null tg_send "$chat_id" "IP: <code>$text</code> ✅\n\n<b>ВХОДЯЩИЙ</b> порт:" "$(kbd_back)" > /dev/null
else else
bot_set_state "$chat_id" "STATE=awaiting_port" "PROTO=$proto" "NAME=$name" "CUSTOM=0" "TARGET_IP=$target_ip" bot_set_state "$chat_id" "STATE=awaiting_port" "PROTO=$proto" "NAME=$name" "CUSTOM=0" "TARGET_IP=$text"
tg_send "$chat_id" "Сервер: <b>$(fmt_ip_short "$target_ip")</b>\n\nВведите порт:" "$(kbd_back)" > /dev/null tg_send "$chat_id" "IP: <code>$text</code> ✅\n\nВведите порт:" "$(kbd_back)" > /dev/null
fi ;; fi ;;
awaiting_port) awaiting_port)
if ! validate_port "$text"; then tg_send "$chat_id" "❌ Порт (1-65535)." "" > /dev/null; return; fi if ! validate_port "$text"; then tg_send "$chat_id" "❌ Порт (1-65535)." "" > /dev/null; return; fi
local proto name target_ip local proto name target_ip
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP") proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP")
bot_clear_state "$chat_id" local port="$text"
apply_iptables_rules "$proto" "$text" "$text" "$target_ip" "$name" local probe_msg; probe_msg=$(tg_send "$chat_id" "🔍 Проверяю <code>$target_ip:$port</code>..." "")
tg_send "$chat_id" "✅ <b>$name</b>\n<code>$proto ${MY_IP:-*}:$text$target_ip:$text</code>\n$(fmt_ip_tg "$target_ip")" "$(kbd_back)" > /dev/null ;; local probe_mid; probe_mid=$(echo "$probe_msg" | jq -r '.result.message_id // empty')
local probe_result; probe_result=$(probe_server_tg "$target_ip" "$port")
local info_text="<code>$target_ip:$port</code>\n${probe_result}\nВведите имя (или <code>-</code> — пропустить):"
[ -n "$probe_mid" ] && tg_edit "$chat_id" "$probe_mid" "$info_text" "$(kbd_back)" > /dev/null \
|| tg_send "$chat_id" "$info_text" "$(kbd_back)" > /dev/null
bot_set_state "$chat_id" "STATE=awaiting_name" "PROTO=$proto" "NAME=$name" "CUSTOM=0" "TARGET_IP=$target_ip" "PORT=$port"
;;
awaiting_name)
local proto name custom target_ip port
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME")
custom=$(bot_get_state "$chat_id" "CUSTOM"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP")
port=$(bot_get_state "$chat_id" "PORT")
if [ "$text" != "-" ] && [ -n "$text" ]; then set_alias "$target_ip" "$text"; fi
bot_set_state "$chat_id" "STATE=awaiting_note" "PROTO=$proto" "NAME=$name" "CUSTOM=$custom" "TARGET_IP=$target_ip" "PORT=$port" "IN_PORT=$(bot_get_state "$chat_id" "IN_PORT")" "OUT_PORT=$(bot_get_state "$chat_id" "OUT_PORT")"
tg_send "$chat_id" "Примечание (или <code>-</code> — пропустить):" "$(kbd_back)" > /dev/null
;;
awaiting_note)
local proto name custom target_ip port
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME")
custom=$(bot_get_state "$chat_id" "CUSTOM"); target_ip=$(bot_get_state "$chat_id" "TARGET_IP")
if [ "$text" != "-" ] && [ -n "$text" ]; then set_alias_note "$target_ip" "$text"; fi
if [ "$custom" = "1" ]; then
local in_port out_port
in_port=$(bot_get_state "$chat_id" "IN_PORT"); out_port=$(bot_get_state "$chat_id" "OUT_PORT")
bot_clear_state "$chat_id"
apply_iptables_rules "$proto" "$in_port" "$out_port" "$target_ip" "$name"
tg_send "$chat_id" "✅ <b>Custom</b>\n<code>$proto ${MY_IP:-*}:$in_port$target_ip:$out_port</code>\n$(fmt_ip_tg "$target_ip")" "$(kbd_back)" > /dev/null
else
port=$(bot_get_state "$chat_id" "PORT")
bot_clear_state "$chat_id"
apply_iptables_rules "$proto" "$port" "$port" "$target_ip" "$name"
tg_send "$chat_id" "✅ <b>$name</b>\n<code>$proto ${MY_IP:-*}:$port$target_ip:$port</code>\n$(fmt_ip_tg "$target_ip")" "$(kbd_back)" > /dev/null
fi ;;
awaiting_in_port) awaiting_in_port)
if ! validate_port "$text"; then tg_send "$chat_id" "❌ Порт." "" > /dev/null; return; fi if ! validate_port "$text"; then tg_send "$chat_id" "❌ Порт." "" > /dev/null; return; fi
local proto name target_ip local proto name target_ip
@@ -1426,9 +1436,14 @@ bot_handle_message() {
local proto name target_ip in_port local proto name target_ip in_port
proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME") proto=$(bot_get_state "$chat_id" "PROTO"); name=$(bot_get_state "$chat_id" "NAME")
target_ip=$(bot_get_state "$chat_id" "TARGET_IP"); in_port=$(bot_get_state "$chat_id" "IN_PORT") target_ip=$(bot_get_state "$chat_id" "TARGET_IP"); in_port=$(bot_get_state "$chat_id" "IN_PORT")
bot_clear_state "$chat_id" local probe_msg; probe_msg=$(tg_send "$chat_id" "🔍 Проверяю <code>$target_ip:$text</code>..." "")
apply_iptables_rules "$proto" "$in_port" "$text" "$target_ip" "$name" local probe_mid; probe_mid=$(echo "$probe_msg" | jq -r '.result.message_id // empty')
tg_send "$chat_id" "✅ <b>Custom</b>\n<code>$proto ${MY_IP:-*}:$in_port$target_ip:$text</code>\n$(fmt_ip_tg "$target_ip")" "$(kbd_back)" > /dev/null ;; local probe_result; probe_result=$(probe_server_tg "$target_ip" "$text")
local info_text="<code>$target_ip</code> (вход:$in_port → выход:$text)\n${probe_result}\nВведите имя (или <code>-</code> — пропустить):"
[ -n "$probe_mid" ] && tg_edit "$chat_id" "$probe_mid" "$info_text" "$(kbd_back)" > /dev/null \
|| tg_send "$chat_id" "$info_text" "$(kbd_back)" > /dev/null
bot_set_state "$chat_id" "STATE=awaiting_name" "PROTO=$proto" "NAME=$name" "CUSTOM=1" "TARGET_IP=$target_ip" "IN_PORT=$in_port" "OUT_PORT=$text"
;;
awaiting_threshold) awaiting_threshold)
if ! validate_port "$text"; then tg_send "$chat_id" "❌ Число (1-65535):" "" > /dev/null; return; fi if ! validate_port "$text"; then tg_send "$chat_id" "❌ Число (1-65535):" "" > /dev/null; return; fi
local mon_ip mon_interval local mon_ip mon_interval