Системный администратор
0,0
рейтинг
10 мая 2013 в 15:41

Разработка → 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 # 

Роман @YangAngel
карма
8,0
рейтинг 0,0
Системный администратор
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (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
    Картинка с Шелдоном клевая. Откуда взял?
    • +1
      Взял с deviantart.com
  • +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

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