Port knocking – настолько простой, насколько и эффективный способ защиты вашей локальной сети от несанкционированного доступа снаружи в случаях, когда вам необходимо использовать проброс портов. В этой статье я расскажу, как реализовать этот простой алгоритм авторизации на роутере MikroTik.
О том, что использовать обычный проброс портов не является правильным, я уже упомянул вскользь в статье “Проброс портов в MikroTik“. Но порой все же возникает необходимость давать доступ к удаленным рабочим столам некоторым сотрудникам (например, бухгалтерам в период сдачи отчетности – знакомо, да?).
При этом:
- вам неизвестен адрес, с которого человек будет подключаться и ограничиться правилом в фаерволе у вас не получится;
- использование VPN не представляется возможным в силу нескольких причин, начиная с некомпетентности сотрудника и заканчивая принципиальным запретом VPN на устройствах, через которые этот самый сотрудник будет пытаться подключиться (например, какой-нибудь бесплатный Wi-Fi в отеле на острове Пасхи).
Поможет в этом случае port knocking. Суть этого метода заключается в том, что пользователь, прежде чем получить доступ к чему-то, должен представиться. В классическом решении port knocking используются проколы TCP или UDP – пользователь “простукивает” определенную последовательность портов (обычно не менее трех), после чего его IP добавляется в список адресов с определенными привилегиями: в нашем случае к пробросу порта RDP на его рабочее место. Это как “постучи в дверь три раза, потом – два, потом – пять, чтобы я понял, что это ты”. Знакомо, не правда ли?
Суть алгоритма работы firewall при обработке последовательности port knocking заключается в том, что на ряду с проверкой текущего условия происходит проверка: было ли выполнено предыдущее условие.
Последовательность портов для простукивания и ее длина обусловлены только вашей фантазией. Но тут возникает небольшая проблема: если с простукиванием портов из Linux штатными средствами проблем никаких не наблюдается, то с Windows этот номер просто так не пройдет. Но у ваших бухгалтеров наверняка на ноутбуках стоит Windows, а слово Linux они вообще воспринимают, как ругательство.
Пример простукивания портов штатными средствами на Linux:
|
[root@server~]# nc -zu 1.1.1.1 35123
[root@server~]# nc -zu 1.1.1.1 18357
[root@server~]# nc -zu 1.1.1.1 43249
|
Здесь использовалась команда nc [параметры] [хост] [порт] , где
- z – говорит программе о том, что нужно просто “стукнуться”, не посылая каки-либо дополнительных данных и не слушая ответ;
- u – использование UDP вместо TCP.
К сожалению, данный пример не решает нашей задачи со штатными средствами Windows. А решение простое и лежит на поверхности: вместо UPD или TCP использовать ICMP ping. Принцип port knocking мы оставим, а последовательность портов заменим последовательностью разных размеров пакета.
Выглядеть “простукивание” из Windows будет так:
|
C:\>ping 1.1.1.1 -f -n 1 -l 432
C:\>ping 1.1.1.1 -f -n 1 -l 521
C:\>ping 1.1.1.1 -f -n 1 -l 598
|
Простой ping с параметрами:
- -4 – использовать IPv4
- -f – запрет фрагментации пакета;
- -n – количество запросов;
- -l – буфер отправки (объем данных, которые мы отправляем “в нагрузку”).
Т.к. стандартный размер MTU – 1500, который к тому же может быть уменьшен всякими VLAN’ами и пр., а нам нужно, чтобы все влезло в один Ethernet фрейм, то рекомендую использовать буфер отправки в диапазоне 0-1000. Еще следует учесть, что размер самого пакета эхо-запроса ICMP “без нагрузки” (с L=0) – 28 байт, т.к. помимо данных там еще присутствует TCP-, ICMP-заголовки и .т.д. Можете погуглить, что из себя представляет ICMP-пакет. Таким образом, на роутере ловим пакеты размером равным [буфер отправки+28].
Теперь наш MikroTik должен распознать последовательность из трех пакетов с размерами 460, 549, 626. “На пальцах” алгоритм выглядит так:
- если размер пакета 460 (432+28), добавить этот IP в список “первый уровень”;
- если размер пакета 549 (521+28) и IP-адрес в списке “первый уровень”, добавить этот IP в список “второй уровень”.
- если размер пакета 626 (598+28) и IP-адрес в списке “второй уровень”, добавить этот IP в список “доступ к пробросу портов по RDP”
Реализация port knocking на MikroTik
Сначала в картинках:
Рис. 1 Создадим свою цепочку portKnocking и направим туда входящий ICMP
Рис.2 Создадим правило, которое в случае нужного размера пакета будет добавлять IP-адрес в список checkLevelOne
Рис.3 Аналогично первому создадим второе правило за тем лишь исключением, что проверим присутствие в списке прошедших первую проверку checkLevelOne. Добавлять будем в список checkLevelTwo
Рис.4 Аналогично второму создадим третье правило, которое уже добавит наш IP в список, которому разрешен доступ к пробросу порта. Четвертое правило в списке – возврат из цепочки обратно, если ни одно из правил не сработало.
Правила проверки port knocking в фаерволе надо разместить вверху до разрешений related/established. Иначе вы не уйдете дальше первой проверки – будут срабатывать правила related/established.
Рис.5 Сначала проверим, не стучится ли кто, потом разрешим related и established. В противном случае в цепочке portKnocking дальше первого правила не уйдем.
В скриптах:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#
#
/ip firewall filter
#направим входящий ICMP в свою цепочку portKnocking. Для удобства.
add action=jump chain=input comment="port knocking check" dst-address=1.1.1.1 jump-target=portKnocking protocol=icmp
#первый пинг packet-size=460
add action=add-src-to-address-list address-list=checkLevelOne address-list-timeout=5s chain=portKnocking comment=CheckLevelOne packet-size=460 protocol=icmp
#второй ping packet-size=549 и признак успешной проверки первого пинга src-address-list=checkLevelOne
add action=add-src-to-address-list address-list=checkLevelTwo address-list-timeout=5s chain=portKnocking comment=CheckLevelTwo packet-size=549 protocol=icmp src-address-list=checkLevelOne
#третий пинг packet-size=626 и признак успешной проверки второго пинга src-address-list=checkLevelTwo
add action=add-src-to-address-list address-list=AllowRDP address-list-timeout=30m chain=portKnocking comment=AllowRDP packet-size=626 protocol=icmp src-address-list=checkLevelTwo
#возврат из цепочки portKnocking
add action=return chain=portKnocking
#
#где-то в правилах, где у вас разрешения на INPUT
add chain=input comment="Allow RDP from PortKnockin authorized" protocol=tcp dst-port=4565,4355 src-address-list=AllowRDP
#
#проброс порта для адресов из списка AllowRDP
/ip firewall nat
# первому пользователю порт 4565 - > 192.168.33.129:3389
add action=dst-nat chain=dstnat comment=test dst-address=1.1.1.1 dst-port=4565 in-interface=inetTest src-address-list=AllowRDP protocol=tcp to-addresses=192.168.33.129 to-ports=3389
# второму пользователю порт 4355 - > 192.168.33.130:3389
add action=dst-nat chain=dstnat comment=test dst-address=1.1.1.1 dst-port=4355 in-interface=inetTest src-address-list=AllowRDP protocol=tcp to-addresses=192.168.33.130 to-ports=3389
|
Обратите внимание на параметр address-list-timeout в правилах, где IP добавляется в список адресов. Для этапов проверки я выставляю address-list-timeout=5s , т.к. считаю, что 5 секунд должно хватить для проверки следующего условия. Для завершающего правила, где адрес добавляется в разрешенные для подключения по RDP, address-list-timeout=30m – т.е. для подключения к удаленному рабочему столу человеку дается полчаса после успешного “простукивания” MikroTIk’а.
По истечении получаса адрес будет удален из списка AllowRDP, но сеанс не прервется, т.к. будут срабатывать правила allow related/established. Пользователю придется заново “представиться” в случае, если он сам прервет сеанс или за него это сделает плохая связь.
Для автоматизации процесса пишем пакетный файл (.bat или .cmd – кому как больше нравится) следующего содержания:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@echo off
rem раз
ping 1.1.1.1 -f -n 1 -l 432 > NUL
rem подождем секунду, вдруг роутер притормаживает
timeout 1 > NUL
rem два
ping 1.1.1.1 -f -n 1 -l 521 > NUL
rem подождем еще секунду
timeout 1 > NUL
rem три
ping 1.1.1.1 -f -n 1 -l 598 > NUL
rem запустим клиента удаленного рабочего стола, указав адрес сервера и порт
mstsc.exe /v:1.1.1.1:4565
|
Теперь осталось только выслать каждому пользователю свой файл.
Как вы поняли, реализация алгоритма с простукиванием портов не только аналогична описанной выше, но даже проще – там не надо заморачиваться с размером пакета, а просто указать порт. Но для Windows нужны свои костыли… |