Сети для самых маленьких. Часть 1: модели OSI и TCP/IP
Это первая статья серии «Сети для самых маленьких». «Для самых маленьких» — не про возраст читателя, а про точку старта: рассказывать буду с нуля и не буду предполагать ничего, кроме умения открыть терминал. Серия для тех, кто пишет программы, администрирует серверы или просто хочет понять, что происходит между нажатием Enter в адресной строке и появлением страницы.
У серии один принцип: о каждом протоколе — не только зачем он нужен, но и как он работает. Какие байты идут по проводу, кто на них отвечает, что происходит, когда что-то ломается. Поэтому почти в каждой части будут заголовки пакетов, команды и вывод tcpdump. Чтобы повторять примеры, хватит любой Linux-машины (подойдёт и WSL) с установленным tcpdump и Wireshark на рабочем компьютере.
План такой: сначала основа — модели, Ethernet, Wi-Fi и PPPoE; затем IPv4 с ARP и ICMP; транспорт — UDP и TCP; служебные протоколы DHCP и DNS; отдельным блоком IPv6 с Neighbor Discovery, SLAAC и DHCPv6; в конце — VLAN, VXLAN, IPsec с IKEv2 и разговор о том, чем VPN отличается от прокси. Статьи выходят по одной, и в конце каждой написано, что будет в следующей.
Задача, которую решает сеть
Две программы на разных компьютерах хотят обменяться байтами. Между ними — кабель или радио, коммутаторы, роутеры, несколько провайдеров и половина земного шара. Чтобы байты дошли, кто-то должен ответить на целый список вопросов:
- как закодировать биты в электрический сигнал, свет или радиоволну;
- как среди десятка устройств на одном кабеле передать данные именно соседу;
- как найти машину на другом конце планеты, не зная, через какие сети к ней идти;
- как убедиться, что данные дошли целиком и в правильном порядке, и повторить потерянное;
- какой из сотни процессов на той машине должен получить эти байты.
Можно написать одну большую программу, которая решает всё сразу. Так и делали в 1970-х, и каждая сеть получалась несовместимой с соседней: протокол для коаксиального кабеля ничего не знал о радио, а программа, написанная под одну сеть, не работала в другой.
Решение, к которому пришли, — разделить задачу на уровни. Каждый уровень решает одну из задач списка выше, пользуется услугами уровня под собой и предоставляет услугу уровню над собой. Уровень N на одной машине «разговаривает» с уровнем N на другой и не знает, как нижние уровни доставляют его данные. Транспортный уровень не знает, идут ли данные по Wi-Fi или по оптике; Wi-Fi не знает, несёт он TCP или UDP.
Из этой идеи выросли две модели, которыми описывают сети: OSI и TCP/IP.
Модель OSI
Модель OSI (Open Systems Interconnection) опубликована ISO в 1984 году. У неё семь уровней, считают снизу вверх:
| № | Уровень | За что отвечает | Единица данных | Примеры |
|---|---|---|---|---|
| 7 | Прикладной (Application) | Протокол самой программы: что означают передаваемые данные | данные, сообщение | HTTP — браузер запрашивает у сервера страницы; SMTP — серверы передают друг другу почту; SSH — удалённый терминал; DNS — превращает имена в адреса (часть 12) |
| 6 | Представления (Presentation) | Кодировки, сжатие, шифрование данных приложения | данные | отдельного протокола в TCP/IP нет; сюда условно относят TLS — шифрование поверх TCP, на котором работает HTTPS |
| 5 | Сеансовый (Session) | Установление и завершение сеансов, восстановление диалога | данные | отдельного протокола нет: сеансом управляет само приложение |
| 4 | Транспортный (Transport) | Доставка данных конкретному процессу; надёжность и порядок, если нужны | сегмент (TCP), датаграмма (UDP) | UDP — только порты, без гарантий (часть 9); TCP — с доставкой, порядком и повторами (часть 10) |
| 3 | Сетевой (Network) | Адресация машин во всей сети и выбор пути между сетями | пакет | IPv4 (части 5–6), IPv6 (часть 13), ICMP (часть 8) |
| 2 | Канальный (Data Link) | Передача данных между соседями в одном сегменте: адреса соседей, кадры, обнаружение ошибок | кадр | Ethernet (часть 2), Wi-Fi (часть 3), PPP (часть 4), VLAN (часть 17) |
| 1 | Физический (Physical) | Биты в сигнал: уровни напряжения, частоты, разъёмы, кабели | биты | витая пара, радио Wi-Fi, оптическое волокно |
Полезно видеть, что на каждом уровне свой вид адреса:
| Уровень | Адрес | Отвечает на вопрос |
|---|---|---|
| 2 | MAC-адрес 3c:52:82:1a:2b:3c |
какому соседу на этом кабеле отдать кадр |
| 3 | IP-адрес 192.168.1.10 |
какой машине в мире предназначен пакет |
| 4 | Порт 443 |
какому процессу на этой машине |
| 7 | Имя www.vitaliy.org, URL |
что именно нужно человеку |
Главное, что нужно знать о модели OSI: в чистом виде её никто не реализует. У ISO был свой набор протоколов под каждый уровень (X.400, CLNP, TP4), и он проиграл TCP/IP ещё в 1990-х. Выжила сама схема — как общий язык. Когда говорят «L2-коммутатор», «L3-свитч», «балансировщик L7», «файрвол L4», имеют в виду уровни именно из этой таблицы: устройство смотрит на заголовки этого уровня и ниже и не трогает то, что выше.
Уровни 5 и 6 в реальных сетях размыты. Классический вопрос «на каком уровне TLS?» не имеет точного ответа: он лежит между транспортом и приложением, его называют и L5, и L6, и «L4.5». На практике это неважно: все эти функции живут внутри приложения или его библиотек.
Модель TCP/IP
Модель, по которой сети устроены на самом деле, описана в RFC 1122 и у неё четыре уровня:
| TCP/IP | Что внутри | Уровни OSI |
|---|---|---|
| Прикладной (Application) | Протокол приложения, включая кодировки, сеансы и TLS | 7, 6, 5 |
| Транспортный (Transport) | TCP, UDP | 4 |
| Межсетевой (Internet) | IP, ICMP, маршрутизация | 3 |
| Канальный (Link) | Всё, что доставляет IP-пакет соседу: Ethernet, Wi-Fi, PPP вместе с физикой | 2, 1 |
Разница с OSI одна: TCP/IP не делит на части то, что в реальных системах и так неделимо. Приложение само решает, шифровать ли ему данные и как держать сеанс, а сетевая карта вместе с драйвером отвечает и за кадры, и за сигнал в кабеле.
Дальше в серии я буду пользоваться нумерацией OSI (L2, L3, L4), потому что так говорят все, а по устройству следовать TCP/IP, потому что так всё работает.
Инкапсуляция: как пакет выглядит на проводе
Самая важная идея этой статьи. Каждый уровень берёт данные от уровня выше, приписывает к ним свой заголовок и отдаёт вниз. На проводе оказывается матрёшка из заголовков.
Возьмём запрос к сайту по HTTPS. Браузер отдал TLS-библиотеке HTTP-запрос, та зашифровала его и передала байты в TCP-сокет. Дальше по стеку:
┌───────────────────┐
прикладной: │ TLS-запись (HTTP) │
└───────────────────┘
┌────────────┬───────────────────┐
транспортный (TCP): │ TCP 20 Б │ данные │
│ порты, │ │
│ seq, ack │ │
└────────────┴───────────────────┘
┌────────────┬────────────┬───────────────────┐
сетевой (IP): │ IPv4 20 Б │ TCP │ данные │
│ адреса, │ │ │
│ TTL, proto │ │ │
└────────────┴────────────┴───────────────────┘
┌────────────┬────────────┬────────────┬───────────────────┬───────┐
│ Ethernet │ IPv4 │ TCP │ данные │ FCS │
│ 14 Б: MAC, │ │ │ │ 4 Б │
│ EtherType │ │ │ │ │
└────────────┴────────────┴────────────┴───────────────────┴───────┘
← это и уходит в кабель, слева направо
Размеры здесь минимальные: у заголовков IPv4 и TCP бывают опции, и тогда они длиннее 20 байт. Для кадра Ethernet без опций получаем 14 + 20 + 20 + данные + 4 байта контрольной суммы, которую считает сетевая карта.
На приёмной стороне матрёшка разбирается в обратном порядке, и здесь есть вопрос, без которого схема не работает: откуда уровень знает, что лежит внутри? Получив кадр, сетевой стек должен понять, отдать его содержимое IPv4, IPv6 или ARP. Получив IP-пакет — TCP, UDP или ICMP. Получив сегмент TCP — какому из процессов.
Ответ: в заголовке каждого уровня есть поле, которое говорит, что внутри. Это называется демультиплексированием.
| Уровень | Поле | Значения |
|---|---|---|
| Ethernet | EtherType (2 байта) | 0x0800 IPv4, 0x86DD IPv6, 0x0806 ARP, 0x8100 VLAN |
| IPv4 / IPv6 | Protocol / Next Header (1 байт) | 1 ICMP, 6 TCP, 17 UDP, 50 ESP (зашифрованный пакет IPsec, часть 19), 58 ICMPv6 (часть 14) |
| TCP / UDP | порт назначения (2 байта) | 443 HTTPS, 53 DNS, 22 SSH; в общем случае — что слушает процесс |
Так что сетевой стек — это по сути цепочка switch-ов: прочитать заголовок, посмотреть в поле «что внутри», снять заголовок, отдать следующему обработчику.
Вот как это выглядит в tcpdump для первого пакета TCP-соединения к веб-серверу. Ключ -e просит показать и заголовок Ethernet:
$ sudo tcpdump -i eth0 -n -e 'tcp port 443' -c 1
12:00:01.123456 3c:52:82:1a:2b:3c > d8:47:32:0a:0b:0c, ethertype IPv4 (0x0800), length 74:
192.168.1.10.51234 > 203.0.113.10.443: Flags [S], seq 1234567890, win 64240,
options [mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 7], length 0
Разбираем по уровням:
- L2: кадр от MAC
3c:52:82:1a:2b:3c(моя сетевая карта) кd8:47:32:0a:0b:0c(это роутер, а не сервер — почему, через раздел), EtherType0x0800, то есть внутри IPv4. Длина кадра 74 байта: 14 Ethernet + 20 IPv4 + 40 TCP (20 заголовка и 20 опций). Контрольную суммуtcpdumpне показывает: её снимает сетевая карта. - L3: от
192.168.1.10к203.0.113.10, протокол TCP — иначеtcpdumpне разобрал бы порты. - L4: с порта
51234на порт443, флагS(SYN, начало соединения), данных 0 байт.
Про названия единиц данных. Строго говоря, на L2 это кадр (frame), на L3 — пакет (packet), на L4 — сегмент у TCP и датаграмма у UDP. В разговоре всё называют пакетами, и я буду так же, когда уровень неважен. Когда важен — буду говорить «кадр» или «сегмент».
Кто что обрабатывает по пути
Пакет из примера выше пройдёт примерно такой путь:
ноутбук ──► коммутатор ──► домашний роутер ──► роутер провайдера ──► … ──► сервер
L1–L7 L2 L3 L3 L1–L7
Каждое устройство на пути разбирает матрёшку только до своего уровня:
- Коммутатор читает заголовок Ethernet, по MAC-адресу назначения выбирает порт и отправляет кадр туда, не меняя в нём ни байта. Что внутри — IPv4, IPv6, ARP — ему всё равно. Это устройство L2.
- Роутер снимает заголовок Ethernet целиком, читает заголовок IP, по адресу назначения находит в своей таблице маршрутов следующий роутер (next hop), уменьшает TTL на единицу, пересчитывает контрольную сумму заголовка IP и упаковывает пакет в новый кадр: с собственным MAC-адресом отправителя и MAC-адресом следующего роутера в поле получателя. Если следующий интерфейс не Ethernet, а, скажем, PPPoE (часть 4) или сотовая сеть — пакет уедет в кадр совсем другого формата. IP-пакету это безразлично. Это устройство L3.
- Сервер разбирает всё до приложения.
Отсюда таблица того, что меняется по дороге:
| Что | Меняется ли |
|---|---|
| MAC-адреса в кадре | на каждом участке между роутерами — новые |
| IP-адреса | не меняются от отправителя до получателя (исключение — NAT, часть 6) |
| TTL в заголовке IP | минус один на каждом роутере |
| TCP-заголовок и данные | не трогаются (исключения — NAT и файрволы, тоже часть 6) |
Теперь понятно, почему в tcpdump кадр шёл на MAC роутера, а не сервера: MAC-адрес — это адрес соседа на этом кабеле, IP-адрес — адрес конечного получателя. Ноутбук знает, что 203.0.113.10 не в его сети, значит, кадр надо отдать роутеру, а уж тот разберётся дальше. Как ноутбук узнаёт MAC роутера — тема части 7 про ARP; как решает, что адрес «не в его сети» — части 5.
Это же отвечает на вопрос, который задают все начинающие: зачем два адреса, если есть IP? Потому что они про разное. IP-адрес глобален и не зависит от среды передачи; MAC-адрес живёт в пределах одного сегмента Ethernet и ничего не знает о сетях за роутером. У Wi-Fi есть MAC-адреса, у PPP их нет вовсе, а IP работает поверх и того и другого.
Зачем нужна независимость уровней и где она протекает
Выключите кабель и включите Wi-Fi: IP-адрес может остаться тем же, TCP-соединения тем более ничего не узнают о смене среды (если адрес не поменялся). Поменяйте TCP на UDP: Ethernet не заметит. Это и есть выигрыш от уровней: за сорок лет сменилось несколько поколений физики, от коаксиала до 400-гигабитной оптики, а IP-пакет 1981 года в них всех одинаковый.
Но абстракция не абсолютна, и большая часть «интересных» сетевых проблем — там, где она протекает:
- MTU. Размер кадра L2 ограничивает размер пакета L3: в Ethernet это 1500 байт. Пакет большего размера надо либо резать (фрагментация), либо узнать об ограничении заранее (Path MTU Discovery). Об этом в частях 6 и 8, а симптом «пинг ходит, сайт не открывается» растёт именно отсюда.
- NAT. Домашний роутер, устройство L3, переписывает адреса в заголовке IP и порты в заголовке TCP/UDP, то есть лезет на уровень выше своего. Часть 6.
- Файрволы и балансировщики принимают решения по портам и даже по содержимому HTTP, хотя стоят посреди сети.
- Wi-Fi повторяет кадры при потерях на радио, и TCP над ним видит не потери, а странные задержки. Часть 3.
Понимание того, что уровни независимы по замыслу, но связаны на практике, — половина умения разбираться в сетевых проблемах.
Смотрим руками
На любой Linux-машине уровни видны прямо в командах. Каждая команда показывает свой этаж.
Канальный уровень — интерфейсы и их MAC-адреса:
$ ip link
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 3c:52:82:1a:2b:3c brd ff:ff:ff:ff:ff:ff
Сетевой уровень — IP-адреса и таблица маршрутов, по которой стек решает, кому отдать пакет:
$ ip addr show eth0
inet 192.168.1.10/24 brd 192.168.1.255 scope global dynamic eth0
$ ip route
default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10
Транспортный уровень — кто какие порты слушает:
$ ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))
И всё сразу — tcpdump. Запустите его в одном окне, а в другом откройте любой сайт:
$ sudo tcpdump -i eth0 -n -e -c 20
Ключи: -i — интерфейс, -n — не превращать адреса в имена (иначе tcpdump сам полезет в DNS и засорит вывод), -e — показывать заголовок Ethernet, -c — сколько пакетов поймать.
Ещё нагляднее Wireshark. Поймайте тем же tcpdump -w capture.pcap файл или запустите захват в самом Wireshark, откройте и щёлкните по любому пакету. Средняя панель — это ровно наша матрёшка, уровень за уровнем:
▸ Frame 1: 74 bytes on wire
▸ Ethernet II, Src: 3c:52:82:1a:2b:3c, Dst: d8:47:32:0a:0b:0c
▸ Internet Protocol Version 4, Src: 192.168.1.10, Dst: 203.0.113.10
▸ Transmission Control Protocol, Src Port: 51234, Dst Port: 443, Seq: 0, Len: 0
Раскройте каждый уровень: там все поля заголовка с значениями, а в нижней панели подсвечены байты, которым они соответствуют. В каждой следующей части серии мы будем смотреть на заголовки именно так.
Что запомнить
- Сетевой стек разбит на уровни, каждый решает одну задачу и пользуется уровнем под собой. OSI — семиуровневая модель-язык (L2, L3, L7), TCP/IP — четырёхуровневая модель того, как всё устроено на самом деле.
- Каждый уровень добавляет свой заголовок; на проводе — матрёшка Ethernet → IP → TCP/UDP → данные.
- В каждом заголовке есть поле «что внутри»: EtherType, Protocol, порт. По ним принимающая сторона разбирает матрёшку.
- Коммутатор смотрит на L2, роутер на L3, конечные машины — на всё. MAC-адреса меняются на каждом участке, IP-адреса доходят до конца.
- Абстракция уровней протекает: MTU, NAT, файрволы. Там живут самые интересные проблемы.
Дальше — Ethernet: формат кадра по байтам, устройство MAC-адреса, что на самом деле делает коммутатор, почему минимальный кадр — 64 байта и что такое duplex mismatch.
Оставить комментарий могут только зарегистрированные пользователи.
Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.