Pt站点禁用Aria2客户端方法分析

Rhilip 2018-10-01 PM 6848℃ 11条

为什么Private Tracker需要限制客户端,因为并不是所有的BT客户端都是完全遵守BEP规范的实现(其实常用的ut、tr之流也并不是完全遵守的2333)。所以以NP框架为代表的站点要尽量把用户使用的客户端限制在允许的范围,使得能相对正确的记录用户的做种信息。

但是这并不能解决一些能伪造User-Agent以及peer_id_prefix的软件,例如Aria2这样的综合下载软件或者一些流量作弊软件。因为他们可以很容易的伪造,以绕过NP的检测。甚至于Aria2专门提供了这样的配置项来进行修改。例如下面的例子中就将Aria2伪装成 Transmission/2.77,能成功的绕过原版的NexusPHP检测。

# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
user-agent=Transmission/2.77
  1. 甚至可以这样伪装(UA为Tr 2.79,但peer_id为Tr 2.77).虽然一看就知道是有问题的,但是根据NP的匹配规则是能通过的233333
peer-id-prefix=-TR2770-
user-agent=Transmission/2.79

那能不能通过一些手段尽可能的检测出来这种伪装的客户端那?这就是本文想要探讨的内容。

太长不看

在announce.php文件 check passkey行为 之前添加以下信息即可~

if (isset($_SERVER["HTTP_Want-Digest"]) || strpos($peer_id, $key) !== false) {
    err("Anti-Cheater: You may use Aria2");
}

Announce报文分析

通过将Aria2伪装成Transmission/2.77,配置proxy选项,并使用Fiddler 4抓包,我们得到了Aria2向Tracker的Announce报文

TIM截图20181001111020.jpg

其中一次的报文完整如下

GET /announce.php?passkey={hide}&info_hash=%E6%C2%A0%081b%B1%25%40%14%F7Xbf%B0%F1U%A4%26%E7&peer_id=-TR2770-8u%13Y%CB9%D3%CE%F6mF%0A&uploaded=0&downloaded=0&left=165431200&compact=1&key=%CB9%D3%CE%F6mF%0A&numwant=50&no_peer_id=1&port=51413&supportcrypto=1 HTTP/1.1
User-Agent: Transmission/2.77
Accept: */*
Host: tracker.byr.cn
Want-Digest: SHA-512;q=1, SHA-256;q=1, SHA;q=0.1

而对使用uTorrent或者其他客户端抓包结果分别如下:

  • uTorrent 2.2.1
GET /announce.php?passkey={hide}&info_hash=%b0.%00%2bY%8a%eah%bc%0b%e0%0f%3d4%27%0a3%11%20%8c&peer_id=-UT2210-%d6bE%c7L7%d8%aeD1%1e%c3&port=32971&uploaded=0&downloaded=0&left=13300779178&corrupt=0&key=9BA854A1&event=started&numwant=200&compact=1&no_peer_id=1&ipv6={hide} HTTP/1.1
Accept-Encoding: gzip
User-Agent: uTorrent/2210(25302)
Host: nexusphp.localhost
Cache-Control: no-cache
  • rTorrent/0.9.4/0.13.4
GET /announce.php?passkey={hide}&info_hash=M%db%82%ad%5do%ac%cd%e2%9b%ac%88%5b%b1H%a8EQ-%11&peer_id=-TR2940-tyyz4k6tzpz2&port=53185&uploaded=0&downloaded=0&left=0&numwant=80&key=5f7e4d94&compact=1&supportcrypto=1&event=started&ipv6={hide} HTTP/1.1
Host: nexusphp.localhost
User-Agent: rtorrent/0.9.4/0.13.4
Accept: */*
Accept-Encoding: deflate, gzip

对比分析

通过对比,我们可以发现一些明显属于Aria2的一些指纹。

  • Want-Digest头

Aria2会添加一个Want-Digest头,该段实现在 src/HttpRequest.cc#L250 中,而其他BT客户端并不会自动添加这个请求头。通过翻阅Aria2的issus,发现有人于2月提出相关issue : issues#1136 - Is there a way to remove an auto added header (Want-Digest) 但是,并没有引起相关团队的重视。那么可以使用该段来进行检测。当发现用户提交的Headers中含有该请求头则禁止访问。示例代码如下:

$headers = getallheaders();
if (isset($headers["Want-Digest"])) err("header 'Want-Digest' is exist");

注: $headers["Want-Digest"]可以直接写作$_SERVER["HTTP_Want-Digest"]。因为getallheaders是一个apache的方法,这样就不用注入在全局中注入。

  • key和peer_id中有重复字段

通过对比requests的params,可以发现Aria2提交的peer_id中包含key的全部内容,而其他客户端并没有这种表现。对应 src/DefaultBtAnnounce.cc#L160 中相关实现,可以发现相关构造中均使用了相同的信息。(Use last 8 bytes of peer ID as a key

peer_id -> util::percentEncode(bittorrent::getStaticPeerId(), PEER_ID_LENGTH).c_str()
key -> util::percentEncode(bittorrent::getStaticPeerId() + PEER_ID_LENGTH - keyLen, keyLen).c_str()

故可以通过这两个字段进行检查,当key值能在peer_id中发现,则可认为用户使用Aria2,示例代码如下:

$peer_id = $_GET["peer_id"];
$req_key = $_GET["key"];
if (strpos($peer_id, $_GET["key"]) !== false) err("May use Aria2 because of key find in peer_id");
  • 请求间隔

Aria2并不会遵循Response中对于interval值的规定,无论是请求成功还是失败,Aria2会保持每两分钟进行一次轮询。通过限制用户两次Announce的最小间隔限制,可能就能禁止Aria2的之后多次请求,但是这不能限制用户通过查询成功时获得的peer_list从而完成对应种子的下载。(可以考虑通过Cache锁等形式,一直锁住Announce duration 小于2分钟的请求)

  • 无Scrape请求

使用Aria2并不会产生Scrape动作,即不会预查询对应种子的做种情况,但是由于scrape和announce请求是分离的,此外一些(较早的)正规的BT软件也同样存在无Scrape请求的情况,故较难利用该点进行判断。

  • 请求字段及其顺序

由于在Announce请求中,info_hash以及peer_id都是需要escaped的,所以多数软件都是使用字符串拼合的形式构造GET请求的url。例如Transmission构造的请求链接格式就是以下格式( libtransmission/announcer-http.c#L61):

/info_hash=%s&peer_id=%*.*s&port=%d&uploaded=%d&downloaded=%d&left=%d&numwant=%d&key=%x&compact=1&supportcrypto=1(&requirecrypto=1)?(&corrupt=%d)?(&event=%s)?(&trackerid=%s)?(&ipv6=%s)?/

使用libtorrent库(如qbittorrent,Deluge)格式( libtorrent/src/http_tracker_connection.cpp#L97-L193

/info_hash=%s&peer_id=%s&port=%d&uploaded=%d&downloaded=%d&left=%d&corrupt=%d&key=%08X(&event=%s)?&numwant=%d&compact=1&no_peer_id=1(&supportcrypto=1)?(&redundant=%s)?(&trackerid=%d)?(?<i2p>&ip=%s.i2p)?(&ip=%s)?(?!\g<i2p>&ipv4=)?(?!\g<i2p>&ipv6=)?$/

而Aria2拼出来则如下 (src/DefaultBtAnnounce.cc#L165):

/info_hash=%s&peer_id=%s&uploaded=%d&downloaded=%d&left=%d&compact=1&key=%s&numwant=%d&no_peer_id=1(&port=%u)?(&event=%s)?(&trackerid=%s)?(&requirecrypto=1|&supportcrypto=1)(&ip=%s)?/

通过对比了解,可以发现Aria2并不会提交&ipv6=字段,并可以通过对$_SERVER["QUERY_STRING"]字段进行正则匹配,区分是否是对应软件。


Update 2018/10/21

经过近一个月对某站的Announce Error日志分析,通过Want-Digest头key和peer_id中有重复字段已经基本能确定用户确实使用Aria2进行访问操作,如下图所示:
TIM截图20181021091522.jpg
第一位用户使用Aria2伪装成Transmission 2.79,但是UA和peer_id其实并不能切合(peer_id为Tr 2.77的格式,但是通过了NexusPHP的客户端检测)且url format符合Aria2的格式,虽然不知道通过什么方式去除了Want-Digest头,但是仍然检测出来。
第二位用户使用Aria2伪装成Transmission 2.77,通过Want-Digest头以及key和peer_id中有重复字段两项直接检测出来。

基于以上Aria2的检测方法,公开其实现有

标签: PT, nexusphp, aria2

非特殊说明,本博所有文章均为博主原创。

评论啦~



已有 11 条评论


  1. povsister
    povsister

    好!
    (来自一名不愿透露姓名的网友点赞)

    回复 2018-10-29 12:22
  2. Alpha
    Alpha

    前来捉R酱

    回复 2018-11-15 18:51
  3. 林一二
    林一二

    那要是这些 bug 都修复了,或者有一个自定义客户端把你上面说的这些都考虑进去了,而上传量数据完全是由客户端提供的,那不就完全没法防止作弊了吗?

    难道没有更好的服务端方案(假设客户端不可信)来防止作弊吗?

    回复 2019-04-17 11:31
    1. Rhilip
      Rhilip 博主

      使用client探针方法(利用peers之间的交换比peer与tracker之间的通信可信度更高,以及伪造客户端因为实现成本更高而不进行peers之间交换的),或者计算站点对应种子总上传下载情况,基本比率能稳定在0.9-1.3,超过再做核查。当然,一些很明显的作弊特征,如果管理有经验的话,应该能直接发现。

      回复 2019-05-07 09:47
  4. Balthild
    Balthild

    想问问为什么要禁止 aria2,它好像也不是迅雷那种吸血客户端吧。主要个人感觉现在想在 Linux 上搭个客户端,除了 transmission 之外也就 aria2 最方便了。

    回复 2019-06-10 01:33
    1. Rhilip
      Rhilip 博主

      文章最开头已经说了,伪造User-Agent以及peer_id

      回复 2019-06-10 17:52
  5. nmsl
    nmsl

    劣币驱除良币

    回复 2019-12-30 22:13
    1. watson
      watson

      aria2也不算劣币吧,个人觉得PT站可以限制一下aria2的伪造代理,但是不要禁止aria2

      回复 2020-04-06 12:53
  6. 椰子
    椰子

    aria2只是管理方便 又不会吸血的 封他干嘛?

    回复 2020-06-07 19:17
    1. Rhilip
      Rhilip 博主

      不是禁止aria2 而是只允许某些bt软件,自然要封掉钻漏洞伪造peer_id和ua的。
      更何况aria2暴力announce消耗服务器资源。
      如果你觉得不合适,可以和站点sysop说明。
      本文只是给想要禁用aria2伪装的站点sysop一个思路。
      此次回复也是最后一次回复为什么封aria2。

      回复 2020-06-07 21:15
  7. 混淆
    混淆

    aria2其实性能相当差。。在种子这种高吞吐多连接的情况下经常容易假死,而相同配置下qb和tr就能work,所以还是拿来做HTTP下载比较好

    回复 2020-09-18 17:17