Замедление bruteforce атак на SSH с помощью PF


GreenX: Продолжив поиск статей по борьбе с bruteforce атаками на ssh с помощью PF - набрел на блог Thomas ?ksnes и его статью на эту тему. Основа, таже как и в прошлом переводе - max-src-conn-rate, но есть другие полезные мысли. Перевожу ее для Вас.

После небольшой беседы с Claudio о путях борьбы с brute force атаками на SSH, Я был вдохновлен на провеление собственого эксперимента. Есть уже достаточно руководств о том как замедлять их или даже автоматически вносить адреса в церный список, но нет никаких реальных цифр, о том насколько это эффективно. Я установил такие требования для этих правил PF:
Не блокировать нормальные соединения
Ни чего не блокировать на совсем

Тестовая система FreeBSD 6.0-STABLE. Заметьте, что некоторые возможности используемые в этих правилах доступны только с версии PF 3.7 и старше (FreeBSD 6.x синхронизированно с 3.7). Также я использую expiretable для автоматического очищения таблиц файрвола от старых записей. Я нашел этот ruby скрипт для bruteforce атак. Он однопоточный, часто ошибается или подвисает при не идеальных условиях, но это лучше чем ничего.

Я не планирую детально объяснять мои правила - это не руководство пользователя по PF, но если что не понятно - пишите.
LANIF = "em0"
LOIF = "lo0"
set block-policy drop
pass out all keep state
block in all
pass on $LOIF all
pass on $LANIF inet proto tcp from any to $LANIF port ssh keep state

Смысл: разрешить всё исходящее и блокировать всё входящее, за исключением SSH.

В sshd_conf, кроме 'UseDNS' со значением 'no', остальные параметры стоят "по умолчанию". Подчеркну, что использую 'AllowUsers' для ограничения доступа. Я видел людей подвергающих риску свои машины, временно создав пользователя backup, они забыли в последствии его удалить.

Теперь посмотрим, как быстро работает этот скрипт на гигабитном соединении.
time ./ssh-rbrute.rb -h edea -u root -l passwords.txt -p 22

real 0m29.602s
user 0m5.091s
sys 0m3.229s

real 0m29.469s
user 0m4.973s
sys 0m3.188s

OK, запомнили. Я проверил - в лог файле добавиль 100 записей о попытках войти в систему. Начинаем душить!
LANIF = "em0"
LOIF = "lo0"
set block-policy drop
pass out all keep state
block in all
pass on $LOIF all
pass on $LANIF inet proto tcp from any to $LANIF port ssh keep state
(max-src-conn 10, max-src-conn-rate 5/60)

Смысл: разрешить максимум 10 одновременных соединений и не более 5 за 60 секунд.

Эффект ощутим.
real 8m58.501s
user 0m5.203s
sys 0m2.784s

С 30 секунд до 9 минут - "нормальная добавка к пенсии", но может быть лучше. А что, если люди атакующие меня, начнут терять огромное количество пакетов?
LANIF = "em0"
LOIF = "lo0"
set block-policy drop
pass out all keep state
block in all
pass on $LOIF all
pass on $LANIF inet proto tcp from any to $LANIF port ssh keep state
(max-src-conn 10, max-src-conn-rate 5/60, overload <hammering> flush)
block on $LANIF inet proto tcp from <hammering> to $LANIF port ssh
probability 65%

Смысл: Фильтр помещая соединения в таблицу <hammering> отбрасывает 65% пакетов соответствующих этой таблице.

Теперь, я должен сказать вам правду. Скрипт ни разу не закончил все 100 попыток входа в систему. Он "сломался" (failed/stalled?) каждый раз выдавая 'connection timeout'. Однако, после нескольких перезапусков, он сумел примерно 50 раз попытаться войти в систему.
real 9m55.291s
user 0m2.214s
sys 0m1.219s

Почти 10 минут на 50 попыток входа. Можно подумать, что они использовали Ethernet на голубиной почте в сезон охоты! Но есть еще прихолы, которые можно сделать при помощи PF. Я хочу подделать результаты возвращаемые Nmap при сканировании. Например сделать перенаправление всех портов на 22 порт нашего компа для нежелательных соединений:
LANIF = "em0"
LOIF = "lo0"
set block-policy drop
rdr pass on $LANIF proto tcp from any os NMAP to any port 1:65535 -> $LOIF port 22
pass out all keep state
block in all
pass on $LOIF all
pass on $LANIF inet proto tcp from any to $LANIF port ssh keep state
(max-src-conn 10, max-src-conn-rate 5/60, overload <hammering> flush)
block on $LANIF inet proto tcp from <hammering> to $LANIF port ssh
probability 65%

Смысл: Послать соединения из источника на котором определилась ОС Nmap на 22 порт нашей машины.

Теперь мы имеем очень плохой файрвол. Вот пример того, что выдает Nmap.
%sudo nmap -sS 10.0.0.4 -O -p 100-110

Warning: OS detection will be MUCH less reliable because we did not find at least 1 open and 1 closed TCP port
Insufficient responses for TCP sequencing (0), OS detection may be less accurate
Interesting ports on 10.0.0.4:
PORT STATE SERVICE
100/tcp open newacct
101/tcp open hostname
102/tcp open iso-tsap
103/tcp open gppitnp
104/tcp open acr-nema
105/tcp open csnet-ns
106/tcp open pop3pw
107/tcp open rtelnet
108/tcp open snagas
109/tcp open pop2
110/tcp open pop3
MAC Address: 00:0E:0C:84:82:17 (Intel)
Too many fingerprints match this host to give specific OS details

Всё выглядит открытым, но при подключении в ручную - каждый порт закрыт. Кто сказал что файрволить не прикольно?

http://wiki.bsdportal.ru/doc:grblocksshbruteforce

Обновлено: 12.03.2015