Крім високої надійності та продуктивності, операційна система
FreeBSD славиться і своїм firewall’ом — зручним і зрозумілим засобом
роботи із протоколом TCP/IP. Далі по тексту я буду досить вільно
кидатися словами «адреса», «порт», «луна» і т. д., тому тим, для кого
ці слова звучать дуже незрозуміло, рекомендую спочатку ознайомитися з
TCP/IP (http://book.itep.ru/4/44/inter_44.htm).
Для нас буде важливо, в основному, тільки те, що в
заголовку кожного ip-пакета є 32-бітові адреси джерела і
призначення, а в пакетах протоколів UDP і TCP так само номери портів
джерела і призначення пакета. З перерахованих вище тільки TCP
є протоколом зі встановленням з’єднання, і вимагає пересилання
кількох спеціальних пакетів для встановлення з’єднання перед
початком корисної передачі даних.

Firewall — це система, що управляє проходженням пакетів даних через
систему на основі заданих адміністратором правил та інформації,
що міститься в заголовках пакетів. Звичайне використання firewall –
заборона проходження небажаних пакетів, наприклад, відключення
абонента, який не оплатив послуги зв’язку, або закриття частини сервісів
локальної мережі від зовнішнього світу. В системі FreeBSD firewall — це
набагато більше, ніж просто турнікет в метро — це потужний інструмент
управління мережею, що дозволяє, наприклад, підраховувати трафік за будь-яким
розумних правил, що засновується на даних заголовків пакетів
протоколів стека TCP/IP, обробляти пакети зовнішніми програмами,
ховати за одним комп’ютером цілу мережу і т. п.

На відміну від різноманітних систем firewall для операційних систем
сімейства Windows, під FreeBSD firewall є частиною самої
операційної системи, тому працює значно швидше і надійніше
своїх не-UNIX конкурентів (виключаючи, звичайно, системи, створені
спеціально для обробки мережевого трафіку, такі як Cisco IOS). Але
т. к. firewall потрібен далеко не на кожному комп’ютері з FreeBSD (адже
FreeBSD — це ще й потужний файл-сервер, швидкий і
надійний сервер додатків, потужна робоча станція), підтримка
firewall не включена в ядро FreeBSD за замовчуванням.

Ми вже збирали ядро з підтримкою firewall у першій главі, але тепер
зупинимося на опціях ядра детальніше:

IPFIREWALL Включення підтримки firewall в ядро FreeBSD. Якщо потрібні
тільки найпростіші функції, на зразок заборони або дозволу проходження
пакетів, то цю опцію можна не включати — FreeBSD завантажить
відповідний модуль автоматично, якщо в /etc/rc.conf дозволено
використання firewall, але підтримка можливостей буде мінімальною.
IPFIREWALL_VERBOSE При включенні даної опції firewall може
записувати всі «події» в лог-файл. Корисно для аналізу роботи
системи і спостереження за спробами злому. Деякі особливо обдаровані
особистості навіть роблять на цьому системи обліку трафіку, хоча для цього
є і менш винчестероемкие технології.
IPFIREWALL_VERBOSE_LIMIT= Обмеження числа потрапляють в лог
повідомлень. При відсутності ліміту хакер або просто зіпсований комп’ютер в
мережі здатні в лічені хвилини створити стільки пакетів, що
лог-файл firewall’а займе увесь дисковий простір.
IPFIREWALL_DEFAULT_TO_ACCEPT За замовчуванням при завантаженні системи
firewall знаходиться в режимі «нікому нічого не можна», тобто весь трафік
блокується. Дана опція змушує firewall завантажуватися в режимі
«усім можна все». Не рекомендується, якщо Ви точно не знаєте, навіщо воно
Вам потрібно, і не можете обійтися без цієї опції. Прикладом необхідності
такої опції може бути використання FreeBSD як операційної системи
для бездискових робочих станцій — в цьому випадку при відсутності
зазначеної опції в ядрі FreeBSD весь трафік буде заблокований до того,
як FreeBSD зможе подмонтировать мережеві диски і завантажити з них
цей набір правил для firewall.
IPDIVERT Підтримка можливості передати пакет на обробку зовнішньої
програмі. Прикладом такої програми є natd — демон, що маскує
локальну мережу і переписывающий заголовків IP-пакетів. Програма
обробки обов’язково повинна бути запущена на цій же машині.
IPFIREWALL_FORWARD Можливість перенаправлення пакетів іншому
адресату. З допомогою цієї функції можна організувати, наприклад,
transparent proxy (http-проксі сервер для всіх клієнтів
примусовому режимі в не залежності від того, звертаються вони до
якогось сайту безпосередньо, або «просять» його у проксі-сервера), або
перенести web-сервер всередину закритій nat’ом мережі так, щоб він був
доступний з зовнішнього світу за адресою сервера доступу.
DUMMYNET Система обмеження пропускної здатності певних
сполук, заснована на затримку проходження пакетів через роутер.
Для багатьох системних адміністраторів саме ця можливість стала
визначальною при виборі операційної системи — форвардінг пакетів і
nat можна організувати на практично будь-якої мережевої операційної
системі, але з обмеженням пропускної здатності мало хто впорається
так само добре, як FreeBSD.
HZ= dummynet працює, переглядаючи чергу поставлених на очікування
пакетів з деякою частотою (за замовчуванням — 100 разів у секунду). Ви
можете збільшити або зменшити цей параметр, відповідно підвищивши
точність обмеження швидкості ціною підвищення навантаження на процесор,
або зменшити навантаження на процесор за рахунок зменшення точності
обмеження пропускної здатності. Має сенс змінювати цей параметр
бік збільшення тільки якщо при нормальній роботі Ваш процесор
навантажений не більше ніж на 10%. Зменшення цього параметра зазвичай не
дає сильного виграшу при перевантаженому процесорі, хіба що
обмеження смуги пропускання — це основна виконується сервером
завдання. Збільшення цього параметра, до речі, збільшує нагрівання
процесора. Надмірне збільшення може навпаки призводити до зниження
точності роботи dummynet, т. к. процесор може не встигати
відпрацьовувати сигнали від таймера.

І кілька опцій, які не належать до firewall безпосередньо, але щоб вже
більше не повертатися:

TCP_DROP_SYNFIN Відкидати рідко зустрічаються при нормальній роботі
TCP-пакети одночасно з встановленими прапорами початку і завершення
з’єднання. Користь від таких пакетів вкрай мала (є всього кілька
випадків, коли такі пакети реально використовуються), але такими пакетами
часто користуються хакери в своїх мерзенних цілях.
ICMP_BANDLIM Обмеження числа генеруються машиною повідомлень про
помилки TCP/IP. На нормальну роботу не впливає, але може допомогти в
отбивании деяких DoS-атак.
BRIDGE Перетворює Ваш сервер в звичайний Ethernet-комутатор, тільки
дуже добре керований.

Як працює firewall

Firewall — це захисна стіна, що стоїть між адаптером і мережним
операційною системою. Будь-який IP-пакет, перш ніж потрапити на обробку
операційною системою (наприклад, для маршрутизації або передачі його
web-серверу) проходить через суворий контроль. Будь вихідний пакет
так-же наштовхується на цю стіну, і може бути пропущено, відкинутий,
те, полічені або змінений. Якщо пакет проходить через операційну систему
наскрізь (маршрутизируется), то його перевірка відбувається як на вході,
так і на виході. При обробці пакета він може проходити через
firewall і більше разів.

Перевірка пакету проводиться за впорядкованому списку правил, які
задаються адміністратором. Кожному правилу присвоюється номер (або
вручну адміністратором, або автоматично), і правила не перевіряються
строго в порядку зростання номерів. Кілька правил можуть мати
один і той же номер — в цьому випадку вони перевіряються в тому порядку, в
якому вони були занесны в список. Кожне правило містить умову і
дія. Ось загальний вигляд правила firewall:
[prob ] [log [loamount ]] from to

де:
— ціле число в діапазоні від 1 до 65535. Правило з номером 65535 вседа
існує, його можна видалити, і воно визначається параметром ядра
IPFIREWALL_DEFAULT_TO_ACCEPT, дозволяючи чи забороняючи весь IP-трафік
залежно від наявності цього параметра. Правила з іншими номерами
повністю управляються адміністратором.
prob — Дія застосовується з деякою ймовірністю. Дана
можливість використовується досить рідко. З допомогою цього можна вказівки
симулювати, наприклад, нестабільну лінію, або різний час
проходження пакетів. в даному випадку — речовий, в діапазоні від 0
до 1 (0-правило не виконується ніколи, 1 — завжди).
— одна з наступних команд:

allow, pass, accept, permit Синоніми. Дозвіл подальшого
проходження пакета. Наступні правила не розглядаються, тобто пакет
виходить з firewall (пакет, що проходить комп’ютер «наскрізь», може
знову потрапити в firewall на «виході» системи)
unreach Заборона проходження пакета. Відправникові пакета відправляється
повідомлення (по протоколу ICMP) про невдачу. Вид повідомлення задається
параметр «тип»:
* net — мережа адресата не доступна
* host — адресат не доступний
* needfrag — необхідна фрагментація пакету
* – host unknown — немає такої адреси
* та ін.

Детальніше див. man ipfw
Після цього інші правила не розглядаються, і пакет
припиняє своє існування.
reject Дію аналогічно unreach host
deny, drop Пакет відкидається без повідомлення відправника.
reset Заборона проходження пакета. Діє тільки для протоколу
TCP. За адресою відправника пакета надсилається повідомлення TCP RST,
інформує відправника про закриття TCP-сесії — в даному випадку
абонент відразу розуміє, що йому відмовили, і може
коректно завершити з’єднання без зайвого очікування і повідомлень про
помилки. На практиці застосовується досить рідко.
skipto Перейти до розгляду правила з заданим номером. Всі правила,
знаходяться між поточним і цільовим не перевіряються. Пакет не покидає
меж firewall і продовжує перевірятися іншими правилами.
count Не робить ніяких дій. Але, як і для будь-якого правила
firewall, лічильники заноситься кількість і сумарний обсяг пакетів,
які відповідають цьому правилу, тому єдине логічне
застосування цього правила — підрахунок трафіку, що відповідає і
назви дії — count. Пакет не виходить з firewall і переходить
під владу наступного за черговістю правила.
fwd, forward Перенаправлення пакета за вказаною адресою. Заголовок
пакета змінюється. Якщо мається на увазі, що на даний пакет очікується
відповідь, то він прийде вже з «нового» адреси — це може викликати проблему
в роботі деяких програм, які перевіряють адреса відправника
відповідному пакеті. Тим не менш, це дуже корисна властивість часто
використовується для організації «transparent-proxy» або при перенесенні
якихось сервісів на інший комп’ютер, при цьому звертатися до цих
сервісів можна і за старою адресою.
divert Перенаправлення пакету на додаткову обробку програмі,
запущеної на тому ж комп’ютері, що і firewall. Зовнішня програма
може змінити пакет по своєму розумінню, знищити його, повернути в
firewall для продовження обробки з наступного правила або ввести
його firewall заново для перевірки з самого першого правила. Використовуючи
дану можливість firewall’а працюють такі програми, як natd
(який ми вже налаштовували в першій главі) і ipacctd (програма
«інтелектуального» підрахунку трафіку).
tee Аналогічний дії divert, але на обробку надсилається копія
пакета. Сам пакет продовжує рух за списком правил. Може
применятья для підрахунку трафіку, аналізу стану мережі,
протоколювання і т. п. Повернення пакета firewall при такій обробці
не бажаний, але можливий.
pipe, queue Проходження пакету через «канал» або «чергу» dummynet.
Використовується для обмеження пропускної здатності, внесення затримок
у проходження пакетів. Після «виходу» з dummynet пакет може
продовжити подорож за списком правил, або вийти з firewall у
залежно від установок sysclt net.inet.ip.fw.one_pass (детальніше про
sysctl — дещо пізніше). За замовчуванням пакет виходить з firewall
(тобто діє як allow).

— якщо ядро скомпільовано у опцією IPFIREWALL_VERBOSE, то в системний
журнал буде записаний звіт про проходження пакетом цього правила. Дана
можливість може виявитися досить корисною, якщо Ви очікуєте атаки
хакера або отлаживаете складний набір правил, розібратися в якому
вручну не вистачає сил. В журнал записується час, номер правила і
адреси джерела і призначення пакета. logamount — максимальне
кількість пакетів, запис про яких потрапляє в журнал. За замовчуванням
встановлюється рівним значенню опції IPFIREWALL_VERBOSE_LIMIT в ядрі
операційної системи.
Дія буде зроблено, якщо пакет задовольняє наступним
умов:
— назва протоколу, до якого відноситься даний пакет. Можливі
значення — ip або all (для всіх протоколів стека TCP/IP), udp, tcp,
icmp, igmp і т. д. Повний список доступних для вказівки протоколів Ви
можете подивитись у файлі /etc/protocols.
from — IP-адреса джерела пакета. Для протоколів TCP і UDP так само
може бути вказано порт. Може бути вказаний IP-адресу, доменне ім’я
комп’ютера (типу www.hub.ru), або ціла підмережа у форматі IP:MASK або
IP/LEN, наприклад 192.168.0.0:255.255.255.0 або 192.168.0.0/24. Є
так само два спеціальних слова — any, що означає будь-яку адресу (аналогічно
0.0.0.0/0) і me, означає будь-який з адрес, що належать локальної
системі. Номер порту вказується після адреси через пробіл. Кілька
номерів портів можна вказати через кому. Перед адресою або номером
порту може стояти слово «not», инвертирующее значення або адреси
порту, тобто from not 192.168.0.0/24 означає «всі пакети, що прийшли не
з мережі 192.168.0.0/24».
to — Адреса призначення пакета. Формат адреси аналогічний попередньому.

З додаткових умов найбільш потрібними і часто використовуваними
є напрямок пакета (вхідний або вихідний) і мережевий
інтерфейс, при проходженні через який був «спійманий» пакет. Формат
вказівки напряму та інтерфейсу наступний:
[in|out] [via ]

де in та out — напрям пакета (вхідний та вихідний)
відношенню до операційної системи, інтерфейс — назва пристрою
(rl0, lo0, etc) або IP-адресу пристрою (192.168.0.1, 127.0.0.1,
etc).

Управління firewall проводиться за допомогою програми /sbin/ipfw,
дозволяє видаляти і додавати правила, управляти налаштуваннями
dummynet, знімати і обнуляти статистику. Команда може викликатися з
такими наборами параметрів:

/sbin/ipfw [-adetN] list [число…] — показати поточний список правил.
Ключі команди мають наступні значення:

-a Відображати поточні значення лічильників пакетів. Більш короткий і
осмислене вираз для команди /sbin/ipfw -a list виглядає як
/sbin/ipfw show.
-d Показувати динамічні правила. Програми типу можуть natd
створювати додаткові правила firewall, мають обмежене
час життя, і не виводяться при звичайному перегляді. Дана опція
дозволяє розібратися в причинах несподіваною непрацездатності на
перший погляд нормального набору правил, або глибше вникнути в суть
роботи деяких «інерційних» правил, про які буде розказано
далі.
-de Опція -d показує тільки діючі динамічні правила. При
додавання опції-e показуються також і застарілі динамічні
правила, ще не вилучені зі списку.
-N При виведенні списку правил ipfw намагається знайти доменні імена для
IP-адрес, і дати символічні імена протоколами, зазначеним через
номер порту. Наприклад, правило allow tcp from any to 195.54.192.86 80
буде виведено у вигляді allow tcp from to ant jubjub.rinet.ru http
-t Показувати час останнього спрацьовування правила. Іноді допомагає
при налагодженні firewall.

/sbin/ipfw [q] add правило — додає правило в список. Якщо в тілі
правила не вказано його номер, то він буде обчислений як номер останнього
правила в списку + 100. Прапор -q відключає виведення на екран
підтверджує повідомлення, що дуже корисно при завданні великого
кількості правил з скрипта (наприклад, при старті системи).

/sbin/ipfw delete номер правила — видалити правило з заданим номером.
Якщо в списку існує кілька правил з даним номером — будуть
видалені всі.

/sbin/ipfw [q] zero [номер правила] — обнуляє лічильники статистики
для вибраного правила, або для всіх правил, якщо номер не вказаний.

/sbin/ipfw [-i] resetlog [номер правила] — обнуляє лічильник потрапили в
журнал записів про спрацювання правила (якщо включена опція
IPFIREWALL_VERBOSE_LIMIT=XXX). Якщо журнал ведеться для моніторингу
спроб хакерських атак, то корисно періодично виконувати цю команду
для продовження ведення журналу.

/sbin/ipfw [-f | q] flush — повне очищення списку правил. Опція -f
позбавляє від питання «чи Ви Справді хочете видалити», і опція
-q, крім того, пригнічує і висновок на екран підтверджує повідомлення.

/sbin/ipfw { pipe | queue } номер config опції — конфигрирование
каналу або черги dummynet. Про конфігуруванні dummynet — пізніше.

Перерахованих вище можливостей достатньо для конфігурування
працездатного firewall’а (подивитися man ipfw все-таки рекомендую
:)) тому пропоную перейти до розгляду прикладу,
конфигурирующего наш сервер для надання користувачам мережі
192.168.0.0/24 доступу в мережу Інтернет, що захищає від сервер
небажаних сполук із зовнішнього світу, і надає доступ
адміністратору сервера для конфігурування системи з будь-якої точки
світу. Отже, спробуємо переписати вміст нашого файлу
/usr/local/billing/rc.firewall користуючись наявними знаннями:

#!/bin/sh
ipfw=’/sbin/ipfw -q’
ournet=’192.168.0.1/24′
uprefix=’192.168.0′
ifout=’rl0′
ifuser=’rl1′
${ipfw} flush
${ipfw} add 100 check-state
${ipfw} add 200 deny icmp from any to any in icmptype
5,9,13,14,15,16,17
${ipfw} add 210 reject ip from ${ournet} to any in via ${ifout}
${ipfw} add 300 allow ip from any to any via lo
${ipfw} add 310 allow tcp from me to any keep-state via ${ifout}
${ipfw} add 320 allow icmp from any to any
${ipfw} add 330 allow udp from me to any domain keep-state
${ipfw} add 340 allow udp from any to me domain
${ipfw} add 350 allow ip from me to any
${ipfw} add 400 allow tcp from any to me http,https,ssh
${ipfw} add 410 allow tcp from not ${ournet} to me smtp
${ipfw} add 500 fwd 127.0.0.1,3128 tcp from ${ournet} to any http out
via ${ifout}
${ipfw} add 510 divert natd ip from ${ournet} to any out via ${ifout}
${ipfw} add 1002 allow ip from ${uprefix}.2 to any via ${ifuser}
${ipfw} add 1002 allow ip from any to ${uprefix}.2 via ${ifuser}
${ipfw} add 1003 allow ip from ${uprefix}.3 to any via ${ifuser}
${ipfw} add 1003 allow ip from any to ${uprefix}.3 via ${ifuser}
${ipfw} add 1004 allow ip from ${uprefix}.4 to any via ${ifuser}
${ipfw} add 1004 allow ip from any to ${uprefix}.4 via ${ifuser}
#${ipfw} add 65535 deny ip from any to any

Приклад, швидше, ілюстративний, ніж «промисловий», однак хвилі
працездатний, і на його основі ми спробуємо розібратися з загальними
принципами побудови списків правил firewall.

Розглянемо запропонований приклад по порядку, опустивши поки рядка 100,310
і 330, містять поки не відомі нам слова ckeck-state і
keep-state. У перших рядках задаються значення змінних начальницького
інтерпретатора, що описують, відповідно, клієнтську мережу (ournet),
загальну частину всіх адрес наших клієнтів (uprefix), назву «зовнішнього»
і «внутрішнього» інтерфейсів (ifout і ifuser) Такі змінні дозволять
уникнути випадкових помилок, і дозволять легко змінити настроку
firewall у випадку, наприклад, виходу з ладу мережевої карти, і заміни
її на мережеву карту іншого виробника (в цьому випадку назва
зовнішнього інтерфейсу може змінитися, наприклад, на fxp0 для карт Intel
EtherExpress).

Правила з номерами 200 і 210 служать для підвищення хакероустойчивости
системи: правило 200 забороняє появу пакетів з адресою,
належить внутрішньої мережі, на «зовнішньому» інтерфейсі, т. к. улюблене
зброя хакера — представити свій «смертельний» пакет як-би прийшов
з локальної мережі, для якої ступінь довіри вища. Правило 210
заборонить проходження деяких ICMP-пакетів: icmptype 5 — це пакет
ICMP-REDIRECT, який може бути використаний при атаці типу «фальшивий
маршрутизатор», інші icmptype — просто розкриють хакеру деяку
«зайву» з нашої точки зору інформацію… Сюди ж можна додати
інші захисні правила — будь «гуру» насыпет їх Вам з три короби.

Правила 300-350 забезпечують працездатність самої системи. Правило
300 дозволяє проходження будь-яких пакетів всередині системи (lo — локальний
інтерфейс системи, що має адресу 127.0.0.1. Використовується системою для
звернення до себе самої). 320 правило дозволяє проходження будь-яких
ICMP-пакетів, т. к. їх виникнення погано передбачувано, але їх втрата
загрожує збоями в роботі — наприклад, icmp-пакет є єдиним
способом повідомити «викликає» комп’ютера, що «викликається» адреса не
доступний. Правило 340 дозволяє проходження пакетів DNS з зовнішнього
світу на сервер (me — всі локальні адреси сервера). Це має сенс,
якщо сервер DNS-сервером, що підтримує одну або кілька
DNS-зон для мережі Інтернет, наприклад, зону Вашої мережі. Якщо Ви не
реєстрували для Вашої мережі домен, то це правило можна прибрати.
Правило 350 дозволяє серверу посилати будь-які пакети куди завгодно — самі
собі ми довіряємо, чи не правда?

Правила 400 і 410 дозволяють користуватися деякими сервісами,
надаються системою. Правило 400 дозволяє всім (і користувачам
локальної мережі і Інтернету) підключатися до Web-сервера (у Вас же є
Web-сервер, що рекламує Вашу мережу… крім того, користувач повинен
мати можливість дізнатися про стан свого рахунку незалежно від
того, сплачений у нього «Інтернет», чи ні), і до служби SSH (Secure
SHell — захищена консоль, яка використовується для віддаленого управління
системою). Правило 410 дозволяє прийом вхідної електронної пошти,
якщо у Вас встановлений поштовий сервер.

Правила 500 510 забезпечують додаткову обробку
користувацького трафіку. Правило 500 «загортає» весь http-трафік
на локальний проксі-сервер (якщо він є, якщо ні — то й правило не
потрібно). Правило 510 відправляє весь вихідний трафік користувачів
«переробку» системі NAT для трансляції адрес.

Правила 10ХХ керують доступом до Інтернету окремих користувачів.
Користувачам за адресою 192.168.0.2 відповідають два правила з номером
1002, що дозволяють проходження будь-якого трафіку до користувача і від
користувача. Якщо Ви хочете «відключити» пльзователя (наприклад, за
несплату) — просто видаліть ці правила (однією командою — /sbin/ipfw
delete 1002), і користувач зможе працювати тільки з вашим
власним Web-сервером…

Тепер про правила з загадковими словами keep-state. Ми, очевидно, не
хочемо, щоб хакери з Інтернету вільно підключалися до будь-яких портів
сервера і робили свою чорну справу. З іншого боку, досить
бажано, щоб наш сервер міг з’єднуватися з будь-якою машиною в
Інтернеті. Однак, не існує способу по вмісту одного
єдиного IP-пакета визначити, ініційоване з’єднання нашої
системою, або «ворогом». Правило з позначкою keep-state дозволяє
запам’ятати задовольняє правилу з’єднання на деякий час: якщо
пакет відповідає правилу keep-state, то firewall створює
динамічне правило, дозволяє проходження пакетів між адресами,
зазначеними в першому пакеті. Наступні пакети подовжують життя
тимчасового правила ще на деякий час. Якщо активність сполуки
припиняється — зазвичай із списку зникає, і з’єднання рветься.

Правило 310 дозволяє проходження TCP-пакетів з локальної машини на
будь-яку іншу машину, запам’ятовуючи з’єднання в тимчасовому правилі. Таким
чином, дозволяється проходження і «зворотних» пакетів від «викликаної»
машини. Тимчасові правила перевіряються firewall’ом при проходженні
через правило check-state — тому ми і помістили його на перше
місце. Ознайомитися з поточним списком динамічних правил Ви можете,
ввівши команду ipfw -d list.

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

Нехай користувач 192.168.0.2 бажає подивитися сторінку www.hub.ru
(вважаємо, що на сервері працює transparent-proxy і DNS). Першим
справою користувач посилає DNS-запит — UDP-пакет на адресу сервера
(192.168.0.1) на порт 53 (domain). Правила 100-330 пакет проходить не
задерживаяясь, т. к. він їм не задовольняє. Правило 340 дозволяє
проходження пакета з будь-якої адреси на локальний DNS, тому шлях
запиту на цьому закінчується. Відповідь локального сервера DNS — UDP-пакет
з адреси 192.168.0.1, порт 53, на адресу 192.168.0.2 (порт — щось
начебто 1025, перший-ліпший під руку комп’ютера користувача),
проходить за правилом 350, разрешающему проходження будь-яких пакетів
сервера куди завгодно. Якщо в кеші локального DNS-сервера не знайдеться
запис про сервер www.hub.ru, то він змушений буде послати запит
своєму вищестоящому DNS-сервера — UDP-пакет з адресою джерела
193.232.100.100 на адресу 195.34.32.10 (для прикладу взято DNS-сервер
MTU), який пройде за правилом 330, породивши тимчасове правило,
дозволяє зворотного проходження пакета.

Наступним етапом відкриття сторінки буде TCP-з’єднання з сервером
www.hub.ru на порт 80 (http). Користувач, що одержав від DNS-сервера
IP-адреса сервера www.hub.ru (195.54.192.86) пошле TCP-пакет з адресою
відправника 192.168.0.2 (порт типу 1026) і адресою призначення
195.54.192.86, порт 80. Цей пакет пройде firewall до правила
1002, який дозволяє користувачеві будь-який трафік, почсле чого потрапить в
систему маршрутизації, яка спробує відправити його через зовнішній
інтерфейс — тобто знову потрапить у firewall, але вже як вихідний. В
цьому своєму другому подорожі він добереться до правила 500, де його
адреса призначення буде переправлений на 127.0.0.1, порт 3128, після чого
він потрапить в proxy-сервер. Proxy-сервер згенерує відповідний пакет, з
адресою призначення 192.168.0.1, який за правилом 350 буде відправлений
користувачеві. Після того, як proxy-сервер зрозуміє, яку саме
сторінку хоче отримати користувач (для цього користувачеві і
proxy-сервера доведеться обмінятися ще декількома пакетами з тієї-ж
схемою), proxy почне власне tcp-з’єднання з сервером www.hub.ru
— відправить tcp-пакет з адреси 193.232.100.100 на адресу 195.54.192.86,
порт 80. Цей пакет пройде за правилом 310, породивши динамічне
правило. Відповідь від www.hub.ru буде пропущено цим динамічним правилом
при перевірці правила з номером 100 — check-state.

Наступний приклад — звернення користувача до зовнішнього ftp-сервера,
наприклад — ftp.freebsd.org. DNS-запит на дозвіл доменного імені
пройде аналогічно попередньому прикладу, повернувши користувачеві
IP-адреса 62.243.72.50. Отримавши адресу сервера користувач пошле на
нього tcp-пакет, який буде відповідати правилу 1002, і потрапить
в маршрутизатор, який спробує відправити його через зовнішній
інтерфейс.

При спробі «вибратися» з системи пакет дійде до правила 510,
яке «заверне» пакет на обробку natd, і вийде із системи c
адресою джерела, рівним нашому «зовнішньому» адресою — 193.232.100.100.
При цьому natd запам’ятає у тимчасовому правилі справжнє джерело пакета,
і прийшов пакет буде прередан користувачеві, пройшовши через
резрешающее правило 1002.

Зауваження для критиків — так, я знаю, що все це можна організувати
трохи ефективніше, зокрема без динамічних правил — але даний
приклад створений в ілюстративних цілях. Для бажаючих зробити все
максимально ефективно в Інтернеті є безліч прикладів налаштувань
(що часто суперечать один одному), однак динамічні правила я
все-таки вважав за потрібне описати.

Додатковою можливістю, що надається динамічними правилами,
є можливість обмеження кількості одночасних з’єднань,
відповідних якомусь правилу (це може стати в нагоді, якщо Ви
захочете боротися з «лівими» проксі-серверами в мережі — для
нормальної роботи користувача цілком достатньо десяти одночасних
сполук, в той час як для проксі-сервера таку кількість
є явно недостатнім). Для обмеження сполук додайте до
«генерирующему» правилом параметр limit, наприклад:

/sbin/ipfw add allow ip from 192.168.0.1/24 to any keep-state limit
src-addr 10

заборонить кожному абоненту мережі 192.168.0.1:255.255.255.0 встановлювати
більше 10 з’єднань одночасно. Параметр src-addr вказує, що
обмеження вважається за адресами джерел пакетів (тобто в нашому
прикладі — для кожного користувача). Допустимі значення
параметра: dst-addr (обмеження підраховується за адресами
призначення), src-port (обмеження підраховується по портам
джерела), dst-port (обмеження підраховується по портам
призначення), а також будь-які комбінації цих параметрів, наприклад, limit
dst-port dst-addr 1 дозволить встановити тільки одне з’єднання з будь-яким
портом будь-якого сервера, при цьому можна буде встановити кілька
сполук з одним сервером (наприклад, HTTP, SMTP і POP3 одночасно)
і неколько сполук на один порт різних серверів (наприклад,
одночасно завантажувати www.anekdot.ru і www.hub.ru).
Обмеження швидкості

Firewall дозволяє Вам не тільки дозволяти або забороняти проходження
IP-пакетів, але і обмежувати швидкість їх проходження. Для цього
використовується всроенная в ядро FreeBSD система dummynet — емулятор
«поганий» лінії зв’язку з настраевыми характеристиками, такими як
абсолютна затримка проходження пакета, обмеження швидкості
проходження даних по лінії, втрата певної кількості пакетів.

Dummynet складається з каналів (pipe, труба) і черги (queue). Канал
характеризується пропускною здатністю (біти в секунду), затримкою
проходження пакета (в секундах), розміром черги (скільки даних
може одночасно «знаходиться» в каналі), відсотком втрат. Задати ці
значення Ви можете за допомогою команди
/sbin/ipfw pipe config bw delay queue plr

, де — номер каналу. Вибирается адміністратором довільно з
діапазону 1-65534

— пропускна здатність каналу. Задається у вигляді числа,
интерпретируемого як біти в секунду. Можливо також завдання та одиниці
вимірювання з слоедующего набору: bit/s, Kbit/s, Mbit/s Bytes/s,
KBytes/s,MBytes/s. Одиниці виміру вказуються після числа без
прогалин: 2MBytes/s, 64Kbit/s.

— час затримки пакета в мілісекундах, завжди додається до часу
знаходження будь-якого пакета в каналі не залежно від поточної завантаження
каналу.

— розмір черги в пакетах або в кілобайтах (якщо вказана одиниці
вимірювання — Bytes або KBytes). Не помістилися в чергу пакети
отбрасывабтся.

— відсоток втрачених пакетів. Зазвичай використовується для емуляції поганих
ліній зв’язку при перевірці стійкості мережевого програмного
забезпечення до збоїв. Задається як десяткове число від 0 до 1 (0 –
втрат немає, 1 — втрачаються всі пакети).

Для управління каналом потрібно уявляти собі, як він працює –
інакше неминучі розбіжності і неприємні розчарування. При поданании в
канал пакет «стає в хвіст» черги — зовсім як у магазині.
Dummynet певну кількість разів в секунду (задається параметром HZ
при складанні ядра операційної системи) перевіряє наявність пакетів
черги, і, якщо не перевищений ліміт швидкості виходу даних з каналу,
випускає пакет. Вважається саме швидкість сходу пакетів з каналу –
тому якщо пакети в чергу надходять з більшою швидкістю, ніж
дозволена для даного каналу швидкість виходу з черги, то
«непоместившиеся» в чергу пакети просто губляться (не станете ж Ви
в чергу за хлібом, якщо перед Вами вже 50 осіб, а продавець
обслуговує клієнтів дуже повільно).

Для користувача, якщо він працює за протоколом TCP, втрати пакетів не
помітні — сервер перестає посилати пакети, якщо клієнт не посилає
підтвердження прийому. Однак, очікування підтвердження на кожен пакет
знижує продуктивність — канал зв’язку може забезпечувати велику
пропускну здатність при досить великому часу проходження
пакета, і якщо чекати відповіді на кожен пакет, то канал буде
простоювати. Тому в протоколі TCP використовується метод вікна –
надсилаються відразу кілька пакетів поспіль без очікування підтвердження,
і посилка пакетів припиняється лише в тому випадку, якщо підтвердження
не настав ще на поза-поза-минулого пакет.

Щоб робота по протоколу TCP через канал dummynet відбувалася без
необхідність повторної пересилки пакета, необхідно щоб всі пакети
«вікна» могли поміститися в черзі. Стандартного розміру черги (50
пакетів) вистачає для одночасної роботи приблизно 10 TCP-з’єднань
(це число дуже сильно залежить від параметрів протоколу TCP на машинах
клієнтів і на серверах, а так-же від середнього розміру пакета,
генерованого додатками). При перевищенні цього числа пакети почнуть
губитися, що потребують їх перепосылки заново. Якщо Ви платите за
трафік — ця особливість може боляче вдарити Вас по кишені: Ваш
провайдер порахує всі передані Вашій системі пакети, в тому числі і
загублені у dummynet, однак Ви (або Ваш клієнт), отримають тільки
частина з них — тому, якщо Ви пускаєте через один канал dummynet
велика кількість з’єднань — пропорційно збільшити і розмір
черги. Причому підрахунок пікового кількості одночасних з’єднань
зовсім не так простий — користувачі з затиснутою пропускною здатністю
канали мають звичку відкривати граздо більше одночасних
сполук, ніж володарі високошвидкісних каналів: поки читають одну
сторінку запускають на скачування ще кілька. Крім того,
користувачі менеджерів завантаження типу GetRight швидко виявлять, що
закачування файлу в декілька потоків відбувається швидше, ніж в один –
адресовані їм пакети, у вигляді більшого їх числа, бедет «витісняти»
черги чужі з’єднання… та й тривалість одного з’єднання
зросте, що теж призведе до збільшення їх одночасного числа.

Ну ладно, полякали — і вистачить. Вирішенням цих проблем може бути як
обмеження числа з’єднань через pipe, так і грамотна настройка
всієї системи обмеження, зокрема з використанням пріоритетів
трафіку: кожен канал може мати більше однієї черги пакетів, при
цьому пакети з черг «виходять» у відповідності з пріоритетами,
заданими черг. Для конфігурування черзі використовуйте команду:

/sbin/ipfw queue config pipe weight

, де — довільно вибраний адміністратором ідентифікатор
діапазону 1-65534

— номер каналу, частиною якого стає ця черга

— пріоритет черзі, число з діапазону 1-100, де 100 — самий
пріоритетний канал, 1 — найбільш безправний. За замовчуванням для кожної
черги встановлюється пріоритет 1.

Щоб «пропустити» трафік через канал, скористайтеся командами:

/sbin/ipfw add pipe або
/sbin/ipfw add quqeue, наприклад

/sbin/ipfw add pipe 1 ip from any to 192.168.0.2 зажене в канал номер
1 весь трафік, що йде до користувача 192.168.0.2.

Якщо потрібно виставити однакові обмеження для великої кількості
користувачів, то вводити сотні правил, що відрізняються тільки одним
адресою може виявитися досить стомлюючим заняттям. Для спрощення
таких завдань FreeBSD пропонує додатковий параметр mask,
дозволяє згрупувати абонентів на основі їх IP-адрес: адреса
комбінується (неисключающее побітове АБО) з маскою, і вийшло в
результаті значення є ідентифікатором групи, наприклад

/sbin/ipfw add pipe 1 ip from any to 192.168.0.1/24
/sbin/ipfw pipe 1 config bw 64Kbit/s ma