Files
AuraVPN/docs/pki.md
T
xah30 083c441e4c docs: rewrite all documentation in Russian + add deployment guide
- docs/protocol.md, pki.md, split-tunnel.md, sing-box.md переведены на русский
  и сверены с текущим кодом (транспорт v2: свой UDP + TCP/443 + QUIC fallback,
  handover; PKI; split-tunnel; sing-box-план).
- docs/deployment.md (новый, 369 строк): пошаговое руководство для удалённого
  сервера — сборка, PKI init/issue-server/issue-client (проверено бинарём),
  server.toml/client.toml на основе фактических config/*.example, firewall +
  NAT/IP-форвардинг, sudo-запуск, бандл клиента (ca.crt + client.crt + client.key
  + server addr/sni), на каком транспорте идёт трафик, ограничения v1.
- README.md (новый, корень): краткий обзор + таблица крейтов + быстрый старт.

Всё на русском (проза); команды/идентификаторы/конфиги — как есть.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 10:42:08 +03:00

14 KiB
Raw Blame History

PKI Aura

Aura использует небольшую самодостаточную X.509-PKI для взаимной аутентификации во внутреннем рукопожатии. Один самоподписанный CA Aura выдаёт один сертификат для сервера и по одному сертификату для каждого клиента. Во время рукопожатия клиент проверяет сертификат сервера, а сервер — сертификат клиента, и в обе стороны проверка идёт против этого CA.

PKI реализована в крейте aura-pki (ca.rs, cert.rs, store.rs) и доступна в командной строке как aura pki ... (crates/aura-cli/src/pki.rs, crates/aura-cli/src/main.rs).

Внешний QUIC/TLS-слой эту PKI не использует — он принимает любой сертификат (см. protocol.md, раздел про слой мимикрии). Всё доверие сертификатам сосредоточено во внутреннем рукопожатии Aura.


Модель доверия

            Aura CA (self-signed)
            CN = <ca_name>, isCA, keyCertSign/crlSign
                     |
        +------------+------------+
        |                         |
   server leaf               client leaf(s)
   CN = <domain>             CN = <client_id>
   SAN: DNS:<domain>         (нет SAN)
   EKU: serverAuth           EKU: clientAuth
  • CA самоподписан, имеет BasicConstraints: CA (unconstrained) и keyUsage: keyCertSign + crlSign + digitalSignature. Срок действия по умолчанию — 3650 дней.
  • Server leaf несёт CN = <domain>, DNS:<domain> SAN и extendedKeyUsage = serverAuth. Именно DNS-SAN сравнивается клиентом с ожидаемым server_name.
  • Client leaf несёт CN = <client_id> и extendedKeyUsage = clientAuth. Этот CN — та идентичность, которую увидит сервер и запишет как peer_id сессии.
  • keyUsage для листовых сертификатов: digitalSignature + keyEncipherment. Срок действия по умолчанию — 365 дней.
  • У всех выпускаемых сертификатов (и у CA, и у листовых) not_before смещён назад на 5 минут, чтобы выдерживать небольшой расхождение часов.

Алгоритмы

Все ключи — ECDSA P-256 / SHA-256 (KeyPair::generate rcgen по умолчанию). Приватные ключи сохраняются в PKCS#8 PEM. Проверка цепочки (cert.rs) принимает ECDSA P-256/SHA-256 (обязательно), а также ECDSA P-384/SHA-384 и Ed25519, — так что развёртывание сможет позже сменить тип ключа без изменения кода.


Раскладка файлов

CLI хранит файлы в обычных директориях. Стандартные имена (crates/aura-cli/src/pki.rs):

Файл Константа Содержимое
ca.crt CA_CERT Сертификат CA (PEM)
ca.key CA_KEY Приватный ключ CA (PKCS#8 PEM) — секрет
server.crt Листовой сертификат сервера (PEM)
server.key Приватный ключ сервера (PEM) — секрет
client.crt Листовой сертификат клиента (PEM)
client.key Приватный ключ клиента (PEM) — секрет
revoked.crl CRL_FILE Список отозванных идентификаторов (по одному в строке)

Команды issue-server и issue-client загружают CA из ca.crt + ca.key в директории CA и записывают server.{crt,key} / client.{crt,key} в выходную директорию. Пути, начинающиеся с ~, раскрываются в домашнюю директорию (из $HOME, либо $USERPROFILE на Windows).

Эти имена напрямую соответствуют секции [pki] в server.toml / client.toml (ca_cert, cert, key).


Команды aura pki

aura pki init         --ca-name <CN>  --out <DIR>
aura pki issue-server --domain <DNS>  --out <DIR> [--ca <CA_DIR>]
aura pki issue-client --id <CLIENT>   --out <DIR> [--ca <CA_DIR>]
aura pki revoke       --id <ID>                   [--crl <PATH>]
aura pki list                                     [--crl <PATH>]

Для issue-server / issue-client параметр --ca по умолчанию равен значению --out (так что CA и выпущенный лист могут лежать в одной директории). Для revoke / list параметр --crl по умолчанию равен ./revoked.crl.

init — создать CA

Генерирует свежий самоподписанный CA и записывает ca.crt + ca.key в --out (директория создаётся при необходимости).

aura pki init --ca-name "Aura Root CA" --out ~/.aura
# CA generated:
#   cert: ~/.aura/ca.crt
#   key:  ~/.aura/ca.key

issue-server — выпустить сертификат сервера

Выпускает листовой сертификат для DNS-имени, подписанный CA, с SAN DNS:<domain> и EKU serverAuth.

aura pki issue-server --domain vpn.example.com --out ~/.aura --ca ~/.aura
# server certificate issued for 'vpn.example.com':
#   cert: ~/.aura/server.crt
#   key:  ~/.aura/server.key

Значение --domain должно совпадать с тем именем, которое клиент ожидает в рукопожатии. В поставляемой конфигурации клиента это имя берётся из [client] sni, поэтому SNI камуфляжа и проверяемый SAN сервера — это одно и то же значение.

issue-client — выпустить сертификат клиента

Выпускает листовой сертификат с CN = <id> и EKU clientAuth. Это <id> станет проверенным peer_id, который увидит сервер.

aura pki issue-client --id laptop --out ~/.aura --ca ~/.aura
# client certificate issued for 'laptop':
#   cert: ~/.aura/client.crt
#   key:  ~/.aura/client.key

revoke — добавить в список отзыва

Добавляет идентификатор — это либо client id / Common Name, либо серийный номер сертификата (строчные шестнадцатеричные цифры без разделителей) — в CRL-файл, создавая его (и родительские директории) при отсутствии.

aura pki revoke --id laptop --crl ~/.aura/revoked.crl
# revoked 'laptop' (CRL: ~/.aura/revoked.crl)

list — показать отозванные идентификаторы

Печатает идентификаторы из CRL-файла (пусто, если файла нет).

aura pki list --crl ~/.aura/revoked.crl
# revoked identifiers (CRL: ~/.aura/revoked.crl):
#   laptop

Полный пример

# 1. Создать CA.
aura pki init --ca-name "Aura Root CA" --out ~/.aura

# 2. Выпустить серверный сертификат для публичного DNS-имени.
aura pki issue-server --domain vpn.example.com --out ~/.aura

# 3. Выпустить клиентский сертификат — по одному на устройство.
aura pki issue-client --id laptop --out ~/.aura

# 4. (позже) Отозвать скомпрометированный клиент.
aura pki revoke --id laptop

Проверка

Проверку выполняет AuraCertVerifier (crates/aura-pki/src/cert.rs), собранный из PEM-сертификата CA. Внутри он использует rustls-webpki для валидации листового сертификата пира против CA как trust anchor. Рукопожатие Aura вызывает его с обеих сторон (см. protocol.md).

Сертификат сервера (verify_server_cert), запускает клиент:

  1. webpki-валидация цепочки против CA с key usage serverAuth плюс проверка срока действия (времени).
  2. Лист должен быть валиден для запрошенного server_name (совпадение DNS-SAN); расхождение — NameMismatch.
  3. Проверка по CRL (см. ниже).

Сертификат клиента (verify_client_cert), запускает сервер:

  1. webpki-валидация цепочки против CA с key usage clientAuth плюс проверка срока действия.
  2. client id извлекается как первый Common Name из subject листа (отсутствие CN — MissingIdentity).
  3. Проверка по CRL.
  4. Возвращает client id, который рукопожатие фиксирует как peer_id сессии.

Листовой сертификат передаётся inline в рукопожатии (DER, без промежуточной цепочки); CA — это единственный trust anchor. Владение приватным ключом листового сертификата доказывается отдельно подписью рукопожатия по транскрипту (см. protocol.md).

Ошибки сообщаются как PkiError: CertParse, EmptyChain, TrustAnchor, Verification, NameMismatch, MissingIdentity, Revoked.


Отзыв (CRL)

Механизм отзыва в Aura v1 намеренно минимальный (crates/aura-pki/src/store.rs). CrlStore — это множество строк-идентификаторов отозванных сертификатов, где идентификатор — это либо:

  • серийный номер сертификата (строчные hex-цифры без разделителей), либо
  • client id / Common Name.

При проверке, если CRL непуст, листовой сертификат отвергается (Revoked), когда либо его серийный номер, либо его Common Name присутствует в множестве. Пустой CRL пропускает проверку полностью.

Формат на диске — один идентификатор в строке; пустые строки и комментарии # игнорируются при загрузке. Файл управляется командами aura pki revoke / aura pki list.

Ограничение v1: это плоское множество разрешения/запрета, а не подписанный X.509 CRL. Нет подписи CRL, нет nextUpdate и нет автоматического распространения — файл нужно доставить на проверяющую сторону вне протокола. Верификатор передаёт None в собственные крючки отзыва webpki и полагается исключительно на это множество.


Замечания по безопасности

  • Защищайте приватные ключи. ca.key — корень всего доверия; владея им, можно выпускать любые валидные серверные/клиентские сертификаты. server.key / client.key должны оставаться на своих хостах. CLI пишет их с дефолтными правами файловой системы — ограничивайте доступ средствами ОС.
  • CA самоподписан и не ограничен (BasicConstraints: CA unconstrained). Это единственный trust anchor; в v1 нет уровня промежуточных CA.
  • Идентичность сервера связана с именем. Клиент принимает только тот серверный лист, чей DNS-SAN совпадает с ожидаемым именем, поэтому другой валидный лист от того же CA не будет принят для чужого хоста.
  • Отзыв — best-effort (см. выше): планируйте раздачу CRL-файла и поддерживайте его в актуальном состоянии на каждом сервере, который проверяет клиентов.
  • Срок жизни листов — 365 дней; планируйте перевыпуск. Автоматической ротации в v1 нет.