Итак, очередная попытка досконально разобраться с ipfw свелась к следующему. Извините, если длинно, но мне кажется не один я маюсь с этой проблемой.
В хендбуке
http://www.freebsd.org/doc/handbook/firewalls-ipfw.html
и вот тут:
http://www.unixfaq.ru/index.pl?req=qs&id=286
приводятся похожие схемы реализации nat + statefull filtering (пока опустим dummynet, реализацию прозрачного прокси через fwd и пробрасывания сервисов внутрь сети). Упростим пример, договорившись, что
net.inet.ip.fw.enable=1,
net.link.ether.ipfw=0
net.link.ether.bridge_ipfw=0
т.е. каждый пакет проходит через ipfw два раза - на входе и на выходе ip layer.
# разрешаем запросы из локальной сети
add 100 pass all from any to any via $internal_if
# натим входящие во внешний интерфейс пакеты
add 120 divert natd all from any to $natip in via $natif
# чекстейт :)
add 130 check-state
# проверяем пакеты выходящие из внешнего интерфейса
add 140 skipto 160 all from $internal_network to any out via $natif keep-state
# запрещаем всё
add 150 deny log all from any to any
# Секция, куда переходим по skipto
add 160 divert natd all from $internal_network to any out via $natif
add 170 pass all from any to any
Теперь представим себя пакетом с машины из локалки идущим по 80 порту, к примеру:
1) Пакет входит в $internal_if, срабатывает правило 100, файрвол заканчивает работу.
2) Пакет выходит из $natif, срабатывает правило 140, запоминаем коннекшн в keep-state, и выполняется правило 160. Пакету переписывается адрес отправителя, теперь там адрес $natif. Вот тут получается непонятка. В man ipfw написано, что правило divert "terminates search", т.е. по идее пакет должен выходить из файрвола, ан нет! Выполняется правило 170. Пакет ушел на запрашиваемый сайт.
3) Ответ от сервера попадает на внешний интерфейс. Срабатывает правило 120. Пакету переписывается адрес назначения - теперь это адрес машины в локалке, которая запросила страницу. Выполняется правило 130. Оно, если верить man ipfw дёргает то правило, которое устнавливало соединение, т.е. 140, идём на 160 (пропускаем его, условие не выполняется) и выполняется 170.
Вроде бы всё логично, поправьте где ошибаюсь...
Теперь ситуация 2. Я представляю себя злобным пакетом идущим на 80 порт внешнего интерфейса $natif.
1) Пакет входит в файрвол
2) Срабатывает правило 120... Вопрос: как срабатывает? Мне кажется, что пакет просто не изменяется, ведь в таблице NAT'а записи о нём нет?
3) Выполняется 150, пакет запрещается, файрвол заканчивает работу.
Вот так. Теперь скажите где я гоню :)