СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

| сохранено

H Torrent/uTP — о протоколе и самодельных DPI в черновиках Recovery Mode

В 2009 году появился Micro Transport Protocol, сокращённо — uTP, можно ознакомится тут.
Суть задумки в том, чтобы не полагаться на TCP Congestion Control, которым под виндой рулить весьма проблематично, а самим управлять загрузкой канала.
uTP выявил много узких мест как у провайдеров так и у пользователей: ещё вчера прекрасно работающие роутеры превратились в тыкву. А некоторые пользователи обнаружили что торренты качаются на все 100 мегабит, не зависимо от тарифа.
image

Также провайдерам намного сложнее блокировать передачу данных через μTP благодаря отсутствию строгих, формализованных отличий UDP пакетов обычного трафика (формируемого, к примеру, сетевыми играми) от трафика, формируемого протоколом μTP, в отличие от TCP пакетов, по содержанию полей которых можно делать вывод об их принадлежности к p2p-трафику.

https://ru.wikipedia.org/wiki/ΜTorrent
image


Как не правильно блокировать можно почитать тут: geektimes.ru/post/243305/
и немного ниже :)

Жизнь с uTP


Слухи, сплетни, домыслы
В адрес авторов uTP звучала масса упрёков в изобретении TCP с нуля и хождении по всем граблям, в том что они не взяли уже готовые протоколы, и в том что теперь придётся обновляться и расширятся.
С точки зрения разработчиков — выбора особо не было: TCP все провайдеры шейпят и душат, для управления всеми аспектами работы tcp протокола в винде нужны права администратора и скорее всего свой драйвер, многие другие протоколы которые ходят поверх IP (tcp/udp/gre/udplite/...) вообще провайдерами фильтруются и в винде их так просто не реализовать.
Потому просто взяли и сделали поверх UDP.

Это решение подкосило многие домашние мыльницы и некоторых провайдеров.
Количество трансляций в NAT роутеров стало очень быстро расти.
Для TCP — NAT знает когда соединение установлено и когда оно завершено, а для UDP понятие соединений отсутствует в принципе, поэтому обычно применяются таймеры для удаления старых сессий.

Другим побочным эффектом явилось то, что uTorrent запрашивал больше трафика чем позволял тарифный план провайдера, и от этого страдали даже те провайдеры у которых шейпер был настроен правильно: на хомячка из интернета прилетало ощутимо больше его тарифного плана и этот излишек дропался шейпером. Провайдеры несли финансовые потери от такого DDoS хомяка на самого себя.
Авторы uTorrent позже всё таки научились правильно подстраиваться под канал, но их эксперименты стоили нервов и денег.

Ещё одним неприятным моментом в экспериментах с uTP на начальных этапах было то, что он генерировал большую пакетную нагрузку, отправляя множество мелких UDP пакетов. Позднее авторы научились заполнять пакеты с данными целиком.
Повышение пакетрейта губительно сказывается на WiFi и прочих радиолинках.

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


Протокол uTP


Документация на английском

Версия 0

Начиная с uTorrent 1.8
typedef struct utp_pkt_s { 	/* offset - PacketFormat */
	uint32_t	connid;		/* 00 connection ID */
	uint32_t	tv_sec;		/* 04  */
	uint32_t	tv_usec;	/* 08  */
	uint32_t	reply_micro;	/* 12  */
	uint8_t	windowsize;	/* 16 receive window size in PACKET_SIZE chunks */
	uint8_t	ext;		/* 17 Type of the first extension header */
	uint8_t	flags;		/* 18 Flags */
	uint16_t	seq_nr;		/* 19 Sequence number */
	uint16_t	ack_nr;		/* 21 Acknowledgment number */
								/* 23 ext/data */
} utp_pkt_t, *utp_pkt_p; /* 23 bytes */


Версия 1

Начиная с uTorrent 2.0
typedef struct utp_pkt_v1_s { 	/* offset - PacketFormatV1 */
	uint8_t	version:4;	/* 00 protocol version */
	uint8_t	type:4;		/* 00 type (formerly flags) */
	uint8_t	ext;		/* 01 Type of the first extension header */
	uint16_t	connid;		/* 02 connection ID */
	uint32_t	tv_usec;	/* 04  */
	uint32_t	reply_micro;	/* 08  */
	uint32_t	windowsize;	/* 12 receive window size in bytes */
	uint16_t	seq_nr;		/* 16 Sequence number */
	uint16_t	ack_nr;		/* 18 Acknowledgment number */
								/* 20 ext/data */
} utp_pkt_v1_t, *utp_pkt_v1_p; /* 20 bytes */


Типы пакетов

enum {
	ST_DATA		= 0,	/* Data packet. */
	ST_FIN		= 1,	/* Finalize the connection. This is the last packet. */
	ST_STATE		= 2,	/* State packet. Used to transmit an ACK with no data. */
	ST_RESET		= 3,	/* Terminate connection forcefully. */
	ST_SYN		= 4,	/* Connect SYN. */
	ST_NUM_STATES	/* Used for bounds checking. */
};


flags из версии 0 превратился в type в версии 1, типы пакетов перечислены выше.
Сначала отправляется SYN на него приходит ответ STATE или RESET.
Завершается соединение на FIN или RESET.
DATA и STATE используются при передаче данных.

connid — идентификатор соединения. В TCP его роль выполняет номер порта (вернее их пара). Номер соединения у двух хостов всегда различается на единицу.
Вообще довольно запутанная и странная схема установления соединения:
>> SYN: connid=34 — запрос на установление соединения
<< STATE: connid=34 — подтверждение
>> DATA: connid=35 — передача данных
<< STATE: connid=34 — подтверждение передачи данных
Те инициатор соединения задаёт номер соединения в первом пакете а в дальнейшем использует номер на единицу больше.

seq_nr и ack_nr — используется чтобы ориентироваться в потоке в случае потери или реордеринга (когда первый отправленный пакет приходит после второго).

Остальные поля меня интересовали мало, хотя для ext опций валидацию написал.

ext — если есть дополнительные расширения/данные в пакете после заголовка, аналог IP otions.

tv_usec, reply_micro, windowsize — относятся к информации необходимой для управления скоростью передачи.

Шифрование

Если кто то ещё читает и не уснул то мог заметить что шифрования нет.
Его действительно нет!
Не потому что описание не полное а потому что оно реализовано несколькими уровнями выше и uTP никак не касается.
uTP заголовки никак не шифруются.

Заход 1: uTPControl


Из спортивного интереса я решил попробовать написать нечто что сможет аккуратно выключать uTP у юзеров чей трафик проходит через роутер с моей программой.
В начале я пробовал слать RESET с виндовой машины, перебирая connid, но это явно не работало, не совпадали адреса отправителя пакета и seq_nr, ack_nr. Это был первый неудачный опыт.

uTPControl — была первая более менее программа которую я написал под FreeBSD.
uTPControl — block uTP torrent proto
uTP протокол был любезно предоставлен в libuTP всему интернету :)

Работало uTPControl чрезвычайно просто: программа создавала divert сокет и бесконечно читала из него пакеты в цикле. Если это был UDP пакет, в котором ВОЗМОЖНО uTP версии 0 или 1 и тип пакета не FIN и не RESET то генерируем UDP-uTP RESET пакет и отправляем обратно.
Те клиент пытался установить связь и сразу получал RESET — те его вроде как отключил тот к кому он подключался.

Минусов у этого решения было два:
1. Ложные срабатывания: иногда пакеты от некоторых онлайн игр были прямо как uTP и им улетал ответ, видимо у игр от этого срывало крышу и юзеры жаловались.

2. Низкая производительность: все пакеты из ядра копировались в юзерспейс и там в один поток обрабатывались.
В один поток на CoreDuo Е5300 под FreeBSD 7.3 выдавало до 100 тысяч пакетов RESET в секунду.
Один поток можно было обойти запустив несколько экземпляров и как то раскидав через ipfw пакеты между ними.

В виду этих фатальных недостатков интерес со стороны сообщества пропал и я её забросил.

Был человек который превратил это в netgraph ноду, но ложные срабатывания это не вылечило.

Заход 2: ng_utp


uTP (udp torrent) netgraph node
Прошло полтора года, я успел покопаться в ядре FreeBSD и netgraph, лучше узнать как работает сеть и пришла мысль: uTP имеет состояния аналогичные TCP, значит чтобы его 100% определять нужно эти состояния отслеживать.
Заодно я ещё раз заглянул в libuTP и получше посмотрел за что можно зацепится.
За сигнатуры я решил не цепляться, это плохой путь с массой ложных срабатываний и мучениями по их поддержанию — авторы уже несколько раз меняли начальные константы и сигнатуры «протухали» у тех кто их использовал.
Идеальный вариант это свой «клиент» с референсной реализацией uTP который будет выстраивать таблицу соединений на основе пролетающих через него пакетов и уже по данным этой таблицы что то можно делать.

В итоге получилась netgraph нода, которую можно подключать к L2 хукам типа ng_ether или L3 хукам, например ng_ipfw. В первом случае можно вообще сделать прозрачный эзернет мост из двух сетевух (не обязательно физических). Ещё можно просто поставить тазик и зеркалировать на него весь траф, но я сейчас не уверен в работоспособности такой схемы.

Результатов замеров производительности я не сохранил.
Однако нода без проблем параллелится по ядрам, может выполнятся как контексте ISR так и потоками netgraph, взаимные блокировки потоков сведены к минимуму.

В случае L2: мультикаст и броадкаст пакеты пролетают сразу насквозь, тэгированный трафик обрабатывается как обычный. QinQ не делал, добавить не сложно.
Обрабатываются только IPv4 пакеты UDP, не адресованные и не отправленные с 127/8, не являющиеся броадкастом или мультикастом, и ещё немного проверок что это не мусор а то что нужно, включая опциональную проверку контрольной суммы IP и UDP.

Далее проверяется что содержимое UDP пакета похоже на uTP.
Если содержимое похоже то ищем в таблице состояний запись для данной пары хостов: src ip:port / dst ip:port, если не находим то меняем местами и ищем ещё раз. Не нашли и пакет не FIN или RESET — добавляем. (подозреваю что на линухе с conntrack было бы чуть проще, а тут пришлось самому писать)
Теперь есть элемент который хранит все uTP соединения между двумя хостами или то что похоже на них.
Ищем там connid, если не нашли то connid+-1, если опять нет — добавляем.

Теперь у нас есть куда писать данные по конкретному uTP соединению.
Пишем: время последнего обновления, время последней отправки запроса и получения ответа, считаем запросы и ответы, запоминаем какие типы пакетов встречались.
seq_nr и ack_nr можно было бы тоже запоминать и анализировать но и без них достаточно точно получается определять.
Старые записи удаляются автоматически.

Теперь мы точно знаем что хосты установили uTP соединения, знаем сколько каждый отправил пакетов и получил ответов, знаем их идентификаторы, можно действовать.

Действовать имеет смысл только для DATA и STATE пакетов.

Что можно сделать:
  • ничего, просто мониторинг: есть счётчики по хостам, соединениями, сами таблицы с хостами...
  • дропать пакеты с uTP: src ip:port + dst ip:port есть
  • помечать пакеты: на L2 в VLAN заголовке PCP для тегированных пакетов 802.1P
  • помечать пакеты: на L3 в IP заголовке — ip_tos — DSCP
  • отправлять uTP — RST пакеты

Чтобы сгенерировать RST пакет все данные есть: src ip:port + dst ip:port, pkt_ver, connid, ack_nr, seq_nr.
Фактически у IP/UDP пакета заменяются данные, пересчитывается контрольная сумма и от отправляется дальше.

Подробнее про счётчики — по ссылке, там описание, если его мало есть код :)

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

Сигнатуры


И эти люди продают мне интернет?!!!
— возникает у меня периодически к голове, когда я читаю провайдерский форум. :)

Провайдеры искали способ как быстро нормализовать работу сети и решили фильтровать uTP по сигнатурам пакетов, добавляя их то в ACL коммутаторов то в фаервол BSD/Linux роутера.
«Странность» ситуации в том, что сигнатуры искали анализируя пакеты.
Притом, что код libuTP был открыт 16 мая 2010 года — через 4 месяца после выхода uTorrent 2.0 где uTP был включён.

Спустя пару месяцев «живительные» сигнатуры путём нечеловеческих усилий по анализу пакетов были получены.
Ещё через некоторое время авторы поменяли пару незначительных для протокола начальных значений в SYN пакете и что то рандомизировали (connid, seq_nr — больше не смогли) :)


После того как ng_utp был написан стало понятно что проверять корректность работы с помощью tcpdump без правильных сигнатур мягко говоря не удобно — слишком много лишнего приходилось пробегать глазами.
Я ещё раз пробежался по коду libuTP и получились такие сигнатуры, сейчас может быть они уже устарели.

Версия 0

SYN

syn — 14 bytes

'udp[17] = 2 and udp[18] = 4 and udp[21:2] = 0 and udp[23] = 0 and udp[24] = 8 and udp[25:4] = 0 and udp[29:4] = 0'

41 = udp hdr len (8) + upd pkt data len

upd header included:
'(udp[4:2] = 41 and udp[25:2] = 0x0204 and udp[29:4] = 0x00000008 and udp[33:4] = 0 and udp[37:4] = 0)'

— последнее это то что можно скармливать в tcpdump, отличается от первой смещениями и тем что константы объединены чтобы сравнений было меньше. Первая больше для самообразования.

RESET

rst — 4 bytes

'udp[17] = 0 and udp[18] = 3'

31 = udp hdr len (8) + upd pkt data len

upd header included:
'(udp[4:2] = 31 and udp[25:2] = 0x0003)'

Версия 1

SYN

syn — 14 bytes

'udp[0] & 0x0f = 1 and udp[0] & 0xf0 = 0x40 and udp[1] = 2 and udp[18:2] = 0 and udp[20] = 0 and udp[21] = 8 and udp[22:4] = 0 and udp[26:4] = 0'

(udp[0] & 0x0f = 1 and udp[0] & 0xf0 = 0x40) => udp[0] = 0x41

38 = udp hdr len (8) + upd pkt data len

upd header included:
'(udp[4:2] = 38 and udp[8:2] = 0x4102 and udp[26:4] = 0x00000008 and udp[30:4] = 0 and udp[34:4] = 0)'

RESET

rst — 4 bytes
'udp[0] & 0x0f = 1 and udp[0] & 0xf0 = 0x30 and udp[1] = 0'
(udp[0] & 0x0f = 1 and udp[0] & 0xf0 = 0x30) => udp[0] = 0x31)
28 = udp hdr len (8) + upd pkt data len

upd header included:
'(udp[4:2] = 28 and udp[8:2] = 0x3100)'

Обнаружение фильтрации


Проще всего, используя описание протокола, реализовать простенький клиент, который будет устанавливать соединение и пытаться отправлять данные.
По сути нужно симулировать установление соединения, и дальше пытаться слать DATA и STATE пакеты в ответ с ext типа ACK.
Дальше один клиент запускается в интернете, другой у себя и смотрим теряются ли пакеты в 100% случаев или может RESET приходят.
Сходным образом при использовании yota некоторые пакеты из l2tp на завершающем этапе согласования пропадают в 100% случаев. Так было ещё в сентябре.

Заключение


1. То что написано в вики на русском — полнейший бред: uTP имеет достаточно чёткие сигнатуры и легко ловится DPI.
Более того, ловить сигнатуры в TCP ощутимо сложнее, поскольку для гарантированного обнаружения нужно уметь собирать несколько пакетов вместе и уже потом проверять содержимое: клиент может передавать данные по одному байту.
Авторы uTP либо не ставили себе цель сделать протокол без сигнатур либо даже не приблизись к цели.
(На мой взгляд в начале не ставили, а потом было уже поздно и рандомизация отдельных полей не помогает).
Вики на английском более адекватна.

2. Производители различных DPI уже давно добавили сигнатуры для uTP, вряд ли им это было трудно сделать.

3. В порядке слухов: для линукса вроде бы тоже есть ядерная версия для работы с uTP протоколом на базе ipp2p а может уже отдельно. Но в паблик её не выкладывали. С середины 2012 года.

4. Для IPv6 код не писал, на всякий случай ;)

5. uTP не лучше TCP для передачи данных, вся проблема в том, что TCP можно хоть как то управлять из приложения только на BSD/Linux — setsockopt(..., IPPROTO_TCP, TCP_CONGESTION,...) — основное что требуется, хотя и там более тонкие параметры congestion control для отдельных сокетов не настраиваются.
Говорить про оверхэд в 23/20 байт сейчас уже не актуально, HTTP/2.0 не сильно лучше.
Возможно с приходом кучи готовых либ для HTTP/2.0 торренты пустят и через него, скорее всего это вопрос времени.
+48
34402

комментарии (49)

0
Xlab ,  
4. Для IPv6 код не писал, на всякий случай ;)
Кстати, а что с IPv6?
0
Ivan_83 ,  
Ничего, пакеты пролетают насквозь без разбора и анализа, так же как и ARP в случае L2 или как TCP, GRE, UDPLite и прочие L4 протоколы.
Если с ipfw завернуть ipv6 — тоже ничего не будет: офсеты и размеры адресов не совпадают — добавится лишней работы процу и не более.
+6
qw1 ,  
Странно, что зашифрован не весь пакет.

Например, в DC++ зашифрован весь UDP-пакет с использованием RC4 и ключом является DHT ID пользователя, которому предназначен пакет. Начальный список ID получаем с bootstrap-сервера, далее, отправляя сообщения юзерам, в заголовке есть поле «кому» и «от кого», благодаря последнему юзеры узнают мой ID и могут шифровать отправляемые данные.

Схема идеальная для обхода блокировок, т.к. на firewall-е придётся держать таблицу соответствий IP+PORT↔DHT ID и расшифровывать каждый пакет.

К сожалению, в DC++ DHT не реализована передача контента по UDP — только поисковый трафик и служебная информация DHT-сети. Юзеры, нашедшие друг друга, для передачи кусков файлов устанавливают соединения по TCP с опциональным SSL.
0
Ivan_83 ,  
Ничего странного, если посмотреть на архитектуру uTorrent/libuTP.
У них уже есть обкатанный код для TCP, их не устраивала работа TCP, чтобы много не писать самим и другие чтобы по быстрее освоили новый протокол сделали обёртку над сетевыми функциями, и получилось что чуть выше libuTP в приложении нет разницы между uTP и TCP.
Те для шифрования uTP им бы пришлось делать отдельное шифрование или менять код шифрования от TCP.

Дырок к реализации libuTP я не нашёл, всё проверяется. «Усиление» (ответ больше запроса) — тоже отсутствует.

Я не понял, в DC++ в заголовке пакета «DHT ID пользователя» — кому отправляется в расшифрованном виде?
Или там идут для идента пользователей в открытом виде а дальше всё зашифрованно используя один из идентов в качестве ключа?

Сходу могу сказать что:
— расшифровывать каждый отдельный пакет целиком не нужно, достаточно несколько блоков RC4 из начала.
— это мало кому интересно — трафика мало и никого не напрягает, разве что копирастов :)
+1
qw1 ,   * (был изменён)
Я не понял, в DC++ в заголовке пакета «DHT ID пользователя» — кому отправляется в расшифрованном виде?
Или там идут для идента пользователей в открытом виде а дальше всё зашифрованно используя один из идентов в качестве ключа?


Каждый пакет (в расшифрованном виде) содержит в заголовке поля «кому», «от кого» и какую-то полезную нагрузку. Пакет шифруется весь полностью идентификатором получателя. Получатель всегда имеет возможность расшифровать пакет (т.к. свой ID он знает).

Сходу могу сказать что:
— расшифровывать каждый отдельный пакет целиком не нужно, достаточно несколько блоков RC4 из начала.


Нужно расшифровывать и парсить пакеты, чтобы пополнять мапу IP+PORT↔ID.
Например, я запросил поиск по сети, соседи мне скинули IP+PORT+ID юзеров, у которых есть контент.
firewall должен расшифровать промежуточный результат поиска и занести данные в свою мапу, чтобы расшифровывать и блокировать пакеты, отправляемые к ним.

Но на самом деле firewall-у нужно получить ID DHT-соседей, с которыми я начинаю работать c сетью, которые я получаю с bootstrap-сервера. Если firewall пропустил момент бутстрапа, он уже не может расшифровывать пакеты. В случае bootstrap по HTTP, как-то можно его распарсить (хотя парсить XML на роутере та ещё работка), а если SSL — то только блокировать известные bootstrap-сервера (их список как-то узнавать и поддерживать).
0
qw1 ,  
— расшифровывать каждый отдельный пакет целиком не нужно, достаточно несколько блоков RC4 из начала.

Там ещё есть сюрприз: под RC4 пакет пожат zlib ))
+1
SaveTheRbtz ,  
Ну, я бы не сказал, что такое «шифрование» особо полезно, ибо ключ общеизвестен, rc4 нынче не особо безопасен, да и как любой другой поточный шифр он требует уникальных nonces для каждого запроса. Однако от шейпинга оно защищает, да.

В идеале каждая DHT-нода должна должна на старте генерить private/public ключи и использовать public часть как свой DHT ID. Тогда любая нода сможет шифровать для любой ноды.
0
Ivan_83 ,  
Оно же для обфускации только используется, даже сами ключи шифрования не являются тайной.
Для вскрытия RC4 нужно насобирать пакетов а потом их анализировать.

С ключами есть одна проблема: публичные ключи нужно как то распространять.
0
SaveTheRbtz ,  
Для обфускации можно использовать и что-то попроще — arcfour конечно быстрый[1], но и простого XOR(payload, node_id) хватило бы для обфускации =)

Использование публичного ключа в качестве DHT node id как раз и решает проблему дистрибуции ключей.
В случае с BEP-5[2] DHT node id имеет размер 160 бит (длинна sha1 хеша), что конечно весьма мало, однако если использовать Elliptic Curve ключи, то на близжайшие несколько лет хватить должно.

[1] openssl speed rc4
/usr/local/Cellar/openssl/1.0.1j_1/bin/openssl speed rc4
Doing rc4 for 3s on 16 size blocks: 75875715 rc4's in 2.99s
Doing rc4 for 3s on 64 size blocks: 19906494 rc4's in 3.00s
Doing rc4 for 3s on 256 size blocks: 5131209 rc4's in 3.00s
Doing rc4 for 3s on 1024 size blocks: 1313093 rc4's in 3.00s
Doing rc4 for 3s on 8192 size blocks: 163742 rc4's in 3.00s
OpenSSL 1.0.1j 15 Oct 2014
built on: Sun Dec  7 02:14:31 GMT 2014
options:bn(64,64) rc4(ptr,char) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: clang -fPIC -fno-common -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -arch x86_64 -O3 -DL_ENDIAN -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
rc4             406023.89k   424671.87k   437863.17k   448202.41k   447124.82k

[2] www.bittorrent.org/beps/bep_0005.html
0
Ivan_83 ,  
Простой XOR не сильно быстрее и сильно меньше прячет. Ещё и ломается практически на автомате.
Нынче в моде ChaCha и XChaCha, пашут оч быстро, просты в реализации и пока ничего плохого про них не нашли.

Минимальный размер параметров для ECDSA от NIST — 112 бит.
Тут вот табличка есть: длинна ключа ECDSA и эуквивалент для RSA: tools.ietf.org/html/rfc4492
160 бит будет круче, чем 3072 для RSA.

Жаль что 256 бит туда не влезут, можно было бы использовать Ed25519.
0
SaveTheRbtz ,  
Тут не могу не поспорить: потоковое шифрование известным ключём прячет ровно столькоже сколько XOR с известным ключём (по определению потокового шифрования =))
По производительности [0] XOR на том же железе быстрее почти в 20 раз быстрее.

ПС. 160 бит ECC ключ чуть менее стоек, чем RSA1024[1], который на данный момент официально не сломан, но применять уже не рекомендуют.
ППС. ECDSA и Ed25519 — это про цифровые подписи, Вы наверное имели в виду Curve25519.
[0] linux 3.19rc5 dmesg
...
xor: using function: generic_sse (7596.000 MB/sec)
...

[1] rfc4492
                    Symmetric  |   ECC   |  DH/DSA/RSA
                   ------------+---------+-------------
                        80     |   163   |     1024
                       112     |   233   |     2048
                       128     |   283   |     3072
                       192     |   409   |     7680
                       256     |   571   |    15360

                  Table 1: Comparable Key Sizes (in bits)
0
Ivan_83 ,  
Взять к примеру ChaCha, минимальный ключ — 128 бит, из него генерируется ключевой поток, 512 бит — размер блока, из одного ключа таких блоков получается 2^64 штук. (при желании больше, там же nonce есть)
Когда ключевой поток XOR-ится с данными то это далеко не тоже самое что ксорить их с ключём: в случае когда ксорим с одним и тем же ключём достаточно знать хотя бы немного открытого текста в произвольных местах чтобы как минимум частично восстановить ещё неизвестные данные.

ChaCha тоже имеет реализации на SSE/AVX.
Она медленнее обычного XOR и не в 20 раз а по больше, по идее, но и узким местом врядли станет.

Вот «правильная» табличка для правильных параметров: «SEC 2: Recommended Elliptic Curve Domain Parameters», страница 5.
Применять можно хоть 112 хоть вообще 64 бита, весь вопрос лишь в том, чтобы время применения были меньше времени ломки.

ECDSA — это же ядро с этими же параметрами используется и для ECDH — генерция совместного закрытого ключа на основе публичных ключей.
0
SaveTheRbtz ,   * (был изменён)
Мы говорим о случае когда ключ известен (это DHT ID), nonce по определению известен, либо неявно (захардкожен внтри программы (lol, PS3 [0])), либо явно (передаётся внутри самого сообщения). На основе этой информации можно расшифровать любой пакет, неважно это ChaCha/Salsa/RC4 или простой XOR. Так зачем, как говорится, платить больше? =)

ПС. Документу на который вы ссылаетесть[1] уже как почти 15 лет. 5 лет назад он был перевыпущен[2]. Там минимальный размер ключа для Koblitz-кривых — 163 бита, для Prime-field — 192.

[0] www.schneier.com/blog/archives/2011/01/sony_ps3_securi.html
[1] SEC 2: Recommended Elliptic Curve Domain Parameters (Version 1.0)
[2] SEC 2: Recommended Elliptic Curve Domain Parameters (Version 2.0)
0
qw1 ,  
Так зачем, как говорится, платить больше? =)

Чтобы шейперам жизнь мёдом не казалась. Чтобы максимально усложнить реализацию на сетевом оборудовании, оставив сложность допустимой для десктопных клиентов.
0
Ivan_83 ,  
Ещё раз: для XOR даже я смогу написать «отгадыватель» пароля, и будет оно работать в ядре потребляя минимум.
В случае XOR перебор 2^128 или сколько там будет ключ, — не потребуется.

Их рекомендации касаются применения для всяких документов и пр где нужно гарантировать что ещё минимум ХХ лет это не подделают. Где то в этих же документах или соседних даже табличка есть с годами.
В случае DHT, где закрытый ключ генерируется каждый раз во время старта и не защищает ничего ценного достаточно и 128/160 бит, даже 112 бит.
+2
DoMoVoY ,   * (был изменён)
Используем собственные сигнатуры и фильтруем через u32 (выявили по первым пакетам установления соединения с помощью tcpdump). UDP составляет всего 18% от общего трафика. Жалоб на проблемы с играми или другими протоколами не наблюдаем уже несколько лет.
В цепочке для UDP трафика делаем:
8439M  405G DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            u32 "0x24&0xffffffff=0x0&&0x28&0xffffffff=0x100000"
3247M  156G DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            u32 "0x1a&0xffff=0x4100&&0x24&0xffffffff=0x0&&0x28&0xffffffff=0x0"
3721M  349G DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            u32 "0x3c&0xffffffff=0x65313a71&&0x40&0xffffffff=0x343a7069&&0x44&0xffffffff=0x6e67313a"
 562M   32G DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            u32 "0x24&0xffffffff=0x0&&0x28&0xffffffff=0x380000"
1067M   62G DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            u32 "0x1a&0xffff=0x4102&&0x24&0xffffffff=0x7fffffff&&0x28&0xffffffff=0xf000"

При этом тачка лопатит 7мегапакетов в ЧНН.
+1
SaveTheRbtz ,  
Говорят[1] xt_bpf/cls_bpf удобнее для этого дела. Особенно если уже есть готорые фильтры для tcpdump'а. Впрочем, если вы уже на u32 всё написали, то переделывать смысла особо нет.

[1] blog.cloudflare.com/bpf-the-forgotten-bytecode/
0
DoMoVoY ,  
была идея переписать на BPF, но только в целях повысить производительность фаервола. А, т.к. u32 в нашем случае не создает проблем с производительностью, то переписыванием не занимались. BPF фильтры использовали в FreeBSD на старых сегментах.
+5
+6 –1
Meklon ,  
Вопрос с точки зрения пользователя. А нам что делать? У меня есть чувство, что за мной следят и облучают через зеркала провайдер режет исходящий торрент-трафик. Хочется инструмент для диагностики этих вещей у провайдера, чтобы лучше выбирать. Кроме того, были ситуации, когда пиров много, а подключается максимум к 3-4 и скорость невелика. Я конечно понимаю, что оверселлинг, но плачу я тоже не для формальной циферки в тарифе. Обещали 75 мегабит — дайте возможность использовать.
+2
Ivan_83 ,  
Наваять програмку для этого дела, одну поставить где то на хостинге в инете, другую у себя запускать.
Или засетапить там впн сервер и пробовать через него.

Только это не покажет если у ваших пиров фильтрация.
Если бы с вашей стороны фильтровали то скорее всего оно бы резало 100% пиров.

В любом случае я не готов вот так сесть и на этой неделе написать, потестить, потом выкатить в паблик, разместить у себя «серверную» часть.
Да ещё и гуй красивый под винду делать %)

Может кто то сделает сам раньше, описание достаточное.
Я вижу это как некоторую серверную часть работающую демоном, к которой цепляешься по tcp, она скидывает номер порта для юдп конекта, и дальше начинаются пробы отправки uTP пакетов симулирующих установление связи, по TCP скидываются результаты: дошёл очередной uTP пакет или нет.
Вероятно это всё можно как то и на джаве в пределах браузера сделать а на сервере на пхп, но я эти языки знаю слишком поверхностно.
0
Meklon ,  
Я вообще линуксоид) но проблема фильтрации вещь актуальная для многих. Было бы круто иметь тестовый сервер с веб-мордой. Подключился к тестовому серверу, встал на закачку/раздачу. Получил от того же сервера результат тестирования
0
Ivan_83 ,  
Консольную сделать проще :)
Linux/BSD/винда — особой разницы нет для такой ерунды.
0
DoMoVoY ,  
Режет именно torrent или uTP для торрента? Какой именно протокол Вы хотите проверить? Сам TCP BitTorent ничего плохого провайдеру не несет и смысла блокировать его нет.
0
Meklon ,  
TCP. Несколько лет назад спокойно раздавалось терабайтами. Сейчас отдача на всех клиентах на Windows и Linux близка к нулю. Даже на популярных раздачах вроде дистрибутивов Linux.
0
leotsarev ,   * (был изменён)
При белом IP?
0
Meklon ,  
Да. IP белый и фиксированный
0
Semenych ,  
Я как пользователь поступаю очень просто — у меня в подъезде 7 провайдеров. Если один меня не устраивает (к примеру заявленная скорость 40Мб а реально торенты качаются медленее), я беру следующего провайдера из списка.
0
Meklon ,  
Вот я тоже с Ростелекома планирую слезть) Мне хватило 1.5 часов на ожидание и получаса на оформление простыни на получение белого адреса. По-другому у этих динозавров никак. Еще и бумажку с печатью и адресом выдали)
0
Aingis ,  
Адреса IPv4 кончаются, будет только хуже. Хотя всё равно бюрократия адова.
0
Meklon ,  
Так у всех белые. Просто у них дебильная система рвать линк каждый день и тут же выдавать новый адрес. DHCP у них даже на несколько секунд не резервирует адрес. Нафига так делать? Я в МТС с динамическим ip адрес сохрянял месяцами до отключения света в районе надолго.
0
AKashta ,  
А uTP версии 0 до сих пор используетс​я?
–1
Ivan_83 ,  
В теории да, в клиентах от 1.8 до 2.0 (исключительно).
Некоторые до сих пор на 1.8 зачем то сидят.
+1
Gray_Wolf ,  
1.8.2 считается одним из самых стабильных версий uTorrent.
К сожаление версии 2+ начинают довольно странно себя вести при 500+ торрентов стоящих на раздаче.
+3
DoMoVoY ,  
Затем, что в тех версиях еще не было рекламы
+1
SaveTheRbtz ,  
Статистика по большому Bittorrent трекеру России.

Типы клиентов
uTorrent        45.91%
Transmission    41.15%
libTorrent      3.53%
BitTorrent      1.88%
uTorrent/Mac    1.65%
MediaGet2       1.35%
Azureus         1%
FakeUT          0.6%
Deluge          0.46%
qBittorrent     0.4%
TorrentStream   0.39%
ktorrent        0.37%
BitSpirit       0.24%
BitComet        0.2%
Tixati          0.19%


Версии uTorrent
3420 (35702)    39.62%
3420 (37754)    16.65%
3420 (37951)    2.73%
3300 (29625)    2.44%
3230 (28705)    2.14%
3420 (37594)    1.95%
1820 (15357)    1.94%
2210 (25302)    1.69%

0
ValdikSS ,  
Ого! Не думал, что так много Transmission.
0
Meklon ,  
Тоже удивился. Хотя сам сижу на Ktorrent. Привык.
+1
grumbler66rus ,  
Transmission является клиентом по умолчанию в Ubuntu и Altlinux, а они наиболее популярны для домашних компьютеров (последний — второй по популярности среди русскоязычных пользователей). Плюс transmission-daemon наиболее удобен для использования на серверах.
0
Ivan_83 ,  
Винда сдаёт позиции :)
+1
Borz ,  
или качать начинают не с компов, а с диск-массивов/роутеров и иже с ними
0
SaveTheRbtz ,  
К сожалению нет =(
Статистика по ОС
Windows    90.66%
Android    3.39%
Macintosh  3.22%
Linux      1.57%
iOS        0.92%

Судя по всему, пользователи transmission раздают МНОГО больше торрентов (seedbox'ы?)
0
Andrii_Z ,  
А если клиент использует шифрование, то как передаются пакетьі?
0
alklim ,  
Шифруется нагрузка.
Заголовки пакетов, по которым торрент-клиенты определяют uTP это трафик или нет, не шифруются.
Т.е. любой анализатор uTP трафик спокойно вычислит, хоть шифрованный он, хоть нет.
0
Andrii_Z ,  
Но вьіборочно заблокировать конкретньій контент не вьійдет, или будут рубить весь торрент-трафик, или никакой?
0
alklim ,  
Если трафик не шифрованный, то info_hash можно легко поймать. Но кто и зачем это будет делать? Операторы ведь шейпят трафик чтобы его стало меньше в канале, им до лампочки что именно там передается, рубят всё подряд.

Если трафик шифрованный, то тут незнаю, может быть и можно info_hash вычислить. Автор вот выше тут вроде писал что RC4 дешифруется по нескольким пакетам.
0
Ivan_83 ,  
Для ответа на этот вопрос нужно смотреть как именно там реализуется шифрование.
Так же нужно смотреть все механизмы получения списка пиров.

В целом, выборочно что то блокировать проблематично: много трафика лопатить, и нужно оперативно реагировать на изменения хэша раздачи, ведь достаточно в раздаче хоть что то поменять как меняется хэш целиком.
0
SaveTheRbtz ,  
Интересно, будут ли авторы torrent клиентов эксперементировать с QUIC[1]? Тогда шейпить Torrent траффик будет весьма не просто, особенно если torrent клиенты под Windows начнут делать bind(2) на порт 443.

[1] www.chromium.org/quic
0
grumbler66rus ,  
Сразу «глаз споткнулся»:
для управления всеми аспектами работы tcp протокола в винде не нужны права администратора и скорее всего свой драйвер

По смыслу «не» — лишняя.
0
grumbler66rus ,  
Спасибо за работу.

Ещё опечатки:
В TCP его роль выполняет норме порта

Проще всего используя описание протокола реализовать простенький клиент
— не хватает двух запятых вокруг «используя описание протокола».
Сходным образом при использовать yota
— наверное, должно быть «при использовании»