On 09.12.2014 15:39, Anton Sayetsky wrote: > 8 декабря 2014 г., 18:43 пользователь Eugene Grosbein > <eu...@grosbein.net> написал: >> On Mon, Dec 08, 2014 at 06:03:36PM +0200, Anton Sayetsky wrote: >>> Вообще задача следующая: >>> Есть сервак, на внешнем интерфейсе которого поднят IPSec (cryptomap >>> 172.31.249.0/24=>192.168.137.0/24). >>> Есть несколько tun/tap, с которых приходят различные сети. >>> (192.168.90.0/24, 172.17.5.0/24 и т.п.) >>> Вот и нужно из всех tun/tap отнатить в 172.31.249.0/24, чтобы дальше >>> трафик ушёл на 192.168.137.0/24 >>> ipfw nat не работает, трафик натится правильно, но не заходит в SPD IPSec. >>> >>> Правила вида: >>> ipfw nat 1 config ip 172.31.249.1 >>> ipfw add nat 1 ip from any to any via tun1 >>> Дают мне траф вида 172.31.249.1=>192.168.137.2 на re0, а должно >>> паковаться в ESP. >> >> Неплохо бы о применении IPSEC в схеме упоминать в первом письме, >> а не к концу обсуждения. Потому как пакет на выходе из роутера >> сначала поступает на обработку в IPSEC, а только потом идёт >> через пакетные фильтры (ipfw) и выйдя из NAT, уже в IPSEC >> не направляется. И неважно, ipfw nat это, natd или pf. > Т.е. ipfw nat работать не будет принципиально? ipsec.filtertunnel может > помочь?
filtertunnel может помочь в трансляции входящих пакетов, но его недостаточно для трансляции исходящих. Сделал патч на ядерную часть ipfw nat для того, чтобы он поддерживал эту функциональность, что была в natd: позволяет явно задавать направление трансляции пакетов (in->out или out->in). Сейчас ipfw nat определяет это направление только автоматически: если пакет проходит по списку правил ipfw первый раз, на входе в маршрутизатор, он считается входящим и транслируется только как out->in. Если пакет проходит по правилам ipfw повторно и после выполнения routing lookup (на выходе и уже имеет атрибут xmit interface), то он транслирцется только как in->out. Патч http://www.grosbein.net/freebsd/patches/ip_fw_nat.c.diff не меняет это поведение по умолчанию: патченная система работает так же. Однако, патч вводит два новых sysctl с дефолтными нулевыми значениям: net.inet.ip.fw.nat_tag_in net.inet.ip.fw.nat_tag_out Если пакет, попавший в правило ipfw nat, имеет прикрепленный тег с номером, равным ненулевому значению sysctl net.inet.ip.fw.nat_tag_out, он безусловно транслируется по схеме in->out, даже если обрабатывается на входе в маршрутизатор. Аналогично, если пакет имеет тег, равный ненулевому net.inet.ip.fw.nat_tag_in, он транслируется как входящий снаружи по схеме out->in. Трансляция для пакетов, не имеющих таких тегов, выполняется как на непатченной системе. Для пакетов, имеющих теги, эти теги при трансляции снимаются. Теперь для решения исходной задачи можно задать sysctl net.inet.ip.fw.nat_tag_out=10 и заменить одно правило ipfw add nat 1 ip from any to any via tun1 на три: tag_out=$(sysctl -n net.inet.ip.fw.nat_tag_out) # Трансляция трафика из мира в локалку ipfw add 1000 nat 1 ip from any to any in recv $ext_if # Тегирование пакетов для трансляции из локалки в мир ipfw add 1010 count tag $tag_out ip from $LAN to not $LAN in recv 'ng*' # Трансляция тегированных пакетов на ВХОДЕ в маршрутизатор ipfw add 1020 nat 1 ip from any to any tagged $tag_out in Таким образом добиваемся необходимого эффекта: сначала трансляция исходящего трафика, затем обработка IPSEC на выходе (между ними routing lookup). Не забываем, что при sysctl net.inet.ip.fw.one_pass=1 оттранслированные на входе пакеты не идут дальше по правилам ipfw. Прикладывать патч: cd /usr/src && patch < /path/to/patch Затем пересобрать ядро либо только модуль ipfw_nat.ko (модуль ipfw.ko не требуется пересобирать), если используется модуль, а не кастомное ядро с FIREWALL_NAT. Модуль можно выгрузить/загрузить на лету, только после этого обязательно сделать service ipfw start, иначе трансляция не заработает. Патч сделан и проверен на 9.3. Вариант для 8.4: http://www.grosbein.net/freebsd/patches/ip_fw_nat.c.8.diff Для других версий, возможно, потребуется незначительная правка.