# Развёртывание Aura VPN Этот документ — пошаговое руководство, по которому вы поднимаете сервер Aura на удалённой машине, провижините на нём сертификат для клиента и подключаете клиент (десктоп) к этому серверу. Все команды и поля конфигов взяты из фактического кода и поставляемых примеров в `config/`. > Полезные сопутствующие документы: [`protocol.md`](protocol.md) (wire-протокол), > [`pki.md`](pki.md) (CA и сертификаты), [`split-tunnel.md`](split-tunnel.md) (правила > маршрутизации), [`sing-box.md`](sing-box.md) (интеграция с sing-box, план). --- ## 1. Обзор схемы Сервер Aura на удалённой машине провижинит сертификат для клиента (десктопа или, в будущем, телефона через sing-box), отдаёт клиенту бандл сертификатов и трастового якоря, и клиент подключается к серверу по протоколу AuraVPN. На проводе по умолчанию используется **собственный UDP-транспорт Aura с пост-квантовой криптографией** (без QUIC и без внешнего TLS на основном пути); fallback'и — это TCP/443 и QUIC. Всё рукопожатие пост-квантовое: **гибридное X25519 + ML-KEM-768** с взаимной X.509-аутентификацией. Для данных используется AEAD **ChaCha20-Poly1305** с explicit-nonce. Обфускация — это паддинг датаграмм до «корзин» размера, характерных для HTTPS. ``` [клиент-десктоп] [удалённый сервер aura] client.toml + PEM-бандл server.toml + PKI (CA + server leaf) | | | UDP (основной) / TCP/443 / QUIC | | гибридное PQ-рукопожатие | | ChaCha20-Poly1305 | +---------------------------------------> AuraVPN ``` --- ## 2. Сервер (удалённый хост) ### 2.1. Установка бинаря В корне репозитория: ```bash cargo build --release # -> target/release/aura ``` Скопируйте получившийся бинарь `target/release/aura` на сервер (например в `/usr/local/bin/aura`) либо соберите его прямо на сервере (требуется Rust toolchain). ### 2.2. Поднять PKI Эти три команды создают CA и выпускают листовые сертификаты для сервера и клиента. Все они проверены против реализации в `crates/aura-pki/src/{ca,cert,store}.rs` и `crates/aura-cli/src/pki.rs`. ```bash # 1) Создать CA Aura. aura pki init --ca-name "Aura Root CA" --out /etc/aura/pki # -> /etc/aura/pki/ca.crt # -> /etc/aura/pki/ca.key # секрет, защищайте правами файловой системы # 2) Выпустить сертификат сервера. --domain должен совпадать с тем именем, # которое клиент будет ожидать в [client] sni (это же имя проверяется по SAN). aura pki issue-server \ --domain vpn.example.com \ --out /etc/aura/pki/server \ --ca /etc/aura/pki # -> /etc/aura/pki/server/server.crt # -> /etc/aura/pki/server/server.key # секрет # 3) Выпустить сертификат клиента (по одному на устройство). # --id становится Common Name'ом и проверенным peer_id, который видит сервер. aura pki issue-client \ --id phone-1 \ --out /etc/aura/clients/phone-1 \ --ca /etc/aura/pki # -> /etc/aura/clients/phone-1/client.crt # -> /etc/aura/clients/phone-1/client.key # секрет ``` Подробности (включая `aura pki revoke` / `list`) — см. [`pki.md`](pki.md). ### 2.3. `server.toml` Раскладка ниже взята из `config/server.toml.example` и поставляемых serde-структур (`crates/aura-cli/src/config.rs`). Скопируйте пример и поправьте под себя. ```toml [server] # Человекочитаемое имя (также внутренняя identity сервера в рукопожатии). name = "aura-edge-1" # UDP/TCP listen-сокет. ":443" мимикрирует под HTTPS; для его биндинга нужны привилегии. # IP отсюда переиспользуется как listen-IP для каждого включённого транспорта. listen = "0.0.0.0:443" # Число accept-воркеров (в v1 носит совещательный характер). workers = 4 [pki] # Trust anchor (Aura CA) и листовая пара сервера, все PEM. ca_cert = "/etc/aura/pki/ca.crt" cert = "/etc/aura/pki/server/server.crt" key = "/etc/aura/pki/server/server.key" [tunnel] # Адресный пул для клиентов; в v1 на сервере один общий TUN в этой сети. pool_cidr = "10.7.0.0/24" # MTU TUN-устройства (запас под QUIC + framing Aura). mtu = 1420 # DNS, анонсируемый клиентам (в v1 информационно). dns = "10.7.0.1" [mimicry] # Hostname, под который мимикрирует внешний TLS-слой (для QUIC). sni = "cdn.example.com" # Паддинг для размытия размеров пакетов под «корзины» HTTPS. padding = true [transport] # Набор и порядок транспортов, биндящихся одновременно. UDP — основной; TCP/443 и # QUIC (мимикрия H3) — fallback'и. При отсутствии всей секции включаются udp/tcp/quic # на 443/443/444. order = ["udp", "tcp", "quic"] # UDP-транспорт и QUIC оба используют UDP, поэтому udp_port и quic_port ДОЛЖНЫ # различаться. TCP может занимать тот же номер порта (другой протокол). udp_port = 443 tcp_port = 443 quic_port = 444 # UDP: дополнять датаграммы до «корзин» размера HTTPS, чтобы размыть распределение размеров. obfuscate = true # TCP: добавлять минимальный HTTP/1.1-преамбулу (Host = [mimicry] sni), чтобы открытие # выглядело как обычный HTTP. masquerade = true ``` Пути могут начинаться с `~` (раскрывается в домашнюю директорию). ### 2.4. Сеть на сервере #### Файрвол Откройте те порты, которые перечислены у вас в `[transport]`. С приведённой выше конфигурацией: - UDP **443** — основной транспорт Aura. - TCP **443** — fallback Aura поверх TCP. - UDP **444** — fallback Aura поверх QUIC. Важно: UDP-транспорт и QUIC — это **оба UDP**, поэтому их порты обязательно должны различаться (в примере: udp_port=443, quic_port=444). Конфиг-валидатор `transport.modes()` отвергает совпадение. #### IP-форвардинг и NAT (для выхода клиентов в интернет) В v1 настройка egress на стороне сервера — **обязательный ручной шаг**. На Linux: ```bash # 1) Включить IP-форвардинг. sudo sysctl -w net.ipv4.ip_forward=1 # (для постоянства добавьте в /etc/sysctl.conf или /etc/sysctl.d/*) # 2) MASQUERADE для исходящего трафика клиентов на интернет-интерфейсе (например eth0). sudo iptables -t nat -A POSTROUTING \ -s 10.7.0.0/24 \ -o eth0 \ -j MASQUERADE ``` Подставьте свой `pool_cidr` и имя интернет-интерфейса. ### 2.5. Запуск сервера ```bash sudo aura server --config /etc/aura/server.toml ``` `sudo` нужен для создания TUN-устройства и для биндинга привилегированных портов (`:443`). Можно опционально указать путь admin-сокета: ```bash sudo aura server \ --config /etc/aura/server.toml \ --admin-socket /var/run/aura-admin.sock ``` По умолчанию admin-сокет — `/tmp/aura-admin.sock`. --- ## 3. Что вы получаете для клиента (бандл) Отдайте клиенту **три PEM-файла**: - `ca.crt` (из `/etc/aura/pki/ca.crt`) — trust anchor; - `client.crt` (из `/etc/aura/clients//client.crt`) — листовой сертификат клиента; - `client.key` (из `/etc/aura/clients//client.key`) — **секрет**, приватный ключ клиента. И сообщите ему два параметра: - **Адрес сервера** (например `203.0.113.10`). - **`sni`** — то DNS-имя, которое вы указали в `aura pki issue-server --domain`. Оно же ожидается в SAN серверного сертификата и проверяется в `verify_server_cert`. Эти три файла плюс два параметра — это всё, что нужно клиенту для подключения. --- ## 4. Клиент (десктоп) Путь для телефона — через sing-box; пока нативного клиента нет, см. раздел 6 ниже. ### 4.1. `client.toml` Раскладка взята из `config/client.toml.example` и `crates/aura-cli/src/config.rs`. ```toml [client] # Человекочитаемое имя/id клиента. name = "laptop" # UDP-сокет сервера. IP отсюда переиспользуется как server-IP для каждого транспорта. server_addr = "203.0.113.10:443" # Внешний TLS-SNI (hostname-камуфляж), предъявляемый серверу. Он же проверяется # внутри рукопожатия Aura против SAN серверного сертификата. sni = "cdn.example.com" [pki] # Trust anchor (Aura CA) и листовая пара клиента, все PEM. ca_cert = "~/.aura/ca.crt" cert = "~/.aura/client.crt" key = "~/.aura/client.key" [tunnel] # Запрошенное имя TUN-интерфейса (на macOS совещательно — ядро назначает utunN). tun_name = "aura0" # Локальный адрес для TUN и длина префикса. local_ip = "10.7.0.2" prefix = 24 # MTU TUN. mtu = 1420 # DNS, используемый туннельным резолвером (в v1 информационно; реально используется # системный резолвер). dns = "10.7.0.1" # Split-tunnel: действие по умолчанию плюс точечные правила. [tunnel.split] default = "VPN" [[tunnel.split.direct]] cidr = "192.168.0.0/16" [[tunnel.split.direct]] cidr = "10.0.0.0/8" [[tunnel.split.direct]] domain = "intranet.example.com" # Более узкий префикс возвращает поддиапазон обратно в VPN (longest-prefix бьёт /8). [[tunnel.split.vpn]] cidr = "10.7.0.0/24" [mimicry] padding = false [transport] # Порядок fallback'а (handover), пробуется слева направо: первый удавшийся побеждает. # При отсутствии всей секции — ["udp","tcp","quic"] на 443/443/444. order = ["udp", "tcp", "quic"] udp_port = 443 tcp_port = 443 quic_port = 444 obfuscate = true masquerade = true ``` Подробности про `[tunnel.split]` — в [`split-tunnel.md`](split-tunnel.md). ### 4.2. Запуск клиента ```bash sudo aura client --config client.toml ``` `sudo` нужен для поднятия TUN-устройства. Клиент: 1. Загружает PEM-файлы из `[pki]` и строит `aura_proto::ClientConfig`. 2. Строит таблицу маршрутизации из `[tunnel.split]`. 3. Дозванивается до сервера, перебирая транспорты в `[transport] order` (handover UDP → TCP → QUIC); первый, который удался, побеждает. 4. Разрезолвит доменные правила split-tunnel'а в host-маршруты (best-effort). 5. Создаёт TUN, передаёт его маршрутизатору и начинает гонять трафик. В логе при успехе вы увидите строку с выбранным транспортом: ``` INFO connected and authenticated to server peer=Some("cdn.example.com") mode=udp ``` `mode` принимает значения `udp`, `tcp` или `quic`. ### 4.3. Управление на лету После запуска клиента (или сервера) admin-сокет позволяет менять правила и смотреть статус без перезапуска: ```bash # Добавить CIDR на лету. aura route add --cidr 8.8.8.0/24 --action direct # Завернуть домен через VPN. aura route add --domain example.com --action vpn # Перечислить правила. aura route list # Удалить CIDR-правило. aura route remove --cidr 8.8.8.0/24 # Статус и счётчики. aura status # Aura tunnel status # peer: cdn.example.com # default: vpn # rules: 2 # rx packets: 0 # tx packets: 0 ``` Если сокет лежит не там, добавьте `--admin-socket ` к каждой команде. Полная спецификация команд и wire-протокола admin'а — в [`split-tunnel.md`](split-tunnel.md). --- ## 5. Что идёт по проводу (резюме) - **Основной**: собственный UDP-транспорт Aura (в примере — `443/udp`). Один UDP-сокет несёт обе фазы, различимые по первому байту: - `0x01` HS — рукопожатие с надёжным DTLS-подобным слоем поверх (повторы, ack, упорядочивание); - `0x02` DATA — датаграммы данных с explicit-nonce AEAD; обфускация = паддинг до «корзин» HTTPS (`[64, 128, 256, 512, 1024, 1280, 1460]`). - **Fallback TCP/443**: настоящий **outer TLS-443** (rustls) поверх TCP — на проводе неотличимо от валидного HTTPS, ALPN `[h2, http/1.1]`. Внутри TLS — тот же Aura-handshake. Клиент использует `AcceptAnyServerCert` (security гарантирует только внутренний Aura-handshake). - **Fallback QUIC**: внешний TLS-камуфляж под HTTP/3 + внутреннее Aura-рукопожатие. - Клиент пробует транспорты по `order`, переключается при отказе или таймауте подключения (по умолчанию 8 с). Сервер слушает все включённые транспорты одновременно (`MultiServer`). Подробный wire-протокол — в [`protocol.md`](protocol.md). --- ## 6. v2 — что устранено и что остаётся ### Устранено в v2 (по сравнению с v1) - ✓ **Мульти-клиент UDP-сервер.** `UdpServer` теперь демультиплексирует датаграммы по адресу пира: один сокет обслуживает много клиентов параллельно, каждый со своим `ReliableHsAdapter` и своим `UdpConnection`. `MultiServer::accept` выдаёт по соединению на каждого нового клиента (в любом из включённых транспортов). - ✓ **IP-пул + per-client маршрутизация на сервере.** Новая секция `[server.pool]` (`cidr`, `strategy`, `static`) выдаёт каждому клиенту IP при accept; `ServerRouter` держит карту `client_ip → Arc`, читает с TUN, диспатчит пакеты по `dst_ip` в нужное подключение, а параллельные per-conn-задачи пишут входящий трафик обратно в TUN. - ✓ **`send_direct` устранён.** Новое `[tunnel.os_routes]` (по умолчанию `enabled = true`) программирует **системную таблицу маршрутов**: DIRECT-цели идут мимо TUN через изначальный default-gateway, через TUN попадает только VPN-трафик. RAII-guard откатывает все добавленные маршруты при остановке клиента. - ✓ **Настоящий TLS-443 в TCP-транспорте.** Вместо лёгкой HTTP/1.1-преамбулы — полный outer rustls handshake (ALPN `[h2, http/1.1]`); клиент с `AcceptAnyServerCert`, поэтому SNI на внешнем слое не верифицируется (это камуфляж), а вся реальная аутентификация — внутри Aura-рукопожатия. На проводе неотличимо от валидного HTTPS. - ✓ **Авто-NAT на сервере.** `[server.nat] {auto, egress_iface, dry_run}` поднимает IP-форвардинг + MASQUERADE на старте (Linux: `sysctl ip_forward` + `iptables -t nat MASQUERADE`; macOS: `sysctl ip.forwarding` + `pfctl`). RAII-guard откатывает изменения при остановке. Опциональный `dry_run = true` логирует команды без выполнения — для отладки. - ✓ **Privilege drop.** `[server]/[client] run_as = "nobody"` — после поднятия TUN и привилегированных портов euid/gid сбрасываются в нерутового пользователя (Linux: `setresuid/setresgid`; macOS: `setgid` + `setuid` permanent drop). Минимизирует время процесса под root. - ✓ **Admin-сокет на Windows.** Cfg-gated транспорт: на Unix — Unix socket (`/tmp/aura-admin.sock`), на Windows — Tokio named pipe (`\\.\pipe\aura-admin`). JSON-протокол и команды (`route add/list/remove`, `status`) идентичны. - ✓ **In-band CRL.** Сервер сразу после handshake пушит подписанный CA CRL клиенту через мультиплексированный control-envelope с magic-префиксом `[0xAA,0xAA,0xC0,0x01]` (не конфликтует с IPv4/v6, которые начинаются с `0x4X`/`0x6X`). Клиент проверяет подпись ECDSA-P256 против CA, применяет к `AuraCertVerifier`, кэширует на диск. Конфиг `[pki] crl_push = true` / `accept_pushed_crl = true` (по умолчанию). - ✓ **Анти-надзор v2 (NEW в ответ на дрегнет операторов):** - **Port-knocking** на UDP-транспорте: сервер молчит на скан-зондах, отвечает только на валидный 16-байтный HMAC-SHA256 «стук» с ±1-минутным окном (ключ из CA fingerprint). Сканер видит закрытый порт. `[transport.knock] enabled = true`. - **Cover traffic / chaff**: при простое UDP-соединение шлёт `Ping` каждые ~500мс±50% (jitter). Defeats volume/timing-fingerprinting. Под нагрузкой подавляется автоматически. `[transport.cover] enabled = true`. - ✓ **Автоматизация развёртывания:** - `aura server-init --domain ... --pki-dir ...` — одна команда: CA + серверный cert + готовый `server.toml` (с авто-определением egress-iface). - `aura provision-client --id --out ` — выпускает client cert и собирает готовый бандл (`ca.crt` + `client.crt` + `client.key` + `client.toml`). `--id` опционален — дефолт UUID v4 (имя пользователя не привязано к сертификату). - ✓ **Минимизация идентификаторов:** - `[server] no_logs = true` / `[client] no_logs = true` — поля `peer_id`, `client_ip`, `source_addr`, `client_id`, `local_ip`, `user`, `id`, `assigned_ip` редактируются из tracing-вывода через field-level фильтр (события фиксируются, идентификаторы вычищаются). - `[client] bridges = [...]` — список запасных серверов, клиент пробует случайный порядок. Блокировка одного IP не убивает доступ. - ✓ **НОВОЕ: ежедневная ротация масок в 05:00 МСК.** Внешний фингерпринт (SNI/UA/Server- header/UDP padding-профиль) детерминированно меняется раз в сутки. И сервер, и клиент выводят одинаковый `MaskSet` из общего seed (SHA-256 от CA-сертификата) + UTC-даты через HKDF-SHA256, без сетевой координации. Конфиг: `[transport.masks] enabled = true` (по умолчанию). Новые подключения берут текущую маску; уже установленные остаются на своих. Палитры: 16 SNI default + 15 SNI russian, 10 User-Agent, 5 Server-headers, 4 padding-профиля; профиль 0 байт-в-байт совместим с v1-паддингом (бэк-совместимость). v3.2 добавляет `palette = "default" | "russian" | "mixed"` для случая, когда нужно, чтобы outer SNI выглядел как обращение к российскому сайту (см. сценарий в §7). - ✓ **Multi-hop / onion routing v3.1 + v3.2.** Цепочка из 2-3 хопов: client → entry-relay → (опционально middle) → exit. Entry-relay не знает destination, exit-узел не знает клиентский IP. v3.2: per-hop client cert (CN entry и exit различаются — нельзя слинковать handshakes по identity), cell padding (constant-size cells устраняют per-packet size-fingerprinting), CIDR whitelist на relay'е. Конфиг — `[client.circuit]` / `[server.relay]`. См. сценарий §7 для деплоймента «российский entry, иностранный exit». - ✓ **Let's Encrypt outer-TLS cert.** `[server.outer_cert] cert_path / key_path` — outer-TLS слой QUIC и TCP использует настоящий CA-trusted сертификат вместо self-signed Aura cert; внутренний Aura mutual-auth handshake продолжает аутентификацию против Aura CA. ### v3.3 — Windows-as-client стал first-class - ✓ **Windows OS-маршруты реализованы.** `[tunnel.os_routes] enabled = true` теперь работает на Windows: `route ADD MASK METRIC 1` для DIRECT-обходов, `netsh interface ipv4 add route "Aura" store=active` для VPN-маршрутов через wintun- адаптер. Дефолт-GW автодетектится через `route print 0`. Rollback подменяет `ADD`→`DELETE` и `add`→`delete` на обоих путях. Подробности и пошаговый запуск — в §8. - ✓ **wintun audit.** Найден и устранён баг: `Arc` больше не дропается раньше `Session` (поле `_adapter` в `AuraTun` держит адаптер живым на всё время сессии). - ✓ **Cross-compile.** Весь workspace проверен под `cargo check --target x86_64-pc-windows-gnu` без warnings. ### Остающиеся честные ограничения - **TUN всё ещё требует root / Администратор** для **создания** интерфейса (это OS-уровень). На Linux/macOS privilege drop минимизирует окно работы под root; на Windows аналога нет — клиент работает от Администратора до выхода (warning в логе). - **IPv6 в OS-маршрутах и iptables MASQUERADE** не реализован — только IPv4 (план v3.4). - **Windows-as-server не первоклассный.** `[server.nat]` (IP-форвардинг + MASQUERADE) на Windows не реализован; роль сервера / relay лучше держать на Linux/macOS. Windows клиент работает с любым сервером. - **Нативного Go-клиента для телефона нет** — через sing-box (Option B нативный Go-outbound, по `protocol.md` + KAT из Rust, см. [`sing-box.md`](sing-box.md)). Сейчас доступен только десктоп-клиент / process-bridge. Это явно исключённый из v2 пункт. - **Bridge-discovery без хардкода IP в конфиге** — план v3.3. Сейчас `[client] bridges` хардкодит список запасных IP; если их все заблокируют (включая российские entry-узлы из сценария §7), восстановление требует обновления конфига клиента вручную. --- ## 7. Сценарий: российский entry-узел против тарификации иностранного трафика ### 7.1. Контекст и угроза Российские операторы связи могут начать тарифицировать «иностранный трафик» отдельно: классификация выполняется по destination IP исходящего пакета пользователя. Если первый IP, к которому обращается устройство, — российский, биллинг считает соединение «российским», даже если внутри этого соединения трафик уходит дальше за рубеж. Цель в этом сценарии — добиться того, чтобы оператор биллил трафик пользователя как «российский», при этом сохраняя VPN-выход за рубежом. Решение опирается на три компонента, уже реализованные в AuraVPN: 1. **Multi-hop / onion routing v3.1+** (`[client.circuit]` / `[server.relay]`) — entry-узел в РФ не знает destination, exit-узел за рубежом не знает клиентский IP. 2. **Палитра SNI «russian»** (v3.2) — `[transport.masks] palette = "russian"` ротирует outer-TLS SNI среди крупных российских доменов (`vk.com`, `www.ozon.ru`, `mail.yandex.ru`, ...). 3. **OS-уровень kill-switch** (`[tunnel.os_routes] enabled = true`) — гарантия, что системный трафик (push-уведомления, OS-сервисы) не обходит туннель и не попадает напрямую к иностранным серверам в обход entry-узла. ### 7.2. Топология ``` [устройство] | | весь трафик через TUN (kill-switch) v [оператор] <-- видит только UDP/443 на RU_VPS_IP, SNI = "vk.com" | v [Russian VPS / entry-relay] <-- v3.1 relay: forward to next hop, never decodes IP packets | | inner Aura handshake (PQ-encrypted, opaque) v [Foreign VPS / exit] <-- настоящий VPN-выход в интернет | v [internet] ``` Оператор видит только трафик до **entry-узла**: один UDP-поток с SNI крупного российского сайта. Внутри этого потока — зашифрованный многохоп; entry-relay не имеет ключей внутреннего рукопожатия и видит только AEAD-ciphertext, который он форвардит на exit. Exit видит только IP entry-узла, а не IP клиентского устройства. ### 7.3. Что покупать **Подходящие провайдеры для entry-узла в РФ** (юрисдикция РФ, IP в российских AS): - **Selectel** (Москва, СПб). - **Beget** (СПб). - **Yandex.Cloud** (Москва). - **VK Cloud** (бывш. Mail.ru Cloud Solutions). - **Timeweb Cloud**. **Неподходящие для роли entry-узла в РФ**: - **Hetzner** (Германия/Финляндия) — IP классифицируется как «иностранный». - **DigitalOcean / Vultr / Linode** (США/EU) — то же самое. - **AWS / GCP / Azure** даже с российскими DC-локациями — IP-блоки за пределами российских AS у большинства операторов. Для **exit-узла** наоборот — берите любой удобный иностранный VPS (Hetzner, DigitalOcean, Vultr, любой подходящий по юрисдикции и пропускной способности). ### 7.4. Конфиг сервера в РФ (entry-relay) `server.toml` на российском VPS (например, Selectel с IP `RUSSIAN_VPS_IP`): ```toml [server] name = "aura-ru-entry-1" listen = "0.0.0.0:443" [pki] ca_cert = "/etc/aura/pki/ca.crt" cert = "/etc/aura/pki/server/server.crt" key = "/etc/aura/pki/server/server.key" [tunnel] # Pool нужен формально (для v1-fallback-пути), но в роли чистого relay он не используется — # bridged-клиенты не получают IP из пула и не регистрируются в ServerRouter. pool_cidr = "10.7.0.0/24" mtu = 1420 # v3.1: relay-режим. Принимаем ExtendBridge от клиента и сплайсим на foreign exit. [server.relay] enabled = true allow_extend_to = ["EXIT_FOREIGN_IP:443"] # IP вашего иностранного exit-узла # v3.2 cell padding: relay сам не декодирует — это сквозной байт-форвардинг. Знаки опции тут # для симметрии конфига; реальный декод цельных ячеек — на exit'е. cell_padding = true cell_size = 1280 [transport.masks] enabled = true # v3.2: outer-TLS SNI крутится среди крупных российских доменов. Каждый день — другой домен. palette = "russian" # Опционально: настоящий outer-TLS сертификат (Let's Encrypt) поверх UDP/QUIC и TCP. Без него # работает self-signed Aura, но с настоящим LE-сертификатом outer-handshake становится # неотличим от обычного HTTPS на CA-trusted сайт. [server.outer_cert] cert_path = "/etc/letsencrypt/live/relay.example.ru/fullchain.pem" key_path = "/etc/letsencrypt/live/relay.example.ru/privkey.pem" ``` И аналогичный `server.toml` на **иностранном exit-узле** — обычный VPN-сервер БЕЗ `[server.relay]`, но с `cell_padding_for_circuit_clients = true` в секции `[server]`, чтобы он понимал constant-size cells от клиента: ```toml [server] name = "aura-exit-1" listen = "0.0.0.0:443" # v3.2: exit для cell-padded клиентов — декодирует ячейки внутреннего рукопожатия. cell_padding_for_circuit_clients = true [pki] ca_cert = "/etc/aura/pki/ca.crt" cert = "/etc/aura/pki/server/exit.crt" key = "/etc/aura/pki/server/exit.key" [tunnel] pool_cidr = "10.7.0.0/24" [server.nat] auto = true # включить IP-форвардинг и MASQUERADE на egress-интерфейсе egress_iface = "eth0" [transport.masks] # На exit'е SNI палитра не критична (клиент видит exit только через relay) — оставим default. palette = "default" ``` ### 7.5. Конфиг клиента ```toml [client] name = "laptop" server_addr = "RUSSIAN_VPS_IP:443" # entry-узел в РФ; именно этот IP видит оператор sni = "relay.example.ru" # SAN серверного outer-TLS сертификата (если есть LE) [pki] ca_cert = "~/.aura/ca.crt" cert = "~/.aura/client.crt" key = "~/.aura/client.key" [tunnel] tun_name = "aura0" local_ip = "10.7.0.2" prefix = 24 mtu = 1420 [tunnel.split] default = "VPN" # КРИТИЧНО: kill-switch — весь трафик через TUN, OS-уровень. Без этого push-уведомления и # OS-сервисы могут уйти напрямую в иностранные сервера в обход entry-узла, и оператор # зачтёт это как «иностранный» трафик. [tunnel.os_routes] enabled = true # v3.1 / v3.2: цепочка хопов client -> RU_entry -> foreign_exit. [client.circuit] enabled = true cell_padding = true cell_size = 1280 [[client.circuit.hops]] addr = "RUSSIAN_VPS_IP:443" # entry в РФ — то, что видит оператор cert_path = "~/.aura/circuit/entry.crt" key_path = "~/.aura/circuit/entry.key" [[client.circuit.hops]] addr = "EXIT_FOREIGN_IP:443" # exit за рубежом, к которому привязаны DNS/маршруты внутри VPN cert_path = "~/.aura/circuit/exit.crt" key_path = "~/.aura/circuit/exit.key" [transport.masks] enabled = true # Должно совпадать с palette = "russian" на entry-узле — иначе SNI в логах двух сторон # не будут симметричны (на проводе это не ошибка, но удобнее для отладки). palette = "russian" ``` Сертификаты двух хопов — разные (`entry.crt` != `exit.crt`). Это v3.2 identity-unlinkability: entry-relay видит только клиентский cert для роли entry, exit-узел видит только cert для роли exit, и они не пересекаются (см. `aura provision-client --circuit-hops 2 ...`). ### 7.6. Что это даёт - **Оператор биллит как «российский».** На проводе оператор видит один UDP-поток на `RUSSIAN_VPS_IP:443` — это российский IP в российской AS, классификатор биллинга его не обозначает как иностранный. - **SNI выглядит как обращение к российскому сайту.** В пакетах outer-TLS / outer-QUIC hostname-камуфляж берётся из `SNI_PALETTE_RUSSIAN`: каждый день — другой домен (`vk.com`, `www.ozon.ru`, `mail.yandex.ru`, ...). DPI видит «нормальный HTTPS на крупный российский сайт». - **Реальный VPN-выход — за рубежом.** Внутри multi-hop клиент дозванивается до иностранного exit-узла; именно его IP видят внешние ресурсы. Entry-узел в РФ форвардит зашифрованный трафик, не зная destination и не имея ключей внутреннего рукопожатия. - **Kill-switch предотвращает обход.** `[tunnel.os_routes] enabled = true` программирует системную таблицу маршрутов так, что весь трафик идёт через TUN — push-уведомления, OS-сервисы и любые «прямые» обращения в обход VPN заблокированы, поэтому ничто из устройства не уйдёт напрямую к иностранному IP в обход entry-узла. ### 7.7. Что это НЕ даёт (честное ограничение) - **Не скрывает сам факт VPN-использования** от российских органов. DPI с deep-inspection может по статистическим паттернам трафика (timing, размеры, поведение в течение сессии) узнать Aura-протокол; ротация масок и `palette = "russian"` маскирует пассивного наблюдателя, но не активного аналитика. Для дополнительной защиты включайте `[transport.knock]` и `[transport.cover]` (port-knocking + cover traffic). - **Не освобождает от ответственности за заходы на запрещённые ресурсы.** Кто и за что отвечает при заходе на запрещённый ресурс через VPN — вопрос юрисдикции exit-узла и применимого законодательства, не технический. - **Не защищает от блокировки самого entry-IP.** Если СОРМ-система или Роскомнадзор начнут активно блокировать конкретные VPS-IP, придётся ротировать IP / bridges. Сейчас это решается через `[client] bridges = [...]` — список запасных российских entry-узлов; клиент пробует их в случайном порядке при отказе primary. Полноценный bridge-discovery (без хардкода IP в конфиге) — план v3.3. - **Cell padding не скрывает наличие туннеля.** Constant-size cells устраняют per-packet size-fingerprinting внутри multi-hop, но не делают сам поток неотличимым от HTTPS — общий объём и временные паттерны остаются. Это компромисс между обфускацией и накладными расходами. ### 7.8. Что менять при ротации При смене IP entry-узла (например, при блокировке текущего) обновите три места: 1. `[[client.circuit.hops]] addr` первого хопа → новый `RUSSIAN_VPS_IP:443`. 2. `[client] server_addr` → тот же новый IP. 3. На новом VPS — поднять PKI, выпустить cert для entry-роли, перенести `server.toml` с `[server.relay]` и `palette = "russian"`. Перевыпускать сертификаты двух хопов не нужно — они остаются те же, меняется только wire-адрес entry-узла. На сертификате entry-сервера должен быть SAN, совпадающий с `[client] sni` (см. `aura pki issue-server --domain relay.example.ru`). --- ## 8. Windows как клиент Windows-клиент стал first-class в v3.3. Сервер на Windows не поддерживается на уровне автонастройки сети — `[server.nat]` (IP-форвардинг + MASQUERADE) реализован только для Linux/macOS. Эта секция — про **клиент**. ### 8.1. Требования - Windows 10 / 11 (или Server 2019+) с правами **Администратора** для процесса `aura.exe` — поднятие wintun-адаптера и программирование таблицы маршрутов требуют привилегий. - **wintun.dll** рядом с `aura.exe`. Скачать с официального сайта [https://www.wintun.net/](https://www.wintun.net/) (драйвер от автора WireGuard); распаковать `wintun/bin/amd64/wintun.dll` в каталог `aura.exe`. ### 8.2. Сборка / получение бинаря Если у вас есть Rust toolchain на Windows — `cargo build --release` соберёт `target\release\aura.exe`. С macOS / Linux можно собрать кросс-компиляцией (нужен mingw-w64): ```bash rustup target add x86_64-pc-windows-gnu # (на macOS) brew install mingw-w64 cargo build --release --target x86_64-pc-windows-gnu # -> target/x86_64-pc-windows-gnu/release/aura.exe ``` ### 8.3. PKI и провижининг Команды `aura.exe pki ...` и `aura.exe provision-client ...` работают идентично Unix-версии (см. §2.2). Бандл для клиента — те же три PEM-файла (`ca.crt`, `client.crt`, `client.key`) плюс `client.toml`. PowerShell-форма: ```powershell .\aura.exe pki init --ca-name "Aura Root CA" --out C:\ProgramData\Aura\pki .\aura.exe pki issue-server --domain vpn.example.com --out C:\ProgramData\Aura\pki\server ` --ca C:\ProgramData\Aura\pki .\aura.exe provision-client --id laptop-1 --out C:\Users\me\.aura ``` ### 8.4. `client.toml` на Windows Раскладка идентична §4.1. Имя TUN — это **отображаемое имя wintun-адаптера**: указанное в `tun_name` имя становится `Display Name` адаптера в Device Manager (а также используется в командах `netsh interface ipv4 add route ... "Aura"` — см. §8.5). ```toml [client] name = "laptop" server_addr = "203.0.113.10:443" sni = "vpn.example.com" # run_as на Windows — no-op (нет аналога setresuid; warning в логе). [pki] ca_cert = "C:\\Users\\me\\.aura\\ca.crt" cert = "C:\\Users\\me\\.aura\\client.crt" key = "C:\\Users\\me\\.aura\\client.key" [tunnel] tun_name = "Aura" # имя wintun-адаптера; то же имя используется в netsh-командах ниже local_ip = "10.7.0.2" prefix = 24 mtu = 1420 [tunnel.split] default = "VPN" [[tunnel.split.direct]] cidr = "192.168.0.0/16" # v3.3: OS-уровень kill-switch теперь работает на Windows. [tunnel.os_routes] enabled = true # Опционально: pin gateway + interface IP (читается `route print 0` если не задано). # gateway = "192.168.1.1" # egress_iface = "192.168.1.42" [transport] order = ["udp", "tcp", "quic"] udp_port = 443 tcp_port = 443 quic_port = 444 ``` ### 8.5. Что делает `[tunnel.os_routes]` на Windows На Linux/macOS клиент программирует системную таблицу маршрутов через `ip` / `route`. На Windows — через `route ADD` (для DIRECT-обходов через исходный default-GW) и `netsh interface ipv4 add route` (для VPN-маршрутов через wintun-адаптер). **Auto-detect default GW:** клиент выполняет `route print 0` и парсит row `0.0.0.0 0.0.0.0 ` из IPv4 Active Routes. Если автодетект не сработал (например, у машины несколько NIC и нет default'а в IPv4-таблице) — задайте `gateway` и `egress_iface` явно в `[tunnel.os_routes]`. На Windows `egress_iface` — это **IP** upstream-интерфейса (не имя), как в колонке `Interface` в `route print`. **Что реально выполняется** (с пулом DIRECT `192.168.0.0/16` и default = VPN): ``` netsh interface ipv4 add route 0.0.0.0/0 "Aura" 10.7.0.2 store=active route ADD 192.168.0.0 MASK 255.255.0.0 192.168.1.1 METRIC 1 ``` **Что выполняется при выходе клиента** (Drop порядка LIFO): ``` route DELETE 192.168.0.0 MASK 255.255.0.0 netsh interface ipv4 delete route 0.0.0.0/0 "Aura" ``` `store=active` указывает Windows не сохранять маршрут в персистентном store — он привязан к TUN, который исчезает на выходе клиента. Параметр `METRIC 1` обеспечивает приоритет DIRECT-обхода над любыми существующими маршрутами с большей метрикой. ### 8.6. Запуск PowerShell как Администратор: ```powershell cd C:\Aura .\aura.exe client --config .\client.toml ``` В логе при успехе: ``` INFO connected and authenticated to server peer=Some("vpn.example.com") mode=udp INFO OS-level split-tunnel routes installed (DIRECT traffic now bypasses the TUN) INFO running: netsh interface ipv4 add route 0.0.0.0/0 "Aura" 10.7.0.2 store=active INFO running: route ADD 192.168.0.0 MASK 255.255.0.0 192.168.1.1 METRIC 1 ``` Прервать через `Ctrl+C` — выводящийся guard корректно вызывает `route DELETE` / `netsh ... delete route` и затем закрывает wintun-сессию + адаптер (см. §8.7). ### 8.7. Cleanup на Windows (что происходит при остановке клиента) Порядок dropping: 1. **OsRouteGuard::drop** — выполняет rollback-команды в LIFO-порядке (`route DELETE ...`, затем `netsh ... delete route ...`). Ошибки логируются warn-ом, дальнейший rollback продолжается — один сбойный шаг не остановит зачистку остальных маршрутов. 2. **wintun::Session::drop** — `WintunEndSession` завершает сессию (закрывает ring buffer). 3. **wintun::Adapter::drop** — `WintunCloseAdapter` снимает адаптер с системы. Drop порядка полей в `AuraTun` гарантирует, что Session завершается до Adapter (поле `inner` объявлено раньше `_adapter`). Если процесс упал без graceful shutdown (kill -9 / BSOD): wintun-адаптер останется зарегистрированным в системе, и при следующем запуске `Adapter::create` найдёт его по имени и переиспользует. Орфанных системных маршрутов в персистентном store не будет — все наши маршруты идут через `store=active`, которые система очищает на reboot. ### 8.8. Известные ограничения Windows-клиента - **`run_as`** на Windows — no-op. Аналога `setresuid` для безпрепятственного drop'а к service-account во время работы нет; рекомендация — запустить `aura.exe` как Windows Service от выделенной учётной записи (см. документацию `sc.exe create`), либо просто из PowerShell-сессии Администратора. - **`[server.nat]`** на Windows не реализован — Windows-as-server не первоклассный сценарий. Используйте Linux/macOS для роли сервера / relay. - **IPv6 routes** программируются через `netsh interface ipv6 add route` для VPN, но IPv6 DIRECT-обходы попадают в тот же `netsh ipv6` путь (а не в IPv4-only `route ADD`). Для чистой IPv4-only установки это не имеет значения. - **Mixed-mode** (часть транспортов в одну сеть, часть в другую) на Windows не тестировался глубоко — `netsh ... store=active` маршруты могут конфликтовать с существующими VPN- клиентами (WireGuard, OpenVPN) если те уже захватили default-route. Отключите конкурирующие VPN перед запуском aura-клиента.