0887 371 498 support@itservice-bg.net
Незаетите публични адреси пълнят LAN-а с ARP: как се спира в RAW
13.11.2026 · Самуил Арсов · MikroTik, Рутери

Незаетите публични адреси пълнят LAN-а с ARP: как се спира в RAW

Повечето хора мислят, че незает публичен адрес е просто „празно място“ в мрежата. Никой не го ползва, значи и трафик към него няма. Не е така. Ако адресът е от мрежа, която рутерът ти държи директно в LAN-а, всеки пакет от интернет към него влиза навътре. Рутерът няма как да знае, че адресът е свободен, и прави единственото, което може: пита целия LAN кой е собственикът.

Ето как го видяхме на живо, какво струва и с едно RAW правило на мрежа как се спира.

Казусът

Мрежата е доставчик в няколко села. Публичните /24 мрежи са конфигурирани директно на LAN интерфейсите на рутерите. Отдолу е едно L2 ядро с над 2000 устройства: суичове, EPON OLT-та и безжични сектори до клиентите. Поводът за одита беше ICMP флуд между двама абонати, който удари и съседите им. Докато търсехме защо, погледнахме колко broadcast стига до всеки порт на ядрото.

Отговорът беше около 200 пакета в секунда, постоянно, на всеки порт надолу. Денем и нощем, без значение от натоварването. По обем е малко, но е шум, който никой не беше поръчвал.

Механизмът

Да вземем, че на рутера е зададено 203.0.113.1/24 на LAN интерфейса и от 254 адреса са раздадени 200. Някъде в интернет скенер (Shodan, Censys, поредният ботнет) обикаля всеки IPv4 адрес подред. Стига до 203.0.113.57, който не е на никого:

  1. Пакетът идва по BGP или по default маршрута до твоя рутер. Всичко е нормално, мрежата е твоя и е анонсирана.
  2. Рутерът вижда, че 203.0.113.0/24 е connected. Значи трябва да го достави директно, на L2.
  3. За това му трябва MAC адрес. Няма го в ARP таблицата и затова праща ARP who-has 203.0.113.57 като broadcast.
  4. Суичът разлива broadcast-а на всеки порт: към всеки суич надолу, всяко OLT, всеки безжичен сектор и всеки клиентски рутер.
  5. Никой не отговаря. Записът остава failed, рутерът опитва отново, а скенерът вече праща към .58, .59…

Рутерът е длъжен да пита. Той не знае кой адрес е зает. Знае само, че мрежата е негова. Затова всеки скенер, който мине през твоите префикси, на практика генерира broadcast във всеки ъгъл на мрежата ти.

Blackhole маршрутът за анонса (/ip route add dst-address=203.0.113.0/24 blackhole) не помага. Connected маршрутът за същия префикс е с distance 0 и печели. Blackhole-ът се ползва само ако интерфейсът падне.

Защо това е проблем

  • Ефирът. В безжичните сектори broadcast се праща на най-ниската basic скорост, за да го чуят всички. Сто малки пакета в секунда на 6 Mbps заемат реално ефирно време от всеки сектор, всяка секунда.
  • Процесорът на всяко крайно устройство. Всеки клиентски рутер получава ARP заявката, разглежда я и я изхвърля. Камера, принтер или евтин CPE правят това 200 пъти в секунда.
  • Шумът крие истинските проблеми. Когато нивото на broadcast е постоянно високо, истинска L2 примка или бурен клиент не се виждат на графиките.
  • Неплатилите абонати. Абонат, който е спрян, но адресът му стои в мрежата, също събира трафик от интернет, който никой няма да обработи.

Как се мери

Първо колко адреса рутерът търси и не намира:

/ip arp print count-only where !complete interface=ether2

У нас на трите рутера бяха 50, 280 и 365 записа. Почти всички бяха в нашите публични мрежи и нито един не беше на абонат.

После кой точно пълни LAN-а с ARP:

/tool sniffer quick interface=ether2 mac-protocol=arp duration=10s

Броиш редовете с FF:FF:FF:FF:FF:FF по SRC-MAC. Клиентите бяха с по няколко заявки за 10 секунди. Рутерите бяха с по 100 до 1100.

Трето, ако имаш LibreNMS или друг SNMP мониторинг: броячите ifOutBroadcastPkts на портовете на ядрото показват колко broadcast получава всеки суич надолу. Това е числото, което реално има значение.

Правилото

Идеята е проста: пакет към адрес от моята мрежа, който не е на абонат и не е на самия рутер, се изхвърля, преди да стигне до ARP. В RAW, за да не струва нищо на connection tracking-а:

/ip firewall raw add chain=prerouting \
    dst-address=203.0.113.0/24 \
    dst-address-list=!customers \
    dst-address-type=!local \
    action=drop comment=drop-unassigned
Условие Защо
dst-address=203.0.113.0/24 Само нашата мрежа. Транзитът към интернет не се пипа.
dst-address-list=!customers Адресът не е на активен абонат. Списъкът е същият, с който режеш неплатилите в посока навън.
dst-address-type=!local Пази адресите на самия рутер: шлюза .1 и адреса за NAT. Без това режеш управлението и NAT-а.
без in-interface Хваща и трафика от LAN към незаетите адреси: абонат, който сканира съседите си, също пуска ARP.

Къде се слага

Подредбата в raw има значение. При нас prerouting изглежда така:

0  accept   DHCP (src 0.0.0.0 → 255.255.255.255)
1  drop     in-interface=ether2 src-address-list=!customers   ← неплатилите навън
2  drop     dst-address=203.0.113.0/24  !customers  !local     ← drop-unassigned
3  drop     dst-address=198.51.100.0/24 !customers  !local     ← drop-unassigned
4  accept   src-address-list=nat-range
5  accept   dst-address-list=nat-range
6  notrack

Правилото е след drop-а на неплатилите и преди всеки accept. Accept в raw е терминиращ: каквото мине през него, не стига до следващите правила. Повече за това е в статията RAW в RouterOS: notrack не спира веригата, а accept изключва anti-spoof-а.

Едно правило на мрежа, или диапазон

Изкушението е публичните мрежи да влязат в една address list и да стане едно правило. Не става. Едно правило в RouterOS приема dst-address-list само веднъж, а то вече е заето от !customers. Затова нашите мрежи се описват с dst-address, по една на правило.

Ако мрежите са съседни, например /25 и /24 една след друга, dst-address приема и диапазон:

dst-address=198.51.100.128-198.51.101.255

Преди да го пуснеш: кой ще отрежеш

Правилото реже всичко в мрежата, което не е в customers. Ако в същата /24 има твой сървър, камера или суич с публичен адрес, който не е в списъка, той изчезва от интернет. Затова преди това провери кои адреси с жив или статичен ARP не са в списъка:

:foreach i in=[/ip arp find where complete address~"^203\\.0\\.113\\."] do={
  :local a [/ip arp get $i address]
  :if ([:len [/ip firewall address-list find list=customers address=$a]] = 0) do={
    :put ($a . " " . [/ip arp get $i mac-address] . " " . [/ip arp get $i comment])
  }
}

При нас излязоха няколко клиентски рутера на стари абонати. Те и без това не можеха да излизат навън, защото правило 1 ги реже. Наше устройство нямаше. Ако при теб има, добави го в списъка или в отделно accept преди drop-а.

Странични ефекти, които трябва да приемеш съзнателно:

  • Трафикът от интернет към спрени абонати също се реже. Според нас това е желано: и без това не могат да отговорят.
  • Нов абонат работи едва когато адресът му влезе в customers. Ако списъкът се поддържа автоматично, това вече е така и в посока навън.

Връщането е един ред:

/ip firewall raw remove [find comment=drop-unassigned]

Резултатът

Мерено от SNMP броячите на портовете на L2 ядрото, средно в пакети в секунда:

предния ден, вечер същия ден, преди след
broadcast към всеки суич / OLT надолу 188 211 6
broadcast от рутерите към ядрото 185 209 4
общо broadcast, влизащ в ядрото 229 255 50

Почти целият broadcast в мрежата се оказа ARP на рутерите за адреси, които не съществуват. Около 97% от шума, стигащ до клиентите, изчезна с няколко правила, без нито една промяна по VLAN-ите или суичовете. Останалите ~50 pps идват от самите абонати. Port isolation на ядрото пуска техния broadcast само към рутерите, не към съседите.

По процесора на рутерите ефект почти няма: правилата са евтини, а отрязаните пакети са десетки в секунда. Печалбата е в мрежата под рутера, не в него.

Какво това правило не решава

Има близък, но различен проблем: трафик към абонат, който е в списъка, но е изключен. Ако рутерът държи статичен ARP за него, ARP заявка няма. Суичът обаче забравя MAC адреса му след ageing-time и започва да разлива всеки пакет към него като unknown unicast, пак на всеки порт. Това се решава на L2 и е тема за отделна статия.

Но ако имаш публични мрежи директно в LAN-а и не си ги филтрирал, започни от /ip arp print count-only where !complete. Ако числото е над няколко десетки, интернет вече ползва твоя LAN.