DataLife Engine > Безопасность > Расширенная конфигурация IPFW

Расширенная конфигурация IPFW


27-10-2010. Разместил: synergix Расширенная конфигурация IPFW
Обычная конфигурация

Большинство примеров в интернете показывают "плоскую" конфигурацию файрвола

 ipfw 10 add divert 8778 ip from 3.3.3.0/24 to 6.6.6.0/24
ipfw 20 add divert 8668 ip from 3.3.3.0/24 to any
ipfw 30 add divert 8668 ip from 4.4.4.0/24 to 5.5.5.0/24
ipfw 40 add divert 8778 ip from 4.4.4.0/24 to any
ipfw 50 add fwd 1.1.1.254 ip from 1.1.1.1 to any
ipfw 60 add fwd 2.2.2.254 ip from 2.2.2.2 to any
ipfw 70 add divert 8668 ip from any to 1.1.1.1
ipfw 80 add divert 8778 ip from any to 2.2.2.2


 #!/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 https,httpss,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 https out via ${ifout}
 ${ipfw} add 510 divert natd ip from ${ournet} to any out via ${ifout}
 ${ipfw} add 511 divert natd ip from any to ${REAL_IP} in 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


Плоская, потому что любой трафик проходит ВСЕ! правила файрвола, даже через те правила, которые не предназначались для данного пакета.
Например в 1-м примере для пакета 4.4.4.5 -> I.N.E.T который получен с интерфейса rl2 и будет направлен в интернет пройдёт 6 проверок (75% всех правил) из который нужных только 2 (25%). И ответ I.N.E.T -> 2.2.2.2 (I.N.E.T -> 4.4.4.5 после undiverta) пройдёт все правила (100%), из которых нужная только одна (12%).

Для сравнения в примере 2 эффективность файрвола ещё меньше. Для пакета 192.168.0.4 -> I.N.E.T делается 13 проверок (68%), из которых 2 полезных (10%). И для ответа I.N.E.T -> 192.168.0.4 19 проверок (100%), из которых нужных тоже 2 (10%).

Также обратите внимание что в оригинале пропущен обратный диверт, нет правила ${ipfw} add 511 divert natd ip from any to ${REAL_IP} in via ${ifout} где ${REAL_IP} это ИП адрес на ${ifout} интерфейсе (в данном случае rl0) Без этого правила трафик не сможет вернуться обратно и будет отвергнут
65535-м правилом.

Учитывая тот факт, что файрвол имеет тенденцию разрастаться, то со временем количество ненужных проверок будет расти и соответственно производительность падать. А это ненужные задержки... Как бы то нибыло с задержками можно ещё смирится или например поставить более производительное железо. Но с фактом быстрого роста сложноcти файвола Вы не поспорите никак. Очень частая ошибка будет свзяна с тем, что Вы будет забывать указывать in recv/out xmit/via ${iface} и трафик будет дропаться/дивертиться/форвардится не туда куда нужно и Вы будете тратить часы сидя с tcpdump'ом, чтобы найти куда же ушел пакет или почему он не возвращается.

Открытый файрвол VS Закрытый файрвол

По умолчанию при загрузке системы firewall находится в режиме "никому ничего нельзя", т.е. весь трафик блокируется. Я бы не советовал пересобирать ядро с опцией IPFIREWALL_DEFAULT_TO_ACCEPT. Т.к. в этом случае Ваш файрвол будет похож на большую дыру =) и, фактически, в этом случае Вы ничего не контролируете. Каждый более менее продвинутый пользователь сможет получить халявный трафик! Вы можете попытаться блокировать не нужный трафик, тогда у Вас выйдето что-то вроде:

ipfw add xxx deny all from 192.168.0.0/16 to any
 ipfw add xxx deny all from 172.16.0.0/12 to any
 ... и другие возможные блокировки
 ipfw add 65535 allow all from any to any



Поверьте всё не заблокируете. Также давайте будем исходить из того факта, что если у Вас что-то не работает. Т.е. Вы забыли разрешить нужный трафик, то пользователи Вашей сети или сотрудники предприятия обратятся к Вам с этой проблемой и Вы сможете исправить ситуацию. Однако злобный пользователь, который юзает Ваш роутер для своих мерзких целей никогда НИКОГДА не прийдёт к Вам и не скажет, что мол вот у тебя дырочка и ты терпишь убытки. Поэтому предпочтение лучше отдать закрытому файрволу. т.е. по умолчанию блокируем любой трафик

ipfw add 65535 deny all from any to any


Разделяй и властвуй

Идея построения улучшенного файрвола базируется на принципе "Разделяй и властвуй". Нужно разделить трафик по интерфейсам и рулить "потоком" отдельно на каждом интерфейсе.

ipfw add 09999 skipto 10000 all from any to any via em
 ipfw add 09999 skipto 11000 all from any to any via rl0
 ipfw add 09999 skipto 12000 all from any to any via rl1
 ipfw add 09999 skipto 13000 all from any to any via rl2
 ipfw add 09999 skipto 65000 ip from any to any

 ipfw add 10999 skipto 65000 ip from any to any
 ipfw add 11999 skipto 65000 ip from any to any
 ipfw add 12999 skipto 65000 ip from any to any
 ipfw add 13999 skipto 65000 ip from any to any



Таким образом мы получаем что трафик с разных интерфейсов не пересекается и также получаем возможность работать с каждым интерфейсом как бы изолированно. Диапазон 00001-99998 можно использовать по своему усмотрению. Например мы не используем сеть 10.0.0.0/8 и поэтому блокируем её на ВСЕХ интерфейсах. Или например мы хотим заблокировать icmp трафик на всех интерфейсах, поэтому мы пишем

 ipfw add 9010 deny all from 10.0.0.0/8 to any
 ipfw add 9010 deny icmp from any to any



Также этот диапазон можно использовать для счётчиков.
ВАЖНО!!! Всегда считайте до того, как Вы заблокируете какой либо вид трафика. Иначе Вы рискуете потерять часть статистики.

 ipfw add 910 deny tcp from any 135 to any in recv ng0
 ipfw add 910 count tcp from any to any in recv ng0



В данном случае Вы не посчитатете трафик на 135 порту от клиента, хотя по сути клиент загрузил часть канала. В итоге Вы не дополучаете некоторую сумму, когда клиент расчитывается с Вами за интернет.

Распределение диапазона 00001-09999

00001- 00089 зарезервировано. Всегда нужно иметь такой пустой диапазон. Обычно использую для тестирования или когда необходимо на гарячую что-то сделать с трафиком. Например остановить флуд:
ipfw add 1 deny all from any 135 to any


00090 - 00099 для глобальных (на всех интерфейсах) блокировок.
ЗАМЕТЬТЕ: Трафик заблокированный здесь НЕ БУДЕТ посчитан!

00100 - 00899 использую для подсчёта трафика.

00900 - 00999 Для глобальных блокировок.
ЗАМЕТЬТЕ: Трафик заблокированный здесь БУДЕТ посчитан.

01000 - 09998 Испольуйте этот диапазон на своё усмотрение

09999 Служит для деления трафика по интерфейсам. По умолчанию последнее должно быть
ipfw add 09999 skipto 65000 ip from any to any


10000 - 10999 Правила для интерфейса lo

11000 - 11999 Правила для интерфейса 1

11000 - 11999 Правила для интерфейса 2 ...

64000 - 64999 Правила для интерфейса 2

65000 - 65534 Правила блокировки по умолчания и/или логирования

65535 блокировка по умолчанию

ЗАМЕТКИ:
а) 5 цифр в номере использую только для визуального оформления, поэтому 00001 0001 001 и 1 это одно и тоже.

б) Последнее правило для каждого интерфейса хх999 должно быть

ipfw add хх999 skipto 65000 ip from any to any


Это нужно для того, чтобы проверить правильность конфигурации правил для интерфейса. Запомните! через это хх999 правило не должен проскользнуть ни один пакет и поэтому если коунтер на этом правиле не равен нулю, что значит что-то Вы упустили. Как узнать, что именно было сделано не верно я раскажу ниже. (см. хх998 правило)


Написание правил для интерфейса

И так для правил интерфейса у нас имеется диапазон xx000 - xx998.
xx999 правило должно быть ipfw add хх999 skipto 65000 ip from any to any
Каждое сотое правило зарезервировано ххy00: хх100, хх200, ..., хх900

хх000 - хх099 зарезервировано. Также как и для правил 00001- 00089 используется для "гарячих" целей или тестирования.

хх101 - хх199 блокируем весь нежелательный трафик здесь. Например если на интерфейсе висит сеть 192.168.0.0/24, то дропаем всё, что не с этой сети:

 ipfw add 11101 deny all from not 192.168.0.0/24 to any in recv rl0



хх201 - хх299 этот диапазон идеален для правил подсчета (count) трафика для исхода, тк. здесь трафик ещё не попал в диверт (виден src-ip)

xx301 - xx399 здесь можно расположить skipto xx500 правила, если мы не хотим чтобы они попадали в очередь и/или шейпер. Однако этого я бы не рекомендовал делать. (см Как не нужно делать)

хх401 - хх499 ложим исходящий трафик в очередь и/или канал. Вы должны сделать это до диверта, тк. после диверта весь исходящий трафик получит Ваш внешний ИП и Вы не сможете распределить канал между локальными
пользователями. А до виверта Вы можете сделать это по src-ip.

хх501 - хх599 дивертим входящий/исходящий трафик тут.

хх601 - хх699 этот диапазон идеален для правил подсчета (count) трафика для входа, тк. здесь трафик ещё уже прошел диверт (виден dst-ip)

хх701 - хх799 здесь можно расположить skipto хх900 правила, если мы не хотим чтобы они попали в очередь и/или шейпер. Однако этого я бы не рекомендовал делать. (см. Как не нужно делать)

хх801 - хх899 ложим входящий трафик в очередь и/или канал. Вы должны сделать это после диверта, тк. до диверта весь входящий трафик имеет Ваш внешний IP и Вы не сможете распределить канал между локальными
пользователями. А после диверта Вы можете сделать это по dst-ip. (см. Недостатки ALTQ)

хх901 - хх997 разрешающие правила. Т.к. у нас файрвол закрытый, то это обязательная часть файрвола, где мы должны указать какой трафик разрешен. Если это внешний интерфейс, то разрешаем трафик на Ваш
реальный IP I.N.E.T:

 ipfw add 11903 allow all from I.N.E.T to any out xmit rl0
 ipfw add 11903 allow all from any to I.N.E.T in recv rl0



Если это внутренний интерфейс 192.168.0.1/255.255.255.0 (ака локальная сеть), то разрешаем сеть:

ipfw add 11903 allow all from 192.168.0.0/24 to 192.168.0.1 in recv rl1
 ipfw add 11903 allow all from 192.168.0.1 to 192.168.0.0/24 out xmit rl1



Здесь я использую один номер для всех правил, для экономии номеров. Кроме экономии я ещё показываю однотипность правил, показываю то, что все эти правила выполняют одинаковую работу, то, что не важно в каком порядке они выполняются.

Такие логические блоки можно отделять друг от друга с шагом 5 или 10. В зависимости от количества таких блоков. Обычно 6-8 блоков хватает, поэтому для каждого выделяю номера (шаг10) ххх03, ххх13, ххх23 и тд. Сплошную нумерацию лучше не делать: ххх01, ххх02, ххх03, т.к. если Вам понадобиться срочно добавлять/удалять какое-либо правило между ххх01 и ххх02, Вам прийдется помучатся с передобавлением ххх01 правил. Чего Вы избежите, когда у Вас будут пустые номера между группами. По мере заполнения этого пространства не забывайте каждые месяц/пол года перенумеровывать правила с шагом 5/10. Это избавит Вас от лишней работы
в критические ситуации.

хх998 здесь должно быть правило: deny log all from any to any via IFACE

Этим правилом мы облегчаем себе жизнь в разы. Любой трафик который мы не учли будет попадать в лог /var/log/security.

Jun 21 15:58:02 kes kernel: ipfw: 10998 Deny ICMP:5.1 10.0.16.3 172.16.128.61 in via rl0
Jun 21 15:58:02 kes kernel: ipfw: 10998 Deny ICMP:5.1 10.0.16.3 172.16.128.61 in via rl0



И если у Вас правильно настроена ротация лог файлов /etc/newsyslog.conf, стандартный конфиг это:

/var/log/security 600 10 100 * JC

то можно не боятся что файловая система будет переполнена =)

хх999 здесь должно быть правило: skipto 65000 ip from any to any
Весь трафик который вы не учли попадёт на 65000 - 65535 правила.
НЕ ЛЕНИТЕСЬ НАПИШИТЕ ЭТО ПРАВИЛО. ДАЖЕ ЕСЛИ ВЫ УВЕРЕНЫ, ЧТО хх998
ПРАВИЛО ОБРАБОТАЕТ ВСЕ СЛУЧАИ.
ПОТОМУ ЧТО БОГ ЗНАЕТ В КАКОМ СОСТОЯНИИ ПРИЙДЕТСЯ ВАМ ПРАВИТЬ ФАЙРВОЛЛ =)

ВНИМАНИЕ!!!
Также обязательно в конце правила обязательно указывайте направление и интерфейс.
Это съэкономит время на ловке ошибок при конфигурации файрвола. Поверьте, это экономит время!
Ну и последнее правило должно быть:

65534 ipfw add deny log all from any to any


Собираем всё до кучи.

Для удобства, правила для каждого интерфеса ложите в отдельный файл называнный именем этого интерфейса: rl0, rl1, em0, ng*. Здесь ng* это VPN пул. Для того чтобы не писать кучу одинаковых ng0, ng1 ... ngX я назвал этот общий файл "ng*", можно было назвать "ng". Но это на любителя =)

Теперь создадим файл файрвола:

 # mkdir /usr/local/etc/firewall
 # cd /usr/local/etc/firewall
 # touch firewall
 # chmod 700 firewall


И сам скрипт:

 #!/bin/sh
 #первый параметр к скрипту это start|stop|reload

 #разрешаем задать путь к ipfw
 if [ -n "${2}" ]; then
fwcmd=${2}
 else
fwcmd="/sbin/ipfw" #если ничего не задали
 fi

 workDir="/usr/local/etc/firewall"

 start () {

 #This rule set are independed. So run it first.
 #Загружаем файл с набором каналов
  . $workDir/f-pipes.ipfw

 #We wanna count something???
 #файл с набором коунтеров
  if [ -f $workDir/f-count.ipfw ]; then
. $workDir/f-count.ipfw
  fi

 #Файл с набором по умолчанию
  if [ -f /$workDir/f-defaults.ipfw ]; then
num=00
. $workDir/f-defaults.ipfw
  fi

 #Интерфейс rl0 имеет нумерацию на 10000, поэтому num = 10
  num=10
  . $workDir/f_rl0
 #Интерфейс tun0 имеет нумерацию на 11000, поэтому num = 11
  num=11
  . $workDir/f_tun0
  num=13
  . $workDir/f_ng*

 #Обратите внимание наличие точки и пробела в комманде  ". $workDir/f_tun0" обязательно
 #Без них работать ничего не будет

 #this rule must be runned last to be the last record in 9999 rule
 #по умолчанию весь трафик идет на 65000 правила
  ${fwcmd} add 9999 skipto 65000 all from any to any
 #по умолчанию дропаем всё и пишем в лог
  ${fwcmd} add 65534 deny log all from any to any

 }

 #удаляем все правила, пайпы, очереди
 stop () {
  ${fwcmd} -f flush
  ${fwcmd} -f pipe flush
  ${fwcmd} -f queue flush
 }

 #Разрешаем работу обратной петли. правило 99!
 setup_loopback () {
 ############
 # Only in rare cases you want to change these rules
 #
 ${fwcmd} add 99 pass all from any to any via lo0
 ${fwcmd} add 99 deny all from any to 127.0.0.0/8
 ${fwcmd} add 99 deny ip from 127.0.0.0/8 to any
 }

 #Статистика перезапуска файрвола =)
 echo `date` >> /etc/reboot

 case ${1} in
 start)
  setup_loopback
  start
;;
 stop)
  stop
;;
 reload)
  stop
  setup_loopback
  start
;;
 *)
  echo "Usage: `basename ${0}` { start | stop | reload& } "
  echo "WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!"
  echo "Don't foget to add '&' if you reload the firewall remoutly"
;;
 esac



Если Вы захотите перезагрузить файрвол с помощью этого скрипта
удалённо, то ОБЯЗАТЕЛЬНО добавьте в конец команды знак & чтобы скрипт
выполнялся в фоне. Иначе когда удалятся правила Ваша сессия сбросится и
выполнение скрипта остановится.
Таким образом вы отрежете себе путь к серверу.

Теперь по поводу правил для интерфейсов:

 # touch f-count.ipfw
 # touch f-pipes.ipfw
 # touch "f_ng*"
 # touch f_rl0
 # touch f_tun0



Обязательная шапка для всех файлов:

 #!/bin/sh
 iface="имя_интерфейса"

 #перенаправляем трафик с общего потока на правила которые отвечают за интерфейс ${iface}
 ${fwcmd} add 9999 skipto ${num}000 all from any to any via "${iface}"



Если присваивать имя интерфейса переменной и не писать имя интерфейса в
каждом правиле, то мы экономим время, если меняется имя интерфейса,
например с rl2 -> em0, а логически подключение остаётся тоже. Тогда
просто заходим и меняем имя в одном месте ;-)

Значения переменных $fwcmd и $num устанавливаются в скрипте firewall
Итак кусочек файрвола для ng*

f_ng

 #!/bin/sh
 iface="имя_интерфейса"

 #перенаправляем трафик с общего потока на правила которые отвечают за интерфейс ${iface}
  ${fwcmd} add 9999 skipto ${num}000 all from any to any via "${iface}"

 #на VPN пул выдаются адреса с сети 192.168.0.0/16, поэтому всё что не наше дропаем
 #Фактически весь не разрешенный трафик убъётся хх998 правилом, но делая это здесь Вы выигрываете в производительности
  ${fwcmd} add ${num}101 deny all from not 192.168.0.0/16 to any in recv "${iface}"

 #Шейпим
  ${fwcmd} add ${num}406 pipe 1 all from 192.168.7.0/24 to any in recv "${iface}"
  ${fwcmd} add ${num}406 pipe 2 all from any to 192.168.7.0/24 out xmit "${iface}"
  ${fwcmd} add ${num}406 pipe 3 all from 192.168.8.0/24 to any in recv "${iface}"
  ${fwcmd} add ${num}406 pipe 4 all from any to 192.168.8.0/24 out xmit "${iface}"
  ${fwcmd} add ${num}406 pipe 5 all from 192.168.5.0/24 to any in recv "${iface}"
  ${fwcmd} add ${num}406 pipe 6 all from any to 192.168.5.0/24 out xmit "${iface}"

 #Разрешаем трафик
  ${fwcmd} add ${num}901 allow all from any to 192.168.0.0/16 out xmit "${iface}"
  ${fwcmd} add ${num}902 allow all from 192.168.0.0/16 to any in recv "${iface}"

 #Дропаем всё ненужное
  ${fwcmd} add ${num}998 deny log all from any to any via "${iface}"
  ${fwcmd} add ${num}999 skipto 65000 all from any to any



f_rl0

#!/bin/sh

 iface="rl0"

 #Isolate traffic via "${iface}" for decrease number of passing via firewall rules
  ${fwcmd} add 9999 skipto ${num}000 all from any to any via "${iface}"

 #DENY all unwanted traffic
  ${fwcmd} add ${num}101 deny all from 192.168.0.0/16to any in recv "${iface}"
  ${fwcmd} add ${num}101 deny all from 172.16.0.0/12 to any in recv "${iface}"

 #Даём приоритет для VPN трафика над локальным
  ${fwcmd} add ${num}401 queue 31 gre from 10.0.0.0/8 to 10.0.0.0/8 out xmit "${iface}"
  ${fwcmd} add ${num}401 queue 32 not gre from 10.0.0.0/8 to 10.0.0.0/8 out xmit"${iface}"

  ${fwcmd} add ${num}801 queue 33 gre from 10.0.0.0/8 to 10.0.0.0/8 in recv "${iface}"
  ${fwcmd} add ${num}801 queue 34 not gre from 10.0.0.0/8 to 10.0.0.0/8 in recv "${iface}"

 #ALLOW rules
  ${fwcmd} add ${num}901 allow all from I.N.E.T to any out xmit "${iface}"
  ${fwcmd} add ${num}902 allow all from any to I.N.E.T in recv "${iface}"

 #Allow LAN traffic
  ${fwcmd} add ${num}904 allow all from any to 10.11.0.0/16 via "${iface}"
  ${fwcmd} add ${num}904 allow all from any to 10.10.0.0/16 via "${iface}"
 #для работы samba, нужны броадкасты
 #Здесь направление может быть любое, поэтому я ставлю via
  ${fwcmd} add ${num}906 allow all from any to 255.255.255.255 via "${iface}"
  ${fwcmd} add ${num}906 allow all from 255.255.255.255 to any via "${iface}"

 #по аналогии
 #Deny all other traffic
  ${fwcmd} add ${num}998 deny log all from any to any via "${iface}"
  ${fwcmd} add ${num}999 skipto 65000 all from any to any


f_tun0


 #!/bin/sh

 iface="tun0"

 #Isolate traffic via "${iface}" for decrease number of passing via firewall rules
  ${fwcmd} add 9999 skipto ${num}000 all from any to any via "${iface}"

 #DENY all unwanted traffic
  ${fwcmd} add ${num}103 deny all from 10.0.0.0/8 to any out xmit "${iface}"
  ${fwcmd} add ${num}103 deny all from 192.168.0.0/16 to any in recv "${iface}"
  ${fwcmd} add ${num}103 deny all from 10.0.0.0/8 to any in recv "${iface}"
  ${fwcmd} add ${num}103 deny all from 172.16.0.0/16 to any in recv "${iface}"

 #Put out traffic into pipe
 #Обратите внимание на тот факт, что пакет выходи с очереди и пападает в правило
 #СО СЛЕДУЮЩИМ НОМЕРОМ, не в сделующее правило!
 #Так пакет выйдя с очереди 22 попадёт сразу в правило хх803
  ${fwcmd} add ${num}403 queue 21 all from 192.168.1.0/24 to any out xmit "${iface}"
  ${fwcmd} add ${num}403 queue 27 all from any to 192.168.0.0/16 in recv "${iface}"

  ${fwcmd} add ${num}803 queue 26 all from any to 192.168.1.0/24 in recv "${iface}"
  ${fwcmd} add ${num}803 queue 27 all from any to 192.168.0.0/16 in recv "${iface}"

 #ALLOW rules
 #К примеру у Вас маршрут по умолчанию через tun0 интерфейс
 #Но также есть выход в и-нет через интерфейс rl0. Тут мы форвардим на шлюз 
 #провайдера (G.A.T.E) трафик который уходит с реального IP интерфейса rl0 I.N.E.T
 #Обратите внимание что пакет сразу уйдет на шлюз провайдера через rl0 и не будет проходить файр вол ещё раз
  ${fwcmd} add ${num}901 fwd G.A.T.E all from I.N.E.T to any via "${iface}"

 #просто разрешаем весь трафик через интерфейс, тк. на tun0 IP динамический
 #Это правило - дыра в файрволе!! Т.к. любой может указать нашу машину шлюзом и отправлять трафик в и-нет
 #Поэтому мы всё не нужно отсекли в секции хх100-хх199
 #Однако на 100% быть уверенным нельзя, что закрыли всё ненужное. Вот поэтому делать РАЗРЕШЕНО ПО УМОЛЧАНИЮ не стоит!
  ${fwcmd} add ${num}902 allow all from any to any out xmit "${iface}"

 #Deny all other traffic
  ${fwcmd} add ${num}998 deny log all from any to any via "${iface}"
  ${fwcmd} add ${num}999 skipto 65000 all from any to any



Файл пайпов и очередей
f-pipes.ipfw

#!/bin/sh

  ${fwcmd} pipe 1 config bw 8Kbytes queue 15 mask src-ip 0xffffffff gred 0.002/10/30/0.1#in
  ${fwcmd} pipe 2 config bw 8Kbytes queue 15 mask dst-ip 0xffffffff gred 0.002/10/30/0.1#out

  ${fwcmd} pipe 3 config bw 16Kbytes queue 25 mask src-ip 0xffffffff gred 0.002/10/30/0.1#in
  ${fwcmd} pipe 4 config bw 16Kbytes queue 25 mask dst-ip 0xffffffff gred 0.002/10/30/0.1#out
  ${fwcmd} pipe 5 config bw 32Kbytes queue 50 mask src-ip 0xffffffff gred 0.002/10/30/0.1#in
  ${fwcmd} pipe 6 config bw 32Kbytes queue 50 mask dst-ip 0xffffffff gred 0.002/10/30/0.1#out

  ${fwcmd} pipe 7 config bw 4096Kbits #in
  ${fwcmd} pipe 8 config bw 1024Kbits #out
 #Так как две очереди имеют разный приоритет, то трафик с очереди 21 начнет обрабатываться только после очереди 22
 #Если же 22 будет загружать канал на 100%, то трафик с очереди 21 никогда не обработается
  ${fwcmd} queue 21 config pipe 8 weight1 mask src-ip 0xffffffff gred 0.002/10/30/0.1
  ${fwcmd} queue 22 config pipe 8 weight  50 mask src-ip 0xffffffff gred 0.002/10/30/0.1

  ${fwcmd} queue 26 config pipe 7 weight1 mask dst-ip 0xffffffff gred 0.002/10/30/0.1
  ${fwcmd} queue 27 config pipe 7 weight  50 mask dst-ip 0xffffffff gred 0.002/10/30/0.1

  ${fwcmd} pipe 9 config bw 2312Kbits #Out
  ${fwcmd} pipe 10 config bw 2312Kbits #In
  ${fwcmd} pipe 11 config bw 256Kbits #Out
  ${fwcmd} pipe 12 config bw 256Kbits #In

  ${fwcmd} queue 31 config pipe 9 mask dst-ip 0xffffffff gred 0.002/10/30/0.1
  ${fwcmd} queue 32 config pipe 11 mask dst-ip 0xffffffff gred 0.002/10/30/0.1
  ${fwcmd} queue 33 config pipe 10 mask src-ip 0xffffffff gred 0.002/10/30/0.1
  ${fwcmd} queue 34 config pipe 12 mask src-ip 0xffffffff gred 0.002/10/30/0.1



Неслько слов о порядке обработки пакетов

* Пакеты обрабатываются в порядке их поступления и с максимально возможной скоростью.
* Пакеты, которые не могут быть отправлены/обработаны в данный момент ложатся в буфер. По умолчанию queue 50, т.е. 50 пакетов максимальной длины 1500 байт.
* Если пакет попал в пайп, то он отправляется со скоростью указанной для пайпа
* Если необходимо чтобы пакеты от разных источников отправлялись поочерёдно (roundrobin), то нужно чтобы пакеты с нескольких очередей попадали в один пайп(очередь?) и вес этих очередей должен
быть одинаков. Иначе очередь с меньшим весом будет обрабатываться только тогда, когда в
очереди с большим весом не будет пакетов.

ipfw pipe 1 config bw 512Kbits
 ipfw add queue 1 config pipe 1 weight 10
 ipfw add queue 2 config pipe 1 weight 10
 ipfw add queue 3 config pipe 1 weight 10



В этом примере пакеты будут выбираться по одному с каждой очереди по порядочку:
* пакет с очереди 1
* пакет с очереди 2
* пакет с очереди 3
* пакет с очереди 1
* пакет с очереди 2
* пакет с очереди 3
* и тд.

Если в данный момент есть трафик только на одной очереди, то пакеты с этой очереди будут выбиратся со скоростью в 512Кбит. Однако если две очереди загружены по максимуму, то каждая получит 256Кбит.

Если же работают все 3 очереди, одна на 128Кбит, а остальные две пытаются загрузить по максимуму, то эти две получат по (512-128)/2 =192Кбита

Для того чтобы не создавать кучу очередей, можно использовать маску. По умолчанию она равна 0х00000000 и дополнительные очереди не создаются. Если же задать mask src-ip 0xffffffff, то для каждого нового источника (IP) будет создана новая очередь. Или же mask src-ip 0xffffff00 то для каждой подсети /24 будет создана новая очередь. Например:

пакеты у которых источник 192.168.0.5, 192.168.0.17, 192.168.0.33 попадут в одну очередь (общая часть 192.168.0) а пакеты у которых источник 192.168.1.7, 192.168.1.15 попадут в другую (другая общая часть 192.168.7, поэтому другая очередь) даже для пакетов у которых источник 10.0.7.1, 10.0.7.3 также попадут в свою очередь (общая часть 10.0.7)

Таким образом 0 задаёт ту часть адреса, которая будет игнорироваться при создании новой очереди. Одним словом маска =)

Рассмотрим очень простой пример:

 ipfw pipe 1 config bw 512Kbits mask src-ip 0xffffff00
 ipfw add queue 1 config pipe 1 mask src-ip 0xffffffff
 ipfw add 1 queue 1 all from any to any out xmit rl0 #шейпится на выходе к провайдеру



Все пакеты будут обрабатываться в порядке roundrobin и для каждой подсети 255.255.255.0 будет выделен канал 512Кбит

f-count.ipfw

 #!/bin/sh

 #считаем наш трафик к/от провайдера
 ipfw add 103 count all from any to any in recv rl0
 ipfw add 104 count all from any to any out xmit rl0

 #обычно на интерфейсе может шнырять всякая лабуда типа router discovery, DHCP, б
 роадкасты, поэтому лучше считайте только свой трафик
 ipfw add 105 count all from any to I.N.E.T in recv rl0 #Входящий на ваш IP
 ipfw add 106 count all from I.N.E.T to any out xmit rl0 #Исходящий с вашего IP


Обратите внимание num= "00" (строка 27 в firewall)

f-defaults.ipfw

 #!/bin/sh

 #Блокируем трафик с локальной сети в интернет
 ${fwcmd} add ${num}901 deny ip from 10.0.0.0/8 to any via tun0


ipfw vs pf

Недостаток ALTQ

Я бы не использовал ALTQ в качестве шейпера только по одной причине: шейпится только исходящий трафик. Это самый большой минус, который можно придумать! Этот минус сводит на нет все достоинства ALTQ. Почти везде можно увидить:

MB> потому что шейпить входящий трафик дурость =)
На самом деле дурость - это НЕ ШЕЙПИТЬ входящий трафик!!!
Простой пример. хост -- роутер -- шлюз -- инет

Если пользователь ХОСТ и РОУТЕР будут качать, то НЕВОЗМОЖНО создать правило, которое будет обрабатывать пакеты предназначенные для ХОСТ и РОУТЕР поочерёдно (roundrobin). Т.е. НЕВОЗОМЖНО разделить канал от ШЛЮЗ
к РОУТЕР на равные части между пользователем ХОСТ и РОУТЕР ПОЧЕМУ?

Потому что для РОУТЕР исхода не будет (пакет когда попадёт в ядро сразу передастся приложению) и поэтому мы не сможем пропустить этот пакет через ALTQ.

Поэтому пользователь РОУТЕР может загрузить канал в ущерб для ХОСТ. Некоторые могут возразить что мол мы не можем контролировать входящий поток.

Я отвечу что можем! Наверное Вы просто ребята не читали работу протокола TCP/IP.

То что не получится для входящего трафика, так это приоритезировать его по типам. Например www дать меньше приоритета, чем голосовому трафику. Тут уж как пришли к нам пакеты, так уж пришли.
То что можно сделать, так это перенаправлять входящий трафик клиентам по очереди, таким образом разделив канал поровну между ними. Также можно ограничить потребление некоторым клиентом не более K% трафика. Что касается тупого флуда на Ваш интерфейс, то тут действительно кроме удара в голову флудеру ничего не поможет.
Но это частный случай!

Что не нужно делать

1. Берите люди интернет кто хотите:

 ipfw add 1 divert natd all from any to any
 ipfw add 2 allow all from any to any



2.Не ложите в один пайп входящий и исходящий трафик. Возьмите за правило: одно направление трафика - один пайп.
К примеру если создать пайп на 115200bit и положить в него вход и исход, то получится канал как на Sirius. Кто работал через этот модем, тот уже представил какая лажа будет :-D

3. Если у Вас есть пайп на направление, то не пропускайте трафик мимо этого пайпа Т.к. некоторые алгоритмы шейпинга будут работать неверно (например RED) если реальная скорость канала (pipe) будет отличаться сконфигурированной. Например у нас на интерфейсе подключение 256Кбит и мы создали канал на 256Кбит и направили весть трафик в этот канал. Трафик отлично подрежится и будет бегать с задданой скоростью. Но в ситуации если вдруг Вы решили пустить трафик от какого-то хоста мимо пайпа, ничего работать не будет. Давайте посмотрим что произойдет, если этот хост загрузит канал на 128Кбит, а весь остальной трафик, который попадает в пайп, будет идти пытаться со скоростью 192Кбит. В итоге получим, что в канале пиковое значение 256Кбит достигнуто не будет и следовательно он не будет шейпится, а на выходе возникнут потери, т.к. наш интерфейс способен обработать только 256Кбит, а не 128+192=320Кбит!!!
Вернуться назад