Определить SYN атаку просто — команда netstat выдает огромный список полуоткрытых подключений:
Можем просто подсчитать количество:
Для начала — проверяем параметр tcp_syncookies — он должен быть равен 1:
Так и оставляем. По умолчанию в новых дистрибутивах этот параметр всегда включен.
Если параметр tcp_syncookies установлен (доступен только когда ядро собрано с CONFIG_SYNCOOKIES), тогда ядро обрабатывает SYN пакеты TCP в обычном режиме до тех пор, пока очередь не заполнится. После заполнения очереди включается механизм SYN cookies.
SYN cookies вообще не использует очередь SYN. Вместо этого ядро отвечает на каждый SYN пакет, как обычно SYN|ACK, но туда будет включено специально сгенерированное число на основе IP адресов и портов источника и получателя, а также времени посылки пакета. Атакующий никогда не получит эти пакеты, а поэтому и не ответит на них. При нормальном соединении, будет послан третий пакет, содержащий число, а сервер проверит был ли это ответ на SYN cookie и, если да, то разрешит соединение даже в том случае, если в очереди SYN нет соответствующей записи.
Включение механизма SYN cookies является очень простым способом борьбы против атаки SYN флудом. При этом немного больше загружается процессор из-за необходимости создавать и сверять cookie. Так как альтернативным решением является отклонять все запросы на соединение, SYN cookies являются хорошим выбором.
Также нужно увеличить очередь полуоткрытых соединений — tcp_max_syn_backlog(в Debian Lenny по-умолчанию 1024 соединения):
Увеличиваем:
Кроме того, можем уменьшить время ожидания соединения tcp_synack_retries:
Целочисленное значение (1 байт) tcp_synack_retries определяет число попыток повтора передачи пакетов SYNACK для пассивных соединений TCP. Число попыток не должно превышать 255. Используемое по умолчанию значение 5 соответствует приблизительно 180 секундам на выполнение попыток организации соединения.
Уменьшаем до 1 (это примерно 9 секунд):
tcp_fin_timeout
Целое число в файле tcp_fin_timeout определяет время сохранения сокета в состоянии FIN-WAIT-2 после его закрытия локальной стороной. Партнер может не закрыть это соединение никогда, поэтому следует закрыть его по своей инициативе по истечении тайм-аута. По умолчанию тайм-аут составляет 60 секунд. В ядрах серии 2.2 обычно использовалось значение 180 секунд и вы можете сохранить это значение, но не следует забывать, что на загруженных WEB-серверах вы рискуете израсходовать много памяти на сохранение полуразорванных мертвых соединений. Сокеты в состоянии FIN-WAIT-2 менее опасны, нежели FIN-WAIT-1, поскольку поглощают не более 1,5 Кбайт памяти, но они могут существовать дольше.
Меняем на 30:
tcp_keepalive_probes
Целочисленная переменная tcp_keepalive_probes задает число передач проб keepalive, после которого соединение считается разорванным. По умолчанию передается 9 проб.
Ставим 5:
tcp_keepalive_intvl
Целочисленная переменная tcp_keepalive_intvl определяет интервал передачи проб. Произведение tcp_keepalive_probes * tcp_keepalive_intvl определяет время, по истечении которого соединение будет разорвано при отсутствии откликов. По умолчанию установлен интервал 75 секунд, т.е., время разрыва соединения при отсутствии откликов составит приблизительно 11 минут.
Ставим 15:
netdev_max_backlog
Здесь указывается максимальное количество пакетов в очередь на обработку если интерфейс получает пакеты быстрее, чем ядро может их обработать.
Увеличиваем:
somaxconn
Максимальное число открытых сокетов, ждущих соединения.
Увеличиваем:
Так как подобные изменения параметров ядра не сохранятся после перезагрузки — добавляем в /etc/rc.local:
Кроме того, можно добавить ограничение числа SYN пакетов в единицу времени в iptables:
Число новых SYN пакетов — максимум 500 в секунду, при превышении порога в 1500 — новые пакеты блокируются:
Более наглядно этот критерий можно представить себе как некоторую емкость с выпускным отверстием, через которое проходит определенное число пакетов за единицу времени (т.е. скорость «вытекания»). Скорость «вытекания» как раз и определяет величина --limit. Величина --limit-burst задает общий «объем емкости». А теперь представим себе правило --limit 3/minute --limit-burst 5, тогда после поступления 5 пакетов (за очень короткий промежуток времени), емкость «наполнится» и каждый последующий пакет будет вызывать «переполнение» емкости, т.е. «срабатывание» критерия. Через 20 секунд «уровень» в емкости будет понижен (в соответствии с величиной --limit), таким образом она готова будет принять еще один пакет, не вызывая «переполнения» емкости, т.е. срабатывания критерия.
https://rusua.org.ua/2013/01/07/411/
Код:
netstat -n --tcp | grep SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:1084 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:1228 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:2652 SYN_RECV
tcp 0 0 xxx.xxx.xxx.xxx:80 yyy.yyy.yyy.yyy:3446 SYN_RECV
Код:
netstat -n --tcp | grep SYN_RECV | wc -l
238
Код:
cat /proc/sys/net/ipv4/tcp_syncookies
1
Если параметр tcp_syncookies установлен (доступен только когда ядро собрано с CONFIG_SYNCOOKIES), тогда ядро обрабатывает SYN пакеты TCP в обычном режиме до тех пор, пока очередь не заполнится. После заполнения очереди включается механизм SYN cookies.
SYN cookies вообще не использует очередь SYN. Вместо этого ядро отвечает на каждый SYN пакет, как обычно SYN|ACK, но туда будет включено специально сгенерированное число на основе IP адресов и портов источника и получателя, а также времени посылки пакета. Атакующий никогда не получит эти пакеты, а поэтому и не ответит на них. При нормальном соединении, будет послан третий пакет, содержащий число, а сервер проверит был ли это ответ на SYN cookie и, если да, то разрешит соединение даже в том случае, если в очереди SYN нет соответствующей записи.
Включение механизма SYN cookies является очень простым способом борьбы против атаки SYN флудом. При этом немного больше загружается процессор из-за необходимости создавать и сверять cookie. Так как альтернативным решением является отклонять все запросы на соединение, SYN cookies являются хорошим выбором.
Также нужно увеличить очередь полуоткрытых соединений — tcp_max_syn_backlog(в Debian Lenny по-умолчанию 1024 соединения):
Код:
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
1024
Код:
echo "20000" > /proc/sys/net/ipv4/tcp_max_syn_backlog
Целочисленное значение (1 байт) tcp_synack_retries определяет число попыток повтора передачи пакетов SYNACK для пассивных соединений TCP. Число попыток не должно превышать 255. Используемое по умолчанию значение 5 соответствует приблизительно 180 секундам на выполнение попыток организации соединения.
Код:
cat /proc/sys/net/ipv4/tcp_synack_retries
5
Код:
echo "1" > /proc/sys/net/ipv4/tcp_synack_retries
Целое число в файле tcp_fin_timeout определяет время сохранения сокета в состоянии FIN-WAIT-2 после его закрытия локальной стороной. Партнер может не закрыть это соединение никогда, поэтому следует закрыть его по своей инициативе по истечении тайм-аута. По умолчанию тайм-аут составляет 60 секунд. В ядрах серии 2.2 обычно использовалось значение 180 секунд и вы можете сохранить это значение, но не следует забывать, что на загруженных WEB-серверах вы рискуете израсходовать много памяти на сохранение полуразорванных мертвых соединений. Сокеты в состоянии FIN-WAIT-2 менее опасны, нежели FIN-WAIT-1, поскольку поглощают не более 1,5 Кбайт памяти, но они могут существовать дольше.
Код:
cat /proc/sys/net/ipv4/tcp_fin_timeout
60
Код:
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
Целочисленная переменная tcp_keepalive_probes задает число передач проб keepalive, после которого соединение считается разорванным. По умолчанию передается 9 проб.
Код:
cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
Код:
echo "5" > /proc/sys/net/ipv4/tcp_keepalive_probes
Целочисленная переменная tcp_keepalive_intvl определяет интервал передачи проб. Произведение tcp_keepalive_probes * tcp_keepalive_intvl определяет время, по истечении которого соединение будет разорвано при отсутствии откликов. По умолчанию установлен интервал 75 секунд, т.е., время разрыва соединения при отсутствии откликов составит приблизительно 11 минут.
Код:
cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
Код:
echo "15" > /proc/sys/net/ipv4/tcp_keepalive_intvl
Здесь указывается максимальное количество пакетов в очередь на обработку если интерфейс получает пакеты быстрее, чем ядро может их обработать.
Код:
cat /proc/sys/net/core/netdev_max_backlog
1000
Код:
echo "20000" > /proc/sys/net/core/netdev_max_backlog
Максимальное число открытых сокетов, ждущих соединения.
Код:
cat /proc/sys/net/core/somaxconn
1024
Код:
echo "20000" > /proc/sys/net/core/somaxconn
Код:
echo "20000" > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo "1" > /proc/sys/net/ipv4/tcp_synack_retries
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "5" > /proc/sys/net/ipv4/tcp_keepalive_probes
echo "15" > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo "20000" > /proc/sys/net/core/netdev_max_backlog
echo "20000" > /proc/sys/net/core/somaxconn
Код:
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 500/s --limit-burst 1500 -j RETURN
iptables -A syn_flood -j DROP
Более наглядно этот критерий можно представить себе как некоторую емкость с выпускным отверстием, через которое проходит определенное число пакетов за единицу времени (т.е. скорость «вытекания»). Скорость «вытекания» как раз и определяет величина --limit. Величина --limit-burst задает общий «объем емкости». А теперь представим себе правило --limit 3/minute --limit-burst 5, тогда после поступления 5 пакетов (за очень короткий промежуток времени), емкость «наполнится» и каждый последующий пакет будет вызывать «переполнение» емкости, т.е. «срабатывание» критерия. Через 20 секунд «уровень» в емкости будет понижен (в соответствии с величиной --limit), таким образом она готова будет принять еще один пакет, не вызывая «переполнения» емкости, т.е. срабатывания критерия.
https://rusua.org.ua/2013/01/07/411/