Как многие уже знают, во FreeBSD 12.0-CURRENT был добавлен новый сетевой псевдоинтерфейс if_ipsec(4). На первый взгляд кажется, что он выполняет те же самые задачи что и уже существующий десятилетия if_gif(4). Но это не совсем так.
Оба интерфейса предоставляют виртуальный туннель, в который может маршрутизироваться трафик. Оба интерфейса настраиваются подобным образом: при помощи ifconfig(8) создаётся интерфейс, ему назначаются адреса конечных точек туннеля, настраиваются адреса внутри туннеля, при необходимости добавляются дополнительные маршруты. В случае с if_gif(4) этих действий уже достаточно для работы интерфейса. Он может принимать и передавать инкапсулированные в IPv4 или IPv6 пакеты.
Чтобы зашифровать передаваемый внутри туннеля трафик необходимо настроить политики и ассоциации безопасности, которые будут применять IPsec преобразования к трафику туннеля, т.е. в качестве селектора адресов для политики должны выступать адреса конечных точек туннеля, а селектором протокола - в зависимости от настроек могут быть различные вариации инкапсуляции IP в IP. Можно конечно "матчить" весь трафик между конечными точками туннеля, но это чаще всего неудобно. Когда таких туннелей нужно создать много, то встаёт задача синхронизации настроек каждого if_gif(4) туннеля и настроек политик безопасности IPsec. К тому же, наличие большого числа политик безопасности не ускоряет работу по поиску подходящей политики для каждого пакета.
В решении части этих проблем и должен помочь if_ipsec(4). Его особенность в том, что он не выполняет инкапсуляцию сам, как это делает if_gif(4), а использует применяемую для туннельного режима "встроенную" в IPsec инкапсуляцию. При настройке туннеля if_ipsec(4) автоматически создаёт нужные политики безопасности, в которых уже указаны адреса конечных точек туннеля. Стоит заметить, что и принцип применения этих политик отличается от используемого для if_gif(4). Создаваемые интерфейсом if_ipsec(4) политики безопасности "матчат" вообще весь IPv4 и IPv6 трафик. Но так как они привязаны к конкретному интерфейсу, то и "матчат" они только трафик, проходящий через интерфейс.
В итоге можно иметь сотни таких политик безопасности в системе, но при прохождении пакетов поиск подходящей политики вообще не выполняется, т.к. каждый if_ipsec(4) интерфейс выбирает свою единственную политику, которой владеет он.
На маршрутизаторе, где используется только if_ipsec(4), даже fastforwarding будет работать для всего остального трафика, чего нельзя получить с классическим if_gif(4) и глобальными политиками безопасности, т.к. fastforwarding автоматически отключается при наличии таких политик.
Теперь про особенности настройки. Как я уже сказал, с точки зрения конфигурации интерфейса, всё настраивается точно так же как и для if_gif(4). Но есть один дополнительный параметр reqid. Который может назначаться автоматически, но если не предполагается использовать IKE, то лучше назначить его руками. Этот параметр помагает системе различать политики нескольких интерфейсов и выполнять поиск подходящей ассоциации безопасности.
Ещё одна особенность, отличающая if_ipsec(4) от if_gif(4) - при использовании if_ipsec(4) нет возможности "выключить" IPsec и проверить, что всё работает без шифрования.
Ну и конечно же, настройку ассоциаций безопасности никто не отменял. Пароли и ключи шифрования автоматически никто придумывать за вас не будет. Чтобы ассоциация безопасности начала использоваться интерфейсом if_ipsec(4), нужно при её добавлении использовать специальный параметр у утилиты setkey(8) "-u id", где id - это упомянутый ранее reqid интерфейса.
Пример создания туннеля между двумя тестовыми машинами test15 и test25:
test15# ifconfig ipsec0 create reqid 145 test15# ifconfig ipsec0 inet tunnel 87.250.242.145 87.250.242.144 test15# ifconfig ipsec0 inet 10.0.0.145/24 10.0.0.144 test15# ifconfig ipsec0 ipsec0: flags=8051metric 0 mtu 1400 tunnel inet 87.250.242.145 --> 87.250.242.144 inet 10.0.0.145 --> 10.0.0.144 netmask 0xffffff00 inet6 fe80::225:90ff:fef9:3c92%ipsec0 prefixlen 64 scopeid 0x4 nd6 options=23 reqid: 145 groups: ipsec test15# setkey -c add 87.250.242.145 87.250.242.144 esp 0xbadcafe -u 145 -E rijndael-cbc "1234567890987654" -A hmac-sha2-256 "12345678901234561234567890123456"; add 87.250.242.144 87.250.242.145 esp 0xcafebad -u 145 -E rijndael-cbc "0987654321123456" -A hmac-sha2-256 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa12"; ^D
После настройки адресов туннеля на интерфейсе создаются вот такие политики безопасности.
test15# setkey -DP 0.0.0.0/0[any] 0.0.0.0/0[any] any in ipsec esp/tunnel/87.250.242.144-87.250.242.145/unique:145 spid=1 seq=3 pid=9427 refcnt=1 ::/0[any] ::/0[any] any in ipsec esp/tunnel/87.250.242.144-87.250.242.145/unique:145 spid=3 seq=2 pid=9427 refcnt=1 0.0.0.0/0[any] 0.0.0.0/0[any] any out ipsec esp/tunnel/87.250.242.145-87.250.242.144/unique:145 spid=2 seq=1 pid=9427 refcnt=1 ::/0[any] ::/0[any] any out ipsec esp/tunnel/87.250.242.145-87.250.242.144/unique:145 spid=4 seq=0 pid=9427 refcnt=1
Изменить политики можно только уничтожив интерфейс или изменив его
настройки (адреса или reqid). Удалить их при помощи setkey -DPF так же не
выйдет.
test25# ifconfig ipsec0 create reqid 144 test25# ifconfig ipsec0 inet tunnel 87.250.242.144 87.250.242.145 test25# ifconfig ipsec0 inet 10.0.0.144/24 10.0.0.145 test15# setkey -c add 87.250.242.145 87.250.242.144 esp 0xbadcafe -u 144 -E rijndael-cbc "1234567890987654" -A hmac-sha2-256 "12345678901234561234567890123456"; add 87.250.242.144 87.250.242.145 esp 0xcafebad -u 144 -E rijndael-cbc "0987654321123456" -A hmac-sha2-256 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa12"; ^D
test15# tcpdump -qnvi ix0 host 87.250.242.144 tcpdump: listening on ix0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:28:25.170705 IP (tos 0x0, ttl 64, id 33289, offset 0, flags [none], proto ESP (50), length 156) 87.250.242.144 > 87.250.242.145: ESP(spi=0x0cafebad,seq=0x3), length 136 14:28:25.170928 IP (tos 0x0, ttl 64, id 4871, offset 0, flags [none], proto ESP (50), length 156, bad cksum 0 (->d212)!) 87.250.242.145 > 87.250.242.144: ESP(spi=0x0badcafe,seq=0x1), length 136 14:28:45.288935 IP (tos 0x0, ttl 64, id 21702, offset 0, flags [none], proto ICMP (1), length 84) 87.250.242.144 > 87.250.242.145: ICMP echo request, id 37388, seq 0, length 64 14:28:45.288955 IP (tos 0x0, ttl 64, id 32712, offset 0, flags [none], proto ICMP (1), length 84, bad cksum 0 (->65ca)!) 87.250.242.145 > 87.250.242.144: ICMP echo reply, id 37388, seq 0, length 64
test25# ping -c1 10.0.0.145 PING 10.0.0.145 (10.0.0.145): 56 data bytes 64 bytes from 10.0.0.145: icmp_seq=0 ttl=64 time=0.508 ms --- 10.0.0.145 ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.508/0.508/0.508/0.000 ms test25# ping -c1 87.250.242.145 PING 87.250.242.145 (87.250.242.145): 56 data bytes 64 bytes from 87.250.242.145: icmp_seq=0 ttl=64 time=0.090 ms --- 87.250.242.145 ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.090/0.090/0.090/0.000 ms
Этот пример показывает как использовать if_ipsec(4) в режиме ручной настройки. Но if_ipsec(4) вполне может использоваться совместно с различными IKE демонами. В этом случае создание политик безопасности от IKE демона не требуется. Ядро запросит у IKEd создание ассоциации безопасности при первой же попытке прохождения пакета через интерфейс, что может инициировать согласование параметров ассоциаций безопасности между IKE.