Современные
информационные технологии/Вычислительная техника и программирование
Мясищев А.А.
Хмельницкий национальный
университет, Украина
Резервирование каналов Интернет с
помощью ipfw
nat
на маршрутизаторах под UNIX
FreeBSD
В
локальных сетях организаций, которые имеют выход в Internet через несколько внешних каналов, иногда требуется
такое подключение нескольких «важных» серверов, при котором в случае
исчезновения связи по одному из каналов сервера переподключаются автоматически
к другому каналу. Рассмотрим решение этой задачи, когда в качестве
маршрутизатора используется компьютер с ОС Unix FreeBSD 7.3 и установленным
там ipfw nat(«ядерным»
nat, который появился в FreeBSD с версии 7.0).
Однако
перед решением задачи рассмотрим более детально, как происходит движение
трафика в стеке FreeBSD (рис.1).
Рис.1.
Простейший маршрутизатор обычно использует
два интерфейса, через который проходит трафик. Через каждый интерфейс трафик
идет как на вход, так и на выход. Поэтому каждый интерфейс логически имеет два
прохода out и in. Проходы
in
и
out
важны тем, что при поступлении в них сетевого трафика, этот трафик попадает в
фаервол, где проходит через правила фильтрации ipfw. Таким образом, трафик,
проходящий через маршрутизатор, проходит через правила ipfw два раза - на
проходе IN сетевого адаптера через который он был получен, и на проходе
out
сетевого адаптера через который он будет передан.
Рассмотрим
пример [1]. Допустим, что имеем
следующий набор правил:
ipfw
add
1
deny
tcp
from
any
to
any
135,445
ipfw
add
2
divert
8668
all
from
any
to
any
via
ext
0
ipfw
add
3
count
icmp from any to any
ipfw
add 4 allow all from any to any
#
в
65535
по
умолчанию
deny
Когда пакет проходит через машину, к
нему системой прикрепляется дополнительная информация, помимо собственно его
содержимого, видного в tcpdump. Например, на каком интерфейсе он был получен,
через какой отправляется, и т.п. Эту информацию можно проверять соответствующими
опциями в правилах ipfw. На рис.1 показаны места, где будут срабатывать
соответствующие указания in/out и recv/xmit для сетевых адаптеров.
В соответствии с рис.1 рассмотрим
более подробно прохождение пакетов через интерфейс, предполагая, что они
предварительно обработаны подсистемой
Ethernet
и попали на интерфейс как
ip
пакеты.
IP
пакет на входе попадает в функцию ip_input(), в точку (2),
где выполняются базовые проверки на корректность пакета, после чего пакет приходит
в ipfw - функция ipfw_chk(). Допустим, правила были простые, без использования
других подсистем. Тогда, вернувшись из ipfw, пакет продолжает движение по
ip_input(), которая смотрит, предназначен ли пакет нашей машине либо кому-то
другому. Если нам, то пакет уходит в точку (3), где решится, в какую программу
его отправить.
Если же пакет был предназначен не нам,
то он из ip_input() направится в точку (4), где ip_forward() проверит,
установлен ли sysctl, разрешающий форвардинг, произведет уменьшение на единицу
TTL и другие действия. После этого пакет придет в точку (6) - функцию
ip_output(). Туда же он попадет напрямую, когда какая-нибудь программа решит
что-то отправить в сеть. Функция
ip_output() вначале смотрит в таблицу маршрутизации, определяя, на какой
интерфейс и на какой шлюз надо направить пакет. С этой информацией пакет вновь
передается в ipfw, в котором опять пробегается по всем правилам. После выхода
из ipfw_chk() в ip_output(), если ядро было скомпилировано с соответствующей
опцией, проверяется, не был ли применен ipfw fwd - если да, то просмотр
таблицы маршрутизации выполняется заново с целью получить MAC-адрес
нового шлюза. Затем пакет в точке (7) покидает ip_output() и передается дальше,
на 2-й уровень модели
OSI
и к драйверам интерфейсов.
Теперь, предположим, что в правилах
файрвола появляется divert(смотри приведенные выше правила). Предположим, что
пакет из внутренней локальной сети должен пойти в Интернет на порт 80. Тогда
путь
следования будет
таким. Пакет войдет на внутреннем интерфейсе в точку (1), пройдет начальные
проверки в функции ip_input() на корректность в (2), будет передан в ipfw_chk()
и начнет проходить по правилам. Под правило 1 пакет не подпадает, под 2 тоже, так как имя интерфейса сейчас
int0(интерфейс внутренней сети). Правило
3 не срабатывает, а под правило 4 подходят все пакеты, и он выходит из
ipfw_chk() дальше в ip_input(). В этой функции
выясняется, что предназначен он для сети Интернет, поэтому пакет попадает в
точку (4) и затем в (6), где ip_output() определяет адрес выходящего интерфейса
и шлюза. Интерфейсом будет ext0, с чем
пакет и попадает опять в ipfw_chk() и снова идет по правилам. Правило 1 снова
не подходит, но условие правила 2 срабатывает - "
from
any
to
any
via ext0”, соответствующее проходу через интерфейс ext0 в
любом направлении. Здесь срабатывает divert - пакет из ipfw_chk() передается в
точку (8), в подсистему divert, при этом к нему предварительно прикрепляется
метаинформация с направлением (out), интерфейсом (ext0) и номером правила 2.
Подсистема divert передает этот пакет в указанный в правиле порт (8668), на
котором работает natd. Он обрабатывает пакет, метаинформацию не трогает, и
возвращает подсистеме divert измененный пакет. Подсистема divert выводит
полученный из natd пакет из точки (9) в точку (6). Далее пакет попадает в
ip_output() еще раз. Потом пакет опять входит в ipfw_chk() и в нем проверяется
номер правила, которое соответствует 2. Далее ipfw_chk() пропускает
правила номер 1 и 2, и начинает с номера 3. (в противном случае пакет снова
попал бы в divert, и получился бы бесконечный цикл). На этом месте пакет
продолжит движение с правила номер 3, под которое он не попадет, а по правилу 4
уйдет в точку 7 и далее в сеть. Таким образом, несмотря на то, что пакет
попадал в ip_output() два раза, с точки зрения пользователя это выглядит так,
как если бы он был там один раз и
никуда из файрвола не уходил - просто на правиле 2 в пакете поменялись адреса и
порты в соответствии с настройками
nat
.
Аналогичным образом, ответный пакет,
возвращающийся из Интернета на интерфейс ext0, пройдет через машину по пути (1)
- (2). Функцией ip_input() пакет будет передан на ipfw_chk() и пойдет по правилу 1, правилу 2, которое передаст
его в точку (8). Дальше он попадает в
divert, natd, divert и выйдет в точку (9) и далее в (2). Снова вернется на ipfw_chk() но на правило 3, затем на
правило 4. После него в точку (4), потом в
(6) на интерфейс
int0
.
Функция ip_output() передаст пакет на ipfw_chk(), который пойдет по правилам 1, 2 , 3. После правила 4 –
пакет попадет в точку (7) которая соответствует его отправке через интерфейс
int0.
Подобное выведение пакета из обработки
ipfw в другую подсистему характерно не толька для divert, но и для pipe и queue
в dummynet, передача пакета в netgraph, а также и для ipfw nat, который появился в
FreeBSD
7.0. Отличие в том, что в последних подсистемах пакет
остается внутри ядра, никакому демону не передается (т.е.
natd
). Поэтому, во-первых, подсистемы вместо номера правила
сохраняют на пакет полный указатель, и он вернется непосредственно в следующее
правило, даже если оно имеет тот же номер. Во-вторых, для таких подсистем
действует настройка one_pass в sysctl. Если net.inet.ip.fw.one_pass=1, то при повторном
входе пакета в ipfw после возврата из подсистемы dummynet (netgraph),
ipfw_chk() сразу вернет пакет в ip_output() (ip_
input
t() ) без прохода по правилам, как если бы к пакету был
применен allow. Это поведение позволяет упростить правила файрвола, когда
известно, что если пакет попал в трубу, то он уже точно отправляется дальше без
возврата на
ipfw
,
и не требуется после каждого pipe вставлять allow (чтобы пакет не попал в
следующие правила и следующие pipe/queue). Если же конфигурация требует сначала
ограничить трафик, а потом уже разбираться по правилам, что разрешить, а что
запретить, то упрощению правил будет способствовать отключенный one_pass (net.inet.ip.fw.one_pass=0).
Таким образом, пакет проходит по списку правил последовательно, в порядке возрастания номеров правил. Список правил можно рассматривать как таблицу с тремя столбцами: номер, действие (
allow
,
deny
,
nat
,
pipe
) и условия (from any to 192.168.0.0/16 in
via
em0). Таблица просматривается сверху вниз, пакет сравнивается с условиями. На первом совпавшем условии система смотрит в столбец действий, выполняет действия, прекращает просмотр и ... выполняет дальнейшие действия.
Механизм ipfw nat можно рассматривать как своеобразный фильтр-преобразователь трафика. В зависимости от того, как настроен
nat
, и от того какие IP адреса отправителя и получателя есть в проходящем через него пакете,
nat
будет преобразовывать в пакете IP адрес отправителя, либо IP адрес получателя, или же просто отвергать пакет. Важно знать, что
nat
разделяет трафик на исходящий (тот который надо маскировать) и входящий (тот который надо демаскировать) в зависимости от того, на каком проходе(
out
или
in
)трафик был получен. Так, трафик, попавший в
nat
из прохода
out
, требуется маскировать (заменить IP адрес отправителя на IP адрес
nat
машины), а трафик пришедший из прохода
in
демаскировать. На поведение механизма nat влияет настройка параметра one_pass. В зависимости от ее значения трафик прошедший через
nat
может либо вернуться в проход фаервола из которого он был направлен в
nat
(net.inet.ip.fw.one_pass=0), либо выйти из фаервола (net.inet.ip.fw.one_pass=1). Такая гибкость дает возможность делать с трафиком много полезных вещей. ipfw nat позволяет запускать множество своих экземпляров, каждый из которых имеет свою
nat
-таблицу и настройки.
Рассмотрим некоторые возможности ipwf nat, которые необходимы для решения поставленной задачи и некоторые параметры конфигурации.
Некоторыепараметры конфигурации
ipfw
nat
if
nic
-
Параметр предписывает
ip
адрес используемый при маскировании и демаскировании, на основе имеющихся настроек для сетевого интерфейса с именем "nic".
deni
_
in
-
запрещает пропускать через nat входящие пакеты для которых нет совпадения во внутренней таблице активных соединений, или же нет совпадения с другими правилами демаскировки. Если данный параметр не установлен то для входящих соединений будет создаваться новая запись в таблице активных соединений и пакет будет пропускаться.
same_ports
- параметр предлагает механизму nat поведение при котором тот будет стараться сохранять оригинальные номера портов в уходящих(маскируемых) пакетах.
r
eset
- предписывает очищать внутреннюю таблицу активных соединений при изменениях параметра "ip", указывающего адрес используемый при маскировании и демаскировании.
redirect_addr localIP publicIP
- параметр предписывает проводить перенаправление трафика поступающего на внешний IP адрес (publicIP), на машину с IP адресом во внутренней сети (localIP). Пример:
redirect_addr 192.168.1.36 212.111.198.77
redirect_port proto targetIP:targetPORT[-targetPORT][aliasIP:]aliasPORT[-aliasPORT][remoteIP[:remotePORT[-remotePORT]]]
-
параметр
предписывает
проводить
перенаправление
входящих
соединений
поступающих
на
указанный
номер
порта
(
ов
),
на
другой
хост
и
порт
(
ы
).
Аргумент "proto" –
tcp
либо
udp
. Аргумент "targetIP" указывает IP адрес, на который должна происходить пересылка трафика, а аргумент "targetPORT" порт (или диапазон портов) на который будет перенаправлен трафик. Аргумент "aliasIP" - IP адрес входящих соединений, "aliasPORT" - номер порта входящих соединений. Аргументы "remoteIP" и "remotePORT" –указывают удаленные источники/назначения трафика. Пример:
redirect
_
port
tcp
192.168.100.65:
telnet
8088 -
означает, что входящие TCP пакеты, направляемые на порт 8088
nat
машины, будут перенаправлены на порт 23 (telnet) машины с
ip
адресом 192.168.100.65
Для включения
ipfw
,
nat
,
forwarding
,
divert
и
Dummynet
необходима пересборка ядра в нашем случае для системы
Unix
FreeBSD
7.3 со следующими параметрами:
options
IPFIREWALL
#собственно файрвол
options
IPFIREWALL
_
VERBOSE
#логгинг пакетов
options IPFIREWALL_VERBOSE_LIMIT=10 #
ограничение
логов
options IPFIREWALL_DEFAULT_TO_ACCEPT #
разрешающее
правило
options
IPFIREWALL
_
NAT
#разрешение “ядерного”
nat
options
IPFIREWALL
_
FORWARD
# перенаправление пакетов
options LIBALIAS #
библиотека
nat
options
IPDIVERT
#если нужен “обычный” NAT (трансляция адресов)
options ROUTETABLES=2 #включение 2-х таблиц маршрутизации
options DUMMYNET #включение ограничения скорости
options HZ="1000"
Рис.2
На рис.2 представлена схема фрагмента подключения двух локальных сетей к
router
-у
NAT
через два сетевых адаптера
fxp
0(сеть 172.20.0.0/16) и
rl
0(172.21.0.0/16). С другой стороны этот
router
подключен к Интернет через два адаптера –
re
0(78.152.183.32/27 -
Infocom
) и
re
1(212.111.198.32/28 -
URAN
). “Важный” сервер находится в локальной сети 172.20.0.0/16 и имеет адрес 172.20.6.37. Требуется, чтобы по умолчанию он работал в Интернет через сеть 212.111.198.32/28 и был виден с Интернет по адресу 212.111.198.37. В случае обрыва связи работа с сервером переключалась на канал Интернет по сети 78.152.183.32/27, а с Интернет он был бы виден по адресу 78.152.183.35. С сети
Internet
необходимо разрешить
telnet
, т.е. по команде
telnet
78.152.183.34 8023
подключение к
router
-у
NAT
, а по команде
telnet
78.152.183.34 8024
подключение к локальному компьютеру 172.21.8.2. Аналогично по команде
telnet
212.111.198.39 8023
подключение по
telnet
к
NAT
, а по команде
telnet
212.111.198.39 8024
подключение к локальному компьютеру 172.20.5.3
Необходимо также обеспечить прохождение пакетов для
DNS
запросов (порт 53) через интерфейс
re
0, так как
router
NAT
является также
DNS
сервером. Сервер (172.20.6.37) должен иметь внешнее имя
ed
.
tup
.
km
.
ua
и отзываться по нему в случае обрыва канала. Узлы сети 172.20.0.0/16 должны разделять между собой один канал
pipe
1 с пропускной способностью
3024KBit/s. Также должны выполняться следующие скоростные условия: узел
172.21.8.1 имеет выход в Internet со скоростью pipe 5 - 3024KBit/s,узел
172.21.8.2 - pipe 10 - 2024KBit/s,узел
172.21.8.3 - pipe 15 - 4096KBit/s,узел
172.21.8.4 - pipe 20 - 3024KBit/s иузел
172.21.8.200 разделяет с узлом 172.21.8.3 канал pipe 15 со скоростью 4096KBit/s.
Так как ядро
router
-а
NAT
собрано с опцией ROUTETABLES=2, то он поддерживает работу с двумя таблицами маршрутизации. Примем, что трафику, исходящему из сети 172.20.0.0/16 будет назначена таблица маршрутизации 0 (таблица по умолчанию со шлюзом 212.111.198.33), а трафику из сети 172.21.0.0/16 – таблица маршрутизации 1 (для нее шлюз по умолчанию 78.152.183.33).
Тогда /
etc
/
rc
.
conf
будет выглядеть следующим образом:
gateway_enable="YES"
hostname="nat.tup"
ifconfig_rl0="inet 172.21.88.1 netmask 255.255.0.0"
ifconfig_fxp0="inet 172.20.50.2 netmask 255.255.0.0"
ifconfig_re0="inet 78.152.183.34 netmask 255.255.255.224"
ifconfig_re0_alias0="inet
78.152.183.35 netmask
255.255.255.224"
ifconfig_re1="inet 212.111.198.39 netmask 255.255.255.240"
ifconfig_re1_alias0="inet
212.111.198.37 netmask
255.255.255.240"
inetd_enable="YES"
sshd_enable="YES"
firewall_enable="YES"
firewall_script="/etc/firewall"
Файл /etc/sysctl.conf
описывает вариант, когда пакет после захода в
nat
,
pipe
возвращается опять в правила
ipfw
:
net.inet.ip.fw.one_pass=0
Файл
/etc/rc.local
setfib 0 route add default 212.111.198.33
setfib 1 route add default 78.152.183.33
/usr/sbin/named -c /etc/namedb/named.conf
/usr/home/alex/ru.exe &
Первая и вторая строки (setlib) назначают для 0-й и 1-й таблиц маршрутизации шлюзы
по умолчанию. В четвертой строке запускается скрипт, необходимый для мониторинга основного канала через re1(URAN). В 3-й
строке запускается кэширующий DNS сервер.
Скрипт /usr/home/alex/ru.exe:
sleep 60
/usr/home/alex/monit.exe &
sleep 10
echo Load ROUT
/usr/home/alex/rout.exe &
Задержка 60 секунд необходима для гарантированного
поднятия интерфейсов router-а NAT. Скрипт /usr/home/alex/monit.exe, используя
команду ping, проверяет работоспособность канала URAN. Если пакеты теряются на 100% при 5-и пингах, то
формируется “непустой”файл /usr/home/alex/los.dat.
/usr/home/alex/monit.exe:
#!/bin/sh
while [ 1 ]
do
sleep
5
/sbin/ping -c 5 212.111.195.121 > /usr/home/alex/pin.dat
cat
/usr/home/alex/pin.dat | grep "100.0% packet loss" >
/usr/home/alex/los.dat
done
Скрипт /usr/home/alex/rout.exe проверяет файл /usr/home/alex/los.dat. Если он ‘непустой”, то удаляется 0-я таблица
маршрутизации и вместо нее записывается таблица со шлюзом по умолчанию
78.152.183.33. Таким образом, устанавливаются две одинаковых таблицы. Далее
идет задержка на 3600 секунд, соответствующая ожиданию восстановления линии
через URAN, и таблицы маршрутизации возвращаются к исходному
виду. Потом опять проверяется файл /usr/home/alex/los.dat. Если он
пустой, тогда линия восстановилась и никаких изменений по переназначению таблиц маршрутизации не
происходит. В противном случае снова происходит изменение 0-й таблицы.
/usr/home/alex/rout.exe:
#!/bin/sh
while [ 1 ]
do
while [
1 ]
do
sleep
1
if [
-s /usr/home/alex/los.dat ]
then
route delete default 212.111.198.33; route add default 78.152.183.33; break
fi
done
#
sleep 3600
#
route delete default 78.152.183.33
route add default 212.111.198.33
done
Для
решения поставленной задачи скрипт /
etc
/
firewall
имеет вид:
#!/bin/sh
ipfw pipe 1
config bw 3024KBit/s
ipfw pipe 5
config bw 3024KBit/s
ipfw pipe 10 config bw 2024KBit/s
ipfw pipe 15 config bw 4096KBit/s
ipfw pipe 20 config bw 3024KBit/s
ipfw add 5000 setfib 0 ip from any to any in
recv fxp0
ipfw add 5010 setfib 1 ip from any to any in
recv rl0
ipfw add 06000 setfib 0 ip from any to any in
recv re1
ipfw add 06010 setfib 1 ip from any to any in
recv re0
ipfw add 10040 pipe 1 ip from any to
172.20.0.0/16 out via fxp0
ipfw add 10045 pipe 1 ip from 172.20.0.0/16 to
any in via fxp0
ipfw add 10050 pipe 5 ip from any to 172.21.8.1 out via rl0
ipfw add 10055 pipe 5 ip from 172.21.8.1 to any in via rl0
ipfw add 10060 pipe 10 ip from any to
172.21.8.2 out via rl0
ipfw add 10065 pipe 10 ip from 172.21.8.2 to
any in via rl0
ipfw add 10070 pipe 15 ip from any to
172.21.8.3 out via rl0
ipfw add 10075 pipe 15 ip from 172.21.8.3 to
any in via rl0
ipfw add 10080 pipe 20 ip from any to
172.21.8.4 out via rl0
ipfw add 10085 pipe 20 ip from 172.21.8.4 to
any in via rl0
ipfw add 10380 pipe 15 ip from any to
172.21.8.200 out via rl0
ipfw add 10385 pipe 15 ip from 172.21.8.200 to
any in via rl0
ipfw add 10400 skipto 30000 ip from any to
172.20.0.0/16 out via fxp0
ipfw add 10405 skipto 30000 ip from
172.20.0.0/16 to any in via fxp0
ipfw add 10410 skipto 30000 ip from any to
172.21.8.1 out via rl0
ipfw add 10415 skipto 30000 ip from 172.21.8.1
to any in via rl0
ipfw add 10420 skipto 30000 ip from any to
172.21.8.2 out via rl0
ipfw add 10425 skipto 30000 ip from 172.21.8.2
to any in via rl0
ipfw add 10430 skipto 30000 ip from any to
172.21.8.3 out via rl0
ipfw add 10435 skipto 30000 ip from 172.21.8.3
to any in via rl0
ipfw add 10440 skipto 30000 ip from any to
172.21.8.4 out via rl0
ipfw add 10445 skipto 30000 ip from 172.21.8.4
to any in via rl0
ipfw add 10450 skipto 30000 ip from any to
172.21.8.200 out via rl0
ipfw add 10455 skipto 30000 ip from
172.21.8.200 to any in via rl0
ipfw add 10620 deny ip from any to any via fxp0
ipfw add 10630 deny ip from any to any via rl0
ipfw nat 1 config if re0 reset same_ports
deny_in redirect_port tcp 78.152.183.34:23 8023 redirect_port udp
78.152.183.34:53 53 redirect_port tcp 172.21.8.2:23 8024
ipfw nat 2 config if re1 reset same_ports deny_in
redirect_port tcp 212.111.198.39:23 8023 redirect_port tcp 172.20.50.3:23 8024
ipfw nat 3 config if re1 reset same_ports
redirect_addr 172.20.6.37 212.111.198.37
ipfw nat 4 config if re0 reset same_ports
redirect_addr 172.20.6.37 78.152.183.35
ipfw nat 5 config if re0 reset same_ports
deny_in redirect_port tcp 78.152.183.34:23 8023
ipfw add 10710 skipto 20100 ip from 172.20.6.37
to any out via re1
ipfw add 10720 skipto 20110 ip from any to
212.111.198.37 in via re1
ipfw add 10810 skipto 20200 ip from 172.20.6.37
to any out via re0
ipfw add 10820 skipto 20210 ip from any to
78.152.183.35 in via re0
#
ipfw add 10830 skipto 20300 ip from any to
78.152.183.34 8023 in via re0
ipfw add 10840 skipto 20310 ip from
78.152.183.34 23 to any out via re1
ipfw add 20000 nat 1 ip from any to any via re0
ipfw add 20010 nat 2 ip from any to any via re1
ipfw add 20020 allow ip from any to any
ipfw add 20100 nat 3 ip from 172.20.6.37 to any
out via re1
ipfw add 20110 nat 3 ip from any to
212.111.198.37 in via re1
ipfw add 20120 allow ip from any to any
ipfw add 20200 nat 4 ip from 172.20.6.37 to any
out via re0
ipfw add 20210 nat 4 ip from any to
78.152.183.35 in via re0
ipfw add 20220 allow ip from any to any
ipfw add 20300 nat 5 ip from any to
78.152.183.34 8023 in via re0
ipfw add 20310 nat 5 ip from 78.152.183.34 23
to any out via re1
ipfw add 20320 fwd 78.152.183.33 ip from
78.152.183.34 8023 to any out via re1
ipfw add 30000 allow ip from any to any
Во
всех представленных выше скриптах команды пишутся в одну строчку.
Описание
прохождения трафика через фаервол в представленной конфигурации.
Для
router
-а
NAT
(работают 2 канала Интернет):
Трафик, инициализированный от
router
-а
NAT
из точки (5) рис.1 пойдет в точку (6). Попав в
ip
_
output
() трафику будет присвоен шлюз по умолчанию 212.111.198.33 и тег с сетевым интерфейсом re1, через который он должен выйти в Интернет(out via re1). Трафик войдет в фаервол и начнет проходить через цепочку правил. Дойдет до правила 20010 и будет передан в точку (8) т.е. на обработку в nat как выходящий трафик, так как он поступил из прохода
out
. В подсистеме nat для трафика в таблице соединений будет создана запись соответствия пар локальный_ip: порт < - > удаленный_
ip
: порт (например, 212.111.198.39:50318< - > 193.193.193.107:23). После этого в точке (9) трафик выйдет из подсистемы nat и опять будет передан в точку (6), попав опять в
ip
_
output
(). Трафик вновь войдет в фаервол но уже в правило 20020 и по нему уйдет в Интернет через re1.
Трафик, возвращающийся в виде ответа, войдет в точку (1), попадет в проход
in
, получит тег
re
1(
in
via
re
1). Затем трафик зайдет в (2) и попадет в функцию ip_input(). Далее он зайдет в фаервол и пойдет по цепочке правил. Правило 6000 определит трафику таблицу маршрутизации 0 и пойдет по правилам дальше. В правиле 20010 он будет передан в точку (8) на обработку в nat, как входящий трафик. В подсистеме nat для трафика в таблице соединений будет найдена ранее созданная запись соответствия пар локальный_ip: порт < - > удаленный_
ip
: порт(212.111.198.39:50318< - > 193.193.193.107:23) по установленному соединению 193.193.193.107:23 < -> 212.111.198.39:50318, после чего он будет демаскирован. Однако в данном случае, так как адрес маскировки/демаскировки один и тот же локальный 212.111.198.39, изменений не будет. После этого трафик из точки (9) выйдет из подсистемы
nat
и будет передан обратно в точку (2). Т.е. попадет опять в ip_input(). По правилу 20020 трафик выйдет из ipfw и будет передан программе, которая ранее инициализировала соединение.
Если из сети Интернет приходит трафик, не имеющий в таблице соединений соответствия, кроме запроса на соединение с адресами 212.111.198.37 и 78.152.183.35, то такой трафик при поступлении в nat дальше не пойдет, так как в настройках
nat
выставлен параметр
deny
_
in
.
Если из
сети Интернет приходит трафик,
адресованный на ip 212.111.198.37, то он войдет в точку (1), попадет в проход
in
, получит тег
re
1(
in
via
re
1). Затем трафик зайдет в (2) и попадет в функцию
ip_input(). Далее он зайдет в фаервол и
пойдет по цепочке правил. Правило 6000 определит трафику таблицу маршрутизации 0,
и он пойдет по правилам дальше. Дойдя до правила 10720, он будет передан
правилу 20110. Здесь трафик пойдет в точку (8) на обработку в nat, как входящий
трафик. Там он будет демаскирован в локальный адрес 172.20.6.37 (по
nat
3), далее выйдет в точку (9), перейдет в точку (2) и
продолжит идти по правилам фаервола.
Сразу попав на правило 20120, трафик выходит из ipfw и возвращается функции
ip_input(). Она определяет, что трафик предназначен не нам, передает его
в точку (4), где функция ip_forward() произведет уменьшение на единицу TTL и
после этого трафик будет передан в точку (6). Здесь он попадает в функцию
in_output(), которая по ip 172.20.6.37 присвоит трафику выходящий шлюз
172.20.50.2 и интерфейс fxp0. Далее трафик попадает в ipfw и идет по правилам.
По правилу 10040 трафик попадает в трубу pipe 1. Однако после этого он не покинет
фаервола, так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила 10400, трафик переходит к
правилу 30000 и попадает в точку (7), затем в локальную сеть на узел
172.20.6.37.
Ответный
трафик с узла 172.20.6.37
войдет
в точку (1), попадет в проход
in
, получит тег
fxp
0(
in
via
fxp
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Правило 5000 определит трафику таблицу
маршрутизации 0, и он пойдет по правилам дальше. По правилу 10045 трафик
попадает в трубу pipe 1. Однако после этого он не покидает фаервола так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила
10405, трафик переходит к правилу
30000, попадает в точку (4) и управление передается функции ip_forward(), которая произведет
уменьшение на единицу TTL. После этого трафик будет передан в точку (6) –
функцию in_output(). Она по таблице маршрутизации 0, внешнего адреса
узла, от которого шел запрос, назначит шлюз по умолчанию (212.111.198.33) и имя
выходящего интерфейса
re
1(
out
via
re
1). Далее трафик передается функции
ipfw_chk() и идет по правилам фаервола. Дойдя до правила 10710
,
управление передается на правило 20100. По нему управление передается в
точку (8), попадает в nat. Здесь по записи соответствия для nat 3 локальный
адрес 172.20.6.37 будет заменен внешним адресом 212.111.198.37 и трафик попадет
в точку (9), далее в точку (6) в функцию
in_output(). Трафик вновь пойдет по правилам фаервола,
дойдет до правила 20120 и выйдет через точку (7) в Интернет.
Теперь
предположим, что с Интернет приходит трафик, адресованный на ip 78.152.183.35.
Тогда он войдет в точку (1), попадет в проход
in
, получит тег
re
0(
in
via
re
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Дойдя до правила 6010, трафику будет назначена
таблица маршрутизации 1. В 10820, он будет передан правилу 20210. Здесь трафик
пойдет в точку (8) на обработку в nat (по
nat
4), как входящий трафик. Там он будет демаскирован в
локальный адрес 172.20.6.37 (по
nat
4), далее выйдет в точку (9), перейдет в точку (2) и
продолжит идти по правилам фаервола.
Сразу попав на правило 20220, трафик выходит из ipfw и возвращается функции
ip_input(). Она определяет, что трафик предназначен не нам, передает его
в точку (4), где функция ip_forward() произведет уменьшение на единицу TTL и
после этого трафик будет передан в точку (6). Здесь он попадает в функцию
in_output(), которая по ip 172.20.6.37 присвоит трафику выходящий шлюз
172.20.50.2 и интерфейс fxp0. Далее трафик попадает в ipfw и идет по правилам.
По правилу 10040 трафик попадает в трубу pipe 1. Однако после этого он не
покинет фаервола, так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила 10400, трафик переходит к
правилу 30000 и попадает в точку (7), затем в локальную сеть на узел
172.20.6.37.
Ответный трафик с узла 172.20.6.37
войдет в точку (1), попадет в проход
in
, получит тег
fxp
0(
in
via
fxp
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Правило 5000 определит трафику таблицу маршрутизации
0, и он пойдет по правилам дальше. По правилу 10045 трафик попадает в трубу
pipe 1. Однако после этого он не покидает фаервола так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила 10405, трафик переходит к правилу 30000, выйдет из
фаервола, попадает в точку (4) и управление передается функции ip_forward(), которая произведет
уменьшение на единицу TTL. После этого трафик будет передан в точку (6) –
функцию in_output(). Она по таблице маршрутизации 0, внешнего адреса
узла, от которого шел запрос, назначит шлюз по умолчанию (212.111.198.33) и имя
выходящего интерфейса
re
1(
out
via
re
1). Далее трафик передается функции
ipfw_chk() и идет по правилам фаервола. Дойдя до правила 10710,
управление передается на правило 20100. По нему управление передается в точку
(8), попадает в nat. Здесь, по записи соответствия для nat 3 локальный адрес
172.20.6.37 либо будет заменен внешним адресом 212.111.198.37, если она
там была, либо замены не произойдет
вообще, так как запись соответствия была сформирована в
nat
4. Далее трафик попадет в точку (9), затем в точку (6) в функцию
in_output(). Снова пойдет по правилам фаервола, дойдет до
правила 20120 и выйдет через точку (7) в Интернет. В этом случае соединения с
удаленным узлом установлено не будет. Однако если в правила фаервола добавить
строку
ipfw add 5030
setfib 1 ip from 172.20.6.37 to any in recv fxp0
тогда для трафика узла 172.20.6.37 будет
переопределена таблица маршрутизации 1, и после попадания в точку (6) функция in_output() назначит
шлюз по умолчанию (78.152.183.33) и имя выходящего интерфейса
re
0(
out
via
re
0). В этом случае соединение с
удаленным узлом будет установлено. Однако предыдущий случай, рассмотренный для
установления соединения по адресу 212.111.198.37, работать не будет.
Рассмотрим
случай переназначения входящих соединений, поступающих на указанный порт, на
другой узел, которым может быть либо узел в локальной сети, либо сам
router
NAT
. Предположим, что с удаленного
узла была введена команда на
telnet
соединение по порту 8024:
telnet
78.152.183.34 8024
В этом случае с Интернет приходит трафик, адресованный на ip
78.152.183.34 и порт 8024 по протоколу
tcp
. Тогда он войдет в точку (1), попадет в проход
in
, получит тег
re
0(
in
via
re
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Дойдя до правила 6010, трафику будет
назначена таблица маршрутизации 1. В правиле 20000 трафик пойдет в точку (8) на
обработку в nat (по
nat
1), как входящий трафик. Там он будет демаскирован по статической записи
172.21.8.2:23 8024 <-> любой_
ip
:любой_
port
. Далее трафик выйдет в точку (9), перейдет в точку (2) и
продолжит идти по правилам фаервола.
Попав на правило 20020, трафик выходит из ipfw
и возвращается функции
ip_input(). Она определяет, что трафик предназначен не нам, передает его
в точку (4), где функция ip_forward() произведет уменьшение на единицу TTL и
после этого трафик будет передан в точку (6). Здесь он попадает в функцию
in_output(), которая по ip 172.21.8.2 присвоит трафику выходящий шлюз
172.21.88.1 и интерфейс fxp0. Далее трафик попадает в ipfw и идет по правилам.
По правилу 10060 трафик попадает в трубу pipe 10. Однако после этого он не
покинет фаервола, так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила 10420, трафик переходит к
правилу 30000 и попадает в точку (7), затем в локальную сеть на узел
172.21.8.2, где запускается программа
telnetd
на порту 23.
Ответный
трафик от узла 172.21.8.2:23
войдет
в точку (1), попадет в проход
in
, получит тег
rl
0(
in
via
rl
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Правило 5010 определит трафику таблицу
маршрутизации 1, и он пойдет по правилам дальше. По правилу 10065 трафик
попадает в трубу pipe 10. Однако после этого он не покидает фаервола так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. Дойдя до правила
10425, трафик переходит к правилу
30000, выйдет из фаервола, попадает в точку (4) и управление передается
функции ip_forward(), которая
произведет уменьшение на единицу TTL. После этого трафик будет передан в точку
(6) – функцию in_output(). Она по таблице маршрутизации 1, внешнего адреса
узла, от которого шел запрос, назначит шлюз по умолчанию (78.152.183.33) и имя
выходящего интерфейса
re
0(
out
via
re
0). Далее трафик передается функции
ipfw_chk() и идет по правилам фаервола. Дойдя до правила 20000,
управление передается в точку (8), попадает в nat. Здесь, по записи
соответствия для nat 1 локальный адрес 172.21.8.2:23 будет маскирован на 78.152.183.34:8024
в соответствии со статической записью в
nat
1. Далее трафик попадет в точку
(9), затем в точку (6) в функцию
in_output().
Снова пойдет по правилам фаервола, дойдет до правила 20020 и выйдет через точку
(7) в Интернет. Таким образом, соединение будет установлено.
Аналогично
будут срабатывать правило для
nat
1 -
redirect_port udp
78.152.183.34:53 53 и все правила в nat 2.
Рассмотрим
особый случай – правило redirect_port tcp
78.152.183.34:23 8023 для nat 1. Согласно
нему, если на удаленном компьютере набрать команду
telnet
78.152.183.34 8023
соединение по
telnet
должно установиться с
router
-ом
NAT
. Рассмотрим прохождение трафика в этом случае.
С Интернет приходит трафик, адресованный на ip 78.152.183.34
и порт 8023 по протоколу
tcp
.
Он войдет в точку (1), попадет в проход
in
, получит тег
re
0(
in
via
re
0). Затем трафик зайдет в (2) и попадет в
функцию ip_input(). Далее он зайдет в фаервол
и пойдет по цепочке правил. Дойдя до правила 6010, трафику будет
назначена таблица маршрутизации 1. В правиле 10830 трафик будет переброшен на
правило 20300, а потом пойдет в точку (8) на обработку в nat (по
nat
5), как входящий трафик. Там он будет демаскирован по
статической записи 78.152.183.34:23 8023 <-> удаленный_любой_
ip
:удаленный_любой_
port
. Далее трафик выйдет в точку (9), перейдет в точку (2) и
продолжит идти по правилам фаервола.
Попав на правило 30000, трафик выходит из ipfw
и возвращается функции
ip_input(). Она определяет, что трафик предназначен нам, передает его в
точку (3), где запустится программа
telnetd
:23 на обработку трафика с адресом 78.152.183.34:23, после
чего он будет передан в точку (5) и потом в точку (6). Но
telnetd
:23, запущенный на
router
-е
NAT
сформирует трафик с исходящим адресом 212.111.198.39, а не 78.152.183.34, так
как по умолчанию он работает с 0-й таблицей маршрутизации (иначе не объяснить
наблюдаемый поток пакетов через интерфейсы с помощью программы
trafshow
). Попав в функцию
ip
_
output
()
она по ip 212.111.198.39 присвоит трафику выходящий шлюз 212.111.198.33 и
интерфейс
re
1.
Далее трафик попадает в ipfw и идет по правилам. Дойдя до правила 10840, трафик переходит к правилу 20310 и попадает в
точку (8) на обработку в nat (по
nat
5), как исходящий трафик. Там он будет маскирован в адрес
78.152.183.34:8023 и перейдет в точку (9), (6) и вновь пойдет по правилам. Правило
20320 переназначит трафику шлюз по умолчанию с 212.111.198.33 на 78.152.183.33
и по правилу 30000 произойдет выход трафика из фаервола. Далее управление
передается функции
ip
_
output
(), которая переназначит трафику выходящий интерфейс с
re
1 на
re
0
и выведет его в Интернет.
Для сети 172.20.0.0/16(работают 2 канала Интернет):
Трафик, инициализированный, например, от 172.20.50.20 войдет
router
NAT
через сетевой
интерфейс
fxp
0,
пройдет через точку (1), получит тег с сетевым интерфейсом
fxp
0 (
in
via
fxp
0).
Далее трафик зайдет в точку (2) и попадет в функцию ip_input(). После этого он
зайдет в фаервол и пойдет по правилам. Трафик дойдет до правила 5000 и ему
будет назначена таблица маршрутизации 0. По правилу 10045 он войдет в трубу
pipe
1, а по правилу 10405 будет передан на правило 30000,
которое выведет трафик из
ipfw
. Затем он вновь попадает в функцию ip_input(), где
принимается решение, что трафик принадлежит не нам. Поэтому он будет
направлен в функцию
ip
_
forward
(),
точку (4). В ней у трафика будет уменьшено значение
TTL
, после чего он будет передан в точку (6) в функцию
ip
_
output
().
По таблице маршрутизации 0 трафику будет присвоен шлюз по умолчанию
212.111.198.33 и тег с исходящим интерфейсом
re
1 (
out
via
re
1).
Трафик войдет в фаервол и начнет проходить по цепочке правил. Он дойдет до
правила 20010 и будет передан в точку (8) на обработку в
nat
2 как выходящий трафик. Для него в таблице соединений будет
создана запись соответствия пар 172.20.50.20:порт<->удаленный_
ip
:порт и
ip
-адрес 172.20.50.20 в заголовке пакета будет заменен
ip
-адресом 212.111.198.39. В точке (9) трафик выйдет из
nat
2 и в точке (6) зайдет заново в
ip
_
output
().
Однако после этого он не покинет фаервола,
так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. В правиле 20020 трафик выйдет из фаервола
и уйдет в Интернет с адресом отправителя 212.111.198.39, а не 172.20.50.20
через интерфейс
re
1 (
out
via
re
1).
Трафик, возвращающийся в виде ответа,
зайдет в точку (1) и попадет в проход
in
, получит тег с сетевым интерфейсом
re
1(
input
via
re
1), через который он
вошел. Далее трафик зайдет в точку (2) и попадет в функцию ip_input() после
чего войдет в фаервол и начнет проходить через цепочку правил. Трафик дойдет до
правила 6000 и ему будет присвоена таблица маршрутизации 0. Пойдет по правилам
далее, дойдет до 20010 и будет передан в точку (8) на обработку в
nat
2 как входящий трафик, поступивший из прохода
in
. В подсистеме
nat
для трафика в таблице соединений будет найдена ранее
созданная запись соответствия пар 172.20.50.20:порт <->
212.111.198.39:порт <-> IP_удаленный:порт, после чего он адрес получателя
в заголовке IP пакета будет заменен с 212.111.198.39 на 172.20.50.20. Далее в точке (9) трафик выйдет из подсистемы
nat
и будет передан обратно в точку (2), попав ip_input(). Затем
он вновь попадает в
ipfw
,
доходит до правила 20020, по нему выходит из фаервола и попадет обратно в
ip_input() где будет принято решение о том, что он предназначен не нам, а
следовательно должен быть направлен в точку (4), в функцию ip_forward(). Здесь у IP трафика будет уменьшено значение TTL, и
он будет передан в точку (6) в функцию ip_output(). Попав ip_output() ему будет
присвоен шлюз 172.20.50.2 и тег с сетевым интерфейсом fxp0, через который он
должен выйти в локальную сеть (
out
via fxp0). Трафик войдет в фаервол и начнет проходить через
цепочку правил. Он дойдет до правила 10040, попадет в трубу
pipe
1, дойдет до правила 10400 по которому переместиться на
30000,и по нему выйдет из
ipfw
. После этого трафик уйдет в локальную сеть через fxp0, имея
IP адрес получателя 172.20.50.20.
Если с
Интернет приходит трафик, не имеющий в таблице соединений записи соответствия,
то такой трафик при поступлении в
nat
будет отвергнут, так как в настройках
nat
выставлен параметр deny_in.
Для сети 172.21.0.0/16, когда работают 2 канала Интернет, алгоритм прохождения трафика аналогичный. Только трафик попадает по правилам фаервола в таблицу маршрутизации 1 и выходит через интерфейс
re
0.
Для сети 172.20.0.0/16(работает 1 канала Интернет на
Infocom
):
Предположим, что канал на
URAN
отключен. Тогда скрипт
/usr/home/alex/rout.exe удаляет для 0-й таблицы маршрутизации шлюз по умолчанию 212.111.198.33 и вместо него устанавливает 78.152.183.33:
route delete default 212.111.198.33
route add default 78.152.183.33
Тогда 0-я и 1-я таблицы маршрутизации становятся идентичны. Алгоритм прохождения трафика будет следующим.
Трафик, инициализированный, например, от 172.20.50.20 войдет
router
NAT
через сетевой интерфейс
fxp
0, пройдет через точку (1), получит тег с сетевым интерфейсом
fxp
0 (
in
via
fxp
0). Далее трафик зайдет в точку (2) и попадет в функцию ip_input(). После этого он зайдет в фаервол и пойдет по правилам. Трафик дойдет до правила 5000 и ему будет назначена таблица маршрутизации 0. По правилу 10045 он войдет в трубу
pipe
1, а по правилу 10405 будет передан на правило 30000, которое выведет трафик из
ipfw
. Затем он вновь попадает в функцию ip_input(), где принимается решение, что трафик принадлежит не нам. Поэтому он будет направлен в функцию
ip
_
forward
(), точку (4). В ней у трафика будет уменьшено значение
TTL
, после чего он будет передан в точку (6) в функцию
ip
_
output
(). По таблице маршрутизации 0 трафику будет присвоен шлюз по умолчанию 78.152.183.33 и тег с исходящим интерфейсом
re
0 (
out
via
re
0).
Трафик войдет в фаервол и начнет проходить по цепочке правил. Он дойдет до правила 20000 и будет передан в точку (8) на обработку в
nat
1
как выходящий трафик. Для него в таблице соединений будет создана запись соответствия пар 172.20.50.20:порт<->удаленный_
ip
:порт и
ip
-адрес 172.20.50.20 в заголовке пакета будет заменен
ip
-адресом 78.152.183.34. В точке (9) трафик выйдет из
nat
1
и в точке (6) зайдет заново в
ip
_
output
(). Однако после этого он не покинет фаервола, так как
net
.
inet
.
ip
.
fw
.
one
_
pass
=0. В правиле 20020 трафик выйдет из фаервола и уйдет в Интернет с адресом отправителя 78.152.183.33, а не 172.20.50.20 через интерфейс
re
0 (
out
via
re
0).
Трафик, возвращающийся в виде ответа, зайдет в точку (1) и
попадет в проход
in
,
получит тег с сетевым интерфейсом
re
0(
input
via
re
0),
через который он вошел. Далее трафик зайдет в точку (2) и попадет в функцию
ip_input() после чего войдет в фаервол и начнет проходить через цепочку правил.
Трафик дойдет до правила 6010 и ему будет присвоена таблица
маршрутизации 0. Пойдет по правилам далее, дойдет до 20000 и будет передан в
точку (8) на обработку в
nat
1
как входящий трафик, поступивший из прохода
in
. В подсистеме
nat
для трафика в таблице соединений будет найдена ранее
созданная запись соответствия пар 172.20.50.20:порт <-> 78.152.183.34:порт
<-> IP_удаленный:порт, после чего он адрес получателя в заголовке IP
пакета будет заменен с 78.152.183.34 на 172.20.50.20. Далее в точке (9) трафик выйдет из подсистемы
nat
и будет передан обратно в точку (2), попав ip_input().
Затем он вновь попадает в
ipfw
, доходит до правила 20020, по нему выходит из фаервола и
попадет обратно в ip_input() где будет принято решение о том, что он
предназначен не нам, а следовательно должен быть направлен в точку (4), в
функцию ip_forward(). Здесь у IP
трафика будет уменьшено значение TTL, и он будет передан в точку (6) в функцию
ip_output(). Попав ip_output() ему будет присвоен шлюз 172.20.50.2 и тег с
сетевым интерфейсом fxp0, через который он должен выйти в локальную сеть (
out
via fxp0). Трафик войдет в фаервол и начнет проходить через
цепочку правил. Он дойдет до правила 10040, попадет в трубу
pipe
1, дойдет до правила 10400 по которому переместиться на
30000,и по нему выйдет из
ipfw
. После этого трафик уйдет в локальную сеть через fxp0, имея
IP адрес получателя 172.20.50.20.
Для сети 172.21.0.0/16, когда работает 1 канал Интернет, алгоритм
прохождения трафика такой же, как и в случае работы 2-х каналов.
Предположим, что на компьютере
172.20.6.37 установлен
WEB
сервер. Для того чтобы он отзывался по имени, например
ed
.
tup
.
km
.
ua
в случае работы 2-х каналов связи и в случае обрыва канала
URAN
, необходимо в
DNS
сервере прописать следующие строки:
ed 0 IN A 212.111.198.37
ed 0 IN A 78.152.183.35
Таким образом, одно доменное имя имеет два
ip
адреса. Число 0 означает, сколько времени необходимо
удерживать запись соответствия имени
ip
-адресу до следующего возобновления в кеши компьютера. Чем
меньше это время, тем быстрее компьютер подставит для запроса другой
ip
-адрес в случае невозможности доступа по предыдущему
ip
-адресу.
Выводы.
1.Благодаря возможности
FreeBSD
7.3-
RELEASE
поддерживать одновременно несколько таблиц маршрутизации удается просто перенаправлять
трафик с разных локальных сетей на различные внешние каналы Интернет.
2.Переключение трафика на разные таблицы маршрутизации возможно
лишь для входного трафика. Например
,
работает
команда
ipfw add 5000
setfib 0 ip from any to any in via fxp0
Команда
ipfw add 5000
setfib 0 ip from any to any out via fxp0
не работает.
3.Замечено, что в версии FreeBSD 8.1-
RELEASE
не работает параметр sysctl -
net.inet.ip.fw.one_pass.
4.Замечено, что если приложение запущено на
NAT
узле, то при внешнем запросе на него с интерфейса,
принадлежащего не нулевой таблице маршрутизации, это приложение отсылает ответы
на внешний интерфейс, описанный в нулевой таблице. Например, работа с
telnet
,
ftp
.
Поэтому приходится в
ipfw
использовать
fwd
как в рассмотренном примере.
Литература.
1.
Подробное руководство по ipfw nat. http://www.lissyara.su/articles/freebsd/tuning/ipfw_nat/,
2010
2.Гончаров
В.
ipfw: порядок
прохождения пакетов, сложные случаи http://nuclight.livejournal.com/124348.html, 2008