[О блоге]
[наверх]
[пред]
[2016-12-03 17:23:12+03:00]
[2fe7ed63a6726a694abb6031699132cb3b585a2b]
Темы: [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"
[оставить комментарий]