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, да и с другими размерами пакетов тоже).

Ответить