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 <noreply@anthropic.com>
This commit is contained in:
@@ -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/<id>/client.crt`) — листовой сертификат клиента;
|
||||
- `client.key` (из `/etc/aura/clients/<id>/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 <PATH>` к каждой команде. Полная спецификация
|
||||
команд и 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.
|
||||
|
||||
Reference in New Issue
Block a user