Я долго разбирался с проблемой, частично вызванной другим оборудованием, но MikroTik-роутер тоже был связан с ней следующим образом: роутер содержит правила Forward, которые пропускают Established/Related, сбрасывают Invalid и разрешают новые соединения в одном направлении. Ничего необычного. Это не NAT-среда, а pure routing.
Что я заметил: некоторые TCP-сессии, в которых нет трафика, считают таймаут “TCP unacked”, а не “TCP established”, как задано в connection tracking. Этот таймаут по умолчанию всего 5 минут, тогда как established — целый день. После этих 5 минут запись в трекинге удаляется, а через некоторое время удалённый конец закрывает неактивное соединение с FIN ACK, который отбрасывается как “invalid” (что правильно), и локальная сторона никогда не видит закрытия соединения, думая, что оно всё ещё открыто.
Когда локальная сторона пытается отправить данные, роутер создаёт новую запись трекинга, и данные отправляются. Но дальше по пути есть ещё один файрвол (не MikroTik), который видел этот безответный FIN ACK и уже удалил свою запись трекинга, поэтому он сбрасывает эти данные как недействительные. При этом он не отправляет никакого ответа, чтобы сообщить об этом. Локальная система видит "мертвое" TCP-соединение и ругается.
Я обошёл эту проблему сначала, отправляя TCP RESET для TCP-трафика, который сбрасывался как invalid (это заставляет локальную систему понять, что что-то не так и заново устанавливать сессию). Но потом я заметил корень проблемы, увеличил таймаут “TCP unacked” — и теперь сессия корректно закрывается.
Однако корень проблемы в неправильной классификации неактивной сессии. Кажется, я уже сталкивался с этим раньше — SSH-сессии, которые умирали при простое. В моём случае исследовалась связь Linux — Windows, в случае SSH — Linux с Linux.
Что вообще означает “TCP Unacked”? Там есть и таймер “TCP retransmit”, но он не задействован (я менял таймауты, чтобы понять, какой именно отсчитывает). В WiKi это не описано. Может быть, этот таймер срабатывает некорректно, когда одна сторона шлёт “TCP Keepalive”, а другая — нет?
Что я заметил: некоторые TCP-сессии, в которых нет трафика, считают таймаут “TCP unacked”, а не “TCP established”, как задано в connection tracking. Этот таймаут по умолчанию всего 5 минут, тогда как established — целый день. После этих 5 минут запись в трекинге удаляется, а через некоторое время удалённый конец закрывает неактивное соединение с FIN ACK, который отбрасывается как “invalid” (что правильно), и локальная сторона никогда не видит закрытия соединения, думая, что оно всё ещё открыто.
Когда локальная сторона пытается отправить данные, роутер создаёт новую запись трекинга, и данные отправляются. Но дальше по пути есть ещё один файрвол (не MikroTik), который видел этот безответный FIN ACK и уже удалил свою запись трекинга, поэтому он сбрасывает эти данные как недействительные. При этом он не отправляет никакого ответа, чтобы сообщить об этом. Локальная система видит "мертвое" TCP-соединение и ругается.
Я обошёл эту проблему сначала, отправляя TCP RESET для TCP-трафика, который сбрасывался как invalid (это заставляет локальную систему понять, что что-то не так и заново устанавливать сессию). Но потом я заметил корень проблемы, увеличил таймаут “TCP unacked” — и теперь сессия корректно закрывается.
Однако корень проблемы в неправильной классификации неактивной сессии. Кажется, я уже сталкивался с этим раньше — SSH-сессии, которые умирали при простое. В моём случае исследовалась связь Linux — Windows, в случае SSH — Linux с Linux.
Что вообще означает “TCP Unacked”? Там есть и таймер “TCP retransmit”, но он не задействован (я менял таймауты, чтобы понять, какой именно отсчитывает). В WiKi это не описано. Может быть, этот таймер срабатывает некорректно, когда одна сторона шлёт “TCP Keepalive”, а другая — нет?
