>>>> Вам стоит указать версию, на которой производились эксперименты - в >>>> ядре могло что-то меняться, например, порядок загрузки подсистем >>>> точно правили. Я провел сейчас эксперимент на 6.2, в GENERIC был >>>> загружен модулем ipfw, затем pf: block drop in proto icmp all >>>> сработал для входящего первым, в ipfw count in proto icmp осталось по >>>> нулям, для направления наружу наоборот, счетчик в ipfw увеличился, >>>> потом пакет был дропнут pf. То есть схема соответствует - добавивший >>>> свой хук последним на входе будет первым, на выходе последним.
>>> Спасибо за дополнение! указал в статье.
>>> Но, у меня на 6.2, и 6.4-PR схема осталась без изменений (pf, ipfw >>> вкомпилены в ядро)
>>> что противоречит схеме в статье Всеволода (при вкомпиленных фаерах): >>> ipfw -> pf -> ipfilter -> stack - для входящего >>> stack -> ipfilter -> pf -> ipfw - для исходящего
>>> В чем же тогда ошибка ??
>> Мой эксперимент относился к фразе:
>> ВНИМАНИЕ: тут мне кажется, что Всеволод где-то перепутал порядок. >> Исходя из альтернативной информации, и личных экспериментов: >> "То есть, для входящего трафика модуль, добавивший свой хук >> последним, будет обрабатывать пакеты первым^W - последним"
>> Эксперимент показал, что загруженный последним pf - сел на входящий >> трафик первым хуком, а вовсе не последним, как в цитате, то есть в этом >> вопросе у Всеволода всё верно, а в цитате нет. Эксперимент был про >> инвертирование порядка на входе.
> Допустим, так.
> Тогда не могли бы вы сначала загрузить pf, затем ipfw, и посмотреть > порядок прохождения.
> Я только что провел эксперимент на 7STABLE (7.1-PRERELEASE) > и попрежнему получил > --> [pf] --> [ipfw] inbound traffic > --> [ipfw] --> [pf] --> outbound traffic
> (pf, ipfw вкомпилены в ядро)
> Итого: > согласно порядку загрузки подсистем, порядок загрузки модулей: ipfilter > -> pf -> ipfw > при этом получится что ipfw зарегистрирует свой хук последним, и должен > будет обрабатывать пакеты первым, а это уже идет в разрез с > экспериментами ( на 6 и 7 стейбл )
Что ж, провел эксперимент, запись ниже. После пинга гугла и просмотра состояния ipfw я делал пинг подопытной машинки снаружи. Был немало озадачен тем, что сначала получил такое же поведение, как в прошлый раз, когда ipfw был загружен первым. После чего выгрузил оба модуля, полез в сырцы, загрузил снова, обратить внимание на измененный порядок команд (кто-нибудь догадается уже из записи, но на всякий случай объясню потом):
nuclight:~# kldunload pf nuclight:~# kldunload ipfw nuclight:~# ipfw show ipfw: getsockopt(IP_FW_GET): Protocol not available nuclight:~# kldload pf nuclight:~# kldload ipfw && ipfw add pass all from any to any 00100 allow ip from any to any nuclight:~# ipfw add 50 count icmp from any to any in 00050 count icmp from any to any in nuclight:~# ipfw add 50 count icmp from any to any out 00050 count icmp from any to any out nuclight:~# grep -v '^#' /etc/pf.conf pass in all pass out all block in proto icmp block out proto icmp nuclight:~# pfctl -f /etc/pf.conf No ALTQ support in kernel ALTQ related functions disabled nuclight:~# pfctl -e No ALTQ support in kernel ALTQ related functions disabled pf enabled nuclight:~# ping google.com PING google.com (74.125.45.100): 56 data bytes ping: sendto: Operation not permitted ^C --- google.com ping statistics --- 1 packets transmitted, 0 packets received, 100% packet loss nuclight:~# ipfw show 00050 0 0 count icmp from any to any in 00050 1 84 count icmp from any to any out 00100 437 40167 allow ip from any to any 65535 0 0 deny ip from any to any nuclight:~# ipfw show 00050 0 0 count icmp from any to any in 00050 1 84 count icmp from any to any out 00100 456 42564 allow ip from any to any 65535 0 0 deny ip from any to any nuclight:~# pfctl -vs rules No ALTQ support in kernel ALTQ related functions disabled pass in all [ Evaluations: 146 Packets: 89 Bytes: 6961 States: 0 ] pass out all [ Evaluations: 146 Packets: 53 Bytes: 6920 States: 0 ] block drop in proto icmp all [ Evaluations: 146 Packets: 3 Bytes: 252 States: 0 ] block drop out proto icmp all [ Evaluations: 58 Packets: 1 Bytes: 84 States: 0 ] nuclight:~# kldunload ipfw nuclight:~# kldunload pf nuclight:~# kldload pf nuclight:~# pfctl -f /etc/pf.conf No ALTQ support in kernel ALTQ related functions disabled nuclight:~# pfctl -e No ALTQ support in kernel ALTQ related functions disabled pf enabled nuclight:~# kldload ipfw && ipfw add pass all from any to any 00100 allow ip from any to any nuclight:~# ipfw -q add 50 count icmp from any to any in nuclight:~# ipfw -q add 50 count icmp from any to any out nuclight:~# ping google.com PING google.com (209.85.171.100): 56 data bytes ping: sendto: Operation not permitted ^C --- google.com ping statistics --- 1 packets transmitted, 0 packets received, 100% packet loss nuclight:~# ipfw show 00050 0 0 count icmp from any to any in 00050 0 0 count icmp from any to any out 00100 271 45097 allow ip from any to any 65535 0 0 deny ip from any to any nuclight:~# pfctl -vs rules No ALTQ support in kernel ALTQ related functions disabled pass in all [ Evaluations: 350 Packets: 212 Bytes: 26378 States: 0 ] pass out all [ Evaluations: 350 Packets: 137 Bytes: 26118 States: 0 ] block drop in proto icmp all [ Evaluations: 350 Packets: 0 Bytes: 0 States: 0 ] block drop out proto icmp all [ Evaluations: 138 Packets: 1 Bytes: 84 States: 0 ] nuclight:~# pfctl -vs rules No ALTQ support in kernel ALTQ related functions disabled pass in all [ Evaluations: 371 Packets: 223 Bytes: 27229 States: 0 ] pass out all [ Evaluations: 371 Packets: 145 Bytes: 27654 States: 0 ] block drop in proto icmp all [ Evaluations: 371 Packets: 2 Bytes: 168 States: 0 ] block drop out proto icmp all [ Evaluations: 149 Packets: 1 Bytes: 84 States: 0 ] nuclight:~# ipfw show 00050 2 168 count icmp from any to any in 00050 0 0 count icmp from any to any out 00100 363 54560 allow ip from any to any 65535 0 0 deny ip from any to any nuclight:~# kldunload pf
А оказалось вот что: pfctl -d/-e контролирует как раз регистрирование/разрегистрирование хука. То есть, получается, что при загрузке, что модуля, что вкомпилированным в ядро, pf никаких хуков не регистрирует вообще - это происходит позже в момент pfctl -e, и может получиться как у меня, что он всегда будет в одном и том же порядке. Значит, в 7-ке поведение ipfw при enable/disbale унифицировали с pf, и без всяких компиляций и манипуляций с модулями простой последовательностью команд можно иметь гарантированный порядок хуков, независимо от. Правда, и напороться на какие-нибудь грабли - тоже. Таким образом, часть статьи, посвященная порядку загрузки подсистем, актуальна лишь для ipfilter на 7-ке и ipfw с ipfilter на 6-ке.
Вот окончательная истина, стало быть. Если, конечно, в коде регистрации/дерегистрации хуков в файрволах опять ничего не поменяют :)
Friday, December 5, 2008, 2:51:59 PM, Vadim wrote:
>> Сейчас переписал правила:
>> ${fwcmd} add 1000 deny ip from any to ${bad_int_ip} via ${ext_if} in >> ${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
>> Если применяю хотя бы одно из правил, то ${bad_ext_ip} проначеный в >> ${bad_int_ip} перестает пинговаться. Правила PF: > Так а на каком из них счетчики растут?
На обоих.
> Пинг ведь есть не только запросы, но и ответы :)
Раньше я об этом догадывался..., теперь я точно уверен! ;)
Но суть то от этого не меняется. Для ipfw в данном случае без разницы - запрос это или ответ.
> Поскольку работают оба файрвола, они в итоге оба срабатывают и при > отсутствии ната заблокирует любой.
PF я использую только для NAT'а.
>> binat on $ext_if from $slow_int_ip to any -> $slow_ext_ip >> binat on $ext_if from $bad_int_ip to any -> $bad_ext_ip
>> nat on $int_if from any to $int_if:network -> $int_if
>> Может я где-то что-то путаю? > Положим, цепочка выглядит так:
in: pf ->> ipfw out: ipfw ->> pf
Это применительно к интерфейсу или к ядру вцелом?
> Тогда на in via $ext_if сначала в pf в dst возникнет ${bad_int_ip}, а > потом 1000 правило ipfw его дропнет.
Да.
> А на in via $int_if c адресом > ${bad_int_ip} pf еще ничего не сделает, binat сработает обратно на out via > $ext_if, поэтому ответ на пинг должен попасть в правило 1010 и дропнуться. > Вроде бы так.
Хорошо, проводим тест.
pf.conf:
set skip on lo
scrub in all fragment reassemble scrub out all random-id
binat on $ext_if from $slow_int_ip to any -> $slow_ext_ip binat on $ext_if from $bad_int_ip to any -> $bad_ext_ip
nat on $int_if from any to $int_if:network -> $int_if
pass in pass out
Криминального ничего нет, один NAT. Посему его трогать не будем.
В ipfw.conf добавляю правило для внешнего интерфейса:
${fwcmd} add 1000 deny ip from any to ${bad_ext_ip} via ${ext_if} in
01000 0 0 deny ip from any to 1.2.3.34 via em0 in 65535 1404658 191750022 Fri Dec 5 21:25:07 2008 allow ip from any to any
ping проходит, счетчики по нулям.
меняю правило:
${fwcmd} add 1000 deny ip from any to ${bad_int_ip} via ${ext_if} in
01000 2 120 Fri Dec 5 21:26:16 2008 deny ip from any to 10.11.1.34 via em0 in 65535 1405262 191813657 Fri Dec 5 21:26:18 2008 allow ip from any to any
ping не прошел, счетчики считают пакеты.
На внешнем интерфейсе: PF(NAT) -> ipfw.
Теперь внутренний интерфейс (на внешнем никаких правил нет):
${fwcmd} add 1010 deny ip from ${bad_ext_ip} to any via ${int_if} in
01010 0 0 deny ip from 1.2.3.34 to any via em1 in 65535 1406225 191951163 Fri Dec 5 21:29:03 2008 allow ip from any to any
пинг проходит, счетчики по нулям.
Меняем правило
${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
01010 2 120 Fri Dec 5 21:30:38 2008 deny ip from 10.11.1.34 to any via em1 in 65535 1407795 192108052 Fri Dec 5 21:30:42 2008 allow ip from any to any
Пинг не прошел, пакеты посчитали.
Соответственно для внутреннего интерфейса схема следующая: ipfw -> PF (NAT)
как то у вас сложная схема...(все удаленное выше) и не понятно откуда и куда делаете пинги.
Ядро ведь не различается внешний и внутренний интерфейс, это абстракция, потому не стоит к ним привязываться. Также в данной схеме все очень зависит от порядка следования пакетов. Транзитный пакет через роутер из локалки для внутреннего интерфейса будет входящим а для внешнего исходящим.
PS. попробуйте на PF сделать запрещающее правило и поппинговать роутер из локалки. На счетчиках ipfw ничего не должно появится.
> как то у вас сложная схема...(все удаленное выше) и не понятно откуда и > куда делаете пинги.
Ping'аю снаружи внешний интерфейс, который пробрасывается NAT'ом во внутреннюю подсеть.
> Ядро ведь не различается внешний и внутренний интерфейс, это абстракция, > потому не стоит к ним привязываться.
Согласен.
> Также в данной схеме все очень зависит от порядка следования пакетов. > Транзитный пакет через роутер из локалки для внутреннего интерфейса > будет входящим а для внешнего исходящим. > PS. попробуйте на PF сделать запрещающее правило и поппинговать роутер > из локалки. На счетчиках ipfw ничего не должно появится.
Добавил в pf.conf правило
block in quick on $int_if from $bad_int_ip to any
Пинги с $bad_int_ip не проходят. Счетчики в ipfw по нулям.
Тем не менее, если пингаю внешний интерфейс проначенный на внутренний IP, счетчики в ipfw срабатывают
01100 15 1260 prob 0.200000 deny ip from any to 10.11.1.34 via em0 in 01110 24 2016 prob 0.200000 deny ip from 10.11.1.34 to any via em1 in
и сумма потерянных пакетов равна сумме probability в 2х правилах ipfw:
100 packets transmitted, 61 received, 39% packet loss, time 99044ms rtt min/avg/max/mdev = 0.749/9.581/509.228/64.507 ms
причем в обоих правилах указывается ip address внутреннего сервера. Либо я что-то не до конца понимаю, либо... у меня нет вариантов :)
Снимите с ручника в другом таске :)
Добавил алиас на внутренний Win2k3 сервер и алиас на внешний интерфейс FreeBSD. На новом адресе необходимо эмулировать низкоскоростное соединение.
Без шейперов с одним натом на PF все отлично работает, внешний интерфейс пингуется, tcpdump видит пакеты на внутреннем интерфейсе:
10:02:30.781250 IP 10.11.1.28 > 10.11.1.33: ICMP echo request, id 63600, seq 1, length 64 10:02:30.781457 IP 10.11.1.33 > 10.11.1.28: ICMP echo reply, id 63600, seq 1, length 64 10:02:31.778451 IP 10.11.1.28 > 10.11.1.33: ICMP echo request, id 63600, seq 2, length 64 10:02:31.778756 IP 10.11.1.33 > 10.11.1.28: ICMP echo reply, id 63600, seq 2, length 64
Добавляю правило шейпера на внешний интерфейс FreeBSD:
${fwcmd} pipe 10 config bw 56Kbit/s queue 5KBytes
${fwcmd} add 1000 pipe 10 ip from any to ${slow_int_ip} via ${ext_if} in
${fwcmd} add 1100 prob 0.2 deny ip from any to ${bad_int_ip} via ${ext_if} in ${fwcmd} add 1110 prob 0.2 deny ip from ${bad_int_ip} to any via ${int_if} in
tcpdump на внутреннем интерфейсе 'tcpdump -i em1 host 10.11.1.33' молчит как партизан.
Зато счетчик пакеты считает:
01000 135 11340 pipe 10 ip from any to 10.11.1.33 via em0 in 01100 0 0 prob 0.200000 deny ip from any to 10.11.1.34 via em0 in 01110 0 0 prob 0.200000 deny ip from 10.11.1.34 to any via em1 in 65535 1752809 234176958 allow ip from any to any
>>> ${fwcmd} add 1000 deny ip from any to ${bad_int_ip} via ${ext_if} in >>> ${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
>>> Если применяю хотя бы одно из правил, то ${bad_ext_ip} проначеный в >>> ${bad_int_ip} перестает пинговаться. Правила PF:
>> Так а на каком из них счетчики растут?
> На обоих.
>> Пинг ведь есть не только запросы, но и ответы :)
> Раньше я об этом догадывался..., теперь я точно уверен! ;)
> Но суть то от этого не меняется. Для ipfw в данном случае без разницы > - запрос это или ответ.
Есть, на каком интерфейсе какое сработает, in или out. Для результата, конечно, не важно.
>> Положим, цепочка выглядит так:
> in: pf ->> ipfw > out: ipfw ->> pf
> Это применительно к интерфейсу или к ядру вцелом?
К ядру, какое ему дело до интерфейсов...
> Теперь внутренний интерфейс (на внешнем никаких правил нет):
> ${fwcmd} add 1010 deny ip from ${bad_ext_ip} to any via ${int_if} in
> 01010 0 0 deny ip from 1.2.3.34 to > any via em1 in > 65535 1406225 191951163 Fri Dec 5 21:29:03 2008 allow ip from any to any
> пинг проходит, счетчики по нулям.
Дык откуда на _внутреннем_ интерфейсе, из локалки взяться _входящему_ ВНЕШНЕМУ айпищнику? там всегда будут нули.
> Меняем правило
> ${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
> 01010 2 120 Fri Dec 5 21:30:38 2008 deny ip from 10.11.1.34 > to any via em1 in > 65535 1407795 192108052 Fri Dec 5 21:30:42 2008 allow ip from any to any
> Пинг не прошел, пакеты посчитали.
Каким бы ни был порядок, на внутреннем интерфейсе это правило всегда сработает, нат же на внешнем.
> 06.12.08 @ 02:44 Sergey A. Kobzar wrote: >>>> Сейчас переписал правила:
>>>> ${fwcmd} add 1000 deny ip from any to ${bad_int_ip} via ${ext_if} in >>>> ${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
>>>> Если применяю хотя бы одно из правил, то ${bad_ext_ip} проначеный в >>>> ${bad_int_ip} перестает пинговаться. Правила PF:
>>> Так а на каком из них счетчики растут?
>> На обоих.
>>> Пинг ведь есть не только запросы, но и ответы :)
>> Раньше я об этом догадывался..., теперь я точно уверен! ;)
>> Но суть то от этого не меняется. Для ipfw в данном случае без разницы >> - запрос это или ответ. > Есть, на каком интерфейсе какое сработает, in или out. Для результата, > конечно, не важно. >>> Положим, цепочка выглядит так:
>> in: pf ->> ipfw >> out: ipfw ->> pf
>> Это применительно к интерфейсу или к ядру вцелом? > К ядру, какое ему дело до интерфейсов... >> Теперь внутренний интерфейс (на внешнем никаких правил нет):
>> ${fwcmd} add 1010 deny ip from ${bad_ext_ip} to any via ${int_if} in
>> 01010 0 0 deny ip from 1.2.3.34 to >> any via em1 in >> 65535 1406225 191951163 Fri Dec 5 21:29:03 2008 allow ip from any to any
>> пинг проходит, счетчики по нулям. > Дык откуда на _внутреннем_ интерфейсе, из локалки взяться _входящему_ > ВНЕШНЕМУ айпищнику? там всегда будут нули. >> Меняем правило
>> ${fwcmd} add 1010 deny ip from ${bad_int_ip} to any via ${int_if} in
>> 01010 2 120 Fri Dec 5 21:30:38 2008 deny ip from 10.11.1.34 >> to any via em1 in >> 65535 1407795 192108052 Fri Dec 5 21:30:42 2008 allow ip from any to any
>> Пинг не прошел, пакеты посчитали. > Каким бы ни был порядок, на внутреннем интерфейсе это правило всегда > сработает, нат же на внешнем.
Согласен. Просто показал все возможные комбинации :)