9 декабря 2014 г., 22:20 пользователь Eugene Grosbein <[email protected]> написал: > On 09.12.2014 15:39, Anton Sayetsky wrote: >> 8 декабря 2014 г., 18:43 пользователь Eugene Grosbein >> <[email protected]> написал: >>> 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 > Для других версий, возможно, потребуется незначительная правка. У меня сейчас 10.1. Пожалуй, где-нибудь рядом подниму ещё одну машину, тестовую, да попробую накатить. Пока сделал так: root@vpnc:~# cat /etc/natd.conf # log deny_incoming log_denied unregistered_only instance default alias_address 172.31.249.1 in_port 7020 out_port 7021 root@vpnc:~# ipfw -d show | grep divert 00260 194446 3036896712 divert 7021 ip from 172.17.5.0/24 to 192.168.137.0/24 in via tun1 00270 194284 3036900457 divert 7020 ip from 192.168.137.0/24 to 172.31.249.1 in via re0 root@vpnc:~# sysctl net.inet.ipsec.filtertunnel net.inet.ipsec.filtertunnel: 1 root@vpnc:~# ifconfig lo1 lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6> inet 172.31.249.1 netmask 0xffffff00 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> root@vpnc:~# Причём natd жрёт меньше проца, чем openvpn, netisr и irq taskq (при тупом тесте: ping -f -s 16384, да и с другими размерами пакетов тоже).
