MikroTik Настройка Firewall
За несколько лет работы, мы для себя нашли некоторую золотую середину в настройке Firewall MikroTik, и естественно хотим поделиться ею с вами.
MikroTik Firewall Filter
Хочу признаться мне не очень нравиться дефолтный конфиг Firewall, но я прекрасно понимаю, что тем кто его придумал, была задача найти условно общую конфигурацию которая бы подходила к большинству и покрывала решение зада большинства, но мы не большинство, и будем “лепить” свой конфиг.
Естественно чистим конфигурацию или просто очищаем полностью Filter Firewall-а.
/ip firewall filter remove [find]
В первую очередь мы должны защитить наш маршрутизатор от условных проблем, атак или злоумышленников из сети интернет.
Interface List ISP
В моём случае для примера у меня три провайдера ether1, ether2, ether3 и поверх ether3 запущен PPPoE туннель для получения доступа к интернету.
Создадим лист интерфейсов в котором перечисляем все интерфейсы подключенные к сетям провайдеров. Причём неважно один или два или десять у вас таковых интерфейсов.
/interface list add name=ISP
Как вы его назовёте, не имеет значения, главное чтобы вам был понятен смысл имени и наверное очень важно, то чтобы было понятно любому другому человеку который взглянет на ваши настройки. Ведь согласитесь если вы его назовёте “Bla-bla-bla” смысл для любого человека будет непонятен, хотя возможно для вас он и будет иметь сакральный смысл.
Я предпочитаю называть данный лист ISP, что обозначает Internet Service Provider.
Соответственно добавляем в данный лист все интерфейсы провайдеров.
/interface list member
add list=ISP interface=ether1
add list=ISP interface=ether2
add list=ISP interface=ether3
add list=ISP interface=ether3.PPPoE
Обратите вниманию я добавил ether3 и PPPoE интерфейс которые поднят через него же. По поводу наименование PPPoE туннеля не удивляйтесь у меня есть привычка использовать в наименовании интерфейсов точку в случае если данные интерфейс является sub интерфейсом другого интерфейса. К примеру если у меня будет vlan 100 на первом интерфейсе его имя будет ether1.100.
Настройка MikroTik
Закажи настройку MikroTik непосредственно сейчас, поможем в поиске решения по любому кейсу связанному с MikroTik.
Предоставляю гарантию две недели на свою работу, оплата постфактум, работаю как с юридическими, так и физическими лицами.
На данный момент мы закончили с настройкой листа ISP и может приступить непосредственно к настройке Firewall.
Firewall Filter
Начнём непосредственно настраивать наш filter.
Firewall Filter Input
Первым делом мы будем настраивать трафик, который пришёл на маршрутизатор, и является потенциально опасным для маршрутизатора.
Все дальнейшие правила мы делаем в разделе фильтра, я не буду указывать в приведённых примерах.
/ip firewall filter
Самым первым правилом отправляем весь трафик с интерфейсов провайдеров в кастомную цепочку (custom chain) с помощью jump.
add chain=input in-interface-list=ISP action=jump jump-target=ISP-Input
С этого момента мы будем работать ТОЛЬКО с цепочкой ISP-Input
, про цепочку
input
можете пока забыть, хотя она нам ещё понадобится.
Следующим правило мы разрешаем, пакеты established
которые возвращаются на уже
установленное соединение, такие пакеты необходимо разрешать.
add chain=ISP-Input connection-state=established action=accept
Обратите внимание, что я не указываю ни интерфейсы, ни список интерфейсов, нам нет необходимости этого делать, так как самое первое правило отправило в данную цепочку только трафик которые приходит с интерфейсов провайдеров перечисленных в листе ISP.
Следующее правило разрешаем related
, это пакеты, которые создали вторичное соединение,
такие пакеты помечаются когда на основании какого либо payload создаются новые соединения,
например если вы используете NAT-helper ftp или SIP. Также related
в некоторых
случаях это ICMP ответ маршрутизатора.
add chain=ISP-Input connection-state=related action=accept
Мы часто используем возможность снижение нагрузки на connection-tracker с помощью исключения пакетов с помощью raw untracked, также используется для обхода NAT в случае когда необходимо исключить процедуру изменения заголовка пакета.
add chain=ISP-Input connection-state=untracked action=accept
Кто-то из вас скажет, “Стоп-стоп, но ведь мы можем все эти три последние правила
описать одним, просто перечислив состояния через запятую!!! Зачем создавать три
правила?!” Да можем, но моя задача, во-первых, показать вам все правила наглядно,
а во вторых у нас появляется возможность видеть количество трафика и нагрузку pps
по каждому конкретному типу пакетов, и в случае необходимости изменить порядок для
оптимизации.
Настала пора создать наше первое запрещающее правило, мы должны запретить пакеты с состоянием
invalid
, таким состоянием помечаются пакеты в нескольких случаях:
- Если на вашем маршрутизаторе закончится память и connection-tracker не сможет создать запись для соединения, но это редкий случай.
- Если пакет принадлежит к одному из протоколов
GRE
,ICMP
илиTCP
, то RouterOS умеет понимать по-содержимому пакетов данные протоколов должен являться данный пакет частью существующего соединения или нет.Если по признакам он является частью соединения, но соединения нет в connection-tracker, то такой пакет помечается какinvalid
.Пример на маршрутизатор пришёл один пакет TCP с флагамиsyn
иack
, т.е.Какой-то хост “по идеи” ответил на посылкуsyn
пакета, но если соединения нет, то нам такой пакет не нужен. Также это простая защита от TCP RST Flood.
add chain=ISP-Input connection-state=invalid action=drop
Как вы наверное знаете в RouterOS с включенным connection-tracker существует пять
состояний пакетов, четыре из которых мы описали, а так как правила в firewall терминирующие,
т.е после срабатывания правила пакет прекращает обработку в filter.У нас остаётся
всего один тип пакетов это new
это те самые пакеты которые создают соединения,
другими словами когда кто-то инициализирует соединение к маршрутизатору такой пакет
имеет состояние new
. Но так как мы описали четыре состояния, нет смысла указывать
состояние, так как подразумевается по остаточному принципу, что в следующем правиле
и так будут только new
.
Мне часто приходится настраивать RouterOS под проекты, и зачастую я подготавливаю оборудование так, чтобы с ним было комфортно работать заказчику, так как со временем у заказчика могут появиться дополнительные кейсы, и чтобы было однотипность в настройках мы поступаем следующим образом.
Выносим все разрешающие правила в отдельную цепочку например с именем ISP-Input-Allow
.
В таком случае нет необходимости думать в каком месте по порядку разместить правила,
чтобы они были правильно расположены относительно всех других правил.
add chain=ISP-Input action=jump jump-target=ISP-Input-Allow
Следующим правилом мы запрещаем все остальные пакеты, которые дошли до следующего правила. Будьте аккуратны, возможно если вы подключены через провайдера к маршрутизатору, вы не сможете подключиться к маршрутизатору в случае разрыва соединения.
add chain=ISP-Input action=drop
Ну вот пожалуй с каркасом закончили, теперь нам необходимо разрешить какой-то трафик на сам маршрутизатор.
Для закрепления результата представим, что у нас поднят на RouterOS l2tp сервер и мы хотим иметь возможность подключаться по ssh, а также маршрутизатор должен отвечать на запросы icmp.
Мы будем использовать кастомную цепочку ISP-Input-Allow и порядок правил в нём не важен, а также неважно расположение правил в этой цепочке относительно всех других правил, хоть в разнобой, хоть в конце, хоть в начале.Это не принципиально. Наверное всё-таки для удобства желательно расположить их по порядку и в одном месте. Но это только для тех кто использует winbox для настроек, а для тех кто используется CLI или как-то оркестратор типа ansible, как раз проявляется удобство в том, что вам не надо думать о прядке правил.
Опишу правила одним блоком
add chain=ISP-Input-Allow protocol=icmp action=accept
add chain=ISP-Input-Allow protocol=tcp dst-port=22 action=accept
add chain=ISP-Input-Allow protocol=udp dst-port=1701 action=accept
Если пакет которых поступает в данную цепочку дойдёт до конца её, то он перейдёт на следующее правило после которого он попал в данную цепочку.
Вот таким образом у вас должен выглядеть filter в winbox.

Я отформатировал вывод убрав отображение некоторых столбцов.
А теперь давайте посмотрим как будут работать данные правила, при поступлении рафика в цепочку INPUT.
Первый пример HOST 5.5.5.5 хочет установить соединение с SSH MikroTik с адресом 2.2.2.2.
Хост 5.5.5.5 отправляет syn пакет для установления соединения с ssh сервером на MikroTik

Такой пакет первым же правилом попадает под jump и отправляется к custom chain ISP-Input
Далее маршрутизатор находит все правила в кастомной цепочке ISP-Input перебирать соответствию пакета для правила

В первых 4 правилах в цепочке ISP-Input он не найдёт соответствия, а вот в пятом правиле сделает jump на ещё одну цепочку. Соответственно выберет все правила из новой цепочке ISP-Input-Allow

И будет снова сверять по порядку, соответствия пакета правилу.

Как только найдено терминирующее правило, а в нашем случае это accept, маршрутизатор заканчивает обработку данного пакета в filter firewall и отправляет пакет в Local Process.
SSH сервер ответит пакетом TCP c флагами syn,ack после получения такого пакета клиент
отправит пакет с флагом ACK и такой пакет уже будет обрабатываться как established
.


Но первым же правилом в цепочке ISP-input у нас есть разрешающее терминирующее правило для пакетов с состоянием established. Такой пакет сразу отправиться в Local Process.

А теперь давайте попробуем разобраться, что будет если хост отправит пакет на порт Winbox TCP 8291, который мы явно не запрещали.
Начало будет одинаковое


Когда пакет будет проверяться соответствиям правилам в цепочке ISP-Input-Allow, для него не найдётся, не одного подходящего правила.

В этом случае произойдёт автоматически return, и обработка выйдет из цепочки ISP-Input-Allow
и продолжит обрабатываться в цепочке ISP-Input
а у нас есть правило, которое
отбрасывает все пакеты DROP всё, такой пакет не когда, не попадёт в Local Process.

Т.е если в custom chain не найдено соответствие, не с одним правилом, то обработка такого пакета возвращается и продолжает обработку по порядку со следующего правила места входа.
Для удобства восприятия поставил слева номера, чтобы был понятен порядок обработки

И ещё раз порядок правил имеет значения только для каждой отдельной цепочки, а не относительно всех цепочек.
Firewall Filter Input SSH-Brute-force
В данном разделе мы рассмотрим настройку защиты от перебора паролей по протоколу SSH в сетях с использованием RouterOS.
Изменение порта SSH
Практика показывает, что даже самое простое изменение порта SSH-сервера может сделать вас менее уязвимыми перед большинством сканеров, хотя, конечно, не перед всеми. В локальной сети за маршрутизатором мы можем оставить стандартный порт 22, а с внешней стороны сети изменить его, например, на порт 1024 с использованием простого перенаправления (redirect).
/ip firewall nat
add action=redirect chain=dstnat dst-port=1024 in-interface-list=ISP protocol=tcp to-ports=22
Настройка фильтрации
Далее нам нужно добавить или изменить правило в цепочке ISP-Input-Allow, чтобы разрешить трафик SSH.
add chain=ISP-Input-Allow protocol=tcp dst-port=22 connection-nat-state=dstnat action=jump jump-target=SSH-Brute-force
Обратите внимание на параметр connection-nat-state=dstnat, который позволяет разрешить только тот трафик, который попал под перенаправление dstnat.
Создание цепочки правил SSH-Brute-force
Далее создаем кастомную цепочку правил с названием SSH-Brute-force, которая будет обрабатывать попытки перебора паролей.
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-block action=drop
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-4 action=add-src-to-address-list address-list=SSH-Brute-force-block address-list-timeout=8h
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-3 action=add-src-to-address-list address-list=SSH-Brute-force-4 address-list-timeout=1m
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-2 action=add-src-to-address-list address-list=SSH-Brute-force-3 address-list-timeout=1m
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-1 action=add-src-to-address-list address-list=SSH-Brute-force-2 address-list-timeout=1m
add chain=SSH-Brute-force action=add-src-to-address-list address-list=SSH-Brute-force-1 address-list-timeout=1m
add action=accept chain=SSH-Brute-force
Эти правила позволяют блокировать адреса, с которых выполняются подозрительные попытки входа, а также ввести тайм-ауты для автоматического разблокирования адресов после определенного времени.
Такая конфигурация поможет усилить безопасность вашего SSH-сервера и снизить риск успешных атак перебора паролей.
На этом этапе мы закончили работу с трафиком Input и переходим к Forward.
Firewall Filter Forward
Естественно нам необходимо защитить трафик, который проходит со стороны провайдеров через маршрутизатор.
Многие наверное скажут, а зачем его защищать, ведь трафик нельзя отправить через маршрутизатор, для этого необходимо адрес маршрутизатора прописать как шлюз, что в свою очередь говорит о том, что маршрутизатор должен находится в Connected сети.
Вот вам маленькая история.
Мне провайдер выдаёт внутренней адрес из сети /22 и со всеми соседями я нахожусь в одном Broadcast домене. Получилось так, что пропустил платёж и мне провайдер на шлюзе зарезал интернет, но он не отключил порт на коммутаторе, и мне всё также была доступна внутренняя сеть. Запустил LLDP на интерфейсе провайдера и увидел что со мной в одной сети находятся как минимум пять маршрутизаторов MikroTik. И логика была у меня такая:
По умолчания в RouterOS на первом порту отключен LLDP, а если я вижу это значит что-либо конфигурации была сброшена либо используется порт не ether1. Соответственно возможно, что на нём неправильно настроен firewall.
Так и получилось я на своём маршрутизаторе прописал адрес MikroTik первого из списка и у меня появился интернет, да с другого IP адреса, но этого достаточно. Сразу скажу, что на всех пяти MikroTik-ах которые я видел, и кстати до сих пор я наблюдаю в сети данные MikroTik c таким образом настроенным Firewall, что я в любой момент могу получить доступ в интернет через них.
Вот именно от таких ситуаций нам необходимо защититься.
И опять же мы будем использовать custom цепочку.
Первым правилом мы отправляем весь проходящий forward трафик с интерфейсов провайдеров в цепочку ISP-Forward.
add action=jump chain=forward in-interface-list=ISP jump-target=ISP-Forward
Следующие правила вам должны быть уже знакомы. Не буду повторять описание
add chain=ISP-Forward connection-state=established action=accept
add chain=ISP-Forward connection-state=related action=accept
add chain=ISP-Forward connection-state=untracked action=accept
add chain=ISP-Forward connection-state=invalid action=drop
Единственно, что необходимо уточнить, это то что в случае если вы используете BGP или асинхронную маршрутизацию. То вам необходимо разрешать трафик invalid. Но в большинстве случаев это не так.
Далее вы помните, что по типу исключения у нас остаётся только пакеты, которые имеют состояние new, и если подумать то такие пакеты могут проходить через маршрутизатор со стороны провайдера только если они попадают под процедуру изменения адреса назначения.
Поэтому нам необходимо разрешить пакеты new которые попадают под dst NAT.
add chain=ISP-Forward connection-nat-state=dstnat action=accept
И последний правилом мы закрываем доступ из вне всем отвальным пакетам.
add chain=ISP-Forward action=drop
Собственно всё.
Давайте взглянем на наши правила.

Соответственно, если вам необходимо разрешить подключаться к маршрутизатору, будь то по VPN или ещё как-то, вы всегда можете добавить правило в цепочку ISP-Input-Allow и не думать о порядке правил.
Я приведу итоговый результат немного отформатированный.
/ip firewall filter
add chain=input in-interface-list=ISP action=jump jump-target=ISP-Input
add chain=forward in-interface-list=ISP action=jump jump-target=ISP-Forward
add chain=ISP-Input connection-state=established action=accept
add chain=ISP-Input connection-state=related action=accept
add chain=ISP-Input connection-state=untracked action=accept
add chain=ISP-Input connection-state=invalid action=drop
add chain=ISP-Input jump-target=ISP-Input-Allow action=jump
add chain=ISP-Input action=drop
add chain=ISP-Forward connection-state=established action=accept
add chain=ISP-Forward connection-state=related action=accept
add chain=ISP-Forward connection-state=untracked action=accept
add chain=ISP-Forward connection-state=invalid action=drop
add chain=ISP-Forward connection-nat-state=dstnat action=accept
add chain=ISP-Forward action=drop
add chain=ISP-Input-Allow protocol=icmp action=accept
add chain=ISP-Input-Allow protocol=tcp dst-port=22 connection-nat-state=dstnat action=jump jump-target=SSH-Brute-force
add chain=ISP-Input-Allow dst-port=1701 protocol=udp action=accept
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-block action=drop
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-4 action=add-src-to-address-list address-list=SSH-Brute-force-block address-list-timeout=8h
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-3 action=add-src-to-address-list address-list=SSH-Brute-force-4 address-list-timeout=1m
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-2 action=add-src-to-address-list address-list=SSH-Brute-force-3 address-list-timeout=1m
add chain=SSH-Brute-force src-address-list=SSH-Brute-force-1 action=add-src-to-address-list address-list=SSH-Brute-force-2 address-list-timeout=1m
add chain=SSH-Brute-force action=add-src-to-address-list address-list=SSH-Brute-force-1 address-list-timeout=1m
add action=accept chain=SSH-Brute-force
/ip firewall nat
add action=redirect chain=dstnat dst-port=1024 in-interface-list=ISP protocol=tcp to-ports=22
На этом на сегодня всё, продолжение следует…
Поделиться
Обсуждение
Лицензия
Текст данной статьи распространяется под общедоступной лицензией CC BY-NC-ND 4.0, ознакомиться с тектом лицензии вы можете на данной странице.