Dezz
08-12-2006, 09:04
Возникла необходимость использовать несколько фаерволов одновременно. Удобно, когда в ipfw трафик на внешнем интерфейсе перенаправляется на разные NETGRAPH модули, pipe-ы с ограничением ширины канала и т.д. При этом, большинство правил строятся автоматически - программами. PF же используется администратором.
Пошарился по исходному коду, нашёл описание подсистемы pfil, к которой можно подцеплять сколько угодно фильтров. В том месте, где происходит регистрация обработчиков фаерволов нашёл такое место:
/*
* insert the input list in reverse order of the output list
* so that the same path is followed in or out of the kernel.
*/
if (flags & PFIL_IN)
TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
else
TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
return 0;
получается, что для каждого нового подцепляемого фильтра в систему его обработчик входящих пакетов добавляется в начало списка (т.е. он первый будет проверять этот пакет, до добавления нового фильтра) и соответственно, для исходящих пакетов каждый новый добавляемый обработчик добавляется в конец списка.
(man queue)
Вот так добавляет в список обрабочики фаервол ipfw:
pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
вот так pf:
pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
при автоматической загрузке модулей, фри грузит сначало ipfw.ko, потом pf.ko,
получается, что при выходе пакета ipfw будет обрабатывать первой, а потом будет pf...
путь прохождения пакетов следующий:
клиентская машина с адресом 192.168.150.164, шлюз на котором проводятся тесты - 192.168.150.1 и компьютер за шлюзом 192.168.100.1
lnc0 (192.168.150.1 mask /24) - внутренняя подсеть тестового шлюза
lnc1 (192.168.100.9 mask /24) - внешняя подсеть тестового шлюза
ipfw.conf
ipfw add 100 netgraph 61 all from any to any in via lnc1
ipfw add 200 netgraph 60 all from any to any out via lnc1
ipfw add 300 allow all from any to any
на 61,60 узле висит ng_nat
начинаю экспериментировать с pf.conf
1. Первый вариант естественно такой:
pass in all
pass out all
всё работает отлично, пинги проходят с 192.168.150.164 на 192.168.100.1
2. Второй вариант
block in all
block out all
pass on lnc0 from 192.168.150.164 to any
pass on lnc0 from any to 192.168.150.164
pass on lnc1 from 192.168.100.9 to any
pass on lnc1 from any to 192.168.100.9
не работает (пишу всё по памяти, но вроде проходят только ping request наружу)
3. Поэтому добиваю ещё одно правило
block in all
block out all
pass on lnc0 from 192.168.150.164 to any
pass on lnc0 from any to 192.168.150.164
pass on lnc1 from 192.168.100.9 to any
pass on lnc1 from any to 192.168.100.9
pass on lnc1 from any to 192.168.150.164
работает!
Изначально всё соответствует теории, если бы не результаты 2ого и третьего теста...
что это, ошибка условий тестирования? мой косяк?
Или получается, что после того, как меняется адрес назначения пакет проходит, через ip_input ещё раз?
Вот это та часть текста ip_input, где происходит проверка:
/*
* Run through list of hooks for input packets.
*
* NB: Beware of the destination address changing (e.g.
* by NAT rewriting). When this happens, tell
* ip_forward to do the right thing.
*/
/* Jump over all PFIL processing if hooks are not active. */
if (inet_pfil_hook.ph_busy_count == -1)
goto passin;
odst = ip->ip_dst;
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
PFIL_IN, NULL) != 0)
return;
if (m == NULL) /* consumed by filter */
return;
ip = mtod(m, struct ip *);
dchg = (odst.s_addr != ip->ip_dst.s_addr);
я долго ковырялся, пытаясь понять дальнейший путь пакета, но не получилось :)
Может кто-нибудь в курсе как он дальне пойдёт после смены адреса назначения?
Опять штоли на ip_input и опять через все фаерволы прогоняться будет? (изврат)
p.s. писал по памяти, может где-нибудь ошибся
FreeBSD 6.1
Пошарился по исходному коду, нашёл описание подсистемы pfil, к которой можно подцеплять сколько угодно фильтров. В том месте, где происходит регистрация обработчиков фаерволов нашёл такое место:
/*
* insert the input list in reverse order of the output list
* so that the same path is followed in or out of the kernel.
*/
if (flags & PFIL_IN)
TAILQ_INSERT_HEAD(list, pfh1, pfil_link);
else
TAILQ_INSERT_TAIL(list, pfh1, pfil_link);
return 0;
получается, что для каждого нового подцепляемого фильтра в систему его обработчик входящих пакетов добавляется в начало списка (т.е. он первый будет проверять этот пакет, до добавления нового фильтра) и соответственно, для исходящих пакетов каждый новый добавляемый обработчик добавляется в конец списка.
(man queue)
Вот так добавляет в список обрабочики фаервол ipfw:
pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
вот так pf:
pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
при автоматической загрузке модулей, фри грузит сначало ipfw.ko, потом pf.ko,
получается, что при выходе пакета ipfw будет обрабатывать первой, а потом будет pf...
путь прохождения пакетов следующий:
клиентская машина с адресом 192.168.150.164, шлюз на котором проводятся тесты - 192.168.150.1 и компьютер за шлюзом 192.168.100.1
lnc0 (192.168.150.1 mask /24) - внутренняя подсеть тестового шлюза
lnc1 (192.168.100.9 mask /24) - внешняя подсеть тестового шлюза
ipfw.conf
ipfw add 100 netgraph 61 all from any to any in via lnc1
ipfw add 200 netgraph 60 all from any to any out via lnc1
ipfw add 300 allow all from any to any
на 61,60 узле висит ng_nat
начинаю экспериментировать с pf.conf
1. Первый вариант естественно такой:
pass in all
pass out all
всё работает отлично, пинги проходят с 192.168.150.164 на 192.168.100.1
2. Второй вариант
block in all
block out all
pass on lnc0 from 192.168.150.164 to any
pass on lnc0 from any to 192.168.150.164
pass on lnc1 from 192.168.100.9 to any
pass on lnc1 from any to 192.168.100.9
не работает (пишу всё по памяти, но вроде проходят только ping request наружу)
3. Поэтому добиваю ещё одно правило
block in all
block out all
pass on lnc0 from 192.168.150.164 to any
pass on lnc0 from any to 192.168.150.164
pass on lnc1 from 192.168.100.9 to any
pass on lnc1 from any to 192.168.100.9
pass on lnc1 from any to 192.168.150.164
работает!
Изначально всё соответствует теории, если бы не результаты 2ого и третьего теста...
что это, ошибка условий тестирования? мой косяк?
Или получается, что после того, как меняется адрес назначения пакет проходит, через ip_input ещё раз?
Вот это та часть текста ip_input, где происходит проверка:
/*
* Run through list of hooks for input packets.
*
* NB: Beware of the destination address changing (e.g.
* by NAT rewriting). When this happens, tell
* ip_forward to do the right thing.
*/
/* Jump over all PFIL processing if hooks are not active. */
if (inet_pfil_hook.ph_busy_count == -1)
goto passin;
odst = ip->ip_dst;
if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif,
PFIL_IN, NULL) != 0)
return;
if (m == NULL) /* consumed by filter */
return;
ip = mtod(m, struct ip *);
dchg = (odst.s_addr != ip->ip_dst.s_addr);
я долго ковырялся, пытаясь понять дальнейший путь пакета, но не получилось :)
Может кто-нибудь в курсе как он дальне пойдёт после смены адреса назначения?
Опять штоли на ip_input и опять через все фаерволы прогоняться будет? (изврат)
p.s. писал по памяти, может где-нибудь ошибся
FreeBSD 6.1