VLAN, ARP і сусіди
Навіщо це
Section titled “Навіщо це”У вас є один комутатор на двадцять портів, а мереж потрібно дві: бухгалтерія не повинна бачити широкомовних кадрів гостьового Wi-Fi. Купувати другий комутатор дорого, тягнути між поверхами два окремі кабелі ще дорожче. VLAN дозволяє розрізати один фізичний комутатор на кілька логічних, а один кабель між комутаторами вживати для всіх них.
Друге питання звучить буденніше. Ви запускаєте ping 192.0.2.2, і кадр
Ethernet потребує MAC-адреси отримувача, а ви знаєте лише IP. Хтось
мусить перекласти одне в інше, і саме тут трапляється «ping то проходить,
то ні», «сервер бачить чужу MAC-адресу» і «весь трафік раптом іде через
ноутбук у кутку». Перекладає ARP, а мережевий стек Linux тримає результат
у таблиці сусідів, яку корисно вміти читати.
Передумови. Кадр, MAC-адреса, комутатор і широкомовний домен — модуль 4. IP-адреса як поняття — модуль 1; детально про неї в модулі 6.
VLAN: один комутатор, кілька мереж
Section titled “VLAN: один комутатор, кілька мереж”Широкомовний домен комутатора охоплює всі його порти. Щоб поділити його на частини, можна купити більше комутаторів, а можна навчити один комутатор тримати кілька ізольованих доменів. Останнє й називається VLAN (virtual LAN). Кожному порту приписується номер VLAN, і кадр, що прийшов на порт, лишається всередині цього VLAN: на порти інших VLAN його не розішлють навіть при flooding. Хости з різних VLAN не бачать одне одного на канальному рівні, навіть якщо сидять на сусідніх портах. Щоб вони поспілкувалися, між мережами потрібен маршрутизатор (модуль 7).
Ізоляції достатньо, поки всі хости підключені до одного комутатора. Коли комутаторів два, з’являється питання, як передати кадри двох VLAN одним кабелем так, щоб другий комутатор знав, до якого VLAN належить кожен кадр. Для цього є стандарт IEEE 802.1Q: у кадр вставляється 4-байтовий тег між адресою відправника й EtherType.
Тег складається з:
- TPID
0x8100: це значення стоїть там, де звичайно EtherType, і повідомляє приймачеві, що далі йде тег; - PCP (3 біти): пріоритет кадра;
- DEI (1 біт): чи можна кадр викинути першим при перевантаженні;
- VID (12 біт): номер VLAN. Номери 0 і 4095 зарезервовані, тож користувачу доступні 1–4094.
Після тега йде справжній EtherType. Кадр став на 4 байти довшим (1522 байти замість 1518), а MTU лишився 1500, бо вимірюється по навантаженню. Про це варто пам’ятати, коли в мережі є старе обладнання, яке не чекає на кадри понад 1518 байтів.
Access-порт належить одному VLAN. Кадри від хоста приходять без тегу, комутатор у думках «прикріплює» до них номер VLAN порту, а назад віддає без тегу. Хост навіть не підозрює, що VLAN існує.
Trunk-порт несе кілька VLAN. Кадри по ньому йдуть з тегами, за якими
сусідній комутатор розпізнає, куди кадр належить. На trunk зазвичай
одна VLAN ходить без тегу: це native VLAN (у термінології Linux —
pvid з untagged). Вона потрібна для сумісності, коли на тому кінці хост
чи пристрій про теги не знає. Якщо native VLAN не збігається на двох кінцях
trunk, кадри однієї VLAN потрапляють в іншу, тож
її роблять однаковою на обох кінцях і найкраще порожньою, без хостів.
Кілька VLAN у Linux-мості
Section titled “Кілька VLAN у Linux-мості”Міст Linux вміє це сам. Вмикається фільтрація
vlan_filtering, і кожен порт моста отримує список VLAN, які через нього
проходять. За замовчуванням усі порти в VLAN 1 як pvid untagged, тобто
нічого не змінюється, доки не налаштуєте. Далі командою bridge vlan add
виставляється, який порт у якій VLAN.
ip link add br0 type bridge vlan_filtering 1# access-порти: кадри без тегу, належать одній VLANbridge vlan add dev q1 vid 10 pvid untaggedbridge vlan add dev q2 vid 20 pvid untagged# trunk-порт: кадри обох VLAN із тегамиbridge vlan add dev q3 vid 10bridge vlan add dev q3 vid 20# прибрати початкову VLAN 1 з access-портівbridge vlan del dev q1 vid 1bridge vlan del dev q2 vid 1bridge vlan showport vlan-idq1 10 PVID Egress Untaggedq2 20 PVID Egress Untaggedq3 10 20br0 1 PVID Egress UntaggedМітки PVID і Egress Untagged означають: кадри без тегу, що прийшли
на порт, потрапляють у цю VLAN, а виходять з порту вже без тегу.
Рядок без міток (як для q3) описує тегований вхід і вихід. Окремо
мости в Linux мають власний інтерфейс br0, який теж належить до VLAN
(bridge vlan add dev br0 vid 10 self), якщо хост із цим мостом
бере участь в мережі, наприклад, має там IP-адресу.
А от на самому хості, що сидить на trunk, VLAN створюється як окремий
інтерфейс: ip link add link eth0 name eth0.10 type vlan id 10. Кадри, які
надсилає цей інтерфейс, отримують тег 10 автоматично.
ARP: як з IP-адреси отримати MAC
Section titled “ARP: як з IP-адреси отримати MAC”Хост 192.0.2.1 хоче надіслати пакет на 192.0.2.2, що в тій самій
підмережі. Кадр мусить мати MAC-адресу призначення, а хост її не знає.
Цю задачу розв’язує ARP (address resolution protocol), і розв’язує
найпростіше: питає всіх.
-
Хост надсилає широкомовний кадр (адресат
ff:ff:ff:ff:ff:ff, EtherType0x0806) із запитом: «хто має адресу192.0.2.2? Скажіть192.0.2.1», а у полі відправника стоїть його власна MAC-адреса. -
Усі пристрої широкомовного домену отримують кадр. Той, хто має цю IP-адресу, відповідає унікастом одному запитувачу: «
192.0.2.2знаходиться за8e:ce:a8:35:e6:ac». Решта мовчить. -
Запитувач записує пару в кеш ARP і відправляє накопичений пакет. Наступні пакети йдуть без запиту, поки запис живий.
Пакет ARP маленький, 28 байтів для IPv4 поверх Ethernet: тип апаратури і протоколу, довжини адрес, код операції (1 — запит, 2 — відповідь) і по дві пари «MAC + IP» відправника й цілі. Він не використовує IP, лежить прямо в кадрі, тому ARP не маршрутизується й не виходить за межі широкомовного домену. Якщо цільовий хост у іншій мережі, ARP питає не про нього, а про шлюз (як хост це вирішує, розповідає модуль 7).
Таблиця сусідів і її стани
Section titled “Таблиця сусідів і її стани”У Linux кеш ARP входить до загальної таблиці сусідів (neighbour table),
якою користуються і ARP для IPv4, і NDP для IPv6. Дивляться на неї командою
ip neigh. Запис у ній проходить кілька станів, бо сусід
може зникнути, а хост не хоче ні щоразу питати наново, ні слати пакети в нікуди.
INCOMPLETE: запит надіслано, відповіді ще немає. Пакети до цього адресата чекають у короткій черзі.REACHABLE: сусід нещодавно підтвердив себе. Час у цьому стані береться зbase_reachable_time_ms(30 секунд за замовчуванням), ядро додає випадковий розкид, тож реальне число коливається.STALE: часу минуло багато, і запис «можливо, застарів». Але він лишається придатним: пакети йдуть на збережену MAC-адресу без пауз. Перевірка настає лише тоді, коли знадобиться.DELAY: відправили пакет наSTALE-запис і чекаємо 5 секунд, чи не надійде непряме підтвердження (наприклад, від TCP прийшла відповідь).PROBE: підтвердження не було, ядро надсилає сусідові унікастні запити.FAILED: відповіді не дочекалися. Пакети на цю адресу викидаються, а програма отримує помилкуNo route to hostабо тайм-аут.PERMANENT: запис внесений вручну й не старіє, нічого не перевіряється.
Якщо запис завис на INCOMPLETE або FAILED, хост не отримує відповіді
на ARP, і причину треба шукати нижче за IP:
фізичний порт, VLAN, фільтр на комутаторі чи просто не той хост.
Gratuitous ARP
Section titled “Gratuitous ARP”Gratuitous ARP хост надсилає без жодного питання, про власну адресу; це може бути і запит, і відповідь. У запиті власна IP-адреса стоїть і як адреса відправника, і як цільова.
Так хост, який щойно налаштував адресу, перевіряє, чи хтось уже нею користується. Якщо прийшла відповідь, адреса конфліктує.
Важливіше інше застосування. Коли адреса переходить на інший пристрій (міграція віртуальної машини, перемикання на резервний сервер, VRRP), усі сусіди ще тримають у кеші стару MAC-адресу, і трафік іде в нікуди до закінчення запису. Новий власник розсилає gratuitous ARP, і сусіди, що вже мають запис, оновлюють його й негайно перемикаються, і адреса переїжджає «плавно».
ARP-спуфінг
Section titled “ARP-спуфінг”Головна слабкість протоколу в тому, що ARP не має автентифікації. Будь-хто в широкомовному домені може оголосити себе власником чужої IP-адреси, і хости повірять. Досить надіслати кожному потрібну «відповідь» чи gratuitous ARP. Це називається ARP-спуфінг, або отруєння кеша. Зловмисник, що оголосив свою MAC-адресу замість шлюзу, стає посередником: увесь трафік жертви в інтернет проходить через нього, і він може читати його, змінювати або просто викидати (тоді жертва втрачає зв’язок).
Захист від цього будують шарами:
- Dynamic ARP Inspection на керованих комутаторах: комутатор звіряє кожен ARP-пакет із таблицею, зібраною DHCP snooping (яка адреса видана якому порту), і відкидає неправдиві.
- Port security: обмеження кількості й набору MAC-адрес на порту.
- Статичні записи для критичних адрес (шлюз сервера):
ip neigh replace … nud permanent. Працює, але незручно в більшій мережі. - Шифрування вище за рівнем: TLS і SSH не прибирають перехоплення, але роблять його марним, бо зловмисник бачить лише зашифровані байти. Підміна сертифіката при цьому помітна.
- Моніторинг:
arpwatchповідомляє, коли пара «IP — MAC» змінюється.
Жоден із цих методів не закладений у сам ARP: його проєктували для довірливої локальної мережі 1980-х.
NDP: той самий задум в IPv6
Section titled “NDP: той самий задум в IPv6”В IPv6 ARP нема. Його роль виконує NDP (neighbor discovery protocol), який
працює поверх ICMPv6: замість широкомовного запиту — Neighbor Solicitation,
замість відповіді — Neighbor Advertisement. Запит іде не на широкомовну адресу,
якої в IPv6 немає, а на спеціальну групову, яку слухає лише вузьке
коло хостів, серед яких шуканий. Таблиця сусідів і її стани лишаються тими самими, ip -6 neigh покаже
ті самі REACHABLE і STALE. Подробиці — у модулі 10.
Як це насправді в Linux
Section titled “Як це насправді в Linux”Стенд той самий, що в модулі 4: комутатор із трьох хостів,
поки без VLAN. Тобто
є простори імен h1, h2, h3 з адресами 192.0.2.1/24,
192.0.2.2/24 і 192.0.2.3/24 на інтерфейсах p1, p2, p3 і міст
br0 у просторі sw.
Свіжий кеш порожній, а після першого ping у ньому є сусід:
sudo ip netns exec h1 ping -c1 192.0.2.2sudo ip netns exec h1 ip neigh show192.0.2.2 dev p1 lladdr 8e:ce:a8:35:e6:ac REACHABLEЗачекайте з пів хвилини й подивіться ще раз: тепер там STALE. Щоб
пройти цикл далі, надішліть пакет і подивіться, не чекаючи:
sudo ip netns exec h1 ping -c1 192.0.2.2 >/dev/nullsudo ip netns exec h1 ip neigh showsleep 6sudo ip netns exec h1 ip neigh show192.0.2.2 dev p1 lladdr 8e:ce:a8:35:e6:ac DELAY192.0.2.2 dev p1 lladdr 8e:ce:a8:35:e6:ac REACHABLEСусід одразу після пакета у DELAY, а за кілька секунд, коли ядро
перепитало його, знову REACHABLE. ICMP-відповідь ядро не вважає підтвердженням
досяжності, тож перепитує сусіда саме; той відповідає, і цикл замикається.
Тепер адреса, якої нема:
sudo ip netns exec h1 ping -c1 -W1 192.0.2.50sudo ip netns exec h1 ip neigh show 192.0.2.50192.0.2.50 dev p1 INCOMPLETEЧерез кілька секунд, коли ядро зробить усі спроби, запис стає FAILED.
Файл /proc/net/arp показує те саме в старому форматі (колонка Flags:
0x2 — запис повний, 0x0 — невдалий, 0x6 — постійний).
Лічильники і параметри: ip -s neigh додає колонки used і probes, а
налаштування читаються з sysctl net.ipv4.neigh.default (там
base_reachable_time_ms = 30000, delay_first_probe_time = 5,
ucast_solicit = 3, mcast_solicit = 3).
Щоб побачити ARP без ICMP, підійде arping (пакет arping у Debian і Ubuntu).
Він шле лише ARP, тож спрацює й тоді, коли ICMP на шляху блокують:
sudo ip netns exec h1 arping -c2 -i p1 192.0.2.2ARPING 192.0.2.242 bytes from 8e:ce:a8:35:e6:ac (192.0.2.2): index=0 time=5.785 usec42 bytes from 8e:ce:a8:35:e6:ac (192.0.2.2): index=1 time=4.878 usecОпція -i задає інтерфейс. Існує ще інша програма з такою ж назвою (з
пакета iputils), де інтерфейс задається -I, а синтаксис інший; тому
звіряйтеся з arping -h.
Підміна, яку видно
Section titled “Підміна, яку видно”Чесно проведемо атаку на власний стенд. Вона працює лише у ваших просторах
імен, але ілюструє справжню поведінку. Залежно від пакета ваш arping
може мати інші опції.
Хост h1 знає справжню MAC-адресу h2. Хост h3 надсилає gratuitous ARP,
від імені 192.0.2.2 зі своєю MAC-адресою (-S задає підставлену IP-адресу,
-U — unsolicited-запит):
sudo ip netns exec h3 arping -c1 -U -S 192.0.2.2 -i p3 192.0.2.2sudo ip netns exec h1 ip neigh show 192.0.2.2192.0.2.2 dev p1 lladdr ce:a4:16:e4:26:bb STALElladdr тепер MAC-адреса h3 (ce:a4:16:e4:26:bb). Запис лишився чинним,
але змінився, а ping 192.0.2.2 із h1 більше не отримує відповіді: кадри
йдуть на h3, у якого цієї IP-адреси нема. Тепер захист:
sudo ip netns exec h1 ip neigh replace 192.0.2.2 lladdr 8e:ce:a8:35:e6:ac dev p1 nud permanentsudo ip netns exec h3 arping -c1 -U -S 192.0.2.2 -i p3 192.0.2.2sudo ip netns exec h1 ip neigh show 192.0.2.2192.0.2.2 dev p1 lladdr 8e:ce:a8:35:e6:ac PERMANENTЗапис PERMANENT нова «відповідь» не чіпає, і пінг знову працює.
VLAN-фільтрація
Section titled “VLAN-фільтрація”Якщо ip link set br0 type bridge vlan_filtering 1 повертає
Operation not supported, ваше ядро зібране без CONFIG_BRIDGE_VLAN_FILTERING.
Таке трапляється в контейнерах і на деяких хостингах; на віртуальній машині
з ядром дистрибутива фільтрація працює. Перевірити, що VLAN справді ізолює,
можна так: хости h1 і h2 з одного
VLAN пінгують один одного, а h1 і h3 з різних VLAN ні, і ARP-запит
від h1 у tcpdump на h3 не з’являється.
Прибрати за собою: sudo ip netns delete h1 і так само h2, h3, sw.
Типові помилки розуміння
Section titled “Типові помилки розуміння”«VLAN — це окрема підмережа IP». VLAN — рівень 2, підмережа — рівень 3. Зазвичай одній VLAN відповідає одна підмережа, але технічно ніщо цього не вимагає: на одній VLAN можна налаштувати дві підмережі, а одну підмережу розтягнути на дві VLAN і отримати сюрпризи.
«Хост у VLAN 10 бачить тег». На access-порту тегу нема: комутатор додає
й знімає його сам. Теги бачать лише trunk-порти й пристрої, що
налаштовані на VLAN явно (наприклад, інтерфейс eth0.10).
«ARP питає про цілий інтернет». ARP працює лише в межах широкомовного домену. Для адреси поза підмережею хост питає MAC шлюзу за замовчуванням, а не адресата.
«STALE означає, що сусід недоступний». Навпаки: запис цілком
придатний. STALE означає «давно не перевіряли», а недоступний
сусід — це FAILED.
«Якщо ping працює, то ARP у порядку». Ping проходить і тоді, коли кеш
отруєно, але отруїв його ваш сусід, який пересилає трафік далі. Поки кадри
доходять, ніхто нічого не помічає. Справжню картину показує ip neigh:
чи збігається lladdr шлюзу з MAC-адресою справжнього шлюзу.
«Проти ARP-спуфінгу допоможе брандмауер на хості». Брандмауер працює вище за кадри. Підміна відбувається на канальному рівні, до нього пакет навіть не доходить. Потрібен захист на комутаторі або шифрування вище.
Перевір себе
Лабораторна
Section titled “Лабораторна”B1. Міст і VLAN руками: два хости й міст, тоді
VLAN-фільтрація на мості; ARP і широкомовлення видно в tcpdump. Там же
на практиці стає зрозуміло, чим access відрізняється від trunk.
B7. Налагодження зламаної мережі: одна
з несправностей стосується ARP. Вміння швидко зазирнути в ip neigh і
відрізнити FAILED від STALE заощадить там час.
Джерела
Section titled “Джерела”- Kurose, Ross, Computer Networking: A Top-Down Approach, розділ про канальний рівень, ARP і VLAN
- Peterson, Davie, Computer Networks: A Systems Approach, розділ про комутатори й VLAN
- Stevens, TCP/IP Illustrated, Vol. 1, розділ про ARP
- IEEE 802.1Q (VLAN), RFC 826 (ARP)
man 8 ip-neighbour,man 8 bridge,man 7 arp- Документація ядра Linux:
Documentation/networking/ip-sysctl.rst(параметриneighіarp_*)