Говоря о TCP (1): конечный автомат и механизм повторной передачи

задняя часть сервер Государственный аппарат Wireshark

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

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

Большая часть этой статьи основана наЭти вещи о TCP (Часть 1)Изменено, некоторые точки зрения отличаются от исходного текста, а в важные места добавлены пояснения.

Предварительное знание

некоторые основы сети

TCP — это четвертый уровень в семиуровневой модели сети OSI — Транспортный уровень, IP — это третий уровень — Сетевой уровень, ARP — это второй уровень — Канальный уровень, а данные на втором уровне. называется Frame, данные третьего уровня называются Packet, а данные четвертого уровня называются Segment.

Данные прикладного уровня сначала будут отправлены в TCP-сегмент, затем TCP-сегмент будет отправлен в IP-пакет, а затем в Ethernet-кадр.Передать данные протоколу более высокого уровня для обработки.

Формат заголовка TCP

Перед формальным обсуждением давайте взглянем на формат заголовка TCP: [Изображение загружается...(image.png-eed30f-1522722733998-0)]

image.png

Уведомление:

  • Пакеты TCP не имеют IP-адресов, это вопрос уровня IP. Но есть исходные порты и порты назначения.
  • Для TCP-соединения требуется четыре кортежа для представления одного и того же соединения (src_ip, src_port, dst_ip, dst_port) (если быть точным, пять кортежей, и один — протокол, но поскольку это только протокол TCP, поэтому здесь я говорю только квады) .
  • Обратите внимание на четыре очень важные вещи на изображении выше:
    • Sequence Number, порядковый номер пакета Seq,Используется для разрешения сетевых пакетов не по порядку(переупорядочивание).
    • Acknowledgement Number, Ack используется для подтверждения получения Seq (Ack = Seq + 1, что указывает на то, что Seq и пакеты до Seq были получены, и ожидается Seq + 1),Используется для решения проблемы потери пакетов.
    • Window, он жеAdvertised Window, что можно приблизительно понять как滑动窗口(Раздвижное окно) размер,для управления потоком.
    • TCP Flagразличать типы пакетов, такие как пакеты SYN, пакеты FIN, пакеты RST и т. д., которые в основном используются для управления конечной машиной TCP.

Другие поля относятся к следующему рисунку:

image.png

Конечный автомат TCP

фактически,Сетевая передача не подключена - так называемое «соединение» TCP на самом деле просто поддерживает «состояние соединения» между обеими сторонами связи., чтобы казалось, что есть соединение. Поэтому переход состояния TCP очень важен.

НижеупрощатьСравнительная диаграмма «автомат протокола TCP» и «трехстороннее рукопожатие TCP для установления соединения + передача данных + четыре взмаха рук для отключения», эти две диаграммы по существу описывают конечный автомат протокола TCP, но сценарии немного отличаются.Эти две картинки очень важны, и их нужно иметь в виду..

Конечный автомат протокола TCP не делает различий между клиентом и сервером:

image.png

На рисунке ниже показано классическое «трехстороннее рукопожатие TCP для установления соединения + передача данных + четыре волны для отключения», клиент инициирует рукопожатие, передает данные на сервер (сервер не передает клиенту) и, наконец, инициирует волна:

image.png

Три рукопожатия и четыре волны

Многие спросят,Почему для установления соединения требуется три рукопожатия, а для отключения – четыре волны?

Трехстороннее рукопожатие для установления соединения

Главное — _инициализировать начальное значение Sequence Number_.

Обеим сторонам связи необходимо синхронизировать ISN (начальный порядковый номер) другой стороны, поэтому это называется SYN (полное название «Синхронизация порядковых номеров»). То есть x и y на приведенном выше рисунке. При передаче данных в будущем это число увеличивается в порядке отправки на стороне клиента и реорганизуется в порядке возрастания на стороне сервера, чтобы гарантировать, что данные, полученные прикладным уровнем, не будут нарушены из-за сетевых проблем.

Четыре взмахнули руками, чтобы отключить

На самом деле _обе стороны махнули по 2 раза_.

Поскольку TCP является полнодуплексным, и клиент, и сервер занимают свои собственные ресурсы для отправки сегментов (один и тот же канал и одновременная двунаправленная передача seq и ack), поэтому,Обе стороны должны закрыть свои собственные ресурсы (отправить FIN другой стороне) и подтвердить, что ресурсы другой стороны закрыты (ответить другой стороне с помощью Ack); и обе стороны могут активно закрыться одновременно, или одна сторона может пассивно закрыть другую сторону. Однако, как правило, это пример того, как одна сторона активна, а другая пассивна (как показано на рисунке, клиент активен, а сервер пассивен), так что это похоже на так называемые 4 раза волнения.

Если обе стороны активно отключаются одновременно, обе стороны войдутCLOSINGГосударство, а потомTIME_WAITсостояние, последний тайм-аут идет наCLOSEDусловие. На следующем рисунке показана схема активного отключения обеих сторон в одно и то же время (соответствует ветви «Одновременное закрытие» в конечном автомате TCP):

image.png

Другие вопросы во время рукопожатия

Тайм-аут SYN при установлении соединения

После того, как сервер получит SYN, отправленный клиентом, и ответит Ack(SYN) (здесь называется Ack1), если клиент отключен (или время ожидания сети истекло), сервер не сможет получить Ack(Ack(SYN). )) ответил клиент (упоминаемый здесь как Ack2), соединение находится вПромежуточное состояние(неуспех, неуспех).

Чтобы решить проблему промежуточного состояния, если сервер не получит Ack2 в течение определенного периода времени, он повторно отправит Ack1(отличается от механизма ретрансляции при передаче данных). В Linux повторная попытка по умолчанию составляет 5 раз, а первый раз отправляется в общей сложности до 6 раз; интервал повтора удваивается с 1 с (экспоненциальная стратегия отсрочки, экспоненциальная отсрочка), а 5 повторных попыток равны 1 с соответственно. 2 с, 4 с, 8 с, 16 с, после 5-го выпуска требуется 32 с, чтобы решить, что 5-й раз также истекает. так,Отправляется не более 6 раз, после 1 с + 2 с + 4 с + 8 с + 16 с + 32 с = 2 ^ 6 -1 = 63 с TCP будет учитывать тайм-аут SYN для отключения соединения..

SYN-флуд-атака

Его можно инициировать с помощью механизма тайм-аута SYN при установлении соединения.SYN Flood攻击—— Отправьте SYN на сервер и немедленно отключитесь, поэтому сервер должен занимать ресурсы в течение 63 секунд по умолчанию перед отключением. Скорость отправки SYN очень высока, поэтому злоумышленник может легко исчерпать ресурсы очереди SYN на сервере, что сделает сервер неспособным обрабатывать нормальные новые подключения.

Для решения этой проблемы Linux предоставляетtcp_syncookiesПараметры решают эту проблему -Когда очередь SYN заполнена, TCP создаст специальный порядковый номер через порт исходного адреса, порт адреса назначения и отметку времени и отправит его обратно, что называется SYN Cookie.Если это злоумышленник, ответа не будет.Если это является обычным соединением, то этот файл cookie SYN будет отправлен обратно, а затем серверная сторона сможет установить соединение через файл cookie SYN.(даже если вы не находитесь в очереди SYN). Что касается соединения в очереди SYN, то оно не будет обработано до закрытия таймаута. осторожность,Не используйте егоtcp_syncookiesпараметры для обработки обычных ситуаций подключения большой нагрузки, потому что файл cookie SYN фактически разрушает механизм тайм-аута SYN для установления соединения и является скомпрометированной версией протокола TCP.

Для обычных запросов на подключение есть три дополнительных параметра на выбор:

  • tcp_synack_retriesПараметр задает количество попыток тайм-аута SYN.
  • tcp_max_syn_backlogПараметр задает максимальное количество SYN-соединений (емкость очереди SYN)
  • tcp_abort_on_overflowПараметр отказывает в соединении, когда запрос SYN не может быть обработан.

Синхронизация ISN

  • первый,Статический ISN не может быть выбран. Например, если соединение установлено, в качестве ISN всегда используется 1. Если клиент отправляет 30 сегментов (при условии, что один байт на сегмент), но сеть отключена, клиент снова подключается и использует 1 в качестве ISN, но старый one Когда приходят эти сегменты соединения (называемые «потерянные повторяющиеся группы»), поскольку пятерка, которая отличает соединение, одна и та же (называя новое соединение «аватаром» старого соединения), сервер обрабатывает их как сегменты в новое соединение.
  • Тогда, как видно из приведенного выше примера,Необходимо, чтобы ISN динамично рос с часами., чтобы у нового подключения был больший ISN, чем у старого подключения.
  • наконец,С точки зрения безопасности и т. д. рост ISN нельзя сделать регулярным.(например, просто расти пропорционально часам). Это легко понять: если закон роста слишком прост, легко подделать ISN, чтобы запустить атаки на обоих концах сети.

Наконец, разработаны различные алгоритмы роста ISN, которые, как правило, обеспечивают динамический рост ISN в соответствии с тактовой частотой и определенную случайность. Простой алгоритм роста ISN описан в RFC793: ISN привязан к поддельным часам, которые увеличивают ISN каждые 4 микросекунды, пока он не превысит 2^32, снова начиная с 0. Таким образом, период одного ИСН примерно равен 4,55 (Я насчитал 4,77? ? ?)Часы. Максимальное время жизни сегмента в сети определяется как MSL (Maximum Segment Lifetime).Пакеты, время жизни которых превышает MSL в сети, будут отбрасываться. Следовательно, если используется алгоритм роста ISN в RFC793, значение MSL должно быть меньше 4,55 часов, чтобы гарантировать, что ISN не будет повторно использоваться в соседних соединениях (TIME_WAITтоже имеет такой эффект). В то же время это косвенно ограничивает размер сети (конечно, 4,55 часа MSL уже позволяют построить очень большие сети).

MSL должен быть больше, чем время преобразования TTL протокола IP.RFC793 рекомендует устанавливать MSL равным 2 минутам, а Linux, следуя обычаю Беркли, устанавливает его равным 30 с.

Другие проблемы во время волны

О TIME_WAIT

Зачем вам TIME_WAIT

В конечном автомате TCP изTIME_WAITсостояния в состояние CLOSED с тайм-аутом 2 * MSL. зачем нужноTIME_WAITсостояние с тайм-аутом 2*MSL? Есть две основные причины:

  • 2 * MSL гарантирует, что пассивной стороне достаточно времени для получения ACK или активной стороне для получения FIN, который повторно передается по тайм-ауту пассивной. То есть, если пассивная сторона не получит Ack, это заставит пассивную сторону повторно передать FIN, отправить Ack + получить FIN ровно 2 MSL,TIME_WAITПосле того, как соединение в состоянии получает повторно переданный FIN, оно повторно передает Ack, а затем ожидает время 2 * MSL.
  • Убедитесь, что у вас достаточно времени для "迷途的重复分组"Просроченный сброс. Для этого нужен только 1 * MSL, а пакеты, превышающие MSL, будут отбрасываться, иначе их легко смешать с данными нового соединения (нельзя полагаться только на ISN).

Масса TIME_WAIT

Распространенная проблема заключается в том, что TIME_WAIT возникает в больших масштабах, обычно в сценариях с высокой степенью параллелизма и короткими подключениями, которые потребляют много ресурсов.

Большинство статей в интернете учат открывать два параметра,tcp_tw_reuseилиtcp_tw_recycle. Оба параметра отключены по умолчанию.tcp_tw_recycleСравниватьtcp_tw_reuseБолее агрессивный; чтобы использовать оба, также нужно открытьtcp_timestamps(открыт по умолчанию), в противном случае недействителен. но,Включение этих двух параметров может вызвать странные проблемы с TCP-соединениями.: Как упоминалось выше, при повторном использовании соединения без ожидания тайм-аута данные старого и нового соединения могут перепутаться, например, если FIN старого соединения получен во время рукопожатия нового соединения, новый соединение будет сброшено. следовательно,Следует соблюдать осторожность при использовании этих двух параметров..

Детали каждого параметра следующие:

  • tcp_tw_reuse: Официальная документация говоритtcp_tw_reuseплюсtcp_timestampsможет гарантироватьклиент(Только клиент) Безопасен с точки зрения протокола, но должен быть открыт с обеих сторон.tcp_timestamps.
  • tcp_tw_recycle:еслиtcp_tw_recycleЕсли он открыт, предполагается, что пир открыт.tcp_timestamps, а затем сравните временные метки.Если временные метки становятся больше, соединение можно использовать повторно (сеть NAT может не установить соединение, и возникает ошибка «время ожидания соединения»).

Добавьте параметр:

  • tcp_max_tw_buckets: контролирует параллелизмTIME_WAITКоличество (по умолчанию 180000), если оно превышает лимит, система поставит лишнееTIME_WAITСоединение уничтожается, и в журнале печатается предупреждение (например, "переполнение таблицы времени ожидания"). В официальном документе на сайте говорится, что этот параметр используется для борьбы с DDoS-атаками и его необходимо учитывать в зависимости от реальной ситуации.

Совет на TIME_WAIT

Короче,TIME_WAITПоявиться на той стороне, которая активно махала, то есть тот, кто инициирует волну, будет жертвовать ресурсами, чтобы поддерживать тех, кто ждет отTIME_WAITПеревести вCLOSEDсостояние соединения.TIME_WAITНаличие необходимо, следовательно,Вместо того, чтобы нарушать протокол с указанными выше параметрами, чтобы избежатьTIME_WAIT, лучше оптимизировать бизнес(например, переход на длинные соединения и т. д.), оптимизированные для разных сервисовTIME_WAITпроблема.

Для HTTP-сервера можно установить параметр HTTP KeepAlive, повторно использовать TCP-соединение на прикладном уровне для обработки нескольких HTTP-запросов (требуется взаимодействие с браузером) и позволить клиенту (т. е. браузеру) инициировать волну, чтобыTIME_WAITПоявляется только на стороне клиента.

Пример

Следующее изображение — это изображение, которое я взял из Wireshark с передачей данных, когда я посетил coolshell.cn, вы можете обратиться, чтобы понять, как меняются Seq и Ack (используйте Statistics -> Flow Graph… в меню Wireshark):

image.png

можно увидеть,Seq связан с увеличением Ack и количеством переданных байтов.. На приведенном выше рисунке после трехэтапного рукопожатия пришли два пакета Len: 1440, поэтому первый пакет — Seq(1), а второй — Seq(1441). Затем принимается первый Ack(1441), указывающий, что данные с 1 по 1440 были получены, и ожидается Seq(1441). Кроме того, видно, что пакет может действовать как Ack и Seq, передавая данные и ответы за одну передачу.

Если вы посмотрите на трехстороннее рукопожатие с помощью программы перехвата пакетов Wireshark, вы обнаружите, что ISN всегда равен 0. Это не так, Wireshark использует Relative Seq — относительный порядковый номер для более удобного отображения. Вам просто нужно снять флажок с параметра протокола в контекстном меню, чтобы увидеть «Абсолютная последовательность».

Механизм повторной передачи TCP

Протокол TCP гарантирует, что все сегменты могут достичь одноранговой стороны с помощью механизма повторной передачи, и допускает определенную степень беспорядка и потери пакетов через скользящее окно.(Скользящее окно также имеет такие функции, как управление потоком, которые пока не будут обсуждаться). Обратите внимание, что механизм повторной передачи здесь относится конкретно к фазе передачи данных, а механизм передачи фаз рукопожатия и волны отличается от этого.

TCP ориентирован на байты,Рост Seq и Ack в байтах. В наивной реализации, чтобы уменьшить сетевой трафик,Получатель отвечает только на Ack последнего последовательного пакета.и соответствующим образом переместите окно. Например, отправитель отправляет 1, 2, 3, 4 и 5, всего пять фрагментов данных (при условии, что один фрагмент данных равен одному байту), получатель быстро получает Seq 1, Seq 2 и возвращается к Ack 3. и перемещает окно; Когда дело доходит до Seq 4, поскольку Seq 3 не был получен ранее (не по порядку), если он все еще находится в пределах окна, он только заполнит окно, но не отправит Ack 5, иначе Seq 3 будет отброшен (аналогично эффекту потери пакета); предположим, в окне, когда Seq 3 будет получен позже, будет обнаружено, что Seq 4 и предыдущие пакеты данных были получены, затем вернитесь к Ack 5 и переместите окно.

Механизм повторной передачи по тайм-ауту

Когда отправитель находит Ack, ожидающий Seq 3 (т.е. Ack 4)тайм-аутПосле этого он будет считать, что Seq 3 отправил «сбой» и повторно передаст Seq 3.. Как только получатель получит Seq 3, он немедленно вернет Ack 4.

Отправитель не может отличить потерю пакета Seq 3, отказ получателя или потерю пакета Ack 4.

У этого метода есть некоторые проблемы: предполагается, что последовательность 4 получена, а поскольку последовательность 3 не получена, отправитель повторно передает последовательность 3. Перед получением повторно переданной последовательности 3 она включает вновь полученную последовательность 5 и только что полученную последовательность 3. получено Seq 5. Seq 4 не может ответить на Ack, отправитель легко может повторно передать Seq 4 и Seq5. Приемник ранее сохранил в окне Seq 4 и Seq 5. В настоящее время повторная передача Seq 4 и Seq 5 явно расточительна.

То есть механизм повторной передачи по тайм-ауту сталкивается с "ретранслировать один или ретранслировать все", то есть:

  • Повторно передать один: повторно передавать только пакет с истечением времени ожидания (т. е. Seq 3), а затем повторно передавать последующие пакеты после истечения времени ожидания. Экономьте ресурсы, но немного менее эффективно.
  • Повторно передать все: каждый раз повторно передавать пакет тайм-аута и все последующие данные (т. е. Seq 3, 4, 5). Более эффективно (если полоса пропускания не заполнена), но пустая трата ресурсов.

Видно, что оба метода относятся к超时重传机制, у каждого есть свои плюсы и минусы, но обоим нужно ждать тайм-аута, даведомый временемДа, производительность тесно связана с длительностью тайм-аута. Если тайм-аут очень большой (распространенный случай), это сильно повлияет на производительность обоих методов.

Механизм быстрой ретрансляции

Наиболее идеальное решение: до истечения времени ожидания отправитель должен повторно передать пакет времени ожидания (т.е. Seq 3) как можно скорее с помощью какого-либо механизма, такого как快速重传机制(Быстрая повторная передача). Эта схема тратит ресурсы (сколько зависит от того, "переслать один или все", см. ниже), но очень эффективна (поскольку нет необходимости ждать тайм-аута).

Механизм быстрой ретрансляции не зависит от времени, а基于数据驱动:Если пакет приходил непрерывно, пакет, который может быть потерян, будет потерян; если отправитель получает один и тот же ACK подряд, он повторно передает соответствующий SEQ..

Например: предположим, что отправитель по-прежнему отправляет 5 копий данных 1, 2, 3, 4 и 5; получатель сначала получает Seq 1 и возвращает Ack 2; затем Seq 2 теряется по сетевым причинам и получает Seq 3 в обычном режиме. и продолжает отвечать на Ack 2; Seq 4 и Seq 5 прибыли позже, последним пакетом, который может быть потерян, все еще является Seq 2, и он продолжает возвращаться на Ack 2; теперь отправитель получил 4 раза подряд (больше или равно до 3 раз) один и тот же Ack (т. е. Ack 2), зная, что неполученный пакет с наибольшим порядковым номером — это Seq 2, поэтому повторно передайте Seq 2 и очистите счетчик Ack 2; наконец, получатель получает Seq 2, и Окно просмотра обнаруживает, что были получены Seq 3, 4 и 5. , возвращается к Ack 6. Схематическая диаграмма выглядит следующим образом:

image.png

Быстрая повторная передача решает проблему тайм-аута, но по-прежнему сталкивается с проблемой «повторить одну или повторить все». Для приведенного выше примера следует ли повторно передавать только Seq 2 или следует повторно передавать Seq 2, 3, 4, 5?

Если вы используете только быструю повторную передачу, вы должны повторить все: потому что отправитель не знает, какие Seq возвращаются для вышеуказанных 4 последовательных Ack 2. Предположим, отправитель отправляет Seq 1–Seq 20 для 20 копий данных, только Seq 1, 6, 10 и 20 достигают получателя, вызывая повторную передачу Ack 2; затем отправитель повторно передает Seq 2, а получатель получает его и отвечает с помощью Подтверждение 3. Далее ни отправитель, ни получатель больше не отправляют данные, и оба конца застревают в ожидании. Поэтому отправитель может выбрать только «повторную передачу всего», что также является фактической реализацией некоторых протоколов TCP, и повышение эффективности повторной передачи очень очевидно, когда полоса пропускания не заполнена.

Более совершенный дизайн состоит в том, чтобы сочетать повторную передачу по тайм-ауту с быстрой повторной передачей.При срабатывании быстрой повторной передачи повторно передается только небольшая часть Seq (принцип локальности, даже только одна Seq повторно передается), а остальные Seq повторно передаются по истечении тайм-аута..


Ссылаться на:


Ссылка на эту статью:Говоря о TCP (1): конечный автомат и механизм повторной передачи
автор:обезьяна 007
Источник:monkeysayhi.github.io
Эта статья основана наCreative Commons Attribution-ShareAlike 4.0Международное лицензионное соглашение выпущено, его можно перепечатать, вывести или использовать в коммерческих целях, но авторство и ссылка на эту статью должны быть сохранены.