awesome-everything EN
↑ Обратно к восхождению

Сети и протоколы

SYN cookie, TFO и TIME-WAIT при высокой нагрузке

Суть Как SYN cookie обменивают память на CPU при flood-атаке, что экономит TCP Fast Open и почему его развёртывание застопорилось, и как устранить исчерпание TIME-WAIT на нагруженном балансировщике.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 16 min

Нагруженный балансировщик начинает возвращать EADDRNOTAVAIL на исходящих соединениях к бэкенду. Команда ss -tan показывает 30 000 сокетов в состоянии TIME-WAIT. Одновременно публичный слушатель атакуется SYN flood. Оба явления решаются через sysctl Linux — но неправильный sysctl ухудшает ситуацию.

При SYN flood очередь полуоткрытых соединений на сервере переполняется. Вместо выделения request_sock для каждого SYN ядро использует путь в net/ipv4/tcp_ipv4.c:cookie_v4_init_sequence:

ISN_в_SYN-ACK = MAC от (saddr, sport, daddr, dport, isn, secret)

Старшие 5 бит кодируют индекс MSS (8 вариантов), следующие 6 бит — счётчик минут (окно повтора), нижние 21 бит — HMAC. Соединение тут же забывается. Когда приходит ACK, cookie_v4_check пересчитывает и проверяет. Если проверка прошла — ядро выделяет полный сокет. Если нет — ACK молча отбрасывается.

Компромисс: CPU вместо памяти — хорошо для больших серверов, не для маленьких. Цена: в cookie выживает только MSS. Масштаб окна, SACK и метки времени, предложенные в исходном SYN, молча отбрасываются для соединений, прошедших проверку через cookie. На высококачественном пути с большим RTT во время flood пропускная способность легитимных клиентов деградирует — окно ограничено 64 КиБ без масштабирования.

Linux включает SYN cookie, когда очередь полуоткрытых соединений превышает tcp_max_syn_backlog (зависит от системы, обычно 4096). Включается через net.ipv4.tcp_syncookies=1 (по умолчанию с ядра 2.4). Значение 2 форсирует безусловную генерацию cookie для тестирования.

Компромиссы SYN cookie
Cookie защищает от
SYN flood / переполнения очереди полуоткрытых
Что выживает в cookie
Только индекс MSS (5 бит)
Что молча отбрасывается
Масштаб окна, SACK, метки времени
Окно без масштабирования
Максимум 64 КиБ на соединение
Дефолт Linux
tcp_syncookies=1 (условный)
Принудительно для тестов
tcp_syncookies=2
Найди ошибку

Трассировка tcpdump SYN flood с включёнными SYN cookie

log
$ sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' -tnn
14:23:45.123456 IP 203.0.113.50.34521 > 198.51.100.10.443: Flags [S], seq 1000000, win 29200, length 0
14:23:45.123489 IP 198.51.100.10.443 > 203.0.113.50.34521: Flags [S.], seq 3851629874, ack 1000001, win 28960, length 0
14:23:45.124000 IP 203.0.113.50.34522 > 198.51.100.10.443: Flags [S], seq 2000000, win 29200, length 0
14:23:45.124050 IP 198.51.100.10.443 > 203.0.113.50.34522: Flags [S.], seq 4025814937, ack 2000001, win 28960, length 0
14:23:45.125000 IP 203.0.113.50.34521 > 198.51.100.10.443: Flags [.], seq 1000001, ack 3851629875, win 29200, length 0
14:23:45.125010 IP 203.0.113.50.34522 > 198.51.100.10.443: Flags [.], seq 2000001, ack 4025814938, win 29200, length 0
14:23:45.200000 IP 203.0.113.100.55000 > 198.51.100.10.443: Flags [S], seq 5000000, win 29200, length 0
14:23:45.200050 IP 198.51.100.10.443 > 203.0.113.100.55000: Flags [S.], seq 2941837465, ack 5000001, win 28960, length 0
(ACK от 203.0.113.100 не пришёл; SYN flood с разных поддельных адресов)

Два ACK пришли (легитимные клиенты завершили рукопожатие), но третий источник ACK не отправил. Есть ли риск для сервера?

TCP Fast Open (TFO, RFC 7413)

Стандартное рукопожатие стоит 1 RTT до данных приложения. TFO устраняет это для последующих соединений:

  1. Первое соединение: сервер отправляет опцию Fast Open Cookie в SYN-ACK; клиент кэширует её для пары (IP-сервера, порт-сервера).
  2. Последующие соединения: клиент помещает cookie в SYN вместе с данными приложения размером до MSS; сервер проверяет и обрабатывает данные, пока завершает рукопожатие — экономя 1 RTT.

На RTT 280 мс (Лондон → Сидней) TFO экономит 280 мс на каждом тёплом соединении.

Реальность развёртывания: проблемы с промежуточными устройствами убили широкое серверное распространение TFO. Middlebox-устройства (файрволы, DPI, некоторые NAT-шлюзы) вырезают опцию TFO из SYN, ломая доставку cookie. Некоторые NAT-шлюзы ломают cookie при смене внешнего IP клиента. Откат обязателен, но добавляет задержку. Серверное развёртывание ограничено; большинство интереса к 0-RTT сместилось к QUIC, который работает поверх UDP и обходит протокольное окостенение сетевой инфраструктуры. Linux поддерживает обе стороны с ядра 3.6 (2012) через битовую маску net.ipv4.tcp_fastopen (1=клиент, 2=сервер, 3=оба).

Проследи
1/5

Нагруженный балансировщик возвращает EADDRNOTAVAIL на исходящих соединениях к одному апстриму. Проследите диагностику и исправление.

1
Step 1 of 5
Шаг 1: что означает EADDRNOTAVAIL на connect()?
2
Locked
Шаг 2: куда уходят порты?
3
Locked
Шаг 3: почему бы не уменьшить MSL для более быстрого выхода из TIME-WAIT?
4
Locked
Шаг 4: включаем net.ipv4.tcp_tw_reuse=1. Почему это безопасно?
5
Locked
Шаг 5: структурное исправление?
Викторина

Старший инженер утверждает, что SYN cookie не имеют никакой производительностной цены. В чём ошибка этого утверждения?

Викторина

Что делал tcp_tw_recycle и почему он был удалён из ядра Linux в 4.12?

Почему это работает

Почему интерес к TFO сместился к QUIC. TFO требует, чтобы клиентская библиотека и серверное приложение явно подключились, чтобы middlebox-устройства не вырезали опцию, и чтобы NAT-шлюзы не меняли адреса в полёте. QUIC обходит всё это, работая поверх UDP — middlebox-устройства, которые его не понимают, просто пересылают, и протокол может эволюционировать без изменений ядра. 0-RTT возобновление QUIC достигает той же экономии задержки, что и TFO, но с гораздо лучшим успехом развёртывания. Это паттерн, повторяющийся в сетях: когда существующий протокольный уровень слишком закостенел для эволюции, инновации перемещаются на уровень выше.

Вспомните перед уходом
  1. 01
    Объясните механизм SYN cookie: что кодируется в cookie, что теряется и когда ядро активирует cookie?
  2. 02
    Что такое исчерпание TIME-WAIT, что его вызывает и каковы три производственных исправления?
  3. 03
    Почему TCP Fast Open получил ограниченное серверное распространение, несмотря на доступность с Linux 3.6?
Итог

SYN cookie защищают нагруженные серверы от SYN flood, вычисляя криптографический токен из четырёхкортежа соединения и кодируя его в порядковом номере SYN-ACK, так что память не выделяется до прихода валидного ACK. Цена: в cookie выживает только MSS — SACK, масштаб окна и метки времени отбрасываются, ухудшая пропускную способность для легитимных клиентов с большим RTT во время flood. Включайте через tcp_syncookies=1 (по умолчанию) и убедитесь, что backlog достаточно велик, чтобы cookie не нужны были при стационарной нагрузке. Исчерпание TIME-WAIT — EADDRNOTAVAIL на connect() — устраняется через tcp_tw_reuse=1 (безопасное переиспользование на основе меток времени согласно RFC 6191), расширением ip_local_port_range и использованием пула соединений. Никогда не используйте tcp_tw_recycle (удалён в Linux 4.12, ломает NAT). TCP Fast Open экономит 1 RTT для тёплых соединений, но требует непрерывных middlebox-устройств; QUIC вытеснил большинство интереса к TFO.

Связанные уроки
Продолжить восхождение ↑BBR, производственная наблюдаемость и за пределами TCP
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources5
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05

Trademarks belong to their respective owners. Editorial reference only.