xah30 15c7da12fe fix(server): v3.6 — implicit auto-NAT on Linux (root cause of full-VPN dying)
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>
2026-06-01 14:11:24 +03:00

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-устройства. Клиент:

  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-сокет позволяет менять правила и смотреть статус без перезапуска:

# Добавить 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-сокет несёт обе фазы, различимые по первому байту:
    • 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.


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:

  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):

[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-узла (например, при блокировке текущего) обновите три места:

  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.

S
Description
No description provided
Readme 1.5 MiB
Languages
Rust 92.3%
Go 6.5%
TypeScript 0.8%
CSS 0.4%