Пришлось облазить много ресурсов. Думал и скрипты писать по отслеживанию 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, от которой я начал отталкиваться при построении решения.
ссылка на оригинал статьи http://habrahabr.ru/post/198108/
Добавить комментарий