Учите по одному предложению на английском языке каждый день и каждый день добивайтесь небольшого прогресса:
предисловие
«А? Что такое большая белая акула?»
Кхм, в основном из-за инструментов сетевого анализаWireshark
Икона особенно напоминает рог на вершине большой белой акулы.
Если вы мне не верите, см.:
«Почему так долго публиковали?»
Для того, чтобы всем было проще "увидеть" TCP, я построил множество тестовых сред и много раз перехватывал пакеты данных.На перехват пакетов данных, которые легче анализировать, ушло много времени.
Далее, характеристики TCP, такие как потеря пакетов, нарушение порядка, повторная передача по тайм-ауту, быстрая повторная передача, выборочное подтверждение, управление потоком и т. д.
Верно, я сорвал с TCP «одежду», просто чтобы показать всем ясно, хи-хи.
текст
Явно «невидимые» сетевые пакеты
Взаимодействие пакетов данных в сетевом мире невидимо для нашего невооруженного глаза, и они кажутся невидимыми.Когда мы изучаем компьютерные сети по учебникам, мы будем чувствовать себя очень абстрактно, что увеличивает сложность обучения.
Не говоря уже о том, что когда я сам учился в колледже, было то же самое.
Пока после работы я изучил два мощных инструмента для анализа сети:tcpdump и Wireshark, эти два мощных инструмента представляют наши «невидимые» пакеты данных перед нашими глазами, что ясно с первого взгляда.
Увы, когда я изучал дживан в колледже, если бы я знал об этих двух инструментах, я бы так не запутался.
В чем разница между tcpdump и Wireshark?
Tcpdump и Wireshark являются наиболее часто используемыми инструментами захвата и анализа сетевых пакетов, а также незаменимыми инструментами для анализа производительности сети.
- tcpdump поддерживает только формат командной строки и часто используется для захвата и анализа сетевых пакетов на серверах Linux.
- В дополнение к захвату пакетов Wireshark также предоставляет графическую страницу для визуального анализа сетевых пакетов.
Таким образом, они фактически используются вместе.Сначала используйте команду tcpdump для захвата пакетов на сервере Linux, а затем перетащите захваченные файлы на компьютер Windows для визуального анализа с помощью Wireshark.
Конечно, если вы перехватываете пакеты в Windows, просто используйте инструмент Wireshark.
Как tcpdump захватывает пакеты в Linux?
tcpdump предоставляет большое количество опций и различных выражений фильтра, которые помогут вам захватить указанные пакеты данных, но не беспокойтесь, вам нужно только освоить некоторые общие параметры и выражения фильтра, чтобы удовлетворить потребности большинства сценариев.
Предположим, мы хотим перехватить следующие пакеты ping:
Чтобы перехватить вышеуказанный пакет команды ping, сначала нам нужно знать, что пакет pingicmp
протокола, а затем при использовании tcpdump для захвата пакетов можно указать захватывать только пакеты протокола icmp:
Затем, когда tcpdump перехватывает пакет icmp, выходной формат выглядит следующим образом:
Из пакетов icmp, захваченных tcpdump, мы можем ясно видетьicmp echo
Процесс взаимодействия завершен, сначала отправитель инициируетICMP echo request
Сообщение запроса, получатель возвращает сообщение после его полученияICMP echo reply
ответное сообщение, послеseq
является инкрементным.
Я также отсортировал для вас некоторые из наиболее распространенных употреблений и свел их в таблицу для справки.
Во-первых, давайте взглянем на обычно используемые классы опций.В приведенном выше примере ping мы использовали-i
Опция указывает сетевой порт, используемый-nn
Параметры не разрешают IP-адреса и имена портов. Другие часто используемые параметры, как показано в следующей таблице:
Далее, давайте взглянем на обычно используемую таблицу фильтров.В приведенном выше примере ping мы использовалиicmp and host 183.232.231.174
, что означает захват пакетов данных протокола icmp, а также пакетов, адрес отправителя или адрес получателя которых равен 183.232.231.174. Другие часто используемые параметры фильтрации я также организовал в следующей таблице.
Сказав так много, вы также должны были обнаружить, что, хотя tcpdump является мощным, формат вывода не интуитивно понятен.
Поэтому на работе tcpdump используется только для захвата пакетов данных, а не для анализа пакетов данных, а для сохранения пакетов данных, захваченных tcpdump, в виде файлов с суффиксом pcap, а затем для анализа пакетов данных используется инструмент Wireshark.
Как инструмент Wireshark анализирует пакеты?
В дополнение к захвату пакетов Wireshark также предоставляет графическую страницу для визуального анализа сетевых пакетов, а также ряд встроенных инструментов сводного анализа.
Например, взяв приведенный выше пример ping, мы можем использовать следующую команду для сохранения захваченных пакетов в файл ping.pcap.
Затем перетащите файл ping.pcap на компьютер и откройте его с помощью Wireshark. После открытия вы можете увидеть следующий интерфейс:
правильно? На странице Wireshark вы можете более интуитивно анализировать пакеты данных, не только отображая информацию о заголовке каждого сетевого пакета, но и используя разные цвета для различения разных протоколов.Поскольку этот захват пакетов имеет только протокол ICMP, есть только фиолетовые записи . . .
Затем, после выбора сетевого пакета в списке сетевых пакетов, в сведениях о сетевом пакете под ним,Можно более четко увидеть, что подробная информация об этом сетевом пакете на каждом уровне стека протоколов. Например, возьмем сетевой пакет номер 1 в качестве примера:
- На канальном уровне вы можете увидеть информацию заголовка MAC, такую как поля MAC-адреса источника и MAC-адреса назначения;
- На уровне IP вы можете увидеть информацию заголовка IP, такую как IP-адрес источника и IP-адрес назначения, TTL, длина IP-пакета, протокол и т. д. Значение и значение каждого поля IP-протокола;
- Вы можете просмотреть информацию заголовка ICMP на уровне ICMP, такую как значение и значение каждого поля протокола ICMP, такого как тип и код;
Wireshark использует многоуровневый метод для отображения информации заголовка пакета каждого уровня и четко показывает нам «невидимые» пакеты данных.Есть ли какая-то причина не изучать компьютерные сети? не так лиувидимся позже?
На примере ping мы видим, что многоуровневая сеть похожа на упорядоченное разделение труда.Каждый уровень имеет свою сферу ответственности и информацию.После того, как протокол верхнего уровня завершает работу, он передается следующему уровню, и, наконец, формируется полная сеть Сумка.
Расшифровать трехстороннее рукопожатие TCP и четырехстороннюю волну
Теперь, когда мы изучили два основных инструмента сетевого анализа, tcpdump и Wireshark, давайте продолжим и воспользуемся ими для захвата и анализа сетевых пакетов протокола HTTP, а также поймем принцип работы трехстороннего рукопожатия TCP и четырехсторонней волны.
В этом примере мы получим доступ к серверу http://192.168.3.200. Используйте команду tcpdump для захвата пакетов в первом терминале:
Затем выполните следующую команду curl на Терминале 2:
Наконец, вернитесь в Терминал 1, нажмите Ctrl+C, чтобы остановить tcpdump, и перенесите полученный http.pcap на компьютер.
После открытия http.pcap с помощью Wireshark вы увидите следующий интерфейс в Wireshark:
Все мы знаем, что HTTP передается на основе протокола TCP, тогда:
- Первые три пакета — это пакеты для трехэтапного рукопожатия TCP для установления соединения.
- Посередине находятся пакеты HTTP-запроса и ответа.
- И последние 3 пакета это вейв пакеты отключения TCP
Wireshark умеет отображать процесс взаимодействия пакетов на диаграмме последовательности.В строке меню нажмите Статистика -> График потока, а затем во всплывающем интерфейсе выберите «Потоки TCP» в «Тип потока». выполнение потока TCP на протяжении всего процесса:
Вам может быть интересно, почему Seq процесса трехэтапного рукопожатия равен 0?
На самом деле, поскольку оптимизацию за нас выполнил инструмент Wireshark, по умолчанию он показывал, что порядковый номер seq является относительным, а не реальным значением.
Если вы хотите увидеть фактическое значение серийного номера, вы можете щелкнуть правой кнопкой мыши меню, затем найти «Настройки протокола», затем найти «Относительная последовательность» и отменить его следующим образом:
После отмены Seq показывает истинное значение:
Видно, что серийные номера клиента и сервера на самом деле разные, а серийный номер является случайным значением.
На самом деле это очень похоже на трехстороннее рукопожатие TCP и четырехстороннюю волну, которые мы видели в нашей книге.Для сравнения, процесс трехстороннего рукопожатия TCP и четырехсторонней волны, который вы обычно видите, в основном выглядит следующим образом:
Почему захваченный ПТС махается три раза, а не четыре раза, как написано в книге?
Поскольку сервер получаетFIN
После этого сервер должен одновременно закрыть соединение, чтобыACK
а такжеFIN
Объединенные и отправленные вместе, сохранение одного пакета становится «тремя волнами».
Обычно сервер получает запрос клиента.FIN
После этого, вероятно, данные еще не были отправлены, поэтому сначала ответит клиенту.ACK
Пакет, подождите некоторое время, после того, как все пакеты данных будут отправлены, он будет отправленFIN
Мешок четыре машет.
Как показано на рисунке ниже, это процесс четырехкратного взмаха руками:
Практический анализ нештатной ситуации трехэтапного рукопожатия TCP
Считается, что процесс трехэтапного рукопожатия TCP знаком всем, поэтому задумывались ли вы когда-нибудь об этих трех нештатных ситуациях:
- Потерян SYN первого рукопожатия TCP, что происходит?
- Пакеты SYN и ACK второго рукопожатия TCP потеряны, что произойдет?
- Что происходит, когда пакет ACK третьего рукопожатия TCP потерян?
Некоторые знакомые могут сказать: «Все очень просто, если пакет потеряется, он будет передан повторно».
Тогда я продолжаю вас просить:
- Сколько раз он будет ретранслироваться?
- Как изменится время RTO повторной передачи тайм-аута?
- Как установить количество повторных передач в Linux?
- ….
Вы потеряли дар речи и не можете ответить?
Неважно, если вы не знаете.Далее я буду использовать три экспериментальных случая, чтобы заставить всех исследовать эти три аномалии.
Экспериментальная сцена
В этом эксперименте используются две виртуальные машины, одна в качестве сервера, а другая в качестве клиента. Их взаимосвязь следующая:
- И клиент, и сервер — CentOs 6.5 Linux, версия ядра Linux 2.6.32.
- Сервер 192.168.12.36, веб-сервис apache
- клиент 192.168.12.37
Эксперимент 1: потеря SYN-пакета при первом рукопожатии TCP
Чтобы смоделировать потерю SYN-пакетов при первом рукопожатии TCP, я сразу же выполнил команду curl на клиенте после отключения сетевого кабеля сервера:
Команда tcpdump для захвата пакетов выглядит следующим образом:
Через некоторое время curl возвращает ошибку подключения по тайм-ауту:
отdate
Время возвращено, можно обнаружить, что curl вернул ошибку после того, как тайм-аут был близок к 1 минуте.
Затем откройте файл tcp_sys_timeout.pcap с помощью Wireshark для анализа, и отобразится следующий рисунок:
Как видно из рисунка выше, после того, как клиент инициировал пакет SYN, он не получил ACK от сервера, поэтому он был повторно передан 5 раз с течением времени, и время ожидания RTO каждый раз разное:
- Первый раз - повторная передача с тайм-аутом в 1 секунду
- Второй - повторная передача с 3-секундным тайм-аутом.
- Третий раз — повторная передача с 7-секундным тайм-аутом.
- Четвертая — ретрансляция с 15-секундным тайм-аутом.
- Пятый раз - повторная передача с тайм-аутом 31 секунда.
Можно обнаружить, что каждый тайм-аут RTO равенИндекс (удвоенный) вверх, при превышении максимального количества повторных передач клиент больше не будет отправлять SYN-пакеты.
В Linux первое рукопожатиеSYN
Количество повторных передач тайм-аута определяется следующими параметрами ядра:
$ cat /proc/sys/net/ipv4/tcp_syn_retries
5
tcp_syn_retries
Значение по умолчанию — 5, то есть максимальное количество повторных передач SYN — 5 раз.
Далее продолжаем экспериментировать, ставяtcp_syn_retries
Установите в 2 раза:
$ echo 2 > /proc/sys/net/ipv4/tcp_syn_retries
После повторной передачи захваченного пакета откройте анализ с помощью Wireshark, и отобразится следующий рисунок:
Экспериментальное резюме эксперимента один
Благодаря экспериментальным результатам эксперимента 1 мы можем знать, что когда клиент инициирует первый SYN-пакет TCP-рукопожатия и не получает ACK от сервера в течение периода ожидания, пакет SYN будет повторно передан в течение периода ожидания, а повторная передача будет выполняться каждый тайм-аут.RTO удваивается до тех пор, пока не будет достигнуто количество повторных передач SYN-пакетаtcp_syn_retries
После установки значения клиент больше не отправляет пакеты SYN.
Эксперимент 2: второе рукопожатие TCP SYN, потеря пакета ACK
Чтобы имитировать, что клиент не может получить пакеты SYN и ACK второго рукопожатия от сервера, мой подход состоит в том, чтобы добавить ограничения брандмауэра для клиента и напрямую и грубо отбросить данные с сервера.Брандмауэр настроен следующим образом. :
Затем выполните команду curl на клиенте:
отdate
До и после времени возврата можно подсчитать, что примерно через 1 минуту curl сообщил об ошибке и завершил работу.
Пакеты данных, захваченные клиентом в течение этого периода, открываются и анализируются с помощью Wireshark, и отображаемая диаграмма последовательности выглядит следующим образом:
Из рисунка видно, что:
- После того, как клиент инициирует SYN, поскольку брандмауэр блокирует все пакеты данных с сервера, curl не может получить пакеты SYN и ACK от сервера.Когда происходит тайм-аут, пакет SYN будет передан повторно.
- После того, как сервер получит пакет SYN от клиента, он вернет пакеты SYN и ACK, но клиент не вернул ACK.По истечении времени ожидания сервер повторно передает пакеты SYN и ACK.Через некоторое время на сервер приходит SYN-пакет, повторно переданный клиентом overtime.После того, как сервер его получает, таймер тайм-аута пересчитывается, а затем возвращаются SYN- и ACK-пакеты, поэтому таймер тайм-аута на стороне сервера срабатывает. только сработал.Еще раз сбросил.
- Наконец, время ожидания повторной передачи SYN клиента достигает 5 раз (значение tcp_syn_retries по умолчанию равно 5 раз), и он больше не будет отправлять пакеты SYN.
Итак, мы можем найти это,Когда пакеты SYN и ACK второго рукопожатия потеряны, клиент будет повторно передавать пакет SYN с течением времени, и сервер также будет повторно передавать пакеты SYN и ACK с течением времени.
Хм? Клиент установил брандмауэр для блокировки сетевых пакетов сервера.Почему tcpdump все еще может перехватывать сетевые пакеты сервера?
После добавления ограничений iptables способность tcpdump перехватывать пакеты зависит от добавленных ограничений iptables:
- Если вы добавите
INPUT
правила, вы можете захватывать пакеты - Если вы добавите
OUTPUT
правила, пакет не может быть пойман
Последовательность сетевых пакетов, поступающих на хост, следующая:
- Порядок, который приходит в Wire -> NIC ->tcpdump -> netfilter/iptables
- порядок выходаiptables -> tcpdump -> NIC -> Wire
tcp_syn_retries ограничивает количество повторных передач SYN Каково максимальное количество повторных передач для второго рукопожатия SYN и ACK?
Максимальное количество повторных передач пакетов SYN и ACK во втором рукопожатии TCP осуществляется черезtcp_synack_retries
Значения параметров ядра по умолчанию следующие:
$ cat /proc/sys/net/ipv4/tcp_synack_retries
5
Да, значение по умолчанию для максимального количества повторных передач пакетов SYN и ACK во втором рукопожатии TCP равно5
Второсортный.
Чтобы убедиться, что максимальное количество повторных передач пакетов SYN и ACK равно 5 раз, мы продолжаем делать следующий эксперимент.tcp_syn_retries
Если установлено значение 1, это означает, что максимальное количество тайм-аутов SYN клиента равно 1. Цель состоит в том, чтобы предотвратить множественные повторные передачи SYN и сбросить таймеры тайм-аута SYN и ACK сервера.
Затем те же действия, что и выше:
- Клиент настраивает брандмауэр для блокировки пакетов данных сервера.
- Клиентский tcpdump захватывает пакеты данных при выполнении curl
Откройте захваченный пакет данных с помощью Wireshark для анализа, и отображаемая диаграмма последовательности выглядит следующим образом:
Из приведенного выше рисунка мы можем проанализировать:
- SYN клиента был ретранслирован только 1 раз, т.к.
tcp_syn_retries
значение равно 1 - После того, как сервер отвечает на пакет SYN, повторно переданный клиентом с течением времени, поскольку пакет ACK от клиента не был получен, сервер повторно передает пакеты SYN и ACK с течением времени, и каждое RTO также увеличивается экспоненциально, в 5 раз, потому что
tcp_synack_retries
значение 5
Далее я ставлюtcp_synack_retries установлено на 2,tcp_syn_retries
По-прежнему установлено значение 1:
$ echo 2 > /proc/sys/net/ipv4/tcp_synack_retries
$ echo 1 > /proc/sys/net/ipv4/tcp_syn_retries
Продолжайте выполнять те же экспериментальные шаги, затем откройте захваченные пакеты данных с помощью Wireshark для анализа, и отображаемая диаграмма последовательности выглядит следующим образом:
видимый:
- Пакет SYN клиента повторно передается только один раз сверхурочно, что соответствует значению, установленному tcp_syn_retries;
- Тайм-ауты SYN и ACK сервера передаются дважды, что соответствует значению, установленному tcp_synack_retries.
Краткое изложение эксперимента 2
Благодаря экспериментальным результатам эксперимента 2 мы можем знать, что при потере пакетов SYN и ACK второго рукопожатия TCP клиентский SYN-пакет будет повторно передан с течением времени, а серверные SYN и ACK также будут повторно переданы с течением времени.
Максимальное количество повторных передач клиентских SYN-пакетов с течением времени определяется параметром tcp_syn_retries, значение по умолчанию — 5 раз, максимальное количество повторных передач серверных SYN- и ACK-пакетов определяется параметром tcp_synack_retries, значение по умолчанию — 5 раз.
Эксперимент 3: потеря пакета ACK третьего рукопожатия TCP
Чтобы имитировать потерю пакетов ACK при третьем рукопожатии TCP, мой экспериментальный метод заключается в настройке брандмауэра на стороне сервера для защиты пакетов, бит флага которых равен ACK в сообщении TCP клиента, то есть когда сервер получает сообщение TCP ACK клиента. Оно будет отброшено, если команда конфигурации iptables будет выглядеть следующим образом:
Затем выполните на клиенте следующую команду tcpdump:
Затем клиент инициирует telnet к серверу, потому что команда telnet инициирует TCP-соединение, поэтому используйте эту команду для проверки:
В это время, поскольку сервер не может получить пакет ACK третьего рукопожатия, он находится вSYN_RECV
условие:
Клиент завершил установление TCP-соединения и находится вESTABLISHED
условие:
Через 1 минуту обратите внимание, что TCP-соединение на сервере пропало:
Через 30 минут клиент все еще находится вESTABLISHED
условие:
Затем в сеансе telnet, установленном клиентом, введите 123456 символов для отправки:
На «долгое» время телнет клиента отключается:
На этот раз вышеизложенное является феноменом реализации три.Здесь есть два сомнения:
- Почему сервер изначально в
SYN_RECV
Статус подключения пропадает через 1 минуту? - Почему telnet отключается через долгое время после того, как клиент telnet вводит 123456 символов?
Не волнуйтесь, мы используем Wireshark, чтобы открыть анализ только что захваченного пакета данных, и отображаемая диаграмма последовательности выглядит следующим образом:
Процесс, показанный выше:
- Клиент отправляет серверу пакет SYN. После того, как сервер его получает, он возвращает клиенту пакеты SYN и ACK. В это время TCP-соединение сервера находится в состоянии
SYN_RECV
государство; - После того, как клиент получает пакеты SYN и ACK от сервера, он возвращает пакет ACK на сервер.В это время TCP-соединение клиента находится в активном состоянии.
ESTABLISHED
государство; - Поскольку сервер настроен с помощью брандмауэра для блокировки пакета ACK клиента, сервер был в
SYN_RECV
статус, не введенESTABLISHED
Причина, по которой tcpdump может захватывать пакет ACK клиента, заключается в том, что порядок пакетов данных, поступающих в систему, заключается в том, чтобы сначала войти в tcpudmp, а затем пройти через iptables; - Затем сервер ретранслировал пакеты SYN и ACK с течением времени, и после 5 ретрансляций, т.е.Превышает значение tcp_synack_retries (значение по умолчанию 5), а затем не продолжает повторную передачу.В это время TCP-соединение сервера активно завершается, поэтому TCP-соединение в состоянии SYN_RECV только что разорвано, в то время как клиент все еще находится в
ESTABLISHED
государство; - Хотя сервер TCP отключен, через некоторое время обнаруживается, что клиент все еще находится в
ESTABLISHED
состояние, поэтому в сеансе telnet клиента было введено 123456 символов; - На данный момент, поскольку сервер был отключен,Пакеты данных, отправленные клиентом, были повторно переданы с течением времени. Значение RTO увеличивается экспоненциально с каждой повторной передачей, поэтому телнету клиента потребовалось много времени, чтобы сообщить об ошибке и завершить работу. На данный момент в общей сложности было выполнено 15 повторных передач. сделано.
Благодаря этой волне анализа только что развеялись два сомнения:
- Сервер превышает максимальное количество повторных передач при повторной передаче пакетов SYN и ACK.
tcp_synack_retries
, поэтому TCP-соединение на сервере активно разрывается. - Когда клиент отправляет пакет данных на сервер, поскольку TCP-соединение сервера было разорвано, пакет данных был повторно передан с течением времени, и telnet отключился после 15 повторных передач.
Максимальное количество повторных передач пакетов SYN с тайм-аутом при первом квитировании TCP определяется параметром tcp_syn_retries, а максимальное количество повторных передач пакетов SYN и ACK с тайм-аутом во втором квитировании TCP определяется параметром tcp_synack_retries. подключение Какой параметр указывает количество раз?
Для передачи пакета данных после того, как TCP устанавливает соединение, максимальное количество повторных передач тайм-аута определяетсяtcp_retries2
Укажите, значение по умолчанию — 15 раз, как показано ниже:
$ cat /proc/sys/net/ipv4/tcp_retries2
15
Если все 15 повторных передач завершены, TCP сообщит прикладному уровню: "Это не работает, пакет не может пройти!"
Тогда, если клиент не отправляет данные, когда соединение в состоянии ESTABLISHED будет разорвано?
Здесь нужно упомянуть ПТСмеханизм поддержания активности. Принцип работы этого механизма следующий:
Определите период времени. В течение этого периода времени, если нет активности, связанной с подключением, начнет функционировать механизм поддержания активности TCP. Каждый временной интервал отправляется "пробное сообщение". Тестовое сообщение содержит очень мало данных. , если нет ответа на несколько последовательных тестовых пакетов, считается, что текущее TCP-соединение разорвано, и ядро системы уведомит приложение верхнего уровня о сообщении об ошибке.
В ядре Linux есть соответствующие параметры для установки времени поддержания активности, количества обнаружений поддержания активности и временного интервала обнаружений поддержания активности.Следующие значения по умолчанию:
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9
- tcp_keepalive_time=7200: указывает, что время проверки активности составляет 7200 секунд (2 часа), то есть, если в течение 2 часов не будет активности, связанной с соединением, будет активирован механизм проверки активности.
- tcp_keepalive_intvl=75: указывает, что каждый интервал обнаружения составляет 75 секунд;
- tcp_keepalive_probes=9: указывает, что после 9 обнаружений нет ответа, а другая сторона считается недостижимой, что прерывает текущее соединение.
Другими словами, в системе Linux требуется не менее 2 часов 11 минут и 15 секунд, чтобы найти «мертвое» соединение.
Это время немного велико, поэтому, если я буду перехватывать пакеты достаточно долго, я смогу перехватывать пробные пакеты.
Сводка по третьему эксперименту
При установлении TCP-соединения, если сервер не может получить ACK третьего рукопожатия, сервер временно находится в состоянииSYN_RECV
состояние, и клиент будет вESTABLISHED
государство.
Поскольку сервер никогда не получал ACK третьего рукопожатия TCP, он будет повторно передавать пакеты SYN и ACK до тех пор, пока количество повторных передач не превыситtcp_synack_retries
значение (по умолчанию 5 раз), сервер отключит TCP-соединение.
У клиента будет две ситуации:
- Если клиент не отправляет пакет, он всегда находится в
ESTABLISHED
состоянии, а затем за 2 часа 11 минут и 15 секунд до обнаружения «мертвого» соединения и разрыва соединения с клиентом. - Если клиент отправляет пакет данных и не получил сообщение подтверждения для пакета данных от сервера, он будет повторно передавать пакет данных до тех пор, пока количество повторных передач не превысит
tcp_retries2
значение (по умолчанию 15 раз), клиент отключает TCP-соединение.
Установление быстрого TCP-соединения
Когда клиент инициирует HTTP-запрос GET к серверу, для полного процесса взаимодействия требуется задержка в 2,5 RTT.
Поскольку третье рукопожатие может передавать данные, если во время третьего рукопожатия инициируется HTTP-запрос GET, требуется задержка в 2 RTT.
Но в следующий раз (не в следующий раз того же TCP-соединения) инициируется HTTP-запрос GET, опытный RTT будет таким же, как показано ниже:
В версии ядра Linux 3.7 предусмотрена функция TCP Fast Open, позволяющая уменьшить задержку установления TCP-соединения.
- Когда соединение устанавливается впервые, сервер генерирует
Cookie
(зашифровано) и отправляется клиенту через пакеты SYN и ACK, поэтому клиент кэширует этоCookie
, поэтому, когда запрос HTTP Get инициируется в первый раз, по-прежнему требуется задержка в 2 RTT; - При следующем запросе клиент принимает пакет SYN.
Cookie
Отправить на сервер, вы можете заранее пропустить процесс трехэтапного рукопожатия, т.к.Cookie
Некоторая информация хранится на сервере, к которой можно получить доступ с сервера.Cookie
Для получения информации, относящейся к TCP, HTTP-запросу GET, инициированному в это время, требуется только задержка в 1 RTT;
Примечание. После того, как клиент запрашивает и сохраняет файл cookie быстрого открытия, он может повторять TCP Fast Open до тех пор, пока сервер не сочтет файл cookie недействительным (обычно с истекшим сроком действия).
Как включить Fast Open в Linux?
может быть установленnet.ipv4.tcp_fastopn
Параметр ядра для включения функции Fast Open.
Значение каждого значения net.ipv4.tcp_fastopn:
- 0 выкл.
- 1 Используйте функцию Fast Open в качестве клиента
- 2 Используйте функцию Fast Open в качестве сервера
- 3 Fast Open может использоваться как в качестве клиента, так и сервера
Анализ перехвата пакетов TCP Fast Open
На рисунке ниже пакет данных № 7, когда клиент инициирует второе TCP-соединение, пакет SYN будет нести Cooike и данные длины 5.
После того, как сервер получает его, он проверяет, что Cooike действителен, поэтому он возвращает пакеты SYN и ACK и подтверждает, что он получил пакет данных клиента, ACK = 5 + 1 = 6
Двойное подтверждение TCP и быстрая повторная передача
Когда получатель получает неупорядоченный пакет, он отправляет дубликат ACK, чтобы сообщить отправителю о повторной отправке пакета.Когда отправитель получает 3 дубликата ACK, запускается быстрая повторная передача, и пора повторно отправлять потерянные пакеты.
Случай двойного подтверждения TCP и быстрой повторной передачи, проанализированный с помощью Wireshark, показывает следующее:
- Seq следующего пакета, ожидаемого пакетом 1, равен 1, но Seq, отправленный пакетом 2, равен 10945, что указывает на то, что полученный пакет является неупорядоченным, поэтому возвращается пакет 3, все тот же Seq = 1, Ack = 1, что указывает на дублированный ACK;
- Пакеты 4 и 6 по-прежнему не соответствуют порядку, поэтому все равно возвращаются повторяющиеся ACK;
- Когда другая сторона получает три повторных ACK, она быстро повторно передает пакет 8 с Seq = 1 и Len = 1368;
- Когда получен повторно переданный пакет данных, обнаруживается, что Seq = 1 является ожидаемым пакетом данных, поэтому отправляется ACK для подтверждения приема быстрой повторной передачи.
Примечание. Быстрая повторная передача и дублирование информации маркера ACK — это функция Wireshark, а не информация самого пакета.
В приведенном выше случае согласование разрешено во время трехэтапного рукопожатия TCP.Выборочное подтверждение SACK, поэтому, как только пакет потерян и получен дубликат ACK, необходимо повторно передать только потерянный пакет, даже если другие пакеты были успешно получены после потерянного пакета. Без включения SACK каждый пакет после потерянного пришлось бы передавать повторно.
Если вы хотите поддержатьSACK
, должны быть поддержаны обеими сторонами. Под Linux это можно сделать черезnet.ipv4.tcp_sack
параметр, чтобы включить эту функцию (по умолчанию включено после Linux 2.4).
управление TCP-потоком
Чтобы предотвратить отправку данных отправителем бездумно, вызывая заполнение буфера получателя, TCP имеет механизм скользящего окна, который может использовать окно приема получателя для управления объемом данных, отправляемых отправителем, т. е. контроль потока.
Окно приема — это значение, указанное получателем и сохраненное в заголовке TCP.Оно может сообщить отправителю размер его собственного буферного пространства TCP, которое представляет собой пространство для чтения данных приложением:
- Если приложение читает данные в буфере, буферное пространство удалит прочитанные данные.
- Если приложение не считывает данные, они остаются в буфере.
Размер окна приема согласовывается в трехстороннем рукопожатии TCP.Во время последующей передачи данных, когда получатель отправляет сообщение ACK с подтверждением, он будет нести текущий размер окна приема, чтобы информировать отправителя.
Предполагая, что после того, как получатель получит данные, прикладной уровень сможет быстро прочитать данные из буфера, тогда размер окна останется неизменным, процесс выглядит следующим образом:
Однако в действительности сервер будет занят, при низкой скорости чтения приложения пространство кэша будет медленно заполняться, поэтому для того, чтобы данные, отправляемые отправителем, не превышали размер буфера, сервер отрегулируйте значение размера окна, а затем уведомите другую сторону через сообщение ACK, чтобы сообщить текущий размер окна приема, чтобы контролировать размер данных, отправляемых отправителем.
Уведомление об отсутствии окон и обнаружение окон
Предполагая, что получатель не может обрабатывать данные так же быстро, как он их получает, кэш будет заполнен, в результате чего окно получения будет равно 0. Когда отправитель получит уведомление о нулевом окне, он прекратит отправку данных.
Как показано на рисунке ниже, размер окна приемника постоянно уменьшается до 0:
Далее отправитель будетРегулярно отправлять пакеты определения размера окна, чтобы знать изменение размера окна приемника во времени.
Следующая диаграмма анализа Wireshark используется в качестве примера для иллюстрации:
- Отправитель отправляет получателю пакет 1. После его получения получателем, поскольку буфер заполнен, возвращается уведомление с нулевым окном;
- После того, как отправитель получит уведомление о нулевом окне, он больше не будет отправлять данные до тех пор, пока
3.4
Через несколько секунд отправляется сообщение TCP Keep-Alive, которое представляет собой сообщение об определении размера окна; - Когда получатель получает сообщение об обнаружении окна, он немедленно возвращает уведомление об окне, но размер окна по-прежнему равен 0;
- Отправитель обнаруживает, что окно по-прежнему равно 0, поэтому продолжает ждать.
6.8
Через (удвоенные) секунды сообщение об обнаружении окна отправляется снова, и получатель по-прежнему возвращает уведомление о том, что окно равно 0; - Отправитель обнаруживает, что окно по-прежнему равно 0, поэтому продолжает ждать.
13.5
Через (удвоенные) секунды сообщение об обнаружении окна отправляется снова, и получатель по-прежнему возвращает уведомление о том, что окно равно 0;
Можно обнаружить, что эти пакеты обнаружения окна появляются с интервалами 3,4 с, 6,5 с и 13,5 с, что указывает на то, что период тайм-аута будетдвойнойУвеличение.
Это соединение приостановлено на 25 секунд, представьте, когда вы играете в короля, вы все еще можете играть в короля с задержкой в 25 секунд?
Анализ окна отправки
Размер окна, отображаемый в Wireshark, также равен "win =". Представляет ли это значение окно отправки?
Это не окно отправки, а объявление другого окна своего окна приема.
Вам может быть любопытно, в файле захвата есть "Коэффициент масштабирования размера окна", который на самом деле является коэффициентом умножения для расчета фактического размера окна. "Значение размера Windows" на самом деле не является реальным размером окна. Формула для расчета реального Размер окна следующий:
"Значение размера окна" * "Коэффициент масштабирования размера окна" = "Расчетный размер окна"
Соответствующий случай на рисунке ниже: 32 * 2048 = 65536.
На самом деле значение Рассчитанного размера окна рассчитывается инструментом Wireshark.Значения Коэффициента масштабирования размера окна и значения размера Виндос находятся в заголовке TCP, а Коэффициент масштабирования размера окна определяется в течение трех- процесс рукопожатия.Если в захваченных данных нет трехэтапного рукопожатия TCP, может быть невозможно вычислить реальный размер окна, как показано на следующем рисунке:
Как посмотреть размер окна отправки в пакете?
К сожалению, простого пути нет.Хотя окно отправки определяется окном приема, на него могут влиять сетевые факторы, то есть окно перегрузки.Фактически окно отправки – это значение min(окно перегрузки, получение окно).
Какое отношение окно отправки имеет к MSS?
Окно отправки определяет, сколько байтов можно отправить за один раз, а MSS определяет, сколько пакетов нужно отправить этих байтов.
Например, если окно отправки 16000 байт, если MSS 1000 байт, то необходимо отправить 1600/1000 = 16 пакетов.
Отправитель отправляет n пакетов в окне, нужно ли ему n пакетов подтверждения ACK?
Не обязательно, потому что TCP имеет кумулятивный механизм подтверждения, поэтому при получении нескольких пакетов данных необходимо ответить только на сообщение ACK последнего пакета данных.
Отложенное подтверждение TCP и алгоритм Нэгла
Когда данные, переносимые нашим TCP-сообщением, очень малы, например, несколько байтов, эффективность всей сети очень низкая, потому что каждое TCP-сообщение имеет 20-байтовый заголовок TCP, а также будет 20-байтовый IP-адрес. заголовка и всего несколько байтов данных, поэтому доля достоверных данных во всем пакете будет очень низкой.
Это так же расточительно, как курьер на большом грузовике доставляет маленькую посылку.
Тогда есть две общие стратегии для уменьшения передачи небольших пакетов, а именно:
- Алгоритм Нэгла
- отложенное подтверждение
Как алгоритм Нэгла позволяет избежать передачи большого количества небольших TCP-пакетов?
Алгоритм Nagle использует некоторые стратегии, чтобы избежать отправки слишком большого количества небольших пакетов данных, что может повысить эффективность передачи.
Стратегия алгоритма Нэгла:
- Если не было отправлено ни одного неподтвержденного сообщения, данные отправляются немедленно.
- При наличии неподтвержденного сообщения данные не отправляются до тех пор, пока «нет отправленного неподтвержденного сообщения» или «длина данных не достигнет размера MSS».
Пока одно из вышеуказанных условий не выполняется, отправитель продолжает накапливать данные до тех пор, пока не будут выполнены вышеуказанные условия отправки.
Алгоритм Nagle включен в правой части рисунка выше и его процесс отправки данных:
- В начале, поскольку неподтвержденное сообщение не отправлено, немедленно отправляется символ H;
- Затем, когда подтверждающее сообщение для символа H не было получено, отправитель копил данные до тех пор, пока не было получено подтверждающее сообщение.В это время не было отправлено неподтвержденных сообщений, поэтому сохраненный символ ELL сохраняется. отправлены получателю вместе;
- После получения подтверждающего сообщения для символа ELL отправляется последний символ O.
Как можно заметить,Алгоритм Нэгла должен иметь небольшой пакет, то есть в самом начале.
Кроме того, алгоритм Nagle включен по умолчанию.Для некоторых программ, требующих взаимодействия с небольшими пакетами, таких как telnet или ssh, необходимо отключить алгоритм Nagle.
Можно установить в сокетTCP_NODELAY
Возможность отключения этого алгоритма (отключение алгоритма Нагла не имеет глобального параметра, его нужно отключать в соответствии со своими особенностями каждого приложения).
Как насчет отложенного подтверждения?
Фактически, когда нет ACK, передающего данные, его сетевая эффективность также очень низка, потому что он также имеет 40-байтовый заголовок IP и заголовок TCP, но не передает пакеты данных.
Для решения проблемы низкой эффективности передачи ACK было полученоОтложенное подтверждение TCP.
Политика отложенного подтверждения TCP:
- Когда есть данные ответа для отправки, ACK будет отправлено другой стороне немедленно вместе с данными ответа.
- Когда нет данных ответа для отправки, ACK будет задержан на период времени, чтобы дождаться отправки данных ответа вместе.
- Если второй пакет данных другой стороны прибывает во время ожидания отправки ACK, ACK будет отправлен немедленно.
Время ожидания задержки определяется в ядре Linux, как показано ниже:
Ключ в том, чтобы нуждатьсяHZ
Размер этого значения, HZ, связан с тактовой частотой системы, и каждая операционная система отличается.В моей системе Linux размер HZ равен1000
,Как показано ниже:
Зная размер ХЗ, то можно рассчитать:
- Максимальное время задержки подтверждения составляет
200
мс (1000/5) - Минимальное время подтверждения задержки составляет
40
мс (1000/25)
Отложенное подтверждение TCP может быть установлено в SocketTCP_QUICKACK
возможность отключить этот алгоритм.
Nagle и отсроченные алгоритмы подтверждения, используемые в комбинации, создаст новые проблемы
Когда отложенное подтверждение TCP и алгоритм Nagle используются вместе, потребление времени увеличивается, как показано на следующем рисунке:
Отправитель использует алгоритм Нэгла, а получатель использует отложенное подтверждение TCP.Происходит следующий процесс:
- Отправитель сначала отправляет небольшое сообщение, а после того, как получатель его получает, из-за механизма отложенного подтверждения у него нет данных для отправки, и он может только ждать прибытия следующего сообщения отправителя;
- Однако из-за механизма алгоритма Nagle отправитель не будет отправлять последующие данные, пока не будет получено подтверждение первого сообщения;
- Следовательно, получатель может ждать не более 200 мс, прежде чем возвратить сообщение ACK, а отправитель может отправлять последующие данные только после получения подтверждающего сообщения первого сообщения.
Очевидно, что использование этих двух одновременно приведет к дополнительной задержке, из-за чего сеть будет казаться «медленной».
Для решения этой проблемы есть только два пути:
- Либо отправитель отключает алгоритм Нэгла
- Либо получатель закрывает отложенные подтверждения TCP
плечи гигантов
[1] Искусство сетевого анализа Wireshark, Лин Пейман, Издательство «Народные сообщения и телекоммуникации».
[2] Сетевой анализ Wireshark — это так просто, Лин Пейман, издательство People's Posts and Telecommunications Publishing House.
[3] Анализ пакетов Wireshark на практике, Крис Сандерс, People's Posts and Telecommunications Press.
нытье ворчание
Скриншоты анализа Wireshark в статье могут быть неясными.Для удобства всех желающих использовать Wireshark для анализа,Я поделился всеми исходными файлами захвата пакета в статье с публичной учетной записью, и каждый может получить его, ответив на «захват пакета» в фоновом режиме.
Кобаяши — человек-инструмент, созданный для всех. До свидания, увидимся в следующий раз!
Вопросы и ответы читателей
Читатель спросил: «Два вопроса задайте автору:
В каких случаях действует параметр tcp_retries1?
Ограничен ли tcp_retries2 только указанным количеством раз или он ограничен минимальным количеством раз и ограничениями по времени? "
И tcp_retries1, и tcp_retries2 являются сценариями после трехэтапного рукопожатия TCP.
- Когда количество повторных передач превышает tcp_retries1, уровень IP получает указание выполнить определение MTU, обновление маршрута и другие процессы, и не будет разрывать соединение TCP.Когда количество повторных передач превышает tcp_retries2, поток TCP будет отключен.
- Количество повторных передач tcp_retries1 и tcp_retries2 ограничено значением тайм-аута.Значение тайм-аута рассчитывается в соответствии с их значениями.Когда время повторной передачи превышает тайм-аут, он не будет продолжать повторную передачу, даже если количество раз не достигло .
Читатель спросил: «tcp_orphan_retries также управляет закрытием tcp-соединений. Отличается ли это от tcp_retries1 и tcp_retries2?»
После того, как активная сторона отправляет сообщение FIN, соединение находится в состоянии FIN_WAIT1, которое обычно должно измениться на FIN_WAIT2 в течение десятков миллисекунд. Если ACK, возвращенный другой стороной, не получен, в это время ядро будет регулярно повторно отправлять сообщение FIN, а количество повторных передач контролируется параметром tcp_orphan_retries.
Читатель спросил: «Извините, а почему последовательность двух последовательных сообщений одинакова, как, например, у сообщения после тройного рукопожатия? Или это одно и то же сообщение с тем же порядковым номером, но оно просто разобрано и выведено на экран? "
- Первые два раза в трехэтапном рукопожатии: seq+1;
- Последний акк в трехэтапном рукопожатии действительно может нести данные.Поскольку пример в моей статье не отправляет данные, вы можете видеть, что len=0 третьего рукопожатия, на этапе передачи данных "следующая последовательность=последовательность" +len ", поэтому последовательность третьего рукопожатия такая же, как последовательность следующей дейтаграммы, потому что len равно 0;