MAATRIX / Блог / TCP-пинг до порта 443: почему цифры отличаются от ICMP и какой из них верить

TCP-пинг до порта 443: почему цифры отличаются от ICMP и какой из них верить

MAATRIX

Гоняете ping до сервера — 18 мс, всё стабильно. Рядом запускаете tcping или curl -w до того же хоста на 443 порт — и цифра другая: то выше на несколько миллисекунд, то ниже, то ICMP вовсе молчит, а TCP проходит без единой заминки. Первая реакция — один из двух замеров врёт. На самом деле оба говорят правду, просто про разные вещи: ICMP echo и TCP SYN до конкретного порта — это два разных пути через сеть и через сервер, и совпадение цифр было бы скорее совпадением, чем нормой.

ICMP ping и TCP-пинг измеряют не одно и то же

ping отправляет ICMP echo request и ждёт echo reply. Это протокол уровня IP — он не поднимается выше сетевого уровня, не знает о портах, не запускает никаких сервисов и не проходит через большую часть логики приложения. Пакет долетел до стека ядра на другой стороне — ядро сразу же, на максимально низком уровне, отправило ответ.

tcping (или nc -zv, или curl с параметром -w и таймингами) устанавливает настоящее TCP-соединение до конкретного порта: three-way handshake — SYN, SYN-ACK, ACK — и уже дальше, если это HTTP(S), может идти TLS handshake и сам HTTP-запрос. Это уровень транспорта (а для curl — ещё и уровень приложения), и на этом пути стоит на порядок больше логики: слушающий сокет, очередь backlog, правила файрвола именно для этого порта, а иногда и обработка на уровне веб-сервера или балансировщика.

Отсюда и вывод, который стоит держать в голове весь остальной текст: ping меряет "жив ли IP-адрес и отвечает ли ядро на ICMP", а tcping/curl -w меряет "доступен ли конкретный сервис на конкретном порту и сколько до него добираться". Это разные вопросы, и разные ответы на них — норма, а не повод для тревоги.

Приоритизация ICMP на маршрутизаторах: почему echo может быть медленнее

На магистральных и пограничных маршрутизаторах пересылка обычного транзитного трафика (в том числе TCP SYN до какого-то далёкого сервера) в большинстве случаев идёт через быстрый путь — ASIC или другую специализированную аппаратную логику коммутации, которая просто смотрит на таблицу маршрутизации и толкает пакет дальше, почти не тратя циклов CPU управляющей платы.

ICMP echo, адресованный самому маршрутизатору (а не транзитный ICMP, идущий сквозь него к другому хосту), — это другая история. Такой пакет часто обрабатывается на control plane, то есть на общем процессоре устройства, у которого гораздо более скромные ресурсы, чем у выделенной коммутационной матрицы, и который вдобавок занят маршрутными протоколами, SNMP, логированием и десятком других задач. Многие производители сетевого оборудования сознательно понижают приоритет обработки ICMP echo и трассировочных пакетов (TTL exceeded) на control plane — это защита от исчерпания ресурсов при флуде подобным трафиком, а не небрежность. В результате пинг именно до промежуточного узла в трассе может показывать задержку выше, чем реально добавляет этот узел транзитному трафику — эффект подробно разобран в статье про хоп со 100% потерь в трассировке: устройство отвечает на ICMP неохотно или с опозданием, а пакеты, которые просто идут через него дальше, обрабатывает штатно и быстро.

То же самое, только в меньшем масштабе, может происходить и на конечном сервере: если ICMP echo обрабатывается тем же ядром, что и TCP, но правило файрвола для ICMP стоит в другом месте цепочки или помечено с другим приоритетом — сравнение по миллисекундам между ICMP и TCP до одного и того же хоста перестаёт быть чистым экспериментом. Насколько именно велика эта разница — вопрос конкретного оборудования и конкретной сети; универсальных цифр здесь нет, и любые "средние по больнице" значения стоит воспринимать только как ориентир, а не как норматив.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Что добавляет TCP-рукопожатие на стороне сервера

Даже когда оба протокола не блокированы и оба доходят до сервера без проблем на маршруте, у TCP SYN путь обработки на конечной машине объективно длиннее, чем у ICMP echo.

ICMP echo reply нередко формируется на самом раннем этапе обработки в сетевом стеке ядра — фактически "не просыпая" остальную систему.

TCP SYN до порта 443 проходит заметно больше шагов:

  1. Пакет поднимается по сетевому стеку ОС до уровня, где ядро проверяет, есть ли слушающий сокет на этом порту.
  2. Если на сервере стоит файрвол (iptables/nftables, ufw, security group у облачного провайдера), пакет проходит цепочку правил — и правила для TCP обычно сложнее и длиннее, чем разрешение или запрет ICMP echo одной строкой. При большом числе правил это может добавлять заметную обработку.
  3. Ядро создаёт запись о полуоткрытом соединении в SYN-очереди (SYN backlog) и формирует SYN-ACK.
  4. Если порт слушает не голое ядро, а процесс за прокси или балансировщиком (nginx, HAProxy, облачный LB) — до самого TCP handshake или сразу после него в дело может вступать ещё один сетевой узел со своей собственной обработкой.
  5. Если замер идёт не голым TCP-коннектом, а через curl до https:// — сверху добавляется TLS handshake (обмен сертификатами, согласование шифров), который сам по себе может занимать больше времени, чем весь предыдущий путь.

Каждый из этих шагов добавляет какие-то доли миллисекунды или единицы миллисекунд обработки, которых у ICMP echo просто физически нет в конвейере. Поэтому TCP-пинг до открытого порта на нагруженном сервере или за балансировщиком почти всегда будет чуть выше, чем ICMP до того же IP, — и это ожидаемое поведение, а не деградация.

Когда ICMP заблокирован, а TCP проходит — сравнение по разным путям

Отдельная и, пожалуй, самая частая на практике причина расхождения — не разница в приоритетах обработки, а то, что ICMP и TCP до одного адреса физически идут по разным правилам фильтрации, а иногда и по разным маршрутам с точки зрения того, что вообще долетает до цели.

Типичная картина: ping до сервера отвечает Request timeout строка за строкой или показывает 100% потерь, а tcping/curl -w до 443 порта того же сервера отрабатывает штатно, с разумной задержкой. Причины разбираются подробно в статье ICMP запрещён: как измерять доступность без обычного пинга — коротко: ICMP echo часто режут намеренно, как часть ужесточения периметра на самом сервере, дефолтной политики облачного провайдера или фильтрации на промежуточной сети, тогда как открытый порт 443 остаётся доступен, потому что иначе сервис перестанет работать для реальных посетителей.

Важный практический вывод отсюда: если ICMP до хоста молчит, а TCP до порта отвечает, это не "расхождение цифр", которое нужно как-то согласовать между собой, — это два теста с разной судьбой на пути. Сравнивать их задержку в этом случае вообще некорректно: не с чем сравнивать, один из показателей отсутствует. Единственный валидный вывод в такой ситуации — TCP/HTTP замер, потому что он единственный вообще что-то говорит о доступности сервиса.

Как замерить оба варианта на практике

Ниже — минимальный набор команд, которого достаточно, чтобы получить оба числа и сравнить их осознанно, а не гадать.

Классический ICMP ping (Linux/macOS):

ping -c 10 example.com

TCP-пинг через tcping (нужно поставить отдельно — на разных дистрибутивах пакет называется по-разному, есть версии на Go и Python):

tcping example.com 443

То же самое без установки дополнительных утилит, через nc (замер грубый, без точных таймингов, но чтобы просто проверить, что порт открыт и отвечает):

time nc -zv example.com 443

Через curl с разбивкой по фазам соединения — самый информативный вариант, потому что показывает не только TCP-connect, но и TLS handshake, и время до первого байта ответа:

curl -o /dev/null -s -w \
  "connect: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\ntotal: %{time_total}s\n" \
  https://example.com:443/

time_connect здесь — это как раз честный аналог TCP-пинга: время от начала соединения до завершения TCP-рукопожатия, без TLS и без ожидания ответа приложения. Если хочется сопоставить именно с ICMP — сравнивайте ping со значением time_connect, а не с time_total, иначе в сравнение подмешается TLS и время работы сервера, разбор которого отдельно есть в статье про TTFB 800 мс при пинге 20 мс.

Трассировка по TCP вместо ICMP, если нужно понять маршрут именно для трафика на 443, а не для ICMP: в mtr есть режим TCP, который отправляет TCP SYN на каждый хоп вместо ICMP echo — это меняет картину трассы, если где-то по пути ICMP режется избирательно:

mtr --tcp -P 443 example.com

Про то, как вообще читать колонки в выводе mtr (Loss%, Avg, StDev), — отдельная статья MTR вместо traceroute: как читать колонки.

Как трактовать расхождение: несколько типичных сценариев

Ниже — таблица с сочетаниями, которые встречаются на практике чаще всего, и что каждое из них обычно означает. Числа условные — важна логика, а не конкретные миллисекунды, которые у вас неизбежно будут своими.

ICMP pingTCP-пинг до 443Вероятная причинаЧто делать
Отвечает, задержка низкаяОтвечает, задержка чуть выше (обычно на единицы мс)Нормальная разница в глубине обработки — TCP handshake длиннее ICMP echoНичего, это ожидаемо
Не отвечает вовсе (timeout)Отвечает нормальноICMP заблокирован на сервере, у провайдера или на промежуточной сети; порт при этом открытОриентируйтесь на TCP-замер, ICMP тут неинформативен
ОтвечаетНе отвечает / connection refusedПорт закрыт или занят другим процессом, либо файрвол режет именно TCP на этот портПроверить, слушает ли сервис порт (ss -tlnp), и правила файрвола для порта
Задержка ICMP заметно скачет (джиттер)Задержка TCP стабильнаICMP echo на промежуточных узлах обрабатывается с низким и непостоянным приоритетом на control planeДоверяйте TCP-цифре как более показательной для сервиса
Оба замера стабильно расходятся на десятки мсСкорее всего TCP идёт через дополнительный узел на пути — балансировщик, прокси, WAFСравнить путь traceroute/mtr в обычном режиме и в --tcp режиме

Если видите джиттер именно в ICMP-замерах при том, что TCP стабилен, — это отдельная тема: нестабильность метрики сама по себе может быть свойством конкретно этого протокола замера, а не сети целиком.

Какому из двух верить: практический вывод

Если цель — понять, что реально ощущает пользователь, открывающий ваш сайт или API на 443 порту, TCP/HTTP-замер точнее отражает действительность, чем ICMP, по одной простой причине: реальные пользователи не отправляют ICMP echo. Браузер, мобильное приложение, сторонний API-клиент — все они устанавливают TCP-соединение, чаще всего поверх него ещё TLS, и уже затем идёт HTTP-запрос. Задержка, которую видит пользователь, гораздо ближе к тому, что покажет curl -w или tcping до 443, чем к тому, что покажет обычный ping.

Но это не значит, что ICMP бесполезен и его стоит выбросить из инструментария. У него есть то, чего нет у TCP-пинга: он не зависит от того, какой сервис слушает порт, не требует открытого 443-го, и по нему удобно смотреть маршрут по хопам (traceroute, mtr в обычном режиме) без риска упереться в закрытый порт где-то на промежуточном узле. Для быстрой проверки "жив ли хост вообще" на инфраструктурном уровне ICMP по-прежнему рабочий и лёгкий инструмент — если он не заблокирован по пути.

Практическая рекомендация: используйте оба замера как взаимодополняющие, а не выбирайте один как «более правильный» в абсолюте.

  • ICMP ping/mtr — для быстрой проверки доступности хоста и грубой оценки маршрута, когда не важен конкретный сервис.
  • TCP-пинг (tcping, nc -zv) — когда нужно знать, отвечает ли именно интересующий порт, независимо от того, разрешён ли ICMP.
  • curl -w с разбивкой по фазам — когда нужно понять, где именно уходит время: в сети (time_connect), в TLS (time_appconnect) или на сервере (time_starttransfer минус time_appconnect).
  • mtr --tcp -P <порт> — когда обычный ICMP-mtr показывает подозрительную картину, а нужно понять маршрут именно для трафика на нужный порт.

Если после сравнения расхождение остаётся необъяснимым — не полагайтесь на итоговое число, а смотрите на конкретный шаг: time_connect в curl -w отделяет чистый TCP-хендшейк от TLS и ответа приложения, а сравнение mtr в обычном и в --tcp режиме отделяет "маршрут в принципе" от "маршрут для конкретного порта". Это надёжнее, чем спорить, какое из двух итоговых чисел «настоящее».

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему TCP-пинг иногда показывает меньшую задержку, чем ICMP, а не только большую?

Если на промежуточном маршрутизаторе ICMP echo обрабатывается на нагруженном control plane с низким приоритетом, а транзитный TCP-трафик через тот же узел идёт по быстрому аппаратному пути, ICMP может оказаться медленнее TCP, хотя интуитивно кажется, что должно быть наоборот — ICMP же "проще".

Можно ли вообще не мерить ICMP и полагаться только на TCP-пинг?

Можно, если единственная цель — состояние конкретного сервиса на конкретном порту. Но для диагностики маршрута (где именно на пути растёт задержка) ICMP-инструменты вроде mtr без --tcp часто удобнее и не требуют открытого порта на каждом промежуточном узле — хотя mtr --tcp тоже смотрит только на финальную цель, а не на промежуточные хопы по TCP.

Разница в 1-3 мс между ICMP и TCP — это повод разбираться?

Обычно нет. Такая разница укладывается в нормальную стоимость дополнительной обработки TCP-рукопожатия на сервере и не говорит о проблеме. Поводом для разбора стоит считать разницу в десятки миллисекунд или нестабильность (то одно значение, то совсем другое при повторных замерах).

curl -w до 443 без TLS (http:// вместо https://) даст более честное сравнение с ICMP?

Да, ближе, потому что убирает время TLS handshake из уравнения — time_connect в этом случае будет практически чистым TCP three-way handshake. Но учтите, что на многих серверах порт 80 либо не слушает вовсе, либо сразу отдаёт редирект на HTTPS, так что для реального замера порта 443 полезнее смотреть time_connect именно в запросе к https://, просто отдельно от time_appconnect.

Что делать, если и ICMP, и TCP-пинг показывают стабильно высокую задержку одновременно?

Это уже не про расхождение протоколов, а про реальную сетевую задержку до хоста — начните с методичного замера через несколько разных точек, а не с сравнения ICMP и TCP между собой.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →