Knockd – программа, которая запускает заранее заданную команду, если выполнено условие коннекта на определенные порты компьютера. Это если кратко и попонятней 🙂 На самом деле коннекты должны идти в определенной последовательности и с определенным интервалом.
Есть серверная часть – демон knockd, в конфигурации которого задана команда выполнения и задан набор определенных портов компьютера. Также есть клиентская часть, с помощью которой и происходит открытие той двери, которая закрыта за knockd. Клиент программы есть для Unix и Windows систем.
В основном команды knockd управляют открытием или закрытием портов брандмауэра компьютера, но никто вам не запрещает исполнить любую другую команду.
В данной статье я разберу пример как защитить порт ssh от посторонних соединений.
Дополнительную информацию о программе и примерах конфигурационных файлов можно узнать на официальном сайте
Установка knockd и базовая настройка
Установка во всех дистрибутивах очень проста, в ubuntu (debian) она сводится к выполнению команды
#sudo aptitude install knockd
После установки knockd в /etc/knockd.conf находим конфиг программы следующего содержания, показать
В linux дистрибутивах этого конфига достаточно, чтобы уже запускать демон knockd и начинать работать. Перед запуском демона требуется сперва убрать доступ к 22 порту в брандмауэре и само собой на этом порту должен работать openssh сервер 🙂
Кто забыл как работать с брандмауэром в linux советую прочитать мои статьи iptables – полезные команды и настраиваем защищенный iptables
Итак, запускаем демон
#knockd -d
Переходим на машину, откуда будем пробовать соединиться с удаленным портом. В зависимости от ОС на этой машине ставим или скачиваем клиентскую команду knock.
Пробуем соединиться на 22 порт через ssh, пускать не должно. После выполнения команды knock с заветными номерами портов доступ к порту ssh будет предоставлен
mik@gw:~$ telnet m1k 22
Trying 192.168.0.17...
^C
mik@gw:~$ knock -v m1k 7000 8000 9000
hitting tcp 192.168.0.17:7000
hitting tcp 192.168.0.17:8000
hitting tcp 192.168.0.17:9000
mik@gw:~$ telnet m1k 22
Trying 192.168.0.17...
Connected to m1k.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.2
Закрыть обратно доступ – выполним команду knock с портами закрытия
mik@gw:~$ knock -v m1k 9000 8000 7000
hitting tcp 192.168.0.17:9000
hitting tcp 192.168.0.17:8000
hitting tcp 192.168.0.17:7000
mik@gw:~$ telnet m1k 22
Trying 192.168.0.17...
^C
В логах на сервере /var/log/knockd.log можно всегда посмотреть с какого ip и в какое время выполнялись команды открытия/закрытия.
Если что-то не получается даже с этим простейшим примером, то дело скорей всего в брандмауэре. Нельзя сначала явно запретить доступ в брандмауэре а потом пытаться его открыть. В следующем листинге показана ситуация, когда я явно запретил правило в конфигах, а потом открыл доступ к порту через knockd команду.
12 720 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
0 0 ACCEPT tcp -- * * 192.168.0.254 0.0.0.0/0 tcp dpt:22
По количеству байт и пакетов видно, что сначала отрабатывает правило запрета, а до разрешающего правила доступ не доходит. Выход тут только один “неявно” делать запрет. Как вариант в общей политике iptables прописывать
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
а потом разрешать входящие только то, что требуется. Так что правило для входящих на 22 порт от knockd будет в этом случае очень кстати 🙂
Дополнительные настройки knockd
Конфигурационный файл /etc/knockd можно дополнить следующими опциями и командами
[options]
#задать имя интерфейса на которое будет срабатывать команда
interface = eth0
В параметрах открытия закрытия тонко указать использовать tcp или udp порты
sequence = 1234:udp,5678:tcp,9101:udp
соответсвенно чтобы выполнить команду такой последовательности надо выполнять команду
$knock host 1234:udp 5678:tcp 9101:udp
Можно задавать время в секундах между выполнением команд открытия и закрытия портов.
start_command = открываем порт
cmd_timeout = 600 #время между выполнением команд
stop_command = закрываем порт
Для совсем помешанных на безопасности можно создать файл с уникальными последовательностями портов на каждой строчке и потом каждый раз входить по определенной последовательности портов. В /etc/knockd.conf файл последовательностей задается переменной
One_Time_Sequences = /path/to/one_time_sequences_file
В файле рекомендуется каждую последовательность начинать с пробела, т.к. после использования этой последовательности демон knockd комментирует строку символом #. Нельзя редактировать файл последовательностей портов пока демон работает!
Для выполнения команды knockd, где требуется открыть больше одного порта по заданию одной последовательности портов, создадим любой файл в котором опишем нужные команды. Вместо переменной %IP% требуется писать $1. Например для открытия одновременно 22 и 23 портов создаем файл с содержимым
/usr/sbin/iptables -A INPUT -s $1 -p tcp --dport 22 -j ACCEPT
/usr/sbin/iptables -A INPUT -s $1 -p tcp --dport 23 -j ACCEPT
Назовем файл open_22_23 и сделаем его исполняемым.
В конфиге knockd.conf вместо команды iptables пишем
command = /path/to/open_22_23 %IP%
Аналогично с командой закрытия, только для нее уже создадим другой файл команд.
Для брандмауэра ipfw в системе FreeBSD применяем следующие команды открытия/закрытия 22 порта. При добавлении-удалении используем номер правила.
/sbin/ipfw add 111 allow tcp from %IP% to me 22 keep-state
/sbin/ipfw delete 111
В дальнейшем не забыть поставить демон в автозагрузку при старте ОС. В ubuntu это можно сделать, изменив параметр START_KNOCKD=1 в файле /etc/default/knockd