360 lines
19 KiB
Markdown
360 lines
19 KiB
Markdown
# 📝 Проектирование Hidden Services
|
||
|
||
**Версия:** 1.0
|
||
**Дата:** 23 ноября 2025
|
||
**Статус:** ✅ Завершено
|
||
**Автор:** Manus AI
|
||
|
||
---
|
||
|
||
## 1. Введение
|
||
|
||
Этот документ описывает архитектуру и протоколы для реализации **Hidden Services** (скрытых сервисов) в сети Phantom Protocol. Hidden Services позволяют пользователям публиковать и получать доступ к сервисам (например, веб-сайтам), не раскрывая их реальное местоположение (IP-адрес).
|
||
|
||
**Цели:**
|
||
- Обеспечить анонимность как для поставщика сервиса, так и для клиента.
|
||
- Использовать существующую Kademlia DHT для обнаружения сервисов.
|
||
- Минимизировать задержки при установке соединения.
|
||
- Обеспечить устойчивость к атакам на обнаружение и доступность.
|
||
|
||
---
|
||
|
||
## 2. Архитектура (Задача 1.1.2 ✅)
|
||
|
||
Архитектура Hidden Services состоит из четырех основных компонентов, которые взаимодействуют для обеспечения анонимности:
|
||
|
||
1. **Скрытый Сервис (Hidden Service):** Это серверное приложение, которое прослушивает трафик только внутри сети Phantom. Оно никогда не раскрывает свой IP-адрес и устанавливает исходящие анонимные туннели к нескольким **точкам входа (Introduction Points)**, чтобы анонсировать свое существование.
|
||
|
||
2. **Клиент (Client):** Это приложение пользователя, которое инициирует соединение со скрытым сервисом. Клиент находит информацию о сервисе в DHT и анонимно договаривается о соединении через **точку рандеву (Rendezvous Point)**.
|
||
|
||
3. **Точка Рандеву (Rendezvous Point):** Это любой узел в сети Phantom, выбранный клиентом для "встречи" со скрытым сервисом. Его основная задача - соединить два анонимных туннеля (от клиента и от сервиса), не зная ничего о конечных участниках.
|
||
|
||
4. **Дескриптор Сервиса (Service Descriptor):** Это небольшая структура данных, подписанная скрытым сервисом и опубликованная в Kademlia DHT. Она содержит публичный ключ сервиса и адреса его точек входа, позволяя клиентам инициировать соединение.
|
||
|
||
### Диаграмма Архитектуры
|
||
|
||
```mermaid
|
||
graph TD
|
||
subgraph "Клиент"
|
||
C[Клиент]
|
||
end
|
||
|
||
subgraph "Скрытый Сервис"
|
||
HS[Сервис]
|
||
end
|
||
|
||
subgraph "Phantom Сеть"
|
||
DHT[Kademlia DHT]
|
||
RP[Точка Рандеву]
|
||
IP1[Точка входа 1]
|
||
IP2[Точка входа 2]
|
||
end
|
||
|
||
C -- "1. Запрос дескриптора по .phantom адресу" --> DHT
|
||
DHT -- "2. Возврат дескриптора" --> C
|
||
HS -- "3. Периодическая публикация дескриптора" --> DHT
|
||
HS -- "4. Создание туннеля к точке входа" --> IP1
|
||
C -- "5. Создание туннеля к точке рандеву" --> RP
|
||
RP -- "6. Сообщение о рандеву (Introduce1)" --> IP1
|
||
IP1 -- "7. Передача сообщения сервису" --> HS
|
||
HS -- "8. Создание туннеля к точке рандеву" --> RP
|
||
C <-. "9. Установлено анонимное соединение" .-> HS
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Формат .phantom Адреса (Задача 1.1.3 ✅)
|
||
|
||
`.phantom` адрес - это человекочитаемый и безопасный идентификатор скрытого сервиса. Он является производным от его постоянного публичного ключа.
|
||
|
||
**Формат:** `[52-символьный Base32-хэш].phantom`
|
||
|
||
**Пример:** `v4vyh26w7qf5g3z4v3h2g5g3z4v3h2g5v4vyh26w7qf5g3z4v3h2g.phantom`
|
||
|
||
### Процесс Генерации Адреса
|
||
|
||
1. **Генерация ключевой пары:** Сервис генерирует долгосрочную ключевую пару для идентификации.
|
||
- `(public_key, private_key) = Ed25519_generate()`
|
||
|
||
2. **Хэширование публичного ключа:** Для получения уникального идентификатора и сокращения длины используется хэширование.
|
||
- `hash = BLAKE2b-256(public_key)` (BLAKE2b выбран за скорость и безопасность)
|
||
|
||
3. **Добавление контрольной суммы:** Для предотвращения опечаток добавляется контрольная сумма.
|
||
- `checksum = SHA256(SHA256(public_key))[0:2]` (первые 2 байта двойного хэша)
|
||
- `payload = hash + checksum`
|
||
|
||
4. **Кодирование в Base32:** `payload` кодируется в Base32 (RFC 4648) для удобства использования в DNS и URL.
|
||
- `base32_payload = Base32_encode(payload)`
|
||
|
||
5. **Формирование адреса:**
|
||
- `address = base32_payload + ".phantom"`
|
||
|
||
---
|
||
|
||
## 4. Процессы Регистрации и Подключения
|
||
|
||
### Процесс Регистрации Сервиса (Задача 1.1.5 ✅)
|
||
|
||
1. **Инициализация:** Сервис генерирует свою ключевую пару Ed25519.
|
||
2. **Выбор Точек Входа:** Сервис выбирает 3-5 надежных и хорошо подключенных узлов в сети в качестве своих **точек входа (Introduction Points)**.
|
||
3. **Построение Туннелей:** Сервис строит анонимные туннели к каждой из своих точек входа и поддерживает их в активном состоянии.
|
||
4. **Создание Дескриптора:** Сервис создает **дескриптор**, содержащий его публичный ключ и список адресов точек входа.
|
||
5. **Подпись и Публикация:** Сервис подписывает дескриптор своим приватным ключом и публикует его в DHT. Ключом для хранения в DHT является хэш публичного ключа сервиса.
|
||
6. **Перепубликация:** Сервис периодически (например, каждые 60 минут) перепубликовывает свой дескриптор, чтобы он не истек в DHT.
|
||
|
||
### Процесс Подключения Клиента (Задача 1.1.6 ✅)
|
||
|
||
1. **Получение Адреса:** Клиент получает `.phantom` адрес сервиса (например, через веб-сайт, мессенджер).
|
||
2. **Запрос Дескриптора:** Клиент декодирует адрес, извлекает хэш и запрашивает у DHT дескриптор по этому хэшу.
|
||
3. **Проверка Дескриптора:** Клиент получает дескриптор и проверяет его подпись, используя публичный ключ из самого дескриптора.
|
||
4. **Выбор Точки Рандеву:** Клиент выбирает случайный узел в сети в качестве **точки рандеву (Rendezvous Point)**.
|
||
5. **Туннель к Рандеву:** Клиент строит анонимный туннель к точке рандеву и отправляет ей **одноразовый секрет (cookie)**, сгенерированный случайным образом.
|
||
6. **Отправка Сообщения:** Клиент выбирает одну из точек входа из дескриптора и анонимно отправляет ей **сообщение о рандеву (introduce message)**. Это сообщение зашифровано для публичного ключа сервиса и содержит адрес точки рандеву и тот же cookie.
|
||
7. **Пересылка Сервису:** Точка входа пересылает сообщение сервису по ранее установленному туннелю.
|
||
8. **Туннель от Сервиса:** Сервис расшифровывает сообщение, строит свой анонимный туннель к указанной точке рандеву и отправляет ей тот же cookie.
|
||
9. **Соединение:** Точка рандеву, получив одинаковые cookie от клиента и сервиса, "соединяет" их туннели. Теперь трафик может течь между клиентом и сервисом анонимно в обе стороны.
|
||
|
||
---
|
||
|
||
## 5. Протокол Рандеву (Задача 1.1.4 ✅)
|
||
|
||
Протокол рандеву - это ядро установки соединения. Он состоит из двух ключевых сообщений.
|
||
|
||
### Сообщение о Рандеву (Introduce1)
|
||
|
||
Отправляется от клиента к точке входа, зашифровано для публичного ключа сервиса.
|
||
|
||
**Содержимое (Protobuf):**
|
||
|
||
```protobuf
|
||
// Файл: protos/hidden_service.proto
|
||
|
||
message Introduce1 {
|
||
// Адрес точки рандеву (фантомный адрес)
|
||
bytes rendezvous_address = 1;
|
||
|
||
// Одноразовый секрет (cookie, 32 байта), сгенерированный клиентом
|
||
bytes rendezvous_cookie = 2;
|
||
|
||
// Публичный ключ клиента для DH-обмена (X25519)
|
||
bytes client_dh_public_key = 3;
|
||
}
|
||
```
|
||
|
||
### Сообщение о Рандеву (Rendezvous1)
|
||
|
||
Отправляется от скрытого сервиса к точке рандеву.
|
||
|
||
**Содержимое (Protobuf):**
|
||
|
||
```protobuf
|
||
// Файл: protos/hidden_service.proto
|
||
|
||
message Rendezvous1 {
|
||
// Тот же одноразовый секрет, что и в Introduce1
|
||
bytes rendezvous_cookie = 1;
|
||
|
||
// Публичный ключ сервиса для DH-обмена (X25519)
|
||
bytes service_dh_public_key = 2;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Структуры Данных (Задача 1.1.7 ✅)
|
||
|
||
### Дескриптор Сервиса (Protobuf)
|
||
|
||
```protobuf
|
||
// Файл: protos/hidden_service.proto
|
||
|
||
syntax = "proto3";
|
||
|
||
package phantom;
|
||
|
||
message ServiceDescriptor {
|
||
// Публичный ключ сервиса (Ed25519, 32 байта)
|
||
bytes public_key = 1;
|
||
|
||
// Список точек входа
|
||
repeated IntroductionPoint introduction_points = 2;
|
||
|
||
// Версия протокола (например, 1)
|
||
uint32 protocol_version = 3;
|
||
|
||
// Временная метка создания (Unix timestamp)
|
||
uint64 timestamp = 4;
|
||
|
||
// Подпись (public_key, introduction_points, protocol_version, timestamp)
|
||
bytes signature = 5;
|
||
}
|
||
|
||
message IntroductionPoint {
|
||
// Адрес узла (фантомный адрес)
|
||
bytes address = 1;
|
||
|
||
// Публичный ключ для шифрования сообщений от клиента (X25519)
|
||
bytes encryption_key = 2;
|
||
}
|
||
```
|
||
|
||
### `phantom_hidden_service.h`
|
||
|
||
```c
|
||
#ifndef PHANTOM_HIDDEN_SERVICE_H
|
||
#define PHANTOM_HIDDEN_SERVICE_H
|
||
|
||
#include <openssl/evp.h>
|
||
#include <stdint.h>
|
||
#include "kademlia.h"
|
||
|
||
#define PHANTOM_HS_ADDRESS_LEN 52
|
||
#define PHANTOM_HS_COOKIE_LEN 32
|
||
#define PHANTOM_HS_MAX_INTRO_POINTS 5
|
||
|
||
// Структура для хранения информации о точке входа
|
||
typedef struct {
|
||
phantom_address_t address; // Фантомный адрес точки входа
|
||
EVP_PKEY *encryption_key; // Ключ шифрования X25519
|
||
// ... информация о туннеле
|
||
} phantom_intro_point_t;
|
||
|
||
// Структура для хранения информации о скрытом сервисе
|
||
typedef struct {
|
||
// Постоянные ключи сервиса
|
||
EVP_PKEY *identity_key; // Ed25519
|
||
|
||
// .phantom адрес
|
||
char address[PHANTOM_HS_ADDRESS_LEN + 9]; // + .phantom + null
|
||
|
||
// Список точек входа
|
||
phantom_intro_point_t intro_points[PHANTOM_HS_MAX_INTRO_POINTS];
|
||
int num_intro_points;
|
||
|
||
// ... информация о потоках, состоянии и т.д.
|
||
|
||
} phantom_hidden_service_t;
|
||
|
||
// Функции
|
||
|
||
/**
|
||
* @brief Создает и инициализирует новый скрытый сервис
|
||
* @return Указатель на структуру сервиса или NULL при ошибке
|
||
*/
|
||
phantom_hidden_service_t* phantom_hs_create();
|
||
|
||
/**
|
||
* @brief Публикует дескриптор сервиса в DHT
|
||
* @param service Указатель на структуру сервиса
|
||
* @param dht Указатель на экземпляр Kademlia DHT
|
||
* @return 0 при успехе, -1 при ошибке
|
||
*/
|
||
int phantom_hs_publish(phantom_hidden_service_t *service, kademlia_dht_t *dht);
|
||
|
||
/**
|
||
* @brief Запускает прослушивание входящих соединений от точек входа
|
||
* @param service Указатель на структуру сервиса
|
||
* @return 0 при успехе, -1 при ошибке
|
||
*/
|
||
int phantom_hs_listen(phantom_hidden_service_t *service);
|
||
|
||
#endif // PHANTOM_HIDDEN_SERVICE_H
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Диаграммы Последовательности (Задача 1.1.8 ✅)
|
||
|
||
### Публикация Сервиса
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant HS as Скрытый Сервис
|
||
participant IP as Точка Входа
|
||
participant DHT as Kademlia DHT
|
||
|
||
HS->>HS: 1. Генерация identity_key (Ed25519)
|
||
HS->>IP: 2. Установка анонимного туннеля
|
||
HS->>HS: 3. Создание дескриптора (с адресом IP)
|
||
HS->>HS: 4. Подпись дескриптора своим identity_key
|
||
HS->>DHT: 5. Публикация дескриптора (PUT)
|
||
Note right of DHT: Хранится 1 час
|
||
loop Каждые 60 минут
|
||
HS->>DHT: Перепубликация дескриптора
|
||
end
|
||
```
|
||
|
||
### Подключение Клиента
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as Клиент
|
||
participant DHT as Kademlia DHT
|
||
participant IP as Точка Входа
|
||
participant RP as Точка Рандеву
|
||
participant HS as Скрытый Сервис
|
||
|
||
C->>DHT: 1. Запрос дескриптора (GET)
|
||
DHT-->>C: 2. Возврат дескриптора
|
||
C->>C: 3. Проверка подписи дескриптора
|
||
C->>RP: 4. Установка туннеля и отправка cookie
|
||
C->>IP: 5. Отправка Introduce1 (зашифровано для HS)
|
||
IP->>HS: 6. Пересылка зашифрованного сообщения
|
||
HS->>HS: 7. Расшифровка, проверка cookie
|
||
HS->>RP: 8. Установка туннеля и отправка того же cookie
|
||
RP->>RP: 9. Сравнение cookie от C и HS
|
||
Note over RP: Cookie совпали, соединяем туннели
|
||
C-->>HS: 10. Обмен данными по анонимному туннелю
|
||
```
|
||
|
||
---
|
||
|
||
## 8. План Реализации
|
||
|
||
**Задача 1.1: Проектирование (2 недели)**
|
||
- [x] Создать этот документ
|
||
- [x] Описать архитектуру
|
||
- [x] Определить формат адреса
|
||
- [x] Спроектировать протокол рандеву
|
||
- [x] Описать процесс регистрации сервиса
|
||
- [x] Описать процесс подключения клиента
|
||
- [x] Определить структуры данных
|
||
- [x] Создать диаграммы последовательности
|
||
|
||
**Задача 1.2: Реализация `phantom_hidden_service.c` (6-8 недель)**
|
||
- [ ] Реализовать `phantom_hs_create()`
|
||
- [ ] Реализовать генерацию адреса
|
||
- [ ] Реализовать создание дескриптора
|
||
- [ ] Реализовать `phantom_hs_publish()`
|
||
- [ ] Реализовать `phantom_hs_listen()`
|
||
|
||
**Задача 1.3: Реализация клиентской части (4-6 недель)**
|
||
- [ ] Реализовать `phantom_client_connect_hs()`
|
||
- [ ] Реализовать запрос дескриптора
|
||
- [ ] Реализовать протокол рандеву
|
||
|
||
**Задача 1.4: Тестирование (2 недели)**
|
||
- [ ] Написать unit-тесты
|
||
- [ ] Написать интеграционные тесты
|
||
- [ ] Протестировать реальный сценарий (веб-сервер)
|
||
|
||
---
|
||
|
||
## 9. Открытые Вопросы
|
||
|
||
1. **Защита от DoS-атак на точки входа:** Как предотвратить флуд сообщениями о рандеву?
|
||
- *Решение:* Требовать небольшой proof-of-work (например, Hashcash) от клиента при отправке сообщения `Introduce1`. Это будет реализовано в версии 2 протокола.
|
||
|
||
2. **Ротация точек входа:** Как часто сервис должен менять свои точки входа для повышения анонимности?
|
||
- *Решение:* Сервис должен выбирать новые точки входа каждые 24 часа и публиковать обновленный дескриптор.
|
||
|
||
3. **Хранение дескрипторов в DHT:** Как обеспечить постоянное наличие дескрипторов в DHT?
|
||
- *Решение:* Сервис должен перепубликовывать свой дескриптор каждые 60 минут. Если сервис отключается, дескриптор автоматически истечет.
|
||
|
||
4. **Балансировка нагрузки:** Как распределить нагрузку между несколькими точками входа?
|
||
- *Решение:* Клиент должен выбирать точку входа из дескриптора случайным образом. Это обеспечивает простую и эффективную балансировку.
|
||
|
||
---
|
||
|
||
**Конец документа**
|