From 1893e24174f00589d89177e9ae09f56711a32144 Mon Sep 17 00:00:00 2001 From: xah30 Date: Wed, 27 May 2026 20:38:39 +0300 Subject: [PATCH] docs: README is now the full deployment guide Expanded the root README to include the complete setup instructions (crates table + intro + the full 7-section deployment guide that previously lived only in docs/deployment.md, with the doc-link paths adjusted for a root-level README and a list of every v2/v3 feature plus the RF entry-relay scenario). docs/deployment.md is preserved for in-tree navigation. Co-Authored-By: Claude Opus 4.7 --- README.md | 720 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 711 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d9056c0..3954bdc 100644 --- a/README.md +++ b/README.md @@ -22,15 +22,717 @@ HTTPS-размеров. | `aura-tunnel` | TUN, маршрутизатор, split-tunnel (CIDR + домены), DNS-резолв в host-маршруты | | `aura-cli` | Бинарь `aura`: `pki`, `server`, `client`, `route`, `status`, `bench-crypto` | -## Быстрый старт +## Сопутствующая документация -Подъём сервера на удалённой машине и подключение клиента описаны в -[`docs/deployment.md`](docs/deployment.md). Это основная точка входа для развёртывания. +- [docs/protocol.md](docs/protocol.md) — wire-протокол: рукопожатие, кадры, выбор транспорта +- [docs/pki.md](docs/pki.md) — модель PKI, команды `aura pki`, верификация и CRL +- [docs/split-tunnel.md](docs/split-tunnel.md) — split-tunnel, статика и admin-сокет на лету +- [docs/sing-box.md](docs/sing-box.md) — план интеграции с sing-box (для мобильных клиентов) +- [docs/deployment.md](docs/deployment.md) — копия инструкции по развёртыванию (та же, что ниже в README) -## Документация +## Состояние -- [`docs/deployment.md`](docs/deployment.md) — руководство по развёртыванию (сервер + клиент) -- [`docs/protocol.md`](docs/protocol.md) — wire-протокол: рукопожатие, кадры, выбор транспорта -- [`docs/pki.md`](docs/pki.md) — модель PKI, команды `aura pki`, верификация и CRL -- [`docs/split-tunnel.md`](docs/split-tunnel.md) — split-tunnel, статика и admin-сокет на лету -- [`docs/sing-box.md`](docs/sing-box.md) — план интеграции с sing-box (для мобильных клиентов) +`cargo test --workspace` → 284 passed, 0 failed. `cargo clippy --workspace --all-targets -- -D warnings` чисто. `cargo fmt --all -- --check` чисто. + +--- + +# Инструкция по развёртыванию + +Этот README — пошаговое руководство, по которому вы поднимаете сервер Aura на удалённой машине, +провижините на нём сертификат для клиента и подключаете клиент (десктоп) к этому серверу. Все +команды и поля конфигов взяты из фактического кода и поставляемых примеров в `config/`. + +--- + +## 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`) — см. [docs/pki.md](docs/pki.md). + +> **Совет (v2 автоматизация):** есть однокомандный вариант: +> `aura server-init --domain vpn.example.com --pki-dir /etc/aura/pki --out-config /etc/aura/server.toml --enable-knock --enable-cover-traffic` +> — это сразу делает CA + серверный cert + готовый `server.toml`. Полезно для свежей машины. + +### 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] +# Адресный пул для клиентов; v2 сервер выдаёт IP из этого пула per-client. +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 + +[transport.masks] +# v2: ежедневная ротация SNI/UA/Server-header/padding-профиля в 05:00 МСК. Обе стороны +# выводят MaskSet детерминированно из CA fingerprint + UTC-даты. +enabled = true +# default | russian | mixed — выбор палитры SNI: +# default: глобальные CDN-домены (cloudflare, akamai, ...); +# russian: крупные российские (vk.com, mail.yandex.ru, ozon.ru, ...); +# mixed: ~50/50 random-pick по дням. +palette = "default" + +[transport.knock] +# v2: probe resistance. Сервер молчит на скан-зондах; отвечает только на валидный +# 16-байтный HMAC-стук, ключ выводится из CA fingerprint. ±1-минутное окно для clock skew. +enabled = true + +[transport.cover] +# v2: cover traffic. При простое отправляет Ping каждые ~500мс±50% — поток выглядит +# постоянным. Под нагрузкой подавляется автоматически (idle-only). +enabled = true + +[server.nat] +# v2: авто-настройка IP-форвардинга и MASQUERADE на старте; откат при остановке. +auto = true +egress_iface = "eth0" # опционально — autodetect через `ip route show default` +# dry_run = true # для отладки: логировать команды без выполнения + +[server.pool] +# v2: IP-пул для VPN-клиентов. cidr может совпадать с [tunnel] pool_cidr. +cidr = "10.7.0.0/24" +strategy = "static_or_dynamic" # static_only | dynamic_only | static_or_dynamic + +[server.pool.static] +# Опциональные привязки по client_id (CN из сертификата). +# "phone-1" = "10.7.0.20" +# "laptop-1" = "10.7.0.21" + +# Опционально v3: настоящий outer-TLS сертификат (Let's Encrypt) поверх QUIC/TCP. +# Без него работает self-signed Aura cert; с LE outer-TLS неотличим от обычного HTTPS. +# [server.outer_cert] +# cert_path = "/etc/letsencrypt/live/vpn.example.com/fullchain.pem" +# key_path = "/etc/letsencrypt/live/vpn.example.com/privkey.pem" + +# Опционально v2: privilege drop после поднятия TUN. +# run_as = "nobody" +``` + +Пути могут начинаться с `~` (раскрывается в домашнюю директорию). + +### 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 + +В v2 это делает `[server.nat] auto = true` (см. конфиг выше). Если хотите по-старому вручную: + +```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`). С +`[server] run_as = "nobody"` процесс сбросит привилегии после старта (TUN остаётся живым). + +Можно опционально указать путь 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`. + +Эти три файла плюс два параметра — это всё, что нужно клиенту для подключения. + +> **Совет (v2 автоматизация):** `aura provision-client --id phone-1 --out ./phone-1-bundle` — +> одна команда, которая выпускает клиентский сертификат и собирает готовый бандл (ca + cert + key +> + готовый client.toml) для передачи на устройство. `--id` опционален: без него генерируется +> UUID v4, и имя пользователя не привязано к сертификату. + +--- + +## 4. Клиент (десктоп) + +Путь для телефона — через sing-box; пока нативного клиента нет, см. [docs/sing-box.md](docs/sing-box.md). + +### 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" +# Опционально v2: запасные серверы; клиент пробует случайным порядком. +# bridges = ["203.0.113.11", "203.0.113.12"] +# Опционально v2: фильтр чувствительных полей из tracing-логов (peer_id, client_ip, ...). +# no_logs = false + +[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" + +[tunnel.os_routes] +# v2: ОС-уровень split-tunnel: программируем системную таблицу маршрутов так, что +# DIRECT-трафик идёт мимо TUN через default-gateway, а через TUN попадает только VPN. +# КРИТИЧНО для случая «весь трафик через VPN» (kill-switch). +enabled = true + +[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 + +[transport.masks] +enabled = true +palette = "default" # должна совпадать с server.toml + +[transport.knock] +enabled = true # если включено на сервере + +[transport.cover] +enabled = true # если включено на сервере +``` + +Подробности про `[tunnel.split]` — в [docs/split-tunnel.md](docs/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, программирует ОС-маршруты (если `[tunnel.os_routes] enabled = true`), + передаёт 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'а — в [docs/split-tunnel.md](docs/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-протокол — в [docs/protocol.md](docs/protocol.md). + +--- + +## 6. v2/v3 — что реализовано и что остаётся + +### Сделано в v2 + +- **Мульти-клиент UDP-сервер** (демультиплексор по адресу пира; один сокет — много пиров). +- **IP-пул + per-client маршрутизация** на сервере (`[server.pool]`). +- **ОС-уровень split-tunnel** (`[tunnel.os_routes]`) — устранил `send_direct` заглушку. +- **Настоящий TLS-443** в TCP-транспорте (rustls outer + AcceptAnyServerCert). +- **Авто-NAT** на сервере (`[server.nat] auto = true`). +- **Privilege drop** (`run_as = "nobody"`). +- **Admin-сокет на Windows** (named pipe). +- **In-band CRL** (сервер пушит подписанный CRL клиенту по handshake'у). +- **Ежедневная ротация масок в 05:00 МСК** (`[transport.masks]`). +- **Port-knocking** (`[transport.knock]`) — сервер молчит на скан-зондах. +- **Cover traffic / chaff** (`[transport.cover]`). +- **`aura server-init`** и **`aura provision-client`** — однокомандный bootstrap и провижин. +- **`--id` опционален**: UUID v4 default. +- **`no_logs`** — field-level редактирование идентификаторов из tracing. +- **`bridges`** — список запасных IP-серверов. + +### Сделано в v3 + +- **Let's Encrypt outer-cert** (`[server.outer_cert]`) — outer-TLS неотличим от обычного HTTPS. +- **Multi-hop / onion routing v3.1/v3.2** — цепочка из 2-3 хопов с разными сертами на каждом + (identity unlinkability), cell padding (constant-size cells), CIDR whitelist на relay. +- **`palette = "russian"`** — outer SNI ротируется среди крупных российских доменов (см. §7). + +### Остающиеся честные ограничения + +- TUN всё ещё требует root для **создания** интерфейса (privilege drop минимизирует окно, но саму + операцию обойти нельзя). +- IPv6 в OS-маршрутах и iptables MASQUERADE не реализован (план v3.3). +- Windows OS-маршруты — заглушка (план v3.3). Windows admin pipe работает. +- Нативного Go-клиента для телефона нет — через sing-box (см. [docs/sing-box.md](docs/sing-box.md)). +- Bridge-discovery без хардкода IP — план v3.3. + +--- + +## 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`). + +--- + +## Лицензия + +MIT.