MAATRIX / Блог / Что такое ARP и почему сервер иногда «теряет» соседа в той же сети

Что такое ARP и почему сервер иногда «теряет» соседа в той же сети

MAATRIX

Два сервера сидят в одной подсети, пинг между ними обычно укладывается в доли миллисекунды — а потом вдруг несколько секунд пакеты просто не доходят, хотя кабели на месте, свитч не перезагружался и маршрутизация не менялась. Чаще всего виноват не сбой сети, а протокол, о существовании которого вспоминают только в такие моменты — ARP. Разбираемся, как он работает, зачем кеширует ответы и почему эта же экономия иногда оборачивается временной «слепотой» к соседу.

Зачем вообще нужен ARP

IP-адрес — это адрес в логике маршрутизации, а не в логике физической доставки. Когда пакет уже добрался до нужной локальной сети (Ethernet-сегмента, VLAN, моста в гипервизоре), доставить его до конкретного устройства можно только по MAC-адресу — это адрес уровня канала, который понимает сетевая карта и коммутатор. IP-адрес говорит «куда», MAC-адрес говорит «какой физический порт свитча открыть».

ARP (Address Resolution Protocol) — это как раз механизм перевода «IP соседа в той же сети» в «MAC-адрес соседа». Работает предельно просто:

  1. Сервер А хочет отправить пакет серверу Б, чей IP он знает, а MAC — нет.
  2. А рассылает широковещательный ARP-запрос: «кто здесь 10.0.0.5, откликнись своим MAC-адресом» — этот запрос видят все устройства в сегменте.
  3. Только Б узнаёт себя и отвечает уже адресно: «10.0.0.5 — это я, вот мой MAC».
  4. А запоминает пару IP-MAC и с этого момента отправляет кадры сразу на нужный MAC, не спрашивая заново.

Проверить это можно на любом Linux-сервере:

ip neigh show
# 10.0.0.5 dev eth0 lladdr 52:54:00:1a:2b:3c REACHABLE
# 10.0.0.1 dev eth0 lladdr 52:54:00:9f:11:02 STALE

Команда arp -n делает то же самое в старом формате вывода (пакет net-tools, на современных дистрибутивах его чаще нет по умолчанию, ip neigh — актуальный аналог из iproute2). Важная деталь: ARP работает только внутри одного L2-сегмента. Как только пакету нужно попасть за пределы локальной сети, в дело вступает маршрутизация, а не ARP — про то, как устроен путь пакета за пределами сегмента, мы отдельно разбирали в статье про то, как виртуалка живёт с чужим временем после переезда, где похожая логика «старых данных, которые ещё не успели обновиться» приводит к неожиданным эффектам совсем в другой области.

Почему ответы кешируются, а не спрашиваются заново

Слать широковещательный ARP-запрос перед каждым пакетом было бы расточительно: лишняя нагрузка на сеть, лишняя задержка, лишняя работа для каждого устройства в сегменте, которое обязано разобрать broadcast-кадр и решить, что он не для него. Поэтому результат ARP-запроса кешируется — на сервере это называется ARP-таблицей или, в терминологии ядра Linux, neighbor cache (или neighbor table).

Запись в этой таблице живёт не вечно. У неё есть свой жизненный цикл, который в Linux управляется набором таймеров и переходит через несколько состояний:

  • REACHABLE — запись свежая, недавно подтверждена (либо ARP-ответом, либо тем, что по этому MAC уже прошёл подтверждённый трафик, например TCP ACK). Пакеты уходят сразу, без дополнительных проверок.
  • STALE — запись «протухла» по таймеру, но ядро её не удаляет, а продолжает ею пользоваться: пакеты по-прежнему уходят на этот MAC, но при первой возможности запись будет тихо перепроверена.
  • DELAY / PROBE — ядро решило перепроверить запись и либо ждёт, не подтвердит ли её обычный трафик, либо уже само отправляет ARP-запрос заново.
  • FAILED — сосед не откликнулся, запись помечается неработающей, до следующей попытки трафик к этому IP не пойдёт.

В Linux за это отвечают sysctl-параметры вроде net.ipv4.neigh.default.base_reachable_time_ms (сколько запись считается точно свежей) и net.ipv4.neigh.default.gc_stale_time (через сколько ядро начинает фоново перепроверять устаревшие записи). Конкретные значения по умолчанию отличаются между дистрибутивами и версиями ядра, но сама идея одна: свежий ответ используется без вопросов, устаревший — используется, но с оглядкой, а не выбрасывается сразу.

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

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

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

Момент, когда кеш начинает врать

Вот тут и кроется источник тех самых загадочных «потерь соседа». ARP-таблица хранит пару «IP → MAC» и считает её актуальной, пока не наступит время перепроверки. Но что если за это время у соседа сменился MAC-адрес, а IP остался прежним?

Это происходит чаще, чем кажется:

  • Живая миграция виртуальной машины на другой физический хост — гостевая ОС и её IP-адрес не меняются, но виртуальный сетевой интерфейс теперь физически подключён через другую сетевую карту (или через тот же мост, но на другом хосте), и его MAC-адрес меняется — либо потому что сменилась виртуальная NIC, либо потому что на новом хосте её пересоздал гипервизор. Мы разбирали смежный сценарий с миграцией между гипервизорами — там источником сюрприза было время, здесь тем же механизмом «старые данные ещё не протухли» может стать именно ARP-кеш соседей.
  • Замена сетевой карты на физическом сервере — IP-адрес перевесили на новое оборудование, а MAC у новой карты, разумеется, другой (MAC уникален для конкретного физического или виртуального адаптера).
  • Failover / переключение на резервный узел — виртуальный IP (VIP) поднимается на другом сервере кластера, соответственно, соседям, которые продолжают слать пакеты на VIP, нужно узнать новый MAC.
  • Изменение топологии моста в гипервизоре — например, после правок в конфигурации Proxmox виртуалка оказывается подключена к сети через другой bridge или физический интерфейс; о похожих граблях с сетью внутри гипервизора мы писали в материале про мосты и VLAN в Proxmox.

Во всех этих случаях остальные устройства сегмента продолжают слать пакеты по старому MAC-адресу — потому что их ARP-кеш ещё не знает о смене. Свитч честно доставляет кадры туда, куда его научила его собственная таблица коммутации (CAM-таблица) — то есть либо в порт, где раньше был этот MAC (и там теперь либо тишина, либо не тот адресат), либо кадр просто теряется, если свитч этот MAC уже не помнит. Снаружи это выглядит именно как «сервер пропал»: ping не идёт, TCP-соединения подвисают, хотя сам сосед прекрасно жив и отвечает — просто не по тому физическому пути, куда его всё ещё пытаются найти.

Как кеш обновляется сам, без вмешательства

Хорошая новость в том, что ситуация не постоянная. Устаревшая запись рано или поздно перепроверяется — это заложено в тот самый жизненный цикл REACHABLE → STALE → DELAY/PROBE, который был описан выше. Как только ядро решает, что запись пора подтвердить, оно отправляет свежий ARP-запрос — и получает актуальный ответ от соседа, если тот вообще ещё существует по этому IP.

Именно поэтому проблема «потери соседа» после смены железа почти всегда носит временный характер: пока не истечёт таймер устаревания записи и не пройдёт цикл перепроверки, часть трафика может идти в никуда или с задержками, а после — восстанавливается само, без какого-либо вмешательства администратора. Со стороны это выглядит как «сеть на несколько секунд подглючила и сама прошла» — и в большинстве случаев это ровно то, что произошло: не сбой инфраструктуры, а штатное, просто не мгновенное, обновление ARP-кеша у соседей.

Проблема в том, что «рано или поздно» — не то же самое, что «мгновенно». Пока конкретный узел не попытается перепроверить запись (а он может не спешить, если трафика к этому IP в моменте не было), он продолжает считать старый MAC действующим. Для интерактивных соединений (SSH-сессия, TCP с открытым окном, реплика базы) эти несколько секунд простоя иногда чувствительны — соединение может решить, что канал недоступен, и начать пересборку с нуля.

Gratuitous ARP: способ обновить соседей самому, не дожидаясь таймера

Ждать, пока каждый сосед сам решит перепроверить свою запись, не всегда приемлемо — особенно если смена MAC-адреса была плановой и предсказуемой операцией, а не аварией. Для этого существует механизм gratuitous ARP (буквально — «безвозмездный», непрошеный ARP).

Это ARP-пакет, который узел рассылает не в ответ на чей-то запрос, а по собственной инициативе — как правило, сразу после того, как у него появился новый IP или изменился MAC-адрес, связанный с уже существующим IP. Формально это ARP-запрос, в котором узел спрашивает сам себя («кто владеет вот этим IP?») и одновременно объявляет всем в сегменте: «этот IP теперь у меня, вот мой MAC». Устройства, которые получают такой пакет, обновляют свою ARP-таблицу немедленно, не дожидаясь истечения таймера — потому что явное объявление считается более надёжным сигналом, чем молчаливое ожидание протухания кеша.

Именно gratuitous ARP используют:

  • VRRP/keepalived — при переключении VIP на резервный узел новый владелец сразу же рассылает gratuitous ARP, чтобы соседи как можно быстрее узнали новый MAC и не ждали устаревания кеша.
  • Гипервизоры при живой миграции — после переезда виртуальной машины на новый физический хост гипервизор (libvirt/QEMU, VMware и аналоги) обычно сам отправляет несколько gratuitous ARP-пакетов от имени гостевой ОС, чтобы ускорить обновление кеша у соседей и свитча.
  • Ручное восстановление после смены оборудования — если по какой-то причине автоматика не сработала, обновить соседей можно вручную.

Отправить gratuitous ARP из Linux можно утилитой arping (пакет iputils-arping или arping, в зависимости от дистрибутива):

arping -U -I eth0 10.0.0.5

Флаг -U (unsolicited) как раз и означает «непрошеный», то есть gratuitous ARP-запрос с текущим IP и MAC интерфейса eth0. Полезно повторить его несколько раз с небольшой паузой — единичный broadcast-кадр в реальной сети иногда теряется, как и любой другой кадр.

Практические следствия для инфраструктуры

Из механики ARP-кеша вытекает несколько вещей, полезных на практике:

  • «Потеря соседа» после переезда — это не всегда повод паниковать. Если после живой миграции, замены железа или failover’а вы видите несколько секунд недоступности между узлами одного L2-сегмента, а затем всё само восстанавливается — это, скорее всего, штатное поведение ARP-кеша, а не признак сбоя в приложении.
  • Свитч тоже кеширует, и его таблица коммутации живёт по своим правилам. Даже если ARP-кеш соседа уже обновился, свитч может какое-то время слать кадры не в тот порт, пока его собственная таблица MAC-адресов (CAM-таблица) не переучится — обычно это происходит автоматически, как только через новый порт проходит кадр с этим MAC-адресом в качестве источника, но задержка тут отдельная от ARP.
  • Диагностировать проблему можно быстро и без гаданий. Первый шаг — посмотреть текущее состояние таблицы соседей:
ip neigh show

Если для нужного IP запись висит в состоянии FAILED или указывает на MAC, который явно не совпадает с ожидаемым (например, вы знаете актуальный MAC новой сетевой карты) — это прямое подтверждение проблемы. Принудительно очистить конкретную запись или всю таблицу:

ip neigh flush dev eth0

После этого следующий пакет к соседу заново запустит цикл ARP-запроса — если сосед реально доступен по новому MAC, соединение восстановится сразу.

  • Смотреть сам трафик ARP полезно, когда неясно, кто врёт — кеш локальной машины, свитч или сам сосед. tcpdump с фильтром на ARP покажет, кто и что отвечает в сегменте прямо сейчас:
tcpdump -i eth0 -n arp

Если на широковещательный запрос «кто такой 10.0.0.5» отвечают два разных MAC-адреса — это уже не проблема кеша, а конфликт IP-адресов в сети (например, забыли выключить старую копию сервера с тем же IP), и лечится это иначе, чем протухший кеш.

  • Уменьшать время жизни ARP-записей ради «подстраховки» — сомнительная идея. Более короткий таймер означает более частые ARP-запросы на каждый IP, с которым идёт обмен трафиком, то есть дополнительная broadcast-нагрузка на сегмент. В плотных сетях с большим числом соседей это может создать больше проблем, чем решить. Разумнее полагаться на gratuitous ARP при плановых операциях и на понимание того, что при внеплановых переключениях несколько секунд неполной доступности — ожидаемая цена, а не баг.
  • В отказоустойчивых схемах (VRRP, keepalived, кластерный VIP) стоит явно проверить, что gratuitous ARP реально отправляется после переключения — это можно увидеть тем же tcpdump -n arp на узле, который принял VIP. Если пакетов нет, соседи будут ждать истечения своего таймера, и переключение, которое задумывалось как быстрое, на деле растянется на секунды простоя там, где их не должно быть.

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

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

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

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

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

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

ARP работает только в IPv4-сетях?

Да, ARP — протокол именно для IPv4. В IPv6 аналогичную задачу — сопоставление IP-адреса и MAC-адреса — решает NDP (Neighbor Discovery Protocol), который устроен иначе (использует ICMPv6), но логика с кешем соседей и его устареванием там очень похожая.

Почему ping до соседа то работает, то нет, хотя IP точно правильный?

Классический симптом устаревшей или конфликтующей ARP-записи. Проверьте ip neigh show для этого IP и сравните MAC с тем, что реально должен быть у устройства (например, посмотрите его через ip link show на самом сервере-соседе). Если MAC не совпадает — запись устарела, если запросом tcpdump -n arp находится два разных ответчика — на IP отвечают два устройства одновременно.

Нужно ли вручную чистить ARP-кеш после каждой миграции виртуалки?

Обычно нет — современные гипервизоры сами рассылают gratuitous ARP после живой миграции. Ручная чистка (ip neigh flush) нужна, если вы наблюдаете зависшие соединения дольше, чем ожидали, и хотите принудительно заставить систему перепроверить конкретную запись, не дожидаясь таймера.

ARP и NAT — это связанные вещи?

Нет, это механизмы разных уровней: ARP работает внутри одного L2-сегмента и сопоставляет IP с MAC, а NAT подменяет сами IP-адреса при прохождении трафика между сетями, обычно на границе с внешним миром. Про то, как устроен NAT и почему из-за него устройства иногда «не видят» друг друга, у нас есть отдельный разбор — как работает NAT.

Что делать, если проблема с ARP регулярно повторяется на одном и том же сервере, а не только при миграциях?

Это уже повод проверить сеть глубже: дублирующиеся MAC-адреса при клонировании виртуалок из шаблона без сброса сетевого адреса, нестабильный аплинк, который заставляет свитч постоянно переучивать таблицу коммутации, или неправильно настроенный bonding/failover сетевых интерфейсов на самом сервере.

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

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

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