17 Мар 2012

Настройка ядра Linux для поддержки большого числа соединений (~100k) и защиты от DDOS

Пособирал по интернету интересные настройки ядра Linux для обеспечения бесперебойной работы серверов, имеющих дело в большим количеством подключений: торрент-трекеры, вебсерверы и т.д. Один из моих серверов с данными настройками выдержал 258014 соединений. Может быть, выдержал бы и больше, не знаю 🙂 Соединения считались с помощью wc -l /proc/net/ip_conntrack

net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0

Не принимать и не отправлять ICMP-пакеты перенаправления. ICMP-перенаправления могут быть использованы злоумышленником для изменения таблиц маршрутизации. Целесообразно выставить в «0». Единица имеет смысл только для хостов, использующихся в качестве маршрутизаторов.

net.ipv4.tcp_max_orphans = 65536

Целочисленное значение параметра tcp_max_orphans определяет максимальное число допустимых в системе сокетов TCP, не связанных каким-либо идентификатором пользовательского файла (user file handle). При достижении порогового значения “осиротевшие” (orphan) соединения незамедлительно сбрасываются с выдачей предупреждения. Этот порог помогает предотвращать только простые атаки DoS. Не следует уменьшать пороговое значение (скорее увеличить его в соответствии с требованиями системы – например, после добавления памяти. Каждое orphan-соединение поглощает около 64 Кбайт несбрасываемой на диск (unswappable) памяти.

net.ipv4.tcp_fin_timeout = 10

Параметр tcp_fin_timeout определяет время сохранения сокета в состоянии FIN-WAIT-2 после его закрытия локальной стороной. Партнер может не закрыть это соединение никогда, поэтому следует закрыть его по своей инициативе по истечении тайм-аута. По умолчанию тайм-аут составляет 60 секунд. В ядрах серии 2.2 обычно использовалось значение 180 секунд и вы можете сохранить это значение, но не следует забывать, что на загруженных WEB-серверах вы рискуете израсходовать много памяти на сохранение полуразорванных мертвых соединений. Сокеты в состоянии FIN-WAIT-2 менее опасны, нежели FIN-WAIT-1, поскольку поглощают не более 1,5 Кбайт памяти, но они могут существовать дольше.

net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_keepalive_intvl = 15

net.ipv4.tcp_keepalive_probes = 5

tcp_keepalive_time Переменная определяет как часто следует проверять соединение, если оно давно не используется. Значение переменной имеет смысл только для тех сокетов, которые были созданы с флагом SO_KEEPALIVE. Целочисленная переменная tcp_keepalive_intvl определяет интервал передачи проб. Произведение tcp_keepalive_probes * tcp_keepalive_intvl определяет время, по истечении которого соединение будет разорвано при отсутствии откликов. По умолчанию установлен интервал 75 секунд, т.е., время разрыва соединения при отсутствии откликов составит приблизительно 11 минут.

net.ipv4.tcp_max_syn_backlog = 4096

Целочисленное значение в файле tcp_max_syn_backlog определяет максимальное число запоминаемых запросов на соединение, для которых не было получено подтверждения от подключающегося клиента. Если на сервере возникают перегрузки, можно попытаться увеличить это значение.

net.ipv4.tcp_synack_retries = 1

Целочисленное значение (1 байт) tcp_synack_retries определяет число попыток повтора передачи пакетов SYNACK для пассивных соединений TCP. Число попыток не должно превышать 255. Значение 5 соответствует приблизительно 180 секундам на выполнение попыток организации соединения.

net.ipv4.tcp_mem = 50576   64768   98152

Векторная (минимум, режим нагрузки, максимум) переменная в файле tcp_mem cодержит общие настройки потребления памяти для протокола TCP. Эта переменная измеряется в страницах (обычно 4Кб), а не байтах.

Миниум: пока общий размер памяти для структур протокола TCP менее этого количества страниц, операционная система ничего не делает.

Режим нагрузки: как только количество страниц памяти, выделенное для работы протокола TCP, достигает этого значения, активируется режим работы под нагрузкой, при котором операционная система старается ограничивать выделение памяти. Этот режим сохраняется до тех пор, пока потребление памяти опять не достигнет минимального уровня.

Максимум: максимальное количество страниц памяти, разрешенное для всех TCP сокетов.

net.ipv4.tcp_rmem = 4096 87380 16777216

Векторная (минимум, по умолчанию, максимум) переменная в файле tcp_rmem содержит 3 целых числа, определяющих размер приемного буфера сокетов TCP.

Минимум: каждый сокет TCP имеет право использовать эту память по факту своего создания. Возможность использования такого буфера гарантируется даже при достижении порога ограничения (moderate memory pressure). Размер минимального буфера по умолчанию составляет 8 Кбайт (8192).

Значение по умолчанию: количество памяти, допустимое для буфера передачи сокета TCP по умолчанию. Это значение применяется взамен параметра /proc/sys/net/core/rmem_default, используемого другими протоколами. Значение используемого по умолчанию буфера обычно (по умолчанию) составляет 87830 байт. Это определяет размер окна 65535 с заданным по умолчанию значением tcp_adv_win_scale и tcp_app_win = 0, несколько меньший, нежели определяет принятое по умолчанию значение tcp_app_win.

Максимум: максимальный размер буфера, который может быть автоматически выделен для приема сокету TCP. Это значение не отменяет максимума, заданного в файле /proc/sys/net/core/rmem_max. При “статическом” выделении памяти с помощью SO_RCVBUF этот параметр не имеет значения.

net.ipv4.tcp_wmem = 4096 65536 16777216

Векторная переменная в файле tcp_wmem содержит 3 целочисленных значения, определяющих минимальное, принятое по умолчанию и максимальное количество памяти, резервируемой для буферов передачи сокета TCP.

Минимум: каждый сокет TCP имеет право использовать эту память по факту своего создания. Размер минимального буфера по умолчанию составляет 4 Кбайт (4096)

Значение по умолчанию: количество памяти, допустимое для буфера передачи сокета TCP по умолчанию. Это значение применяется взамен параметра /proc/sys/net/core/wmem_default, используемого другими протоколами и обычно меньше, чем /proc/sys/net/core/wmem_default. Размер принятого по умолчанию буфера обычно (по умолчанию) составляет 16 Кбайт (16384)

Максимум: максимальное количество памяти, которое может быть автоматически выделено для буфера передачи сокета TCP. Это значение не отменяет максимум, заданный в файле /proc/sys/net/core/wmem_max. При “статическом” выделении памяти с помощью SO_SNDBUF этот параметр не имеет значения.

net.ipv4.tcp_orphan_retries = 0

Целочисленной значение tcp_orphan_retries определяет число неудачных попыток, после которого уничтожается соединение TCP, закрытое на локальной стороне. По умолчанию используется значение 7, соответствующее приблизительно периоду от 50 секунд до 16минут в зависимости от RTO. На сильно загруженных WEB-серверах имеет смысл уменьшить значение этого параметра, поскольку закрытые соединения могут поглощать достаточно много ресурсов.

net.ipv4.tcp_syncookies = 0

Согласно рекомендациям разработчиков ядра, этот режим лучше отключить.

net.ipv4.netfilter.ip_conntrack_max = 1048576

Максимальное количество соединений для работы механизма connection tracking (используется, например, iptables). При слишком маленьких значениях ядро начинает отвергать входящие подключения с соответствующей записью в системном логе.

net.ipv4.tcp_timestamps = 1

Разрешает временные метки протокола TCP. Их наличие позволяет управлять работой протокола в условиях серьезных нагрузок (см. tcp_congestion_control).

net.ipv4.tcp_sack = 1

Разрешить выборочные подтверждения протокола TCP. Опция необходима для эффективного использования всей доступной пропускной способности некоторых сетей. См. статью для определения целесообразности использования.

net.ipv4.tcp_congestion_control = htcp

Протокол, используемый для управления нагрузкой в сетях TCP. bic и cubic реализации, используемые по умолчанию, содержат баги в большинстве версий ядра RedHat и ее клонов. Рекомендуется использовать htcp.

net.ipv4.tcp_no_metrics_save = 1

Не сохранять результаты измерений TCP соединения в кеше при его закрытии. В некоторых случаях помогает повысить производительность.

net.ipv4.route.flush=1

Актуально для ядер 2.4. По странной причине в ядрах 2.4, если в рамках TCP сессии произошел повтор передачи с уменьшенным размером окна, все соединения с данным хостом в следующие 10 минут будут иметь именно этот уменьшенный размер окна. Данная настройка позволяет этого избежать.

net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

Активируем защиту от IP-спуфинга.

net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

Запрещаем маршрутизацию от источника.

net.ipv4.ip_local_port_range = 1024 65535

Увеличиваем диапазон локальных портов, доступных для установки исходящих подключений

net.ipv4.tcp_tw_reuse = 1

Разрешаем повторное использование TIME-WAIT сокетов в случаях, если протокол считает это безопасным.

net.ipv4.tcp_window_scaling = 1

Разрешаем динамическое изменение размера окна TCP стека

net.ipv4.tcp_rfc1337 = 1

Защищаемся от TIME_WAIT атак.

net.ipv4.ip_forward = 0

Запрещаем переадресацию пакетов, поскольку мы не роутер.

net.ipv4.icmp_echo_ignore_broadcasts = 1

Не отвечаем на ICMP ECHO запросы, переданные широковещательными пакетами

net.ipv4.icmp_echo_ignore_all = 1

Можно вообще не отвечать на ICMP ECHO запросы (сервер не будет пинговаться)

net.ipv4.icmp_ignore_bogus_error_responses = 1

Не отвечаем на ошибочно сформированные сообшения

net.core.somaxconn = 15000

Максимальное число открытых сокетов, ждущих соединения. Имеет смысл увеличить значение по умолчанию, для высоконагруженных серверов советуют значения в районе 15000-20000.

net.core.netdev_max_backlog = 1000

Параметр определяет максимальное количество пакетов в очереди на обработку, если интерфейс получает пакеты быстрее, чем ядро может их обработать.

net.core.rmem_default=65536

Размер буфера приема данных по умолчанию для всех соединений.

net.core.wmem_default=65536

Размер буфера передачи данных по умолчанию для всех соединений.

net.core.rmem_max = 16777216

Максимальный размер буфера приема данных для всех соединений.

net.core.wmem_max = 16777216

Максимальный размер буфера передачи данных для всех соединений.

 

Скрипт для изменения параметров

Просто скопируйте все строки ниже и вставьте в консоль (правая кнопка мыши в Putty):

 sysctl -w net.ipv4.conf.all.accept_redirects=0
 sysctl -w net.ipv4.conf.all.secure_redirects=0
 sysctl -w net.ipv4.conf.all.send_redirects=0
 sysctl -w net.ipv4.tcp_max_orphans=65536
 sysctl -w net.ipv4.tcp_fin_timeout=10
 sysctl -w net.ipv4.tcp_keepalive_time=1800
 sysctl -w net.ipv4.tcp_keepalive_intvl=15
 sysctl -w net.ipv4.tcp_keepalive_probes=5
 sysctl -w net.ipv4.tcp_max_syn_backlog=4096
 sysctl -w net.ipv4.tcp_synack_retries=1
 sysctl -w net.ipv4.tcp_mem=50576   64768   98152
 sysctl -w net.ipv4.tcp_rmem=4096 87380 16777216
 sysctl -w net.ipv4.tcp_wmem=4096 65536 16777216
 sysctl -w net.ipv4.tcp_orphan_retries=0
 sysctl -w net.ipv4.tcp_syncookies=0
 sysctl -w net.ipv4.netfilter.ip_conntrack_max=1048576
 sysctl -w net.ipv4.tcp_timestamps=1
 sysctl -w net.ipv4.tcp_sack=1
 sysctl -w net.ipv4.tcp_congestion_control=htcp
 sysctl -w net.ipv4.tcp_no_metrics_save=1
 sysctl -w net.ipv4.route.flush=1
 sysctl -w net.ipv4.conf.all.rp_filter=1
 sysctl -w net.ipv4.conf.lo.rp_filter=1
 sysctl -w net.ipv4.conf.eth0.rp_filter=1
 sysctl -w net.ipv4.conf.default.rp_filter=1
 sysctl -w net.ipv4.conf.all.accept_source_route=0
 sysctl -w net.ipv4.conf.lo.accept_source_route=0
 sysctl -w net.ipv4.conf.eth0.accept_source_route=0
 sysctl -w net.ipv4.conf.default.accept_source_route=0
 sysctl -w net.ipv4.ip_local_port_range=1024 65535
 sysctl -w net.ipv4.tcp_tw_reuse=1
 sysctl -w net.ipv4.tcp_window_scaling=1
 sysctl -w net.ipv4.tcp_rfc1337=1
 sysctl -w net.ipv4.ip_forward=0
 sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
 sysctl -w net.ipv4.icmp_echo_ignore_all=1
 sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
 sysctl -w net.core.somaxconn=15000
 sysctl -w net.core.netdev_max_backlog=1000
 sysctl -w net.core.rmem_default=65536
 sysctl -w net.core.wmem_default=65536
 sysctl -w net.core.rmem_max=16777216
 sysctl -w net.core.wmem_max=16777216

Перманентное сохранение настроек

Если сервер после применения настроек работает нормально, добавьте настройки в файл /etc/sysctl.conf в следующем виде:

net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.tcp_max_orphans=65536
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_keepalive_time=1800
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.tcp_synack_retries=1
net.ipv4.tcp_mem=50576   64768   98152
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_orphan_retries=0
net.ipv4.tcp_syncookies=0
net.ipv4.netfilter.ip_conntrack_max=1048576
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_congestion_control=htcp
net.ipv4.tcp_no_metrics_save=1
net.ipv4.route.flush=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.lo.rp_filter=1
net.ipv4.conf.eth0.rp_filter=1
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.accept_source_route=0
net.ipv4.conf.lo.accept_source_route=0
net.ipv4.conf.eth0.accept_source_route=0
net.ipv4.conf.default.accept_source_route=0
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_rfc1337=1
net.ipv4.ip_forward=0
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_echo_ignore_all=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.core.somaxconn=15000
net.core.netdev_max_backlog=1000
net.core.rmem_default=65536
net.core.wmem_default=65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216

Метки: , , , , ,

7 комментариев “Настройка ядра Linux для поддержки большого числа соединений (~100k) и защиты от DDOS”

  1. Alexander говорит:

    Наткнулся на вашу статью. Очень полезная, спасибо большое.

    Скажите, а вы уже пробовали эти настройки в «боевом» режиме?

    +я бы еще добавил настройку fs.file-max , т.к. если с высоконагруженного сервера раздаётся очень много файлов, то мы можем «уткнуться» в лимит, прописанный по умолчанию.

  2. FractalizeR говорит:

    Да, эти настройки работают на нескольких моих серверах так сказать в боевом режиме. Сервер раздает файлы как раз, но fs.file-max прописывать пока не требовалось. Все работает и так. Этот параметр по умолчанию там равен 781064 🙂

  3. Maxim Pochtar говорит:

    Благодарю! Интересная статья.

    Параметры сервер принял. Правда, кроме одного:

    # sysctl -w net.ipv4.ip_local_port_range=1024 65535
    net.ipv4.ip_local_port_range = 1024
    error: «65535» must be of the form name=value

  4. FractalizeR говорит:

    Кавычки проглотились.

    sysctl -w net.ipv4.ip_local_port_range="1024 64000"

  5. anzhela говорит:

    «Опция еобходима для эффективного использования всей доступной пропускной способности» — «н» пропустили. А по сабжу — отличная статья, настройки пригодились и сэкономили кучу времени, спасибо!

  6. FractalizeR говорит:

    Исправил, спасибо!

Ответить

Для отправки комментария вам нужно зарегистрироваться. Войти.