Ответы:
Базовый TCP ACK говорит: «Я получил все байты до X». Выборочный ACK позволяет сказать: «Я получил байты XY и VZ».
Так, например, если хост отправил вам 10 000 байтов, а 3000-5000 байтов были потеряны при передаче, ACK сказал бы: «Я получил все до 3000». Другой конец должен был бы отправить байты 3001-10000 снова. SACK может сказать: «Я получил 1000-2999 и 5001-10000», а хост просто отправит 3000-5000.
Это хорошо для канала с высокой пропускной способностью, потерями (или высокой задержкой). Проблема в том, что это может вызвать серьезные проблемы с производительностью в определенных обстоятельствах. Обычные TCP ACK заставляют сервер обрабатывать соединение с высокой пропускной способностью и потерями с помощью защитных перчаток (отправка 500 байтов, ожидание, отправка 500 байтов, ожидание и т. Д.). SACK позволяет ему адаптироваться к высокой задержке, потому что он точно знает, сколько пакетов было фактически потеряно.
Здесь могут случиться плохие вещи. Злоумышленник может заставить ваш сервер долго хранить огромную очередь повторной передачи, а затем обрабатывать эту чертову вещь снова и снова. Это может привязать процессор, поглотить оперативную память и потреблять большую пропускную способность, чем следует. Короче говоря, облегченная система может инициировать DoS против более мощного сервера.
Если ваш сервер надежен и не обслуживает большие файлы, вы довольно хорошо защищены от этого.
Если вы в основном обслуживаете внутреннюю сеть или другую группу пользователей с низкой задержкой, SACK ничего не покупает и может быть отключен по соображениям безопасности без потери производительности.
Если вы используете канал с низкой пропускной способностью (скажем, 1 Мбит / с или менее в качестве абсолютно произвольного эмпирического правила), SACK может вызвать проблемы в обычных операциях, насыщая ваше соединение, и его следует отключить.
В конечном счете, решать вам. Подумайте, что вы служите, кому, от чего, и сравните степень вашего риска с эффектами производительности SACK.
Здесь представлен большой обзор SACK и его уязвимости .
Другая причина, по которой TCP SACK часто отключается, заключается в том, что существует огромное количество сетевых устройств, которые не могут правильно обработать эту опцию. Мы видим это все время с помощью продукта для высокоскоростной передачи файлов, который использует TCP. Наиболее распространенной проблемой является проблема шлюзовых устройств, которые выполняют такие вещи, как рандомизирование порядковых номеров для пакетов TCP, проходящих через устройство из внутренних сетей во внешние, но которые не отменяют рандомизацию параметров TCP SACK, которые могут отправляться с удаленного устройства. конец. Если фактические значения SACK не переводятся этими устройствами обратно в надлежащие значения, тогда сеанс TCP никогда не завершится перед лицом потери пакетов, когда удаленный конец попытается использовать SACK, чтобы получить выборочные преимущества ACK.
Вероятно, это было бы не такой проблемой, если бы люди стали более агрессивно применять профилактическое обслуживание программного обеспечения к этому устройству, но они этого не делают.
На горьком опыте я могу подтвердить, что tcp_sack = 1 вызывает остановленную передачу данных через sftp / rsync / scp и т. Д. С файлами, размер которых превышает 12 МБ, при использовании определенных устройств межсетевого экрана Cisco ASA.
КАЖДЫЙ раз это будет остановлено.
Мы передавали по выделенному каналу 100 Мбит / с между хостом A и хостом B в двух разных центрах обработки данных, используя оба брандмауэра Cisco и аппаратное обеспечение коммутатора с Centos.
Это может быть несколько смягчено путем изменения размеров буфера - например, я не мог передать файл 1GB через sftp с хоста A на хост B, если я не установил буфер sftp на 2048, но я мог независимо от того, тянул ли хост B файл из A.
Эксперименты с одним и тем же файлом с использованием настройки rsync и буфера отправки / получения позволили мне получить около 70 МБ файла размером 1 ГБ, передаваемого из A в B.
Однако окончательным ответом было отключить tcp_sack на хосте A. Первоначально, установив tcp_sack = 0 в ядре на лету - но в конечном итоге - я добавил его в мой /etc/sysctl.conf