MikroTik + port knocking over ICMP

в 16:18, , рубрики: icmp, mikrotik, Сетевое оборудование, метки: ,

Совсем маленький пост рассказывающий, как отловить 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 + port knocking over ICMP
Собственно здесь всё просто.

Поехали дальше удаляем себя из адрес листов.

Многие кто настраивают 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

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js