Port knocking — дополнительная защита портов

Для дополнительной защиты сервера от злоумышленником, помимо файрвола, используется метод «простукивания портов». Принцип работы port knocking сводится к обращению в определенном порядке и за определенный период времени к цепочке заранее указаных портов. Если последовательность обращения верная и она была произведена в заданный промежуток времени то выполняется команда, к примеру правило файрвола, и открывается нужный порт, после чего вы можете к нему подключиться.

Port knocking можно использовать не только для предоставления доступа к конкретному порту, но также запускать любые команды либо скрипты, к примеру, таким образом вы можете запускать резервное копирование, запускать рассылку сообщений либо отправлять разнообразные уведомления.

Принцип работы

Для настройки на стороне сервера мы будем использовать утилиту knockd. Утилита knocd работает в режиме демона и совместно с iptables прослушивает сетевой трафик ожидая корректной последовательности запросов на подключение.

В тот момент когда knockd получается верную последовательность, которая указана в конфигурации knockd, выполняется правило iptables которое разрешает подключение на определенный сетевой порт, либо можно выполнить любую произвольную команду или даже скрипт.

Установка и настройка knockd

Утилита knockd доступна во всех современных дистрибудивах linux и установить вы можете ее одной командой

apt install knockd

Если же по каким-то причинам данная утилита недоступна в вашей системе вы можете скачать исходники которые доступны на официальном сайте и скомпилировать ее.

После установки установим автоматический запуск knockd, для этого откроем файл который находится по адресу /etc/default/knockd

nano /etc/default/knockd

Для автоматического запуска демона knockd необходимо изменить значение START_KNOCKD и установить его равным 1.

START_KNOCKD=1

Перейдем к настройке knock, файл конфиуграционный файл находится по адресу /etc/knockd.conf, откроем его и отредактируем.

nano /etc/knockd.conf

В секцию [options] нам необходимо добавить интерфейс который утилита knockd будет прослушивать. Чтобы узнать имя вашего интерфейса, выполните команду ifconfig, у меня один интерфейс с именем enp0s3.

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.98  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::a00:27ff:fede:11e0  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:de:11:e0  txqueuelen 1000  (Ethernet)
        RX packets 40043  bytes 45766404 (45.7 MB)
        RX errors 0  dropped 961  overruns 0  frame 0
        TX packets 3949  bytes 706255 (706.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Приводим секцию [options] к следующему виду

[options]
        UseSyslog
        Interface = enp0s3

В стандартной конфигурации в качестве примера указаны две последовательности [openSSH] и [closeSSH] их мы с вами разберем подробнее.

[openSSH]
        sequence   = 7000,8000,9000
        seq_timeout= 5
        command    = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        tcpflags   = syn

[closeSSH]
        sequence   = 9000,8000,7000
        seq_timeout= 5
        command    = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        tcpflags   = syn

Последовательность [openSSH] у нас отвечает за «открытие» 22 порта, а последовательность [closeSSH] за его «закрытие» . Для того чтобы порт 22 был доступен необходим сделать запрос на порт 7000, 8000, 9000 , а для того чтобы закрыть доступ к порту 22 необходимо выполнить обратную последовательность на 9000, 8000 и 7000 порт.

Опция sequence содержит последовательность портов, по умолчанию используется протокол tcp, если вы необходимо использовать udp то необходимо задать его через двоеточие

sequence = 7000:tcp,8000:udp,9000:udp

В seq_timeout указывается значение в секундах за которое клиенту необходимо завершить всю последовательность обращения к портам. Устанавливая данный параметр нужно учитывать возможные задержки каналов связи.

<meta charset="utf-8">seq_timeout= 5

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

<meta charset="utf-8">command    = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

tcpflags — определяет TCP-флаги пакетов, которые будут участвовать в последовательности, syn рекомендуется использовать совместно с SSH, так как SSH-трафик может мешать knockd, делая последовательность недействительной.

<meta charset="utf-8">tcpflags   = syn

Если же вам необходимо открыть порт на определенный промежуток времени то можно использовать опции start_command и stop_command которые определяют команды которые должен выполнить knoсkd с интервалом указанном в опции cmd_timeout. Принцип действия следующий — получив указанную последовательность выполняется команда из опции start_command, а по истечении заданного промежутка времени выполняется команда stop_command.

В примере ниже объединены последовательности [openSSH] и [closeSSH] в одну последовательность c именем [10minSSH] и интервалом предоставления доступа к порту равном 10 минут

<meta charset="utf-8">[10minSSH]
sequence = 7000,8000,9000
seq_timeout = 5
start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 600

tcpflags = syn

После внесения всех настроек, сохраняем файл и запускаем службу knockd

service knockd start 

После запуска проверяем статус службы и нет ли ошибок

<meta charset="utf-8">service knockd status
● knockd.service - Port-Knock Daemon
     Loaded: loaded (/lib/systemd/system/knockd.service; disabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-01-26 11:56:40 UTC; 2s ago
       Docs: man:knockd(1)
   Main PID: 6331
      Tasks: 1 (limit: 1066)
     Memory: 320.0K
     CGroup: /system.slice/knockd.service
             └─6331 /usr/sbin/knockd

Jan 26 11:56:40 unixhosttest1.example.com systemd[1]: Started Port-Knock Daemon.
Jan 26 11:56:40 unixhosttest1.example.com knockd[6331]: starting up, listening on enp0s3

Подключение к серверу

Для того чтобы «достучаться» к закрытому порту необходимо выполнить запрос на ту цепочку портов которая указана в конфигурационном файле и сделать это можно либо используя утилиту которая есть почти в любой системе — telnet либо специальный клиент knock.

Для открытия порта используя telnet последовательно выполняем следующие команды

telnet 192.168.1.98 7000
telnet 192.168.1.98 8000
telnet 192.168.1.98 9000

Если вы уложились в заданный промежуток времени seq_timeout то на сервере на который мы «стучались» в статусе службы вы статус успешного прохождения цепочки и команду которая была выполнена

service knockd status
Jan 27 09:35:33 unixhost knockd[6735]: 192.168.1.99: openSSH: Stage 1
Jan 27 09:35:36 unixhost knockd[6735]: 192.168.1.99: openSSH: Stage 2
Jan 27 09:35:39 unixhos knockd[6735]: 192.168.1.99: openSSH: Stage 3
Jan 27 09:35:39 unixhost knockd[6735]: 192.168.1.99: openSSH: OPEN SESAME
Jan 27 09:35:39 unixhost knockd[38167]: openSSH: running command: /sbin/iptables -A INPUT -s 192.168.1.99 -p tcp --dport 22 -j ACCEPT

Для закрытия порта выполняем команду в обратном порядке

<meta charset="utf-8">telnet 192.168.1.98 9000
telnet 192.168.1.98 8000
telnet 192.168.1.98 7000

Утилита knock уменьшает количество вводимых команд до одной, достаточно перечислить все порты которые необходимо простучать. Для открытия порта необходимо выполнить

knock <meta charset="utf-8">192.168.1.98 7000 8000 9000

А для закрытия

knock <meta charset="utf-8">192.168.1.98 9000 8000 7000

Особенности

В подобном способе защиты есть пару нюансов которые необходимо знать перед тем как настраивать подобный способ защиты на своих серверах.

  • knock работает по принципу демона, если демон knockd по каким-то причинам перестанет работать, то доступ к нужным портам будет невозможен.
  • Если Ваш трафик будет прослушиваться то вычислить правильную цепочку не составит труда и чем чаше вы будете использовать port knocking тем легче это будет сделать