Подробно описывать что такое portknock и зачем он нужен не стану, благо на просторах интернета много информации по этой теме, приведу лишь пример моего конфига для SSH. В тех же интренетах в основном описывают использование отдельного процесса knockd для этих целей, что в некоторых дистрибах(Centos 6/7 например) затруднительно, да и в целом оказалось избыточно. Для этих целей нам понадобится добавить всего два правила к типовой конфигурации фаервола:
-A INPUT -p icmp -m string --string knock --algo bm -m recent --name SSH --set -j LOG
тут мы ловим icmp пакет с некоторым ключом(в данном случае это строка "knock") и выставляем флаг, если его поймали,
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH --seconds 60 -j ACCEPT
а тут мы проверяем флаг и если за последние 60 секунд он установлен для данного адреса, разрешаем соединение.
Полный конфиг может выглядеть примерно так:
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -m string --string knock --algo bm -m recent --name SSH --set -j LOG
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH --seconds 60 -j ACCEPT
-A INPUT -j DROP
Отлично, конфиг готов, как же теперь этим пользоваться? А все просто, достаточно выполнить
$ ping -p 6b6e6f636b -c 1 example.com
и мы получаем открытый 22й порт на 60 секунд, далее ssh example.com и все дела.
Чуть подробнее о магической последовательности ping -p 6b6e6f636b -c 1 example.com, это обычный ping(icmp пакет) в теле которого ключ knock задан в виде hex последовательности 6b6e6f636b. Получить нужный hex из строки можно например так:
$ python -c "import sys;h=sys.argv[1];print('%s %s'%(h,''.join(x.encode('hex') for x in h)))" knock
knock 6b6e6f636b
-A INPUT -p icmp -m string --string knock --algo bm -m recent --name SSH --set -j LOG
тут мы ловим icmp пакет с некоторым ключом(в данном случае это строка "knock") и выставляем флаг, если его поймали,
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH --seconds 60 -j ACCEPT
а тут мы проверяем флаг и если за последние 60 секунд он установлен для данного адреса, разрешаем соединение.
Полный конфиг может выглядеть примерно так:
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -m string --string knock --algo bm -m recent --name SSH --set -j LOG
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH --seconds 60 -j ACCEPT
-A INPUT -j DROP
Отлично, конфиг готов, как же теперь этим пользоваться? А все просто, достаточно выполнить
$ ping -p 6b6e6f636b -c 1 example.com
и мы получаем открытый 22й порт на 60 секунд, далее ssh example.com и все дела.
Чуть подробнее о магической последовательности ping -p 6b6e6f636b -c 1 example.com, это обычный ping(icmp пакет) в теле которого ключ knock задан в виде hex последовательности 6b6e6f636b. Получить нужный hex из строки можно например так:
$ python -c "import sys;h=sys.argv[1];print('%s %s'%(h,''.join(x.encode('hex') for x in h)))" knock
knock 6b6e6f636b