Введение в межсетевые экраны
МЭ — обработка сетевого трафика (вообще говоря, на всех уровнях):
- ограничение
- перенаправление
- преобразование
- учёт (в первую очередь для последующего анализа)
МЭ интерфейсного уровня
в Linux:
TODO пример, если останется время
МЭ сетевого и транспортного уровней
Обычно оба уровня, потому что задачи МЭ общие.
В Linux:
nftables (хорошая статья на Арчевики и её перевод)
Попробуем nftables.
Принцип: https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks:
- Ничего страшного, нам нужна только зелёненькая часть ☺
- Обратите внимание на то, что она называется «IP Layer», но она же и транспортная
- Стрелочки — это путь пакета сквозь nftables
- «Local Process» наверху — это получатель и отправитель
Правила, хуки, цепочки, таблицы
- Проходя по стрелочкам, пакет, в зависимости от принятия решений (обозначены ромбами) проходит контрольные точки (обозначены зелёными боксами и для уровня TCP/IP называютюся «Hook», а для интерфейсного — «Bridge»)
Кто придумал такую терминологию, был большой оригинал ☹
В процессе прохождения пакет обрабатывается правилами
Однотипные правила, решающие общую подзадачу, объединяются в цепочки
Типы цепочек: nat (преобразование), filter (фильтрация), route (перенаправление)
- Цепочка может быть «закреплена» на какой-нибудь контрольной точке (или «зацеплена за крюк») — это базовая цепочка.
- Проходя через контрольную точку, пакет «перепрыгивает» на базовую цепочку: по очереди обрабатывается правилами из неё.
- Если при контрольной точке имеется несколько цепочек, сравнивается их приоритет,
- Пакет из цепочки может не выйти — если его выбросят или попросят уйти (goto) на конкретную цепочку, указанную в правиле
- В противном случае пакет доходит до конца цепочки (или правила «покинуть цепочку»), и обработка пакета продолжается в том месте, откуда он перепрыгнул на неё.
- …например, переход в следующую базовую цепочку или по стрелочке на следующую контрольную точку
Цепочки и данные к ним группируются в таблицы — наборы правил для решения определённых пользовательских задач. Единственная роль таблицы, помимо информационной — её можно целиком удалить или заменить.
Имена таблиц и цепочек могут быть любыми.
Типы данных
В справочнике:
Работа nftables — это интерпретация некоторого байт-кода, в который компилируются правила
- Простая арифметика
Множества, в том числе IP-адресов с диапазонами и с исключением элементов по тайм-ауту (например, для временной блокировки)
Словари (map) вида «данные:данные»
Словари вердиктов (vmap) вида «данные:команда»
- …
Наборы данных можно изменять без изменения правил в цепочке (а ещё в них логарифмический поиск)
Кстати, есть ещё «ARP Level» — потому что он межуровневый и там свои задачи.
Высокоуровневые оболочки
Это необъятная тема, со спецификой каждого инструмента
Firewalld — в т. ч. интерактив с пользователем а-ля windows
Shorewall — планирование целой сети
- …тысячи их
Использование NFTables
Площадка: client[12] → router → srv
для простоты запустим avahi
Примеры из Арчевики
Команды утилиты nft sudo cancer detected
nft -a list ruleset
Source NAT
Упростим NAT из прошлой лекции:
table ip masq { chain do_masq { type nat hook postrouting priority srcnat; policy accept; oifname eth0 masquerade } }
Фильтрация портов
Разрешим принимать TCP только на определённые порты, остальное запретим
nft add chain inet filter restrict "{ type filter hook input priority filter; policy drop; }"
цепочка привязана к input, находится в имеющейся по умолчанию таблице filter
- всё сдохло
nft add rule inet filter restrict "tcp dport ssh accept"
- mDNS не работает, ssh работает
nft add rule inet filter restrict "udp dport 5353 accept"
- mDNS работает
Посмотрим: nft -a list ruleset
Удалим правило: nft delete rule inet filter restrict handle №
Удалим всю цепочку nft delete chain inet filter restrict
Проброс портов
- Создадим таблицу:
nft add table ip forwarder
Создадим цепочку, привязанную к prerouting:
nft add chain ip forwarder ssh "{ type nat hook prerouting priority dstnat; }"
Добавим правило dnat:
nft add rule ip forwarder ssh "tcp dport 2222 dnat to адрес_client:22"
Проверим: ssh на 2222 порт должен перекидывать соединение
Посмотрим, что вышло: nft list ruleset
Ограничение частоты соединений
Отказ при превышении лимитов по частоте подключения ( это не шейпинг)
Простой вариант: собственно ограничение частоты соединений
В цепочку, привязанную к input, вставим правило «сбрасывать пакеты tcp соединения на 22-й порт, если их больше. чем 15 в минуту»
[root@srv ~]# nft add table ip limiter [root@srv ~]# nft add chain ip limiter sshstop '{ type filter hook input priority filter; }' [root@srv ~]# nft add rule ip limiter sshstop 'tcp dport ssh ct state new limit rate over 15/minute drop'
- На другом хосте запустим флудилку:
[root@client ~]# for i in `seq 50`; do echo $i; netcat srv.local 22 < /dev/null; done
- Попытки ssh-соединений будут подвисать, пока среднее не опустится ниже ограничения, потом ещё сколько-то происходить, потом опять подвисать, и т. д.
Сложный вариант со списком временно забаненных хостов. Таблицу создавать не будем (хотя бы для того, чтобы показать, как это неудобно ☺): впишем всё прямо в имеющиеся таблицу filter, а правила — в её цепочку input (которая висит на контрольной точке input)
- Зададим множество IP-адресов:
nft add set inet filter over1234 "{type ipv4_addr; flags timeout;}"
Напишем правило: «если conntrack отследил установление соединения на порт 1234, и этих соединений более 5 в секунду, добавим адрес отправителя в множество over1234 и живёт там 6 секунд»:
nft add rule inet filter input "ct state new tcp dport 1234 meter flood { ip saddr limit rate over 5/second } add @over1234 { ip saddr timeout 6s }"
Добавим счётчик stat (по умолчанию он считает пакеты и байты)
nft add counter inet filter stat
Напишем правило: «все пакеты от хостов из over1234 выбрасывать, их содержимое считать в stat»
nft add rule inet filter input "ip saddr @over1234 counter name stat drop"
Запустим на этом хосте вот такой сетевой сервис (он слушает на 1234 порту и выводит клиенту содержимое счётчика stat)
socat TCP-LISTEN:1234,reuseaddr,fork EXEC:"nft list counter inet filter stat"
- На другом хосте запустим флудилку:
for n in `seq 10`; do echo $n; netcat адрес_хоста 1234 < /dev/null; done
Она довольно быстро зависнет, а через 6 секунд продолжится. Если её прибить, даже ping не заработает (выбрасываются любые пакеты).
Посмотрим, что вышло: nft list ruleset
Удалять придётся через handle (так бы удалили таблицу и дело с концом)
…
Для того, чтобы настройки стали постоянными, их надо складывать в /etc/nftables/nftables.nft, или include-ить оттуда файлы из того же каталога, куда скопипастить фрагменты выдачи nft list ruleset.
МЭ прикладного уровня
Это какого? ☺
- Для каждого протокола правила свои
- Например, антиспам, DPI, родительский контроль и т. п.
Пример проекта Layer 7 firewall: Netify
формально OpenSource, но… найдите на сайте ссылку на исходники
Спойлер:
TODO упомянуть https://github.com/crowdsecurity/crowdsec
Д/З
Образ не изменился
Задание 10
TODO задать строгий адрес клиента
Воспроизвести (модифицированный) пример из лекции:
client → router → server
«выход в интернет» должен работать на всех трёх машинах через server
DNS разрешается настраивать вручную при помощи 8.8.8.8 в /etc/resolv.conf
Если ваш провайдер не даёт доступа к 8.8.8.8, впишите адрес DNS-сервера этого вредного провайдера.
Все сетевые настройки выполняются перманентно с помощью sytemd-networkd
(маршрут по умолчанию, маршрут с srv на client и обратно)
SNAT на srv должен быть настроен перманентно с помощью /etc/nftables/nftables.nft
Настроить на router перманентно с помощью /etc/nftables/nftables.nft (руками вводить не надо):
Проброс порта 2222 → client:22 (подключение с server к router на порт 2222 должно приводить к подключению к client на 22)
Ограничение по количеству входящих TCP-соединений к server по ssh за определённый период времени с записью нарушителей в счётчик
- как в «сложном примере» из лекции,
но поскольку обрабатываются не принятые, а пересылаемые пакеты, точка привязки (hook) должна быть другая
Настройка в отчёт не входит.
Отчёт (вместо курсива могут быть числа, IP-адреса и т. п.):
report 10 server:
networkctl status eth0
networkctl status eth1
nft list ruleset
ssh router -p 2222 (должен привести к входу на client!)
выполнить там ip a
report 10 router:
networkctl status eth1
networkctl status eth2
nft list ruleset
date | netcat ya.ru 80 (должно показать 414)
report 10 client:
date | netcat ya.ru 80 (должно показать 414)
for i in $(seq число ); do date | netcat server 22; done
- Должен отработать в рамках ограничения (сколько положено по квоте), а дальше зависнуть
router (продолжение)
Посмотреть множество нарушителей квоты по подключениям (там должен быть client)
Остановить зависшие команды на client и server
Три отчёта (названия сохранить, должно быть: report.10.server, report.10.router и report.10.client) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
В теме письма должно встречаться слово LinuxNetwork2024