ICMP на сервере запрещён: как измерять доступность и задержку без обычного пинга
Пингуете новый сервер — и в ответ тишина, Request timeout строка за строкой, хотя сайт на этом же IP прекрасно открывается в браузере. Первая мысль — сервер недоступен или сеть сломана. Вторая, более верная — ICMP просто заблокирован на одном из участков пути, и ping в принципе не может ничего сказать о состоянии сервиса. Разбираемся, почему так происходит и какими способами измерять доступность и задержку, когда классический ping не работает — а заодно почему для реального сервиса эти способы обычно лучше самого ICMP, даже когда он есть.
Содержание
- Почему ICMP ping недоступен: три причины
- TCP-замер задержки: то же самое, что ping, но через SYN
- HTTP/HTTPS-проверки: не просто задержка, а подтверждение работы сервиса
- Специализированные утилиты и self-hosted мониторинг поверх TCP/UDP
- Почему TCP/HTTP точнее отражают реальный пользовательский опыт, чем ICMP
- Практическая рекомендация: что мониторить в первую очередь
Почему ICMP ping недоступен: три причины
ICMP echo request/reply — протокол, на котором строится ping, — исторически задумывался как диагностический инструмент, а не как часть штатного пользовательского трафика. Именно поэтому его блокировка не редкость, а скорее норма в трёх типичных ситуациях.
Файрвол на самом сервере. Многие руководства по базовой защите сервера рекомендуют закрывать ICMP echo как часть ужесточения периметра — меньше поверхность для разведки сети (network reconnaissance) и часть примитивных сценариев ICMP flood. Это осознанная практика, а не ошибка конфигурации: правило iptables -A INPUT -p icmp --icmp-type echo-request -j DROP или аналог в ufw/firewalld ставится намеренно.
Политика облачного провайдера по умолчанию. У ряда облачных платформ и VPS-провайдеров ICMP в дефолтной security group или сетевом ACL не разрешён — сервер поднимается с закрытым входящим ICMP, и его надо отдельно открывать в панели или в правилах фильтрации на уровне гипервизора/сети, если такая возможность вообще предусмотрена. Если есть панель управления фильтрацией на сетевом уровне (а не только iptables внутри ОС) — начинайте проверку оттуда.
Фильтрация на промежуточной сети. Даже если и на сервере, и у вас ICMP разрешён, между вами могут стоять транзитные сети, корпоративные шлюзы или сети мобильных операторов, которые режут или сильно замедляют ICMP на своём участке — не из-за вашего сервера, а по собственной политике. ping при этом будет молчать, а TCP-соединение до того же адреса пройдёт штатно: фильтр настроен на ICMP, а не на IP-адрес целиком.
Важно отделить эти три случая от аварии: если ping не отвечает, а curl или telnet до нужного порта проходят нормально — это почти наверняка политика фильтрации ICMP, а не проблема с сервером или сетью. Если не отвечает вообще ничего — это уже другой разговор, требующий отдельной диагностики маршрута, а не только конечного узла.
TCP-замер задержки: то же самое, что ping, но через SYN
Раз ICMP недоступен, а нужна цифра, похожая на привычный ping (round-trip time до узла), самый прямой путь — замерить время установления TCP-соединения до открытого порта. Идея простая: клиент отправляет TCP SYN, сервер, если порт открыт и слушает, отвечает SYN-ACK — и время между этими двумя пакетами по сути та же задержка, что измеряет ICMP echo, только через протокол, который реально используется прикладными сервисами.
Специализированные утилиты вроде tcping (существует несколько независимых реализаций под разные ОС, включая версии для Linux и порт для Windows) делают ровно это и выводят результат в формате, привычном по ping:
tcping example.com 443
# Connected to example.com:443 (SYN), time=14.212ms
# Connected to example.com:443 (SYN), time=13.987ms
Если ставить сторонний бинарник не хочется или он недоступен в репозитории, тот же замер легко собрать из инструментов, которые почти наверняка уже есть на сервере:
Через nc (netcat) и time:
time nc -zv -w2 example.com 443
Флаг -z открывает и сразу закрывает соединение без передачи данных — по сути, тот же TCP-хендшейк-пинг, а time покажет, сколько это заняло.
Через bash без внешних утилит вообще, используя псевдоустройство /dev/tcp:
time (exec 3<>/dev/tcp/example.com/443) 2>&1
Способ грубый — точность на уровне десятков миллисекунд, а не микросекунд, — но он работает в голом bash без единой сторонней зависимости, что удобно на минимальном образе или внутри контейнера, где ничего лишнего не установлено.
Через nping из пакета nmap, если нужен именно ICMP-подобный вывод с несколькими пакетами подряд и статистикой:
nping --tcp -p 443 -c 5 example.com
nping умеет слать и TCP SYN, и UDP, и при желании даже сырой ICMP — универсальный инструмент для случаев, когда нужно явно контролировать, какой именно пакет уходит и на какой порт.
Общая идея у всех этих вариантов одна: вместо ICMP echo к самому хосту вы делаете TCP-хендшейк к конкретному порту сервиса — и получаете задержку, максимально близкую по смыслу к тому, что измеряет обычный ping, но без необходимости, чтобы ICMP вообще где-то по пути пропускался.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверHTTP/HTTPS-проверки: не просто задержка, а подтверждение работы сервиса
TCP-хендшейк отвечает на вопрос «порт открыт и что-то слушает», но не отвечает на вопрос «сервис за этим портом реально работает». Процесс может слушать порт 443, принимать TCP-соединение и при этом отдавать 500-ю ошибку на каждый запрос, зависнуть в бесконечном цикле или упереться в исчерпанный пул соединений к базе — TCP-проверка этого не увидит, а HTTP-проверка увидит сразу.
Базовый замер через curl с постатейным таймингом:
curl -o /dev/null -s -w \
"dns: %{time_namelookup}s connect: %{time_connect}s tls: %{time_appconnect}s ttfb: %{time_starttransfer}s total: %{time_total}s\n" \
https://example.com/health
Это раскладывает общее время запроса на этапы — DNS-резолв, TCP-хендшейк, TLS-рукопожатие, время до первого байта ответа (TTFB) и полное время. Если хочется получить только код ответа и общее время без лишнего вывода:
curl -o /dev/null -s -w "%{http_code} %{time_total}\n" https://example.com/health
Для реального мониторинга этого обычно мало — нужен не разовый вызов, а регулярная проверка с интерпретацией результата: код ответа должен быть ожидаемым (не любой 2xx, а именно тот, что означает «сервис действительно работоспособен»), и в идеале эндпоинт /health должен реально проверять зависимости сервиса — соединение с базой, доступность очереди, — а не просто отвечать 200 OK статикой из кода без единой проверки внутри. О том, как легко перепутать «эндпоинт отвечает» с «сервис работает», подробно разобрано в статье про health-чек, который зелёный, пока пользователи жалуются — там же разбор, каким должен быть содержательный health-check, а не просто пинг на уровне HTTP.
Именно поэтому HTTP/HTTPS-проверка в большинстве практических сценариев ценнее голого измерения задержки: она одновременно даёт и тайминг (аналог того, что раньше давал ping), и подтверждение, что прикладной уровень действительно отвечает — то есть закрывает сразу два вопроса одним запросом.
Специализированные утилиты и self-hosted мониторинг поверх TCP/UDP
Для разовой ручной проверки хватает curl и nc, но для постоянного мониторинга удобнее готовые инструменты, которые умеют опрашивать порт по расписанию, хранить историю и алертить при деградации.
Prometheus blackbox exporter — вероятно, самый гибкий self-hosted вариант: один экспортер умеет проверять по расписанию и TCP-порт (tcp_connect модуль — просто хендшейк без данных), и HTTP/HTTPS (http_2xx модуль — код ответа, TLS-сертификат, содержимое страницы), и при желании DNS. Конфиг для TCP-модуля выглядит так:
modules:
tcp_connect_443:
prober: tcp
timeout: 5s
tcp:
# опционально: TLS для проверки порта, где ожидается TLS-хендшейк
tls: false
Дальше Prometheus сам опрашивает экспортер по scrape_configs, а результат (успех/неуспех и время соединения, метрика probe_duration_seconds) уходит в общую базу метрик — ту же, где может храниться и мониторинг из нескольких региональных точек, если вы уже собираете проверки связности из нескольких городов.
Uptime Kuma и аналогичные панели обычно из коробки предлагают тип монитора «TCP Port» — указываете хост и порт, интервал и таймаут, панель сама шлёт TCP SYN и меряет время ответа, без необходимости писать что-то руками. Для HTTP тот же инструмент умеет проверять код ответа, содержимое страницы и срок действия TLS-сертификата отдельным типом монитора.
hping3 — более низкоуровневый инструмент, полезный, когда нужно явно контролировать флаги TCP-пакета (например, отправить именно SYN без завершения хендшейка, приближая нагрузку к тому, что видит сервис при реальном подключении) или собрать статистику по потерям и джиттеру на TCP-уровне, а не только среднюю задержку:
hping3 -S -p 443 -c 10 example.com
Выбор — вопрос масштаба: для разовой диагностики достаточно curl/nc/tcping, для постоянного мониторинга нескольких сервисов удобнее blackbox exporter или Uptime Kuma — они уже умеют расписание, историю и алерты, а не только единичный замер.
Почему TCP/HTTP точнее отражают реальный пользовательский опыт, чем ICMP
Здесь стоит зафиксировать главный тезис, а не только техническую механику. Реальный пользователь никогда не обращается к вашему серверу по ICMP — он открывает страницу по HTTPS, подключается к API по TCP, отправляет запрос к базе через её протокол. ICMP echo — это отдельный, параллельный канал, у которого на сетевом пути может быть совершенно другая судьба, чем у пользовательского трафика.
Три причины, почему ICMP может давать нерепрезентативную картину даже там, где он не заблокирован полностью:
- Приоритет обработки на маршрутизаторах. На многих сетевых устройствах ICMP обрабатывается управляющей плоскостью (control plane) процессора, а не быстрым трактом коммутации, которым идёт обычный транзитный трафик — TCP- и UDP-пакеты форвардятся аппаратно, а ICMP echo может обрабатываться медленнее, особенно под нагрузкой на устройстве. В результате задержка ICMP-ответа иногда выше, чем реальная задержка полезного трафика через тот же узел —
pingв такой ситуации не занижает, а завышает субъективное ощущение проблемы. - Rate-limiting как защита от злоупотреблений. Операционные системы и сетевое оборудование по общей практике ограничивают частоту генерации ICMP-ответов — защита от ICMP-flood и разведки сети. При частых замерах это проявляется как случайные потери в
ping, которых на самом деле нет в пользовательском TCP/HTTP-трафике: страница как грузилась стабильно, так и грузится, аping«теряет пакеты», просто уткнувшись в лимит. - Другой путь и другая политика QoS. Диагностический трафик может маршрутизироваться или классифицироваться иначе, чем прикладной — с более низким приоритетом в очередях, а иногда и по другому пути при дифференцированной обработке по типу протокола. Отсюда и картина, когда 100% потерь на промежуточном хопе в
mtrне значат ничего для реального трафика — подробнее в статье про то, как читать колонки mtr и не обвинить невиновный узел и в разборе конкретного случая 100% Loss при полностью рабочем сервисе.
Вывод простой и практический: ICMP — это метрика состояния диагностического канала, а не метрика состояния сервиса. Она полезна для грубой проверки «жив ли хост вообще», но как только вопрос ставится точнее — «доступен ли сервис пользователям и с какой задержкой они его получают», — единственный честный ответ даёт замер по тому же протоколу, по которому к сервису обращаются реальные пользователи.
Практическая рекомендация: что мониторить в первую очередь
Из всего разобранного следует конкретное правило для настройки мониторинга.
Основной сигнал доступности и задержки — TCP-хендшейк или HTTP-проверка конкретного порта/эндпоинта, а не ICMP ping, даже если ICMP на сервере разрешён и прекрасно отвечает. Причина не в том, что ICMP «плохой» инструмент, а в том, что он измеряет не то, что нужно: он говорит о состоянии диагностического канала, а не о том, ответит ли сервис на реальный запрос пользователя за приемлемое время.
Практическая раскладка по слоям, от грубого к точному:
| Что проверяете | Инструмент | Что узнаёте | Чего не узнаёте |
|---|---|---|---|
| Хост в сети вообще | ICMP ping | Узел отвечает на диагностический пакет | Слушает ли нужный порт, работает ли сервис |
| Порт открыт | tcping/nc -z/nping --tcp | TCP SYN доходит, порт слушает, RTT хендшейка | Отвечает ли приложение за портом корректно |
| Сервис отвечает | curl -w / HTTP health-check | Код ответа, TTFB, полное время, часто и состояние зависимостей | — |
Если приходится выбирать один уровень проверки для алертинга (а на старте почти всегда приходится), берите HTTP/HTTPS-проверку конкретного эндпоинта — она включает в себя факт того, что TCP тоже прошёл, и добавляет подтверждение прикладного уровня. ICMP имеет смысл держать как дополнительный сигнал: он дешёвый, не требует открытого порта приложения и полезен для грубой проверки «жив ли хост физически», когда HTTP уже недоступен.
Отдельно стоит проверить временны́е характеристики: если у сервиса есть жёсткие требования к задержке (торговые системы, realtime-игры, VoIP), одного среднего значения TCP-connect недостаточно — важнее стабильность серии замеров, чем красивое среднее по десятку пакетов, и та же логика без изменений переносится с ICMP-задержки на TCP-задержку.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли просто открыть ICMP на сервере и не заморачиваться с TCP/HTTP-проверками?
Технически можно, если политика безопасности это допускает, но это не решает исходную проблему: ICMP всё равно может быть заблокирован или иметь другой приоритет на промежуточных узлах вне вашего контроля, а главное — он не проверяет работоспособность самого сервиса. Даже при открытом ICMP разумно держать TCP/HTTP-проверку как основной сигнал.
tcping не установлен и ставить его нельзя — чем заменить?
Комбинацией nc -zv -w2 host port с time перед командой, либо трюком через bash /dev/tcp (time (exec 3<>/dev/tcp/host/port)), либо curl -o /dev/null -s -w "%{time_connect}\n" http://host:port/, если порт HTTP. Все три варианта не требуют установки ничего сверх стандартного набора утилит на большинстве Linux-дистрибутивов.
Почему TCP-хендшейк иногда медленнее, чем ICMP-ответ до того же узла?
Потому что установление TCP-соединения — более тяжёлая операция для сервера: нужно выделить сокет, пройти через стек приложения (если измеряете полное соединение, а не только SYN-ACK), тогда как ICMP echo реплицируется сетевым стеком ОС почти без участия приложения. Разница обычно небольшая и не означает проблему — это просто более честная цифра, ближе к тому, что почувствует реальный клиент.
Нужно ли вообще держать ICMP-мониторинг, если TCP/HTTP уже настроены?
Как основной сигнал — нет, не обязательно. Как дополнительный, дешёвый способ быстро отличить «сеть до хоста недоступна» от «сеть жива, но сервис за портом упал» — да, полезно, особенно при разборе инцидентов, когда нужно быстро локализовать уровень проблемы.
HTTP health-check вернул 200, но пользователи всё равно жалуются — в чём дело?
Скорее всего, эндпоинт проверяет не то, от чего реально зависит пользовательский сценарий — например, отвечает статикой без проверки соединения с базой или очередью. Это отдельная и частая проблема, которая разобрана в статье про health-check, зелёный при жалобах пользователей — там же практические примеры содержательных проверок.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →