Как многие уже знают, во 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.
Можно еще pls для наглядности привести вывод "setkey -DP" после "ifconfig ipsec0 create" ?
ОтветитьУдалитьПолитики появляются только после настройки адресов туннеля. Добавил вывод setkey -DP.
УдалитьЭтот комментарий был удален автором.
УдалитьСпасибо! Я правда не совсем понял механизм, как трафик матчится этими политиками, если в них везде "0.0.0.0/0[any] 0.0.0.0/0[any] any".
УдалитьUPD Нет, я неправильно спросил. Под них же любой пакет матчиться будет!
> UPD Нет, я неправильно спросил. Под них же любой пакет матчиться будет!
УдалитьВ этом и фишка :)
матчится любой пакет, но только среди тех, которые проходят через интерфейс if_ipsec(4).
Но блин, в SPD штатно нет селектора по имени интерфейса. Как минимум косметически - это бага, в выводе setkey должно быть как-то видно, что это особые записи в SPD.
УдалитьУ меня где-то был патч на возможность фильтрации вывода setkey -DP по типу политик. Я его закоммичу. Ещё посмотрю на сколько сложно будет туда добавить имя интерфейса.
УдалитьТак данные об интерфейсе в базе SPD вообще есть или нет? Я же вручную не могу создать SPD entry с матчингом по имени интерфейса?
УдалитьТут всё несколько сложнее. Данные о политиках из ядра получаются через стандартный интерфейс PF_KEY, там сильно не разгуляешься в добавлении дополнительной информации. Политики интерфейсов хранятся не в SPD, а в самих интерфейсах. Их видимость для пользователя вообще по сути не нужна, но если их не будет видеть пользователь, значит их не будет видеть IKE демон, значит с IKE они работать не будут.
УдалитьОтображать информацию об интерфейсе можно на основе reqid в самом setkey.
> Политики интерфейсов хранятся не в SPD, а в самих интерфейсах.
УдалитьПолитики интерфейсов - это то что появилось с появлением if_ipsec(4)? Сейчас же (например в 11) никаких политик интерфейсов нет?
> Отображать информацию об интерфейсе можно на основе reqid в самом setkey.
Тогда может это и не слишком нужно. С другой стороны, надо же как-то в выводе spddump отличать "нормальные" политики от "интерфейсных", иначе это будет ад для администратора.
> Политики интерфейсов - это то что появилось с появлением if_ipsec(4)? Сейчас же (например в 11) никаких политик интерфейсов нет?
ОтветитьУдалитьЭто внутренняя особенность if_ipsec(4), относительно других интерфейсов ничего не изменилось.
Я добавил два ключа к setkey -DP:
-g - показывать только глобальные политики
-t - показывать только интерфейсные политики туннелей
Выглядит это примерно так:
test15# setkey -DPt
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=7 seq=3 pid=58025 scope=ifnet ifname=ipsec0
refcnt=1
::/0[any] ::/0[any] any
in ipsec
esp/tunnel/87.250.242.144-87.250.242.145/unique:145
spid=9 seq=2 pid=58025 scope=ifnet ifname=ipsec0
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=8 seq=1 pid=58025 scope=ifnet ifname=ipsec0
refcnt=1
::/0[any] ::/0[any] any
out ipsec
esp/tunnel/87.250.242.145-87.250.242.144/unique:145
spid=10 seq=0 pid=58025 scope=ifnet ifname=ipsec0
refcnt=1
test15# setkey -DPg
::/0 ::/0 icmp6 135,0
out none
spid=5 seq=1 pid=58026 scope=global
refcnt=1
::/0 ::/0 icmp6 136,0
out none
spid=6 seq=0 pid=58026 scope=global
refcnt=1
Вот сейчас наглядно стало, спасибо.
УдалитьПоддержки запуска/создания интерфейса внутри клеток с виртуализированным сетевым стеком (jail vimage) пока нет?
ОтветитьУдалитьСудя по исходникам (если я смотрел туда, куда надо), всё-таки поддержка есть, ну и, конечно, пробовать и "бегать по граблям" мне придётся самостоятельно ;).
И вопрос немного не в тему, ЕМНИП, dummynet не работал так как надо, при попытке запуска внутри клетки (я давно - пару лет назад смотрел, ну и сама фраза моя не совсем корректна - dummynet всё-таки работает внутри ядра).
Судя по https://svnweb.freebsd.org/base?view=revision&revision=302054 там много "косяков" починили.
Я никогда не пользовался jail'ами и VIMAGE тоже. Поэтому не могу никак прокомментировать работоспособность. Если раньше вы могли там использовать gif(4) туннели и пользоваться ipsec'ом, то не вижу препятствий для работы if_ipsec(4).
УдалитьИ на этом спасибо!
УдалитьЕсли я смогу более-менее нормально протестировать работу модуля, то я постараюсь отписаться в этой ветке.
Ну возможность создавать gif(4) туннели - была, хотя сам ipsec не работал на старых версиях ос (возможно с 9-10 релиза уже работает, попросту таких извращенцев, которые всё запускают в клетках - мало).
reboot всё смоет
Удалить