Symptoms: in default = "VPN" full-VPN mode external internet was dead even though tunnel-internal ping (10.7.0.1) worked perfectly. The tunnel itself was assembled and AEAD-encrypted (see TEST_CASES.md), but packets sent through it died on the server side. Root cause: server's `[server.nat]` was opt-in. On the production server (187.77.67.17) deployed before v2, the section is absent in /etc/aura/server.toml, so `aura server` never ran the iptables MASQUERADE plan. Packets egressed to the upstream router with src = 10.7.0.10 (RFC1918), which the provider's reverse-path filter dropped — full-VPN clients saw "internet is dead". Tunnel-internal pool addresses worked because they don't need NAT. Fix: * `server.rs`: when `[server.nat]` is absent in server.toml AND we are on Linux, attempt auto-NAT with an auto-detected egress_iface. If detection or the iptables call fails we DON'T bail — we log a loud error and let the server come up so safe-mode clients keep working. * `config.rs`: `ServerNatSection::default()` now defaults `auto = true`. A bare `[server.nat]` header (no `auto =`) now means "yes, enable it" instead of the silent-noop it used to be. * New tests for both bare-header and explicit `auto = false` opt-out paths. * `docs/server_nat_fix.md`: step-by-step instructions for fixing the existing 187.77.67.17 server (binary upgrade vs. manual server.toml patch vs. fully-manual sysctl + iptables). * `docs/deployment.md`: replaces "manual mandatory step" wording with the new auto-NAT story. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
52 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 (для выхода клиентов в интернет)
v3.6 и новее: настройка делается автоматически при старте aura server.
Если в server.toml есть секция [server.nat] с auto = true (так пишет
aura server-init) — сервер сам сделает sysctl net.ipv4.ip_forward=1 и
поставит правило MASQUERADE на нужный интерфейс, а при остановке откатит обе
операции. Если секции вообще нет (legacy-конфиг до v2), сервер всё равно
попытается включить NAT с автодетектом egress-интерфейса (implicit auto-NAT)
и громко скажет это в логе.
Опт-аут — если оператор уже сам управляет фаерволом:
[server.nat]
auto = false
Legacy / ручной путь (v1 или сценарий с отключённым auto-NAT):
# 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 и имя интернет-интерфейса.
Подробный сценарий «существующий сервер до v3.6, full-VPN не работает» разобран
в docs/server_nat_fix.md.
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) идентичны. - ✓ In-band CRL. Сервер сразу после handshake пушит подписанный CA CRL клиенту
через мультиплексированный control-envelope с magic-префиксом
[0xAA,0xAA,0xC0,0x01](не конфликтует с IPv4/v6, которые начинаются с0x4X/0x6X). Клиент проверяет подпись ECDSA-P256 против CA, применяет кAuraCertVerifier, кэширует на диск. Конфиг[pki] crl_push = true/accept_pushed_crl = true(по умолчанию). - ✓ Анти-надзор v2 (NEW в ответ на дрегнет операторов):
- Port-knocking на UDP-транспорте: сервер молчит на скан-зондах, отвечает
только на валидный 16-байтный HMAC-SHA256 «стук» с ±1-минутным окном (ключ
из CA fingerprint). Сканер видит закрытый порт.
[transport.knock] enabled = true. - Cover traffic / chaff: при простое UDP-соединение шлёт
Pingкаждые ~500мс±50% (jitter). Defeats volume/timing-fingerprinting. Под нагрузкой подавляется автоматически.[transport.cover] enabled = true.
- Port-knocking на UDP-транспорте: сервер молчит на скан-зондах, отвечает
только на валидный 16-байтный HMAC-SHA256 «стук» с ±1-минутным окном (ключ
из CA fingerprint). Сканер видит закрытый порт.
- ✓ Автоматизация развёртывания:
aura server-init --domain ... --pki-dir ...— одна команда: CA + серверный cert + готовыйserver.toml(с авто-определением egress-iface).aura provision-client --id <UUID> --out <dir>— выпускает client cert и собирает готовый бандл (ca.crt+client.crt+client.key+client.toml).--idопционален — дефолт UUID v4 (имя пользователя не привязано к сертификату).
- ✓ Минимизация идентификаторов:
[server] no_logs = true/[client] no_logs = true— поляpeer_id,client_ip,source_addr,client_id,local_ip,user,id,assigned_ipредактируются из tracing-вывода через field-level фильтр (события фиксируются, идентификаторы вычищаются).[client] bridges = [...]— список запасных серверов, клиент пробует случайный порядок. Блокировка одного IP не убивает доступ.
- ✓ НОВОЕ: ежедневная ротация масок в 05:00 МСК. Внешний фингерпринт (SNI/UA/Server-
header/UDP padding-профиль) детерминированно меняется раз в сутки. И сервер, и клиент
выводят одинаковый
MaskSetиз общего seed (SHA-256 от CA-сертификата) + UTC-даты через HKDF-SHA256, без сетевой координации. Конфиг:[transport.masks] enabled = true(по умолчанию). Новые подключения берут текущую маску; уже установленные остаются на своих. Палитры: 16 SNI default + 15 SNI russian, 10 User-Agent, 5 Server-headers, 4 padding-профиля; профиль 0 байт-в-байт совместим с v1-паддингом (бэк-совместимость). v3.2 добавляетpalette = "default" | "russian" | "mixed"для случая, когда нужно, чтобы outer SNI выглядел как обращение к российскому сайту (см. сценарий в §7). - ✓ Multi-hop / onion routing v3.1 + v3.2. Цепочка из 2-3 хопов: client →
entry-relay → (опционально middle) → exit. Entry-relay не знает destination, exit-узел не
знает клиентский IP. v3.2: per-hop client cert (CN entry и exit различаются — нельзя
слинковать handshakes по identity), cell padding (constant-size cells устраняют per-packet
size-fingerprinting), CIDR whitelist на relay'е. Конфиг —
[client.circuit]/[server.relay]. См. сценарий §7 для деплоймента «российский entry, иностранный exit». - ✓ Let's Encrypt outer-TLS cert.
[server.outer_cert] cert_path / key_path— outer-TLS слой QUIC и TCP использует настоящий CA-trusted сертификат вместо self-signed Aura cert; внутренний Aura mutual-auth handshake продолжает аутентификацию против Aura CA.
v3.3 — Windows-as-client стал first-class
- ✓ Windows OS-маршруты реализованы.
[tunnel.os_routes] enabled = trueтеперь работает на Windows:route ADD <net> MASK <mask> <gw> METRIC 1для DIRECT-обходов,netsh interface ipv4 add route <prefix> "Aura" <tun_local_ip> store=activeдля VPN-маршрутов через wintun- адаптер. Дефолт-GW автодетектится черезroute print 0. Rollback подменяетADD→DELETEиadd→deleteна обоих путях. Подробности и пошаговый запуск — в §8. - ✓ wintun audit. Найден и устранён баг:
Arc<wintun::Adapter>больше не дропается раньшеSession(поле_adapterвAuraTunдержит адаптер живым на всё время сессии). - ✓ Cross-compile. Весь workspace проверен под
cargo check --target x86_64-pc-windows-gnuбез warnings. - ✓ Bridge-discovery через подписанный CA-манифест (v3.3).
[client.bridges_discovery] enabled = trueплюс файлbridges.signedна диске. Админ собирает манифест командойaura sign-bridges --ca /etc/aura/pki --bridges "203.0.113.10:443,198.51.100.20:443" --ttl-days 7 --out /etc/aura/bridges.signed(подпись ECDSA-P256/SHA-256 ключом CA — той же примитивой что in-band CRL). Клиент верифицирует подпись против[pki] ca_cert, отвергает истёкшие манифесты (expires_at < now), и расширяет статический список из[client] bridges(дубликаты поSocketAddrудаляются; статика остаётся fallback'ом если файл повреждён / отсутствует). Фон-таск перечитывает файл каждыеrefresh_interval_secsсекунд (default 3600), горячее обновление без рестарта клиента. Сам HTTP- пуш через CDN — план v3.4 (опциональная зависимостьreqwestпод feature gate). См.crates/aura-cli/src/bridges.rsи интеграционный тестtests/bridges_discovery.rs.
Остающиеся честные ограничения
- TUN всё ещё требует root / Администратор для создания интерфейса (это OS-уровень). На Linux/macOS privilege drop минимизирует окно работы под root; на Windows аналога нет — клиент работает от Администратора до выхода (warning в логе).
- IPv6 в OS-маршрутах и iptables MASQUERADE не реализован — только IPv4 (план v3.4).
- Windows-as-server не первоклассный.
[server.nat](IP-форвардинг + MASQUERADE) на Windows не реализован; роль сервера / relay лучше держать на Linux/macOS. Windows клиент работает с любым сервером. - Нативного Go-клиента для телефона нет — через sing-box (Option B нативный Go-outbound,
по
protocol.md+ KAT из Rust, см.sing-box.md). Сейчас доступен только десктоп-клиент / process-bridge. Это явно исключённый из v2 пункт. - Bridge-discovery через push без рестарта клиента — частично реализовано в v3.3:
подписанный CA-манифест на диске (
[client.bridges_discovery]) горячо перечитывается фон- таском; админ переподписывает файл и рассылает любым каналом (rsync/ansible/scp). HTTP-fetch напрямую с CDN — план v3.4. Если все статически-перечисленные IP заблокированы и манифест не обновлён до экспирации, восстановление требует доставки новогоbridges.signedчерез out-of-band канал.
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. v3.3 решает это в две
ступени: (а)
[client] bridges = [...]— статический список запасных entry-узлов, клиент пробует их в случайном порядке при отказе primary; (б)[client.bridges_discovery] enabled = true— клиент горячо перечитывает CA-подписанный манифестbridges.signedна диске (см. v3.3 раздел в §6 «Устранено в v2/v3»), так что админ ротирует список без рестарта клиентского процесса — достаточно переподписать файл и доставить новой копией (rsync / ansible / любой out-of-band канал). HTTP-fetch с CDN — план v3.4. - 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).
8. Windows как клиент
Windows-клиент стал first-class в v3.3. Сервер на Windows не поддерживается на уровне
автонастройки сети — [server.nat] (IP-форвардинг + MASQUERADE) реализован только для
Linux/macOS. Эта секция — про клиент.
8.1. Требования
- Windows 10 / 11 (или Server 2019+) с правами Администратора для процесса
aura.exe— поднятие wintun-адаптера и программирование таблицы маршрутов требуют привилегий. - wintun.dll рядом с
aura.exe. Скачать с официального сайта https://www.wintun.net/ (драйвер от автора WireGuard); распаковатьwintun/bin/amd64/wintun.dllв каталогaura.exe.
8.2. Сборка / получение бинаря
Если у вас есть Rust toolchain на Windows — cargo build --release соберёт target\release\aura.exe.
С macOS / Linux можно собрать кросс-компиляцией (нужен mingw-w64):
rustup target add x86_64-pc-windows-gnu
# (на macOS) brew install mingw-w64
cargo build --release --target x86_64-pc-windows-gnu
# -> target/x86_64-pc-windows-gnu/release/aura.exe
8.3. PKI и провижининг
Команды aura.exe pki ... и aura.exe provision-client ... работают идентично Unix-версии
(см. §2.2). Бандл для клиента — те же три PEM-файла (ca.crt, client.crt, client.key)
плюс client.toml. PowerShell-форма:
.\aura.exe pki init --ca-name "Aura Root CA" --out C:\ProgramData\Aura\pki
.\aura.exe pki issue-server --domain vpn.example.com --out C:\ProgramData\Aura\pki\server `
--ca C:\ProgramData\Aura\pki
.\aura.exe provision-client --id laptop-1 --out C:\Users\me\.aura
8.4. client.toml на Windows
Раскладка идентична §4.1. Имя TUN — это отображаемое имя wintun-адаптера: указанное в
tun_name имя становится Display Name адаптера в Device Manager (а также используется в
командах netsh interface ipv4 add route ... "Aura" — см. §8.5).
[client]
name = "laptop"
server_addr = "203.0.113.10:443"
sni = "vpn.example.com"
# run_as на Windows — no-op (нет аналога setresuid; warning в логе).
[pki]
ca_cert = "C:\\Users\\me\\.aura\\ca.crt"
cert = "C:\\Users\\me\\.aura\\client.crt"
key = "C:\\Users\\me\\.aura\\client.key"
[tunnel]
tun_name = "Aura" # имя wintun-адаптера; то же имя используется в netsh-командах ниже
local_ip = "10.7.0.2"
prefix = 24
mtu = 1420
[tunnel.split]
default = "VPN"
[[tunnel.split.direct]]
cidr = "192.168.0.0/16"
# v3.3: OS-уровень kill-switch теперь работает на Windows.
[tunnel.os_routes]
enabled = true
# Опционально: pin gateway + interface IP (читается `route print 0` если не задано).
# gateway = "192.168.1.1"
# egress_iface = "192.168.1.42"
[transport]
order = ["udp", "tcp", "quic"]
udp_port = 443
tcp_port = 443
quic_port = 444
8.5. Что делает [tunnel.os_routes] на Windows
На Linux/macOS клиент программирует системную таблицу маршрутов через ip / route. На
Windows — через route ADD (для DIRECT-обходов через исходный default-GW) и netsh interface ipv4 add route (для VPN-маршрутов через wintun-адаптер).
Auto-detect default GW: клиент выполняет route print 0 и парсит row 0.0.0.0 0.0.0.0 <gw> <interface_ip> <metric> из IPv4 Active Routes. Если автодетект не сработал (например,
у машины несколько NIC и нет default'а в IPv4-таблице) — задайте gateway и egress_iface
явно в [tunnel.os_routes]. На Windows egress_iface — это IP upstream-интерфейса
(не имя), как в колонке Interface в route print.
Что реально выполняется (с пулом DIRECT 192.168.0.0/16 и default = VPN):
netsh interface ipv4 add route 0.0.0.0/0 "Aura" 10.7.0.2 store=active
route ADD 192.168.0.0 MASK 255.255.0.0 192.168.1.1 METRIC 1
Что выполняется при выходе клиента (Drop порядка LIFO):
route DELETE 192.168.0.0 MASK 255.255.0.0
netsh interface ipv4 delete route 0.0.0.0/0 "Aura"
store=active указывает Windows не сохранять маршрут в персистентном store — он привязан к
TUN, который исчезает на выходе клиента. Параметр METRIC 1 обеспечивает приоритет
DIRECT-обхода над любыми существующими маршрутами с большей метрикой.
8.6. Запуск
PowerShell как Администратор:
cd C:\Aura
.\aura.exe client --config .\client.toml
В логе при успехе:
INFO connected and authenticated to server peer=Some("vpn.example.com") mode=udp
INFO OS-level split-tunnel routes installed (DIRECT traffic now bypasses the TUN)
INFO running: netsh interface ipv4 add route 0.0.0.0/0 "Aura" 10.7.0.2 store=active
INFO running: route ADD 192.168.0.0 MASK 255.255.0.0 192.168.1.1 METRIC 1
Прервать через Ctrl+C — выводящийся guard корректно вызывает route DELETE / netsh ... delete route и затем закрывает wintun-сессию + адаптер (см. §8.7).
8.7. Cleanup на Windows (что происходит при остановке клиента)
Порядок dropping:
- OsRouteGuard::drop — выполняет rollback-команды в LIFO-порядке (
route DELETE ..., затемnetsh ... delete route ...). Ошибки логируются warn-ом, дальнейший rollback продолжается — один сбойный шаг не остановит зачистку остальных маршрутов. - wintun::Session::drop —
WintunEndSessionзавершает сессию (закрывает ring buffer). - wintun::Adapter::drop —
WintunCloseAdapterснимает адаптер с системы. Drop порядка полей вAuraTunгарантирует, что Session завершается до Adapter (полеinnerобъявлено раньше_adapter).
Если процесс упал без graceful shutdown (kill -9 / BSOD): wintun-адаптер останется
зарегистрированным в системе, и при следующем запуске Adapter::create найдёт его по имени и
переиспользует. Орфанных системных маршрутов в персистентном store не будет — все наши
маршруты идут через store=active, которые система очищает на reboot.
8.8. Известные ограничения Windows-клиента
run_asна Windows — no-op. Аналогаsetresuidдля безпрепятственного drop'а к service-account во время работы нет; рекомендация — запуститьaura.exeкак Windows Service от выделенной учётной записи (см. документациюsc.exe create), либо просто из PowerShell-сессии Администратора.[server.nat]на Windows не реализован — Windows-as-server не первоклассный сценарий. Используйте Linux/macOS для роли сервера / relay.- IPv6 routes программируются через
netsh interface ipv6 add routeдля VPN, но IPv6 DIRECT-обходы попадают в тот жеnetsh ipv6путь (а не в IPv4-onlyroute ADD). Для чистой IPv4-only установки это не имеет значения. - Mixed-mode (часть транспортов в одну сеть, часть в другую) на Windows не тестировался
глубоко —
netsh ... store=activeмаршруты могут конфликтовать с существующими VPN- клиентами (WireGuard, OpenVPN) если те уже захватили default-route. Отключите конкурирующие VPN перед запуском aura-клиента.