Что: 2fe7ed63a6726a694abb6031699132cb3b585a2b
Когда: 2016-12-03 17:23:12+03:00
Темы: ipsec ipv6 tip
Мой опыт настройки IPv4/IPv6 IPsec туннеля в домашних условиях Тут я хочу поделиться своими настройками IPsec IPv4/IPv6 сети между домашними серверами. Для меня это всё было не тривиальной задачей, хотя сейчас она выглядит конечно просто. У меня есть два сервера, один из которых подключён к Интернету и является шлюзом, маршрутизатором, NAT и тому прочее. Второй сервер имеет только Ethernet подключение к шлюзу. Между ними хочется иметь зашифрованный трафик. На шлюзе есть один внешний IPv4 адрес на и IPv6 /64 сеть. Хочется чтобы второй сервер мог "выходить" в Интернет. Для IPv4 само собой нужен NAT (ненавижу), для IPv6 просто выделение однго из адресов сети. ------------------------ >8 ------------------------ Без шифрования настройка сети на сервере выглядит так: # ifconfig igb0 inet 192.168.20.2/24 mtu 1500 up # ifconfig igb0 inet6 2001:470:1f0b:10ad::d/64 # route add default 192.168.20.1 # route -6 add default 2001:470:1f0b:10ad::1 ------------------------ >8 ------------------------ Первая часть задачи: сделать туннель вместо использования Ethernet для передачи IPv4/IPv6 пакетов напрямую. Для меня когда-то это было не понятно зачем: IPsec можно легко настроить так, чтобы он шифровал пакеты без каких-либо туннелей. Но проблема в MTU: после шифрования и аутентификации пакет становится большего размера. Как сказать что через Ethernet интерфейс максимальный размер IPsec ESP пакетов может быть таким, а пакетов до обработки IPsec-ов должен быть меньше? Только имея два интерфейса -- в одном из которых ходит трафик до IPsec, а в другом (Ethernet) уже сами IPsec пакеты. Поэтому делаем следующий туннель: # ifconfig gif0 create up # ifconfig gif0 inet 192.168.20.2/32 192.168.20.1 # route add default 192.168.20.1 в нём имеется наш локальный 192.168.20.2 адрес соединённый с .1. Сервер на данный момент знает только два адреса (свой .2 и .1 шлюза) -- это хорошо тем, что без лишних телодвижений обращение к другим адресам сети 192.168.20/24 будет автоматически идти через шлюз. Свой собственный IPv6 адрес задаём на loopback устройстве (сервер теперь знает ещё один IPv6) и говорим что до IPv6 адреса шлюза можно достучаться через наш виртуальный интерфейс: # ifconfig lo0 inet6 2001:470:1f0b:10ad::d/128 alias # route -6 add 2001:470:1f0b:10ad::1 -iface gif0 # route -6 add default 2001:470:1f0b:10ad::1 Работать это сразу же будет потому-что у каждого интерфейса FreeBSD из коробки включён IPv6 с link-local адресами -- из коробки любой интерфейс может общаться по IPv6. Но, этот туннель ещё не соединён ни с кем. Не знаю почему, но у меня никак не вышло использовать link-local адреса для этого. То есть туннелировать IPv4-over-IPv4, IPv4-over-IPv6, IPv6-over-IPv4, IPv6-over-IPv6 можно без проблем, но вот IP*-over-IPv6-link-local не работает. Поэтому, туннель должен быть между какими-то ещё дополнительными адресами, никуда не деться. В IPv6 есть site-local адреса (аналог 192.168., 10., 172.16. сетей IPv4) которые в Интернет не маршрутизируются, но и не являются link-local с которым gif не работает. Добавляем на Ethernet интерфейс site-local адрес и задаём точки соединения туннеля: # ifconfig igb0 inet6 fc00::98f1/64 # ifconfig gif0 inet6 tunnel fc00::98f1 fc00::2752 Тут моя основная претензия к man-ам FreeBSD для ifconfig: до сих пор я нигде не вижу где сказано как задаётся туннель для IPv4 и IPv6 адресов. Примеры везде такие: ifconfig iface tunnel ADDR1 ADDR2. Но, как оказалось, это ifconfig iface inet tunnel ADDR1 ADDR2. inet по-умолчанию, но вместо него можно вставить inet6. Без этого сделать туннель -over-IPv6 было бы невозможно и я долгое время считал что gif в FreeBSD и годится только для IPv4-over-IPv4 и IPv6-over-IPv4. Не забываем уменьшить MTU. В данном случае у меня 1372 байта (эмпирически вышло, не в притык), что ощутимо, по сравнению с GoVPN добавляющим 25 байт overhead на пакет. # ifconfig gif0 mtu 1372 # ifconfig gif0 gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1372 options=80000<LINKSTATE> tunnel inet6 fc00::98f1 --> fc00::2752 inet 192.168.20.2 --> 192.168.20.1 netmask 0xffffffff inet6 fe80::be5f:f4ff:fedd:98f1%gif0 prefixlen 64 scopeid 0x4 nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> groups: gif Все те же самые действия проделываем на шлюзе, зеркально заменяя адреса. И мы получим IPv6 туннель между fc00::X адресами, внутри которого ходит IPv4 трафик между .2 <-> .1 и IPv6 link-local трафик в адресах которого будет ::1 (шлюз) или ::d (второй сервер). ------------------------ >8 ------------------------ Вторая часть задачи: сама аутентификация сторон, согласование ключей, шифрование и аутентификация трафика. Из коробки делается очень просто. Задаём security policy: говорим что пакеты от fc00::98f1 (конец туннеля на сервере) отправляемые на fc00::2752 (второй конец туннеля) должны быть обёрнуты в ESP (encapsulating security payload) туннель IPsec. Это один security policy. И второй -- зеркальный. # cat /usr/local/etc/racoon/setkey.conf flush; spdflush; spdadd fc00::98f1 fc00::2752 any -P out ipsec esp/tunnel/fe80::be5f:f4ff:fedd:98f1%igb0-fe80::be5f:f4ff:fedd:2752%igb0/require; spdadd fc00::2752 fc00::98f1 any -P in ipsec esp/tunnel/fe80::be5f:f4ff:fedd:2752%igb0-fe80::be5f:f4ff:fedd:98f1%igb0/require; В данном случае, IPsec туннель должен быть между какими-то сторонними (не endpoint-ы gif туннеля) адресами. Но дополнительно выделять из адресов ничего не надо, так как, опять же из-за IPv6, мы уже имеем link-local в Ethernet сети. Именно они выше и прописаны. Демон занимающийся созданием security association (инициализацией IPsec туннеля) -- racoon. Его конфигурация в моём случае проста и тривиальна: прописываются правила для анонимных пользователей, просто copy-paste из минимального конфига. # cat /usr/local/etc/racoon/racoon.conf path pre_shared_key "/usr/local/etc/racoon/psk.txt"; log notify; remote anonymous { exchange_mode main; lifetime time 24 hour; proposal { encryption_algorithm blowfish; hash_algorithm sha512; authentication_method pre_shared_key; dh_group 14; } } sainfo anonymous { pfs_group 14; lifetime time 24 hour; encryption_algorithm blowfish; authentication_algorithm hmac_sha1; compression_algorithm deflate; } padding { randomize off; } Используется Diffie-Hellman 2048bit, Blowfish шифрование, HMAC-SHA1 и SHA512 (при согласовании ключей). Задавать другой HMAC я не хочу исключительно из целей экономии трафика, MTU. compression_algorithm задан, потому-что оставить его пустым нельзя, но в sysctl сжатие трафика явно отключено (бессмысленно в в домашней гигабитной сети и медленно, так как это не LZO или LZ4). padding.randomize отключён для экономии MTU и ресурсов. После создания этих файлов, загружаем security policy в ядро и запускаем racoon: service ipsec start; service racoon start. Теперь gif трафик fc00:: адресов шифруется через туннель между fe80:: адресами. В локальной сети ходит только IPv6 link-local ESP IPsec. Все строчки которые я добавил для конфигурирования сервера в rc.conf: ifconfig_lo0_alias0="inet6 2001:470:1f0b:10ad::d/128" ifconfig_igb0_ipv6="inet6 fc00::98f1/64" cloned_interfaces="gif0" ifconfig_gif0="inet 192.168.20.2/32 192.168.20.1 mtu 1372 up" ifconfig_gif0_ipv6="inet6 tunnel fc00::98f1 fc00::2752" ipv6_static_routes="gw" ipv6_route_gw="2001:470:1f0b:10ad::1 -iface gif0" defaultrouter="192.168.20.1" ipv6_defaultrouter="2001:470:1f0b:10ad::1" ipsec_enable="YES" racoon_enable="YES"
Сгенерирован: SGBlog 0.34.0