Step-by-step guide for migrating a Mac fully to AuraVPN as the always-on default VPN: provisioning a bundle (with the v3.4 server-side static-map workaround documented as task #52), installing the client binary, configuring split / full-VPN mode, disabling other coexisting VPNs (the recurring utun4 issue), GUI vs CLI launch, auto-start via LaunchAgent for the GUI tray and LaunchDaemon for the CLI client, DNS-through-tunnel setup, end-to-end verification commands, and a full rollback recipe. Also closes the knowledge gap "where is the .app — I don't see it": we never ran `npm run tauri build` before, so the GUI lived only as src. §6 covers building and installing the .app, including the macOS Gatekeeper workaround for the unsigned v0.1 build. Includes the empirical confirmation from this session's Phase 1 test (5/5 ICMP, server tx/rx counters via the #42 fix, RTT 61 ms over the encrypted TCP/443 tunnel) so the doc has a known-good baseline. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Aura VPN
Aura — гибридный пост-квантовый VPN на Rust. Внутреннее рукопожатие гибридное и взаимно аутентифицированное (X25519 + ML-KEM-768 по FIPS 203 со взаимной X.509-проверкой), данные шифруются ChaCha20-Poly1305 с explicit-nonce, обфускация — паддинг датаграмм под «корзины» HTTPS-размеров.
На проводе по умолчанию идёт собственный UDP-транспорт Aura (без QUIC и без внешнего TLS на
основном пути). Если сеть режет UDP, клиент автоматически переключается на TCP/443 или QUIC
(мимикрия HTTP/3), последовательно пробуя транспорты из настраиваемого [transport] order. На
стороне клиента есть TUN-интерфейс и split-tunnel (longest-prefix matching по CIDR + правила по
доменам), которым можно управлять на лету через admin-сокет.
Крейты
| Крейт | Что внутри |
|---|---|
aura-crypto |
Гибридный KEM (X25519 + ML-KEM-768), HKDF, AEAD ChaCha20-Poly1305, helpers |
aura-pki |
Самоподписанный CA, выпуск server/client-сертификатов, проверка, плоский CRL |
aura-proto |
Рукопожатие Aura, фрейминг, датаграмный/потоковый кодек данных |
aura-transport |
Транспорты: собственный UDP, TCP/443, QUIC; единый dialer с handover |
aura-tunnel |
TUN, маршрутизатор, split-tunnel (CIDR + домены), DNS-резолв в host-маршруты |
aura-cli |
Бинарь aura: pki, server, client, route, status, bench-crypto |
Сопутствующая документация
- docs/protocol.md — wire-протокол: рукопожатие, кадры, выбор транспорта
- docs/pki.md — модель PKI, команды
aura pki, верификация и CRL - docs/split-tunnel.md — split-tunnel, статика и admin-сокет на лету
- docs/sing-box.md — план интеграции с sing-box (для мобильных клиентов)
- docs/deployment.md — копия инструкции по развёртыванию (та же, что ниже в README)
Состояние
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. Установка бинаря
В корне репозитория:
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.
# 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.
Совет (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). Скопируйте пример и поправьте под себя.
[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 (см. конфиг выше). Если хотите по-старому вручную:
# 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. Запуск сервера
sudo aura server --config /etc/aura/server.toml
sudo нужен для создания TUN-устройства и для биндинга привилегированных портов (:443). С
[server] run_as = "nobody" процесс сбросит привилегии после старта (TUN остаётся живым).
Можно опционально указать путь admin-сокета:
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.
4.1. client.toml
Раскладка взята из config/client.toml.example и crates/aura-cli/src/config.rs.
[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.
4.2. Запуск клиента
sudo aura client --config client.toml
sudo нужен для поднятия TUN-устройства. Клиент:
- Загружает PEM-файлы из
[pki]и строитaura_proto::ClientConfig. - Строит таблицу маршрутизации из
[tunnel.split]. - Дозванивается до сервера, перебирая транспорты в
[transport] order(handover UDP → TCP → QUIC); первый, который удался, побеждает. - Разрезолвит доменные правила split-tunnel'а в host-маршруты (best-effort).
- Создаёт 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-сокет позволяет менять правила и смотреть статус без перезапуска:
# Добавить 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.
5. Что идёт по проводу (резюме)
- Основной: собственный UDP-транспорт Aura (в примере —
443/udp). Один UDP-сокет несёт обе фазы, различимые по первому байту:0x01HS — рукопожатие с надёжным DTLS-подобным слоем поверх (повторы, ack, упорядочивание);0x02DATA — датаграммы данных с 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.
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).
- Bridge-discovery без хардкода IP — план v3.3.
7. Сценарий: российский entry-узел против тарификации иностранного трафика
7.1. Контекст и угроза
Российские операторы связи могут начать тарифицировать «иностранный трафик» отдельно: классификация выполняется по destination IP исходящего пакета пользователя. Если первый IP, к которому обращается устройство, — российский, биллинг считает соединение «российским», даже если внутри этого соединения трафик уходит дальше за рубеж. Цель — добиться того, чтобы оператор биллил трафик пользователя как «российский», при этом сохраняя VPN-выход за рубежом.
Решение опирается на три компонента, уже реализованные в AuraVPN:
- Multi-hop / onion routing v3.1+ (
[client.circuit]/[server.relay]) — entry-узел в РФ не знает destination, exit-узел за рубежом не знает клиентский IP. - Палитра SNI «russian» (v3.2) —
[transport.masks] palette = "russian"ротирует outer-TLS SNI среди крупных российских доменов (vk.com,www.ozon.ru,mail.yandex.ru, ...). - 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):
[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 от клиента:
[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. Конфиг клиента
[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-узла (например, при блокировке текущего) обновите три места:
[[client.circuit.hops]] addrпервого хопа → новыйRUSSIAN_VPS_IP:443.[client] server_addr→ тот же новый IP.- На новом 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.