Differences between revisions 2 and 3
Revision 2 as of 2022-04-28 10:20:28
Size: 11310
Editor: FrBrGeorge
Comment:
Revision 3 as of 2022-05-16 10:26:44
Size: 11412
Editor: FrBrGeorge
Comment:
Deletions are marked like this. Additions are marked like this.
Line 214: Line 214:
Новое в [[https://cloud.mail.ru/public/ZPfs/LPrAo93eD|образе]]
 * wireguard и wg-quick

Туннелирование и частные сети

Туннелирование: использование некоторого потока данных для инкапсуляции (в общем случае — произвольного) сетевого трафика.

  • Шифрование контента
  • Защита от пассивного анализа / фильтрации
  • Платформа для включения в инфраструктуру (частные и программно определяемые сети)

Простейший туннель: IP over IP

IP_in_IP

  • Просто добавим ip link соответствующего типа

    • С указанием реальных адресов концов туннеля
  • Настроим IP как обычно)
  • Пример на developers.redhat.com

Использование

Старая схема:

  • клиент ← очень-внутренняя-сеть → маршрутизатор ← внутренняя-сеть → сервер → интернеты

Сервер:

  • Настроим «выход в интернет»
  • 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

Сайт, и конечно Arch-вики

  • Идея та же самая: 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 не работает
    • Тогда придумали туннельный режим. А он как всё такие туннели, только сложнее в поддержке.
  • OpenVPN

    • Если не wireguard, то !OpenVPN — давно и проверенно работает
  • https://github.com/tonarino/innernet

  • … тысячи их

Д/З

Новое в образе

  • wireguard и wg-quick

TODO

LecturesCMC/LinuxNetwork2022/11_TunnelingVPN (last edited 2022-05-16 10:26:44 by FrBrGeorge)