Вогняний блокпост порівняльний огляд файрволів FreeBSD

Зміст статті

Безпека комп'ютера, підключеного до мережі, не була приводом для серйозного занепокоєння хіба що на зорі комп'ютеризації. У наші дні ситуація кардинально змінилася, і операційна система, не забезпечена надійним та функціональним файрволом, навряд чи може претендувати на звання «мережевої». Але все це не про FreeBSD – її за цим критерієм можна назвати «тричі мережевим»!

Короткий вступ у питання

FreeBSD готова запропонувати тобі аж три файрволи, на будь-який смак: рідний IPFirewall (ipfw), присутній у ній з доісторичних часів; IPFilter (ipf), що розробляється як незалежний продукт і доступний для цілої плеяди ОС (хіба що Windows залишилася обділеною); і PacketFilter (pf), портований з OpenBSD, слава про безпеку якої вже, напевно, досягла найближчих до нас мешкаючих світів. Підтримка ipf виникла у FreeBSD 4.0, pf трохи пізніше - починаючи з 5.3. На межі четвертої та п'ятої гілок зазнав деяких змін і доморощений ipfw, надавши користувачам низку додаткових можливостей. У 5.х нова версія стала доступною під ім'ям ipfw2.

Оскільки зараз проблеми стабільності п'ятої гілки у версіях 6.x успішно подолані, то немає особливого сенсу ставити давніші версії. Тож будемо вважати, що «з коробки» тобі доступні всі три файрволи — ipfw/ipfw2, ipf та pf.

Все включено

Інсталяція – це найпростіше питання. Всі три фільтри, що розглядаються, включені в базову поставку FreeBSD, і для їх використання потрібно або завантажити модулі, або вкомпілювати їх підтримку в ядро. Особисто мені більше до вподоби другий шлях (мабуть, звичка), тим більше, що підтримка деяких додаткових опцій (наприклад, черг ALTQ)можлива лише з ядра.

Для того, щоб підвантажувався той чи інший модуль, достатньо /etc/rc.conf вказати відповідні опції (про них буде сказано нижче).

Підказки про те, як зібрати підтримку цих файрволів у ядрі, ти знайдеш у /usr/src/sys/conf/NOTES. Основні опції:

### ipfw options IPFIREWALL # підтримка файрвола options IPFIREWALL_VERBOSE # підтримка логування options IPDIVERT # підтримка divert-сокетів (потрібна для natd) options DUMMYNET # підтримка шейпера dummynet

### ipf options IPFILTER # підтримка файрвола options IPFILTER_LOG # підтримка логування

### pf device pf # підтримка файрвола device pflog # підтримка логування device pfsync # відстеження стану options ALTQ # підтримка шейпера ALTQ

Інструментарій та конфігураційні файли

Для ініціалізації файрволів у системі передбачені відповідні сценарії: /etc/rc.d/. Як і звичайних сервісів, ці скрипти сприймають команди start і stop. Наприклад, команда /etc/rc.d/ipfw start призводить до наступних дій: перевіряється, чи доступний цей фільтр (у даному випадку за змінною sysctl net.inet.ip.fw.enable), і якщо ні, то робиться спроба завантажити модуль ipfw.ko; згідно з налаштуваннями в rc.conf, виконується той чи інший сценарій ініціалізації (зазвичай поточний список правил очищується та завантажується вихідний із зазначеного у конфізі файлу). Аналогічно працюють інші сценарії.

Для керування ipfw існує однойменна утиліта /sbin/ipfw. Фактично з її допомогою можна повністю контролювати роботу цього файрвола. Детально з її синтаксисом можна ознайомитись на сторінці man ipfw(8). Найчастіше використовувані команди: add (додати правило), delete (видалити правило), flush (повністю очистити)таблицю правил), show (показати поточні правила із лічильниками).

Фільтр ipf управляється сімейством більш спеціалізованих програм: /sbin/ipf (робота з правилами фільтрації), /sbin/ipfstat (висновок статистики), /sbin/ipmon (збір логів), /sbin/ipnat (робота з правилами NAT) тощо. буд. Подробиці – на відповідних man-сторінках.

У FreeBSD головним конфігураційним файлом, що відповідає за роботу операційної системи в цілому, і за старт відповідних файрволів навіть, є /etc/rc.conf. Зазвичай задаються:

### ipfw firewall_enable="YES" # підтримка файрвола firewall_type="/etc/ipfw.rules" # тип (спосіб ініціалізації) natd_enable="YES" # підтримка natd

### ipf ipfilter_enable="YES" # підтримка файрвола ipfilter_rules="/etc/ipf.rules" # файл з правилами ipnat_enable="YES" # підтримка ipnat ipnat_rules="/ etc/ipnat.rules" # файл з правилами NAT

### pf pf_enable="YES" # підтримка файрвола pf_rules="/etc/pf.rules" # файл з правилами

Файли, вказані в прикладі, містять правила фільтрації - саме звідси відбувається ініціалізація фільтра під час завантаження (подробиці дивись у документації). Підтримка NAT включається лише у разі потреби. Правила для збору логів опущені (з цього приводу дивись /etc/defaults/rc.conf).

Найпростіший приклад

Почнемо з чогось простенького та класичного. Тут і далі вважатимемо, що rl0 – зовнішній мережевий інтерфейс, а ed0 – внутрішній. Наприклад, заборонимо будь-який вхідний трафік на зовнішній інтерфейс, крім того, що йде на порти 80 і 8080; через ed0 дозволимо все (тут і далі правила даються в тому вигляді, в якому вони будуть заноситися в rules-файли):

// ipfw (запуск без перезавантаження: ipfw -f flush && ipfw /etc/ipfw.rules) add 1000 allow tcp fromany to 10.10.10.10 80,8080 via rl0 add 1010 allow tcp from 10.10.10.10 to any via rl0 add 1100 allow all from any to any via ed0 add 200

// ipf (запуск без перезавантаження: ipf -Fa -f /etc/ipf.rules) block in on rl0 all block out on rl0 all pass in on rl0 from any to 10.10.10.10 port = 80 перейти в rl0 від 10.10.10.10 port = 8080 перейти до rl0 від 10.10.10.10 до будь-якого пройти в ed0 all пройти на ed0 all

// pf (запуск без перезавантаження: pfctl -R -f /etc/pf.rules) block on rl0 all pass in on rl0 proto tcp from any to 10.10.10.10 port pass out on rl0 від 10.10.10.10 до року pass on ed0 all

Відразу зазначимо дві речі. По-перше, синтаксиси ipf і pf багато в чому схожі (хоча є і деталі - в ipf не можна опускати параметр in/out; pf вимагає вказівки протоколу, якщо використовується фільтрація по порту і т.д.) і помітно відрізняються від такого в ipfw. По-друге, важливо пам'ятати про порядок спрацьовування правил. В ipfw пакет проходить за списком до першої відповідності, після чого до нього застосовується вказана дія. У ipf і pf дія, що відповідає правилу, запам'ятовується, а пакет продовжує свій рух за списком, і наступні правила можуть перевизначити дію попередніх. Тобто в цьому випадку застосовуватиметься останнє правило, що збіглося. Це можна перевизначити за допомогою ключового слова quick, яке скасовує подальшу перевірку.

Особливості складніші

Як не дивно, але багато хто примудряється задовольнятися показаними вище найпростішими правилами. Проте міць і гнучкість файрволів проявляються у складніших речах. Розглянемо деякі приклади.

При роботі за протоколом TCP спочатку встановлюється з'єднання і потім у рамках цього з'єднання йде обмінпакетами зі схожими характеристиками. Причому якщо файрвол пропускає перший пакет, то всі наступні у звичайному житті теж повинні бути пропущені. А якщо так, то який сенс проганяти кожен пакет 700-мегабайтного iso-файлу по всьому ланцюжку правил, щоб переконатися в тому, що й так уже очевидно? Загалом, ніякого, і тому всі три файрволи, що розглядаються, підтримують концепцію «встановленого з'єднання»:

/ / ipfw add check-state add allow tcp з будь-якого року з набору via rl0 keep-state

// ipf pass out on rl0 proto tcp from any to any flags S keep state

// pf pass out on rl0 proto tcp from any to any flags S/SA keep state

Так, ми дозволяємо з'єднання, ініційовані "зсередини" мережі. Зверніть увагу, що для ipfw ти можеш поставити правило check-state в будь-якому місці (до нього пакети, що належать до встановлених сполук, будуть оброблятися на загальних підставах; якщо забудеш його вказати, динамічні правила спрацюють на першому keep-state), в той час як pf і ipf автоматично вставляють його на початок ланцюжка. Тут демонструється здатність фільтрів працювати з прапорами заголовків TCP-пакетів.

Натинг, форвардинг та редирект

// ipfw (має бути запущений natd на порту 8668) add divert 8668 ip від 192.168.0.0/24 до будь-якого з rl0 add divert 8668 ip від 200.200.200.200.

// ipf (правила виносяться в ipnat.rules, запускаються командою ipnat) map rl0 192.168.0.0/24 -> 200.200.200.200/32

// pf (розташовуються у загальній конфігурації перед правилами фільтрації) nat on rl0 from 192.168.0.0/24 to any -> 200.200.200.200/32

Трафік-шейпінг

Просунутою фішкою сучасних файрвол є можливість керувати доступною смугою пропускання. У ipfw церобиться за допомогою інтерфейсу dummynet, pf - за допомогою ALTQ. У ipf я підтримки шейпінгу не виявив, хоча згадки, що він вміє працювати з ALTQ-чергами, трапляються. Наприклад, можна вирішити завдання обмеження доступної смуги пропускання (за вхідним трафіку) до 128 кбіт/с:

// ipfw add pipe 1 ip from any to 192.168.0.0/24 pipe 1 config bw 128Kbit/s

// pf altq on rl0 cbq queue q_limited queue q_limited bandwidth 128Kb cbq(default) pass quick from any to 192.168.0.0/24 keep state queue q_limited

До речі, ipfw теж вміє працювати з чергами ALTQ (правда, обмежено). Але для управління самими чергами, як і раніше, потрібно використовувати утиліту pfctl. Також слід зазначити в ipfw підтримку опції prob, яка дозволяє відбирати з потоку правила з деякою часткою ймовірності. Наприклад, правило "add prob 0.2 deny ip from any to any" випадково відкине 20% всього трафіку. Зокрема, це можна використовувати для імітації каналу із втратами. Аналогічні завдання pf вирішуються опцією probability.

Інші особливості

З додаткових функцій аналізованих файрволів можна назвати такі:

Якщо говорити з погляду зручності синтаксису, це багато в чому питання особистих переваг. Таблиці значно спрощують адміністрування великих мереж, а списки і макроси pf часом можуть стати в нагоді. Зате інтерактивність ipfw, що дозволяє змінювати склад правил на льоту без повного їх перезавантаження, дуже комфортна для різноманітних експериментів.

До речі, всі три файрволи чудово уживаються разом. Ти навіть можеш частину з них вкомпілювати в ядро, а частину залишити модулями. Відкидається пакет будь-яким фільтром безапеляційно, у той час як для влучення в систему йому потрібно отримати«схвалення-с» від усіх підключених фільтрів. Це дозволяє знущатися з трафіку вкрай витончено, змушуючи кожен файрвол робити те, що в нього виходить найкращим чином.