...

понедельник, 21 октября 2013 г.

[Из песочницы] ICMP port knocking в OpenWRT

Впечатлённый статьёй решил реализовать подобное решение на домашнем роутере, под управлением OpenWRT (Bleeding Edge r38381). Решение наверно не настолько елегантное как на Miktotik, но главное что рабочее и без скриптов и cron. Так же его можно взять за основу для реализации на других ОС Linux. Кому интересно прошу под кат.

Пришлось облазить много ресурсов. Думал и скрипты писать по отслеживанию LOG или ULOG событий от iptables в системном журнале. Даже наткнулся на проект — Specter, с помошью которого можно реализовать реакцию (выполнение скриптов) на события ULOG от iptables, чего нет в ulogd. Тут большая подборка старых проектов по реализации Port knocking, но совсем не хотелось заниматься компиляцией на роутере или виртуалке. При поиске решения, часто наталкивался на советы про быстроту и удобство ipset-ов, что бы не нагромождать iptables кучей «одинаковых» по деуствию правил. И в них были замечены ключи "--match-set" и "--add-set", дальнейшие поиски и привели к решению.

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


Итак, решение реализовано с использованием сугубо iptables и ipset. Для простоты восприятия комбинация «стуков» будет такой же, как и в упомянутой статье. Напомню это — 2-а ICMP пакета подряд размером 70 байт и за ними 2-а ICMP пакета подряд размером 100 байт. Ну и не забываем о размере заголовка ICMP паркета (28 байт).

В моём случае после соответвующих «стуков» разрешаеться соединение на порту 1194/tcp для OpenVPN сервера для IP адреса, с которого произвели «стуки». С инструкцией по настройке OpenVPN сервера на OpenWRT можно ознакомиться на официальной Wiki, т.к. это выходит за рамки данной статьи.


Подготовка ipset-ов




Стоит отметить, что поддержка правил для создания ipset-ов в файле настроек файрвола OpenWRT появилось только с релиза Attitude Adjustment, правда в ревизии r36349 не работало (При применении правил, выдавало предупреждение, что datatype для ipset-ов не указан).

Но ipset-ы можно создать ручками, желательно создавать их при загрузке, например: прописать в /etc/rc.local.



ipset create knock1 hash:ip
ipset create knock2 hash:ip
ipset create knock3 hash:ip
ipset create AllowedVPN hash:ip




Если же fw3 поддерживает создание ipset-ов (fw3 — это сам инструмент управления файрволом в OpenWRT, с детальным описанием настроек можно ознакомиться на официальной Wiki), то в файл настроек файрвола /etc/config/firewall добавляються следующие пункты:

config ipset
option enabled 1
option name knock1
option storage hash
option match src_ip

config ipset
option enabled 1
option name knock2
option storage hash
option match src_ip

config ipset
option enabled 1
option name knock3
option storage hash
option match src_ip

config ipset
option enabled 1
option name AllowedVPN
option storage hash
option match src_ip


Логика отлавливания последовательности ICMP пакетов




Ловим первый knock


icmptype 8 length 98 ! match-set knock1 src ! match-set knock2 src ! match-set knock3 src ! match-set AllowedVPN src add-set knock1 src



Исходящий адрес ICMP пакета размером 98 байт заносим в ipset knock1, если его нет в остальных ipset-ах.
Ловим второй knock


icmptype 8 length 98 match-set knock1 src ! match-set knock2 src ! match-set knock3 src ! match-set AllowedVPN src add-set knock2 src


Исходящий адрес ICMP пакета размером 98 байт заносим в ipset knock2, если он уже есть в ipset-е knock1 и нет в остальных.
Ловим третий knock


icmptype 8 length 128 match-set knock1 src match-set knock2 src ! match-set knock3 src ! match-set AllowedVPN src add-set knock3 src


Исходящий адрес ICMP пакета размером 128 байт заносим в ipset knock3, если он так же присутсвует в ipset-ах knock1 и knock2, но нет в AllowedVPN.
Ловим четвёртый knock


icmptype 8 length 128 match-set knock1 src match-set knock2 src match-set knock3 src ! match-set AllowedVPN src add-set AllowedVPN src




Исходящий адрес ICMP пакета размером 128 байт заносим в ipset AllowedVPN, если он так же присутсвует в ipset-ах knock1, knock2 и knock3.

Для того что бы последовательность отлавливалась правильно, правила в iptables необходимо заносить в обратном порядке. Иначе первый «стук» будет отловлен первым и вторым правилами сразу так же как третий «стук» отловиться третим и четвёртым правилами сразу.

Дополнительные проверки на отсутсвие в других ipset-ах указаны для чёткого срабатывания последовательности «стуков».

Ниже приведена последовательность команд iptables для занесения в чепочку input_rule (специально созданная чепочка в файрволе OpenWRT для правил пользователя), добавляются в /etc/firewall.user.



iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set AllowedVPN src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock3 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock2 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock1 src




Теже правила, но с логированием в системный журнал


iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set ! --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK4 O) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set AllowedVPN src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK3 O) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock3 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK2 O) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock2 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK1 O) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set ! --match-set AllowedVPN src -j SET --add-set knock1 src







«Самое главное» правило




Именно это правило и разрешает входящее соединение на порт 1194/tcp, если IP адрес с которого производиться соединение, находиться в ipset-е AllowedVPN.

config 'rule'
option enabled 1
option 'target' 'ACCEPT'
option 'name' 'VPN'
option 'src' 'wan'
option 'proto' 'tcp'
option 'dest_port' '1194'
option 'extra' '-m set --match-set AllowedVPN src'




Иначе его можно прописать в /etc/firewall.user

iptables -A input_rule -p tcp --dport 1194 -m set --match-set AllowedVPN src -j ACCEPT




Port knocking




Произвести Port knocking в Windows можно командой:

ping readyshare.mydomain.ua -l 70 -n 2 && ping readyshare.mydomain.ua -l 100 -n 2


Закрытие доступа




Полностью расписывать логику не буду, т.к. она очень схожа с описаной выше, просто логика проверки в правилах инвертирована и происходит удаление из ipset-ов. Ну и соответсвенно если IP адреса нет в ipset-e AllowedVPN — то и нет доступа.

Последовательность «стуков» такая же как и при открытии доступа.

Ниже приведена последовательность команд iptables для занесения в чепочку input_rule, файл /etc/firewall.user

iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set AllowedVPN src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock3 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock2 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock1 src




Теже правила для блокирования, но с логированием в системный журнал


iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK4 C) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set ! --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set AllowedVPN src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK3 C) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 128 -m limit --limit 10/s -m set ! --match-set knock1 src -m set ! --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock3 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK2 C) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set ! --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock2 src
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j LOG --log-prefix "(KNOCK1 C) "
iptables -A input_rule -p icmp -m icmp --icmp-type echo-request -m length --length 98 -m limit --limit 10/s -m set --match-set knock1 src -m set --match-set knock2 src -m set --match-set knock3 src -m set --match-set AllowedVPN src -j SET --del-set knock1 src



Надеюсь мой опыт пригодиться другим.


Хорошая презентация по ipset-ам Chris Cooper-а из QC Co-Lab, от которой я начал отталкиваться при построении решения.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий