UDP Tracker 在 PHP 中宣布

Posted

技术标签:

【中文标题】UDP Tracker 在 PHP 中宣布【英文标题】:UDP Tracker announce in PHP 【发布时间】:2013-07-02 09:25:36 【问题描述】:

基本上我正在尝试从 udp 种子跟踪器获取 php 中的对等点。 目的是分析不同区域的流量。

所以我不需要下载种子,只需获取对等列表并再次宣布即可获得不同的集合。我尝试使用 PHP

我选择了一个开源代码来抓取 udp 种子并对其进行修改。

这是代码

require_once(dirname(__FILE__) . '/tscraper.php');

class udptscraper extends tscraper

    /*  $url: Tracker url like: udp://tracker.tld:port or udp://tracker.tld:port/announce
        $infohash: Infohash string or array (max 74 items). 40 char long infohash. 
        */
    public function scrape($url,$infohash)
        if(!is_array($infohash)) $infohash = array($infohash); 
        foreach($infohash as $hash)
            if(!preg_match('#^[a-f0-9]40$#i',$hash)) throw new ScraperException('Invalid infohash: ' . $hash . '.'); 
        
        if(count($infohash) > 74) throw new ScraperException('Too many infohashes provided.'); 
        if(!preg_match('%udp://([^:/]*)(?::([0-9]*))?(?:/)?%si', $url, $m)) throw new ScraperException('Invalid tracker url.'); 
        $tracker = 'udp://' . $m[1];
        $port = isset($m[2]) ? $m[2] : 80;
        $transaction_id = mt_rand(0,65535);
        $fp = fsockopen($tracker, $port, $errno, $errstr);
        if(!$fp) throw new ScraperException('Could not open UDP connection: ' . $errno . ' - ' . $errstr,0,true); 
        stream_set_timeout($fp, $this->timeout);

        $current_connid = "\x00\x00\x04\x17\x27\x10\x19\x80";

        //Connection request
        $packet = $current_connid . pack("N", 0) . pack("N", $transaction_id);
        fwrite($fp,$packet);

        //Connection response
        $ret = fread($fp, 16);
        if(strlen($ret) < 1) throw new ScraperException('No connection response.',0,true); 
        if(strlen($ret) < 16) throw new ScraperException('Too short connection response.'); 
        $retd = unpack("Naction/Ntransid",$ret);
        if($retd['action'] != 0 || $retd['transid'] != $transaction_id)
            throw new ScraperException('Invalid connection response.');
        
        $current_connid = substr($ret,8,8);

        //ANNOUNCE request
        $hashes = '';
        $pid ='O5214m2Y0z6178K1z090';
        $key = mt_rand(0,65535);
        $down =mt_rand(0,12345);
        $left =mt_rand(0,12345);
        $upped =mt_rand(0,12345);
        $transaction_id = mt_rand(0,65535);
        $event = 2;
        $socket = socket_create_listen (19624);

        foreach($infohash as $hash) $hashes .= pack('H*', $hash); 
        $packet = $current_connid . pack("N", 1) . pack("N", $transaction_id) . $hashes . pack("N", $pid) . pack("N", $down) . pack("N", $left) . pack("N", $upped) . pack("N", 0) . pack("N", 0) . pack("N", $key) . pack("N", -1) . pack("N", 19624);
        fwrite($fp,$packet);

        //ANNOUNCE response
        $readlength = 20 + (6 * count($infohash));
        $ret = fread($fp, $readlength);
        echo $ret;
        if(strlen($ret) < 1) throw new ScraperException('No .',0,true); 
        if(strlen($ret) < 8) throw new ScraperException('Too short  response.'); 
        $retd = unpack("Naction/Ntransid",$ret);
        // Todo check for error string if response = 3
        if($retd['action'] != 1 || $retd['transid'] != $transaction_id)
            throw new ScraperException('Invalid scrape response.');
        
        if(strlen($ret) < $readlength) throw new ScraperException('Too short scrape response.'); 
        $torrents = array();
        $index = 8;
        foreach($infohash as $hash)
            $retd = unpack("Ninterval/Nleechers/Nseeders/Nipaddr/NTCP",substr($ret,$index));
            print_r($retd);
            $retd['infohash'] = $hash;
            $torrents[$hash] = $retd;
            $index = $index + 12;
        

        return($torrents);
    






try
        $timeout = 2;

        $scraper = new udptscraper($timeout);
        $ret = $scraper->scrape('udp://tracker.openbittorrent.com:80/announce',array('8B60D5838A2CE34294AF9E49FF990C5BEC6C61B1'));

        //print_r($ret);
    catch(ScraperException $e)
        echo('Error: ' . $e->getMessage() . "<br />\n");
        echo('Connection error: ' . ($e->isConnectionError() ? 'yes' : 'no') . "<br />\n");
    

?>

我只使用了 1 个 HASH 值 请帮忙。

【问题讨论】:

你得到什么响应信息? 我什么也没有得到我什至没有使用智能嗅探监听端口没有活动我使用了 utorrent 使用的端口然后关闭了 utorrent,也转发了该端口,帖子处于防火墙异常中,甚至禁用了防火墙跨度> 那么,您只需要响应消息中包含的对等列表吗?我不懂php,但是当你开始和tracker server通信时,你不应该使用scrape message。 我用了announce后没有用scrape,名字只说scrape但实际上是announceing,我改变了动作(决定天气是scrape还是announce)rasterbar.com/products/libtorrent/udp_tracker_protocol.html我已经形成使用完全相同格式的数据包理论上它应该返回一个包含信息的数据包,以及根据 numwant 的对等列表或跟踪器允许的最大对等点。我是 php 新手,实际上我想要它用于研究目的。我可以使用 lib torrent,但它的速度慢且效率低,因为我只想要同行而不是数据 【参考方案1】:

编辑: 跟踪服务器有时会发送响应消息,其中对等点列表替换为每个对等点 6 个字节。前 4 字节为主机 IP,后 2 字节为端口号。您应该解析它们以与对等方进行通信。

我认为理论(规格)可能不是事实。来自 Internet 的所有有关 Bittorent 的规范都已过时。仅按照规范可能无法检查宣布请求是否正确。 我建议您尝试使用 Wireshark。捕获普通Bittorent-client发送的数据包,然后检查普通Bittornet客户端的工作原理。将您的 php 代码发送的通知请求与一个普通客户端发送的请求进行比较。

实际上,我正在尝试在 C 中实现 Bittorent 客户端。由于没有在请求消息中指定紧凑字段,因此我很难与跟踪服务器通信。但是大多数规范都说宣布请求中的紧凑字段是可选的。

尝试使用wireshark。然后比较两个请求(您的请求和常见的 bittorent 发送的另一个请求。)

【讨论】:

好的,我会尽快报告 让代码在 Python 中工作,但我得到的 ip 列表搞砸了 你说 ip 的列表是以二进制表示的?有时跟踪服务器会发送响应消息,其中包含作为对等 ip 和端口的二进制表示。 我没有得到任何端口,但是得到了很多 ip,现在已经解决了。你也得到端口吗?谢谢你的回答!

以上是关于UDP Tracker 在 PHP 中宣布的主要内容,如果未能解决你的问题,请参考以下文章

通过 UDP 向 Bittorrent Tracker 发送信息哈希

如何使用 PHP 和 fsockopen 检查 UDP 地址是不是存在?

PHP 中的 Torrent 抓取

Trac PHP 语法高亮在 Wiki 中不起作用

node.js 中的 UDP 跟踪器抓取意外返回零

Trac JSON RPC 问题 - 将 jQuery AJAX 与 PHP 代理一起使用