Описание
Проект icmp-knock предназначен для организации выполнения заданных комманд на целевой системе посредством отсылки на хост icmp пакетов определенной длины кодирующей одноразовый пароль.
Подготовка
Установить модуль ‘python3-pyotp’ (прочие как правило присутствуют в системе по-умолчанию).
Склонировать репу: git clone https://gitflic.ru/project/konsul/icmp-knock.git
Перейти в каталог и запустить основной модуль:
cd /root/icmp-knock
./icmp-knock.py
При первом запуске будет сгенерирована затравка для генератора одноразовых паролей временного типа. Код выведенный в строчке New OTP key generated:
необходимо добавить в google-authenticator или иную аналогичную программу.
После генерации в ответ на запрос Add key to authenticator and enter verification code:
необходимо ввести одноразовый пароль сгенерированный приложением и убедиться, что код принялся корректно. В случае успеха, затравка будет сохранена в локальном конфиге local.d/config.yml
в котором кроме прочего можно добавить свои комманды для выполнения по примеру коробочного config.yml
При последующих запусках, программа будет подгружать локальный конфиг и при наличии в ней параметра otp_key
сразу переходить в рабочий режим.
Применение
Частный случай применения - открытие доступа к машине с динамического адреса через iptables который по-умолчанию блокирует все входящие соединения. Для этого можно добавить в local.d/config.yml
следующие опции:
commands:
code_correct:
- print(f"Executing code_correct for source {addr}")
- subprocess.run(["iptables", "-I","INPUT","-s",addr,"-j","ACCEPT"])
Первая команда выводит сообщение на экран, вторая выполняет команд iptables -I INPUT -s addr -j ACCEPT
где addr
будет замещен на адрес, с которого пришел код. Для отправки кода, необходимо отправить с машины источника три пакета. Первый с нулевой длиной для вычисления размера заголовка и корректного вычисления размера блока данных без разбора пакета. Следом должны прийти два пакета кодирующих одноразовый пароль. Длина одного - первые три цифры пароля (без лидирующего нуля), длина второго - вторые три цифры без лидирующего нуля. Например, генератор выдал пароль 011 873
, на источнике (например windows) выполняется следующие команды:
ping 1.1.1.1 -l 0 -n 1
ping 1.1.1.1 -l 11 -n 1
ping 1.1.1.1 -l 873 -n 1
Опция -l задает размер блока данных, -n число пакетов (по одному). Программа на целевой машине (в примере 1.1.1.1) выведет следующее:
[...][main] Packet from .179 len:28
[...][main] Возможно пилотный пакет с адреса .179
[...][main] Packet from .179 len:299
[...][main] Код-1 011 с адреса .179
[...][main] Packet from .179 len:901
[...][main] Код-2 873 с адреса .179
[...][main] Корректный код с адреса .179
[...][run_commands] Executing cmd: [print(f"Executing code_correct for source {addr}")]
Executing code_correct for source for .179
[...][run_commands] Executing cmd: [subprocess.run(["iptables", "-I","INPUT","-s",addr,"-j","ACCEPT"])]
Т.е. по факту приема корректных пакетов будут выполнены заданные команды.
Прочие замечания
- Нежелательно трогать
config.yml
из поставки, во избежании конфликтов при обновлении. Оптимальной стратегией является создание локально конфига вlocal.d/config.yml
в котором переназначить параметры как надо. Конфиг будет подхвачет при старте автоматически. - Если есть уверенность в размере пустого пакета который генерируется вашими машинами, то имеет смысл откорректировать выражение
pilot_expression
в конфиге для точного попадания в размер. В принципе за пилотный пакет можно принять пакет любого размера, но следует учитывать что размер пилота вычитается из размера кодовых пакетов для возможности прямого переноса одноразового кода в параметр команды ping. В случае если пилот будет с ненулевым блоком данных, одноразовый код придется корректировать на соответствующую величину. - Для исключения повторного использования кода с другого адреса (при перехвате трафика например) он привязывается к источнику на время заданное в конфиге (60 секунд по-умолчанию). Опционально, можно запретить повторное использование кода вообще установив параметр
repeat_allowed
в False.