id: Гость   вход   регистрация
текущее время 01:12 03/05/2024
Владелец: cooshoo редакция от 06/09/2007 18:56 (автор: cooshoo) Печать
Категории: софт, анонимность, tor, спецификации, стандарты
создать
просмотр
редакции
ссылки

Это старая редакция страницы Библиотека / Спецификации / Tor за 06/09/2007 18:56.


Этот документ основан на http://tor.eff.org/svn/trunk/doc/spec/tor-spec.txt


$Id: tor-spec.txt 11207 2007-08-19 21:54:20Z arma $


Спецификация протокола Тор


Roger Dingledine
Nick Mathewson

Внимание: Этот документ содержит спецификации Тор для версий 0.1.2.x
или более ранних. Будущие версии Тора могут применять усовершенствованные
протоколы, и совместимость не гарантируется.


Эта спецификация не является описанием разработки; причины выбора тех или иных
параметров в ней не отражены. Дополнительную информацию почему Тор устроен
именно так, а не иначе, смотри в tor-design.pdf.


0. Вступление


0.1. Символы и обозначения


PK — открытый ключ.
SK — секретный ключ.
K — ключ для симметричного шифрования.

a|b — объединение 'a' и 'b'.

[A0 B1 C2] — трехбайтовая последовательность, содержащая байты с
шестнадцатиричными значениями A0, B1 и C2, в указанном порядке.

Все числовые значения кодируются в сетевом (big-endian) порядке.

H(m) — криптографический хэш от m.

0.2. Параметры безопасности


Тор использует потоковый шифр, шифр с открытым ключом, протокол
Диффи-Хеллмана, и хэш-функцию.

KEY_LEN — длина ключа потокового шифра, в байтах.

PK_ENC_LEN — длина сообщения, зашифрованного открытым ключом, в байтах.
PK_PAD_LEN — число байт, добавляемых перед шифрованием с открытым
ключом, в байтах.
(Таким образом наибольшее число байт, которое может быть зашифровано в
одну операцию с открытым ключом составляет PK_ENC_LEN-PK_PAD_LEN.)

DH_LEN — число байт используемых для представления члена группы Диффи-

Хеллмана.

DH_SEC_LEN — число байт используемых для секретного ключа (x) Диффи-

Хеллмана.
HASH_LEN — длина выхода хэш-функции, в байтах.

PAYLOAD_LEN — наибольшая длина полезных данных в пакете, в байтах. (509)

CELL_LEN — длина пакета Тор, в байтах.

0.3. Шифры.


В качестве потокового шифра, мы используем 128-бит AES в режиме счетчика,
все байты вектора инициализации IV устанавливаются в 0.

В качестве шифра с открытым ключом мы используем RSA с ключом 1024 бита и
фиксированной экспонентой 65537. Мы используем OAEP-MGF1 дополнение, с
SHA-1 в качестве хэш-функции. Мы оставили опциональный параметр "Label"
неустановленным. (Подробно OAEP дополнение смотри
fileftp://ftp.rsasecurity.com/pub/.....kcs-1/pkcs-1v2-1.pdf)

[Nick, как получилось, что "мы оставили опциональный параметр Label
неустановленным"? -RD]

Для схемы Диффи-Хеллмана, мы используем генератор (g) равный 2. В качестве
модуля §, мы используем 1024-битное безопасное простое число из rfc2409
секция 6.2, шестнадцатиричное представление которого:

"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF"

В целях оптимизации, приложения должны выбирать DH секретный ключ (x) длиной
320 бит. Приложения никогда не должны использовать никаких более длинных DH
ключей.
[Могут другие приложения использовать свои DH ключи повторно?? -RD]
[Probably not. Conceivably, you could get away with changing DH keys once
per second, but there are too many oddball attacks for me to be
comfortable that this is safe. -NM]

В качестве хэш-функции мы используем SHA-1.

KEY_LEN=16.
DH_LEN=128; DH_SEC_LEN=40.
PK_ENC_LEN=128; PK_PAD_LEN=42.
HASH_LEN=20.

Когда мы говорим "хэш открытого ключа", мы имеем ввиду SHA-1 хэш DER
encoding открытого ключа ASN.1 RSA (как указано в PKCS.1).

Все "случайные" значения должны быть сгенерированы с помощью криптографически
стойкого генератора случайных чисел, если не указано иначе.

"Гибридное шифрование" байтовой последовательности М открытым ключом PK
вычисляется следующим образом:
    1. Если М короче, чем PK_ENC_LEN-PK_PAD_LEN, дополняем и шифруем М с PK.
    2. В противном случае генерируем случайный ключ К длиной KEY_LEN байт.
      Пусть M1 = первые PK_ENC_LEN-PK_PAD_LEN-KEY_LEN байтов M,
      пусть M2 = остаток M.
      Дополняем и шифруем K|M1 с PK. Шифруем M2 нашим потоковым шифром,
      используя ключ K. Объединяем получившиеся зашифрованные значения.
[XXX Важно: "гибридное шифрование" не мешает атакующему добавлять или
удалять байты в конце сообщения M. Атакующий также может изменять байты,
которые не защищены OAEP — подробности смотри в Goldberg's PET2006 paper.
Впоследствии мы собираемся добавить MAC в эту схему. -RD]

0.4. Значения других параметров.


CELL_LEN=512

1. Краткий обзор системы.


Тор это распределенная сеть, разработанная для анонимизации основанных на
TCP приложений, требующих малых задержек, таких как просмотр веб-страниц,
secure shell, и системы мгновенной передачи сообщений. Клиенты выбирают
путь в сети и строят схему, в которой каждый узел (или "маршрутизатор
луковицы", "onion router" далее "OR") в пути знает только своего
предшественника и преемника, но никаких других узлов схемы. Траффик следует
через схему в виде пакетов стандартного размера, с которых каждый узел
снимает свое симметричное шифрование (как снятие слоя с луковицы) и передает
дальше.

1.1. Ключи и имена.
Каждый сервер Тор имеет несколько пар открытых/закрых ключей:

    • Долговременный, "только для подписи", "Identity key", предназначен для
      подписания документов и сертификатов, и используется для идентификации
      сервера.
    • Среднесрочные "Onion key" используются для расшифрования "слоев луковицы"
      когда предпринимаются попытки расширить схему. (См. 5.1.) Старые ключи
      должны приниматься как минимум в течении одной недели после того, как они
      сняты с рассылки. Поэтому серверы обязаны хранить старые ключи некоторое
      время после их замены.
    • Краткосрочные "Connection key" используются для установки TLS соединения.
      Приложения Тор могут заменять эти ключи так часто, как хотят, и должны
      заменять эти ключи не реже раза в сутки.

Сервера Тор также идентифицируются по "псевдонимам"; они специфицированы в
dir-spec.txt.

2. Соединения


Тор использует TLS/SSLv3 для сетевой аутентификации и шифрования. Все
приложения обязаны поддерживать SSLv3 схему шифрования
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", также должны поддерживать TLS
схему шифрования "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" если это возможно.
Приложения могут поддерживать другие схемы шифрования TLS, но не должны
поддерживать никакие схемы, в которых отсутствуют сеансовые ключи, или в
которых длина ключа симметричного шифрования меньше чем KEY_LEN бит, или
длина хэша меньше чем HASH_LEN бит.
Приложения не должны разрешать никакие другие схемы шифрования SSLv3.

Хотя протоколы соединений одинаковы, мы будем различать их инициаторов как
"маршрутизаторов луковицы" (OR), если они хотят передавать трафик для
других пользователей Тор, или как "прокси луковицы" (OP) если они
обрабатывают только локальные запросы. OP не должны использовать никаких
долговременно отслеживаемых идентификаторов в их протоколах взаимной
идентификации (схемах ключевого соглашения).

Во время ключевого соглашения TLS инициатор соединения всегда посылает
цепочку из двух сертификатов: первый сертификат X.509, использующий
сеансовый открытый ключ, и второй, самоподписанный X.509 сертификат,
содержащий его ключ идентификации. "commonName" первого сертификата это
"псевдоним" OR, "commonName" второго сертификата это "псевдоним" OR, за
которым следует пробел и строка "<identity>". Другая сторона посылает
подобную цепочку сертификатов.

Приложения, использующие Протокол 1 или более ранние, используют значение
"organizationName" "Tor" или "TOR". Будущие приложения (которые поддерживают
версию протокола, описанную в секции 4.1) не должны использовать ни одно из
этих значений для своего "organizationName".

Все стороны, принимающие сертификаты, должны подтвердить, что ключи
идентификации те, которые ожидаются. (При инициализации соединения ожидаемый
ключ идентификации – один из корневых; при создании подключения
пакетом EXTEND, ожидаемый ключ идентификации – один из заданных в пакете.
Если ключ не относится к ожидаемым, сторона должна закрыть соединение.

При подключении к OR все стороны должны отклонять соединение, если сертификат
OR неправильно оформлен или отсутствует. При приеме входящего соединения OR
не должен отклонять входящее соединение, даже если сертификат другой стороны
неправильно оформлен или отсутствует. (Однако OR не должен предполагать, что
получил входящее соединение от другого OR, даже если сертификат присутствует
и правильно оформлен.)

[До версии 0.1.2.8-rc, OR-ы отвергали входящие соединения от OR-ов и OP-ов
если их сертификаты отсутствовали или были неправильно оформлены.]

Когда TLS соединение установлено, обе стороны посылают пакеты
(специфицированные ниже) друг другу. Пакеты посылаются последовательно. Все
пакеты имеют длину CELL_LEN байт. Пакеты могут быть встроены в TLS записи
любой длины или поделены между TLS записями. Но кадрирование TLS записей не
должно допускать никакой утечки информации о типе или содержании пакетов.

TLS соединение не постоянно. Любая сторона может закрыть соединение, если
не было никакого обмена информацией в течение заданного периода времени
("KeepalivePeriod", по умолчанию 5 минут)

(Как исключение корневые сервера могут пытаться оставаться подключенными ко
всем OR — но это будет постепенно убираться в версиях Тор 0.1.2.x)

3. Формат пакетов.


Базовая единица коммуникации для OR и OP это фиксированных размеров "пакет".

В версии 1 соединения каждый пакет содержит следующие поля:

CircID [2 байта]
Command [1 байт]
Payload (дополненный байтами "0") [PAYLOAD_LEN байт]


Поле CircID определяет, с какой из имеющихся схем связан пакет.

The 'Command' field holds one of the following values:

0 — PADDING (дополнение) (См. секц. 7.2)
1 — CREATE (Создать схему) (См. секц. 5.1)
2 — CREATED (Подтверждение создания) (См. секц. 5.1)
3 — RELAY (Данные от точки к точке) (См. секц. 5.5 и 6)
4 — DESTROY (Остановить использование схемы) (См. секц. 5.4)
5 — CREATE_FAST (Создать схему без PK) (См. секц. 5.1)
6 — CREATED_FAST (Схема создана, без PK) (См. секц. 5.1)


Интерпретация 'Payload' зависит от типа ячейки.

PADDING: Данные не используются.
CREATE: Данные содержат предложение ключевого соглашения.
CREATED: Данные содержат ответ на ключевое соглашение.
RELAY: Данные содержат заголовок и тело передаваемой информации.
DESTROY: Данные содержат причину закрытия схемы.
(См. 5.4)
При получении любого другого значения поля команды OR должен отбросить пакет.
[XXXX Версии до 0.1.0.?? писали в лог предупреждение
при отбрасывании пакета; это было неправильно. -NM]

Данные дополняются нулями.

Пакет PADDING в настоящее время применяется для поддержания соединения.
Если нет никакого другого траффика, OR-сы и OP-сы посылают друг другу
PADDING пакет каждые несколько минут.

CREATE, CREATED и DESTROY пакеты используются для управления схемой;
смотри секцию 4 ниже.

RELAY пакеты используются для того чтобы пересылать команды и данные через
схему; смотри секцию 5 ниже.

4. [Этот раздел преднамеренно оставлен пустым.]


5. Управление схемой


5.1. Пакеты CREATE и CREATED.


Пользователи создают схемы наращивая из на один переход за раз. Для создания
новой схемы, OP-сы send aпосылают CREATE пакет первому узлу, с первой
половиной ключевого соглашения DH; этот узел отвечает пакетом CREATED со
второй половиной ключевого соглашения DH плюс первые 20 байт данных для
вычисления ключа (смотри секцию 5.2). Для расширения схемы на следующий
переход, OP посылает пакет EXTEND (смотри секцию 5) который дает последнему
узлу схемы указание послать пакет CREATE для расширения схемы.

Данные для пакета CREATE это "кожица лука", которая состоит из данных первого
шага ключевого соглашения DH (g^x). Это значение гибридно зашифровано с
использованием "onion key" получателя и имеет следующую структуру:

Зашифровано открытым ключом PK:
Дополнение [PK_PAD_LEN байт]
Симметричный ключ [KEY_LEN байт]
Первая часть g^x [PK_ENC_LEN-PK_PAD_LEN-KEY_LEN байт]

Зашифровано симметричным алгоритмом:

Вторая часть g^x [DH_LEN-(PK_ENC_LEN-PK_PAD_LEN-KEY_LEN)
байт]


Данные для соотвествующего пакета EXTEND состоят из:

Адрес [4 байт]
Порт [2 байт]
"Кожица лука" [DH_LEN+KEY_LEN+PK_PAD_LEN байт]
Отпечаток идентификатора [HASH_LEN байт]


Поля "Порт" и "Адрес" содержат IPV4 адрес и порт следующего маршрутизатора
OR в схеме; отпечаток идентификатора это хэш окрытого ключа проверки подписи
(закодированного как указано в PKSC#1 ASN1) следующего OR в схеме. (См. 0.3)
(Включение этого хэша позволяет OR, осуществляющему расширение, проверить,
что он действительно соединился с указанным OR, и предотвращает некоторые
атаки типа "человек посередине").

Даннае для пакета CREATED, или соотвествующие данные для пакета EXTENDED
содержат:

DH данные (g^y) [DH_LEN байт]
Данные для вычисления ключа (KH) [HASH_LEN байт] <см. 5.2 ниже>

Поле CircID для пакета CREATE выбирается узлом (OR или OP), посылающим пакет
CREATE, как случайное двухбайтовое целое. Для предотвращения CircID коллизий,
когда один узел посылает пакет CREATE другому он выбирает только из половины
возможных значений, основанных на открытых ключах подписи OR: если
отправляющий узел имеет меньший ключ, он выбирает CircID с младшим значащим
битом "0", в противоположном случае выбирается CircID с MSB "1".

(OP не имеющие открытого ключа могут выбирать любое CircID по желанию, так
как OP никогда не исполняют пакеты CREATE.)

Открытые ключи сравниваются как числа по модулю.

Как обычно для DH, x и y должны генерироваться случайным образом.

[

Для обеспечения обратной совместимости версий протоколов стороны должны
отбрасывать пакеты CREATE в которых "кожица лука" состоит из одних нулей.

]


5.1.1. Пакеты CREATE_FAST/CREATED_FAST.


Когда первый переход схемы инициализирован, OP уже идентифицировал OR и
выработал общий секретный ключ с использованием TLS. Поэтому не всегда
необходимо для OP выполнять операции с открытым ключом для создания схемы.
В этом случае OP может послать пакет CREATE_FAST вместо пакета CREATE
(только для первого перехода). OR отвечает пакетом CREATED_FAST и схема
создана.

Пакет CREATE_FAST содержит:
Ключевой материал (X) [HASH_LEN байт]


Пакет CREATED_FAST содержит:

Ключевой материал (Y) [HASH_LEN bytes]
Данные для вычисления ключа [HASH_LEN bytes] (См. 5.2 ниже)


Значения X и Y должны быть сгенерированы случайным образом.

[Версии Тора до 0.1.0.6-rc не поддерживают эти типы пакетов;

клиенты не должны посылать пакеты CREATE_FAST старым серверам Тор.]

Ели OR видит схему, созданную с помощью CREATE_FAST, он может быть уверен,
что это первый переход в схеме. OR-ы должны отклонять попытки создать потоки
с помощью RELAY_BEGIN, покидающие схему после первого перехода: разрешение
Тору быть использованному как однопереходный прокси делает выходной узел
более привлекательной целью для компрометации.

5.2. Установка ключей схемы.


После того как ключевое соглашение между OP и OR завершено, оба они могут
вычислить g^xy как в обычном DH. Перед вычислением g^xy и клиент и сервер
обязаны проверить, что полученные значения g^x и g^y не вырожденные; т.е.
они должны быть строго больше единицы и строго меньше p-1, где "p" это DH
модуль. Приложения не должны завершать ключевое соглашение с вырожденными
ключами. Приложения не должны отвергать другие "слабые" значения g^x.

(Отбрасывание вырожденных ключей критично для безопасности; если плохие
ключи не отвергать, атакующий может подменить g^y в пакете CREATED от
сервера на 1 или 0, и с известным g^xy выдать себя за сервер. Отбрасывание
других ключей делает возможными атаки, позволяющие узнать биты секретного
ключа.)

(Основные приложения Тор версий 0.1.1.x-alpha отвергали все значения g^x
меньше чем 2^24 и больше чем p-2^24, или имеющие больше чем 1024-16
одинаковых бит. Это было бесполезно и мы от этого отказались.)

Если CREATE или EXTEND используются для расширения схемы, клиетн и сервер
основывают свой ключевой материал на K0=g^xy, представленном как "big-endian"
беззнаковое целое.

Если используется CREATE_FAST, клиент и сервер основывают свой ключевой
материал на K0=X|Y.

Из основного ключевого материала K0 они вычисляют KEY_LEN*2+HASH_LEN*3 байт
производных ключевых данных:
K = H(K0 | [00]) | H(K0 | [01]) | H(K0 | [02]) | ...

Первые HASH_LEN байт K образуют KH; следующие HASH_LEN образуют прямой хеш
Df; следующие HASH_LEN 41-60 образуют обратный хэш Db; следующие KEY_LEN
61-76 образуют Kf, и последние KEY_LEN образуют Kb. Лишние байты K
отбрасываются.

KH используется в "ответе на рукопожатие" для демонстрации знания
вычисленного общего ключа. Df используется как хэш проверки целостности
потока данных, передаваемых от OP к OR. Db используется как хэш проверки
целостности потока данных, передаваемых от OR к OP. Kf используется для
шифрования потока данных, идущих от OP к OR, и Kb используется для шифрования
потока данных, идущих от OR к OP.

5.3. Создание схемы.
При создании схемы в сети, создатель схемы (OP) выполняет следующие шаги:

      1. Выбирает в качестве последнего узла схемы такой "маршрутизатор
        луковицы" OR, (R_N), чтобы его выходная политика включала в себя
        хотя бы один ожидающий обработки поток, необходимый для схемы
        (если такой есть).

      1. Выбирает цепочку из (N-1) маршрутизаторов OR (R_1...R_N-1) для
        составления пути таким образом, чтобы ни один маршрутизатор не
        входил в путь дважды.

      1. Если соединение с первым маршрутизатором в цепочке еще не установлено,
        открывает новое соединение к этому маршрутизатору.

      1. Выбирает circID не используемое в данный момент для соединения с
        первым маршрутизатором в цепочке; посылает пакет CREATE через это
        соединение, чтобы он был получен первым маршрутизатором OR .

      1. Ждет, пока не будет получен пакет CREATED; заканчивает согласование
        ключей и извлекает прямой ключ Kf_1 и обратный ключ Kb_1.

      1. Для каждого последующего маршрутизатора R (от R_2 до R_N), выполняет
        the circuit to Rрасширение схемы на этот маршрутизатор.

Для расширения схемы на один маршрутизатор R_M, OP выполняет следующие шаги:

      1. Создает "кожицу лука", зашифровая ее открытым ключом "onion key"
        маршрутизатора R_M.

      1. Посылает эту "кожицу лука" в качестве данных пакета EXTEND через
        схему (См. секцию 5).

      1. Когда получен пакет EXTENDED, проверяет KH, вычисляет общие ключи.
        Схема расширена.

Когда OR получает пакет EXTEND, он посылает пакет CREATE следующему OR,
включив в него в качестве данных "кожицу лука". Инициирующий OR выбирает
значение circID, еще не использующееся в соединении между двумя OR.
(Но см. секцию 5.1. выше, относительно выбора circIDs основанного на
алфавитном порядке "псевдонимов".)

Если OR получает пакет CREATE со значением circID, которое уже используется
в данном соединении в построении схемы, он отбрасывает пакет. В противном
случае, после получения пакета CREATE, он завершает схему ключевого
согласования DH и отвечает пакетом CREATED. После получения пакета CREATED,
OR упаковывает его данные в пакет EXTENDED (см. секцию 5), и отправляет этот
пакет по схеме. После получения пакета EXTENDED, OP может извлечь g^y.

(В целях оптимизации, OR приложения могут откладывать обработку "кожиц лука"
на некоторое время, но так чтобы сетевые задержки не стали очень большими.)

5.4. Разрушение схемы.


Схема разрушается если в ней произошла невосстановимая ошибка, или по
таймауту после закрытия всех потоков в ней. Схема может быть разрушена
сразу вся или переход за переходом.

Для того чтобы уничтожить схему полностью, OR или OP посылает пакет DESTROY
смежным узлам схемы, используя соответствующий circID для данного
направления.

После получения пакета DESTROY, OR освобождает ресурсы, связанные с
соответствующей схемой. Если он не является концом схемы, он посылает пакет
DESTROY для этой схемы следующему OR в схеме. Если узел является концом
схемы, он обрывает все связанные с ней соединения (см. секцию 6.1).

После обработки пакета DESTROY, OR игнорирует все пакеты с данными или
пакеты разрушения для соответствующей схемы.


Для разрушения части схемы, OP может послать пакет RELAY_TRUNCATE
для заданного OR (с нулевым ID потока). Этот OR посылает пакет DESTROY
следующему узлу в схеме, и отвечает OP пакетом RELAY_TRUNCATED.

Если во время соединения произошла невосстановимая ошибка в схеме, узлы по
обе стороны от соединения должны действовать следующим образом: узел,
расположенный ближе к OP, должен послать пакет RELAY_TRUNCATED для OP, узел
расположенный дальше от OP, должен послать пакет DESTROY далее по схеме.

Данные пакета RELAY_TRUNCATED или DESTROY содержат единственный байт,
описывающий почему схема будет закрыта или обрезана. Если пакет TRUNCATED
или DESTROY посылается из-за получения другого пакета TRUNCATED or DESTROY,
код ошибки повторяет полученный. Инициатор схемы всегда устанавливает код
ошибки в "0" во избежание утечки информации о причине.

Коды ошибок:

0 — NONE (Причина не указана.)
1 — PROTOCOL (Нарушение протокола Тор.)
2 — INTERNAL (Внутренняя ошибка.)
3 — REQUESTED (Клиент прислал команду TRUNCATE.)
4 — HIBERNATING (Нет текущих операций; попытка разгрузить канал.)
5 — RESOURCELIMIT (Нехватка памяти, портов, или идентификаторов схем.)
6 — CONNECTFAILED (Невозможно подключиться к серверу.)
7 — OR_IDENTITY (Подключились к серверу, но его OR идентификатор не
тот, что ожидается.)

8 — OR_CONN_CLOSED (Соединение с OR, используемое для этой схемы,

пропало.)

9 — FINISHED (Схема закончила функционирование потому что

скомпрометирована или устарела.)
10 — TIMEOUT (Построение схемы заняло слишком много времени.)
11 — DESTROYED (Схема уничтожена без команды клиента TRUNCATE.)
12 — NOSUCHSERVICE (Запрос от неизвестного скрытого сервиса.)

[Версии Тора до 0.1.0.11 не сообщают причин; приложения
должны принимать пустые пакеты TRUNCATED и DESTROY.]

5.5. Маршрутизация пересылаемых пакетов с данными.


Когда OR получает пакет RELAY, он проверяет circID пакета и определяет,
есть ли соответствующее этой схеме подключение. Если нет OR отбрасывает
пакет RELAY.

Иначе, если OR не является краевым узлом схемы со стороны OP (т.е. является
выходным или промежуточным узлом), он рас/зашифровывает данные пакета
симметричным шифром следующим образом:
'Forward' пакет с данными (то же направление, что и запрос CREATE):
Использовать ключ Kf; расшифровать.

'Backward' пакет с данными (направление, противоположое запросу CREATE):

Использовать ключ Kb; зашифровать.

Примечание: в режиме счетчика шифрование и расшифрование представляют собой

одну и ту же операцию.


После этого OR пытается распознать пакет, исследуя его содержимое как
описано в секции 6.1 ниже. Если OR распознал пакет, он обрабатывает его
содержимое. В противоположном случае он пересылает расшифрованный пакет
дальше по схеме, если схема продолжается. Если OR, являющийся концом схемы,
встретил нераспознанный пакет, значит произошла ошибка: OR посылает пакет
DESTROY и разрушает схему.

Когда пакет RELAY поступает на OP, OP расшифровывает данные пакета потоковым
шифром следующим образом:

OP получил пакет с данными:
Для I=N...1,
Расшифровать ключом Kb_I. Если данные распознаны (см. секцию
  1. 1), остановить обработку данных.

Дополнительную информацию смотри в секции 6 ниже.

6. Управление связью и потоком для приложения.


6.1. Пакеты с данными.


В пределах схемы OP и узел выхода используют содержимое пакетов RELAY для
организации "туннеля" для команд и TCP соединений (потоков) сквозь схему.
Команды могут быть инициированы любой стороной, потоки инициируются OP.

Данные каждого незашифрованного пакета RELAY состоят из:
Команда [1 байт]
'Распознано' [2 байта]
StreamID [2 байта]
Дайджест [4 байта]
Длина [2 байта]
Данные [CELL_LEN-14 байт]


Команды RELAY:

1 — RELAY_BEGIN [forward]
2 — RELAY_DATA [forward или backward]
3 — RELAY_END [forward или backward]
4 — RELAY_CONNECTED [backward]
5 — RELAY_SENDME [forward или backward] [возможно контроль]
6 — RELAY_EXTEND [forward] [контроль]
7 — RELAY_EXTENDED [backward] [контроль]
8 — RELAY_TRUNCATE [forward] [контроль]
9 — RELAY_TRUNCATED [backward] [контроль]
10 — RELAY_DROP [forward или backward] [контроль]
11 — RELAY_RESOLVE [forward]
12 — RELAY_RESOLVED [backward]
13 — RELAY_BEGIN_DIR [forward]

        1. .40 — Используется для скрытых сервисов; смотри rend-spec.txt.

Команды, помеченные как "forward" должны посылаться только организатором
схемы. Команды, помеченные как "backward" должны посылаться только другими
узлами. Команды, помеченные обоими направлениями, могут быть посланы как
организатором, так и другими узлами схемы.

Поле 'Распознано' во всех незашифрованых данных всегда установлено в ноль;
поле 'Дайджест' вычисляется как первые четыре байта текущего хэша от всех
байтов, которые были предназначены для этого перехода схемы или порождены
этим переходом схемы, начиная от Df или Db соответственно (рассмотрено в
секции 5.2 выше), и включая данные этого пакета RELAY (взятые с полем
"Дайджест" установленным в "0").

Когда поле 'распознано' пакета RELAY нулевое, и дайджест правильный,
пакет считается распознанным после расшифровки (см. секцию 5.5 выше).

Дайджест не включает никаких байтов пакета RELAY, которые не начинаются или
не заканчиваются на этом перегоне схемы. То есть не включаются данные,
предназначенные для дальнейшей пересылки. Таким образом, если "распознано"
нулевое, но дайджест не соответствует, текущий дайджест узла не обновляется,
и пакет пересылается дальше.

Все пакеты RELAY имеющие отношение к одному или тому же туннелируемому
потоку имеют один и тот же ID потока. Эти идентификаторы выбираются OP
произвольным образом. Пакеты RELAY, котрые влияют не на отдельный поток,
а на саму схему, используют нулевой streamID — они помечены в таблице выше
как пакеты типа "контроль". (Пакет SENDME помечен как "возможно контроль"
потому что они могут обрабатываться как с использованием streamID, так и
независимо от него — смотри Секцию 7.)

Поле "Длина" пакета RELAY содержит число байт в поле данных пакета, которые
действительно используются. Остаток поля данных заполняется нулями.

Если пакет RELAY распознан, но "команда" не понята, пакет должен быть
отброшен и проигнорирован. Хотя его содержимое учитывается при вычислении
дайджеста. [Версии Тор до 0.1.1.10 закрывали схему, если получали
неизвестную команду RELAY. Возможно новый вариант будет более совместим с
будущими версиями. -RD]

6.2. Открытие потоков и передача данных.


Для открытия нового анонимного TCP соединения OP выбирает открытую схему
выход которой может соединиться с адресом назначения, выбирает произвольный
StreamID, не используемый в этой схеме, и создает пакет RELAY_BEGIN в данных
которого кодирует адрес и порт хоста назначения в следующем формате:

ADDRESS | ':' | PORT | [00]


где ADDRESS должен быть DNS именем хоста или адресом IPv4 в формате из
четырех чисел, разделенных точками, или адрес IPv6 в квадратных скобках;
и PORT – десятичное число между 1 и 65535 включительно.

[Что это за [00] в конце? -NM]
[Так проще работать с данными, как с ASCIIZ строкой -RD]

После получения этого пакета, узел выхода вычисляет адрес, если это
необходимо, и открывает новое TCP соединение с указанным портом. Если адрес
не может быть вычислен или соединение не может быть установлено, узел выхода
отвечает пакетом REPLAY_END. (См. 6.4 ниже.)
В противном случае узел выхода отвечает пакетом RELAY_CONNECTED, данные
которого находятся в одном из следующих форматов:

Адрес IPv4 с которым установлено соединение [4 байта]
Число секунд (TTL) в течение которых этот адрес может быть закэширован
[4 байта]

или

Четыре нулевых байта [4 байта]
Тип адреса (6) [1 байт]
Адрес IPv6 с которым установлено соединение [16 байт]
Число секунд (TTL) в течение которых этот адрес может быть закэширован
[4 байта]
[XXXX Версии Тора до 0.1.1.6 игнорируют и не генерируют поле TTL
На текущий момент нет версий Тор генерирующих IPv6 формат.

Сервера Тор до 0.1.2.0 заполняют поле TTL фиксированным значением. Поздние
устанавливают в поле TTL последнее значение, полученное от DNS сервера,
и очищают свои собственные кэши после фиксированного интервала. Это
предотвращает некоторые атаки.]

OP ждет пакет RELAY_CONNECTED перед тем как послать какие либо данные.
После того как соединение установлено, OP и узел выхода упаковывают поток
данных в пакеты RELAY_DATA, и при получении таких пакетов перенаправляют их
содержимое в соответствующий поток TCP.
Пакеты RELAY_DATA посланные для нераспознанных потоков отбрасываются.

Пакеты RELAY_DROP просто дальнодействующие заглушки; после получения такого
пекета OR или OP должны отбросить его.

6.2.1. Открытие корневого потока.


Если Тор сервер является корневым, он должен отвечать на пакет
RELAY_BEGIN_DIR так, как будто бы получил пакет BEGIN с запросом на
соединение с его корневым портом. Пакет RELAY_BEGIN_DIR игнорирует выходную
политику, так как этот поток является локальным для процесса Тор.

Если корневой сервис не запущен на Тор сервере, он должен ответить пакетом
REASON_NOTDIRECTORY RELAY_END.

Клиенты должны заполнять данные пакетов RELAY_BEGIN_DIR одними нулями,
и серверы должны игнорировать эти данные.

[RELAY_BEGIN_DIR не поддерживаются в версиях Тор до 0.1.2.2-alpha; клиенты
не должны посылать их маршрутизаторам, на которых запущены ранние версии
Тор.]

6.3. Закрытие потоков.


Когда анонимное TCP соединение закрыто, или крайний узел получает ошибку в
любом из потоков, он посылает пакет 'RELAY_END' в схему (если возможно) и
немедленно закрывает все TCP соединения. Если крайний узел получает пакет
'RELAY_END' cell для любого из потоков, он закрывает все TCP соединения
полностью, и не посылает больше ничего по схеме для данного потока.

Данные пакета RELAY_END начинаются с одного байта 'причина', который
описывает, почему поток закрывается, плюс опциональные данные (зависящие от
причины.) Используются следующие значения:

1 — REASON_MISC (причины не указаны)
2 — REASON_RESOLVEFAILED (не найдено имя хоста)
3 — REASON_CONNECTREFUSED (удаленныйхост отказал в подключении) [*]
4 — REASON_EXITPOLICY (OR отказал в подключении к хосту или порту)
5 — REASON_DESTROY (Схема разрушена)
6 — REASON_DONE (Анонимное TCP соединение закрыто)
7 — REASON_TIMEOUT (Закончилось время ожидания соединения, или
закончилось время ожидания OR)

8 — (незанято) [**]
9 — REASON_HIBERNATING (OR временно не работает)
10 — REASON_INTERNAL (Внутренняя ошибка OR)
11 — REASON_RESOURCELIMIT (OR не имеет ресурсов для выполнения запроса)
12 — REASON_CONNRESET (Соединение неожиданно сбросилось)
13 — REASON_TORPROTOCOL (Посылается, когда соединение закрывается

из-за нарушения протокола Тор.)

14 — REASON_NOTDIRECTORY (Клиент послал RELAY_BEGIN_DIR серверу,

не являющемуся корневым.)


(Для REASON_EXITPOLICY, опциональными данными являются 4-байтовый IPv4 адрес
или 16-байтовый IPv6 адрес; другие причины дополнительных данных не имеют.
Начиная с версии 0.1.1.6, тело также содержит 4-байтовый TTL.)

OPы и ORы должны принимать причины, не указанные в списке, потому что
будущие версии Тор могут сообщать более конкретные причины.

[*] Старые версии Тор также посылают эту причину при сбросе соединения.
[**] Из-за ошибки в версии Тор до 0095, причина 8 не должна указываться,

пока устаревшие версии полностью не выйдут из обращения.



[Остаток этой секции описывает неосуществленные функциональные

возможности.]

Поскольку TCP соединения могут быть "полуоткрыты", мы вводим эквивалент
TCP протокола FIN/FIN-ACK/ACK для закрытия потоков.

Выходящее соединение может иметь TCP поток в одном из трех состояний:
'OPEN', 'DONE_PACKAGING', и 'DONE_DELIVERING'. В целях моделирования мы
рассматриваем 'CLOSED' как четвертое состояние, хотя соединения в этом
состоянии фактически не отслеживаются "маршрутизаторами луковицы".

Поток начинает с состояния 'OPEN'. После получения 'FIN' от
соответствующего TCP соединения, краевой узел посылает пакет 'RELAY_FIN'
по схеме и изменяет состояние потока на 'DONE_PACKAGING'.
При получении пакета 'RELAY_FIN', краевой узел посылает 'FIN'
соответствующему TCP соединению (например вызывая завершение(SHUT_WR))
и изменяет состояние потока на 'DONE_DELIVERING'.


Если поток уже находящийся в состоянии 'DONE_DELIVERING' получает 'FIN',
он также посылает 'RELAY_FIN' по схеме, и изменяет свое состояние на
'CLOSED'. Когда поток уже находящийся в состоянии 'DONE_PACKAGING' получает
пакет 'RELAY_FIN', он посылает 'FIN' и изменяет свое состояние на 'CLOSED'.

Если краевой узел обнаруживает ошибку в любом из потоков, он посылает пакет
'RELAY_END' (если возможно) и немедленно закрывает этот поток.

6.4. Удаленный поиск имени хоста.


Для нахождения адреса, асоциированного с именем хоста, OP посылает пакет
RELAY_RESOLVE, содержащий имя хоста, которое должно быть распознано. (Для
обратного просмотра, OP посылает пакет RELAY_RESOLVE содержащий in-addr.arpa
адрес.) OR отвечает пакетом RELAY_RESOLVED, содержащим байт статуса и любое
число ответов. Каждый ответ представлен в следующей форме:
Тип (1 байт)
Длина (1 байт)
Значение (переменной длины)
TTL (4 байта)

"Длина" это длина поля "значение".
"Тип" один из:

0x00 — Имя хоста
0x04 — IPv4 адрес
0x06 — IPv6 адрес
0xF0 — Ошибка, транзитная
0xF1 — Ошибка, нетранзитная


Если любой ответ имеет тип "Ошибка", никакие другие ответы не могут быть
получены.


Пакет RELAY_RESOLVE должен иметь ненулевой, отличный от испльзуемых
streamID; соответствующий пакет RELAY_RESOLVED должен использовать тот же
самый streamID. В реальности OR не создает никаких потоков в процессе
распознавания имени.

7. Управление потоком данных.


7.1. Link throttling (Не перевел. Просто не понимаю, о чем речь.)


Each node should do appropriate bandwidth throttling to keep its
user happy.

Communicants rely on TCP's default flow control to push back when they
stop reading.

7.2. Заполнение канала связи.


Заполнение канала связи может быть достигнуто посыланием пакетов PADDING
по соединению; пакеты типа "DROP" могут быть использованы для удаленного
заполнения.

В настоящее время узлы не нуждаются ни в каком типе заполнения или
фиктивного трафика. Так как заполение не защищает от мощных атак и слишком
повышает требования к полосе пропускания узлов, мы планируем не использовать
заполнение, пока его плюсы и минусы не будут лучше изучены.

7.3. Управление передачей данных на уровне схемы.


Для управления использованием полосы пропускания схемы, каждый OR
отслеживает два "окна", показывающих, сколько пакетов RELAY_DATA
он может создать (упаковать для отправки), и как много пакетов RELAY_DATA
ожидают обработки (принято для локальных потоков). Эти ограничения не
применяются для пакетов, которые OR принимает от одного хоста и передает
другому.

Значение каждого "окна" изначально устанавливается в 1000 пакетов данных
для обоих направлений (пакеты, не содержащие данных, не влияют на "окно").
Когда OR хочет отправить больше пакетов, он посылает пакет RELAY_SENDME
в направлении OP, с нулевым StreamID. Когда OR получает пакет RELAY_SENDME c
с нулевым streamID, он увеличивает свое окно упаковки.

Каждый из этих пакетов увеличивает соответствующее окно на 100.

OP действует аналогично, за исключением того, что он должен отслеживать окно
упаковки и окно доставки для кадого OR в схеме.

OR или OP посылает пакеты для увеличения своего окна доставки, когда значение
соответствующего окна падает ниже определенного уровня (900).

Как только значение окна упаковки достигает "0", OR или OP прекращают чтение
из соответствующего TCP соединения для всехпотоков в соотетствующей схеме, и
не посылают больше пакетов RELAY_DATA до тех пор пока не получат пакет
RELAY_SENDME.

[этот материал плохо сформулирован; копия в секции дизайна Тора -RD]


7.4. Управление передачей данных на уровне потоков.


Краевой узел использует пакеты RELAY_SENDME для управления сквозным потоком
данных для отдельных соединений в схеме. Подобно тому как при управлении на
уровне схемы краевые узлы начинают с окном пакетов (500) на поток и
увеличивают окно на фиксированное значение (50) после получения пакета
RELAY_SENDME. Краевые узлы инициируют пакеты RELAY_SENDME при выполнении
одновременно двух условий: a) окно <= 450, и b) менее чем 10 пакетов ожидают
отправки.

A.1. Различия между спецификацией и приложениями.


– Текущая спецификация требует. чтобы все ORы имели IPv4 адреса, но позволяет

серверам выходить на IPv6 адреса, распознавать их, и объявлять IPv6 адреса
в их политиках выхода. Текущее исполнение вообще не имеет никакой поддержки
адресов IPv6.