Разные peer_hash для одного сида в bb_bt_tracker

Started by sхс on 2024-03-15 14:08 — 10 replies, 2936 views

#1
Судя по логам при обновлении в торрент клиенте (реанонсировании) в announce.php отправляется сразу два запроса с разными info_hash
Spoiler content hidden.

где
2b4082f07990900337628740c35a3c79cc303eeb 20битный хэш торрента
e64ff0b2f1713848e03f7b77428467b252d3c9d8 32 битный хэш торрента обрезанный до 20бит

Из-за чего получаем количество сидов в два раза больше чем имеется.

Сначала подумал избавиться от дублей в announce.php добавив info_hash_v2 в генерацию peer_hash
$peer_hash = md5( $info_hash_hex . $info_hash_v2_hex . $passkey . $ip . $port);

Но как это сделать если инфо хэши приходят двумя запросами от торрент-клиента
#2
Причина отправки двух запросов клиентом
#3
Вы пытаетесь внедрить BitTorrent v2 в 2.1.5?

Посмотрите на source код announce.php в ветке 2.4.*, логика v2 анонсов не простая.
#4
Скорее в R600
Нет, вернее в базе храню info_hashv2, но регистрировать на трекере пока не могу. У меня поддерживаются форматы v1 и hybrid(v1+v2) от qbittorrent

Даже если нет поддержки v2, все равно обрезаный хэш v2 приходит от клиента

Я просто не нашел в коде новой версии движка как избавиться от дублей поэтому вывалил это

Если peer_hash формируется на основе одной из версий приходящей info_hash и тем самым порожадет дубли в базе, то не будет ли логичным включить оба info_hash в формирование peer_hash и не важно если какой-то из них будет пустым
#5
В общем я это исправил в announce.php таким кодом. Но это еще один запрос к базе....

$info_hash_hex = bin2hex($info_hash);
//....
$sql="SELECT info_hash, info_hash2 FROM bb_bt_torrents
WHERE HEX(info_hash) = '$info_hash_hex'
OR HEX(info_hash2) LIKE '$info_hash_hex%'
LIMIT 1";

$row_info = DB()->fetch_row($sql);

if(isset($row_info['info_hash']) AND isset($row_info['info_hash2'])) {
    $info_hash_hex = bin2hex($row_info['info_hash']).bin2hex($row_info['info_hash2']);
}

// Peer unique id
$peer_hash = md5(
    $info_hash_hex . $passkey . $ip . $port
);
#6
Вашу логику в коде не понял, но распишу как я избавлялся от дублей:
Если высылаются поочередно два инфо-хеша, мы записываем статистику в базу только одного запроса, так как они идентичны (тот же uploaded, downloaded, event и т.д.)
Я использую для этого переменную $hybrid_unrecord:
    if (!empty($row['info_hash']) && !empty($row['info_hash_v2'])) {
        $stat_protocol = match ($bb_cfg['tracker']['hybrid_stat_protocol']) {
            1 => $row['info_hash'],
            2 => substr($row['info_hash_v2'], 0, 20),
            default => $row['info_hash']
        };
        if ($info_hash !== $stat_protocol) {
            $hybrid_unrecord = true; // This allows us to announce only for one info-hash
        }
    }
Проверьте места где эта переменная используется.

Движок предусматривает по умолчанию запись статистики v1 запроса, версия меняется в config.php:
$bb_cfg['tracker'] = [
// ...
    'hybrid_stat_protocol' => 1, // For hybrid torrents there are two identical requests sent by clients, for counting stats we gotta choose one, you can change this to '2' in future, when v1 protocol is outdated
];

Другой же запрос в базу не записывается, но записывается в кеш.
С первого раза не понятно, понимаю, большое ветвление, но прочитайте код announce.php и попытайтесь вникнуть в логику.
#7
Логика такая: создается релиз и в базу в bb_bt_torrents вносится два значения info_hash и info_hash_v2 посредством функций
$info_hash = pack('H*', sha1(bencode($info)));
$info_hash2 = pack('H*', hash('sha256', bencode($info)));

а уже после смотрю в базу в bb_bt_tracker и вижу там два разных peer_hash на основе этих хэшей

    'hybrid_stat_protocol' => 1, // For hybrid torrents there are two identical requests sent by clients, for counting stats we gotta choose one, you can change this to '2' in future, when v1 protocol is outdated
    'disabled_v1_torrents' => false, // disallow registration of v1-only torrents, for future implementations where client will use v2 only and there won't be need for v1, thus relieving tracker
    'disabled_v2_torrents' => false // disallow registration of v2-only torrents
У меня сегодня выходной под пиво. Но попытаюсь понять.
Я так понял вы даете разрешение посредсвом конфига: либо то либо это.

А почему бы не реализовать распознование всех форматов, будь то 1,2 или гибрид и избавить рядового пользователя от этого конфига? Неизвестно когда v2 вступит в силу и вступит ли? Гибрид уже существует и им пользуются. v1 - еще не скоро от него откажутся, да и полного старых трекеров которые на нем.
#8
По поводу дублей не понял как они ловятся.
Если высылаются поочередно два инфо-хеша, мы записываем статистику в базу только одного запроса
Вот это очень интересно, но я не понял как игнорируется второй запрос
Если peer_hash формируется на основе
torrentpier/bt/announce.php at d5cc52eb7291327dd92255a8b73c7bfdd57e80c8 · torrentpier/torrentpier
#9
Буду писать в этой теме.
Вот это очень интересно, но я не понял как игнорируется второй запрос
В статистике пир отображается, если мы записали его данные в bb_bt_tracker, а мы в него записываем, только если переменная $hybrid_unrecord пуста.
Т.е. тут и здесь, peer_hash здесь роли не играет.

Также оператор LIKE работает не всегда, он текстовый и конвертирует бинарную строку, а она может содержать неправильные последовательности байтов, которые влияют на результат.
SUBSTRING же таких конвертаций не делает. Случай такого торрента внизу.

А почему бы не реализовать распознавание всех форматов, будь то 1,2 или гибрид и избавить рядового пользователя от этого конфига?
Так и делается, регистриются оба формата, и оба принимаются анонсером, только если торрент гибридный, то в базу записываются данные одного формата, против дублей.
Директивы disabled_* для удобства и совместимости, если администратор решит запретить чистые v2, или v1 торренты в будущем.
#10
LIKE работает не всегда
Не знаю как в sql, но в php substr работает очень даже некорректно. Поэтому изобрели mb_substr который тоже, порой, глючно работает. Да и если присмотреться у меня идёт проверка по hex формату (набор шестнадцатеричных символов) там скорее возникнет вопрос в скорости работы если like заменить на две проверки (точного соответствия и обрезанной строки)

В движке так
SUBSTRING(tor.info_hash_v2, 1, 20) IN ('$info_hashes_sql')";
У меня так
HEX(info_hash_v2) LIKE '$info_hash_hex%'

По прежнему считаю что $info_hash нельзя ни экранировать не прогонять через какие либо функции, сначала перевести в hex, а потом уже с ним работать

Не специалист по инъекциям, но даже если она будет, какой от нее толк если она будет в виде набора шестнадцатеричных символов..
...
INSERT
...
$values = "x'$info_hash_hex', x'$info_hash2_hex',