Learning Platform
Глоссарий Troubleshooting
Урок 05.01 · 18 мин
Начальный
EthernetMACMTULink Layer

Ethernet-кадры — как байты летают по проводу

Когда вы открываете github.com в браузере, в какой-то момент HTTP-запрос превращается в электрические импульсы (или радиоволны для Wi-Fi), которые улетают по проводу к ближайшему свитчу. Между «у нас есть TCP-сегмент» и «по проводу побежали единицы и нули» лежит link layer — канальный уровень. Его текущий де-факто стандарт в проводных и беспроводных сетях — Ethernet (включая Wi-Fi, который технически 802.11, но кадры выглядят похоже).

В этом уроке разберём, как устроен Ethernet-кадр, что такое MAC-адрес и почему MTU = 1500 преследует нас с 1980-х годов. Это нужно знать любому DE, потому что когда у вас в Kubernetes pod не может пинговать соседа, или Kafka-продюсер шлёт сообщения по 2 МБ через VPN — проблема почти всегда на этом уровне.


IP-уровень (layer 3) умеет одну вещь: маршрутизировать пакеты по адресам вида 93.184.216.34. Но IP ничего не знает про то, как именно отправить пакет через конкретный кусок проводов между вашим компьютером и роутером. Это работа link layer.

Link layer — это правила, по которым устройства в одной физической сети (один свитч, один Wi-Fi роутер, один сегмент) договариваются о том, кто и когда передаёт. Для Ethernet это означает:

  1. Каждый интерфейс имеет уникальный аппаратный адрес — MAC.
  2. Данные пересылаются дискретными порциями — frames (кадрами).
  3. Свитч решает, в какой порт послать кадр, на основе MAC-адреса назначения.
Где Ethernet в стеке -- между IP и проводом
ApplicationHTTP, SMTP, DNS и др. Знает про данные, не знает ни про адреса, ни про пакеты
TransportTCP/UDP. Добавляет порты, надёжность (TCP). На выходе -- сегменты
NetworkIP. Добавляет IP-адреса (src и dst). На выходе -- IP-пакеты
LinkEthernet / Wi-Fi. Оборачивает IP-пакет в кадр с MAC-адресами. То, о чём этот урок
PhysicalБиты в проводе или эфире: NRZ, MLT-3, OFDM. Физика -- электричество, свет, радио

Важно: link layer работает только внутри одного broadcast domain. Как только пакет уходит через роутер — кадр распаковывается, IP-пакет переоборачивается в новый кадр уже для следующего сегмента. MAC-адреса каждый раз меняются, IP — остаются.


Структура Ethernet-кадра

Современный Ethernet-кадр (Ethernet II, он же DIX) выглядит так:

Анатомия Ethernet II кадра -- 6+6+2+payload+4 байт
Preamble7 байт 10101010 + 1 байт SFD (10101011). Синхронизация приёмника. На уровне ОС обычно невидим -- handler сетевой карты его отрезает
Dst MACMAC-адрес получателя. 6 байт. ff:ff:ff:ff:ff:ff = broadcast. Может быть multicast (01:00:5e:...) или обычный unicast
Src MACMAC-адрес отправителя. 6 байт. Уникален в рамках broadcast domain. Сетевая карта подставляет его автоматически
EtherType2 байта. Что внутри payload. 0x0800 = IPv4, 0x86DD = IPv6, 0x0806 = ARP, 0x8100 = 802.1Q VLAN tag
PayloadОт 46 до 1500 байт. Если IP-пакет меньше 46 -- добавляется padding. 1500 -- стандартный MTU. Внутри обычно IP-пакет
FCSFrame Check Sequence, 4 байта. CRC-32 над всем кадром. Если не сходится -- кадр выбрасывается без объяснений (на link layer нет retransmission)

На уровне операционной системы вы обычно видите кадр без preamble и FCS (их обрабатывает сетевая карта). То есть в tcpdump или Wireshark вы увидите: 6 байт dst MAC, 6 байт src MAC, 2 байта EtherType, потом IP-заголовок и далее.

Вот настоящий кадр из tcpdump:

# tcpdump -i en0 -e -n -X -c 1 'tcp port 443'
# Опции: -e (show MAC), -n (no DNS), -X (hex+ASCII), -c 1 (один пакет)

12:34:56.789012 a4:83:e7:1a:bb:cc > 00:1c:42:00:00:18, ethertype IPv4 (0x0800), length 78:
  192.168.1.42.54321 > 140.82.121.4.443: Flags [S], seq 3478291230, win 65535, ...
  0x0000: 0800 4500 0040 0000 4000 4006 ...

Здесь:

  • a4:83:e7:1a:bb:cc — MAC отправителя (ваш ноутбук).
  • 00:1c:42:00:00:18 — MAC получателя (обычно ваш роутер, если адресат за пределами локалки).
  • ethertype IPv4 (0x0800) — внутри IP-пакет.
  • Дальше уже IP-заголовок начинается с 45 00 (versions/IHL/TOS).

MAC-адреса — что это и откуда берутся

MAC (Media Access Control) — 48-битный аппаратный адрес сетевого интерфейса. Записывается как 6 пар hex-цифр через двоеточие или дефис: a4:83:e7:1a:bb:cc.

Структура MAC-адреса:

MAC-адрес: OUI + serial
a4:83:e7OUI -- Organizationally Unique Identifier. 24 бита. Назначается IEEE производителю сетевого оборудования. По OUI можно понять, какая фирма сделала чип. a4:83:e7 -- Intel, 00:1c:42 -- Parallels, ac:de:48 -- Apple
1a:bb:ccSerial -- уникальный номер устройства внутри OUI. Назначает производитель. Теоретически должен быть глобально уникальный, на практике бывают коллизии и фейковые MAC
U/L bitВторой младший бит первого байта. 0 = глобально назначенный (через OUI), 1 = локально назначенный (например, виртуальная машина или рандомизация MAC в Wi-Fi)
I/G bitСамый младший бит первого байта. 0 = unicast (один получатель), 1 = multicast (группа получателей). Broadcast ff:ff:ff:ff:ff:ff -- частный случай multicast

Несколько важных особенностей MAC-адресов:

  1. Не маршрутизируются. В отличие от IP, MAC-адреса не имеют иерархии. Свитч просто запоминает «по этому проводу видел такой-то MAC». Маршрутизация по MAC не масштабируется — поэтому для глобальной сети есть IP.

  2. Можно подменить. MAC «зашит в железо», но любой современный сетевой стек позволяет его поменять программно (ip link set dev eth0 address aa:bb:cc:dd:ee:ff). Это используется в Wi-Fi для приватности и в атаках (MAC spoofing).

  3. Special-адреса.

    • ff:ff:ff:ff:ff:ff — broadcast, услышат все в сегменте.
    • 01:00:5e:xx:xx:xx — IPv4 multicast.
    • 33:33:xx:xx:xx:xx — IPv6 multicast.
    • 00:00:00:00:00:00 — обычно невалидный, иногда означает «не назначен».

Посмотрите свои MAC-адреса:

# Linux:
ip link show
# 2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
#     link/ether a4:83:e7:1a:bb:cc brd ff:ff:ff:ff:ff:ff

# macOS:
ifconfig en0 | grep ether
#     ether a4:83:e7:1a:bb:cc

# Windows:
getmac /v /fo list

В выводе вы увидите link/ether <MAC> brd ff:ff:ff:ff:ff:ff — значит broadcast-адрес сегмента это вот эти все единицы.


MTU = 1500 — откуда это число и почему оно везде

MTU (Maximum Transmission Unit) — максимальный размер payload, который влезает в один кадр. Для классического Ethernet это 1500 байт. С заголовком (14 байт) и FCS (4 байта) получается 1518 байт всего кадра.

Почему именно 1500? Это компромисс из 1980-х:

  • Слишком маленький payload — большой overhead на заголовки. Если payload = 100 байт, заголовок 14 байт даёт 12% накладных расходов.
  • Слишком большой payload — если в кадре ошибка, нужно перепосылать всё. И при коллизиях на старом hub-based Ethernet задержки росли.

1500 байт — цифра, которая давала хороший баланс на медном Ethernet 10 Мбит/с в 1980-х. И этот размер закрепился в стандарте. Сегодня технические причины уже не такие, но поменять MTU = 1500 во всём интернете нельзя, потому что:

WARNING

Если ваш MTU больше, чем MTU у промежуточного устройства, пакет либо фрагментируется (на IPv4), либо дропается с ICMP ‘Packet Too Big’ (на IPv6 и при DF-флаге). Это популярная причина «таинственных» проблем — TCP-handshake проходит, мелкие пакеты ходят, а большие POST зависают. Называется PMTU Black Hole.

Что это значит на практике для DE:

  1. VPN/туннели уменьшают MTU. WireGuard вычитает ~60 байт, IPsec — ~50-80 байт. На VPN MTU обычно 1420-1450. Если приложение шлёт пакеты с DF (don’t fragment) и MTU между endpoints меньше — может зависать.

  2. Jumbo frames. В дата-центрах часто включают MTU = 9000 (jumbo frames). Это даёт ~6x меньше пакетов на тот же трафик, меньше CPU на упаковку/распаковку. Применяется в storage-сетях, между БД и приложением, в Kubernetes-кластере.

  3. TCP подстраивается. TCP MSS (Maximum Segment Size) = MTU - 40 (IP+TCP headers). При установке соединения стороны договариваются о MSS. Если на пути MTU меньше — TCP уменьшает MSS через MSS clamping.

Проверить и поменять MTU:

# Linux: посмотреть текущий MTU всех интерфейсов
ip link show | grep mtu

# Поменять (нужен root):
sudo ip link set dev eth0 mtu 9000

# Проверить, проходит ли пакет нужного размера без фрагментации:
ping -M do -s 1472 8.8.8.8
# 1472 + 28 (IP+ICMP) = 1500, влезает в стандартный MTU
# Если не проходит "Frag needed and DF set" -- значит на пути MTU меньше

# Найти реальный path MTU до хоста:
tracepath 8.8.8.8

Frame check sequence — CRC и что бывает при ошибках

В конце кадра идёт FCS — 4 байта CRC-32 над всем кадром (от dst MAC до конца payload). Это контрольная сумма, которая позволяет приёмнику обнаружить повреждение кадра.

Что делает приёмник:

  1. Принимает кадр целиком.
  2. Считает CRC над dst MAC + src MAC + EtherType + payload.
  3. Сравнивает с FCS в кадре.
  4. Если не сходится — молча выбрасывает кадр. Уведомлять отправителя — не задача link layer. Это работа более высоких уровней (TCP retransmit, например).
Кадр повреждён -- что происходит
SenderСчитает CRC, кладёт в FCS, отправляет
frame
КабельЭлектрические помехи, плохой контакт, длинный кабель -- бит флипается
ReceiverПринимает повреждённый кадр
CRC mismatchПриёмник считает CRC -- не сходится с FCS. Кадр выбрасывается. Счётчик rx_crc_errors на интерфейсе инкрементируется
No replyНикаких ACK или NACK на link layer. Отправитель не узнает, что кадр пропал. Это узнает TCP по таймауту и переотправит сегмент

Счётчики ошибок видны на интерфейсе:

# Linux:
ip -s link show eth0
# 2: eth0: ...
#     RX: bytes  packets  errors  dropped overrun mcast
#     1234567    8901     12      0       0       45
#     ...
# Если errors растут -- проблема на физическом уровне: кабель, разъём, помехи

# Более детально через ethtool:
ethtool -S eth0 | grep -i error
# rx_crc_errors: 12
# rx_frame_errors: 0
# rx_missed_errors: 0

CRC-ошибки на нормальном проводном Ethernet должны быть нулевыми или единичными. Если их сотни в час — меняйте кабель/SFP/порт.


Wi-Fi — тот же Ethernet?

Технически Wi-Fi — это другой link-layer протокол, 802.11. Но операционная система обычно показывает Wi-Fi-интерфейс с такими же MAC-адресами и Ethernet-like кадрами. С точки зрения приложения это та же абстракция: интерфейс с MAC, MTU обычно 1500.

Различия под капотом:

  • 802.11 кадры имеют 4 MAC-адреса (а не 2): source, destination, transmitter, receiver. Нужно для роуминга между точками доступа.
  • Wi-Fi не использует CRC одинаково с Ethernet — там сложнее (FCS + per-fragment).
  • Передача half-duplex (либо ты говоришь, либо слушаешь), а не full-duplex как современный проводной Ethernet.
  • Включена защита от коллизий (CSMA/CA вместо CD).

Для большинства задач DE это неважно. Важно одно: MAC ваш и MAC приёмника по-прежнему видны и работают.


Попробуй сам

Откройте терминал и проведите следующие эксперименты:

# 1. Найти свой MAC
ip link show  # Linux
ifconfig | grep ether  # macOS

# 2. Захватить ОДИН Ethernet-кадр с MAC-адресами в hex:
sudo tcpdump -i any -e -n -X -c 1 'tcp port 443'
# Откройте параллельно браузер -- сделайте любой HTTPS-запрос
# Увидите: <src MAC> > <dst MAC>, ethertype IPv4 ... + hex-дамп пакета

# 3. Понять размер кадра в проводе:
ping -s 1472 -M do 8.8.8.8
# Если идёт -- ваш MTU >= 1500
# Поменяйте на 1500:
ping -s 1473 -M do 8.8.8.8
# "ping: local error: message too long" -- ровно на 1 байт больше не влезает

# 4. Посмотреть ARP-таблицу (что подсунет следующий урок):
ip neigh   # Linux
arp -a     # macOS
# Увидите соответствие IP -> MAC для всех соседей в локальной сети

# 5. Найти производителя по OUI:
# Возьмите свой MAC, первые 3 байта вставьте сюда:
# https://maclookup.app/  или  https://standards-oui.ieee.org/
# OUI a4:83:e7 -> Intel, 00:1c:42 -> Parallels

Особенно полезно сделать пункт 2 и посмотреть на реальный hex-дамп. Вы увидите, как первые 14 байт это Ethernet-заголовок, потом начинается IP (45 00 … для IPv4), потом TCP, и наконец данные.


MTU в Docker overlay-сетях: типичный источник PMTU проблем Kafka и MTU: размер batch vs MTU при больших сообщениях
Проверка знанийKnowledge check
Коллега жалуется: 'У нас в VPN-туннеле SSH работает нормально, а git clone большого репо зависает на 99%. Ping тоже работает. Что может быть?'
ОтветAnswer
Классическая симптоматика PMTU Black Hole -- проблема с MTU в туннеле. SSH и обычный ping шлют небольшие пакеты, которые легко влезают в любой MTU. А git clone в какой-то момент шлёт TCP-сегменты максимального размера (close to MTU). Если на пути есть узкое место с меньшим MTU и ICMP 'Packet Too Big' блокируется файрволом (а это происходит часто), отправитель никогда не узнает, что его пакеты надо уменьшить -- и продолжит слать большие, которые молча дропаются. TCP видит таймауты, переотправляет те же большие пакеты, и так бесконечно. Решение: уменьшить MTU интерфейса VPN (например, в WireGuard конфиге MTU = 1420), или включить TCP MSS clamping на роутере (iptables правило: -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu). Это типичная ошибка с туннелями: WireGuard добавляет ~60 байт overhead, IPsec ещё больше -- и без правильного MTU работает 'почти всё'.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Какова стандартная структура Ethernet II кадра и какие байты обычно НЕ видны в выводе tcpdump?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4