Совсем маленький пост рассказывающий, как отловить ICMP пакеты и отфильтровать их с логикой.
Реализуем технология port knocking на RouterOS через протокол icmp.
Прошу под кат.
Наверное нету смысла рассказывать, что такое port knoking, так как в интернете довольно-таки много описаний про него.
Если совсем кратко то технология позволяет при определённом порядке перебора портов, при условии что перебор выполнен верно, выполнять различные действия.
Я же вам покажу как можно реализовать данную технологию через протокол ICMP которые не поддерживает порты. И мы будем апеллировать размером ICMP пакета.
Добавляем себя в white_list
У нас есть правило в фильтре
[admin@kirilka] /ip firewall filter> print
Flags: X - disabled, I - invalid, D - dynamic
0 chain=input action=accept protocol=tcp src-address-list=white_list_ssh in-interface=ether1 dst-port=22
Которое говорит, что разрешать входящие соединение по 22 порту (ssh), со всех адресов которые содержаться в white_list.
Добавим два правила
Зададим критерия, нужна простая проверка уз двух подходов. Пусть будет первых стук пакет размером 70, а второй 100, а также обязательно по два пакета.
Не забываем, что заголовок пакета ICMP 28 байт.
И так у нас вырисовывается следующая картина мы должны два раза стукнуться по ICMP с размером пакета 98байт и два раза стукнуться с размером пакета 128 байт.
Ловим первый пакет с размером 98 байт.
chain=input action=add-src-to-address-list protocol=icmp address-list=ICMP_SSH_98_stage1 address-list-timeout=1m in-interface=ether2 packet-size=98
Пакет размером 98 байт по протоколу ICMP заносим исходящий адрес в лист ICMP_SSH_98_stage1
Ловим второй пакет с размером 98 байт.
chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage1 address-list=ICMP_SSH_98_stage2 address-list-timeout=1m in-interface=ether2 packet-size=98
Пакет размером 98 байт по протоколу ICMP и исходящий адрес уже содержится в листе ICMP_SSH_98_stage1, то заносим исходящий адрес в лист ICMP_SSH_98_stage2
Мы поймали два пакета по 98 байт или 70 байт при отправлении.
Ловим третий пакет с размером 128 байт.
chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage2 address-list=ICMP_SSH_128_stage1 address-list-timeout=1m in-interface=ether1 packet-size=128
Пакет размером 128 байт по протоколу ICMP и исходящий адрес уже содержится в листе ICMP_SSH_98_stage2, то заносим исходящий адрес в лист ICMP_SSH_128_stage1
Ловим четвёртый пакет(последний) с размером 128 байт.
chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_128_stage1 address-list=white_list_ssh address-list-timeout=1h in-interface=ether1 packet-size=128
Пакет размером 128 байт по протоколу ICMP и исходящий адрес уже содержится в листе ICMP_SSH_128_stage1, то заносим исходящий адрес в лист white_list_ssh на 1 час.
Я специально сделал первый пример немного не правильно, чтобы вы смогли увидеть последовательность действий.
Для того чтобы всё заработало вам необходимо порядок правил переместить в обратном порядке. Смотри под спойлером.
[admin@kirilka] /ip firewall filter> print
Flags: X - disabled, I - invalid, D - dynamic
0 chain=input action=accept protocol=tcp src-address-list=white_list_ssh in-interface=ether2 dst-port=22
1 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_128_stage1 address-list=white_list_ssh address-list-timeout=1h in-interface=ether1 packet-size=128
2 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage2 address-list=ICMP_SSH_128_stage1 address-list-timeout=1m in-interface=ether1 packet-size=128
3 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage1 address-list=ICMP_SSH_98_stage2 address-list-timeout=1m in-interface=ether1 packet-size=98
4 chain=input action=add-src-to-address-list protocol=icmp address-list=ICMP_SSH_98_stage1 address-list-timeout=1m in-interface=ether1 packet-size=98
Собственно здесь всё просто.
Поехали дальше удаляем себя из адрес листов.
Многие кто настраивают MikroTik используют защиту от перебора паролей Bruteforce wiki.mikrotik.com/wiki/Bruteforce_login_prevention
Бывает сам отрубаю себе руки. Так что сейчас мы будем удалять себя из листов в которые мы могли попасть.
И так используем наработки которые у нас были из прошлого примера изменим только конечный лист на plsdelme
[admin@kirilka] /ip firewall filter> print
Flags: X - disabled, I - invalid, D - dynamic
0 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_128_stage1 address-list=plsdelme address-list-timeout=1m in-interface=ether1 packet-size=128
1 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage2 address-list=ICMP_SSH_128_stage1 address-list-timeout=1m in-interface=ether1 packet-size=128
2 chain=input action=add-src-to-address-list protocol=icmp src-address-list=ICMP_SSH_98_stage1 address-list=ICMP_SSH_98_stage2 address-list-timeout=1m in-interface=ether1 packet-size=98
3 chain=input action=add-src-to-address-list protocol=icmp address-list=ICMP_SSH_98_stage1 address-list-timeout=1m in-interface=ether1 packet-size=98
Так же нам понадобиться скрипт следующего содержания:
:local wlist "plsdelme";
:local tmp "";
:local tmp1 "";
:if ( [/ip firewall address-list find ] != "") do={
:foreach i in [/ip firewall address-list find list=$wlist] do={
:set tmp [/ip firewall address-list get $i address];
:foreach x in [/ip firewall address-list find list~"blacklist"] do={
:set tmp1 [/ip firewall address-list get $x address];
:if ( $tmp1 = $tmp) do={
/ip firewall address-list remove $x;
}
}
}
}
Данный скрипт необходимо поместить в cron scheduler c интервалом меньшим чем время но которое мы добавляем адрес в лист plsdelme
Что делает сприпт?
Он ищет адреса в листах plsdelme и сверяет значения с листами ~«blacklist», если есть совпадение то удаляет эту запись.
Если вы немного модифицируете скрипт, то можно делать в принципе всё что угодно.
Хотя для этих целей, больше подойдёт использование API.
Автор: vasilevkirill