Настройка ядра Linux для тяжелых проектов и защиты от DDOS

Процесс пошел, подумал я, и выйдя из «анабиозного» состояния раздолбая, я понял что нужно работать дальше…

Настройка ядра Linux для тяжелых проектов и защиты от DDOS

Сейчас речь пойдет о том, как можно настроить ядро Linux сервера, чтобы он смог переваривать большое количество запросов, а так же DDos. Все будет кратко с небольшим описанием.

Много материалов я вычитал, для того чтобы понять какие значения оптимальны, так же прилично всего перепробовал, и некоторые решения помогли мне уйти от той высокой нагрузки на сервере. Так же грамотная настройка ядра сервера позволит вам защититься от SYN flood. Ладно, начнем..

Каждый параметр подробненько…

rp_filter

— параметр который включает фильтр обратного пути, проще говоря активируется защита от подмены адресов (спуфинга).

Немного подробное описание rp_filter...

По умолчанию он отключен:

cat /proc/sys/net/ipv4/conf/all/rp_filter 
0

Рекомендуется включить в «строгий режим» проверки (значение 2 включает «свободный режим» проверки), причем включить его можно на всех интерфейсах:

sysctl -w net.ipv4.conf.all.rp_filter=1

Так проверку можно включить на определенном интерфейсе:

sysctl -w net.ipv4.conf.eth0.rp_filter=1

accept_source_route

— запрет маршрутизации от источников.

Немного подробное описание accept_source_route...

По умолчанию эта опция отключена:

cat /proc/sys/net/ipv4/conf/all/accept_source_route 
0

Но если она у вас почему-то включена — отключите, желательно на всех интерфейсах:

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

accept_redirects, secure_redirects, send_redirects

— этими тремя параметрами мы запрещаем принимать и отправлять ICMP пакеты перенаправления. ICMP-перенаправления могут быть использованы злоумышленником для изменения таблиц маршрутизации.

Немного подробное описание... (eng)

По умолчанию все эти параметры включены:

cat /proc/sys/net/ipv4/conf/all/accept_redirects
1
cat /proc/sys/net/ipv4/conf/all/secure_redirects 
1
cat /proc/sys/net/ipv4/conf/all/send_redirects 
1

Но, так как наш сервер не маршрутизатор, в них нет необходимости:

sysctl -w net.ipv4.conf.all.accept_redirects=0^C
sysctl -w net.ipv4.conf.all.secure_redirects=0^C
sysctl -w net.ipv4.conf.all.send_redirects=0

icmp_echo_ignore_broadcasts

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

По умолчанию включено, т.е. broadcast icmp запросы приходить не будут:

cat /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
1

Так и рекомендуется отставить:

sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1

icmp_ignore_bogus_error_responses

— игнорируем ошибочные ICMP запросы.

По умолчанию:

cat /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
1

Так и рекомендуется отставить:

sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1

icmp_echo_ignore_all

— отключаем ответ на ICMP запросы (сервер не будет пинговаться)

По умолчанию:

cat /proc/sys/net/ipv4/icmp_echo_ignore_all 
0

На ваше усмотрение, можно отключить:

sysctl -w net.ipv4.icmp_echo_ignore_all=1

tcp_syncookies

— по умолчанию данный параметр обычно включен. Если количество SYN пакетов забивает всю очередь, включается механизм Syn cookies.

Как проверить, включен ли он у нас:

cat /proc/sys/net/ipv4/tcp_syncookies
1 

Если выдает 1, то включен, 0 — значит отключен. Для отключения «на лету» достаточно воспользоваться следующей командой:

sysctl -w net.ipv4.tcp_syncookies=0

Естественно поставив в конце «1» — механизм будет снова включен.

Немного подробное описание tcp_syncookies...

Таким образом, как описано выше, мы получаем неплохую защиту от syn флуда и терпим небольшую нагрузку на ЦП..

Но согласно описанию, включать генерацию syncookies на высоконагруженных серверах, для которых этот механизм срабатывает, при большом количестве легальных соединений, не следует. Если в логах  есть предупреждения о SYN-флуде, при этом это вполне нормальные соединения, нужно настраивать другие параметры: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.


tcp_max_syn_backlog

— параметр который определяет максимальное число запоминаемых запросов на соединение, для которых не было получено подтверждения от подключающегося клиента (полуоткрытых соединений). По умолчанию:

cat /proc/sys/net/ipv4/tcp_max_syn_backlog
512

Если на сервере возникают перегрузки, можно попытаться увеличить это значение, например до 4096:

sysctl -w net.ipv4.tcp_max_syn_backlog=4096

tcp_synack_retries

—  время удержания «полуоткрытых» соединений.

Немного подробное описание tcp_synack_retries...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_synack_retries
5

Это значение имеет смысл уменьшить, например до 1 (это будет 9 секунд):

sysctl -w net.ipv4.tcp_synack_retries=1

tcp_max_orphans

— определяет максимальное число «осиротевших» TCP пакетов.

Немного подробное описание tcp_max_orphans...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_max_orphans 
262144

Рекомендуется установить 65536, а далее увеличивать, по мере необходимости:

sysctl -w net.ipv4.tcp_max_orphans=65536

tcp_fin_timeout

—  время ожидания приема FIN до полного закрытия сокета.

Немного подробное описание tcp_fin_timeout...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_fin_timeout 
60

Рекомендуется поменять на 10 секунд:

sysctl -w net.ipv4.tcp_fin_timeout=10

tcp_keepalive_time

— проверять TCP-соединения, с помощью которой можно убедиться в том что на той стороне легальная машина, так как она сразу ответит.

Немного подробное описание tcp_keepalive_time...

По умолчанию 2 часа:

cat /proc/sys/net/ipv4/tcp_keepalive_time
7200

Рекомендуется каждую минуту:

sysctl -w net.ipv4.tcp_keepalive_time=60

tcp_keepalive_intvl

— интервал подачи проб…

Немного подробное описание...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75

Рекомендуется поставить:

sysctl -w net.ipv4.tcp_keepalive_intvl=15

tcp_keepalive_probes

— Количество проверок перед закрытием соединения.

Немного подробное описание tcp_keepalive_probes...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_keepalive_probes
9

Рекомендуется поставить:

sysctrl -w net.ipv4.tcp_keepalive_probes=5

netdev_max_backlog

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

По умолчанию:

cat /proc/sys/net/core/netdev_max_backlog
1000

Рекомендуется так и оставить:

sysctl -w net.ipv4.netdev_max_backlog=1000

somaxconn

— Максимальное число открытых сокетов, ждущих соединения.

По у молчанию:

cat /proc/sys/net/core/somaxconn
1024

Рекомендуется установить значения в районе 15000-20000:

sysctl -w net.ipv4.net.core.somaxconn=15000

tcp_mem

— векторная (минимум, режим нагрузки, максимум) переменная которая cодержит общие настройки потребления памяти для протокола TCP

Немного подробное описание tcp_mem...
Немного подробное описание tcp_mem... (еще одно)

По умолчанию:

cat /proc/sys/net/ipv4/tcp_mem
96552 128739 193104

Можно поставить эти же значения.увеличивать имеет смысл в случае увеличения нагрузки.


tcp_rmem

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

Немного подробное описание tcp_rmem...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4119648

Можно поставить эти же значения.увеличивать имеет смысл в случае увеличения нагрузки. В одном из источнике рекомендовали следующие значения:

sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"

tcp_wmem

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

Немного подробное описание...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4119648

Можно оставить эти же значения. Увеличивать их имеет смысл в случае увеличения нагрузки. В одном из источнике рекомендовали следующие значения:

sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

rmem_default, wmem_default

Так же есть «глобальные» параметры размеров буфера, и они не перекрывают значения переменных tcp_rmem и tcp_wmem (читай описание выше)

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

Их значения по умолчанию:

cat /proc/sys/net/core/rmem_default 
229376
cat /proc/sys/net/core/wmem_default 
229376

Можно оставить эти же значения. Увеличивать их имеет смысл в случае увеличения нагрузки. Например, в одном из источнике рекомендовали следующие значения:

sysctl -w net.core.rmem_default=65536
sysctl -w net.core.wmem_default=65536

rmem_max, wmem_max

а эти «глобальные» параметры перекрывают «максимумы» переменных tcp_rmem и tcp_wmem (опять же, читай описание выше)

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

Их значения по умолчанию:

cat /proc/sys/net/core/rmem_max
131071
cat /proc/sys/net/core/wmem_max
131071

Можно оставить эти же значения. Увеличивать их имеет смысл в случае увеличения нагрузки. Например, в одном из источнике рекомендовали следующие значения:

sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

tcp_orphan_retries

— параметр который определяет число неудачных попыток, после которого уничтожается соединение TCP, закрытое на локальной стороне.

Немного подробное описание tcp_orphan_retries...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_orphan_retries 
0

Рекомендуется уменьшить значение этого параметра, поскольку закрытые соединения могут поглощать достаточно много ресурсов (т.е. оставляем 0):

sysctl -w net.ipv4.tcp_orphan_retries=0

ip_conntrack_max

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

По умолчанию:

cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max
65536

При слишком маленьких значениях ядро начинает отвергать входящие подключения с соответствующей записью в системном логе:

sysctl -w net.ipv4.netfilter.ip_conntrack_max=16777216

tcp_timestamps

— включает временные метки протокола TCP, которые позволяют управлять работой протокола в условиях высоких нагрузок (с помощью tcp_congestion_control)

Немного подробное описание...

По умолчанию метки включены:

cat /proc/sys/net/ipv4/tcp_timestamps
1

Кстати, лучше отставить его включенным, иначе не будет работать опция tcp_tw_reuse.

sysctl -w net.ipv4.tcp_timestamps=1

tcp_sack

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

Немного подробное описание...

По умолчанию опция включена:

cat /proc/sys/net/ipv4/tcp_sack 
1

Рекомендуется включать эту опцию, если вы имеете неустойчивые соединения. Однако, если вы соединены 1.5-метровым кабелем с другой машиной, то в таком случае, для достижения наивысшей скорости обмена, следует эту опцию отключить:

sysctl -w net.ipv4.tcp_sack=1

tcp_congestion_control

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

Немного подробное описание...

По умолчанию:

cat /proc/sys/net/ipv4/tcp_congestion_control 
cubic

Для сервера рекомендуется использовать htcp:

sysctl -w net.ipv4.tcp_congestion_control=htcp

tcp_no_metrics_save

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

По умолчанию опция ничего не запрещает:

cat /proc/sys/net/ipv4/tcp_no_metrics_save
0

Так как это помогает повысить производительность, рекомендуется включить:

sysctl -w net.ipv4.tcp_no_metrics_save=1

net.ipv4.route.flush

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

Так как в ядре 3.2 она даже не читается, менять ничего не стал.


ip_local_port_range

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

Немного подробное описание...

По умолчанию там такой диапазон:

cat /proc/sys/net/ipv4/ip_local_port_range 
32768 61000

Для тяжелых проектов диапазон рекомендуется увеличить:

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

tcp_tw_reuse

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

Немного подробное описание tcp_tw_reuse (eng)...

По умолчанию отключена:

cat /proc/sys/net/ipv4/tcp_tw_reuse
0

Лучше включить:

sysctl -w net.ipv4.tcp_tw_reuse=1

tcp_window_scaling

— опция позволяет динамически изменять размер окна TCP стека

Немного подробное описание...

По умолчанию она включена:

cat /proc/sys/net/ipv4/tcp_window_scaling
1 

Лучше так и оставить:

sysctl -w net.ipv4.tcp_window_scaling=1

tcp_rfc1337

— с помощью этой опции мы можем защитить себя от  TIME_WAIT атак.

Немного подробное описание...

По умолчанию опция отключена:

cat /proc/sys/net/ipv4/tcp_rfc1337
0

На сервере она точно не помешает:

sysctl -w net.ipv4.tcp_rfc1337=1

ip_forward

— данная опция управляет переадресацией пакетов. Если этот параметр выключен, ОС считает себя узлом IP сети и дропает все пакеты, предназначенные не ей. Если параметр включен, то ОС считает себя маршрутизатором и действует в соответствии с RFC1812, в том числе пытается переслать адресованные не ей пакеты в соответствии с таблицей маршрутизации.

По умолчанию переадресация включена:

cat /proc/sys/net/ipv4/ip_forward 
0

Если сервер не является маршрутизатором, то включать эту опцию нет необходимости:

sysctl -w net.ipv4.ip_forward=0

tcp_abort_on_overflow

— Эта переменная заставляет ядро отвергать новые соединения, если их поступает количество, с которым система не в состоянии справиться. Эту переменную следует использовать как крайнюю меру! По умолчанию она отключена:

cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

Если ситуация требует, то ее можно включить:

sysctl -w net.ipv4.tcp_abort_on_overflow=1

Как все это применить?

Я намеренно для изменения параметров использовал утилиту sysctl, а значения этих параметров просто читал с помощью cat. Сделано это было все для того, чтобы вам было ясно что способов изменения параметров ядра много.

Например, внести изменения мы так же можем с помощью echo:

echo "20000" > /proc/sys/net/ipv4/tcp_max_syn_backlog

А прочитать значения мы так же можем с помощью команды sysctl:

sysctl net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_max_syn_backlog = 2048

Кому какой способ больше нравится — решайте сами.

Как применить все эти значения разом, не сохраняя их?

Можно прочитать все описание выше и каждую переменную применять руками, с помощью «sysctl -w», и все эти значения будут работать до тех пор, пока вы не перезагрузите систему. Это полезно, пока ваше ядро находится в режиме «вашей отладки».

Для удобства ниже приведены все параметры разом, если решение вам нужно здесь и сейчас:

# включает фильтр обратного пути, она же защита от спуфинга (включаем строгий режим)
sysctl -w net.ipv4.conf.all.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

# запрещаем принимать и отправлять ICMP пакеты перенаправления
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

# отключаем ответ на broadcast ICMP ECHO
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1

# игнорируем ошибочные ICMP запросы
sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1

# ответ на ICMP запросы 
sysctl -w net.ipv4.icmp_echo_ignore_all=0

# отключаем механизм SYN cookies (лучше отключить на высоконагруженных серверах)
sysctl -w net.ipv4.tcp_syncookies=0

# максимальное число полуоткрытых соединений
sysctl -w net.ipv4.tcp_max_syn_backlog=4096

# время удержания полуоткрытых соединений
sysctl -w net.ipv4.tcp_synack_retries=1

# определяет максимальное число осиротевших TCP пакетов
sysctl -w net.ipv4.tcp_max_orphans=65536

# время ожидания приема FIN до полного закрытия сокета
sysctl -w net.ipv4.tcp_fin_timeout=10

# проверять TCP-соединения
sysctl -w net.ipv4.tcp_keepalive_time=60

# интервал передачи проб
sysctl -w net.ipv4.tcp_keepalive_intvl=15

# количество проверок перед закрытием соединения
sysctrl -w net.ipv4.tcp_keepalive_probes=5

# макс. кол-во пакетов в очереди на обработку, если интерфейс получает пакеты быстрее, чем ядро может их обработать
sysctl -w net.ipv4.netdev_max_backlog=1000

# Максимальное число открытых сокетов, ждущих соединения
sysctl -w net.ipv4.net.core.somaxconn=15000

# размер приемного буфера сокетов TCP (мин-нагрузка-макс)
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"

# размер передающего буфера сокетов TCP (мин-нагрузка-макс)
sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# размер буфера приема данных по умолчанию для всех соединений
sysctl -w net.core.rmem_default=229376

# Размер буфера передачи данных по умолчанию для всех соединений
sysctl -w net.core.wmem_default=229376

# макс. размер буфера приема данных для всех соединений
sysctl -w net.core.rmem_max=16777216

# макс. размер буфера передачи данных для всех соединений
sysctl -w net.core.wmem_max=16777216

# число неудачных попыток, после которого уничтожается соединение TCP, закрытое на локальной стороне
sysctl -w net.ipv4.tcp_orphan_retries=0

# макс кол-во соединений для работы механизма connection tracking
sysctl -w net.ipv4.netfilter.ip_conntrack_max=16777216

# включает временные метки протокола TCP
sysctl -w net.ipv4.tcp_timestamps=1

# разрешаем выборочные подтверждения протокола TCP
sysctl -w net.ipv4.tcp_sack=1

# протокол, используемый для управления нагрузкой в сетях TCP
sysctl -w net.ipv4.tcp_congestion_control=htcp

# запрещаем сохранять результаты изменений TCP соединения в кеше при его закрытии
sysctl -w net.ipv4.tcp_no_metrics_save=1

# диапазон локальных портов, доступных для установки исходящих подключений
sysctl -w net.ipv4.ip_local_port_range="1024 65535"

# включаем повторное использование TIME-WAIT сокетов для безопасных протоколов
sysctl -w net.ipv4.tcp_tw_reuse=1

# разрешаем динамически изменять размер окна TCP стека
sysctl -w net.ipv4.tcp_window_scaling=1

# включаем защиту от TIME_WAIT атак
sysctl -w net.ipv4.tcp_rfc1337=1

# отключаем переадресацию пакетов
sysctl -w net.ipv4.ip_forward=0

Как сохранить эти значения?

Если сервер работает корректно со всеми настройками указанными выше, то для их сохранения достаточно добавить все эти переменные в конец файла /etc/sysctl.conf:

net.ipv4.conf.all.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.conf.all.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.icmp_echo_ignore_all=0
net.ipv4.tcp_syncookies=0
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.tcp_synack_retries=1
net.ipv4.tcp_max_orphans=65536
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=5
net.ipv4.netdev_max_backlog=1000
net.ipv4.net.core.somaxconn=15000
net.ipv4.tcp_rmem="4096 87380 16777216"
net.ipv4.tcp_wmem="4096 65536 16777216"
net.core.rmem_default=229376
net.core.wmem_default=229376
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_orphan_retries=0
net.ipv4.netfilter.ip_conntrack_max=16777216
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.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

Заключение

На этом вроде все. В процессе написания статьи я изучал всевозможные настройки ядра, поэтому если есть где-то неточности или вам есть чем дополнить данный материал — пишите, буду очень рад.

Источники и все такое…