ipfw="/sbin/ipfw -q " local="re0"
ISP1="rl0"
ISP2="rl1"
localnet="192.168.0.0/24"
ISP1_ip="123.45.67.89"
ISP2_ip="234.56.78.9"
ISP1_gw="123.45.67.1"
ISP2_gw="234.56.78.1"
nat_ISP1="8668"
nat_ISP2="8669"
nat_global="8670"
${ipfw} -f flush
${ipfw} add 10 check-state
${ipfw} add 11 allow ip from any to any via lo0
${ipfw} add 12 deny ip from any to 127.0.0.0/8
${ipfw} add 13 deny ip from 127.0.0.0/8 to any
#Пример сервисов которые необходимо вывесить на оба внешних интерфейса.
# sshd
${ipfw} add 20 allow tcp from any to me 14441
# Web Server
${ipfw} add 25 allow tcp from any to me 80
# MailServer
${ipfw} add 26 allow tcp from any to me 25
${ipfw} add 27 allow tcp from any to me 110
# Other
${ipfw} add 28 allow tcp from any to me 1723 setup
${ipfw} add 29 allow tcp from any to any via ng*
${ipfw} add 30 allow udp from any to any via ng*
${ipfw} add 31 allow tcp from any to me 53
${ipfw} add 32 allow udp from any to me 53
${ipfw} add 33 allow tcp from any to me dst-port 21,30000-50000 setup
# Здесь самая соль.
# Следующие две строки нужны чтобы сам шлюз был доступен по обоим адресам, то есть с какого адреса идет пакет от шлюза, в тот интерфейс и уходил.
${ipfw} add 100 fwd ${ISP1_gw} ip from ${ISP1_ip} to not ${localnet}
${ipfw} add 200 fwd ${ISP2_gw} ip from ${ISP2_ip} to not ${localnet}
# Далее разделяем весь трафик по интерфейсам и направлениям, для удобства
# Локальный интерфейс
${ipfw} add 400 skipto 1000 all from any to any in recv ${local}
${ipfw} add 410 skipto 2000 all from any to any out xmit ${local}
# Внешние интерфейсы
${ipfw} add 500 skipto 3000 all from any to any in recv ${ISP1}
${ipfw} add 550 skipto 4000 all from any to any out xmit ${ISP1}
${ipfw} add 600 skipto 5000 all from any to any in recv ${ISP2}
${ipfw} add 650 skipto 6000 all from any to any out xmit ${ISP2}
# Если вдруг объявятся еще интерфейсы то рубим их. Все интерфейсы мы должны разрулить сами, иначе все пакеты с этих новых интерфейсов попадут под следующее разрешающее правило
${ipfw} add 900 deny all from any to any
# Локальный входящий
${ipfw} add 1000 allow all from any to any
# Локальный исходящий
${ipfw} add 2000 allow all from any to any
# ISP1 входящий (входящий трафик заворачиваем в нужный порт natd)
${ipfw} add 3000 divert ${nat_ISP1} ip from any to ${ISP1_ip}
${ipfw} add 3010 allow all from any to any
# ISP1 исходящий (аналогично для обоих провайдеров)
# Заворачиваем пакет в natd по порту globalport
${ipfw} add 4000 divert ${nat_global} ip from ${localnet} to any
# Если есть запись трянсляции подключения снаружи вовнутрь, то natd модифицирует пакет и ставит адресом источника тот внешний адрес, на который производилось подключение
# Если это адрес первого провайдера, то далее просто разрешаем пакет и на этом обработка заканчивается
${ipfw} add 4010 allow all from ${ISP1_ip} to any
# Если это адрес второго провайдера, то мы форвардим пакет на шлюз второго провайдера.
${ipfw} add 4020 fwd ${ISP2_gw} ip from ${ISP2_ip} to any
# Если же natd вернул неизмененный пакет, значит данный пакет не относится к подключению извне, тогда заворачиваем его в соответствующий порт natd
${ipfw} add 4030 divert ${nat_ISP1} ip from ${localnet} to any
# Разрешаем прохождение пакета.
${ipfw} add 4040 allow all from any to any
# Для второго провайдера все аналогично
# ISP2 входящий
${ipfw} add 5000 divert ${nat_ISP2} ip from any to ${ISP2_ip}
${ipfw} add 5010 allow all from any to any
# ISP2 исходящий
${ipfw} add 6000 divert ${nat_global} ip from ${localnet} to any
${ipfw} add 6010 allow all from ${ISP2_ip} to any
${ipfw} add 6020 fwd ${ISP1_gw} ip from ${ISP1_ip} to any
${ipfw} add 6030 divert ${nat_ISP2} ip from ${localnet} to any
${ipfw} add 6040 allow all from any to any