Перейти к содержимому

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 указывается значение в секундах за которое клиенту необходимо завершить всю последовательность обращения к портам. Устанавливая данный параметр нужно учитывать возможные задержки каналов связи.

    seq_timeout= 5

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

    command    = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

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

    tcpflags   = syn

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

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

    [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 

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

    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

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

    telnet 192.168.1.98 9000
    telnet 192.168.1.98 8000
    telnet 192.168.1.98 7000

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

    knock 192.168.1.98 7000 8000 9000

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

    knock 192.168.1.98 9000 8000 7000

    Особенности

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

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