§5: TCP/443 fallback now described as real outer TLS-443 (was the lighter HTTP/1.1 masquerade in v1). §6 rewritten "Честные ограничения v1" -> "v2 — что устранено и что остаётся": - Resolved: UDP multi-client demux, server IP pool + per-client routing, OS-level split-tunnel (no more send_direct stub), real TLS-443, auto-NAT, privilege drop, Windows admin named pipe, daily protocol-mask rotation at 05:00 MSK. - Remaining honest limits: TUN creation still needs root (privilege drop shrinks the window), IPv6 in OS routes / iptables not yet, Windows OS routes stubbed, CRL still out-of-band (in-band push deferred), native phone client via sing-box still a plan, no auto-detect of egress iface. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
21 KiB
Развёртывание Aura VPN
Этот документ — пошаговое руководство, по которому вы поднимаете сервер Aura на удалённой машине,
провижините на нём сертификат для клиента и подключаете клиент (десктоп) к этому серверу. Все
команды и поля конфигов взяты из фактического кода и поставляемых примеров в config/.
Полезные сопутствующие документы:
protocol.md(wire-протокол),pki.md(CA и сертификаты),split-tunnel.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. Установка бинаря
В корне репозитория:
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) — см. pki.md.
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]
# Адресный пул для клиентов; в 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:
# 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).
Можно опционально указать путь 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.
Эти три файла плюс два параметра — это всё, что нужно клиенту для подключения.
4. Клиент (десктоп)
Путь для телефона — через sing-box; пока нативного клиента нет, см. раздел 6 ниже.
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"
[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.
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, передаёт его маршрутизатору и начинает гонять трафик.
В логе при успехе вы увидите строку с выбранным транспортом:
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'а — в 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-протокол — в 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<dyn PacketConnection>, читает с 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+setuidpermanent 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) идентичны. - ✓ НОВОЕ: ежедневная ротация масок в 05:00 МСК. Внешний фингерпринт (SNI/UA/Server-
header/UDP padding-профиль) детерминированно меняется раз в сутки. И сервер, и клиент
выводят одинаковый
MaskSetиз общего seed (SHA-256 от CA-сертификата) + UTC-даты через HKDF-SHA256, без сетевой координации. Конфиг:[transport.masks] enabled = true(по умолчанию). Новые подключения берут текущую маску; уже установленные остаются на своих. Палитры: 16 SNI, 10 User-Agent, 5 Server-headers, 4 padding-профиля; профиль 0 байт-в-байт совместим с v1-паддингом (бэк-совместимость).
Остающиеся честные ограничения v2
- TUN всё ещё требует root для создания интерфейса (это OS-уровень). Privilege drop минимизирует окно работы под root, но саму операцию обойти нельзя.
- IPv6 в OS-маршрутах и iptables MASQUERADE не реализован — только IPv4 (план v3).
- Windows OS-маршруты — заглушка с лог-warning (план v3). Windows admin pipe работает.
- CRL пока распространяется out-of-band (плоский файл
revoked.crlна сервере и клиенте); in-band пуш сервером → клиенту запланирован (отдельная v2-задача, не реализована в этом раунде). - Нативного Go-клиента для телефона нет — через sing-box (Option B нативный Go-outbound,
по
protocol.md+ KAT из Rust, см.sing-box.md). Сейчас доступен только десктоп-клиент / process-bridge. - Автоопределение egress-интерфейса для NAT не реализовано:
[server.nat] egress_ifaceобязательно задавать вручную, еслиauto = true(план v3).