Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> программы —> knockd

Port knocking

Автор: fr33man.


Недавно поставил FreeBSD в качестве роутера и получил внешний ip у провайдера. И все было вроде бы хорошо, но через пару дней в логах стали появляться попытки перебора пароля к ssh серверу. Сначала я стал блокировать атакующих через
firewall, но это не помогало... Было ощущение, что на меня ополчился весь интернет. :)) Решение напрашивалось само сабой — закрыть доступ к ssh из вне… но я пошел другим путем. Я помнил об одной технологии, которая могла мне
помочь — port knocking.

Немного теории.

Технология port knocking позволяет выполнять любые действия на сервере, даже если все порты на нем закрыты. В общем случае, Вам достаточно соедениться с определенными портами, в определенной последовательности, которую знаете только Вы и на сервере выполнятся действия, описанные Вами. Port knocking подразумевает наличие сервера и клиента. Сервер определяет все попытки соединения и если он обнаружил некую последовательность подключений, заданную Вами, то на сервере выполнятся некоторые действия, обычно это добавление правила в firewall. Клиент же должен подключиться к определенным портам и протоколам в заданной последовательности. Теперь перейдем от теории к практике.

Какой софт использовать?

Итак, первым делом посмотрим, что есть в портах:
router# cd /usr/ports/
router# make search key=knocking
Port:   doorman-0.81_1
Path:   /usr/ports/security/doorman
Info:   A Port Knocking implementation, both daemon and client
Maint:  lupe@lupe-christoph.de
B-deps: lsof-4.77
R-deps: lsof-4.77
WWW:    http://doorman.sourceforge.net/

Port:   knock-0.5.20051124
Path:   /usr/ports/security/knock
Info:   A flexible port-knocking server and client
Maint:  shaun@FreeBSD.org
B-deps:
R-deps:
WWW:    http://www.zeroflux.org/cgi-bin/cvstrac/knock/wiki/

router#

Вот две программки, которые мне удалось найти. Не знаю почему, но я рещил установить вторую. ;). В состав порта knock входят две программы:
-    сервер (knockd)
-    клиент (knock)
Поэтому я сначала опишу настройку сервера, а потом клиента.

Настройка knockd сервера.

router# cd /usr/ports/security/knock

Конфигурируем порт.
router# make config
---------------------------------------------------------------------¬
¦                  Options for knock 0.5.20051124                    ¦
¦ -----------------------------------------------------------------¬ ¦
¦ ¦               [X] SERVER  Install knockd server                ¦ ¦
¦ ¦               [ ] CLIENT  Install knock client                 ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
+-L------------------------------------------------------------------+
¦                       [  OK  ]       Cancel                        ¦
L---------------------------------------------------------------------

Собираем и устанавливаем knockd.
router# make install clean

В данном случае я устанавливаю только сервер.

Теперь нужно скопировать файл конфигурации и немного его отредактировать.

router# cd /usr/local/etc/
router# cp knockd.conf.sample knockd.conf

knockd.conf:

# Глобальная секция(описание параметров демона)
[options]
		# Имя и путь к лог файлу
        logfile = /var/log/knockd.log
		# На каком интерфейсе демон 
		# будет ждать заданной последовательности
        interface = rl0

# Секция, описывающая открытия
# и закрытия определенного порта
[opencloseSSH]

		# Уникальная последовательность
        sequence      = 15537:udp,16345:tcp,31337:udp

		# Таймаут соединения с портами
        seq_timeout   = 5

		# Флаги, установленные в tcp пакетах
        tcpflags      = syn

		# Команда, которая выполнитсся при успешном
		# соединение с портами в определенной последовательности
        start_command = /sbin/pfctl -t good_hosts -T add %IP%

		# Через какое время будет выполнена stop_command,
		# после выполнения start_command
        cmd_timeout   = 10

		Команда, которая выполнится после timeout'а
        stop_command  = /sbin/pfctl -t good_hosts -T delete %IP%

# Секция для открытия порта
[open22]
        sequence    = 7214:tcp,8745:tcp,9214:udp
        seq_timeout = 5
        tcpflags    = syn

		# Команда, которая выполнится при успешном
		# соединение с портами
        command     = /sbin/pfctl -t good_hosts -T add %IP%

# Секция для закрытия порта
[close22]
        sequence    = 4324:tcp,1244:tcp,4315:tcp
        seq_timeout = 5
        tcpflags    = syn
        command     = /sbin/pfctl -t good_hosts -T delete %IP%

Теперь о том, какие команды я выполняю. У меня в 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

Команда, прописанная в start_cmd или command, для секции [open_метка_], добавляет в таблицу good_hosts ip адрес компьютера которому можно соединяться по
ssh.

Для ipfw правила пишутся еще легче, например так:


# Добавляем разрешающее правило.
/sbin/ipfw add 100 allow tcp from %IP% to me 22 keep-state

# Удаляем предыдущее правило.
/sbin/ipfw delete 100

Теперь запустим демон:

router# cd /usr/local/etc/rc.d/
router# echo knockd_enable=\"YES\" >> /etc/rc.conf
router# ./knockd.sh start
Starting knockd.
router# ps ax | grep knockd
19542  ??  Ss     0:00.01 /usr/local/bin/knockd -d
19544  p2  RL+    0:00.00 grep knockd
router#

Осталось только установить knock клиент на другой машине и протестировать его.

Настройка клиента.

Вторая машина так же  находиться под управлением FreeBSD, так что опять же ставим из портов:

client# cd /usr/ports/security/knock
client# make config

---------------------------------------------------------------------¬
¦                  Options for knock 0.5.20051124                    ¦
¦ -----------------------------------------------------------------¬ ¦
¦ ¦               [ ] SERVER  Install knockd server                ¦ ¦
¦ ¦               [X] CLIENT  Install knock client                 ¦ ¦
¦ ¦                                                                ¦ ¦
¦ ¦                                                                ¦ ¦
+-L------------------------------------------------------------------+
¦                       [  OK  ]       Cancel                        ¦
L---------------------------------------------------------------------

client# make install clean

Настраивать клиент не нужно. Нужно только запомнить или записать последовательность портов к которым нужно
обратиться. Наша последовательность такая: 15537:udp,16345:tcp,31337:udp. Ну что же попробуем подключиться:

client# ssh 192.168.0.2 -l fr33man
^C // Здесь я ждал около 2 минут.
client# knock -v 192.168.0.2 15537:udp 16345:tcp 31337:udp
hitting udp 192.168.0.2:15537
hitting tcp 192.168.0.2:16345
hitting udp 192.168.0.2:31337
client# ssh 192.168.0.2 -l fr33man
Password:
Last login: Sun Sep  3 17:26:19 2006 from 192.168.0.1
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
        The Regents of the University of California.  All rights reserved.

FreeBSD 6.1-RELEASE-p3 (kernel-22.08.2006) #0: Tue Aug 22 12:40:53 MSD 2006

[fr33man@router ~]$

В первый раз у меня соединение не прошло. А вот после того, как я "постучался" на сервер, специально для меня
открылся 22 порт. Посмотрим логи сервера:

router# tail /var/log/knockd.log

[2006-09-03 17:54] 192.168.0.3: opencloseSSH: Stage 1
[2006-09-03 17:54] 192.168.0.3: opencloseSSH: Stage 2
[2006-09-03 17:54] 192.168.0.3: opencloseSSH: Stage 3
[2006-09-03 17:54] 192.168.0.3: opencloseSSH: OPEN SESAME
[2006-09-03 17:54] opencloseSSH: running command: /sbin/pfctl 
-t good_hosts -T add 192.168.0.3

[2006-09-03 17:54] 192.168.0.3: opencloseSSH: command timeout
[2006-09-03 17:54] opencloseSSH: running command: /sbin/pfctl 
-t good_hosts -T delete 192.168.0.3

router#

Теперь можно не боятся, что к Вашему серверу подберут пароль.



размещено: 2006-11-08,
последнее обновление: 2006-11-08,
автор: fr33man


Oxyd, 2006-11-09 в 13:10:51

Ух-ты!!! Грамотная штука, этот port-knocking надо-бы попробовать для OS/2 такое тоже реализовать.

_=KibiZoid=_, 2006-11-13 в 18:07:23

а как быть с виндовым клиентом?

fr33man, 2006-11-13 в 20:15:25

http://www.zeroflux.org/proj/knock/files/knock-cygwin.zip

Тут виндовой клиент.

так же, если вы используете только tcp порты, то можно стандартным telnet'ом подключаться.

siNTez, 2007-04-23 в 14:29:09

Попробовал - понравилось. Если это дело совместить с portsentry и еще задать какой-нибудь другой порт для SSH (например 3022), то в итоге получается достаточно мощная преграда для всякого рода кулхацкеров...

mrsaint, 2007-07-26 в 1:23:43

как заставить работать её с интерфейсом tun?

выдаёт
error: unsupported link-layer type: 0

100kg, 2007-08-26 в 1:43:29

на меня ополчился весь интернет

это все китаицы! пароль у них k перебору MAO DZEDUNG!

taras, 2008-02-05 в 15:17:20

А как заставить работать knock на двух итерфейсах?

Manefesto, 2008-04-23 в 11:51:36

Читай нижесказанное

Manefesto, 2008-04-23 в 11:52:14

"Т0варищщи! Это поля для ввода комментариев к статье, а не для вопросов. Сюда пишите найденные баги, или какие-то фичи :)
Для вопросов есть форум!"

KVIN, 2008-05-12 в 14:08:23

Knockd не поддерживает интерфейсы tun и ng, что делать :(
Гдето читал, что надо в исходниках поправить что-то. Пока не нашел. Мож кто поможет?

TheFeaR, 2008-05-15 в 16:59:10

2mrsaint, 2007-07-26 в 1:23:43, поздновато, но все-же =)

[root@kirill /disk2]#diff knockd.c my.c
215a216,218
>               case 0:
>                       dprint("BSD Loopback detected\n");
>                       break;
1011c1014
<
---
>
1211a1215,1216
>       } else if(lltype == 0) {
>               ip = (struct ip*)((u_char*)packet + 4);

TheFeaR, 2008-05-15 в 17:06:29

пардон, не описал что это, это diff моего knockd который я заставил работать на tun. ng не проверял.

KVIN, 2008-05-19 в 10:50:34

Один многоуважаемый чел (dth) на http://forum.sysfaq.ru предложил такое решение
lltype = pcap_datalink(cap);
switch(lltype) {
case DLT_EN10MB:
dprint("ethernet interface detected\n");
break;
case DLT_LINUX_SLL:
dprint("ppp interface detected (linux \"cooked\" encapsulation)\n");
break;
case DLT_RAW:
dprint("raw interface detected, no encapsulation\n");
break;
case DLT_NULL:
dprint("tun interface detected. pppoe on freebsd\n");
break;

default:
fprintf(stderr, "error: unsupported link-layer type: %d\n", lltype);
cleanup(1);
break;
}

...........

if(lltype == DLT_EN10MB) {
#if defined(__FreeBSD__) || defined(__APPLE__)
eth = (struct ether_header*)packet;
if(ntohs(eth->ether_type) != ETHERTYPE_IP) {
return;
}

ip = (struct ip*)(packet + sizeof(struct ether_header));
} else if(lltype == DLT_LINUX_SLL) {
ip = (struct ip*)((u_char*)packet + 16);
} else if(lltype == DLT_RAW) {
ip = (struct ip*)((u_char*)packet);
} else if(lltype == DLT_NULL) {
ip = (struct ip*)((u_char*)packet + 4);
}


Жирным шрифтом указаны добавления в соответствующие места файла knockd.c
Ставил его на FreeBSD 7.0 из портов, на этапе когда шел configure (сообщения типа checking... ) нажимал Ctrl+C и заменял в папке /usr/ports/security/knock/work/src на тот, который изменял. После этого снова делал make install clean

Проверил на ng интерфейсах - работает

Аноним, 2008-09-29 в 16:23:45

А что, если еще использовать авторизацию по одноразовым паролям через opie, то вполне себе решение, чтобы не таскать с собой постоянно ssh-ключики.

Serg, 2008-10-01 в 0:26:38

еще один виндовый клиент - http://tip-top-sms.ru/winknock.rar
Под винду и под винмобайл

zed, 2009-01-20 в 14:37:57

Вот так

table <idutnafig> persist
block in quick from <idutnafig>

pass in on $ext_if proto tcp to $ext_ip \
   port 22 flags S/SA keep state \
   (max-src-conn 100, max-src-conn-rate 5/30, overload <idutnafig> flush)

>> pf.conf

проще. Но задумка - рулез =)

Мфынф, 2010-11-01 в 21:10:39

Тупая хирня.
Меняйте порт на ССХ и не трахайте себе мозх.

dushkosoft, 2011-11-18 в 14:45:39

to Мфынф,

А так же ш сложно просканить твой поменяный порт ссх))) и трахать мозг перебором на тот порт))

Нужная штука, как писал лисяра - параноя это не плохо))

endo, 2012-03-03 в 1:15:12

Вот же люди, зачем такие сложности. Действительно паранойя.
Использую fail2ban, 3 неверных попытки логина: IP в deny через ipfw на 24 часа. Этим же ipfw смотрю и pop3,imap: долбятся на порт - IP в бан.



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.0538 секунд
Из них PHP: 38%; SQL: 62%; Число SQL-запросов: 77 шт.
Исходный размер: 44602; Сжатая: 10041