6
декабря
3

Защита от brute force или ограничение соединений с помощью PF во FreeBSD



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 <table> – помещение в данную таблицу IP-адреса нарушителей;
flush [global] – уничтожить все соединения, которые были созданы этим исходным IP адресом, а с опцией « global» для всех правил, где с этого IP-адреса создавалось соединение.

Поскольку при brute force происходит постоянное переподключение к открытому порту, то можно лишить смысла такие атаки, установив разумные лимиты количества соединений за определенный промежуток времени. В этом будет крайне полезна опция max-src-conn-rate, которая и задает эти настройки. Также, дополнительно, будут не лишними опции overload и flush.

В /etc/pf.conf следует добавить в нужные места следующие правила:

# динамический список с IP-адресами нарушителей:
table <ssh-bruteforce> persist
# правило для блокирования подключений с этих IP-адресов:
block drop in quick on $ext_if from <ssh-bruteforce>
# собственно правило, которое будет заполнять список недоброжелателей,
#т.е. тех, кто превысил лимит подключений, больше трех за 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 <ssh-bruteforce> 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 
Понравилась статья?
Подписаться на RSS feed
3 комментария:
  1. AK 26 мая, 2011

    А вот у меня при добавлении flash global пф ругается на синтаксис 🙁

  2. admin 30 мая, 2011

    В блоке кода с правилами файервола неправильно отображались угловые скобки , в которые заключено название таблицы (сейчас исправлено). Видимо, проблема с воссприятием синтаксиса правил в этом. Если дело в другом и команда pfctl -nf /etc/pf.conf по прежнему выдает ошибку синтаксиса, то привидите, пожалуйста, ошибочную строку правила.

  3. ttys 26 июля, 2011

    дабы не засирать лог сообщениями от крона у меня сделано так:
    /sbin/pfctl -t sshblock -T expire 86400 > /dev/null 2>&1

Оставить комментарий