Port knocking или как обезопасить себя от брута по ssh

Речь пойдет о борьбе с надоедливыми брутфорсами и сканерами портов, которые всячески норовят получить доступ к серверу. В статье будет рассказано о технологии Port Knocking, позволяющей обезопасить доступ на сервер посредством скрытия портов.



Немного о самой технологии


В технологии Port Knocking есть интересная особенность. Она применяет несколько попыток подключения к закрытым портам. Вы спросите: «А зачем это нужно?» Давайте представим себе, что вы пришли на собеседование в какую-то организацию с пропускным режимом. Сначала вы попадаете на (1)пост охраны, где на вас выписывают пропуск, затем (2)вы попадаете в отдел кадров, где заполняете анкету и с вами беседуют, и в конечном итоге (3)вы попадаете в кабинет управляющего, который проводит завершающую беседу и принимает решение. А теперь давайте представим, что бы случилось, если бы все желающие напрямую шли к управляющему?

Технология Port Knocking осуществляет последовательность попыток подключения к закрытым портам. Даже не смотря на то, что все порты закрыты, вы можете отследить все попытки подключения в лог-файлах файрвола. Сервер, чаще всего, никак не отвечает на эти подключения, но он считывает и обрабатывает их. Но если же серия подключений была заранее обозначена пользователем, то выполнится определенное действие. Как пример, подключение к SSH-сервису на порту 22. Port Knocking позволяет осуществлять не только данное действие. триггер позволяет выполнять и другие действия (скажем, отключение питания, перезагрузку системы и т.д.).

Установка на FreeBSD


На удаленной машине мы имеем FreeBSD 9.1
Port Knocking состоит из двух программ:
— сервер (knockd)
— клиент (knock)

Я приведу пример настройки серверной части.
# cd /usr/ports/
# make search key=knocking
Port:	doorman-0.81_1
Path:	/usr/ports/security/doorman
Info:	Port knocking implementation, both daemon and client
Maint:	lupe@lupe-christoph.de
B-deps:	lsof-4.88.d,8
R-deps:	lsof-4.88.d,8
WWW:	http://doorman.sourceforge.net/

Port:	knock-0.5_1,1
Path:	/usr/ports/security/knock
Info:	Flexible port-knocking server and client
Maint:	sbz@FreeBSD.org
B-deps:	
R-deps:	
WWW:	http://www.zeroflux.org/projects/knock


Переходим в директорию с портом и конфигурируем.
cd /usr/ports/security/knock
make config


Ставим маркер на серверной части, а затем собираем и устанавливаем пакет.

Конфигурация


Теперь давайте займемся непосредственно настройкой.
Для начала скопируем конфиг.
# cd /usr/local/etc/
# cp knockd.conf.sample knockd.conf

В сети много вариаций настройки конфига, я приведу свой.
knockd.conf
[options]
        logfile = /var/log/knockd.log
        interface = em0

[opencloseSSH]
        sequence      = 7000:udp,7007:tcp,7777:udp
        seq_timeout   = 5
        tcpflags      = syn
        start_command = /sbin/pfctl -t good_hosts -T add %IP%
        cmd_timeout   = 10
        stop_command  = /sbin/pfctl -t good_hosts -T delete %IP%


[open22]
        sequence    = 7134:tcp,7675:tcp,7253:udp
        seq_timeout = 5
        tcpflags    = syn

        command     = /sbin/pfctl -t good_hosts -T add %IP%

[close22]
        sequence    = 7253:udp,7675:tcp,7134:tcp
        seq_timeout = 5
        tcpflags    = syn
        command     = /sbin/pfctl -t good_hosts -T delete %IP%


Сохраняем конфиг, добавляем в автозапуск и стартуем сервис.
# cd /usr/local/etc/rc.d/
# echo knockd_enable=\"YES\" >> /etc/rc.conf
# service knockd start


Настройка Firewall


Для начала включим поддержку Firewall, если она у вас отключена (как было в моем случае)
echo pf=\"YES\" >> /etc/rc.conf

Не советую делать данную процедуру удаленно, так как блокируются все подключения и доступа по ssh мы не получим.
Примечание: Если же вы не послушались и сделали данное действие удаленно, то проблему можно решить посредством включения root-логина в sshhd-config.

/etc/pf.conf
ext_if="rl0"

table <good_hosts> persist

block in on $ext_if all
pass in on $ext_if inet proto tcp from <good_hosts> \
 to $ext_if port 22 keep state



Вносим правила в настройки Firewall`a
/sbin/ipfw add 100 allow tcp from %IP% to me 22 keep-state
/sbin/ipfw delete 100


Перезагружаемся.

Стучимся


Для подключения я пользовался сторонним клиентом под MacOS — hping.
# knock -v *e*m*o*c*.ru 7000:udp,7007:tcp,7777:udp
hitting udp *1.*0*.*3*.*0:7000
hitting tcp *1.*0*.*3*.*0:7007
hitting udp *1.*0*.*3*.*0:7777
# ssh *e*m*o*c*.ru -l root
Password:
Last login: Thu May  9 11:30:40 2013 from *****
FreeBSD 9.1-RELEASE-p3 (GENERIC) #0: Mon Apr 29 18:11:52 UTC 2013
root@*e*m*o*c*:/root # 

Метки:
Поделиться публикацией
Похожие публикации
Комментарии 53
  • +17
    ИМХО, лучше воспользоваться fail2ban.
    • 0
      К счастью, я с Вами соглашусь. Поскольку при настройке кнокинга возникло очень много трудностей, с которыми я боролся всю неделю.
      fail2ban удобен тем, что прост в настройке, но он не полностью предотвращает попытки подключения. Да и порт остается открытым.
      • +12
        В случае SSH сильно помогает смена порта ssh-сервера сразу при первоначальной настройке на что-то отличное от 22
        • 0
          Согласен! Была идея, но я решил пойти окольными путями настроив кнокинг и сделав подключение по RSA-ключу. В ближайшем будущем планирую переделать все, как только приобрету резервный сервер. Камни подводные всегда попадаются, на них и учимся.
          • 0
            Добавлю что смена порта на значение большее 1024 — плохая идея. Порты от 1024-го и выше может слушать программа, запущенная любым пользователем, а не только root-ом. А значит злоумышленник, имеющий доступ к вашему серверу, сможет запустить программу, имитирующую ssh-сервер и собирающую пароли.
            • 0
              А ECDSA-ключ она тоже без рутовых прав прочитает?
              • 0
                Ключ не прочитает, вы правы, но ведь предупреждение о смене ключа можно ненароком и не заметить. Короче говоря, лучше перестраховаться.
                • 0
                  Как можно не заметить необходимость вручную вбить в консоль ssh-keygen -R?
                  • –1
                    Можно на автомате в ответ на «Are you sure you want to continue connecting (yes/no)?» написать «yes» и отдать свой пароль.
                    • +1
                      Оно такую надпись выдаёт только при самом первом подключении. И да, тут должна быть простыня текста о полезности авторизации по ключам, но мне лень её писать.
                      • 0
                        Да, я понимаю, что вероятность попасться на такую уловку очень мала. Но когда речь идёт о безопасности, то по-моему лучше устранить даже такую маленькую угрозу. Особенно учитывая то, что для этого надо всего лишь правильно выбрать число.
              • 0
                Для того, чтобы слушать порт, нужно сначала его освободить.

                А смена порта на значение <=1024 идея не плохая, но по-моему бесполезная. Все сканеры сканируют этот диапазон в первую очередь, так что это будет шило на мыло.
                • НЛО прилетело и опубликовало эту надпись здесь
                  • 0
                    С другой стороны, порты выше 1024 и сканируют реже :-)
                    • +1
                      У меня вообще была идея перевести SSH на ipv6-only. Вот там точно задолбуться подбирать комбинации.
                      • 0
                        Почему?
                        • 0
                          Потому что IPv6-адресов намного больше, чем IPv4, поэтому, чтобы «тупо перебрать все IP-адреса» нужно будет потратить намного больше времени :)
                          • 0
                            Спасибо, думал может есть какая то другая причина. В целом IP сканят не только перебором, но и вытаскивают из открытых источников.
                  • +1
                    Он конечно открытый остается, но перебор все-равно не возможен ибо будет оооочень долго.
                  • +6
                    ИМХО, для SSH-сервисов, доступных извне, безопасней всего будет использовать ключи и полностью запретить доступ через ввод пароля. Ибо блокировка по IP спасает только от «тупого» bruteforce, но не от того bruteforce, который распространен в интернете сейчас, когда с кучи разных IP-адресов ломятся и перебирают все возможные пароли.
                    • 0
                      А еще лучше если все вместе. Я оставил авторизацию только по ключам и доступ только со своих ип.
                      • +5
                        Тогда вы не сможете зайти на свой сервер, если смените провайдера или придется пользоваться мобильным интернетом :). На самом деле даже вариант с ключами плох тем, что нужно их бэкапить, иначе зайти на сервер не удастся без KVM…
                        • +1
                          достаточно сделать на сервере файл text.txt и по его загрузке добавлять правило в таблицу ipfw, разрешающее доступ скачавшему этот файл.
                          • 0
                            Совершенно верно, если ип сменился то добавить новый ип в список поможет мобильный который имеет статичный ип.
                            Так же на черный день в списках разрешенных один из тестовых серверов.
                          • 0
                            К сожалению по IP не могу сделать, так как частенько езжу в командировки и приходится заходить либо с планшета, либо с гостиничного WiFi. Поэтому и решено было настроить кнокинг + от CloudFlare подключение к ssh через поддомен.
                        • +1
                          Так же альтернатива: denyhosts
                          • +1
                            А я порекомендую sshguard. Он мониторит много всего, не только ssh, как отражено в названии.
                          • +3
                            Port knocking помимо защиты от брутфорса позволяет защититься от удалённых атак на сервера. Например, вот от таких:
                            0day Linux/CentOS SSHd Spam Exploit — libkeyutils.so.1.9
                            Т.к. в случае использования Port knocking зловредные пакеты от злоумышленника даже не дойдут до уязвимого сервиса

                            Так что не стоит пренебрегать этой технологией
                          • +1
                            fail2ban из коробки справляется, а тут еще настраивать надо и махаться со входом… стоит ли игра свеч?
                            • 0
                              Картинка с Шелдоном клевая. Откуда взял?
                            • +2
                              Я использую ipset + kippo. Если система видит, что кто-то неправильно ввел пароль, то IP добавляется в ipset и iptables перенаправляет его на kippo, который порой пишет презабавнейшие логи активности «хакеров».
                              • 0
                                Отличная штука. Спасибо за наводку. Не могу плюсануть пока.
                                • +1
                                  Посмотрел на youtube активность «хакеров», из логов kippo. На самом деле забавно. Давно так не смеялся. Особенно этот был подарком. А в конце в связи с ребутом вообще чуть не упал со смеху. Спасибо еще раз. Надо себе поставить. Юмор на каждый день, надеюсь, будет обеспечен.
                                  • 0
                                    От себя добавлю, что стоит заменить заново сгенерированные private.key и public.key на такие же, как в системе (при условии, что не используется ECDSA).
                                    У меня ключики скопированы в %kippodir%/ssh_keys и соответственно:
                                    private.key -> ssh_keys/ssh_host_rsa_key
                                    public.key -> ssh_keys/ssh_host_rsa_key.pub

                                    При таком хаке абсолютно не палится факт смены фингерпринта ssh, т.е. со стороны клиента не виден факт подмены оригинального ssh-сервера на фейковый.
                                  • 0
                                    кстати нужно заметить, что на тсп порты можно отправлять «запрос» через telnet, что иногда очень удобно

                                    и knockd можно использовать для построяения интересных схем
                                    к примеру, когда на рабочий тазик приходит сообщение в жаббер, а на домашнем «пикает» :)
                                    (один тазик отправляет запрос домашнему через кнокд, на домашнем срабатывает mplayer)

                                    сколько фантазии хватит…
                                    • +2
                                      Если честно в топике писалось про юникс системы, фрибсд юникс без сомнений, но:
                                      1) у них разные системы авторизации (в частности в линухах есть модуль пам pam_fail_delay, который вводит задержку после неудачного ввода пароля и скаждой неудачной увеличивается время задержки)
                                      2) на моей практике обычно пользуют один фаерфол, или Packet Filter (PF) или IPFIREWALL (IPFW)
                                      3) если взять юниксы в целом, то можно закрыть пароли и пускать только по ключу, если нет флешки(или хотябы мобилки с памятью на борту) не беда, ключи от ssh можно шифрануть (неважно чем, хоть винраром) и использовать почту допустим для хранения, естесственно с мерами безопасности и консперацией + при генерации ключа часть ключа можно вводить с клавы для более высокой стерени паранои.

                                      • 0
                                        Если вы не возражаете, я бы хотел указать на источник картинки, которую вы использовали: knock knock knock penny, by sandara.
                                          • 0
                                            tls?
                                            rsa?
                                            trigger-port?
                                            ossec?
                                            • 0
                                              Позвольте поинтересоваться.
                                              А пароля на 16+ символов и таймаута разве недостаточно? Это реально сбрутфорсить, перебрать?
                                              • +1
                                                Это вроде нет, но переполнить раздел с логами вроде да.
                                              • 0
                                                Добавлю от себя. Обычно мне лениво делать стуки для удаления правила для доступа к сервису. Да и к сервисам этим часто по port knocking ещё люди из отдела стучатся. За всеми не уследить: кто-то был в командировке, кто-то ещё откуда-то. В итоге в списке iptables (т.к. я про Linux сейчас говорю) накапливается куча ненужного хлама. По этой причине я делаю так: в кроне каждую ночь в 4 утра восстанавливаю правила iptables скриптом, в котором прописано:
                                                iptables-restore < /etc/firewall.conf


                                                Соответственно, предварительно эти правила должны быть сохранены в файле:

                                                iptables-save >/etc/firewall.conf
                                                • +2
                                                  Очень не советую использовать механизмы блокировки, основанные на анализе логов. Логи могут почему-то перестать писаться, или вдруг чуть изменить формат. Это происходит в самый неподходящий момент. Например: пришла атака, логи приложений резко выросли, партиция переполнилась, логи сломались, нокинг сломался. И вам повезло, если он просто выключился, и пускает всех. А вот если он не пускает никого до следующего логротейта, а сервера в Европе, тамошняя поддержка спит, ребут не помогает (не чистит партицию)… Не ходите по этим граблям.

                                                  В iptables уже давно существует прекрасный модуль recent, который позволяет отслеживать историю подключений с определённого IP и делать тот же самый порт нокинг.
                                                  • +2
                                                    вот кусок кода который делает всё то же самое что knockd

                                                    iptables -N ssh
                                                    iptables -A ssh -m recent --name ssh_conn --set -j LOG --log-prefix "SSH INN "
                                                    iptables -A ssh -m recent --rcheck --name admins --seconds 60 -j ACCEPT
                                                    iptables -A ssh -m recent -p tcp --update --seconds 600 --hitcount 2 --name ssh_conn -j REJECT --reject-with tcp-reset
                                                    iptables -A ssh -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 22  -j ssh
                                                    
                                                    iptables -A INPUT -p tcp --dport 54321 -m recent --name adm1 --set
                                                    iptables -A INPUT -p tcp --dport 34512 -m recent --rcheck --name adm1 --seconds 200 -j adm1
                                                    iptables -A INPUT -p tcp --dport 24513 -m recent --rcheck --name adm2 --seconds 200 -j adm2
                                                    iptables -A INPUT -p tcp --dport 16438 -m recent --rcheck --name adm3 --seconds 200 -j adm3
                                                    iptables -A INPUT -m recent --rcheck --name adm4 --seconds 600 -j ACCEPT
                                                    


                                                    При стуке по портам по очереди 54321, 34512, 24513, 16438 ip c которого произошел «стук» попадает в список админов на 10 минут, а при попытке авторизации по ssh, если авторизация была неудачная, «падает» в бан на 10 минут.
                                                    • 0
                                                      Забыл вставить, должно идти между двумя фрагментами предыдущими.

                                                      iptables -N adm1
                                                      iptables -A adm1 -m recent --name adm2 --set
                                                      iptables -N adm2
                                                      iptables -A adm2 -m recent --name adm3 --set
                                                      iptables -N adm3
                                                      iptables -A adm3 -m recent --name adm4 --set
                                                      
                                                      • 0
                                                        Хотя на *BSD можно попробовать аналагично сделать через ipfw.
                                                      • 0
                                                        К сожалению iptables под линь-ядра, а у меня семейство BSD. Но вариант интересный — спасибо за наводку. В свободное время попробую пошаманить.
                                                      • 0
                                                        Почему просто не закрыть вход по паролю и сгенерить ключ?
                                                        • 0
                                                          Потому что была идея именно скрыть порт от чужих глаз, но оставить его доступным для себя.
                                                        • –2
                                                          Очень и очень старый вариант «обезопасинвания».
                                                          Очень плохой и очень религиозно-неверный.
                                                          • +1
                                                            Каждый защищает себя по своему, я привел лишь один из вариантов. Если почитать комментарии выше, то можно встретить и другие варианты.
                                                          • 0
                                                            на фре прекрасно себя чувствует bruteblock и sshit

                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.