Туннелирование и частные сети
Туннелирование: использование некоторого потока данных для инкапсуляции (в общем случае — произвольного) сетевого трафика.
- Шифрование контента
- Защита от пассивного анализа / фильтрации
- Платформа для включения в инфраструктуру (частные и программно определяемые сети)
Простейший туннель: IP over IP
Просто добавим ip link соответствующего типа
- С указанием реальных адресов концов туннеля
- Настроим IP как обычно)
Использование
Старая схема:
клиент ← очень-внутренняя-сеть → маршрутизатор ← внутренняя-сеть → сервер → интернеты
Сервер:
- Настроим «выход в интернет»
- NAT сделаем сами примерно так:
table ip nat { chain postrouting { type nat hook postrouting priority srcnat; policy accept; ip saddr 10.0.0.0/8 oif "eth0" masquerade } }
Для краткости воспользуемся ip tunnel
# ip tunnel add hole mode ipip remote IP-клиента local наш-IP # ip l set hole up # ip addr add dev hole адрес-туннеля/24
- Все адреса — и туннеля, и «настоящие» пускай лежат в 10/8
Помните, как в отсутствие OSFP мы ручками настраивали информацию о всех внутренних сетях? В файле внутренняя_сеть.network это выглядит так:
… настройки внутренней сети … … [Route] Destination=очень-внутренняя-сеть-с-клиентом/24 Gateway=ближайший-маршрутизатор
Маршрутизатор:
- Просто две сети и маршрутизация
- Когда будем тестировать туннель, включим nft и добавим туда
# nft add rule inet filter forward ip protocol tcp reject
Клиент:
- Для начала просто настроим очень-внутреннюю сеть.
- Туннель настаиваем так же, как на сервере, только меняем local и remote ☺
Должно работать:
- Ping адрес того конца туннеля
- См. на MTU: мы же запихнули IP в IP ☺
- смотрим на router пакеты в туннеле;
Вот уже почти VPN!
на сервере — по интерфейсу для каждого клиента ☹, и что хуже — по паре IP-адресов. Если клментов много, этих IP-адресову него будет…
- ⇒ для p2p
- нет шифрования и авторизации
Туннель как маршрут по умолчанию
На клиненте:
# date | netcat ya.ru 80 — (всё ещё работает по-старому)
- всё ещё работает по-старому, это же только туннель между двумя хостами
Проблема превращения старого маршрута в маршрут до tunnel endpoint:
- Если тупо задать маршрут по умолчанию через туннель, то как будут ходить пакеты самого туннеля?
Простая реализация:
- Для тестов запрещаем весь проходящий TCP на маршрутизаторе (см выше)
DNS (через UDP) работает, netcat ya.ru 80 — нет
- добавляем 1:1 (/32→/32) маршрут через router на server (бывший default router)
- удаляем default route
- добавляем default route через конец туннеля
netcat ya.ru 80 — работает!
l2tp — фреймы в IP
Всё по ip-l2tp с инкапсуляцией в UDP и для простоты без bridge
TODO скопипастить этот кусок сюда
# ip l2tp show tunnel # ip l2tp show session
Главная фишка: если применять bridge («Configure as bridged interfaces» в man-е): на сервере интерфейс один и IP у него тоже один.
Использование
(если успеем, то тупо пример из MAN)
Wireguard
- Идея та же самая: UDP-пакеты с каким-то payload
- Защита асимметричным шифрованием
- нужны пары откытый/закрытый ключ от всех участников процесса — и от сервера, и от клиентов
- дополнительно можно ключ защитить паролем
- обычно генерирует и раздаёт админ
- Есть клиенты по всякие архитектуры
Лайфхак:
- Для копипасты:
# wg genkey | tee /dev/stderr | wg pubkey
Минимальная настройка:
Сервер:
70-wg.netdev:[NetDev] 70-wg.netdev:Name = wg 70-wg.netdev:Kind = wireguard 70-wg.netdev: 70-wg.netdev:[WireGuard] 70-wg.netdev:ListenPort = 51820 70-wg.netdev:PrivateKey = сервера, никому не показывать (возможно, лучше PrivateKeyFile = …) 70-wg.netdev:# PublicKey = сервера, просто лежит тут прозапас 70-wg.netdev: 70-wg.netdev:[WireGuardPeer] 70-wg.netdev:AllowedIPs = 192.168.111.0/24 70-wg.netdev:PublicKey = клиента 70-wg.network:[Match] 70-wg.network:Name = wg 70-wg.network: 70-wg.network:[Network] 70-wg.network:Address = 192.168.111.1/24
Клиент:
90-wg.netdev:[NetDev] 90-wg.netdev:Name = wg 90-wg.netdev:Kind = wireguard 90-wg.netdev: 90-wg.netdev:[WireGuard] 90-wg.netdev:PrivateKey = этого клиента 90-wg.netdev:# PublicKey = этого клиента, прозапас 90-wg.netdev: 90-wg.netdev:[WireGuardPeer] 90-wg.netdev:AllowedIPs = 192.168.111.0/24 90-wg.netdev:PublicKey = сервера 90-wg.netdev:Endpoint = 10.1.1.1:51820 90-wg.network:[Match] 90-wg.network:Name = wg 90-wg.network: 90-wg.network:[Network] 90-wg.network:Address = 192.168.111.5/24
Частная сеть как выход в интернет
Ещё раз: проблема превращения старого маршрута в маршрут до tunnel endpoint
Задача довольно просто формулируется, но полна нюансов:
- При внезапном перенаправлении всего роутинга в в туннель надо умудриться не направить туда роутинг до end point-а.
- Нюанс № 0: любые нелокальные маршруты, про которые знает внутренний маршрутизатор, но не знает endpoint. Например, локальный DNS-сервер с внутренним DNS-ом.
В нашем случае довольно просто, ибо статика:
Сервер:
- Добавим частную подсеть в NAT
Клиент:
Добавим явный маршрут до сервера частной сети через тот же маршрутизатор, что и по умолчанию
- Добавим ещё явных маршрутов до ключевых локальных сервисов (DNS, файлопомойка, корпоративный мессенджер, whatever)
Только после этого выставим маршрутизатор по умолчанию (в нашем случае статика, поэтому без разницы) на сервер частной сети
При этом либо удаляем старый маршрут по умолчанию, либо делаем так, чтобы метрика новой записи была выше (параметр metric число команды ip route add или Metric= в секции [Route] файла .network).
Нюансы:
- Хорошо, если все важные маршруты можно описать просто большим диапазоном (у нас 10/8) — а ну как нельзя?
Или, что хуже, у админов нет фантазии, и обе сети — и локальная, и частная — это 192.168.0.0/24?
Манипуляции с метрикой надо делать над исходным маршрутом, никак не связанным с частной сетью
- Манипуляции с удалением и добавлением маршрутов — это вообще контекстно-зависимый ад
wg-quick как-то решает эту проблему.
⇒ Нужен разумный best practice. Для начала хотя бы сделать в ядре метрику по умолчанию не 0…
А ещё вот:
https://lists.zx2c4.com/pipermail/wireguard/2022-January/007403.html
Рашн ВПН
…
Всякое
IPsec — безудержно. Но работает!
- Основная фишка: транспортный режим, в котором шифруется только payload от IP…
- …идея была в том, чтобы логика сети оставалась, а в пакеты никто не заглядывал…
- …и она оказалась провальной: даже NAT не работает
- Тогда придумали туннельный режим. А он как всё такие туннели, только сложнее в поддержке.
- Основная фишка: транспортный режим, в котором шифруется только payload от IP…
- Если не wireguard, то !OpenVPN — давно и проверенно работает
- … тысячи их
Д/З
Новое в образе
- wireguard и wg-quick
TODO