====== Защищаем ssh от брутфорса средствами pf ====== # создаём таблицу table persist # пропускаем проверку на петле set skip on lo0 # для отброшенных пакетов TCP отсылается пакет TCP RST set block-policy return # для прочих ICMP Unreachable ### если DOSят то можно указать "drop" ### set block-policy drop #пакет молча отбрасывается #собираем все части пакета перед отправкой scrub in all #запретим все отовсюду block all #блокируем тех кто попал в sshblock block in log quick from # пропускаем на ssh из внутренней подсети, а злодеев заносим в таблицу pass in on $int_if proto tcp from $int_if:network to $int_if port ssh \ synproxy state (max-src-conn-rate 2/60, overload flush global) # пропускаем на ssh из вешней подсети, и тоже заносим злодеев в таблицу pass in on $ext_if proto tcp from any to $ext_if port ssh \ synproxy state (max-src-conn-rate 2/60, overload flush global) # разрешаем всё из локальной сети pass in on $int_if from any to any # разрешаем серверу доступ в интернет pass out on $ext_if from $ext_if to any # разрешаем ping pass in inet proto icmp all icmp-type echoreq Посмотреть тех кто в таблице можно так: pfctl -t sshblock -T show Удалить ip адрес (например 192.168.1.9), из таблицы можно так: pfctl -t sshblock -T delete 192.168.1.9 осталось настроить cron crontab -e 30 * * * * root /sbin/pfctl -t sshblock -T expire 86400 Каждые час (в 30 минут) **-T expire 86400** удаляет все записи из таблицы старше 86400 секунд (сутки) **max number** Ограничение максимального количества записей в таблице состояний, которое может сделать данное правило. По достижении этого предела, будет отброшен любой пакет, который должен был бы завести новую запись в таблице состояний. Пакеты будут отбрасываться до тех пор, пока число записей в таблице состояний не уменьшится. **source-track** Эта опция даёт возможность отслеживать количество записей в таблице состояний в пересчёте на каждый адрес источника. Возможные форматы опции: **source-track rule** — Максимальное количество записей в таблице состояний созданных данным правилом ограничивается опциями **max-src-nodes** и **max-src-states**, заданными в этом правиле. Счётчики заводятся не глобальные, а локальные. **source-track global** — То же что и в предыдущем слуаче, но счётчики ведутся глобально. При этом каждое правило может иметь свои пределы **max-src-nodes** и **max-src-states**, однако счётчики будут общими для всех правил. Общее количество адресов источников, для которых осуществляется глобальный контроль количества строк в таблице состояний, ограничивается при помощи опции **src-nodes**. **max-src-nodes number** При использовании опции source-track опция max-src-nodes ограничивает количество IP-адресов с которых можно одновременно открыть соединения. **max-src-states number** При использовании опции **source-track** опция **max-src-states** ограничивает количество соединений с одного IP-адреса. **max-src-conn number** Ограничение максимального количества TCP соединений прошедших тройное рукопожатие, которые можно открыть с одного IP-адреса. **max-src-conn-rate number / interval** Ограничение скорости с которой можно открывать новые соединения. Задаётся количество соединений за интервал времени. Обе опции автоматически включают опцию **state-track rule** и не совместимы с **state-track global**. В комбинации с данными опциями можно употреблять более агрессивные опции, для «наказания» «провинившихся». **overload** При превышении лимитов занести адрес источника в таблицу. **flash [global]** Уничтожить все записи в таблице состояний соответствующие соединениям с данного IP-адреса. При указании опции **global** записи в таблице состояний сбрасываются независимо от того, какое правило её создало. ====== Дополнительно то же самое ====== **Brute force** — это самый грубый и легко уловимый в файлах журналов (в log-ах) метод проникновения на сервер, использующий перебор возможных паролей. В некоторых случаях это может сработать, так как многие используют простые легко запоминаемые пароли (состоящие, к примеру, только из цифр, непосредственно связанных с человеком). Автоматический подбор паролей ведет к заполнению логов множеством записей о попытках авторизации к сервису, прослушиваемый порт которого доступен для мира. Уже с этого можно сделать вывод, что желательно менять стандартный открытый порт демона на любой другой (лучше, в диапазоне 1024-65536, которые являются непривилегированными) для таких служб, к примеру, как SSH и ограничивать подключения с определенных IP-адресов, если есть такая возможность. Для борьбы с brute force-атаками полезными будут знания специфики «тройного рукопожатия» при установке TCP-соединения. Это передача трех пакетов, которые инициализируют и устанавливают соединение. Первый пакет приходит с установленным флагом SYN, в ответ на который передается SYN/ACK пакет и для него, в свою очередь, приходит подтверждение ACK. После этого по открытому/установленному соединению передаются данные. С помощью возможностей механизма «проверки состояния соединений» сетевым фильтром открывается много гибких возможностей для контроля сессий. PF (packet filter) хранит информацию о каждом соединении в таблице состояний. После установки соединения последующие пакеты, относящиеся к нему, независимо от направления прохождения, не будут заново проверяться имеющимися правилами пакетного фильтра, что улучшает производительность брандмауэра. При просмотре имеющихся правил: pfctl -sr можно увидеть в конце опцию «keep state», если фильтрующее правило создает state-запись, когда пакет соответствует правилу. Эта опция включена по умолчанию. Правила nat, binat, и rdr тоже создают записи в таблице состояний, которые хранятся до тех пор, пока фильтрующие правила их пропускают. Правила NAT и RDR срабатывают до правил фильтрации. Полезными в правилах опциями таблицы состояний могут быть: **max number** – максимальное количество соединений для данного правила, которое применяется пока не достигнут максимум; **no state** – не создавать записи в таблице состояний; **source-track [rule|global]** – для отслеживания кол-ва соединений, созданных IP адресом, применяется к одному правилу или всем, где эта опция упоминается. Каждое правило может указать разные **max-src-nodes** и **max-src-states** опции, которые соответственно ограничивает количество исходных IP адресов, одновременно создающих соединения, и одновременно созданных соединений с одного исходного IP адреса. Для уже установившихся соединений: **max-src-conn number** – максимальное количество одновременно существующих соединений с одного IP; **max-src-conn-rate number / interval** – количество новых соединений, которые можно открывать за указанный интервал времени; **overload ** – помещение в данную таблицу IP-адреса нарушителей; **flush [global]** – уничтожить все соединения, которые были созданы этим исходным IP адресом, а с опцией « global» для всех правил, где с этого IP-адреса создавалось соединение. Поскольку при brute force происходит постоянное переподключение к открытому порту, то можно лишить смысла такие атаки, установив разумные лимиты количества соединений за определенный промежуток времени. В этом будет крайне полезна опция **max-src-conn-rate**, которая и задает эти настройки. Также, дополнительно, будут не лишними опции **overload** и **flush**. В /etc/pf.conf следует добавить в нужные места следующие правила: # динамический список с IP-адресами нарушителей: table persist # правило для блокирования подключений с этих IP-адресов: block drop in quick on $ext_if from # собственно правило, которое будет заполнять список недоброжелателей, #т.е. тех, кто превысил лимит подключений, больше трех за 60секунд к сервису SSH, #с сбросом существующих соединений, инициированных данным IP-адресом: pass in quick on $ext_if proto tcp from any to ($ext_if) port 22 \ flags S/SA keep state (max-src-conn-rate 3/60, overload flush global) Для проверки правил: pfctl -nf /etc/pf.conf а потом для их применения: pfctl -f /etc/pf.conf Посмотреть содержимое любой таблицы можно так: /sbin/pfctl -t ssh-bruteforce -T show Для удаления определенного IP-адреса: /sbin/pfctl -t ssh-bruteforce -T delete IP Для полной очистки таблицы: /sbin/pfctl -t ssh-bruteforce -T flush Если нет желания блокировать IP-адреса в таблице **ssh-bruteforce** до следующей перезагрузки сервера, то ее можно очищать вручную с помощью посторонних утилит (security/expiretable) либо средствами самого PF (pfctl). Критерием удаления записей в таблице служит время, прошедшее после их занесения в нее. Для автоматического очищения таблицы от записей «старше» двух часов каждый час нужно добавить в задачи пользователя root следующую строку (crontab -e): * */1 * * * /usr/local/sbin/expiretable -t 7200 ssh-bruteforce или же * */1 * * * /sbin/pfctl -t ssh-bruteforce -T expire 7200