Time wait что это
3 необычных кейса о сетевой подсистеме Linux
В этой статье представлены три небольшие истории, которые произошли в нашей практике: в разное время и в разных проектах. Объединяет их то, что они связаны с сетевой подсистемой Linux (Reverse Path Filter, TIME_WAIT, multicast) и иллюстрируют, как глубоко зачастую приходится анализировать инцидент, с которым сталкиваешься впервые, чтобы решить возникшую проблему… и, конечно, какую радость можно испытать в результате полученного решения.
История первая: о Reverse Path Filter
Клиент с большой корпоративной сетью решил пропускать часть своего интернет-трафика через единый корпоративный файрвол, расположенный за маршрутизатором центрального подразделения. С помощью iproute2 трафик, уходящий в интернет, был направлен в центральное подразделение, где уже было настроено несколько таблиц маршрутизации. Добавив дополнительную таблицу маршрутизации и настроив в ней маршруты перенаправления на файрвол, мы включили перенаправление трафика из других филиалов и… трафик не пошел.
Схема прохождения трафика через таблицы и цепочки Netfilter
Начали выяснять, почему не работает настроенная маршрутизация. На входящем туннельном интерфейсе маршрутизатора трафик обнаруживался:
Однако на исходящем интерфейсе пакетов не было. Стало ясно, что фильтруются они на маршрутизаторе, однако явно установленных правил отбрасывания пакетов в iptables не было. Поэтому мы начали последовательно, по мере прохождения трафика, устанавливать правила, отбрасывающие наши пакеты и после установки смотреть счетчики:
Проверили последовательно nat PREROUTING, mangle PREROUTING. В mangle FORWARD счетчик не увеличивался, а значит — пакеты теряются на этапе маршрутизации. Проверив снова маршруты и правила, начали изучать, что именно происходит на этом этапе.
В ядре Linux для каждого интерфейса по умолчанию включен параметр Reverse Path Filtering ( rp_filter ). В случае, когда вы используете сложную, асимметричную маршрутизацию и пакет с ответом будет возвращаться в источник не тем маршрутом, которым пришел пакет-запрос, Linux будет отфильтровывать такой трафик. Для решения этой задачи необходимо отключить Reverse Path Filtering для всех ваших сетевых устройств, принимающих участие в маршрутизации. Чуть ниже простой и быстрый способ сделать это для всех имеющихся у вас сетевых устройств:
Возвращаясь к кейсу, мы решили проблему, отключив Reverse Path Filter для интерфейса tap0 и теперь хорошим тоном на маршрутизаторах считаем отключение rp_filter для всех устройств, принимающих участие в асимметричном роутинге.
История вторая: о TIME_WAIT
В обслуживаемом нами высоконагруженном веб-проекте возникла необычная проблема: от 1 до 3 процентов пользователей не могли получить доступ к сайту. При изучении проблемы мы выяснили, что недоступность никак не коррелировала с загрузкой любых системных ресурсов (диск, память, сеть и т.д.), не зависела от местоположения пользователя или его оператора связи. Единственное, что объединяло всех пользователей, которые испытывали проблемы, — они выходили в интернет через NAT.
Механизм закрытия TCP-соединения
И выполните команду:
История третья: об OSPF и мультикастовом трафике
Обслуживаемая корпоративная сеть была построена на базе tinc VPN и прилегающими к ней лучами IPSec и OVPN-соединений. Для маршрутизации всего этого адресного пространства L3 мы использовали OSPF. На одном из узлов, куда агрегировалось большое количество каналов, мы обнаружили, что небольшая часть сетей, несмотря на верную конфигурацию OSPF, периодически пропадает из таблицы маршрутов на этом узле.
Упрощенное устройство VPN-сети, используемой в описываемом проекте
В первую очередь проверили связь с маршрутизаторами проблемных сетей. Связь была стабильной:
Продиагностировав OSPF, мы удивились еще больше. На узле, где наблюдались проблемы, маршрутизаторы проблемных сетей отсутствовали в списке соседей. На другой стороне проблемный маршрутизатор в списке соседей присутствовал:
Следующим этапом исключили возможные проблемы с доставкой ospf hello от 172.24.0.1. Запросы от него приходили, а вот ответы — не уходили:
Заключение
Какой бы сложной ни была проблема, она всегда решаема и зачастую — с помощью изучения документации. Буду рад увидеть в комментариях описание вашего опыта поиска решения сложных и необычных проблем.
2.7. Состояние TIME_WAIT
2.7. Состояние TIME_WAIT
Без сомнений, самым сложным для понимания аспектом TCP в отношении сетевого программирования является состояние TIME_WAIT (время ожидания). На рис. 2.4 мы видим, что узел, выполняющий активное закрытие, проходит это состояние. Продолжительность этого состояния равна двум MSL (maximum segment lifetime — максимальное время жизни сегмента), иногда этот период называется 2MSL.
В каждой реализации TCP выбирается какое-то значение MSL. Рекомендуемое значение, приведенное в документе RFC 1122 [10], равно 2 мин, хотя Беркли-реализации традиционно использовали значение 30 с. Это означает, что продолжительность состояния TIME_WAIT — от 1 до 4 мин. MSL — это максимальное количество времени, в течение которого дейтаграмма IP может оставаться в сети. Это время ограничено, поскольку каждая дейтаграмма содержит 8-разрядное поле предельного количества прыжков (hop limit) (поле TTL IPv4 на рис. А.1 и поле «Предельное количество транзитных узлов» IPv6 на рис. А.2), максимальное значение которого равно 255. Хотя этот предел ограничивает количество транзитных узлов, а не время пребывания пакета в сети, считается, что пакет с максимальным значением этого предела (которое равно 255) не может существовать в сети более MSL секунд.
Пакеты в объединенных сетях обычно теряются в результате различных аномалий. Маршрутизатор отключается, или нарушается связь между двумя маршрутизаторами, и им требуются секунды или минуты для стабилизации и нахождения альтернативного пути. В течение этого периода времени могут возникать петли маршрутизации (маршрутизатор А отправляет пакеты маршрутизатору В, а маршрутизатор В отправляет их обратно маршрутизатору А), и пакеты теряются в этих петлях. В этот момент, если потерянный пакет — это сегмент TCP, истекает установленное время ожидания отправляющего узла, и он снова передает пакет, и этот заново переданный пакет доходит до конечного места назначения по некоему альтернативному пути. Но если спустя некоторое время (не превосходящее количества секунд MSL после начала передачи потерянного пакета) петля маршрутизации исправляется, пакет, потерянный в петле, отправляется к конечному месту назначения. Начальный пакет называется потерянной копией или дубликатом (lost duplicate), а также блуждающей копией или дубликатом (wandering duplicate). TCP должен обрабатывать эти дублированные пакеты.
Есть две причины существования состояния TIME_WAIT:
? необходимо обеспечить надежность разрыва двустороннего соединения TCP;
? необходимо подождать, когда истечет время жизни в сети старых дублированных сегментов.
Первую причину можно объяснить, рассматривая рис. 2.5 в предположении, что последний сегмент ACK потерян. Сервер еще раз отправит свой последний сегмент FIN, поэтому клиент должен сохранять информацию о своем состоянии, чтобы отправить завершающее подтверждение ACK повторно. Если бы клиент не сохранял информацию о состоянии, он ответил бы серверу сегментом RST (еще один вид сегмента TCP), что сервер интерпретировал бы как ошибку. Если ответственность за корректное завершение двустороннего соединения в обоих направлениях ложится на TCP, он должен правильно обрабатывать потерю любого из четырех сегментов. Этот пример объясняет, почему в состоянии TIME_WAIT остается узел, выполняющий активное закрытие: именно этому узлу может потребоваться повторно передать подтверждение.
Чтобы понять вторую причину, по которой необходимо состояние TIME_WAIT, давайте считать, что у нас имеется соединение между IP-адресом 12.106.32.254, порт 1500 и IP-адресом 206.168.112.219, порт 21. Это соединение закрывается, и спустя некоторое время мы устанавливаем другое соединение между теми же IP-адресами и портами: 12.106.32.254, порт 1500 и 206.168.112.219, порт 21. Последнее соединение называется новым воплощением (incarnation) предыдущего соединения, поскольку IP-адреса и порты те же. TCP должен предотвратить появление старых дубликатов, относящихся к данному соединению, в новом воплощении этого соединения. Чтобы гарантировать это, TCP запрещает установление нового воплощения соединения, которое в данный момент находится в состоянии TIME_WAIT. Поскольку продолжительность состояния TIME_WAIT равна двум MSL, это позволяет удостовериться, что истечет и время жизни пакетов, посланных в одном направлении, и время жизни пакетов, посланных в ответ. Используя это правило, мы гарантируем, что в момент успешного установления соединения TCP время жизни в сети всех старых дубликатов от предыдущих воплощений этого соединения уже истекло.
Из этого правила существует исключение. Реализации, происходящие от Беркли, инициируют новое воплощение соединения, которое в настоящий момент находится в состоянии TIME WAIT, если приходящий сегмент SYN имеет порядковый номер «больше» конечного номера из предыдущего воплощения. На с. 958-959 [128] об этом рассказано более подробно. Для этого требуется, чтобы сервер выполнил активное закрытие, поскольку состояние TIME_WAIT должно существовать на узле, получающем следующий сегмент SYN. Эта возможность используется командой rsh. В документе RFC 1185 [54] рассказывается о некоторых ловушках, которые могут вас подстерегать при этом.
Данный текст является ознакомительным фрагментом.
Продолжение на ЛитРес
Читайте также
Состояние процесса
Состояние процесса Поле state дескриптора процесса описывает текущее состояние процесса (рис. 3.3). Каждый процесс в системе гарантированно находится в одном из пяти различных состояний. Рис. 3.3. Диаграмма состояний процессаЭти состояния представляются значением одного из
6.2. Состояние
6.2. Состояние Понятие состояния (state) является фундаментальным не только в метамоде-ли языка UML, но и в прикладном системном анализе. Ранее в главе 1 кратко были рассмотрены особенности представления динамических характеристик сложных систем, традиционно используемых для
Начальное состояние
Начальное состояние Начальное состояние представляет собой частный случай состояния, которое не содержит никаких внутренних действий (псевдосостояния). В этом состоянии находится объект по умолчанию в начальный момент времени. Оно служит для указания на диаграмме
Конечное состояние
Конечное состояние Конечное (финальное) состояние представляет собой частный случай состояния, которое также не содержит никаких внутренних действий (псевдосостояния). В этом состоянии будет находиться объект по умолчанию после завершения работы автомата в конечный
6.5. Историческое состояние
6.5. Историческое состояние Как было отмечено выше, формализм обычного автомата не позволяет учитывать предысторию в процессе моделирования поведения объектов. Однако функционирование целого ряда систем основано на возможности выхода из отдельных состояний с
7.1. Состояние действия
7.1. Состояние действия Состояние действия (action state) является специальным случаем состояния с некоторым входным действием и по крайней мере одним выходящим из состояния переходом. Этот переход неявно предполагает, что входное действие уже завершилось. Состояние действия
Физическое и эмоциональное состояние
Физическое и эмоциональное состояние Казалось бы, очевидная вещь, хорошее физическое и эмоциональное состояние позволяет работать на порядок лучше, меньше уставать, быть более сконцентрированным. Это вроде бы все понимают, и, в то же время, только единицы уделяют этим
Состояние и версия записи
Состояние и версия записи Каждый объект DataRow имеет свойство RowState, которое обозначает текущее состояние или статус записи. Кроме того, каждая запись хранит информацию о четырех разных версиях своего значения. По мере редактирования записи изменяется ее состояние и версия
Статическое состояние
Предыдущее состояние дел
Состояние готовности
Состояние готовности Наконец, нужно гарантировать, что при снятии указателя мыши с пункта меню пользователем в первой текстовой панели не останется «старая» подсказка, а будет отображено некоторое «типовое» сообщение (например: «Ожидание действий пользователя»). В текущем
8.4. Состояние планировщика событий
4.4.1. Состояние гонки
4.4.1. Состояние гонки Предположим, что в программу поступает группа запросов, которые обрабатываются несколькими одновременными потоками. Очередь запросов представлена связанным списком объектов типа struct job.Когда каждый поток завершает свою операцию, он обращается к
Состояние
Состояние Триггер может быть активным (active) или неактивным (inactive). Запускаются только активные триггеры. См. замечания к ALTER TRIGGER по поводу подробностей деактивации
Печенюшка
Протокол TCP: состояние TIME-WAIT
При использовании утилиты TCP View от Sysinternals или консольной команды netstat мы часто видим несколько непонятных состояний TCP-соединений. Если слова ESTABLISHED и LISTENING в состоянии соединения не вызывают вопросов, то что такое TIME_WAIT? Ожидание? Ожидание чего?…
Ответ на этот вопрос в полной мере дал мне сегодня Яндекс.
Состояние TIME-WAIT наступает в ходе разрыва соединения. Для разрыва TCP-соединения нужно обычно обменяться четырьмя сегментами, как показано на рисунке.
На рисунке показано соединение между двумя приложениями, работающими на хостах 1 и 2. Приложение на хосте 1 закрывает свою сторону соединения, при этом TCP посылает сегмент FIN хосту 2. Хост 2 подтверждает FIN сегментом АСК и доставляет FIN приложению в виде признака конца файла EOF (предполагается, что у приложения есть незавершенная операция чтения). Позже приложение на хосте 2 закрывает свою сторону соединения, посылая FIN хосту 1, который отвечает сегментом АСК.
В этот момент хост 2 окончательно закрывает соединение и освобождает ресурсы. С точки зрения хоста 2, соединения больше не существует. Однако хост 1 закрывает соединение, а переходит в состояние TIME-WAIT и остается в нем в течение двух максимальных продолжительностей существования сегмента (2MSL maximum segment lifetime).
Состояние TIME-WAIT служит двум целям:
— не дать соединению пропасть при потере последнего АСК, посланного активной стороной, в результате чего другая сторона повторно посылает FIN;
— дать время исчезнуть «заблудившимся сегментам», принадлежащим этому соединению.
Проблемы с очередью TIME_WAIT
Те кто разрабатывает активно работающие с сетью сервисы может наступить на особенности работы протокола TCP: переходу многих (или всех свободных) портов в состояние TIME_WAIT. В интернете много поверхностной информации и много не совсем корректной. Рассмотрим что это за ситуации, и определим возможные пути выхода из них.
Протокол TCP: закрытие соединения
Ниже типичная схема жизненного цикла TCP-соединения:
Не будем рассматривать её целиком, а сосредоточимся на наиболее важной для нас части — закрытии соединения.
Сторона, инициировавшая закрытие соединения называется «активной», вторая — «пассивной». Причем не важно кто из них был инициатором установки соединения.
Со стороны «пассивной» стороны всё просто. Получив пакет FIN, система должна ответить на него соответствующим ACK-пакетом, но имеет право продолжить отправку данных. С момента получения FIN пакета соединение у пассивной стороны находится в состоянии CLOSE_WAIT. По готовности, отправляется ответный FIN-пакет, после чего сторона дожидается ACK-пакета на него. По получении ACK на ответный FIN — соединение для пассивной стороны закрыто.
С точки зрения «активной» стороны всё несколько сложнее. После отправки FIN-пакета активная сторона переходит в состояние FIN_WAIT_1. Далее возможны три ситуации:
Как видно из диаграммы и описания активная сторона отправляет последний пакет в сессии (ACK на пассивный FIN). Поскольку она не может узнать получен ли этот пакет, для неё предусмотрен статус TIME_WAIT. В данном состоянии соединение должно находиться время 2 * MSL (максимальное время жизни пакета): время доставки пакета пассивной стороне + время доставки возможного ответного пакета назад. На практике, в настоящее время, таймер TIME_WAIT устанавливается в 1 — 2 минуты. По истечению этого таймера соединение считается закрытым.
Проблема TIME_WAIT для исходящих соединений
Соединение в операционной системы идентифицируется четырьмя параметрами: локальный IP, локальный порт, удалённый IP, удаленный порт. Допустим, у нас есть клиент, который активно подключается/отключается к удаленной службе. Поскольку оба IP и удаленный порт остаются неизменными, то на каждое новое соединение выделяется новый локальный порт. Если клиент был активной стороной завершения TCP-сессии, то это соединение будет заблокировано какое-то время в состоянии TIME_WAIT. Если соединения в устанавливаются быстрее чем порты выходят из карантина, то при очередной попытке соединения клиент получит ошибку EADDRNOTAVAIL (errno=99).
Что можно предпринять:
TIME_WAIT на серверах
Главная опасность которою несет разрастание очереди TIME_WAIT на сервере — это исчерпание ресурсов.
Тем не менее могут быть неприятные инциденты и при работе с NAT-клиентами (когда за одним IP находятся большое количество клиентов сервера). В случае малого значения времени карантина порта на Firewall велика вероятность что к серверу придёт запрос соединения с того же порта, соединение с которым ещё не закрыто (находится в TIME_WAIT). В этом случае возможны два три сценария:
Что можно предпринять на сервере.
Параметры ядра net.ipv4.tcp_tw_reuse и net.ipv4.tcp_tw_recycle
В ядре Linux есть два параметра, позволяющие нарушать требования TCP-протокола, высвобождая соединения из TIME_WAIT раньше положенного срока. Обе эти опции базируются на расширении TCP-timestamps (маркировки пакетов относительными временными метками).
Русские Блоги
Здравствуйте, TIME_WAIT!
Что такое TIME_WAIT? Как это случилось?
Что делает TIME_WAIT?
Что нам делать, если TIME_WAIT слишком много?
1.Что такое TIME_WAIT? Как это случилось?
Почему это 2MSL?
Какова роль TIME_WAIT?
3. Что нам делать, если TIME_WAIT слишком много?
Если соединение TIME_WAIT не достигает определенного уровня, например нескольких тысяч, оно действительно может быть обработано. Фактически, потребление ресурсов ЦП и памяти очень мало. Если вам нужно настроить его, вы можете понять некоторые параметры, лежащие в его основе, чтобы предотвратить его влияние на бизнес-условия.
1.tcp_max_tw_buckets Максимальное количество сокетов TIME_WAIT, удерживаемых системой одновременно.Если это число превышено, сокет TIME_WAIT будет немедленно очищен и будет напечатано предупреждающее сообщение.
Из сравнения загрузки машины TIME_WAIT и нагрузки LOAD я не думаю, что это напрямую влияет на производительность машины. Я предпочитаю не изменять параметр tcp_max_tw_buckets, по крайней мере, он не уменьшит его. Если система показывает TCP: время ожидания времени Если переполнение таблицы сообщает об ошибке, пожалуйста, увеличьте ее соответствующим образом
2.net.ipv4.tcp_fin_timeout Время (в секундах), в течение которого TCP остается в состоянии FIN-WAIT-2 для соединения с сокетом, отсоединенного локальным концом. Другая сторона может быть отключена, или соединение не было прервано, или неожиданный процесс мертв. По умолчанию установлено значение 60 с, которое можно настроить на 30 с.
3.net.ipv4.tcp_timestamps RFC 1323 В разделе «Надежность TCP» была представлена опция TCP метки времени: два 4-байтовых поля меток времени, из которых первое 4-байтовое поле используется для экономии времени отправки пакета, а второе 4-байтовое Это поле используется для сохранения времени, когда данные последний раз были получены от другой стороны. С этими двумя временными полями также есть место для последующей оптимизации.tcp_tw_reuse,зависимость оптимизации tcp_tw_recycleпараметр tcp_timestamps
4.net.ipv4.tcp_tw_reuseРазрешить ли повторное использование сокетов TIME-WAIT для новых соединений TCP. По умолчанию 0, что означает закрытый.
параметры | Конфигурация по умолчанию | Настроить конфигурацию | объяснение |
---|---|---|---|
fs.file-max | 1048576 | 9999999 | Количество файловых дескрипторов, открытых всеми процессами |
fs.nr_open | 1635590 | 1635590 | Максимальное количество файлов, которое может быть выделено одним процессом |
net.core.rmem_default | 124928 | 262144 | Буфер чтения TCP по умолчанию |
net.core.wmem_default | 124928 | 262144 | Буфер отправки TCP по умолчанию |
net.core.rmem_max | 124928 | 8388608 | Максимальный буфер чтения TCP по умолчанию |
net.core.wmem_max | 124928 | 8388608 | Максимальный буфер отправки по умолчанию TCP |
net.ipv4.tcp_wmem | 4096 16384 4194304 | 4096 16384 8388608 | Буфер отправки TCP |
net.ipv4.tcp_rmem | 4096 87380 4194304 | 4096 87380 8388608 | TCP-буфер чтения |
net.ipv4.tcp_mem | 384657 512877 769314 | 384657 512877 3057792 | Объем памяти TCP |
net.core.netdev_max_backlog | 1000 | 5000 | Максимальное количество пакетов, которые можно поставить в очередь, когда каждый сетевой интерфейс получает пакеты быстрее, чем ядро может их обработать |
net.core.optmem_max | 20480 | 81920 | Максимально допустимый размер буфера на сокет |
net.core.somaxconn | 128 | 2048 | Максимальная длина очереди прослушивания для каждого порта. Это глобальный параметр. |
net.ipv4.tcp_fin_timeout | 60 | 30 | Для соединения сокета, отключенного локальным концом, время (в секундах), в течение которого TCP остается в состоянии FIN-WAIT-2. Другая сторона может быть отключена или не завершать соединение, или неожиданный процесс умирает |
net.core.netdev_max_backlog | 1000 | 10000 | Максимальное количество пакетов, которое можно поставить в очередь, когда каждый сетевой интерфейс получает пакеты быстрее, чем ядро может их обработать |
net.ipv4.tcp_max_syn_backlog | 1024 | 2048 | Максимальное количество запросов на подключение, которые не были подтверждены другой стороной в очереди. Если сервер часто перегружен, попробуйте увеличить это число |
net.ipv4.tcp_max_tw_buckets | 5000 | 5000 | Максимальное количество сокетов времени ожидания, обрабатываемых системой одновременно |
net.ipv4.tcp_tw_reuse | 0 | 1 | Разрешить ли повторное использование сокетов TIME-WAIT для новых соединений TCP |
net.ipv4.tcp_keepalive_time | 7200 | 900 | Укажите, через сколько секунд после передачи по каналу TCP сообщение с данными не передается, запустите пробное сообщение (отправьте пустое сообщение). |
net.ipv4.tcp_keepalive_intvl | 75 | 30 | Интервал между предыдущим тестовым пакетом и следующим тестовым пакетом |
net.ipv4.tcp_keepalive_probes | 9 | 3 | Указывает количество зондов |
Параметры tcp_tw_reuse и tcp_tw_recycle значительно уменьшат существование соединения TIME_WAIT, но неправильная настройка также приведет к риску нарушения целостности данных.
После полного понимания TIME_WAIT вам не нужно паниковать, потому что вы видите много TIME_WAIT