Політики Firewall в GNU/Linux (Частина 8)

26 березня 2024 2 хвилин Автор: Lady Liberty

Обговорюється, як керувати та застосовувати політики брандмауера в інфраструктурі GNU/Linux, особливо зосереджуючись на контролі дозволів доступу між різними мережевими зонами та пристроями. Надається детальний посібник із налаштування правил брандмауера, щоб увімкнути певні з’єднання, наприклад, дозволити хосту переходу в одній VLAN підключатися до сервера в іншій через SSH, налаштувавши необхідні команди брандмауера. Також охоплюється використання брандмауера для цих конфігурацій, наголошуючи на важливості розуміння цих політик для ефективного адміністрування та безпеки мережі.

Політики Firewall

Минулого разу ми поділили нашу мережу на зони, тим самим перекривши всі доступи. Сьогодні ми розберемося, як точково видавати ці доступи. У реальній інфраструктурі цим зазвичай займається відділ інформаційної безпеки, але ми теж недарма це розуміємо. Зазвичай, коли адміністратор налаштовує та пов’язує якісь сервери у різних зонах, він має звернутися до відділу безпеки та повідомити, що йому потрібно. Мовляв, маємо джампхост у другій лані з IP 10.0.2.101 і потрібно, щоб він міг підключатися до сервера1 за адресою 10.0.5.101 і по порту 22. Тобто. Випрошувати доступи на файрволі – це стандартна процедура для адміністратора. І щоб закріпити це у себе в голові та розуміти, коли це потрібно, а коли ні – ми самі будемо за потребою прописувати ці правила. Так, у реальній інфраструктурі ніхто це не робить через firewalld, але нам головне зрозуміти саму ідею, навіщо і як це робити. А цей інструмент чи інший – абсолютно неважливо.

Сьогодні ми будемо працювати з роутером 1 і 3. Минулого разу ми заборонили з jumphost-а підключатися до роутера1:

firewall-cmd --list-all --zone=dmz

І щоб не налаштовувати все через консоль, тимчасово дозволимо ssh:

firewall-cmd --add-service=ssh --zone=dmz

Стартанем ssh-агент:

eval $(ssh-agent)

додамо ключі:

ssh-add .ssh/jumphost .ssh/servers

І підрубаємося до роутера:

ssh router1

Минулого разу на роутері 3 ми створили зону routers, а на роутері 1 все залишилося у public зоні:

sudo firewall-cmd --list-all

Давайте це виправимо. Для початку створимо зону routers:

sudo firewall-cmd --new-zone=routers --permanent

Перемістимо в неї інтерфейс, який в одній мережі з роутером 3:

sudo firewall-cmd --change-interface=team0 --zone=routers --permanent

Додамо до цієї зони ssh, щоб ми могли з роутера 3 підключатися до роутера 1:

sudo firewall-cmd --add-service=ssh --zone=routers --permanent

Тому що з джампхосту не можна, інакше тільки через консоль. Перезапустимо файрвол і перевіримо нову зону:

sudo firewall-cmd --reload
sudo firewall-cmd --list-all --zone=routers

Все як і має бути.

Поки що не забув. Нещодавно ми на роутері1 прописали 3 маршрути:

ip ro sh

3, 4 та 5 мережі. Але якщо у нас кількість мереж постійно зростатиме, щоб не забувати їх додавати, давайте поміняємо підхід. Приберемо ці 3 мережі:

sudo nmcli connection modify team -ipv4.routes "10.0.3.0/24 10.0.1.254"
sudo nmcli connection modify team -ipv4.routes "10.0.4.0/24 10.0.1.254"
sudo nmcli connection modify team -ipv4.routes "10.0.5.0/24 10.0.1.254"

і замість них пропишемо всю підмережу 10.0.0.0/8 – сюди входить все від 10.0.0.0 до 10.255.255.255.

sudo nmcli connection modify team +ipv4.routes "10.0.0.0/8 10.0.1.254"

Потім піднімемо профіль і перевіримо таблицю маршрутизації:

sudo nmcli connection up team
ip ro sh

Тепер все, що стосується локальної мережі, пересилатиметься на третій роутер.

Давайте уявімо схему підключення jumphost-а до server1. Спочатку пакет йде від jumphost-а до router1. Для router1 jumphost знаходиться в зоні DMZ. Далі router1 передає пакет на router3. Для router1 router3 знаходиться в зоні routers. Теж саме для router3 – router1 знаходиться в зоні routers.

Що стосується router3, у нашій схемі зараз трафік із DMZ зони, щоб потрапити у внутрішню мережу, повинен буде проходити спочатку через router1, і лише потім через роутер3. А це означає, що ми переганятимемо зайвий трафік через роутер1. Тому давайте краще додамо до роутеру3 другий влан, щоб пристрої з DMZ безпосередньо проходили через роутер3.

На роутері 3 створив новий влан інтерфейс з адресою 10.0.2.254 і додав його в зону DMZ.

На самому jumphost-і, щоб він направляв усі пакети у внутрішню мережу через адресу третього роутера, пропишемо новий маршрут:

sudo nmcli connection modify team +ipv4.routes "10.0.0.0/8 10.0.2.254"

Потім піднімемо інтерфейс і перевіримо таблицю маршрутизації:

sudo nmcli connection up team
ip ro sh

Тут бачимо, що це пакети, які у мережу 10.0.0.0/8 проходитимуть через роутер3. А всі інші адреси – через роутер 1.

Тепер підключення від jumphost-а на сервер виглядає простіше – лише роутер3. Jumphost для роутера3 знаходиться у зоні DMZ, а сервер1 у зоні management. Точніше у двох зонах – servers та management, але нас зараз цікавить лише друга зона.

Підключимося до сервера1. До нього по ssh можна підрубатися тільки з 5 волана:

ip a

А він у нас на інтерфейсі ens5. Давайте подивимося tcpdump на цьому інтерфейсі:

tcpdump -i ens5

Тепер йдемо на jumphost і намагаємось пінганути:

ping 10.0.5.101

Пінг немає. Але справа не у файрволі, він у нас усі пінги за замовчуванням дозволяє. Також не виходить підключитися через ssh:

ssh 10.0.5.101

Але це ще зрозуміло, тут справа у файрволі. До нього ми ще прийдемо, а поки що спробуємо розібратися, чому server1 не пінгується.

Ідемо і дивимось tcpdump. Як бачите, пакетів по ssh не було, але пінги приходили. Але на них не було відповіді. Чому?

Є одна особливість, коли у вас в системі кілька IP-адрес, як на нашому сервері1. У нього дві адреси – 10.0.4.101 та 10.0.5.101. А ось default gateway всього 1 – 10.0.4.1. І ось уявіть – джампхост посилає пінг на адресу 10.0.5.101. Сервер1 повинен відповісти на адресу 10.0.2.101. Але в нього в таблиці маршрутизації сказано, що ця адреса доступна за адресою 10.0.4.1 – а значить, відповідь треба посилати з іншого інтерфейсу, на якому IP – 10.0.4.101. Тобто. пакет приходить із одного інтерфейсу, а відповісти треба з іншого. З одного боку, ми могли б на адресу 10.0.2.101 прописати маршрут через 10.0.5.1. Але тоді виникла б зворотна проблема – якщо запит буде приходити на 4.101, то відповідь надсилатиметься з 5.101 – що призведе до такої ж проблеми.

Зазвичай так не має бути. Тому ядро ​​за замовчуванням блокує такі відповіді. Тобто. якщо пакет приходить з одного інтерфейсу, а відповідь потрібно надіслати з іншого – ядро ​​не дозволяє. Загалом, звичайно, можна дозволити, але з погляду маршрутизації це не зовсім правильно. Є правильніший спосіб. Нам потрібно для інтерфейсу, де адреса 5.101 прописати свою таблицю маршрутизації.

Для початку розберемося з таблицями та правилами маршрутизації. Коротко, є таблиця маршрутизації:

ip route sh

Нічого такого. Є ще правила маршрутизації:

ip rule show

Числа ліворуч – пріоритет. Чим ближче до 0 – тим він вищий. Далі від кого – from all. Тут ми вказуємо вихідну мережу. І потім lookup і 3 значення – local, main та default. Це і є таблиці маршрутизації. Та таблиця маршрутизації, що ми бачимо під час введення ip ro sh – одне з них – main. Можемо переконатися в цьому, ввівши команду:

ip route show table main

Є ще local:

ip route show table local

Тут переважно про локальні мережі.

Тобто. ми можемо створити декілька таблиць маршрутизації і можемо написати, що для запитів з таких мереж потрібно використовувати таку таблицю маршрутизації, при цьому враховуючи ще й пріоритет. Щоб було зрозуміліше, зробимо це на сервері1.

Додамо для інтерфейсу ens5 у профілі NetworkManager-а новий маршрут, при цьому вказавши таблицю з якимось числом, припустимо, 2:

nmcli con mod management ipv4.routes "10.0.0.0/8 10.0.5.1 table=2" ipv4.routing-rules "priority 5 from 10.0.5.101 table 2"

І так, ми в профілі інтерфейсу ens5 сказали, що для мережі 10.0.0.0/8 потрібно використовувати як гейтвей 10.0.5.1, при цьому це відноситься до таблиці маршрутизації 2. І відразу додали правило з пріоритетом 5, що виходить IP 10.0.5.101 та цією таблицею 2.

Піднімемо інтерфейс і подивимося правила та таблицю маршрутизації:

nmcli con up management
ip rule list
ip route show table 2

Як бачите, тепер ми маємо правило з пріоритетом 5, яке вказує на таблицю 2, де і вказаний маршрут для локальної мережі. Теоретично, замість 10.0.0.0/8 можна було б вказати 0.0.0.0/0, щоб кожен інтерфейс мав свій default gateway, але оскільки мова стосується management інтерфейсу.

Тепер із самого jumphost-а можна пінгувати server1 як за адресою 4.101, так і за 5.101:

ping 10.0.4.101
ping 10.0.5.101

У результаті виходить така картина: коли запит приходить на інтерфейс з адресою 4.101, то для відповіді використовується таблиця маршрутизації main, в якій default gateway є адреса роутера 4.1. А от якщо запит прийде на адресу 5.101, то використовуватиметься таблиця маршрутизації 2, в якій є зворотний маршрут через адресу роутера 5.1.

Тепер, коли ми упорядкували маршрутизацію, повернемося до файрволу. І так ми на внутрішньому роутері повинні дозволити джампхосту підключатися по ssh до сервера1. Для цього потрібні політики файрволу.

Для початку на роутері3 створимо нову політику:

sudo firewall-cmd --new-policy=jh_srv1_ssh --permanent
sudo firewall-cmd --reload

Вона повинна дозволяти підключення від jumphost-а до сервера1 з ssh. Таку назву і дамо, щоб було зрозуміліше.

Після створення політика майже порожня:

sudo firewall-cmd --info-policy=jh_srv1_ssh

Політика дуже нагадує зону. Але якщо в зоні ми вказуємо порти та сервіси, якими можуть підключатися до нас, то в політиці ми вказуємо порти та сервіси, які ми дозволяємо в пакетах, що проходять, від однієї зони до іншої. Тому тут є два додаткові поля – ingress-zone та egress-zone – вхідна зона та вихідна.

Як ви зрозуміли – тепер ми повинні додати ingress та egress зони до цієї політики:

sudo firewall-cmd --policy=jh_srv1_ssh --add-ingress-zone=dmz --permanent
sudo firewall-cmd --policy=jh_srv1_ssh --add-egress-zone=management --permanent
sudo firewall-cmd --reload

Відповідно, підключення буде із зони dmz, значить ingress zone це dmz, а прямувати пакети будуть в зону management – значить це egress зона. Перевіримо політику:

sudo firewall-cmd --info-policy=jh_srv1_ssh

Як бачите, зони прописалися.

Але оскільки тут немає можливості додати source та destination адреси, нам залишається два варіанти. Або доведеться просто прописати сервіс, що призведе до того, що з будь-якої адреси із зони dmz можна буде по ssh підрубатися до management зони. А ми цього не хочемо.

Або доведеться писати rich rule, що ми зробимо.

sudo firewall-cmd --policy=jh_srv1_ssh --permanent --add-rich-rule='rule family=ipv4 source address=10.0.2.101/32 destination address=10.0.5.101/32 port port=22 protocol=tcp accept'

Отже, тут ми говоримо, що дозволяємо підключення від адреси 10.0.2.101 до адреси 10.0.5.101 за портом 22 та протоколом tcp. І це все застосовується на політику із зони dmz на management.

Перезавантажимо файрвол та перевіримо політику:

sudo firewall-cmd --reload
sudo firewall-cmd --info-policy=jh_srv1_ssh

Так, з’явилося правило. На мою думку, тут політики зроблені трохи нелогічно. Як мінімум потрібна можливість додати source і destination адреси, а не возитися з rich rule-ами. Але це відносно новий функціонал у firewalld та не те, щоб хтось крім нас використовує firewalld як мережевий файрвол. Тому на це можна заплющити очі. У політик є пріоритети, від яких залежить порядок їх перевірки, але ми не сильно з цим морочимось, курс все-таки не про це.

Давайте спробуємо з jumphost-а підключитися до сервера1:

ssh 10.0.5.101

І все працює.

Тепер у нас є можливість потрапити у внутрішню мережу, підключаючись від jumphost-а до сервера1. По суті, тепер server1 виступатиме нашим другим jumphost-ом. Через нього є вихід у п’ять влан, звідки ми можемо підрубатися до менеджменту інтерфейсів. Наприклад, роутера3.

Тепер дивіться якийсь ланцюжок ми можемо створити в ssh підключенні. І так, з інтернету у нас доступний лише jumphost. Але сам jumphost не може підключатися будь-куди, єдиний доступний йому сервер – сервер1. Сам сервер1 може бачити роутер3, оскільки вони перебувають у одному management vlan-е. А з роутера3 можемо підключитися до роутера1. Останнє насправді не обов’язково. Для роутера 1 ви можете використовувати сервер1 як джамп хоста, але тоді треба буде прописати політику файрвола на роутере3, щоб він дозволяв підключення від сервера1 до роутера1.

Спробуємо підключитись. При першому підключенні треба буде зберегти ключі від усіх проміжних хостів та ввести всі паролі від систем, куди ми не закинули ключі.

Більше ми цих повідомлень не побачимо:

ssh router1

А на хости, які просять паролі, можемо закинути ключі:

ssh-copy-id -i .ssh/servers.pub server1
ssh-copy-id -i .ssh/servers.pub router3

І тепер простою командою:

ssh router1

ми через 3 джампхости потрапляємо на роутер1. Та й загалом можемо на будь-який хост у мережі.

Взагалі, якщо використовувати роутер3 як джампхост, можна потрапити на будь-який хост. Але оскільки справжні роутери не дуже годяться як джампхості, замість цього ми будемо писати правила для файрвола і використовувати маршрутизацію. Тому це буде невеликим завданням для вас – прописати на ньому політики, щоб можна було з сервера1 підключатися до користувача1 та роутера1.

Давайте підіб’ємо підсумки. Сьогодні ми з вами розібрали таблиці та правила маршрутизації, а також політики для файрволів. Хоча поки що ми написали лише одну політику, але це в основному було зроблено для майбутніх завдань. Коли ми підніматимемо різні сервіси в різних зонах, нам потрібно буде постійно лізти у файрвол і писати політики. А мережа у нас майже готова – далі можна сконцентруватися на самих сервісах.

Інші статті по темі
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.