Настройка Port Knocking

Иногда возникает необходимость СОВСЕМ-СОВСЕМ обезопасить доступ по ssh на сервер. Например, когда у вас начальник страдает паранойей. Кто-то закрывает доступ для рута, другие ограничивают доступ для всех адресов, кроме конкретных. Мы же в данной заметке рассмотрим так называемый Port Knocking способ.

Суть его заключается в следующем: настройки доступа (читай фаервола) требуют определённой последовательности подключений к определённым же закрытым портам. После того, как эта последовательность соблюдена, фаерволл открывает определённый порт для подключения.

Введение

Для реализации нам потребуется: • Тестовый Linux сервер – можете взять свой любимый дистрибутив • Пакеты iptabels и iptables-services • Модуль iptables recent

Модуль recent нам понадобится для того, чтобы определять «стучался» ли в недавнем времени определенный IP-адрес в нужный нам порт. На основе этих данных можно строить последующую логику. Например, открывать определённый порт на короткий промежуток времени. Как раз то, что нам нужно!

Как всегда настраивая правила iptables будьте осторожны с применением настроек. Вы можете потерять коннект до хоста навсегда. Тем более если у вас нет консоли. Продумайте пути отката.

Для своего стенда я буду использовать CentOS 7.5.

Приступим

Итак, у нас есть сервер с IP-адресом 192.168.11.101. Нам необходимо запретить до него доступ всем, кроме тех, кто знает «как правильно постучаться». Последовательность портов будет такая: 8881 7777 9991

Создаём длинное правило на сервере. Записываем его в файл iptables.rules:

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:TRAFFIC - [0:0]
:SSH-INPUT - [0:0]
:SSH-INPUTTWO - [0:0]

-A INPUT -j TRAFFIC
-A TRAFFIC -p icmp --icmp-type any -j ACCEPT
-A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --seconds 30 --name SSH2 -j ACCEPT
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 9991 -m recent --rcheck --name SSH1 -j SSH-INPUTTWO
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 7777 -m recent --rcheck --name SSH0 -j SSH-INPUT
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 8881 -m recent --name SSH0 --set -j DROP
-A SSH-INPUT -m recent --name SSH1 --set -j DROP
-A SSH-INPUTTWO -m recent --name SSH2 --set -j DROP
-A TRAFFIC -j DROP
COMMIT

На сервере выполняем команды:

systemctl start iptables
systemctl enable iptables
iptables-restore < iptables.rules
service iptables save

Теперь доступ есть только у тех, кто знает нашу последовательность. Я буду «стучаться» с помощью nmap. Для этого напишем простенький скрипт:

#!/bin/bash
HOST=$1
shift
for ARG in "$@"
do
        sudo nmap -Pn --max-retries 0 -p $ARG $HOST
Done

Запускаем его:

chmod + x knock.sh && ./knock.sh 192.168.11.101 8881 7777 9991

Теперь у нас есть 30 секунд для подключения. Если не успели за этот интервал, то придётся запускать скрипт заново.

Заключение

В итоге мы закрыли доступ по ssh для всех, кроме «знающих». Остаётся, мизерная вероятность того, что кто-то в этот же 30 секундный промежуток попытается зайти на ваш сервер! Но это настолько маловероятно, да и вы сами знаете про стандартные средства защиты.

Есть вопрос? Напишите в комментариях!