Две вещи, изменившие миp, были созданы в Беpкли: LSD и Unix. Вряд ли это случайное совпадение.
Jeremy S. Anderson
Для наглядности считаем, что внутренняя сеть адресуется блоком 192.168.0.0/24, шлюзом для внутренней сети выступает 192.168.0.1, IP-адрес внешнего интерфейса роутера – 20.30.40.50, внутренний интерфейс называется xl0 (кстати, он может совпадать и с внешним, если на интерфейсе прибиты одновременно и внешний адрес, и внутренний).
1. Проверяем, что ядро собрано с опциями "IPDIVERT" и "IPFIREWALL", если нет – пересобираем ядро или добавляем куда-то в стартовые скрипты загрузку модулей ipfw.ko и ipdivert.ko (команда kldload).
2. В файл /etc/rc.conf добавляем следующие строки:
firewall_enable="YES"
firewall_type="OPEN"
gateway_enable="YES"
natd_enable="YES"
natd_interface="xl0"
Здесь "xl0" указано для примера, вместо него нужно подставить реальное имя внешнего интерфейса (уходя через который пакеты имеют уже другой адрес отправителя).
3. Добавляем правила в ipfw, которые будут заворачивать трафик к natd:
ipfw add 1000 divert natd ip from 192.168.0.0/24 to not 192.168.0.0/24 out xmit xl0
ipfw add 1100 divert ip from not 192.168.0.0/24 to 20.30.40.50 in recv xl0
Можно было и просто написать
ipfw add 1000 divert ip from any to any via xl0
но мне первый вариант кажется более изящным (особенно в случае когда на интерфейсе xl0 висит куча сеток, а мы хотим чтобы натились только некоторые их них).
Номера правил (в примере 1000 и 1100) следует выбирать с учетом взаимного влияния других правил, лучше их ставить где-то в начале. Если, к примеру, у Вас будет что-то типа "allow tcp from any to any established" под номером 500, то с очень большой вероятностью получите грабли, т.к. трафик для установившихся TCP-сессий не будет проходить через natd, поскольку правило с номером 500 сработает раньше правил с номерами 1000 и 1100.
Важное замечание: если шлюз для внутренней сети 192.168.0.1 и внешний адрес 20.30.40.50 висят на одном интерфейсе, то внешний адрес 20.30.40.50 обязательно должен быть первым (основным, который НЕ-alias), а 192.168.0.1 – алиасом (см. man ifconfig). Иначе работать не будет (сам когда-то полчаса ломал голову в такой ситуации, удивляясь почему не работает то, что построено строго в соответствии с рекомендациями признанных гуру).
Вместо "natd" в этих правилах можно писать "8668" - это "порт", который "слушает" natd. Хотя мне лично непонятно что это за "порт" такой – не в терминах же протокола TCP употребляется здесь слово "порт" (потому что natd работает далеко не только для TCP-трафика, а еще и для UDP, ICMP и др.).
Как построить NAT в другую сторону (извне вовнутрь) описано здесь во второй части статьи.