Нарыл пример того чего я хочу.
Вот оригинал статейки
http://birdofluck.livejournal.com/8778.html
Собственно вот человек рассказывает природу явления и его решение
Следующая задача, которая в общем-то была бы сферической в вакууме, если бы не суровая чугунная реальность:
Требуется обеспечить работоспособность этих редиректов внутри локальной сети.
Проблема тут в следующем:
Пусть есть адрес 172.16.1.42, который через 1.2.3.4:25 должен попадать на 172.16.1.2:25.
Шаг 1 (TCP SYN от .42 прилетает на шлюз)
172.16.1.42:33456 -> 1.2.3.4:25
Шаг 2 (транслируем через 10й инстанс в redirect_port на input)
172.16.1.42:33456 -> 172.16.1.2:25
Шаг 3 (пакет далее не транслируется и убегает в локальную сеть искать 172.16.1.2)
Шаг 4 (172.16.1.2 получает SYN-пакет, отвечает SYN+ACK на 172.16.1.42:33456.)
172.16.1.2:25 > 172.16.1.42:33456
Шаг 5 (172.16.1.42 отвечает RST, поскольку подобного соединения в TCP-стеке найти не может (src-адрес с т.з. 42 должен быть 1.2.3.4))
Таким образом, надо менять еще и адрес источника, то есть вводить еще один nat.
То есть: перед редиректом сначала меняем адрес источника, затем отдаем пакет в нат с редиректами. Ответные пакеты разворачиваем наоборот.
Из-за нюансов, описанных выше, для ната нам нужен будет еще 1 адрес, не висящий непосредственно на интерфейсе. Выбирать в общем-то можно любой приватный, не использующийся в сети (т.е. тот, трафик на который пойдет через наш маршрутизатор с натами). "Не висящий непосредственно на интерфейсе" нужно для корректной работы out-хука в ipfw nat (описано выше).
Реализуется оно например через blackhole маршрут (аналог типичного приема с ''ip route 1.2.3.0/24 null0'' в quagga, когда нужно натить много разных клиентов в пул публичных адресов). Примерно так:
route add 10.10.10.10 -blackhole -iface lo0
Рисуем, как оно должно выглядеть:
# В квадратных скобочках - в каком хуке ipfw мы получаем соответствующий пакет
# TCP SYN
[IN] 172.16.1.42:33456 -> 1.2.3.4:25
# ipfw nat в позе reverse (то есть, натим пакет в внешний адрес, out hook)
[IN] 10.10.10.10:54123 -> 1.2.3.4:25
# наш нат с пробросом портов (in hook)
[IN] 10.10.10.10:54123 -> 172.16.1.2:25
Ответ:
# TCP SYN+ACK
[IN] 172.16.1.2:25 -> 10.10.10.10:54123
# Отдаем пакет нату с пробросом (put hook)
[OUT] 1.2.3.4:25 -> 10.10.10.10:54123
# Отдаем пакет reverse nat'у (in hook)
[OUT] 1.2.3.4:25 -> 172.16.1.42:33456
Смотрим теперь как это выглядит в правилах:
ipfw nat 1 config ip ${isp1_addr} # ISP 1
ipfw nat 2 config ip 2.3.4.5 # ISP 2
ipfw nat 10 redirect_port tcp 172.16.1.2:25 ${isp1_addr}:25 redirect_port tcp 172.16.1.2:25 ${isp2_addr}:25
# skip_global позволяет избежать неприятных нюансов с nat global (global не проверяет этот инстанс), который вызывается раньше
ipfw nat 11 config ip 10.10.10.10 reverse skip_global
ipfw table 1 add 172.16.1.7 1 # Табличка с соответствиями префиксов внутри сети с номерами натов
ipfw table 1 add 172.16.1.0/24 2
...
ipfw skipto 5000 from any to any out # Делим для упрощения IN и OUT
# В данный нат нужно направлять только тот трафик, который относится к редиректам
# Можно сделать это например, так:
ipfw allow ip4 from ${localnet} to ${localnet} recv ${int_iface}
ipfw nat 11 ip4 from ${localnet} to me recv ${int_iface}
ipfw nat 10 ip4 from any to me recv ${isp1_iface}
ipfw nat 10 ip4 from any to me recv ${isp2_iface}
ipfw nat 1 ip4 from any to me recv ${isp1_iface}
ipfw nat 2 ip4 from any to me recv ${isp2_iface}
# Отправляем пакеты на наш виртуальный адрес порт редиректору
ipfw nat 10 ip4 from ${localnet} to 10.10.10.10 recv ${int_iface}
# Направляем их же дальше 2му нату
ipfw nat 11 ip4 from any to 10.10.10.10 recv ${int_iface}
... (5000)
# Направляем в нужный нат существующие трансляции. У оттранслированных пакетов меняется
# src-адрес и в правила дальше они не попадают
ipfw nat global ip4 from ${localnet} to not me
ipfw nat tablearg from ${localnet} to not me
# Направляем отттранслированные пакеты нужному провайдеру
ipfw fwd ${isp1_gw} ip4 from ${isp1_addr} to any
ipfw fwd ${isp2_gw} ip4 from ${isp2_addr} to any
Если у кого есть интерес к данному решению прошу присоеденится к вопросу ...
Собственно саму схему прохождения пакета не совсем понимаю.
Пример сразу на 2 внешних интерфейса, один можно выкинуть (у меня один).
Не совсем понятен смысл правил:
1.
Код: Выделить всё
ipfw nat 1 config ip ${isp1_addr} # ISP 1
ipfw nat 10 redirect_port tcp 172.16.1.2:25 ${isp1_addr}:25 redirect_port tcp 172.16.1.2:25 ${isp2_addr}:25
Почему бы сразу не соеденить в одно
Код: Выделить всё
ipfw nat 1 config ip ${isp1_addr} redirect_port tcp 172.16.1.2:25 ${isp1_addr}:25 redirect_port tcp 172.16.1.2:25 ${isp2_addr}:25
2. Не совсем понимаю смысл правила:
Код: Выделить всё
ipfw allow ip4 from ${localnet} to ${localnet} recv ${int_iface}
На внутреннем интерфейсе оно работать не будет, разве что на внешних .....
Так ?
Если у гуру есть желание распишите пожалуйста прохождение пакета по данной схеме, что то я пал в ступор и запутался ...