Введение: когда ARP-таблица превращается в помойку
Приветствую, коллеги! За 15 лет работы системным администратором я повидал немало «чудес» в сетевой инфраструктуре. Но особое место в моем сердце (и в списке ночных кошмаров) занимают замусоренные ARP-таблицы на MikroTik. Если вы когда-нибудь наблюдали, как ваш роутер медленно превращается в цифровой аналог накопителя, который не может выбросить старые газеты — эта статья для вас.
Проблема проста: устройства в сети постоянно меняются, получают новые IP-адреса, отключаются, но их ARP-записи продолжают жить своей жизнью, как зомби в плохом фильме категории B. Результат? Конфликты адресов, пакеты, улетающие в никуда, и загадочные проблемы с подключением, которые заставляют пользователей думать, что интернет сломался именно из-за них.
Что такое ARP и почему он может испортить вам день
ARP (Address Resolution Protocol) — это протокол, который связывает IP-адреса с MAC-адресами в локальной сети. Представьте, что это телефонная книга вашей сети: вы знаете имя (IP-адрес), но вам нужен номер телефона (MAC-адрес), чтобы позвонить.
Проблема начинается, когда в этой телефонной книге накапливаются записи типа:
- Устройства, которых уже нет в сети
- Дублированные записи с одинаковыми IP, но разными MAC
- Статические записи, которые кто-то добавил в 2015 году и забыл
- Записи с истекшим сроком действия, которые почему-то не удалились
На MikroTik эта проблема особенно актуальна в сетях с DHCP, где устройства постоянно подключаются и отключаются. Без автоматической очистки ARP-таблица раздувается быстрее, чем ваша коллекция неиспользуемых Docker-образов.
Скрипт автоматической очистки ARP-таблицы
Хватит теории, переходим к практике. Я разработал скрипт, который автоматически находит и удаляет проблемные ARP-записи. Этот скрипт проверяет доступность устройств и удаляет записи для недоступных хостов.
Базовый скрипт очистки:
# Скрипт удаления неактивных ARP записей
:log info "Запуск очистки ARP-таблицы"
:local arpCount 0
:local removedCount 0
# Получаем все динамические ARP записи
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local arpMAC [/ip arp get $arpEntry mac-address]
:set arpCount ($arpCount + 1)
# Пингуем адрес (1 пакет, таймаут 1 секунда)
:local pingResult [/ping $arpIP count=1 timeout=1s]
# Если хост не отвечает - удаляем запись
:if ($pingResult = 0) do={
:log warning "Удаляем неактивную ARP запись: $arpIP ($arpMAC)"
/ip arp remove $arpEntry
:set removedCount ($removedCount + 1)
}
}
:log info "Проверено записей: $arpCount, удалено: $removedCount"
Пять практических примеров для разных сценариев
Пример 1: Очистка с исключением критичных устройств
В реальной сети у вас есть критичные устройства (серверы, принтеры, камеры), которые могут временно не отвечать на пинг, но их ARP-записи удалять нельзя. Добавим белый список:
# Скрипт с исключениями для критичных устройств
:local excludeIPs {"192.168.1.1"; "192.168.1.10"; "192.168.1.20"}
:local removedCount 0
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local skip false
# Проверяем, не в белом ли списке IP
:foreach excludeIP in=$excludeIPs do={
:if ($arpIP = $excludeIP) do={
:set skip true
}
}
:if (!$skip) do={
:local pingResult [/ping $arpIP count=1 timeout=1s]
:if ($pingResult = 0) do={
:log warning "Удаляем: $arpIP"
/ip arp remove $arpEntry
:set removedCount ($removedCount + 1)
}
} else={
:log info "Пропускаем критичный IP: $arpIP"
}
}
:log info "Удалено записей: $removedCount"
Пример 2: Очистка только старых записей
Иногда устройство может быть временно недоступно (перезагрузка, обновление). Этот скрипт удаляет только записи старше определенного времени:
# Удаление записей старше 30 минут
:local maxAge 00:30:00
:local removedCount 0
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local arpAge [/ip arp get $arpEntry age]
# Проверяем возраст записи
:if ($arpAge > $maxAge) do={
:local pingResult [/ping $arpIP count=2 timeout=2s]
:if ($pingResult = 0) do={
:log warning "Удаляем старую запись ($arpAge): $arpIP"
/ip arp remove $arpEntry
:set removedCount ($removedCount + 1)
}
}
}
:log info "Удалено устаревших записей: $removedCount"
Пример 3: Очистка дублированных записей
Настоящий кошмар — когда один IP-адрес имеет несколько MAC-адресов в таблице. Это почти всегда признак проблемы (IP-конфликт, спуфинг, или просто хаос):
# Поиск и удаление дублей IP с разными MAC
:local ipArray [:toarray ""]
:local duplicates 0
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local arpMAC [/ip arp get $arpEntry mac-address]
# Ищем другие записи с тем же IP
:local sameIP [/ip arp find address=$arpIP dynamic=yes]
:if ([:len $sameIP] > 1) do={
:log error "Дубликат обнаружен! IP: $arpIP имеет несколько MAC"
# Удаляем все записи кроме самой свежей
:local newestEntry [/ip arp find address=$arpIP dynamic=yes]
:local newestAge "99:99:99"
:local keepEntry ""
:foreach entry in=$newestEntry do={
:local entryAge [/ip arp get $entry age]
:if ($entryAge < $newestAge) do={
:set newestAge $entryAge
:set keepEntry $entry
}
}
# Удаляем старые дубликаты
:foreach entry in=$newestEntry do={
:if ($entry != $keepEntry) do={
:log warning "Удаляем дубликат: $arpIP"
/ip arp remove $entry
:set duplicates ($duplicates + 1)
}
}
}
}
:log info "Удалено дубликатов: $duplicates"
Пример 4: Очистка по расписанию с уведомлениями
Автоматизация — наше всё. Этот скрипт можно запускать по расписанию и получать отчеты в Telegram или по email:
# Скрипт с детальной статистикой для отчетов
:local startTime [/system clock get time]
:local totalARP 0
:local activeARP 0
:local removedARP 0
:local report ""
:set totalARP [:len [/ip arp find dynamic=yes]]
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local arpMAC [/ip arp get $arpEntry mac-address]
:local pingResult [/ping $arpIP count=1 timeout=1s]
:if ($pingResult > 0) do={
:set activeARP ($activeARP + 1)
} else={
/ip arp remove $arpEntry
:set removedARP ($removedARP + 1)
:set report ($report . "$arpIP ($arpMAC)\n")
}
}
:local endTime [/system clock get time]
# Формируем отчет
:log info "=== Отчет очистки ARP ==="
:log info "Время выполнения: с $startTime до $endTime"
:log info "Всего записей: $totalARP"
:log info "Активных: $activeARP"
:log info "Удалено: $removedARP"
:if ($removedARP > 0) do={
:log warning "Удаленные записи:\n$report"
}
# Здесь можно добавить отправку в Telegram/Email
# /tool fetch url="https://api.telegram.org/bot<TOKEN>/sendMessage..."
Пример 5: Умная очистка с проверкой DHCP
Самый продвинутый вариант: проверяем, есть ли у IP-адреса активная DHCP-аренда. Если нет и хост не отвечает — записи точно нужно удалить:
# Очистка с проверкой DHCP-аренд
:local removedCount 0
:local dhcpMismatch 0
:foreach arpEntry in=[/ip arp find dynamic=yes] do={
:local arpIP [/ip arp get $arpEntry address]
:local arpMAC [/ip arp get $arpEntry mac-address]
:local hasLease false
# Проверяем наличие активной DHCP-аренды
:foreach lease in=[/ip dhcp-server lease find address=$arpIP] do={
:local leaseMAC [/ip dhcp-server lease get $lease mac-address]
:if ($leaseMAC = $arpMAC) do={
:set hasLease true
} else={
:log error "MAC не совпадает! ARP: $arpMAC, DHCP: $leaseMAC для IP $arpIP"
:set dhcpMismatch ($dhcpMismatch + 1)
}
}
# Если нет аренды - проверяем доступность
:if (!$hasLease) do={
:local pingResult [/ping $arpIP count=2 timeout=2s]
:if ($pingResult = 0) do={
:log warning "Нет DHCP-аренды и хост не отвечает: $arpIP ($arpMAC)"
/ip arp remove $arpEntry
:set removedCount ($removedCount + 1)
} else={
:log info "Хост $arpIP активен, но без DHCP-аренды (статический IP?)"
}
}
}
:log info "Удалено: $removedCount | Несоответствий MAC: $dhcpMismatch"
Настройка автоматического запуска
Создаем скрипт в System → Scripts и добавляем расписание:
# Создание задачи в планировщике /system scheduler add \ name="arp-cleanup" \ start-time=03:00:00 \ interval=24h \ on-event="/system script run arp-cleanup-script"
Я рекомендую запускать очистку ночью (3-4 часа утра), когда сетевая активность минимальна. Частота зависит от размера сети:
- Маленькая сеть (до 50 устройств) — раз в неделю
- Средняя сеть (50-200 устройств) — каждые 2-3 дня
- Большая сеть (200+ устройств) — ежедневно
Мониторинг и отладка
Чтобы понять, работает ли скрипт правильно, используйте логи:
# Просмотр логов выполнения скрипта /log print where topics~"script" # Просмотр текущего состояния ARP-таблицы /ip arp print where dynamic=yes # Статистика по возрасту записей /ip arp print stats
Типичные ошибки и как их избежать
Ошибка 1: Слишком агрессивная очистка. Если таймаут пинга слишком короткий (менее 1 секунды), можно удалить записи нормально работающих, но медленно отвечающих устройств.
Решение: Используйте count=2 и timeout=2s для более надежной проверки.
Ошибка 2: Удаление статических записей. Некоторые устройства требуют статических ARP-записей для безопасности.
Решение: Всегда фильтруйте по dynamic=yes в скрипте.
Ошибка 3: Запуск скрипта в часы пик. Массовый пинг всей сети может создать дополнительную нагрузку.
Решение: Планируйте выполнение на ночные часы или выходные.
Заключение: спокойная сеть — счастливый админ
За годы работы я понял одну простую истину: лучшие решения — это те, о которых не нужно помнить. Настроив автоматическую очистку ARP-таблицы, вы забудете о целом классе проблем. Пользователи перестанут жаловаться на «странные глюки с сетью», а вы сможете спокойно пить кофе, вместо того чтобы вручную разбираться с конфликтами адресов.
Помните: сеть, как и код, требует регулярной гигиены. Неочищенная ARP-таблица — это техдолг, который рано или поздно потребует оплаты. И лучше заплатить сейчас временем на настройку автоматизации, чем потом — нервными клетками во время аврала.
Используйте эти скрипты, адаптируйте под свои нужды, и пусть ваши MikroTik‘и работают как швейцарские часы. А если что-то пойдет не так — всегда можно откатиться к бэкапу. У вас же есть бэкапы, правда? Правда?



