У меня есть несколько тысяч устройств за NAT, которые разговаривают с двумя серверами. Каждое устройство находится за локальным маршрутизатором (представьте модем / маршрутизатор), на котором они подключаются к частной сети, в которой есть тысячи этих устройств, а на шлюзе этой частной сети сеансы TCP от этих тысяч устройств получают перегрузку NAT / PAT динамически к портам на одном глобальном IP-адресе. Это будет означать, что, скажем, устройство 1 будет разговаривать с сервером, и соединение будет исходить от global_ip_of_the_router: port_number_1. Когда устройство 1 завершит разговор и связь NAT удалена, когда устройство 2 хочет поговорить с тем же сервером, удаленный маршрутизатор может назначить устройству 2 тот же глобальный порт, то есть сервер может видеть, что новое TCP-соединение исходит от global_ip_of_the_router: port_number_1
Сами устройства запускают TCP-соединение, отправляют HTTP-сообщение небольшого файла, разрывают TCP-соединение, создают новое соединение для следующего файла и т. Д. Это отлично работает для ~ 20 файлов, после чего на SYN устройство возвращает только ACK без SYN с сервера. ACK имеет совершенно другой номер ACK, чем порядковый номер в SYN. Устройство немедленно отправляет RST, отключается и пытается выполнить SYN с того же исходного порта через 1 секунду, все еще просто ACK, поэтому оно продолжает откатываться до 3,6,12,24,48 секунд, прежде чем отказаться. В RST от устройства, похоже, используется SEQ, следующий из ACK, в попытке закрыть старое соединение (с точки зрения сервера)
Удаленный хост - это AWS ELB. Вот гипотезы, которые у нас были и что мы пробовали:
Удаленный маршрутизатор должен обрабатывать завершенный сеанс TCP, отключать NAT и повторно использовать глобальный порт быстрее, чем целевой сервер (ELB). Это может быть причиной того, что ELB находится в TCP_TIME_WAIT, поэтому он отвечает на SYN с помощью ACK. Поскольку время ожидания TCP для ELB неизвестно, предполагая, что это было стандартное 60-секундное значение по умолчанию в ядре Linux, оно будет соответствовать таймауту NAT после FIN / RST на удаленном маршрутизаторе. Тем не менее, мы изменили его на маршрутизаторе на 70 секунд, чтобы избежать каких-либо условий гонки. Это не решило проблему. Мы предположили, что если удаленный маршрутизатор отключит NAT раньше, он назначит новый NAT для повторных попыток SYN, поскольку устройство выполняет свою отсрочку. И если проблема на сервере dest была связана с номером глобального порта, используемым на удаленном маршрутизаторе, то, что новый SYN поступает из нового глобального порта на IP-адресе маршрутизатора, должно вывести его из странного состояния. Теперь, хотя мы могли видеть эту работу, похоже, что вновь назначенный порт NAT также сталкивался с той же проблемой на сервере, возвращая ложный ACK, НО с еще одним другим номером ACK. Другая гипотеза заключалась в том, что это происходило только тогда, когда SEQ в SYN был ниже, чем порядковые номера в последнем соединении, которое использовало тот же глобальный порт на удаленном маршрутизаторе. то есть номер ACK в ложном ACK всегда будет выше, чем SEQ в SYN. (Мы переключили Wireshark на абсолютные порядковые номера, чтобы убедиться в этом). Однако оказывается, что мы наблюдаем случаи, когда SYN SEQ больше, чем номер ACK в ложном ACK. Так что эта теория отошла на второй план. Сейчас мы не понимаем, что может здесь происходить. Мы подозревали, что новое соединение получает тот же глобальный порт, что и старое соединение, однако, если это имело место, (а) заставляя маршрутизатор дольше сохранять NAT, он должен был предотвратить это, И (б) если маршрутизатор отключите NAT раньше и назначьте другой NAT для той же попытки подключения, что должно было решить проблему.
Любая помощь здесь в понимании поведения будет очень признательна.
Отслеживание Wireshark здесь: http://www.filedropper.com/traffictrace-anonymizedandpacketswithpayloadremoved
Обратите внимание, что трассировка анонимизирована (IP-адреса и MAC-адреса заменены), а все TCP-пакеты с полезной нагрузкой удалены. Первый экземпляр проблемы начинается с пакета 129, второй экземпляр - пакет 382, затем 463, 699, 816, 1120, 1278, 1323 и т. Д.
Взглянув на самый последний экземпляр в трассировке, мы сократили таймаут NAT после FIN / RST на маршрутизаторе. Вы можете видеть, что первые четыре раза ACK имеет номер AKC = 2899295595. Но на номере 5 ACK равен 3102149417. На номере 6 это 4158039292. Это потому, что здесь маршрутизатор настроен на тайм-аут NAT. раньше, поэтому эти попытки поступают из другого глобального порта маршрутизатора. Если проблема была связана с глобальным портом и предыдущим подключением, которое использовало глобальный порт, это должно было остановить его. Но проблема сохраняется, что заставляет нас думать, что это не связано с исходным портом, а является результатом чего-то в самом TCP SYN.
Вчера мы попытались установить таймер NAT post-FIN / RST на 300 секунд, и это разорванное соединение исчезло. Я предполагаю, что мы отложили повторное использование порта до некоторого момента, когда ELB отбросил предыдущее соединение. Нам интересно, является ли тайм-аут простоя для ELB, установленного на 295 секунд, тем же значением, которое используется для TCP_TIME_WAIT, или для обработки соединения как действительного даже после FIN. Хотя, если бы это было так, мы бы увидели, что намного больше соединений не работают из-за многократного повторного использования портов на маршрутизаторе. Было бы хорошо знать, что происходит.