Я установил для tcp_tw_recycle / reuse значение 1 в моем файле конфигурации.
Каковы последствия этого?
Если повторно используется TCP-сокет, представляет ли это угрозу безопасности? то есть 2 разных соединения, которые потенциально могут отправлять данные?
Подходит ли он для кратковременных подключений с небольшой вероятностью повторного подключения?
По умолчанию, когда оба tcp_tw_reuse
и tcp_tw_recycle
отключены, ядро будет следить за тем, чтобы сокеты в TIME_WAIT
состояние будет оставаться в этом состоянии достаточно долго - достаточно долго, чтобы быть уверенным, что пакеты, принадлежащие будущим соединениям, не будут приняты за поздние пакеты старого соединения.
Когда вы включаете tcp_tw_reuse
, розетки в TIME_WAIT
состояние может использоваться до истечения срока их действия, и ядро будет пытаться убедиться, что нет конфликтов в отношении порядковых номеров TCP. Если вы включите tcp_timestamps
(a.k.a. PAWS, для защиты от обернутых порядковых номеров), он гарантирует, что эти коллизии не могут произойти. Однако вам нужно включить временные метки TCP на обе заканчивается (по крайней мере, я так понимаю). Увидеть определение tcp_twsk_unique за кровавые подробности.
Когда вы включаете tcp_tw_recycle
, ядро становится намного более агрессивным и будет делать предположения о временных метках, используемых удаленными хостами. Он будет отслеживать последнюю временную метку, используемую каждым удаленным хостом, имеющим соединение в TIME_WAIT
state) и разрешить повторно использовать сокет, если временная метка увеличилась правильно. Однако, если временная метка, используемая хостом, изменяется (т. Е. Откатывается назад во времени), SYN
пакет будет отброшен без уведомления, и соединение не будет установлено (вы увидите ошибку, похожую на «время ожидания соединения»). Если вы хотите погрузиться в код ядра, определение tcp_timewait_state_process может быть хорошей отправной точкой.
Отметки времени никогда не должны возвращаться назад во времени; если:
TIME_WAIT
сокет, вероятно, истек, так что это не проблема);TIME_WAIT
соединения останутся немного, но другие соединения, вероятно, будут поражены TCP RST
и это освободит место);В последнем случае у вас может быть несколько хостов за одним и тем же IP-адресом и, следовательно, разные последовательности меток времени (или упомянутые метки времени рандомизируются при каждом подключении межсетевым экраном). В этом случае некоторые хосты не смогут подключиться случайным образом, потому что они сопоставлены с портом, для которого TIME_WAIT
корзина сервера имеет более новую метку времени. Вот почему в документации говорится, что «устройства NAT или балансировщики нагрузки могут начать пропускать кадры из-за настройки».
Некоторые рекомендуют покинуть tcp_tw_recycle
один, но включить tcp_tw_reuse
и ниже tcp_timewait_len
. Я согласен :-)
Я только что укусил меня этим, так что, возможно, кому-то будут полезны мои боль и страдания. Во-первых, задействованная ссылка с большим количеством информации: http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html
В частности:
Простым результатом этого отсутствия документации является то, что мы находим многочисленные руководства по настройке, в которых советуют установить оба этих параметра на 1, чтобы уменьшить количество записей в состоянии TIME-WAIT. Однако, как указано на странице руководства tcp (7), параметр net.ipv4.tcp_tw_recycle довольно проблематичен для общедоступных серверов, поскольку он не обрабатывает соединения с двух разных компьютеров за одним и тем же устройством NAT, что является трудной проблемой. обнаруживают и ждут, чтобы укусить вас:
Я использовал их достаточно успешно, чтобы обеспечить как можно меньшую задержку, возможность подключения haproxy от клиентов к кластеру MySql NDB. Это было в частном облаке, и ни одно соединение вообще не имело никакого NAT в смеси. Сценарий использования имел смысл: максимально снизить задержку для клиентов RADIUS, попадающих в NDB через haproxy. Так оно и было.
Я сделал это снова на общедоступной системе haproxy, с балансировкой нагрузки веб-трафика, без особого изучения воздействия (тупой, верно ?!) и обнаружил после долгого устранения неполадок и преследования призраков, что:
На стороне клиента они будут видеть периоды времени, когда они больше не получают ответов на пакеты SYN, иногда здесь и там, а иногда и в течение длительного времени. Опять случайно.
Короткий рассказ здесь, из моего недавнего болезненного опыта, таков: оставьте их в покое / отключите на общедоступных серверах, независимо от роли!
Из "man 7 tcp" вы увидите следующее:
tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
Enable fast recycling of TIME_WAIT sockets. Enabling this option is not recommended since this causes problems when working with NAT
(Network Address Translation).
tcp_tw_reuse (Boolean; default: disabled; since Linux 2.4.19/2.6)
Allow to reuse TIME_WAIT sockets for new connections when it is safe from protocol viewpoint. It should not be changed without
advice/request of technical experts.
Здесь не особо помогает. У этого вопроса также есть хорошее понимание:
https://stackoverflow.com/questions/6426253/tcp-tw-reuse-vs-tcp-tw-recycle-which-to-use-or-both
Но не конкретная информация о том, почему повторное использование безопаснее, чем переработка. Основной ответ заключается в том, что tcp_tw_reuse позволит использовать один и тот же сокет, если он уже есть в TIME_WAIT с теми же параметрами TCP и находится в состоянии, в котором не ожидается дальнейшего трафика (я считаю, что это когда был отправлен FIN ). С другой стороны, tcp_tw_recycle будет просто повторно использовать сокеты, находящиеся в TIME_WAIT, с одинаковыми параметрами независимо от состояния, что может сбить с толку межсетевые экраны с отслеживанием состояния, которые могут ожидать разные пакеты.
tcp_tw_reuse может выполняться выборочно в коде путем установки параметра сокета SO_REUSEADDR, описанного в man 7 socket
в качестве таких:
SO_REUSEADDR
Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses. For AF_INET
sockets this means that a socket may bind, except when there is an active listening socket bound to the address. When the listening
socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address. Argument is
an integer boolean flag.