Содержание статьи
INFO
Общие принципы безопасной настройки роутера и принципы оптимальной настройки файрвола ты можешь узнать в предыдущих статьях.
Унификация настроек
Если у тебя большая сеть с несколькими филиалами и в каждом из них по два роутера для отказоустойчивости, то правила лучше настроить так, чтобы их можно было легко развернуть на любой железке, независимо от количества и именования портов или типа подключения. Для соединения по PPPoE, например, WAN-интерфейсом будет pppoe-out1
, а для DHCP — ether1
. Если попытаться экспортировать конфиг файрвола с одного роутера на другой, ничего не выйдет, потому что у второго просто нет интерфейса pppoe-out1
. Или представь себе, что в одном филиале локальная сеть висит на ether9
, а в другом стоит роутер с пятью портами, из-за чего конфигурация девятого порта просто не встанет и вылетит с ошибкой.
Поэтому мы будем настраивать роутер так, чтобы конфиг можно было без проблем перенести на любой другой роутер. Это немного усложнит первоначальную настройку, но сэкономит кучу времени в будущем.
Мы уже рассматривали списки интерфейсов. Это фича для оперирования несколькими интерфейсами как одним. Создадим листы WAN и LAN, а затем добавим туда нужные интерфейсы. Теперь правила файрвола будем привязывать к интерфейс-листам, а не к отдельным интерфейсам. Перед экспортом правил на другой роутер просто создадим на нем нужные листы, и конфиг встанет без ошибок.
Обрати внимание, что для использования в файрволе нам нужны L3-интерфейсы, то есть те, на которых есть IP-адреса. Если ты получаешь интернет по PPPoE, то в WAN-лист надо добавить именно его. Если IP локальной сети прописан на бридже или VLAN'е, то и в лист LAN нужно добавить их, а не физические интерфейсы. Если включить в список и логический, и физический интерфейс, ничего страшного произойти не должно, но это нужно будет учитывать в конфигурации.
Но это еще не все. Понятно, что в каждом филиале у нас будет своя подсеть LAN: где-то 192.168.10.0/24, где-то 192.168.11.0/24. Чтобы не путаться с этими значениями и не менять конфиг при переносе с одного роутера на другой, оперировать будем не адресами и подсетями, а списками адресов. На каждом роутере создаем список LAN и дальше работаем только с ним.
В прошлый раз мы создавали адрес-лист MGMT, в котором открывали доступ к управлению роутером только с определенных адресов. А еще раньше рассматривали решение Port Knocking, которое предоставляет доступ к управлению, только если со стороны клиента выполнить секретные манипуляции. Для доступа к роутеру из доверенной сети (LAN) вполне подходит вариант с адрес-листом, а для доступа снаружи — Port Knocking. Было бы хорошо совместить эти варианты в нашей конфигурации. Еще будет удобно разделить цепочку input на две части: input со стороны интернета и input со стороны локалки. Тогда можно применять разные политики фильтрации к разным сегментам сети. В этом нам помогут пользовательские цепочки.
Все, что пришло снаружи, перекидываем в новую цепочку WAN_INPUT
. Все, что изнутри, — в LAN_INPUT
:
/ip firewall filter
add action=jump chain=input in-interface-list=WAN jump-target=WAN_INPUT
add action=jump chain=input in-interface-list=LAN jump-target=LAN_INPUT
Теперь политики фильтрации будут разными для разного источника трафика. Для внешнего трафика будем использовать цепочку WAN_INPUT
и более жесткие ограничения, для внутреннего — LAN_INPUT
и правила попроще. Цепочка input
нам больше не нужна, теперь мы все будем делать в новых цепочках. Причем указывать интерфейсы или списки интерфейсов в правилах больше не понадобится. Однако этот подход может использоваться в сложных решениях, например когда у тебя два провайдера с разными политиками фильтрации или локалка поделена на разные VLAN. Но об этом позже.
В статье о безопасной настройке роутера мы настраивали Port Knocking для доступа к управлению роутером. Ограничивать таким образом доступ изнутри локальной сети — излишество. Поэтому поменяем в правилах цепочку с input
на WAN_INPUT
. Изнутри сети разрешим доступ к WinBox только с нужных адресов: мы уже делали это в статье про основы файрвола. Оставим в правиле только порт WinBox — TCP 8291
. А для SSH разрешим подключения из всей нашей сети, но предотвратим возможность брутфорса (да, изнутри сети тоже может произойти брутфорс SSH, потому что отсутствие троянов в ней не гарантировано).
add action=drop chain=LAN_INPUT comment="drop ssh brute forcers" src-address-list=ssh_blacklist
add action=add-src-to-address-list address-list=ssh_blacklist address-list-timeout=1w3d chain=LAN_INPUT connection-state=new dst-port=22 protocol=tcp src-address-list=ssh_stage3
add action=add-src-to-address-list address-list=ssh_stage3 address-list-timeout=1m chain=LAN_INPUT connection-state=new dst-port=22 protocol=tcp src-address-list=ssh_stage2
add action=add-src-to-address-list address-list=ssh_stage2 address-list-timeout=1m chain=LAN_INPUT connection-state=new dst-port=22 protocol=tcp src-address-list=ssh_stage1
add action=add-src-to-address-list address-list=ssh_stage1 address-list-timeout=1m chain=LAN_INPUT connection-state=new dst-port=22 protocol=tcp src-address-list=!ssh_open
add action=accept chain=LAN_INPUT dst-port=22 protocol=tcp
Тут применяется механизм динамических адрес-листов с тайм-аутами. Мы рассматривали их в статье «Защищаем MikroTik. Хитрости безопасной настройки роутера». При первой попытке подключения пакет обработается правилом 5, и адрес хакера попадет в адрес-лист ssh_stage1
. Вторая попытка подключения обработается правилом 4 и добавит брутфорсера в лист ssh_stage2
. И так далее вплоть до листа ssh_blacklist
, где адрес будет храниться десять дней, а весь трафик, идущий с адресов из этого списка, будет дропаться.
В прошлой статье мы создавали правила, разрешающие коннекты established, related и запрещающие invalid. Давай продублируем эти правила и перенесем их в новые цепочки, а из input
удалим. В результате мы получим четыре правила вместо двух. На прохождение трафика это не повлияет, зато позволит видеть статистику по трафику с разных сторон. В правиле с established, related поставь галочку untracked
. Чуть позже объясню, зачем она. Думаю, адаптировать остальные правила под новую логику не составит труда. В конце каждой цепочки не забудь указать правило дропа.
Две цепочки позволят нам уменьшить количество переходов трафика по правилам, а значит, и немного снизить нагрузку на CPU. Счетчики в разных цепочках дадут возможность увидеть чуть более детальную статистику трафика. Хоть правил и стало больше, но они не применяются ко всему объему трафика: при первом джампе весь трафик будет обрабатываться уже новой цепочкой и в другую никогда не попадет. Подобный подход также упрощает поддержку за счет того, что по названию цепочки сразу видно, что это за трафик и откуда он идет. Можно для разных типов трафика создавать свои цепочки, например отдельную цепочку для management-трафика. За возврат трафика в родительскую цепочку отвечает action return
.
Защищаемся от атак
До сих пор мы рассматривали правила файрвола, позволяющие обрабатывать трафик по простым признакам: интерфейсу, адресу, порту. Но файрвол гораздо более гибкий инструмент, с его помощью можно строить сложную логику для противодействия разным типам атак.
Есть зарезервированные адреса, которые не используются в интернете. Они называются «богон-адресами». Отсечем пакеты с таких адресов:
/ip firewall address-list
add address=0.0.0.0/8 comment="Self-Identification [RFC 3330]" list=Bogon
add address=10.0.0.0/8 comment="Private[RFC 1918] - CLASS A" list=Bogon
add address=127.0.0.0/16 comment="Loopback [RFC 3330]" list=Bogon
add address=169.254.0.0/16 comment="Link Local [RFC 3330]" list=Bogon
add address=172.16.0.0/12 comment="Private[RFC 1918] - CLASS B" list=Bogon
add address=192.168.0.0/16 comment="Private[RFC 1918] - CLASS C" list=Bogon
add address=192.0.2.0/24 comment="Reserved - IANA - TestNet1" list=Bogon
add address=192.88.99.0/24 comment="6to4 Relay Anycast [RFC 3068]" list=Bogon
add address=198.18.0.0/15 comment="NIDB Testing" list=Bogon
add address=198.51.100.0/24 comment="Reserved - IANA - TestNet2" list=Bogon
add address=203.0.113.0/24 comment="Reserved - IANA - TestNet3" list=Bogon
add address=224.0.0.0/4 comment="MC, Class D, IANA" list=Bogon
Мы ожидаем пакеты только с юникаст-адресов, поэтому запретим все, кроме них.
Port Scan Detect — функция, позволяющая обнаружить сканер портов. Как она работает? Портам задается некий условный вес — Weight. Причем для системных портов (до 1024-го) весовой коэффициент низкий (Low ports), а для остальных — высокий (High ports). Если в течение времени Delay Threshold от одного хоста на роутер прилетят пакеты на порты, сумма весов которых окажется больше, чем Weight Threshold, то адрес отправителя будет добавлен в блек-лист. В нашем примере, если с одного хоста за три секунды поступят десять пакетов на порты до 1024-го (общий вес 10 * 2 = 20) и двадцать пакетов на порты выше 1024-го (20 * 1 = 20), общий их вес составит 40. Обрати внимание, что Port Scan Detect работает только для TCP- или UDP-трафика.
Один из самых распространенных видов атак — это атака на отказ в обслуживании, или DDoS. Защититься от нее своими силами практически нереально. Но с помощью простого правила можно отсечь самые простые попытки атаки. Находим хост, который насоздавал к нам больше 100 сессий, и добавляем его в блек-лист. В этом правиле обязательно нужно использовать параметр connection-state=new
. Но мы ведь уже разрешили все established, related и untracked, а invalid дропнули, поэтому сюда дойдут только пакеты new
. Оставлять или нет этот флажок в правиле — твое дело. Отмечу, что с помощью этой же фичи можно выявлять в своей сети торрентокачальщиков.
ICMP — один из важных протоколов в любой сети. Многие админы любят блокировать его, но это очень плохой подход. Именно ICMP позволяет работать трассировке, указывать на недоступность UDP-портов, отправлять разные служебные сообщения. И если запретить его полностью, можно наловить кучу багов. У каждого сообщения ICMP свое предназначение, и уже по этому параметру нетрудно понять, имеет ли смысл разрешить какие-то типы ICMP изнутри сети или снаружи. Например:
- ICMP Echo Request — наш любимый пинг, имеет тип 8, код 0;
- ICMP Echo Reply — ответ на пинг, тип 0, код 0;
- Destination Unreachable — узел недоступен, тип 3 и коды 0–15 в зависимости от причины недоступности:
- 0 — сеть недоступна;
- 1 — хост недоступен;
- 2 — протокол недоступен;
- 3 — порт недоступен;
- 4 — необходима фрагментация пакета, но она запрещена (стоит флаг DF — Don’t Fragment).
Остальное легко найти в интернете, а лучше почитать RFC 792.
Создадим цепочку ICMP и отправим в нее весь ICMP-трафик (можно создать две цепочки: для LAN и WAN — и настроить разные политики). Разрешаем только нужные типы сообщений и ограничиваем обработку пятью пакетами в секунду:
/ip firewall filter
add action=jump chain=WAN_INPUT jump-target=ICMP protocol=icmp
add action=jump chain=LAN_INPUT jump-target=ICMP protocol=icmp
add action=accept chain=ICMP comment="Allow Echo Reply (0:0-255), Limit 5pps" icmp-options=0:0-255 limit=5,5:packet protocol=icmp
add action=accept chain=ICMP comment="ICMP - Allow Destination Unreachable (3:0-255), Limit 5pps" icmp-options=3:0-255 limit=5,5:packet protocol=icmp
add action=accept chain=ICMP comment="ICMP - Allow Source Quench (4:0), Limit 5pps" icmp-options=4:0-255 limit=5,5:packet protocol=icmp
add action=accept chain=ICMP comment="ICMP - Allow Echo Request (8:0), Limit 5pps" icmp-options=8:0-255 limit=5,5:packet protocol=icmp
add action=accept chain=ICMP comment="ICMP - Allow Time Exceeded (11:0), Limit 5pps" icmp-options=11:0-255 limit=5,5:packet protocol=icmp
add action=accept chain=ICMP comment="ICMP - Allow Parameter Bar (12:0), Limit 5pps" icmp-options=12:0-255 limit=5,5:packet protocol=icmp
add action=drop chain=ICMP comment="ICMP - Drop All Others" protocol=icmp
TCP тоже поддерживает кучу флагов, часть которых не может содержаться в одном пакете. Комбинации этих флагов часто используются сканерами портов, чтобы пробить плохо настроенную защиту. Сделаем отдельную цепочку для TCP и дропнем подобные «подозрительные» пакеты:
/ip firewall filter
add action=jump chain=WAN_INPUT comment="Invalid TCP" jump-target=invalid_tcp protocol=tcp
add action=jump chain=LAN_INPUT comment="Invalid TCP" jump-target=invalid_tcp protocol=tcp
add action=jump chain=forward comment="Invalid TCP" jump-target=invalid_tcp protocol=tcp
add action=drop chain=invalid_tcp comment="Invalid TCP - !(FIN/SYN/RST/ACK)" protocol=tcp tcp-flags=!fin,!syn,!rst,!ack
add action=drop chain=invalid_tcp comment="Invalid TCP - FIN/SYN" protocol=tcp tcp-flags=fin,syn
add action=drop chain=invalid_tcp comment="Invalid TCP - FIN/RST" protocol=tcp tcp-flags=fin,rst
add action=drop chain=invalid_tcp comment="Invalid TCP - FIN/!ACK" protocol=tcp tcp-flags=fin,!ack
add action=drop chain=invalid_tcp comment="Invalid TCP - FIN/URG" protocol=tcp tcp-flags=fin,urg
add action=drop chain=invalid_tcp comment="Invalid TCP - SYN/RST" protocol=tcp tcp-flags=syn,rst
add action=drop chain=invalid_tcp comment="Invalid TCP - RST/URG" protocol=tcp tcp-flags=rst,urg
add action=drop chain=invalid_tcp comment="Invalid TCP - Source Port 0" protocol=tcp src-port=0
add action=drop chain=invalid_tcp comment="Invalid TCP - Destination Port 0" dst-port=0 protocol=tcp
То же самое для UDP:
add action=drop chain=invalid_udp comment="Invalid UDP - Source Port 0" protocol=udp src-port=0
add action=drop chain=invalid_udp comment="Invalid UDP - Destination Port 0" dst-port=0 protocol=udp
Цепочка Forward
До сих пор мы в основном смотрели на трафик, прилетевший в input-цепочку, а дальше по каким-то признакам направляли его в разные цепочки. Но весь этот трафик предназначался самому роутеру. Цепочку output используют редко, но ты можешь отфильтровать в ней, например, ICMP-ответы от роутера или IPsec-трафик. Понятно, что большая часть трафика будет попадать в forward — ведь на то он и роутер, чтобы перенаправлять пакеты из одной сети (локалка) в другую (интернет или второй VLAN локалки). И в этой цепочке мы будем управлять трафиком пользователей.
Я не стану детально рассказывать о том, что надо разрешить или запретить, — об основных приемах настройки и так уже написано несколько статей и есть куча примеров в интернете. Рассмотрим более интересный кейс: репутацию сети.
В интернете есть сервисы, содержащие списки спамеров, ддосеров, распространителей нелегального контента. Если на машины в твоей сети попал троян-спамер, то ты тоже окажешься в этих списках. Через какое-то время письма от любого клиента изнутри сети начнут попадать в спам у всех получателей, потом ты будешь добавлен в публичные блек-листы и у пользователей исчезнет доступ ко многим ресурсам. В том числе к сетям партнеров, админы которых пользуются такими списками, чтобы запретить доступ потенциальным вредителям. Представь, что произойдет с твоей премией, когда письмо с многомиллионным контрактом от твоего шефа упадет у контрагента в папку «Спам».
Попробуем защитить свою премию. Для этого нужно понять, по какому поводу нас могут внести в списки. Причин этому несколько:
- мы часть DoS- или иного ботнета;
- мы рассылаем спам;
- с наших адресов брутфорсят чужие сервисы;
- мы нарушаем авторские права (раздаем торренты).
Некоторые читатели этой статьи вполне могли участвовать в DDoS-ботнете, сами того не осознавая. Атаки UDP Amplification основаны на некорректных настройках сервисов, когда можно обратиться к ним с просьбой узнать что-то у другого сервера. Например, к нам может прилететь DNS-запрос с просьбой отрезолвить адрес жертвы. И таких, как мы, миллионы. Когда к жертве поступит миллион пакетов в секунду, она не обрадуется, а мы увидим загрузку CPU под 100%, жуткие тормоза и однажды окажемся в блек-листе. Такая же схема работает и с другими UDP-сервисами, например NTP. Вывод простой: блокируй трафик к этим сервисам снаружи. Но это все еще про INPUT.
Не только роутер может быть частью такого ботнета, но и машины внутри сети. Для детекта таких хостов воспользуемся уже известной фичей connection limit
.
/ip firewall filter
add action=add-src-to-address-list address-list=dns-flood address-list-timeout=none-dynamic chain=forward comment="DNS Flood" connection-limit=100,32 dst-port=53 in-interface-list=LAN protocol=udp
add action=add-src-to-address-list address-list=smb-flood address-list-timeout=none-dynamic chain=forward comment="SMB Flood" connection-limit=100,32 dst-port=445 in-interface-list=LAN protocol=tcp
add action=add-src-to-address-list address-list=telnet-flood address-list-timeout=none-dynamic chain=forward comment="Telnet Flood" connection-limit=20,32 dst-port=23 in-interface-list=LAN protocol=tcp
add action=add-src-to-address-list address-list=ssh-flood address-list-timeout=none-dynamic chain=forward comment="SSH Flood" connection-limit=20,32 dst-port=22 in-interface-list=LAN protocol=tcp
add action=add-src-to-address-list address-list=snpp-flood address-list-timeout=none-dynamic chain=forward comment="SNPP Flood" connection-limit=20,32 dst-port=444 in-interface-list=LAN protocol=tcp
add action=add-src-to-address-list address-list=msf-indication address-list-timeout=none-dynamic chain=forward comment="Metasploit Indication" connection-limit=20,32 dst-port=4444 in-interface-list=LAN protocol=tcp
Слишком «толстые» потоки тоже могут вызывать подозрения. Залогируем их:
add action=log chain=forward comment="Abnormal Traffic" connection-bytes=80000000 in-interface-list=LAN log-prefix=Abnormal-Traffic
По порту назначения можно определить, к какому сервису обращаются хосты изнутри нашей сети. И если это общеизвестный порт, например СУБД, а все наши базы расположены внутри периметра, логично предположить, что сотни пакетов в секунду к этому порту в интернете с компьютера бухгалтера — не простая ошибка и не личный интерес самого бухгалтера. Дропаем подозрительные пакеты и возвращаемся в родительскую цепочку (последнее правило):
add action=jump chain=forward comment="Jump to Virus Chain" disabled=no jump-target=Virus
add action=drop chain=Virus comment="Drop Blaster Worm" disabled=no dst-port=135-139 protocol=tcp
add action=drop chain=Virus comment="Drop Blaster Worm" disabled=no dst-port=445 protocol=tcp
add action=drop chain=Virus comment="Drop Blaster Worm" disabled=no dst-port=445 protocol=udp
add action=drop chain=Virus comment="Drop Messenger Worm" disabled=no dst-port=135-139 protocol=udp
add action=drop chain=Virus comment=Conficker disabled=no dst-port=593 protocol=tcp
add action=drop chain=Virus comment=Worm disabled=no dst-port=1024-1030 protocol=tcp
add action=drop chain=Virus comment="ndm requester" disabled=no dst-port=1363 protocol=tcp
add action=drop chain=Virus comment="ndm server" disabled=no dst-port=1364 protocol=tcp
add action=drop chain=Virus comment="screen cast" disabled=no dst-port=1368 protocol=tcp
add action=drop chain=Virus comment=hromgrafx disabled=no dst-port=1373 protocol=tcp
add action=drop chain=Virus comment="Drop MyDoom" disabled=no dst-port=1080 protocol=tcp
add action=drop chain=Virus comment=cichlid disabled=no dst-port=1377 protocol=tcp
add action=drop chain=Virus comment=Worm disabled=no dst-port=1433-1434 protocol=tcp
add action=drop chain=Virus comment="Drop Dumaru.Y" disabled=no dst-port=2283 protocol=tcp
add action=drop chain=Virus comment="Drop Beagle" disabled=no dst-port=2535 protocol=tcp
add action=drop chain=Virus comment="Drop Beagle.C-K" disabled=no dst-port=2745 protocol=tcp
add action=drop chain=Virus comment="Drop MyDoom" disabled=no dst-port=3127-3128 protocol=tcp
add action=drop chain=Virus comment="Drop Backdoor OptixPro" disabled=no dst-port=3410 protocol=tcp
add action=drop chain=Virus comment="Drop Sasser" disabled=no dst-port=5554 protocol=tcp
add action=drop chain=Virus comment=Worm disabled=no dst-port=4444 protocol=tcp
add action=drop chain=Virus comment=Worm disabled=no dst-port=4444 protocol=udp
add action=drop chain=Virus comment="Drop Beagle.B" disabled=no dst-port=8866 protocol=tcp
add action=drop chain=Virus comment="Drop Dabber.A-B" disabled=no dst-port=9898 protocol=tcp
add action=drop chain=Virus comment="Drop Dumaru.Y" disabled=no dst-port=10000 protocol=tcp
add action=drop chain=Virus comment="Drop MyDoom.B" disabled=no dst-port=10080 protocol=tcp
add action=drop chain=Virus comment="Drop NetBus" disabled=no dst-port=12345 protocol=tcp
add action=drop chain=Virus comment="Drop Kuang2" disabled=no dst-port=17300 protocol=tcp
add action=drop chain=Virus comment="Drop SubSeven" disabled=no dst-port=27374 protocol=tcp
add action=drop chain=Virus comment="Drop PhatBot, Agobot, Gaobot" disabled=no dst-port=65506 protocol=tcp
add action=drop chain=Virus comment="Drop MemCached flood" disabled=no dst-port=11211 protocol=udp
add action=return chain=Virus comment="Return From Virus Chain" disabled=no
Заключение
Мы рассмотрели более продвинутые методы настройки файрвола. Эту статью не нужно воспринимать как инструкцию по настройке: у каждой сети свои особенности и сервисы. Роутеры у всех тоже разные — у кого-то он спокойно обработает тысячи неоптимизированных правил файрвола, для других сотня правил будет обрабатываться с трудом. Поэтому подходи к настройке файрвола с умом.
В две статьи всё не вместишь, и мы не затронули еще несколько больших тем: таблицы NAT, RAW, IPv6 Firewall, Bridge Firewall, фильтрацию по контенту, определение типа трафика по его содержимому (когда мы меняем порт у HTTP, а файрвол все равно понимает, что внутри HTTP), проксирование трафика.
Все эти темы рассматриваются в официальном обучающем курсе MikroTik — MikroTik Certified Traffic Control Engineer. Но чтобы на него попасть, нужно пройти курс MikroTik Certified Network Associate, где изучаются общие принципы настройки роутера и работа TCP/IP.