Путешествие сакуры из Японии в Россию по TCP/IP. Анатомия передачи файла: как выглядят фреймы, сегменты и пакеты
Допустим, я скачиваю фотографию ветки сакуры с сайта в Японии в формате PNG. Изображение ведь не умещается в одном фрейме и его стек TCP/IP поделит на фреймы. Вы знаете как выглядит каждый фрейм в этом случае и сколько их всего? Будет ли внутри них что-то меняться в процессе передачи из Японии в Россию?
Первое о чем вы, наверняка, подумали - заголовки. На всех этапах перемещения данных по стеку TCP/IP каждый протокол добавляет свой заголовок и передает информацию на следующий уровень абстракции (см. рисунок ниже): данные с уровня приложений получают заголовок TСP, потом — заголовок IP, потом — еще заголовок Ethernet. Затем считается контрольная сумма всего созданного из этих заголовков и данных фрейма (FCS). Причем на каждом уровне абстракции мы используем еще и разные названия для структур данных: фрейм (кадр), датаграмма, пакет, сегмент. На уровне приложений, согласно модели OSI ISO, используется термин транзакция. Транзакцией могут быть DNS-запрос и ответ, HTTP-запрос и ответ, SQL-запрос и ответ, запрос и ответный видеопоток YouTube или IP-телефонии. В количестве транзакций в секунду измеряют производительность NGFW, ведь его уровень сборки и анализа информации — именно уровень приложений.
В операционной системе есть программа, реализующая стек TCP/IP, и она делит данные, полученные от вышестоящего приложения, на сегменты TCP и добавляет заголовок сегмента размером минимум 20 байт.
А какой максимальный размер данных с уровня приложений мы можем отправить в одном фрейме? Этот параметр называется TCP maximum segment size (MSS) — максимальная длина сегмента данных TCP. Он, в свою очередь, зависит от максимально возможной длины кадра, которая может быть передана без фрагментации, — maximum transmission unit (MTU). MTU составляет 1500 байт у стандартных фреймов Ethernet и 9000 — у jumbo-фреймов. Значение MSS — это длина фрейма минус длины всех заголовков. Если внутри фрейма есть сегменты TCP, то MSS = MTU − 40 = 1460 байт. Ориентируйтесь на длины заголовков на рисунке ниже:
Обычно MSS определяется во время TCP-рукопожатия с целевым узлом исходя из значений MTU. Однако промежуточный маршрутизатор (например, канал с меньшим MTU) может прослушивать пакеты TCP SYN и подменять значения MSS, анонсируемые конечными устройствами. Такое часто бывает, если где-то посередине есть VPN-канал. В результате конечные узлы «договариваются» о меньших MSS, и пакеты не приходится фрагментировать.
В итоге все эти заголовки и данные объединяются в единый фрейм для передачи, и его длина в сумме составляет 1518 байт. Ваши файлы, записи голоса и видео в виде нарезанных кусочков c размером MSS перемещаются в поле Payload.
Для визуализации передачи фреймов по сети воспользуюсь схемой ниже (заметьте, что в заголовке кадра адрес получателя идет первым, а в IP-заголовке впереди находится уже адрес источника) и рекомендую статью на русском у Артема Санникова или оригинал статьи на английском у Cisco
Практика. Если мы хотим скачать картинку PNG с web-сервера, сколько нам нужно фреймов?
Рекомендую запустить Wireshark и посмотреть, как это будет выглядеть на вашем компьютере. Например, на скриншоте ниже видно, что картинка PNG размером 22 КБ уместилась в 16 сегментах TCP.
Посмотрите, как расположены заголовки, какой в вашей TCP-сессии MSS и какие еще поля есть, например номер последовательности и TTL.
Сколько фреймов займет SSL-транзакция?
Я знаю, что дотошные люди хотят знать про MTU с VLAN, QinQ, MPLS
Очевидно, дотошные люди хотят знать про VLAN, QinQ, MPLS. Они задаются вопросом: а как меняется MTU между свитчами и роутерами при наличии тегов VLAN? А никак :) Показатель остается 1500. Стандарт 802.3AC увеличивает максимальный размер фрейма до 1522 байт, чтобы добавлять информацию о VLAN-тегах 802.1q и битах COS 802.1p. А вот при QinQ нужно повышать MTU уже до 1504 байт. Приобщу для понимания картинку из более подробной статьи.
Вообще говоря, есть огромное количество стандартов IEEE 802.3 для Ethernet. Например, в стандарте 802.3AS максимальный размер фрейма уже 2000 байт (но не MTU).
Самое важное — знать, что как только размер MTU превышает возможности среды передачи, то фреймы фрагментируются. Это плохо влияет на скорость передачи, лучше так не делать. Если вы не знаете, какое значение MTU нужно использовать, то можете протестировать соединение и найти показатель, при котором начинается фрагментация:
ping 10.20.1.11 -M do -s "$((1500-20-8))" -c 1 > MTU_validation.txt
-M do — возвращает ошибку, если пакет ping фрагментирован. Здесь написан вариант ping для Linux при использовании ICMP-пакетов. В Windows применяйте ключи -f -l.
-s packetsize — размер данных:
o 1500 — тот показатель MTU, который хотите использовать;
o 20 — размер IP-заголовка;
o 8 — размер ICMP-заголовка.
TCP регулирует значения MSS, чтобы исключить фрагментацию фреймов.
Статья написана для тех, кто изучает сетевые технологии и их безопасность. Запустите у себя на компьютере wireshark и посмотрите как у вас выглядят сетевые соединения.
В продолжение рекомендую прочитать статью "Что меняется внутри фрейма Ethernet при передаче от роутера к роутеру?"