Протокол TCP

Протокол TCP

Дмитрий Бахтенков

Введение

В этой статье мы поговорим про протокол TCP. Это сетевой протокол транспортного уровня, который отвечает за передачу данных между различными приложениями. Он активно используется в базах данных, а на его основе реализуют другие протоколы уже прикладного уровня.

Зачем это изучать?

Протокол TCP - один из самых часто используемых протоколов в современных сетях. Знание устройства протокола может помочь в разработке и оптимизации сетевых приложений, при работе с безопасностью сети. Протокол TCP активно используется в различных приложениях: поверх него реализован протокол HTTP, WebSocket. Также по TCP мы общаемся с различными СУБД (например MySQL или Postgres).

Прежде чем изучать сам протокол TCP, давайте разберёмся, а что вообще за уровни передачи данных, какой из них транспортный и что вообще происходит. На эти вопросы нам ответит модель TCP/IP.

Модель TCP/IP

TCP/IP - это сетевая модель передачи данных, представленных в цифровом виде. Эта модель описывает протоколы (правила) передачи данных от источника информации к получателю. В модели TCP/IP предполагается прохождение информации через четыре уровня, каждый из которых описывается определёнными протоколами передачи данных.

Базовые протоколы в этой модели - TCP (Transmission Control Protocol) и IP (Internet Protocol). Отсюда и название.

Фан факт: модель TCP/IP может упоминаться как модель DOD - Department Of Defence, так как её разработка финансировалась Министерством Обороны США. К сожалению, я не нашел теорий заговора на эту тему, было бы очень интересно.

Всё начинается с канального, физического уровня данных. К этому уровню относят протоколы Ethernet, WLAN и другие. Канальный уровень — это группа методов и протоколов связи, которые работают только на канале, к которому физически подключен хост. Соединение — физический и логический сетевой компонент, используемый для соединения хостов или узлов в сети, а протокол соединения — это набор методов и стандартов, которые работают только между соседними сетевыми узлами сегмента локальной сети или подключения к глобальной сети.

Далее мы поднимаемся на уровень выше и приходим в Internet Layer (Или “Network Layer”, в разных источниках по-разному). Этот уровень изначально разработан для передачи данных из одной сети в другую. На нём работают маршрутизаторы, которые перенаправляют пакеты в нужную сеть путём расчёта адреса сети по маске сети. Основным протоколом здесь является IP. Именно этот протокол объединил отдельные компьютерные сети во всемирную сеть (интернет).

Ну и наконец, тема этой статьи - транспортный уровень. Протоколы этого уровня определяют, для какого именно приложения предназначены данные, как эти данные будут туда доставляться и гарантируется ли целостность данных. Ключевыми протоколами этого уровня являются TCP и UDP.

На самом верху таблицы находится прикладной уровень. Он обеспечивает взаимодействие сети и пользователя. Уровень разрешает приложениям пользователя иметь доступ к сетевым службам, таким как обработчик запросов к базам данных, доступ к файлам, пересылке электронной почты. Также отвечает за передачу служебной информации, предоставляет приложениям информацию об ошибках. Одним из самых распространённых протоколов этого уровня является HTTP, о котором, кстати, уже была статья.

Инкапсуляция, декапсуляция и данные

Все протоколы сетевой модели TCP/IP так или иначе манипулируют какими-то данными, в разных форматах. На каждом уровне модели мы манипулируем некоторой полезной нагрузкой (данными) и заголовочной информацией, которая содержит какие-то настройки, метаданные, контрольные суммы для поддержки целостности данных и прочую полезную информацию.

Инкапсуляция - это процесс добавления заголовка к данным на каждом уровне сетевой модели. При передаче данных заголовок добавляется на уровне отправителя и удаляется на уровне получателя. Каждый заголовок содержит информацию о том, как обрабатывать данные на каждом уровне модели.

Декапсуляция - это процесс удаления заголовка на каждом уровне сетевой модели при передаче данных. Каждый уровень декапсулирует данные и передает их на уровень выше.

Давайте посмотрим, как происходит инкапсуляция на практике. Допустим, у нас есть некоторый HTTP-запрос. У него есть некоторые заголовки и полезная нагрузка, этот запрос относится к прикладному уровню.

На уровень ниже, в пакет данных для протокола TCP будут упакованы данные и заголовки для HTTP, и к этому всему добавлены новые заголовки:

На следующем, сетевом уровне, будет произведено аналогичное действие с пакетом данных транспортного уровня:

Ну и на самом низком уровне, например в протоколе Ethernet, данные упакуются в так называемые фреймы (Frame). И их полезной нагрузкой будет являться содержимое пакета протокола IP:

В рамках декапсуляции данные проходят тот же путь, только не вниз, а вверх (то есть от канального до прикладного уровня). На каждом уровне распаковывается полезная нагрузка из более низкого уровня:

Итак, основы мы изучили. Теперь поговорим непосредственно о TCP.

TCP

TCP (Transmission Control Protocol) - это надежный протокол, который работает на транспортном уровне стека протоколов TCP/IP. Он используется для установления соединений между сетевыми устройствами и управления ими и обеспечивает надежную и упорядоченную передачу данных.

Внутреннее устройство

Данные, подлежащие отправке, на уровне TCP представляются потоком байт, где каждый байт последовательно пронумерован. TCP делит поток на части — сегменты — и передает их на более низкий (сетевой) уровень для отправки получателю. Каждый сегмент включает в себя некоторые заголовки (headers) и непосредственно данные (payload).

Рассмотрим каждый заголовок подробнее

  • Порты (Source & Destination) - эти поля, размером в 16 бит, содержат номера портов - с какого на какой порт мы отправляем данные. Различные приложения работают на различных портах, например PostgreSQL использует порт 5432. Существует специальный список портов и приложений, которые и используют по умолчанию.
  • Порядковый номер (Sequence Number) - номер первого байта сегмента в общем потоке.
  • Номер подтверждения (ACK SN) - порядковый номер следующего сегмента, ожидаемого от отправителя. Значение Ack означает, что вся непрерывная последовательность байт с первого до Ack-1 приняты успешно.
  • Длина заголовка (Data Offset) - указывает значение длины заголовка. Минимальное значение - 20 байт, а максимальное - 60
  • Размер окна (Window Size) - максимальный размер одного получаемого сегмента. Получатель может управлять интенсивностью получаемых данных с помощью этого заголовка. Если получатель сообщает о нулевом Window Size, передача данных приостанавливается.
  • Флаги. Это поле содержит 9 битовых флагов для управления протоколом.
  • Контрольная сумма (Checksum) - это поле, которое используется для обнаружения ошибок в передаваемых данных. Она вычисляется с помощью математического алгоритма, который учитывает IP-адреса источника и назначения, заголовки и данные TCP-сегмента
  • Urgent Pointer - это поле в заголовке TCP, которое используется для указания того, что определенные данные в сегменте TCP являются срочными и требуют немедленного внимания принимающего устройства. Этот заголовок используется в ситуациях, когда определенные данные в сегменте важнее других данных и должны быть обработаны раньше остальных данных.
  • Дополнительные опции - некоторые значения, которые могут использоваться для тестирования или хранения служебной информации в сегменте TCP.

Принцип работы

TCP устанавливает соединения, которые должны быть созданы перед передачей данных. TCP-сеанс можно разделить на 3 стадии:

  • Установка соединения
  • Передача данных
  • Завершение соединения

У сеанса есть множество состояний, которые описывают некоторый статус TCP-соединения. Начальное состояние сеанса - CLOSED.

Соединение TCP

Процесс установки соединения TCP называется “рукопожатием” (handshake). “Рукопожатие” состоит из трёх шагов:

  1. Отправитель отправляет сегмент с установленным флагом SYN (synchronize) и случайным порядковым номером seq=x на порт получателя.
Приложение отправителя вначале создает сегмент TCP, устанавливает в нем флаг SYN (synchronize) и генерирует случайный порядковый номер seq=x. Флаг SYN говорит получателю, что отправитель хочет установить соединение. Порядковый номер seq=x нужен для идентификации данного сегмента в общем потоке данных и позволяет получателю правильно упорядочить данные. После этого сегмент отправляется на порт получателя.
  1. Получатель отправляет сегмент с установленными флагами SYN и ACK (acknowledgment), номером подтверждения ack=x+1 и своим порядковым номером seq=y.
Когда получатель получает сегмент с установленным флагом SYN, он отправляет в ответ на него свой сегмент. В этом сегменте устанавливаются флаги SYN и ACK, номер подтверждения ack=x+1 и порядковый номер seq=y. Флаг ACK говорит отправителю, что получатель получил сегмент с флагом SYN и готов продолжать процесс установки соединения. Порядковый номер seq=y нужен для идентификации данного сегмента в общем потоке данных и позволяет отправителю правильно упорядочить данные.
  1. Отправитель отправляет сегмент с установленным флагом ACK и номером подтверждения ack=y+1.
После того, как получатель отправил сегмент с установленными флагами SYN и ACK, отправитель получает этот сегмент и отправляет в ответ на него свой сегмент с установленным флагом ACK и номером подтверждения ack=y+1. Флаг ACK говорит получателю, что отправитель получил его сегмент с флагами SYN и ACK и готов продолжить процесс установки соединения.

В результате этого процесса установки соединения у отправителя и получателя устанавливается соединение, которое позволяет начать передачу данных.

TCP A                                                    TCP B
   1.  CLOSED                                               LISTEN
   2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED
   3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED
   4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>      --> ESTABLISHED
   5.  ESTABLISHED <-- <SEQ=301><ACK=101><CTL=ACK>      <-- ESTABLISHED

Передача данных по TCP

Процесс передачи данных - это этап сеанса, на котором фактические данные отправляются и принимаются между взаимодействующими узлами. Этот этап обычно включает в себя следующие шаги:

  1. Сегментация данных: прежде чем данные смогут быть отправлены по TCP-соединению, их необходимо разбить на сегменты. Сегменты TCP обычно имеют размер около 1500 байт, что является максимальной единицей передачи (MTU) для большинства сетей.
  2. Нумерация и последовательность сегментов: отправитель присваивает каждому сегменту TCP уникальный порядковый номер. Порядковый номер позволяет получателю изменять порядок сегментов, которые могут поступать не по порядку, и обнаруживать любые отсутствующие или дублирующиеся сегменты.
  3. Управление потоком данных: чтобы предотвратить перегрузку отправителя данными получателя, TCP использует механизм управления потоком данных (Flow control), который регулирует скорость отправки данных. Управление потоком осуществляется за счет использования поля Window Size, которые указывают объем данных, которые принимающая сторона в данный момент может принять.
  4. Повторная передача: если сегмент потерян или не подтвержден получателем, TCP повторно передаст сегмент по истечении периода ожидания. Это гарантирует, что все данные в конечном итоге будут доставлены получателю, даже при наличии сетевых ошибок или перегрузки.
  5. Подтверждение: после получения каждого сегмента TCP получатель отправляет пакет подтверждения (ACK) отправителю для подтверждения получения. Пакет ACK содержит следующий порядковый номер, который ожидает получить получатель.
  6. Повторная сборка данных: получатель повторно собирает принятые сегменты TCP в их первоначальном порядке и передает данные принимающему приложению.
  7. Keep-alive: для поддержания сеанса TCP и обнаружения любых сбоев, TCP использует периодические пакеты поддержания работоспособности, которые отправляются каждой конечной точкой, чтобы проверить, все ли еще активна другая конечная точка.

В целом, процесс передачи данных в TCP включает в себя множество механизмов, которые обеспечивают надежную, упорядоченную и эффективную доставку данных между взаимодействующими конечными точками.

Завершение TCP-соединения

Процесс завершения TCP-соединения включает в себя следующие шаги:

  1. Отправитель отправляет сегмент с установленным флагом FIN (finish) и номером последовательности seq=x на порт получателя. Этот говорит получателю, что отправитель хочет завершить соединение. После отправки сегмента с флагом FIN, отправитель больше не может отправлять данные.
  2. Получатель отправляет сегмент с установленными флагами ACK и номером подтверждения ack=x+1, тем самым сообщая отправителю, что он получил флаг FIN и готов завершить соединение.
  3. Получатель отправляет сегмент с установленным флагом FIN и номером последовательности seq=y на порт отправителя. Таким образом, получатель сообщает, что он тоже хочет завершить соединение
  4. Отправитель отправляет сегмент с установленными флагами ACK и номером подтверждения ack=y+1 на порт получателя.

После этого процесса завершения соединения TCP заканчивается, и соединение закрывается.

Немного практики

Для того, чтобы посмотреть на работу TCP-протокола, мы развернём БД PostgreSQL, выполним к ней пару запросов.

Я поднял PostgreSQL с помощью docker, но его можно поднять и просто установив на ПК. В качестве админки я установил pgAdmin.

Для анализа трафика мы будем использовать утилиту Wireshark — это популярный инструмент для анализа сетевых протоколов, который обычно используется для анализа сетевого трафика. Это мощный инструмент, который можно использовать для захвата и проверки пакетов данных, передаваемых по сети. Анализируя TCP-трафик с помощью Wireshark, мы можем лучше понять, как работает протокол TCP.

Вообще, Wireshark используется:

  • Системными администраторами для устранения неполадок сети
  • Инженерами сетевой безопасности - для проверки безопасности сети и конкретных протоколов
  • Разработчики, которые делают собственный сетевой протокол, могут использовать его для отладки этого протокола
  • Тестировщики могут использовать его для тестирования сетевых приложений

Я установил Wireshark с оффициального сайта. Чтобы анализировать трафик, необходимо выбрать источник этого трафика.

В случае с docker я выбрал “adapter for loopback traffic capture”. Перейдя туда, увидел много различных TCP-сообщений, в основном PSH (push) и ACK

Эти записи мы можем проигнорировать. Давайте зайдём в pgAdmin и добавим новую базу данных:

Wireshark настолько умный, что сам распознаёт запросы в Postgres. Чтобы найти нужные нам записи, просто введём pgsql в строку поиска:

В качестве данных PgAdmin передал в СУБД команду CREATE DATABASE ….

Мы можем раскрыть информацию о заголовках Transmission Control Protocol и посмотреть, что же находится внутри:

Исходя из этой информации можно понять, что PgAdmin отправляет данные с порта 31268.

Или увидеть, что чексумма не подтверждена!

К счастью, это не значит, что данные невалидны или что-то сломалось. Просто сейчас вычисление чексуммы происходит на уровне железа, а не программно, поэтому мы её и не видим.

Попробуем поотправлсять ещё запросы. Например, добавим таблицу:

И добавим одну строку:

С кириллицей, вайршарк, конечно не очень дружит 🙂

Кстати, я заметил, что pgAdmin любые изменения строк в интерфейсе оборачивает в транзакцию:

Wireshark обладает гораздо более мощным функционалом помимо того, что был показан в этой статье. Но теперь в вашей копилке знаний есть информация о нем, и при желании вы сможете изучить его самостоятельно.

Заключение

Протокол TCP является одним из самых часто используемых протоколов транспортного уровня. С помощью этого протокола работают различные базы данных, мессенджеры и другие сетевые приложения. На его основе работает множество протоколов прикладного уровня: от массовых http или WebSocket, до кастомных протоколов от отдельных приложений, например MTProto от Telegram.

С вами был Flex Code.

Report Page