Syn timeout error

В поисках причин, почему установленные соединения не разрываются в некоторых случаях, я набрёл на отличную статью в блоге Cloudflare. Которая, в итоге помогла н...

В поисках причин, почему установленные соединения не разрываются в некоторых случаях, я набрёл на отличную статью в блоге Cloudflare. Которая, в итоге помогла найти не только решение моей проблемы, но и помогла лучше понять как работают таймауты TCP соединений в Linux

Надеюсь перевод этой статьи будет полезен многим читателям хабра.

Начало

Работая над нашим сервером Spectrum, мы заметили нечто странное: TCP-сокеты, которые, как мы думали, должны были быть закрыты, оставались на месте. Мы поняли, что не совсем понимаем, когда TCP-сокеты должны завершать работу!

 Image by Sergiodc2 CC BY SA 3.0

Image by Sergiodc2 CC BY SA 3.0

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

В этой статье блога мы постараемся показать, как работают эти опции. Мы покажем, как TCP сокет может прерваться по времени на различных этапах своего существования, и как на это влияют TCP keepalives и пользовательский таймаут. Чтобы лучше проиллюстрировать внутреннее устройство TCP-соединений, мы смешаем результаты команд tcpdump и ss -o. Это наглядно показывает передаваемые пакеты и изменяющиеся параметры TCP-соединений.

SYN-SENT

Начнем с самого простого случая — что происходит при попытке установить соединение с сервером, который отбрасывает входящие SYN-пакеты?

Используемые здесь скрипты доступны на нашем Github.

syn-sent

syn-sent

Хорошо, это было просто. После системного вызова connect() операционная система посылает SYN-пакет. Поскольку она не получила никакого ответа, ОС по умолчанию повторит попытку отправки 6 раз. Это можно настроить с помощью sysctl:

$ sysctl net.ipv4.tcp_syn_retries
net.ipv4.tcp_syn_retries = 6

Можно переписать эту настройку для каждого сокета с помощью параметра TCP_SYNCNT setsockopt:

setsockopt(sd, IPPROTO_TCP, TCP_SYNCNT, 6);

Повторные попытки выполняются в шахматном порядке с интервалами 1с, 3с, 7с, 15с, 31с, 63с (время между повторными попытками начинается с 2с и затем каждый раз удваивается). По умолчанию весь процесс занимает 130 секунд, пока ядро не сдастся с ошибкой ETIMEDOUT errno. В этот момент времени жизни соединения настройки SO_KEEPALIVE игнорируются, а TCP_USER_TIMEOUT — нет. Например, установка значения 5000 мс приведет к следующему взаимодействию:

syn-sent-500

syn-sent-500

Несмотря на то, что мы установили время ожидания пользователя равным 5с, мы все еще видели шесть повторов SYN на сокете. Такое поведение, вероятно, является ошибкой (проверено на ядре 5.2): мы ожидали, что будет отправлено только две повторные попытки — на отметках 1с и 3с, а сокет истечет на отметке 5с. Вместо этого мы увидели это, но также мы увидели еще 4 повторно переданных SYN-пакета, выровненных по 5s отметке — что не имеет смысла. Так или иначе, мы узнали одну вещь — TCP_USER_TIMEOUT действительно влияет на поведение connect().

SYN-RECV

Сокеты SYN-RECV обычно скрыты от приложения. Они живут как мини-сокеты в очереди SYN. В прошлом мы писали об очередях SYN и Accept. Иногда, когда включены файлы cookie SYN, сокеты могут вообще пропустить состояние SYN-RECV.

В состоянии SYN-RECV сокет повторит попытку отправки SYN + ACK 5 раз, это контролируется:

$ sysctl net.ipv4.tcp_synack_retries
net.ipv4.tcp_synack_retries = 5

Вот как это выглядит в кабеле:

syn-recv

syn-recv

С настройками по умолчанию SYN+ACK повторно передается с отметками 1с, 3с, 7с, 15с, 31с, а сокет SYN-RECV исчезает с отметкой 64с.

Ни SO_KEEPALIVE, ни TCP_USER_TIMEOUT не влияют на время жизни сокетов SYN-RECV.

Заключительное рукопожатие ACK (Final handshake ACK)

После получения второго пакета в TCP-рукопожатии — SYN+ACK — клиентский сокет переходит в установленное состояние. Серверный сокет остается в SYN-RECV до тех пор, пока не получит окончательный пакет ACK.

Потеря этого ACK ничего не меняет — сокету сервера просто потребуется немного больше времени, чтобы перейти от SYN-RECV к ESTAB. Вот как это выглядит:

test-syn-ack

test-syn-ack

Как вы можете видеть, SYN-RECV имеет таймер «on», такой же, как в предыдущем примере. Мы могли бы возразить, что этот окончательный ACK на самом деле не имеет большого веса. Это мышление привело к разработке функции TCP_DEFER_ACCEPT — она в основном приводит к тому, что третий ACK автоматически отбрасывается. С установленным этим флагом сокет остается в состоянии SYN-RECV до тех пор, пока не получит первый пакет с фактическими данными:

test-syn-ack2

test-syn-ack2

Серверный сокет оставался в состоянии SYN-RECV даже после получения окончательного подтверждения TCP-рукопожатия. У него забавный таймер «on», счетчик застревает на 0 повторных попытках. Он преобразуется в ESTAB — и перемещается из SYN в очередь приема — после того, как клиент отправляет пакет данных или по истечении таймера TCP_DEFER_ACCEPT. По сути, при ОТЛОЖЕННОМ ПРИНЯТИИ мини-сокет SYN-RECV отбрасывает входящий ACK без данных.

Простаивающий ESTAB — это навсегда (Idle ESTAB is forever)

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

ESTABLISHED

ESTABLISHED

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

Вот тут-то и пригодятся TCP keepalives. Давайте посмотрим на это в действии — в этом примере мы использовали следующие переключатели:

  • SO_KEEPALIVE = 1 — Давайте включим keepalives.

  • TCP_KEEPIDLE = 5 — Отправить первый зонд keepalive после 5 секунд бездействия.

  • TCP_KEEPINTVL = 3 — отправка последующих пробников keepalive через 3 секунды.

  • TCP_KEEPCNT = 3 — Тайм-аут после трех неудачных попыток.

test-idle

test-idle

Действительно! Мы можем ясно видеть первый зонд, отправленный на отметке 5 секунд, два оставшихся зонда на расстоянии 3 секунд друг от друга — точно так, как мы указали. В общей сложности после трех отправленных зондов и еще трех секунд задержки соединение прерывается с помощью ETIMEDOUT, и, наконец, передается RST.

Чтобы keepalives работал, буфер отправки должен быть пустым. Вы можете заметить, что таймер keepalive активен в строке «таймер: (keepalive)».

Keepalives с TCP_USER_TIMEOUT сбивают с толку

Мы уже упоминали параметр TCP_USER_TIMEOUT. Он устанавливает максимальное время, в течение которого переданные данные могут оставаться неопознанными, прежде чем ядро принудительно закроет соединение. Сам по себе он мало что делает в случае неработающих соединений. Сокеты останутся ESTABLISHED, даже если соединение будет разорвано. Однако эта опция сокета изменяет семантику TCP keepalives. Руководство по tcp(7) несколько запутано:

Более того, при использовании с опцией TCP keepalive (SO_KEEPALIVE), TCP_USER_TIMEOUT будет преобладать над keepalive для определения момента закрытия соединения из-за отказа keepalive.

Исходное сообщение коммита содержит немного больше деталей:

  • tcp: Add TCP_USER_TIMEOUT socket option

To understand the semantics, we need to look at the kernel code in linux/net/ipv4/tcp_timer.c:693:

tcp-timers.c

tcp-timers.c

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

  • TCP_USER_TIMEOUT = 5*1000 — 5 seconds

  • SO_KEEPALIVE = 1 — enable keepalives

  • TCP_KEEPIDLE = 1 — быстрая отправка первого зонда — 1 секунда простоя

  • TCP_KEEPINTVL = 11 — последующие зонды каждые 11 секунд

  • TCP_KEEPCNT = 3 — отправить три зонда до истечения времени ожидания

keepalive

keepalive

Что же произошло? Соединение отправило первый зонд keepalive на отметке 1с. Не увидев ответа, стек TCP проснулся через 11 секунд, чтобы послать второй зонд. На этот раз, однако, он выполнил путь кода USER_TIMEOUT, который решил немедленно прервать соединение.

Что, если мы увеличим TCP_USER_TIMEOUT до больших значений, скажем, между вторым и третьим зондом? Затем соединение будет закрыто по таймеру третьего зонда. С TCP_USER_TIMEOUT, установленным на 12,5с:

keepalive_3_probe

keepalive_3_probe

Мы показали, как TCP_USER_TIMEOUT взаимодействует с keepalives для малых и средних значений. Последний случай — это когда TCP_USER_TIMEOUT необычайно велик. Допустим, мы установим его на 30 секунд:

keepalive_30s

keepalive_30s

Мы видели шесть зондов keepalive на проводе! При установке TCP_USER_TIMEOUT TCP_KEEPCNT полностью игнорируется. Если вы хотите, чтобы TCP_KEEPCNT имел смысл, единственное разумное значение USER_TIMEOUT немного меньше, чем:

TCP_KEEPIDLE + TCP_KEEPINTVL * TCP_KEEPCNT

Занятый сокет ESTAB не вечен (Busy ESTAB socket is not forever)

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

Давайте подготовим другой эксперимент — после трехстороннего рукопожатия настроим брандмауэр на отбрасывание всех пакетов. Затем выполним отправку на одном конце, чтобы иметь несколько отброшенных пакетов в полете. Эксперимент показывает, что отправляющий сокет умирает через ~16 минут:

tcp_retries2

tcp_retries2

Пакет данных повторно передается 15 раз, что контролируется:

$ sysctl net.ipv4.tcp_retries2
net.ipv4.tcp_retries2 = 15

Из документации ip-sysctl.txt:

Значение по умолчанию, равное 15, дает гипотетический тайм-аут в 924,6 секунды и является нижней границей эффективного тайм-аута. TCP фактически отключит время ожидания при первом RTO, которое превышает гипотетический тайм-аут.

Соединение действительно прервалось через ~ 940 секунд. Обратите внимание, что в сокете запущен таймер «on». Если мы установим SO_KEEPALIVE — не будет иметь никакого значения — когда таймер «on» запущен, keepalives не задействованы.

TCP_USER_TIMEOUT продолжает работать до конца. Соединение будет прервано точно по истечении указанного пользователем времени ожидания с момента последнего полученного пакета. При установленном таймауте пользователя значение tcp_retries2 игнорируется.

Нулевое окно ESTAB — это… навсегда?(Zero window ESTAB is… forever?)

Есть последний случай, о котором стоит упомянуть. Если у отправителя много данных, а приемник медленный, то включается TCP flow control. В какой-то момент получатель попросит отправителя прекратить передачу новых данных. Это несколько иное состояние, чем описанное выше.

В этом случае, когда включено управление потоком, нет никаких летящих или не подтвержденных данных. Вместо этого приемник дросселирует отправителя уведомлением о «нулевом окне». Затем отправитель периодически проверяет, действительно ли это условие, с помощью «зондов окна». В этом эксперименте мы уменьшили размер буфера приема, для простоты. Вот как это выглядит на проводе:

Захват пакетов показывает несколько вещей. Во-первых, мы видим два пакета с данными, каждый длиной 576 байт. Оба они были немедленно подтверждены. Второй ACK содержит уведомление «win 0»: отправителю было сказано прекратить отправку данных.

Но отправитель жаждет отправить еще! Последние два пакета показывают первый «зонд окна»: отправитель будет периодически посылать пакеты «ack» без полезной нагрузки, чтобы проверить, не изменился ли размер окна. До тех пор, пока получатель продолжает отвечать, отправитель будет посылать такие запросы вечно. Информация о сокете показывает три важные вещи:

  • Буфер чтения считывателя заполнен — таким образом, ожидается регулирование «нулевого окна».

  • Буфер записи отправителя заполнен — у нас есть больше данных для отправки.

  • У отправителя запущен таймер «persist», отсчитывающий время до следующего «оконного зонда».

В этой статье блога нас интересуют таймауты — что произойдет, если зонды окна будут потеряны? Заметит ли это отправитель?

По умолчанию оконный зонд повторяется 15 раз — в соответствии с обычной настройкой tcp_retries2.

Таймер tcp находится в состоянии persist, поэтому TCP keepalives не будет запущен. Настройки SO_KEEPALIVE не имеют никакого значения, если задействовано оконное зондирование.

Как и ожидалось, тумблер TCP_USER_TIMEOUT продолжает работать. Небольшое отличие заключается в том, что аналогично user-timeout для keepalives, он включается только при срабатывании таймера повторной передачи. Во время такого события, если с момента последнего хорошего пакета прошло более чем user-timeout секунд, соединение будет прервано.

Примечание об использовании тайм-аутов приложений

В прошлом мы делились интересной военной историей:

  • Любопытный случай медленной загрузки

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

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

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

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

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

  2. Установите TCP_USER_TIMEOUT равным:

    TCP_KEEPIDLE + TCP_KEEPINTVL * TCP_KEEPCNT

  3. Будьте осторожны при использовании тайм-аутов, управляемых приложением. Для обнаружения сбоев TCP используйте TCP keepalives и user-timeout. Если вы хотите сэкономить ресурсы и убедиться, что сокеты не работают слишком долго, подумайте о том, чтобы периодически проверять, истощается ли сокет с желаемой скоростью. Для этого вы можете использовать ioctl(SIOCOUTQ), но он учитывает как данные, буферизованные (не отправленные) в сокете, так и байты в полете (неподтвержденные). Лучший способ — использовать параметр TCP_INFO tcpi_notsent_bytes, который сообщает только о первом счетчике.

Пример проверки темпа слива:

pace_in_bytes_per_second

pace_in_bytes_per_second

Есть способы еще больше улучшить эту логику. Мы могли бы использовать TCP_NOTSENT_LOWFAT, хотя обычно это полезно только в ситуациях, когда буфер отправки относительно пуст. Тогда мы могли бы использовать интерфейс SO_TIMESTAMPING для уведомлений о том, когда данные будут доставлены. Наконец, если мы закончили отправку данных в сокет, можно просто вызвать close() и отложить обработку сокета для операционной системы. Такой сокет будет застрять в состоянии FIN-WAIT-1 или LAST-ACK до тех пор, пока он правильно не опустеет.

Выводы

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

  • SYN-SENT: продолжительность этого состояния можно контролировать с помощью TCP_SYNCNT или tcp_syn_retries.

  • SYN-RECV: обычно это скрыто от приложения. Он настраивается с помощью tcp_synack_retries.

  • Простаивающее ESTABLISHED соединение, никогда не заметит никаких проблем. Решением является использование TCP keepalives.

  • Зависшее ESTABLISHED соединение, придерживается настройки tcp_retries2 и игнорирует TCP keepalives.

  • Соединение ESTABLISHED с нулевым окном, придерживается настройки tcp_retries2 и игнорирует TCP keepalives.

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

Однако это опасная настройка, и если она используется в сочетании с TCP keepalives, ее следует устанавливать на значение немного меньше, чем TCP_KEEPIDLE + TCP_KEEPINTVL * TCP_KEEPCNT. В противном случае оно будет влиять на значение TCP_KEEPCNT и потенциально аннулировать его.

В этом посте мы представили сценарии, демонстрирующие влияние опций сокетов, связанных с таймаутом, в различных сетевых условиях. Чередование захвата пакетов tcpdump с выводом ss -o — отличный способ понять работу сетевого стека. Мы смогли создать воспроизводимые тестовые примеры, демонстрирующие таймеры «on», «keepalive» и «persist» в действии. Это очень полезная основа для дальнейших экспериментов.

Наконец, удивительно трудно настроить TCP-соединение так, чтобы быть уверенным, что удаленный узел действительно работает. Во время отладки мы обнаружили, что просмотр размера буфера отправки и текущего активного таймера TCP может быть очень полезен для понимания того, действительно ли сокет здоров. Ошибка в нашем приложении Spectrum оказалась в неправильной настройке TCP_USER_TIMEOUT — без нее сокеты с большими буферами отправки задерживались гораздо дольше, чем мы предполагали.

Скрипты, использованные в этой статье, можно найти на нашем Github.

Для решения этой задачи пришлось сотрудничать с тремя офисами Cloudflare. Спасибо Хирену Панчасаре из Сан-Хосе, Уоррену Нельсону из Остина и Якубу Ситницки из Варшавы.

Автор оригинальной статьи: Марек Майковски.
Ссылка на оригинальный пост: link

Hello all,

I posted yesterday about a similar topic and all the respones were awesome, very helpful so thank you for that!

Anyway, Im very curious and want to learn more about Cisco ASAs and the logs so I have a question.

A customer wants access to a public IP on port 22 so that they can share files. They claim that they cant reach the IP (let say 200.200.200.200). I asked them to confirm the source IP (10.230.150.36). Here is an output from the logs:

The ACL I configured:

access-list TRANSIT extended permit ip 10.230.150.36 255.255.240.0 host 200.200.200.200. I also see two hitcounts. The 10.230.150.36 is routed via the TRANSIT interface. The ACL is configured on IP and not on specific port. I know I should define a port (22 in this case) instead of just permitting on IP.

2021-07-08T09:10:02+02:00 10.230.130.25 %ASA-6-302013: Built outbound TCP connection 21416433 for OUTSIDE:200.200.200.200 (200.200.200.200) to CDN-TRANSIT:10.230.150.36/51536 (200.200.200.200/51536)

2021-07-08T09:10:21+02:00 10.230.130.25 %ASA-6-302013: Built outbound TCP connection 21419811 for OUTSIDE:200.200.200.200 (200.200.200.200) to CDN-TRANSIT:10.230.150.36/64416 (200.200.200.200/64416)

2021-07-08T09:10:32+02:00 10.230.130.25 %ASA-6-302014: Teardown TCP connection 21416433 for OUTSIDE:200.200.200.200 to CDN-TRANSIT:10.230.150.36/51536 duration 0:00:30 bytes 0 SYN Timeout

2021-07-08T09:10:51+02:00 10.230.130.25 %ASA-6-302014: Teardown TCP connection 21419811 for OUTSIDE:200.200.200.200 to CDN-TRANSIT:10.230.150.36/64416 duration 0:00:30 bytes 0 SYN Timeout

Here as you can see, we have «Build outbound TCP connection» which is good, that is what I want to see. But then you can se «Teardown TCP connection» bytes 0 SYN Timeout». What does that actually mean? I looked that up and apparently it means that the connection timed out because of the remote end server did not give a reply to the attempt of the user to form the TCP connection. So what I understand from this, it should be something on their end that blocking the user from attempting to access the 200.200.200.200, a firewall or an actual problem with the server maybe?

Thanks for all the help.

Во время собеседования я видел резюме кандидатов, написанные со знанием дела в сети и программировании TCP. Я часто задаю вопрос, сколько рукопожатий нужно TCP для установления соединения? Более 95% поступающих могут ответить правильно 3 раза. Требуется несколько рукопожатий, чтобы попросить TCP отключиться, и 70% кандидатов могут правильно ответить на 4 сообщения. Позвольте мне еще раз спросить CLOSE_WAIT, каков статус TIME_WAIT, как это произошло, какое влияние он оказывает на службу и как его устранить? Некоторые студенты не смогли ответить. Это не значит, что я вычитаю детали, но интерфейсный сервер на основе связи должен уметь обрабатывать различные состояния TCP. Например, для подсчета пикового времени TCP-соединения на клиентском компьютере нашей фабрики статистическая команда:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

 

результат:

В дополнение к ESTABLISHED, вы можете видеть, что есть несколько состояний с большим количеством подключений: FIN_WAIT1, TIME_WAIT, CLOSE_WAIT, SYN_RECV и LAST_ACK; в следующей статье кратко описаны условия генерации этих состояний, их влияние на систему и методы обработки.

Статус TCP

Статус TCP показан на рисунке ниже:

Может немного ослепить? Посмотрите на эту временную диаграмму еще раз

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

SYN_RECV 

Сервер находится в состоянии SYN_RECV, когда он получает SYN, который устанавливает соединение, и не получает пакет ACK. Есть две связанные конфигурации системы:

1,net.ipv4.tcp_synack_retries :INTEGER

Значение по умолчанию — 5.

Для SYN запроса удаленного подключения ядро ​​отправит дейтаграмму SYN + ACK, чтобы подтвердить получение последнего пакета запроса на подключение SYN. Это второй этап так называемого механизма трехстороннего рукопожатия. Это определяет количество SYN + ACK, отправленных ядром, прежде чем разорвать соединение. Не должно быть больше 255, значение по умолчанию — 5, что соответствует примерно 180 секундам. Обычно мы не изменяем это значение, потому что надеемся, что TCP-соединение не может быть установлено из-за случайной потери пакетов.

2,net.ipv4.tcp_syncookies

Как правило, сервер устанавливает net.ipv4.tcp_syncookies = 1 для предотвращения атак SYN Flood.Предположим, у пользователя внезапно происходит сбой или сбой после отправки SYN-сообщения на сервер.Line, то сервер не может получить сообщение ACK от клиента после отправки сообщения ответа SYN + ACK (третье рукопожатие не имеетМетод завершен). В этом случае сервер обычно повторяет попытку (снова отправляет SYN + ACK клиенту) и ждет некоторое времяНезавершенное соединение отбрасывается через некоторое время. Продолжительность этого периода времени называется SYN Timeout. Вообще говоря, на этот разЭто порядка минут (около 30 секунд — 2 минуты).

Эти TCP-соединения в SYNC_RECV называются полусоединениями и хранятся в очереди полусоединений ядра.Когда ядро ​​получает пакет подтверждения, отправленный одноранговым узлом, оно будет искать очередь полусоединения и сохранять соответствующую информацию requst_sock. пока не завершится трехстороннее рукопожатие в подключенной очереди, а затем удалите это полусоединение. МногоTCP-соединение SYNC_RECV вызовет переполнение очереди полусоединений, так что последующие запросы на установление соединения будут напрямую отклоняться ядром. Это атака SYN Flood.

Одним из эффективных способов предотвращения атак SYN Flood является SYN Cookie. Принцип SYN Cookie был изобретен Д. Дж. Бернстейном и Эриком Шенком. SYN Cookie — это способ изменить протокол трехстороннего подтверждения TCP-сервера, в частности, для предотвращения атак SYN Flood. Его принцип заключается в том, что когда TCP-сервер получает пакет TCP SYN и возвращает пакет TCP SYN + ACK, он не выделяет специальную область данных, а вычисляет значение cookie на основе пакета SYN. При получении пакета TCP ACK сервер TCP проверяет действительность пакета TCP ACK на основе значения cookie. Если это допустимо, выделите специальную область данных для обработки будущих TCP-соединений.

Количество соединений SYN_RECV в службе наблюдения равно 7314. Для сервера связи с большим количеством одновременных соединений это число относительно нормально.

CLOSE_WAIT

Сторона, которая инициирует закрытие TCP-соединения, называется клиентом, а сторона, которая пассивно закрывается, называется сервером. После того, как пассивно закрытый сервер получает FIN, состояние TCP, которое не отправило ACK, будет CLOSE_WAIT. Эта ситуация обычно возникает из-за проблем с кодом на стороне сервера. Если на вашем сервере появляется много CLOSE_WAIT, вам следует подумать о проверке кода.

TIME_WAIT

Согласно правилу отключения трехстороннего рукопожатия, определенному протоколом TCP, сокет стороны, которая инициирует активное закрытие сокета, перейдет в состояние TIME_WAIT. Состояние TIME_WAIT будет длиться 2 MSL (максимальное время жизни сегмента), что по умолчанию в Windows составляет 4 минуты, что составляет 240 секунд. Сокет в состоянии TIME_WAIT не может быть переработан. Специфическим явлением является то, что для сервера, который обрабатывает большое количество коротких соединений, если сервер активно закрывает клиентское соединение, это вызовет большое количество сокетов в состоянии TIME_WAIT на на стороне сервера, даже больше, чем в состоянии Established. Слишком много сокетов, что серьезно влияет на производительность сервера и даже исчерпывает доступные сокеты и останавливает службу.

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

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

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_fin_timeout, по умолчанию 60 секунд, уменьшите fin_timeout, уменьшите количество соединений TIME_WAIT.

net.ipv4.tcp_tw_reuse = 1 означает включение повторного использования. Разрешить повторное использование сокетов TIME-WAIT для новых TCP-соединений, значение по умолчанию — 0, что означает закрытие;

net.ipv4.tcp_tw_recycle = 1 означает включение быстрой перезагрузки сокетов TIME-WAIT в TCP-соединениях, по умолчанию 0, что означает закрытие.

Следующий:http://maoyidao.iteye.com/blog/1744309 “Опыт системы связи [2] Интерпретация параметров ядра — параметры ограничения ресурсов сокета / дескриптора файла «Я познакомлю вас с другими опциями заводских сетевых настроек, особенно с конфигурацией ядра, связанной с ограничениями системных ресурсов.

  • Remove From My Forums
  • Question

  • Hi All,

    We are running a real time application, sensitive for response time, over a wireless network. Most of the time it works well but 1-2% of the transactions encounter a response time of ~3 seconds. The application expects a response within 2 seconds before complaining.

    Looking further into it I can see that the delay happen during session setup, the three-way handshake. I’ve also found that there is a default timeout of 3s, in older Windows versions called TcpInitialRTT (see technet.microsoft.com/en-us/library/cc938207.aspx) My
    guess is that I loose a packet in the handshake and encounter this timeout.

    Is it possible to change this or a similar parameter in Windows Server 2012 / 2012R2?

    Is it advicable to set it to 1s or will I encounter other problems with this?

    Regards
    mnson

Answers

  • Hi mnson,

    Thanks for posting here.

    >>Is it possible to change this or a similar parameter in Windows Server 2012 / 2012R2?

    Like this link has mentioned before:

    «Windows does not add this entry to the registry.

    You could add it by editing the registry or by using a program that edits the registry.»

    https://technet.microsoft.com/en-us/library/cc938207.aspx

    >>Is it advicable to set it to 1s or will I encounter other problems with this?

    Based on my understanding , you could set it to 1s, but I suppose this settings will be changed due to the network connection speed.

    >>My guess is that I loose a packet in the handshake and encounter this timeout.

    You could use the Wireshark tool to monitor if there are packages dropped between the transactions.

    Download link:

    https://www.microsoft.com/en-us/download/details.aspx?id=4865

    Best regards,


    Andy_Pan

    • Proposed as answer by

      Tuesday, April 5, 2016 9:04 AM

    • Marked as answer by
      Hello_2018
      Thursday, April 7, 2016 7:53 AM

Понравилась статья? Поделить с друзьями:
  • Supply memori error
  • Supervisor error spawn error
  • Supervisor error no such process
  • Supersocket info spnregister error 1355
  • Supermicro ошибка ba