Статус
Утверждено на втором рассмотрении 2025-04-01; спецификации обновлены; реализация ещё не выполнена.
Обзор
В I2P отсутствует централизованная система DNS.
Однако адресная книга в сочетании с системой имён b32 позволяет
маршрутизатору выполнять поиск полных назначений и получать наборы лизингов (lease sets), содержащие
список шлюзов и ключей, чтобы клиенты могли подключиться к этому назначению.
Таким образом, leaseSet’ы похожи на DNS-записи. Однако в настоящее время нет механизма
определения, поддерживает ли хост какие-либо службы, либо на этом назначении, либо на другом,
аналогично DNS-записям SRV
, определённым в RFC 2782
.
Первое применение этого может быть в электронной почте с одноранговой архитектурой.
Другие возможные применения: DNS, GNS, серверы ключей, центры сертификации, серверы времени,
BitTorrent, криптовалюты, другие одноранговые приложения.
Связанные предложения и альтернативы
Списки служб
В Предложении 123
LS2 определялись «записи служб», указывающие, что назначение
участвует в глобальной службе. Флудфилы агрегировали эти записи
в глобальные «списки служб».
Это так и не было реализовано из-за сложности, отсутствия аутентификации,
проблем безопасности и спама.
Это предложение отличается тем, что обеспечивает поиск службы для конкретного назначения,
а не глобальный пул назначений для какой-либо глобальной службы.
GNS
GNS предлагает, чтобы каждый пользователь запускал свой собственный DNS-сервер.
Это предложение является дополнением: мы могли бы использовать записи служб, чтобы указать,
что GNS (или DNS) поддерживается, с именем службы «domain» на порту 53.
Dot well-known
Было предложено
, что службы следует искать через HTTP-запрос к
/.well-known/i2pmail.key. Это требует, чтобы у каждой службы был связанный
веб-сайт для размещения ключа. Большинство пользователей не запускают веб-сайты.
Одним из обходных решений является предположение, что служба для адреса b32 фактически
работает на этом же адресе b32. Таким образом, поиск службы для example.i2p требует
HTTP-запроса с http://example.i
2p/.well-known/i2pmail.key, но
служба для aaa…aaa.b32.i2p не требует такого поиска — можно подключаться напрямую.
Но здесь возникает неоднозначность, поскольку example.i2p также может быть адресован по своему b32.
MX-записи
Записи SRV — это просто обобщённая версия MX-записей для любой службы.
“_smtp._tcp” — это «MX»-запись.
Нет необходимости в MX-записях, если у нас есть записи SRV, и одних MX-записей
недостаточно для обеспечения универсальной записи для любой службы.
Дизайн
Записи служб размещаются в разделе опций LS2
.
Раздел опций LS2 в настоящее время не используется.
Не поддерживается для LS1.
Это похоже на предложение о пропускной способности туннеля
,
которое определяет опции для записей построения туннеля.
Чтобы найти адрес службы для конкретного имени хоста или b32, маршрутизатор получает
leaseSet и ищет запись службы в свойствах.
Служба может быть размещена на том же назначении, что и сам LS, или может ссылаться
на другое имя хоста/b32.
Если целевое назначение для службы отличается, целевой LS также
должен включать запись службы, указывающую на себя, показывая, что он поддерживает эту службу.
Дизайн не требует специальной поддержки, кэширования или каких-либо изменений в флудфилах.
Только издатель leaseSet и клиент, ищущий запись службы,
должны поддерживать эти изменения.
Предлагаются незначительные расширения I2CP и SAM для облегчения получения
записей служб клиентами.
Спецификация
Спецификация опций LS2
Опции LS2 ДОЛЖНЫ быть отсортированы по ключу, чтобы подпись была инвариантной.
Определяется следующим образом:
- serviceoption := optionkey optionvalue
- optionkey := _service._proto
- service := Символическое имя требуемой службы. Должно быть в нижнем регистре. Пример: “smtp”.
Допустимые символы: [a-z0-9-], не должно начинаться или заканчиваться на ‘-’. Должны использоваться стандартные идентификаторы из реестра типов служб DNS-SD или Linux /etc/services, если они определены. - proto := Транспортный протокол требуемой службы. Должен быть в нижнем регистре, либо “tcp”, либо “udp”.
“tcp” означает потоковую передачу, “udp” — ответные датаграммы.
Индикаторы протокола для сырых датаграмм и datagram2 могут быть определены позже.
Допустимые символы: [a-z0-9-], не должно начинаться или заканчиваться на ‘-’. - optionvalue := self | srvrecord[,srvrecord]*
- self := “0” ttl port [appoptions]
- srvrecord := “1” ttl priority weight port target [appoptions]
- ttl := время жизни, целое число в секундах. Положительное целое. Пример: “86400”.
Рекомендуется минимум 86400 (один день), подробности см. в разделе Рекомендации ниже. - priority := Приоритет целевого хоста, меньшее значение означает более предпочтительный. Неотрицательное целое. Пример: “0”
Полезно только при наличии более чем одной записи, но требуется даже при одной записи. - weight := Относительный вес записей с одинаковым приоритетом. Большее значение означает большую вероятность выбора. Неотрицательное целое. Пример: “0”
Полезно только при наличии более чем одной записи, но требуется даже при одной записи. - port := Порт I2CP, на котором находится служба. Неотрицательное целое. Пример: “25”
Порт 0 поддерживается, но не рекомендуется. - target := Имя хоста или b32 назначения, предоставляющего службу. Допустимое имя хоста
. Должно быть в нижнем регистре.
Пример: “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p” или “example.i2p”.
Рекомендуется использовать b32, если только имя хоста не является «хорошо известным», т.е. находится в официальных или стандартных адресных книгах. - appoptions := Произвольный текст, специфичный для приложения, не должен содержать " " или “,”. Кодировка — UTF-8.
Примеры
В LS2 для aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, указывающий на один SMTP-сервер:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p"
В LS2 для aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, указывающий на два SMTP-сервера:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p,86400 1 0 25 cccccccccccccccccccccccccccccccccccccccccccc.b32.i2p"
В LS2 для bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p, указывающий на себя как SMTP-сервер:
"_smtp._tcp" "0 999999 25"
Возможный формат для перенаправления почты (см. ниже):
"_smtp._tcp" "1 86400 0 0 25 smtp.postman.i2p example@mail.i2p"
Ограничения
Структура данных «Mapping», используемая для опций LS2, ограничивает ключи и значения максимум 255 байтами (не символами).
При использовании b32 в качестве цели, optionvalue составляет около 67 байт, поэтому поместится только 3 записи.
Возможно, только одна или две с длинным полем appoptions, или до четырёх-пяти с коротким именем хоста.
Этого должно быть достаточно; несколько записей должны быть редкостью.
Отличия от RFC 2782
- Нет завершающих точек
- Нет имени после proto
- Обязательный нижний регистр
- В текстовом формате с записями, разделёнными запятыми, а не в бинарном DNS-формате
- Другие индикаторы типа записи
- Дополнительное поле appoptions
Примечания
Запрещено использование подстановочных знаков, таких как (звёздочка), (звёздочка)._tcp или _tcp.
Каждая поддерживаемая служба должна иметь свою собственную запись.
Реестр имён служб
Не стандартные идентификаторы, не указанные в реестре типов служб DNS-SD
или Linux /etc/services,
могут быть запрошены и добавлены в спецификацию общих структур
.
Форматы appoptions, специфичные для службы, также могут быть добавлены туда.
Спецификация I2CP
Протокол I2CP
должен быть расширен для поддержки поиска служб.
Требуются дополнительные коды ошибок в MessageStatusMessage и/или HostReplyMessage, связанные с поиском службы.
Чтобы сделать механизм поиска универсальным, а не только для записей служб,
дизайн предусматривает получение всех опций LS2.
Реализация: Расширить HostLookupMessage, чтобы добавить запрос
опций LS2 для хэша, имени хоста и назначения (типы запросов 2-4).
Расширить HostReplyMessage, чтобы добавить отображение опций, если запрошено.
Расширить HostReplyMessage дополнительными кодами ошибок.
Отображения опций могут кэшироваться или отрицательно кэшироваться на короткое время на стороне клиента или маршрутизатора — зависит от реализации.
Рекомендуемое максимальное время — один час, если только TTL записи службы не короче.
Записи служб могут кэшироваться до TTL, указанного приложением, клиентом или маршрутизатором.
Расширить спецификацию следующим образом:
Параметры конфигурации
Добавить следующее в параметры конфигурации I2CP
i2cp.leaseSetOption.nnn
Опции, которые будут помещены в leaseset. Доступно только для LS2.
nnn начинается с 0. Значение опции содержит “key=value”.
(не включать кавычки)
Пример: i2cp.leaseSetOption.0=_smtp._tcp=1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p
Сообщение HostLookup
- Тип поиска 2: Поиск по хэшу, запрос отображения опций
- Тип поиска 3: Поиск по имени хоста, запрос отображения опций
- Тип поиска 4: Поиск по назначению, запрос отображения опций
Для типа поиска 4, элемент 5 — это Destination.
Сообщение HostReply
Для типов поиска 2-4 маршрутизатор должен получить leaseset,
даже если ключ поиска находится в адресной книге.
При успехе HostReply будет содержать отображение опций
из leaseset и включит его как элемент 5 после назначения.
Если в отображении нет опций или leaseset был версии 1,
он всё равно будет включён как пустое отображение (два байта: 0 0).
Все опции из leaseset будут включены, а не только опции записей служб.
Например, могут присутствовать опции для параметров, определённых в будущем.
При неудаче поиска leaseset ответ будет содержать новый код ошибки 6 (ошибка поиска leaseset)
и не будет включать отображение.
Когда возвращается код ошибки 6, поле Destination может присутствовать или отсутствовать.
Оно будет присутствовать, если поиск по имени хоста в адресной книге был успешен,
или если предыдущий поиск был успешен и результат был закэширован,
или если Destination присутствовал в сообщении поиска (тип поиска 4).
Если тип поиска не поддерживается,
ответ будет содержать новый код ошибки 7 (тип поиска не поддерживается).
Спецификация SAM
Протокол SAMv3 должен быть расширен для поддержки поиска служб.
Расширить NAMING LOOKUP следующим образом:
NAMING LOOKUP NAME=example.i2p OPTIONS=true запрашивает отображение опций в ответе.
NAME может быть полным base64-назначением, когда OPTIONS=true.
Если поиск назначения был успешен и опции присутствовали в leaseset,
то в ответе, после назначения,
будет одна или несколько опций в формате OPTION:key=value.
Каждая опция будет иметь отдельный префикс OPTION:.
Все опции из leaseset будут включены, а не только опции записей служб.
Например, могут присутствовать опции для параметров, определённых в будущем.
Пример:
NAMING REPLY RESULT=OK NAME=example.i2p VALUE=base64dest OPTION:_smtp._tcp=“1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p”
Ключи, содержащие ‘=’, и ключи или значения, содержащие символ новой строки,
считаются недопустимыми, и пара ключ/значение будет удалена из ответа.
Если в leaseset не найдено опций или leaseset был версии 1,
то ответ не будет включать опции.
Если в запросе был OPTIONS=true, а leaseset не найден, будет возвращено новое значение результата LEASESET_NOT_FOUND.
Альтернатива поиску имён
Был рассмотрен альтернативный дизайн, поддерживающий поиск служб
в виде полного имени хоста, например _smtp.tcp.example.i2p,
путём обновления спецификации имён
для обработки имён хостов, начинающихся с ‘’.
Это было отклонено по двум причинам:
- Для передачи информации TTL и порта клиенту всё равно потребовались бы изменения в I2CP и SAM.
- Это не было бы универсальным механизмом, который можно было бы использовать для получения других опций LS2,
которые могут быть определены в будущем.
Рекомендации
Серверы должны указывать TTL не менее 86400 и стандартный порт для приложения.
Дополнительные функции
Рекурсивные поиски
Может быть полезно поддерживать рекурсивные поиски, при которых каждый последующий leaseset
проверяется на наличие записи службы, указывающей на другой leaseset, по аналогии с DNS.
Это, вероятно, не требуется, по крайней мере в начальной реализации.
TODO
Поля, специфичные для приложения
Может быть полезно иметь данные, специфичные для приложения, в записи службы.
Например, владелец example.i2p может захотеть указать, что почту следует
пересылать на example@mail.i2p
. Часть «example@» должна быть в отдельном поле
записи службы или удалена из цели.
Даже если владелец запускает собственную почтовую службу, он может захотеть указать,
что почту следует отправлять на example@example.i2p
. Большинство служб I2P запускаются одним человеком.
Поэтому отдельное поле может быть полезным и в этом случае.
TODO, как сделать это универсальным способом
Изменения, необходимые для электронной почты
Вне рамок данного предложения. Подробности см. в обсуждении на i2pforum .
Примечания по реализации
Кэширование записей служб до TTL может выполняться маршрутизатором или приложением — зависит от реализации.
Вопрос о постоянном кэшировании также зависит от реализации.
Поиски должны также искать целевой leaseset и проверять, содержит ли он запись «self»,
прежде чем возвращать целевое назначение клиенту.
Анализ безопасности
Поскольку leaseset подписан, любые записи служб внутри него аутентифицируются ключом подписи назначения.
Записи служб являются публичными и видимыми для флудфилов, если только leaseset не зашифрован.
Любой маршрутизатор, запрашивающий leaseset, сможет видеть записи служб.
Запись SRV, отличная от «self» (т.е. указывающая на другое имя хоста/b32),
не требует согласия целевого имени хоста/b32.
Неясно, может ли перенаправление службы на произвольное назначение облегчить
некоторую атаку, или какова цель такой атаки.
Однако это предложение смягчает такую атаку, требуя, чтобы цель
также публиковала запись SRV «self». Разработчики должны проверять наличие записи «self»
в leaseset цели.
Совместимость
LS2: Проблем нет. Все известные реализации в настоящее время игнорируют поле опций в LS2
и корректно пропускают непустое поле опций.
Это было проверено при тестировании как Java I2P, так и i2pd во время разработки LS2.
LS2 был реализован в версии 0.9.38 в 2016 году и хорошо поддерживается всеми реализациями маршрутизаторов.
Дизайн не требует специальной поддержки, кэширования или каких-либо изменений в флудфилах.
Имена: символ ‘_’ не является допустимым в именах хостов i2p.
I2CP: Типы поиска 2-4 не должны отправляться маршрутизаторам с версией API ниже минимальной,
в которой они поддерживаются (подлежит определению).
SAM: сервер SAM на Java игнорирует дополнительные ключи/значения, такие как OPTIONS=true.
i2pd должен делать то же самое — подлежит проверке.
Клиенты SAM не получат дополнительные значения в ответе, если они не запрошены с OPTIONS=true.
Повышение версии не требуется.
Миграция
Реализации могут добавлять поддержку в любое время, согласование не требуется,
за исключением соглашения о действующей версии API для изменений I2CP.
Версии совместимости SAM для каждой реализации будут задокументированы в спецификации SAM.