Сети для самых маленьких. Часть 20: VPN и прокси

В девятнадцатой части мы разобрали IPsec и IKEv2 как протоколы: пакеты, обмены, ключи. Сегодня — что из них получается на машине пользователя, когда он нажимает «Подключиться», и чем это отличается от другого способа пустить трафик через чужой сервер — прокси. Слово «VPN» затёрто до неузнаваемости: им называют и туннель между офисами, и кнопку в браузере, и это разные вещи с разной механикой. Серия построена на уровнях, и именно уровни дают точный ответ: VPN работает на сетевом уровне, прокси — на транспортном или прикладном. Всё остальное из этого следует.


Что такое VPN

VPN, Virtual Private Network — виртуальная сеть поверх другой сети. В терминах серии: туннель, то есть протокол внутри протокола, как PPPoE внутри Ethernet в четвёртой части или кадр внутри UDP в VXLAN, обычно с шифрованием. Туннель бывает L2 (внутри едут кадры, как в VXLAN) и L3 (внутри едут IP-пакеты, как в IPsec); для удалённого доступа почти всегда L3.

Главное практическое свойство: с точки зрения операционной системы VPN — это сетевой интерфейс и маршруты. После подключения в системе появляется интерфейс tun0, ipsec0, wg0 или ppp0 с адресом из «той» сети, а в таблицу маршрутов ложатся префиксы, которые надо отправлять в него. Приложения пишут в сокеты как обычно; стек по таблице маршрутов решает, что пакет пойдёт в tun0; VPN-клиент берёт его оттуда, шифрует и отправляет по настоящему интерфейсу на сервер; сервер расшифровывает и отправляет дальше, как роутер. Ни одна программа на машине не знает, что что-то изменилось, и это работает для любого протокола — TCP, UDP, ICMP, чего угодно поверх IP.

Два вида:

  • site-to-site — туннель между двумя шлюзами; хосты за ними вообще не участвуют, для них «та» сеть — просто ещё один маршрут через свой роутер. Так соединяют офисы.
  • remote access — клиент на ноутбуке или телефоне, подключающийся к шлюзу. О нём дальше.

IKEv2 remote access: по шагам

Сотрудник в кафе подключается к корпоративной сети. Ноутбук получил от кафе адрес 192.168.1.10, шлюз VPN — vpn.example.com, корпоративная сеть — 10.0.0.0/8.

1. Рукопожатие. Клиент резолвит vpn.example.com в 203.0.113.5 и проводит IKE_SA_INIT и IKE_AUTH из прошлой части: сервер предъявляет сертификат с именем vpn.example.com, клиент — логин и пароль через EAP-MSCHAPv2. В IKE_AUTH клиент просит конфигурацию (CP): «дай адрес, DNS», и предлагает селекторы трафика 0.0.0.0/0 с обеих сторон — «хочу защищать всё».

2. Сервер отвечает. CP: внутренний адрес 10.0.5.17, DNS 10.0.0.53, домен example.com. Селекторы: либо оставляет 0.0.0.0/0 (полный туннель), либо сужает до 10.0.0.0/8 (раздельный). Создаётся пара Child SA.

3. Клиент настраивает систему. Вот что меняется в ip addr и ip route:

$ ip addr show ipsec0                    # или адрес на том же eth0 в policy-based реализациях
    inet 10.0.5.17/32 scope global ipsec0

$ ip route
default via 192.168.1.1 dev wlan0 metric 600          # осталось
203.0.113.5 via 192.168.1.1 dev wlan0                 # (а) хост-маршрут до VPN-сервера
10.0.0.0/8 dev ipsec0                                 # (б) корпоративная сеть — в туннель

Для полного туннеля вместо (б) появится 0.0.0.0/0 dev ipsec0 с лучшей метрикой, чем у кафе, или два маршрута 0.0.0.0/1 и 128.0.0.0/1: они длиннее, чем /0, и по правилу самого длинного префикса побеждают старый default, не удаляя его. Маршрут (а) обязателен: пакеты к самому VPN-серверу должны идти мимо туннеля, иначе зашифрованный пакет попадёт в туннель, будет зашифрован ещё раз, и так до бесконечности.

DNS: в resolv.conf или systemd-resolved первым становится 10.0.0.53, домен поиска example.com.

4. Пакет к корпоративному серверу. Приложение подключается к 10.0.0.42:443:

 приложение   sendto(10.0.0.42:443)
      │
 стек: ip route get 10.0.0.42 → dev ipsec0, src 10.0.5.17
      │
 ┌────┴──────────────────────────────────────┐
 │ IP 10.0.5.17 → 10.0.0.42 │ TCP 443 │ TLS  │   ← то, что видит приложение
 └────┬──────────────────────────────────────┘
      │ xfrm: политика «10.0.0.0/8 → защищать», SA найдена
 ┌────┴────────────────────────────────────────────────────────────────────────────┐
 │ IP 192.168.1.10 → 203.0.113.5 │ UDP 4500 │ ESP spi, seq │ ░░ весь пакет выше ░░ │  ← то, что видит кафе
 └────┬────────────────────────────────────────────────────────────────────────────┘
      │ dev wlan0 → шлюз кафе → NAT кафе → интернет → 203.0.113.5
      ▼
 сервер: расшифровать, проверить селекторы, маршрутизировать 10.0.5.17 → 10.0.0.42 в корпоративную сеть

Кафе и провайдер видят один UDP-поток на 4500 порт: ни адреса 10.0.0.42, ни порта 443, ни содержимого. Сервер 10.0.0.42 видит соединение от 10.0.5.17 — адреса из своей сети — и отвечает ему; ответ по маршрутам корпоративной сети приходит на VPN-шлюз, тот заворачивает его в ESP к 192.168.1.10 (точнее, к внешнему адресу NAT кафе, с которого пришёл клиент), и стек ноутбука, расшифровав, отдаёт приложению.

5. Пакет в интернет зависит от режима.


Полный и раздельный туннель

Split tunneling — в туннель только корпоративные префиксы, остальное напрямую через кафе. Быстрее, не грузит корпоративный канал видео с YouTube, и сервер сам задаёт список через селекторы или CP-атрибут INTERNAL_IP4_SUBNET. Цена — два пути наружу одновременно, и отсюда утечки:

  • DNS. Запрос intranet.example.com может уйти не в 10.0.0.53, а в DNS кафе, если клиент не сумел настроить «этот домен — через этот сервер», а остальное — как было. Кафе узнаёт, какие внутренние имена вы ищете, а имя не резолвится. Windows с несколькими интерфейсами и DNS-серверами на каждом здесь особенно изобретательна.
  • IPv6. Туннель настроен только на IPv4, а у кафе есть IPv6 (тринадцатая часть). Всё, что резолвится в AAAA, уходит мимо туннеля, в открытую. Клиент должен либо провести IPv6 тоже, либо заблокировать его на время подключения.
  • Приложения, знающие свои адреса. WebRTC в браузере (механизм звонков из девятой части) честно перечисляет все локальные адреса машины, включая адрес кафе, тому, с кем соединяется.

Полный туннель — всё в VPN. Кафе видит один шифрованный поток и ничего больше; сайты видят адрес VPN-шлюза. Но весь интернет-трафик идёт через корпоративный канал, и, если VPN-шлюз далеко, с соответствующей задержкой. И даже здесь есть момент до подключения и после обрыва, когда трафик идёт открыто. Для этого придуман kill switch: правило файрвола «ничего, кроме пакетов к VPN-серверу, через wlan0 не выпускать», которое остаётся, пока VPN не отключат явно.

Коммерческие «VPN-сервисы» — это remote access с полным туннелем, где «корпоративная сеть» — интернет за сервером провайдера услуги. Механика та же; меняется только, кто видит ваш трафик расшифрованным: не кафе, а оператор сервиса.


Другие протоколы VPN

IKEv2/IPsec — то, что встроено в Windows, macOS, iOS и Android без клиентов. Остальные, чтобы было понятно, что написано в настройках:

  • WireGuard — туннель поверх UDP с фиксированной криптографией (Curve25519, ChaCha20-Poly1305): у каждого пира открытый ключ, у соединения — список разрешённых префиксов на пира (которые заодно и маршруты), никакого рукопожатия с выбором алгоритмов. Интерфейс wg0 в ядре Linux, несколько тысяч строк кода против сотен тысяч у IPsec, переезд клиента между адресами сам собой. Из-за простоты сейчас самый быстрый и всё чаще предпочитаемый.
  • OpenVPN — туннель внутри TLS-сессии по UDP или TCP, пользовательский процесс и интерфейс tun. Старше, медленнее, но проходит там, где UDP 500/4500 закрыт, потому что умеет TCP 443 и выглядит как HTTPS.
  • L2TP/IPsec — две вещи сразу: L2TP, туннель для кадров PPP поверх UDP 1701, защищённый IPsec в транспортном режиме. Внутри — тот же PPP из четвёртой части с аутентификацией и IPCP. Встроен в старые Windows, живёт по инерции.
  • SSTP — PPP внутри TLS на порту 443, вариант Microsoft для обхода файрволов.
  • PPTP — PPP внутри GRE с шифрованием MPPE, взломан окончательно, не использовать.

Все они одинаковы в главном: интерфейс плюс маршруты, трафик всех приложений.


Прокси

Прокси — посредник на транспортном или прикладном уровне. Приложение не отправляет пакет получателю; оно устанавливает соединение с прокси и просит его соединиться с получателем, а дальше прокси перекладывает байты между двумя соединениями. Операционная система, таблица маршрутов и интерфейсы не меняются. Прокси использует только то приложение, которому его прописали.

HTTP-прокси и CONNECT

Браузер с настроенным прокси proxy.example.com:3128 для открытого HTTP (протокол запросов страниц, запрос — текстовая строка «метод, адрес, версия») шлёт прокси запрос с полным URL:

GET http://www.example.com/page HTTP/1.1
Host: www.example.com

Прокси сам идёт на www.example.com, получает ответ и отдаёт браузеру, по дороге кешируя, фильтруя и записывая всё, что захочет: он читает содержимое.

Для HTTPS читать нечего, и для него есть метод CONNECT:

CONNECT www.example.com:443 HTTP/1.1
Host: www.example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz

HTTP/1.1 200 Connection established

<дальше в этом же TCP-соединении — сырые байты TLS между браузером и сайтом>

Прокси открывает TCP к www.example.com:443, отвечает 200 и с этого момента просто пересылает байты в обе стороны. TLS устанавливается сквозь него, между браузером и сайтом; прокси видит только имя и порт из CONNECT. Так работает большинство корпоративных прокси, так браузер ходит через них на HTTPS, и так же через CONNECT можно пропустить что угодно поверх TCP, например SSH.

В curl -v -x http://proxy.example.com:3128 https://www.example.com первые строки — ровно этот CONNECT и 200.

Прозрачный прокси — тот же HTTP-прокси, но приложение о нём не знает: роутер перенаправляет весь трафик на порт 80 в прокси, и тот разбирает запросы по заголовку Host. С HTTPS прозрачно уже не выходит: без подмены сертификатов прокси видит только имя сервера в начале TLS.

Обратный прокси — та же программа с другой стороны: стоит перед серверами, принимает запросы от всех клиентов и раздаёт их по бэкендам. Это nginx или Traefik перед сайтом, и к теме «пустить мой трафик через посредника» он отношения не имеет; упомянут, чтобы слово не путало.

SOCKS5

SOCKS, RFC 1928, — прокси уровнем ниже HTTP: он не понимает, что внутри, и просто соединяет. Обмен:

 клиент → прокси:  05 02 00 02            версия 5, умею два способа аутентификации: нет и логин/пароль
 прокси → клиент:  05 00                  выбираю «без аутентификации»
 клиент → прокси:  05 01 00 03 0f www.example.com 01 bb
                   │  │  │  └ адрес: тип 3 — доменное имя длиной 15, порт 443
                   │  │  └── резерв
                   │  └── команда 1 — CONNECT
                   └── версия
 прокси → клиент:  05 00 00 01 <адрес, с которого прокси подключился> <порт>
                      └ статус 0 — успех
 дальше — сырые байты в обе стороны

Два свойства, которых нет у HTTP CONNECT. Во-первых, SOCKS5 принимает адрес как имя, и тогда резолвит его прокси, а не клиент: имя не уходит в локальный DNS, и это закрывает ту самую утечку DNS; в curl это --socks5-hostname, в браузерах — «proxy DNS when using SOCKS». Во-вторых, есть команда UDP ASSOCIATE, через которую можно проксировать и UDP; реализаций немного, но они есть.

Самый доступный SOCKS-прокси — ssh -D 1080 user@server: SSH, протокол удалённого терминала с шифрованием, открывает на локальной машине порт 1080, и всё, что приложение отправит в него по SOCKS, уезжает внутри SSH-сессии и выходит в интернет с сервера. Между клиентом и сервером — шифрованный SSH, дальше — обычный трафик от имени сервера.


Чем VPN отличается от прокси

VPN Прокси
Уровень L3: интерфейс и маршруты L4 (SOCKS) или L7 (HTTP): соединение к посреднику
Кто им пользуется всё, что есть на машине, не зная об этом только приложения, где прокси настроен
Протоколы внутри любые поверх IP: TCP, UDP, ICMP TCP; UDP — только SOCKS5 и редко
Шифрование часть протокола (IPsec, WireGuard, TLS у OpenVPN) нет по умолчанию: HTTP-прокси и SOCKS открыты, если не завернуть их в TLS или SSH
Что видит посредник все пакеты расшифрованными: адреса, порты, содержимое, если его не защищает TLS адреса назначения; содержимое открытого HTTP; у HTTPS — только имя и порт
Что видит локальная сеть (кафе) один шифрованный поток к VPN-серверу соединения к прокси; содержимое, если прокси не по TLS; DNS-запросы, если резолвит клиент
Что видит сайт адрес VPN-сервера адрес прокси
DNS через туннель (при полном) или по правилам (при раздельном) клиентский, кроме SOCKS5 с именами
Настройка клиент с правами на интерфейсы и маршруты строка в настройках приложения или переменная https_proxy
Где работает в ядре или с его участием в пространстве пользователя
Что ломает MTU меньше на 50–80 байт; раздельный туннель — утечки приложения без поддержки прокси; UDP

Два практических вывода.

«VPN» в расширении браузера — это прокси. Расширение не может создать интерфейс и менять маршруты; оно настраивает в браузере HTTPS- или SOCKS-прокси. Через него идёт только трафик этого браузера, остальные программы и другие браузеры — мимо. Для сайта в этом браузере разницы нет, для картины «всё моё устройство за VPN» — есть.

Ни то, ни другое не анонимность. VPN-сервер и прокси видят, куда вы ходите, и могут это записывать. Они переносят доверие от локальной сети и провайдера к оператору сервера. Если задача — чтобы никто не связал запрос с вами, нужны цепочки посредников, как в Tor, где каждый узел знает только соседей, и это отдельная история.

Когда что: доступ ко всей удалённой сети всеми программами — VPN; одна программа через другой выход — прокси; обойти файрвол, пропускающий только HTTPS, — прокси по TLS на 443 или VPN, умеющий притворяться HTTPS (OpenVPN на TCP 443, SSTP); между офисами — site-to-site VPN, и никаких прокси.


Смотрим руками

До и после подключения VPN — что изменилось в системе:

$ ip addr | grep -A2 'tun\|wg\|ipsec'
$ ip route
$ ip route get 10.0.0.42            # куда уйдёт пакет в корпоративную сеть
$ ip route get 203.0.113.5          # а к самому VPN-серверу — должен уйти мимо туннеля
$ resolvectl status                 # какие DNS и для каких доменов

WireGuard и некоторые клиенты используют policy routing: маршруты лежат в отдельной таблице, а правило ip rule отправляет туда всё, кроме пакетов самого туннеля (помеченных fwmark). Тогда ip route покажет старую картину, а ip rule и ip route show table all — настоящую.

Утечки: dig intranet.example.com и смотреть в tcpdump, на какой сервер ушёл запрос и по какому интерфейсу; curl -6 https://example.com — уходит ли IPv6 мимо туннеля; ip route get 2001:db8::1.

Прокси вживую:

$ curl -v -x http://proxy.example.com:3128 https://www.example.com      # увидите CONNECT и 200
$ ssh -D 1080 -N user@server.example.com &                              # SOCKS на 1080
$ curl --socks5-hostname 127.0.0.1:1080 https://www.example.com         # имя резолвит сервер

и tcpdump на локальном интерфейсе покажет разницу: в случае VPN — только ESP или UDP к одному адресу; в случае прокси — TCP-соединение к прокси с CONNECT в открытом виде (если прокси без TLS) или SSH-сессию.


Что запомнить

  • VPN — туннель на сетевом уровне: интерфейс и маршруты, все приложения, любые протоколы поверх IP, шифрование встроено. Remote access на IKEv2: адрес и DNS через CP, префиксы через селекторы, хост-маршрут до сервера мимо туннеля.
  • Полный туннель прячет всё от локальной сети; раздельный быстрее, но течёт через DNS, IPv6 и WebRTC. Kill switch закрывает окна до и после.
  • WireGuard, OpenVPN, L2TP/IPsec, SSTP — те же интерфейс и маршруты с другой упаковкой; PPTP — нет.
  • Прокси — посредник для соединений: HTTP с полным URL или CONNECT для TLS, SOCKS5 с резолвом имён на стороне прокси и UDP; работает только для настроенных приложений, шифрование — отдельно.
  • «VPN» в браузере — прокси для одного браузера. Ни VPN, ни прокси не анонимность: они меняют, кто видит ваш трафик.

Дальше — Часть 21: OSPF: как роутеры внутри одной сети сами узнают друг о друге и обо всех подсетях, строят общую карту и считают по ней кратчайшие пути. Hello и соседство, LSA и база состояний линков, алгоритм Дейкстры, стоимость линков, области и что происходит при обрыве кабеля.


Серия «Сети для самых маленьких»

  1. Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
  2. Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
  3. Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
  4. PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
  5. IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
  6. IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
  7. ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
  8. ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
  9. UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
  10. TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
  11. DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
  12. DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
  13. IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
  14. ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
  15. SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
  16. DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
  17. VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
  18. VXLAN — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.
  19. IPsec и IKEv2 — как шифруют пакеты на сетевом уровне и договариваются о ключах.
  20. VPN и прокси (эта статья) — куда уходит каждый пакет при включённом VPN и чем прокси отличается от VPN.
  21. OSPF — как роутеры одной сети сами строят общую карту и считают по ней кратчайшие пути.
  22. BGP — как десятки тысяч независимых сетей интернета договариваются о маршрутах.
  23. TLS и сертификаты — как защищают одно TCP-соединение и откуда браузер знает, что сервер настоящий.

Оставить комментарий могут только зарегистрированные пользователи.

Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.