Быстрое введение в сеть Hidden Lake
Примерно год назад я писал статью в которой приводил процесс поднятия узла анонимной сети Hidden Lake. По моим ощущениям статья получилась неудачной, т.к. в ней уделялось слишком много внимания деталям, из-за чего возникало сопутствующее представление о сложности подобного процесса. С тех пор прошло уже 11 месяцев, код сети Hidden Lake постепенно редактировался, некоторые схемы запуска изменялись, добавлялись новые возможности. Вслед за этим я решил выпустить более новую статью с целью удаления или переноса излишков информации в отдельные секции спойлеров или ссылки, а также с целью актуализации текущего процесса запуска и функционирования сети. В результате, статья должна получиться простой, минималистичной и понятной, буквально на пять минут чтения.
Немного о Hidden Lake
Отличие анонимной сети Hidden Lake от других представителей данной области, по типу Tor, I2P, Mixminion, Crowds и т.п. заключается в теоретически доказуемой защите от действий глобально наблюдателя. Иными словами, даже если сеть будет небольшой, территориально ограниченной и полностью прослушиваемой, то наблюдателю будет всё также невозможно выявить хоть какие-либо связи между её участниками. Это достигается за счёт QB-задачи (задачи на базе очередей), о преимуществах и ограничений которой более подробно можно почитать в статье тут. За счёт такой особенности, сеть Hidden Lake может успешно функционировать даже внутри централизованного сервера, сохраняя при этом тот же уровень анонимности. Об этом более подробно можно почитать здесь.
Запускаем свой сервис
Узел в сети Hidden Lake поднять достаточно просто — достаточно лишь скачать приложение HLS и запустить его. Но в таком случае пользы от этого будет мало по двум причинам: 1) узел поднимется локально и не будет никак связан со внешней сетью, 2) будут отсутствовать прикладные приложения и, как следствие, применения. Поэтому, чтобы рассмотреть и понять процесс интеграции узла с сетью Hidden Lake от А до Я, корректнее всего будет написать собственный небольшой сервис. В нашем случае это будет echo-сервис.
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
req, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
fmt.Fprintf(w, "echo(%s)", string(req))
})
log.Println("service is listening...")
http.ListenAndServe("127.0.0.1:8080", nil)
}
В таком концепте нам потребуется два узла: один будет предоставлять услугу сервиса, другой будет представлен клиентом данной услуги. Для этого скачиваем приложение HLS, устанавливаем права на исполнение и копируем HLS также в директорию клиента.
$ wget https://github.com/number571/go-peer/releases/latest/download/hls_amd64_linux
$ mv hls_amd64_linux hls && chmod +x hls
$ mkdir client && cp hls client/hls
* Вышеописанный пример работает только для платформы Linux. HLS можно скачать также и для Windows / Darwin платформ, а также для arm64 архитектуры. Для этого достаточно поменять название скачиваемого файла, например: hls_arm64_darwin. Если необходимо запустить HLS на другой платформе или архитектуре процессора, тогда понадобится скомпилировать приложение уже самостоятельно.
Компиляция HLS
Код сети Hidden Lake находится полностью в открытом доступе, а потому вышеописанный способ запуска HLS не является единственным. Вместо того чтобы использовать релизные и заранее скомпилированные программы, можно скомпилировать их самим. Для этого потребуется компилятор Go и следующие действия:
$ git clone https://github.com/number571/go-peer.git
$ cd go-peer && go build ./cmd/hidden_lake/service/cmd/hls
Далее, чтобы успешно связаться с внешней сетью Hidden Lake, нам необходимо иметь в распоряжении уже настроенный конфигурационный файл hls.yml. Такие файлы можно скачать здесь. После этого нам необходимо их немного подредактировать.
Конфигурационные файлы
Взял в качестве основы конфигурационный файл в директории prod/1.
Сервисный hls.yml:
settings:
message_size_bytes: 8192
work_size_bits: 22
key_size_bits: 4096
fetch_timeout_ms: 60000
queue_period_ms: 5000
network_key: 8Jkl93Mdk93md1bz
logging:
- info
- warn
- erro
address:
# Удалил tcp поле из-за ненадобности
http: 127.0.0.1:9571 # Поменял порт, чтобы клиент мог запустить свой http сервер
services: # Удалил сторонние сервисы и прописал путь к echo-сервису
hidden-echo-service: # Название сервиса может быть любым
host: 127.0.0.1:8080
connections:
- 94.103.91.81:9581
Клиентский client/hls.yml:
settings:
message_size_bytes: 8192
work_size_bits: 22
key_size_bits: 4096
fetch_timeout_ms: 60000
queue_period_ms: 5000
network_key: 8Jkl93Mdk93md1bz
logging:
- info
- warn
- erro
address:
# Удалил tcp поле из-за ненадобности
http: 127.0.0.1:9572
# Удалил services поле из-за ненадобности
connections:
- 94.103.91.81:9581
После такой редакции узлы успешно смогут подключиться к ретранслятору сети, посредством которого уже смогут далее отправлять и принимать сообщения. Тем не менее Hidden Lake является также F2F сетью, а потому требует, чтобы узлы указывали публичные ключи друг друга для дальнейшей успешной и взаимной аутентификации. Чтобы сгенерировались ключи сервиса и клиента — достаточно запустить HLS приложения:
$ ./hls # Терминал 1
> [INFO] 2024/08/31 03:53:42 HLS is started; {"message_size_bytes":8192,"key_size_bits":4096,"fetch_timeout_ms":60000,"queue_period_ms":5000,"work_size_bits":22,"network_key":"8Jkl93Mdk93md1bz","limit_message_size_bytes":6526}
$ cd client && ./hls # Терминал 2
> [INFO] 2024/08/31 03:55:37 HLS is started; {"message_size_bytes":8192,"key_size_bits":4096,"fetch_timeout_ms":60000,"queue_period_ms":5000,"work_size_bits":22,"network_key":"8Jkl93Mdk93md1bz","limit_message_size_bytes":6526}
После первого запуска будут созданы приватные ключи: hls.key, client/hls.key. Для получения публичных ключей — необходимо обратиться к API каждого узла, обновить файлы hls.yml и перезапустить узлы.
$ curl http://127.0.0.1:9571/api/network/pubkey
> PubKey{3082020A...03010001}
$ curl http://127.0.0.1:9572/api/network/pubkey
> PubKey{3082020A...03010001}
Итоговые конфигурационные файлы
Итоговый сервисный hls.yml:
settings:
message_size_bytes: 8192
work_size_bits: 22
key_size_bits: 4096
fetch_timeout_ms: 60000
queue_period_ms: 5000
network_key: 8Jkl93Mdk93md1bz
logging:
- info
- warn
- erro
address:
http: 127.0.0.1:9571
services:
hidden-echo-service:
host: 127.0.0.1:8080
connections:
- 94.103.91.81:9581
friends:
client-node: PubKey{3082020A...03010001} # Ключ полученный от http://127.0.0.1:9572/api/network/pubkey
Итоговый клиентский client/hls.yml:
settings:
message_size_bytes: 8192
work_size_bits: 22
key_size_bits: 4096
fetch_timeout_ms: 60000
queue_period_ms: 5000
network_key: 8Jkl93Mdk93md1bz
logging:
- info
- warn
- erro
address:
http: 127.0.0.1:9572
connections:
- 94.103.91.81:9581
friends:
service-node: PubKey{3082020A...03010001} # Ключ полученный от http://127.0.0.1:9571/api/network/pubkey
В результате проделанных действий появляется возможность обратиться к сервису в сети Hidden Lake:
$ echo 'hello, world!' | base64
> aGVsbG8sIHdvcmxkIQ==
$ curl -i -X POST http://localhost:9572/api/network/request --data '{
"receiver":"service-node",
"req_data":{
"method":"POST",
"host":"hidden-echo-service",
"path":"/echo",
"body":"aGVsbG8sIHdvcmxkIQ=="
}
}'
>
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 30 Aug 2024 21:06:59 GMT
Content-Length: 102
{"code":200,"head":{"Content-Type":"text/plain; charset=utf-8"},"body":"ZWNobyhoZWxsbywgd29ybGQhKQ=="}
$ echo 'ZWNobyhoZWxsbywgd29ybGQhKQ==' | base64 -d
> echo(hello, world!)
Чтобы не повторять все действия настройки конфигурационных файлов и связывания публичных ключей, подготовлен тестовый репозиторий в котором это всё сделано и на примере которого можно получить тот же результат.