Time wait что это
Перейти к содержимому

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.

Состояние TIME_WAIT в протоколе TCP позволяет системе убедиться в том, что в данном TCP-соединении действительно прекращена передача данных и никакие данные не были потеряны. Но возможное количество одновременно открытых сокетов — величина конечная, а значит — это ресурс, который тратится в том числе и на состояние TIME_WAIT , в котором не выполняется обслуживание клиента.


Механизм закрытия TCP-соединения

Разгадка, как и ожидалось, нашлась в документации ядра. Естественное желание администратора highload-системы — уменьшить «холостое» потребление ресурсов. Беглое гугление покажет нам множество советов, которые призывают включить опции ядра Linux tcp_tw_reuse и tcp_tw_recycle . Но с tcp_tw_recycle не всё так просто, как могло показаться.

    Параметр tcp_tw_reuse полезно включить в борьбе за ресурсы, занимаемые TIME_WAIT . TCP-соединение идентифицируется по набору параметров IP1_Port1_IP2_Port2 . Когда сокет переходит в состояние TIME_WAIT , при отключенном tcp_tw_reuse установка нового исходящего соединения будет происходить с выбором нового локального IP1_Port1 . Старые значения могут быть использованы только тогда, когда TCP-соединение окажется в состоянии CLOSED . Если ваш сервер создает множество исходящих соединений, установите tcp_tw_reuse = 1 и ваша система сможет использовать порты TIME_WAIT в случае исчерпания свободных. Для установки впишите в /etc/sysctl.conf :

И выполните команду:

История третья: об OSPF и мультикастовом трафике

Обслуживаемая корпоративная сеть была построена на базе tinc VPN и прилегающими к ней лучами IPSec и OVPN-соединений. Для маршрутизации всего этого адресного пространства L3 мы использовали OSPF. На одном из узлов, куда агрегировалось большое количество каналов, мы обнаружили, что небольшая часть сетей, несмотря на верную конфигурацию OSPF, периодически пропадает из таблицы маршрутов на этом узле.


Упрощенное устройство VPN-сети, используемой в описываемом проекте

В первую очередь проверили связь с маршрутизаторами проблемных сетей. Связь была стабильной:

Продиагностировав OSPF, мы удивились еще больше. На узле, где наблюдались проблемы, маршрутизаторы проблемных сетей отсутствовали в списке соседей. На другой стороне проблемный маршрутизатор в списке соседей присутствовал:

Следующим этапом исключили возможные проблемы с доставкой ospf hello от 172.24.0.1. Запросы от него приходили, а вот ответы — не уходили:

Никаких ограничений в iptables не было установлено — выяснили, что пакет отбрасывается уже после прохождения всех таблиц в Netfilter. Снова углубились в чтение документации, где и был обнаружен параметр ядра igmp_max_memberships , который ограничивает количество multicast-соединений для одного сокета. По умолчанию это количество равно 20. Мы, для круглого числа, увеличили его до 42 — работа OSPF нормализовалась:

Заключение

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

Устранение проблем нехватки портов

Протоколы TCP и UDP работают на основе номеров портов, используемых для установления подключения. Любому приложению или службе, для которых необходимо установить подключение TCP/UDP, потребуется порт на его стороне.

Существует два типа портов:

  • Временные порты, которые являются динамическими портами, — это набор портов, которые по умолчанию будут использоваться для исходящего подключения на каждом компьютере.
  • Известные порты — это определенный порт для конкретного приложения или службы. Например, служба файлового сервера находится на порту 445, HTTPS — 443, HTTP — 80, а RPC — 135. Пользовательские приложения также будут иметь определенные номера портов.

При установке подключения к приложению или службе клиентские устройства используют временный порт с устройства для подключения к известному порту, определенному для этого приложения или службы. Браузер на клиентском компьютере будет использовать временный порт https://www.microsoft.com для подключения через порт 443.

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

Диапазон динамических портов по умолчанию для TCP/IP

В соответствии с рекомендациями IANA корпорация Майкрософт увеличила диапазон динамических портов клиента для исходящих подключений. Новый начальный порт по умолчанию — 49152, а новый конечный порт по умолчанию — 65535. Это увеличение является изменением конфигурации более ранних версий Windows, которые использовали диапазон портов по умолчанию от 1025 до 5000.

Динамический диапазон портов на компьютере можно просмотреть с помощью следующих команд Netsh:

  • netsh int ipv4 show dynamicport tcp
  • netsh int ipv4 show dynamicport udp
  • netsh int ipv6 show dynamicport tcp
  • netsh int ipv6 show dynamicport udp

Диапазон задается отдельно для каждого транспорта (TCP или UDP). Диапазон портов теперь является диапазоном, который имеет начальную и конечную точки. Клиенты Майкрософт, которые развертывают серверы под управлением Windows Server, могут иметь проблемы, влияющие на связь RPC между серверами, если брандмауэры используются во внутренней сети. В таких ситуациях рекомендуется перенастроить брандмауэры, чтобы разрешить трафик между серверами в диапазоне динамических портов от 49152 до 65535. Этот диапазон является дополнением к известным портам, используемым службами и приложениями. Кроме того, диапазон портов, используемый серверами, можно изменить на каждом сервере. Этот диапазон можно изменить с помощью команды netsh, как показано ниже. Приведенная выше команда задает динамический диапазон портов для TCP.

Начальный порт — это число, а общее число портов — диапазон. Ниже приведены примеры команд.

  • netsh int ipv4 set dynamicport tcp start=10000 num=1000
  • netsh int ipv4 set dynamicport udp start=10000 num=1000
  • netsh int ipv6 set dynamicport tcp start=10000 num=1000
  • netsh int ipv6 set dynamicport udp start=10000 num=1000

Эти примеры команд задают динамический диапазон портов, который должен начинаться с порта 10000 и до порта 10999 (1000 портов). Минимальный диапазон портов, который можно задать, — 255. Минимальный начальный порт, который можно задать, — 1025. Максимальный конечный порт (в зависимости от заданного диапазона) не может превышать 65535. Чтобы дублировать поведение по умолчанию Windows Server 2003, используйте 1025 в качестве начального порта, а затем используйте 3976 в качестве диапазона для TCP и UDP. Этот шаблон использования приводит к началу порта 1025 и порту окончания 5000.

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

Так как исходящие подключения начинают завершаться сбоем, вы увидите множество экземпляров следующих поведений:

Не удается войти на компьютер с учетными данными домена, однако вход с помощью локальной учетной записи работает. Для входа в домен потребуется обратиться к контроллеру домена для проверки подлинности, что снова является исходящим подключением. Если у вас есть учетные данные кэша, вход в домен может по-прежнему работать.

Снимок экрана: ошибка NETLOGON в Просмотр событий.

групповая политика обновлений:

Снимок экрана: свойства события для групповая политика сбоя.

Общие папки недоступны:

Снимок экрана: сообщение об ошибке "Windows не удается получить доступ".

RDP с затронутого сервера завершается ошибкой:

Снимок экрана: ошибка, когда удаленному рабочему столу не удается подключиться.

Любое другое приложение, работающее на компьютере, начнет выдать ошибки

Перезагрузка сервера временно устраните проблему, но по истечении определенного периода времени все симптомы будут устранены.

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

Попробуйте установить исходящее подключение. На сервере или компьютере получите доступ к удаленному ресурсу или попробуйте подключиться по протоколу RDP к другому серверу или telnet к серверу через порт. Если исходящее подключение завершается сбоем для всех этих параметров, перейдите к следующему шагу.

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

Код события 4227

Снимок экрана: событие с идентификатором 4227 в Просмотр событий.

Код события 4231

Снимок экрана: событие с идентификатором 4231 в Просмотр событий.

Соберите netstat -anob выходные данные с сервера. В выходных данных netstat будет показано огромное количество записей для TIME_WAIT для одного piD.

Снимок экрана: выходные данные команды netstate.

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

Вы также можете увидеть CLOSE_WAIT состояния в тех же выходных данных. однако CLOSE_WAIT состоянием является состояние, когда одна сторона однорангового узла TCP не имеет больше данных для отправки (отправлено FIN), но может получать данные с другого конца. Это состояние не обязательно указывает на нехватку портов.

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

Netstat был обновлен в Windows 10 с добавлением параметра -Q, чтобы отобразить порты, для которых истекло время ожидания, как в состоянии BOUND. Выпущено обновление для Windows 8.1 и Windows Server 2012 R2, содержащее эту функцию. Командлет PowerShell Get-NetTCPConnection в Windows 10 также отображает эти порты BOUND.

До 10.01.2016 netstat был неточным. Исправления для netstat, которые были перенаправлены на версию 2012 R2, Netstat.exe и Get-NetTcpConnection правильно сообщать об использовании портов TCP или UDP в Windows Server 2012 R2. Дополнительные сведения см. Windows Server 2012 R2. Исправления временных портов.

Откройте командную строку в режиме администратора и выполните следующую команду:

Откройте файл server.etl с помощью сетевого монитора и в разделе фильтра примените фильтр Wscore_MicrosoftWindowsWinsockAFD.AFD_EVENT_BIND. Status.USStatus.Code == 0x209. Вы должны увидеть записи с STATUS_TOO_MANY_ADDRESSES. Если вы не нашли записей, значит, на сервере по-прежнему нет портов. Если вы найдете их, можно убедиться, что сервер находится в нехватке портов.

Устранение неполадок нехватки портов

Ключ — определить, какой процесс или приложение использует все порты. Ниже приведены некоторые средства, которые можно использовать для изоляции одного процесса.

Метод 1

Начните с просмотра выходных данных netstat. Если вы используете Windows 10 или Windows Server 2016, netstat -anobq можно выполнить команду и проверить идентификатор процесса с максимальным количеством записей как BOUND. Кроме того, можно выполнить приведенную ниже команду PowerShell, чтобы определить процесс:

Большинство утечек портов вызвано неправильной закрытием портов процессами в пользовательском режиме при возникновении ошибки. На уровне пользовательского режима порты (фактически сокеты) являются дескрипторами. И TaskManager , и ProcessExplorer могут отображать счетчики дескрипторов, что позволяет определить, какой процесс использует все порты.

Для Windows 7 и Windows Server 2008 R2 можно обновить версию PowerShell, включив указанный выше командлет.

Метод 2

Если метод 1 не помогает определить процесс (до Windows 10 и Windows Server 2012 R2), ознакомьтесь с диспетчером задач:

Добавьте столбец с именем "handles" в разделе details/processes.

Отсортируйте дескриптора столбцов, чтобы определить процесс с наибольшим количеством дескриптора. Обычно процесс с дескрипторами больше 3000 может быть злоумышленником, за исключением таких процессов, как System, lsass.exe, store.exe, sqlsvr.exe.

Снимок экрана: столбец handles в Windows Task Maner.

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

Метод 3

Если диспетчер задач не помогает определить процесс, используйте обозреватель процессов для изучения проблемы.

Действия по использованию обозревателя процессов:

Скачайте обозреватель процессов и запустите его с повышенными привилегиями.

ALT+ щелкните заголовок столбца, выберите " Выбрать столбцы" и **** на вкладке "Производительность процесса" добавьте число дескрипторов.

Выберите "Вид\ Показать нижнюю панель".

Выберите представление \ Представление нижней панели \ Дескриптора.

Щелкните столбец "Дескриптора ", чтобы отсортировать его по значению.

Изучите процессы с более высоким числом дескриптора, чем остальные (скорее всего, будет более 10 000, если вы не сможете установить исходящие подключения).

Щелкните, чтобы выделить один из процессов с высоким числом дескриптора.

В нижней области дескрипторами, перечисленными ниже, являются сокеты. (Сокеты технически являются дескрипторами файлов).

Снимок экрана: обозреватель процессов.

Некоторые из них являются обычными, а большие — нет (от сотен до тысяч). Закройте указанный процесс. Если это приведет к восстановлению исходящих подключений, вы еще раз докакажите, что причиной является приложение. Обратитесь к поставщику этого приложения.

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

В качестве обходного решения перезагрузка компьютера приведет к его нормальному состоянию и поможет устранить проблему в настоящее время. Однако если перезагрузка нецелесообразно, вы также можете увеличить количество портов на компьютере с помощью следующих команд:

Эта команда задает диапазон динамических портов, который будет начинаться с порта 10000 и до порта 10999 (1000 портов). Минимальный диапазон портов, который можно задать, — 255. Минимальный начальный порт, который можно задать, — 1025. Максимальный конечный порт (в зависимости от заданного диапазона) не может превышать 65535.

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

Для Windows 7 и Windows Server 2008 R2 можно использовать приведенный ниже скрипт для сбора выходных данных netstat с определенной частотой. В выходных данных можно увидеть тенденцию использования портов.

Печенюшка

При использовании утилиты 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;
— дать время исчезнуть «заблудившимся сегментам», принадлежащим этому соединению.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *