首页 > 数码 正文

kad网络是什么意思和BT背后的技术

时间:2023-09-22 作者:佚名

  历史

  早期的BT下载主要是通过开放的网站,进行种子资源的公布。在利用tracker中心服务器完成下载peer的交换,最终实现从下载用户的电脑中获取资源。

  在这个过程中,存在两个风险比较大的点:

  第一个公布种子的网站,种子文件包含了所需要下载资源的全部信息,很容易被检测出种子内容是否合规,从而关闭种子公布资源站点。

  第二个提供tracker的中心服务节点,这个也是很容易从种子中查询到的,很容易被封杀。导致P2P自由的分享环境被打破。

  在这个基础上,就出现替代tracker服务器和种子一些新方法,我们简单的介绍下比较主流的去中心化tracker和种子分享网站的P2P分享网络。

  torrent andmagnet

  首先从第一步获取种子开始,我们一般想找一部电影/游戏或者一些其他资源,一般都是网盘搜索,或者去BT站,PT去找种子,或者论坛上去找链接。先介绍下种子和磁链的关系,种子一般以.torrent结尾的索引文件。

  torrent

  d8:announce62:https://xxxxx.im.xxx/88696dc48cbdad7518e4b111b83ee77c7:comment14:TorrenTGui.ORG10:created by13:uTorrent/221013:creation datei1523099215e8:encoding5:UTF-84:infod6:lengthi23715250176e4:name14:SKY HUNTER.iso12:piece lengthi4194304e6:pieces113100:xxx

  这种被序列化的信息就是种子了,里面使用的是一种明文的序列化方法。bencode 第二节简单介绍。

  反序列化里面主要包含以下信息:

  announce:Tracker的主服务器

  announce-list:Tracker服务器列表

  comment:种子文件的注释

  comment.utf-8:种子文件注释的utf-8编码

  creation date:种子文件建立的时间,是从1970年1月1日00:00:00到现在的秒数。

  encoding:种子文件的默认编码,比如GB2312.Big5.utf-8等

  info:所有关于下载的文件的信息都在这个字段里,根据下载的是单个文件还是多个文件,子字段的项目会不同。

  files:表示文件的名字,大小,该字段包含如下三个子字段:

  length:文件的大小,用byte计算

  path:文件的名字,在下载时不可更改

  path.utf-8:文件名的UTF-8编码,

  多文件Torrent的结构的树形图为

  Multi-file Torrent

  ├─announce

  ├─announce-list

  ├─comment

  ├─comment.utf-8

  ├─creation date

  ├─encoding

  ├─info

  │ ├─files

  │ │ ├─length

  │ │ ├─path

  │ │ └─path.utf-8

  │ ├─name

  │ ├─name.utf-8

  │ ├─piece length

  │ ├─pieces

  │ ├─publisher

  │ ├─publisher-url

  │ ├─publisher-url.utf-8

  │ └─publisher.utf-8

  └─nodes

  单文件Torrent的结构的树形图为

  Single-File Torrent

  ├─announce

  ├─announce-list

  ├─comment

  ├─comment.utf-8

  ├─creation date

  ├─encoding

  ├─info

  │ ├─length

  │ ├─name

  │ ├─name.utf-8

  │ ├─piece length

  │ ├─pieces

  │ ├─publisher

  │ ├─publisher-url

  │ ├─publisher-url.utf-8

  │ └─publisher.utf-8

  └─nodes

  magnet

  为了解决第一种子文件包含的内容信息太多,容易被检测中其中的关键信息。第二种子文件过大,不太容易扩散分享。出现了一种替代种子文件的信息字符串就是磁力链接。形如:magnet:?xt=

  urn:btih:b7d9b9d9df8d7678af1f2542677e195fdbdb1674

  其中主要字段是 btih,其实这里的值就是bt种子文件中info字段sha1值的base32编码后的字符串。

  bencode

  种子文件的bencode 包含四种类型的编码:

  string类型

  string类型的编码格式为[length]:[string]。以字符串的长度开头,加一个冒号,并以字符串内容结束。

  示例:"abc" => 3:abc

  int类型

  int类型的编码格式为i[int]e。以i开头,加上数字,以e结尾。

  示例:123 => i123e

  List类型

  List类型的编码格式为l[object]e。以l开头,加上列表中各个元素的编码(元素的类型同样为BEncoding支持的类型),以e结尾。

  示例:List<"abc", 123> => l3:abci123ee

  Dictionary类型

  Dictionary类型的编码格式为d[Key-Value Pair]e。以d开头,加上字典中每个键值对的编码,以e结尾。

  示例:Dictionary<{"name":"create chen"},{"age":23}> => d4:name11:create chen3:agei23ee

  以上编码list和dictionary支持嵌套。bencode编码方式也被用在后续的BT查询消息的构建上。

  去中心化的peer交换网络 DHT

  在去中心化的交换网络上,每个用户(node)都会存储一部分种子信息和种子索引信息。这些索引信息里面包含自己正在下载的资源(peer)、自己周边正在下载的资源信息(peer)、以及一些可能拥有某种子资源的信息(node)。当我们获取到某个种子或者磁链时,就会到这个网络中查询哪些用户在进行这个种子的资源下载,获取这些用户的peer信息(包含ip port token),然后和这些peer进行连接,获取资源。在查询的过程中,主要利用krpc进行调用,krpc是一种基于udp的rpc调用服务。

  krpc

  基本结构如下:

  {

  "t":"aa", --transcationID 2^16 two byte

  "y":"r", --message type query->q response->r error->e

  "q":" ". --ping find_node get_peers

  "r":{}

  "e"

  "a": --query params

  }

  一条 KRPC 消息由一个独立的字典组成,其中有 2 个关键字是所有的消息都包含的,其余的附加关键字取决于消息类型。每一个消息都包含“t”关键字,它是一个代表了 transaction ID 的字符串类型。transaction ID由请求节点产生,并且回复中要包含回显该字段,所以回复可能对应一个节点的多个请求。transaction ID应当被编码为一个短的二进制字符串,比如 2 个字节,这样就可以对应 2^16 个请求。另一个每个 KRPC 消息都包含的关键字是“y”,它由一个字节组成,表明这个消息的类型。y 对应的值有三种情况:q 表示请求,r 表示回复,e 表示错误。

  主要包含以下四个操作:

  ping

  检测节点是否存活。

  最基础的请求是一个ping。"q"="ping",一个ping请求有一个参数,"id",它的值是一个20字节的字符串,包含网络字节排序的发送者的节点ID。一个ping的适当回复有一个关键字"id",包含发出回复的节点的节点ID。

  arguments: {"id" : ""}

  response: {"id" : ""}

  Example Packets

  ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}

  bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe

  Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}

  bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

  find_node

  查找节点。

  find_node 被用来查找给定 ID 的节点的联系信息。这时 KPRC 协议中的 "q" == "find_node"。find_node请求包含 2 个参数,第一个参数是 id,包含了请求节点的ID。第二个参数是 target,包含了请求者正在查找的节点的ID。当一个节点接收到了 find_node 的请求,他应该给出对应的回复,回复中包含 2 个关键字 id 和 nodes,nodes 是一个字符串类型,包含了被请求节点的路由表中最接近目标节点的 K(n) 个最接近的节点的联系信息。在规范的DHT网络中,K(n)建议值是8.

  arguments: {"id" : "", "target" : ""}

  response: {"id" : "", "nodes" : ""}

  Example Packets

  find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}

  bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe

  Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}

  bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re

  get_peers

  查找文件peer。

  get_peers 与 torrent 文件的 infohash 有关。这时 KPRC 协议中的 "q"="get_peers"。get_peers 请求包含 2 个参数。第一个参数是 id,包含了请求节点的 ID。第二个参数是info_hash,它代表 torrent 文件的 infohash。如果被请求的节点有对应 info_hash 的peers,他将返回一个关键字 values,这是一个列表类型的字符串。每一个字符串包含了 "

  CompactIP-address/portinfo" 格式的 peers 信息。如果被请求的节点没有这个 infohash 的peers,那么他将返回关键字 nodes,这个关键字包含了被请求节点的路由表中离 info_hash 最近的 K 个节点,

  arguments: {"id" : "", "info_hash" : "<20-byte infohash of target torrent>"}

  response: {"id" : "", "token" :"", "values" : ["", ""]}

  or: {"id" : "", "token" :"", "nodes" : ""}

  Example Packets

  get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}

  bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash30:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe

  Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}

  bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re

  Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}}

  bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re

  announce_peer

  发起请求节点。

  这个请求用来表明发出 announce_peer 请求的节点,正在某个端口下载 torrent 文件。announce_peer 包含 4个参数。第一个参数是 id,包含了请求节点的 ID;第二个参数是 info_hash,包含了 torrent 文件的infohash;第三个参数是 port 包含了整型的端口号,表明 peer 在哪个端口下载;第四个参数数是 token,这是在之前的get_peers 请求中收到的回复中包含的。收到 announce_peer 请求的节点必须检查这个 token 与之前我们回复给这个节点get_peers 的 token 是否相同。如果相同,那么被请求的节点将记录发送 announce_peer 节点的 IP 和请求中包含的port 端口号在 peer 联系信息中对应的 infohash 下。

  arguments: {"id" : "",

  "implied_port": <0 or 1>,

  "info_hash" : "<20-byte infohash of target torrent>",

  "port" : ,

  "token" : ""}

  response: {"id" : ""}

  Example Packets

  announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "implied_port": 1. "info_hash":"mnopqrstuvwxyz123456", "port": 6881. "token": "aoeusnth"}}

  bencoded = d1:ad2:id20:abcdefghij012345678912:implied_porti1e9:info_hash30:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe

  Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}

  bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

  DHT and Kademlia

  DHT (Distributed Hash Table)分布式哈希表,Kad网络是其的一种实现方式。Kademlia协议(以下简称Kad)是美国纽约大学的PetarP. Maymounkov和David Mazieres.在2002年发布的一项研究结果《Kademlia: A peerto -peer information system based onthe XOR metric》。

  nodeid

  2^160位(bit)的标志id,可以是本机mac的sha1值。在DHT分享网络中,资源的info-hash正好也是160位(bit)。在利用kad网络,将info-hash存储于与其相近的多个node中,方便在查询过程中利用get_peer进行快速逼近。在如何判定是否与其相近,kad网络利用的是xor运算。

  xor distance

  Kademlia 根据两个标示符之间的距离来把 对分配给特定的节点。对于两个 160 位标示符 x 和 y , Kademlia 把它们之间的距离定义为二者按位异或( XOR )结果的整数值, d(x,y)=x ⊕y 。

  首先,XOR 是一种有效的度量方法(虽然不是欧几里得几何意义上的)。很显然,d(x,x)=0 ;当x 不等于y 时,d(x,y)>0 ,并且对于任意的x,y 来说,d(x,y)=d(y,x) 。XOR 还具有三角特性:d(x,y)+d(y,z) 大于等于d (x,z )。该三角特性可以从如下事实得出:d(x,y) ⊕d(y,z)=d(x,z) ,并且对于任意大于等于0 的a 和b :a+b 都大于等于a ⊕b 。

  同时,XOR 也刻画出了隐含在我们基于二叉树描绘的系统中距离的概念。在160 位ID 的满二叉树中,两个IDs 间的距离大小就是包含它们的最小子树的高度。当树不是满的时,距离ID x 最近的叶子就是其ID 和x 具有最长的公共前缀的那个叶子。如果树中有空的分支,那么具有最长公共前缀的叶子就会有多个。此时,我们基于该树的空分支,把x 对应的位取反得到ID x’ ,那么距离x’ 最近的叶子即为距离x 最近的叶子。利用xor的距离测算,最坏O(n)即可获得到查询结果。

  routing table

  路由表是一颗二叉树,其叶子是 k-buckets 。每个 k-bucket 存放着具有某些公共 ID 前缀的节点。前缀就是该 k-bucket 在二叉树中的位置。了因此,每个 k-bucket 覆盖了 ID 空间的某个范围,所有 k-bucket 合起来完整覆盖了整个 160 位 ID 空间。

  节点是根据需要动态分配到路由树中的。一开始,节点A的路由树只有一个节点——覆盖整个 ID 空间的单个 k-bucket 。当A通过find_node或者get_peer获取一个新节点的联系信息时,就会试图把其插入到相应的 k-bucket 中。如果该 bucket 不满,简单将其插入即可。否则,如果该 k-bucket 的区间范围包含了A自己的节点 ID ,那么该 bucket 会分裂为两个新的 buckets ,原有的内容会被划分到这两个 buckets 中,接着重复插入过程。如果 k-bucket 已满且不含有A的节点 ID ,那么就直接丢弃这个新的联系信息。需要注意的是P2P节点在线时间是不稳定的,需要定期去ping检测每个k-bucket捅中的节点,如果死掉则剔除掉。按照beps005规范没有更新的节点15分钟需要检测一次。每次krpc操作中可以正常响应的则认为是活跃节点。

  在Kad网络中还存在一种高度不平衡的二叉树均衡的过程,在BT的DHT网络中,目前没有看到使用。

  BT 爬虫实现要点

  1.先伪装自己向公共节点进行find_node 查询,将自己加入网络。

  "router.bittorrent.com:6881",

  "router.utorrent.com:6881",

  "dht.transmissionbt.com:6881",

  2.在返回的find_node中,替换返回nodeid的某些n位,造成与返回node节点id不在区间内,继续探索整个网络节点分布。

  func CreateRandomFindNode(target string) (res []byte, transid string) {

  msg := make(map[string]interface{})

  msg["t"] = TCIDMNGR.GetTranscationID()

  msg["y"] = "q"

  msg["q"] = "find_node"

  msg["a"] = map[string]interface{}{"id": target[:15] + OwnNodeID.ToString()[15:], "target": target}

  return []byte(PackageMessage(msg)), msg["t"].(string)

  }

  3.一般BT爬虫被动接收announce_peer 从peer的信息中使用peer wire protocol 获取 metadata 即种子信息。然后分析torrent中的信息确认文件内容。

  4.注意进行ip黑名单过滤,DHT网络中,存在很多这样爬虫,在实现过程中,发现北美有个ip爬虫疯狂变更nodeid进行find_node 请求,把内存塞满的情况(1G),注意控制本地DHT表的总节点数。

  5.加速搜索过程,在获取get_peer请求时进行递归get_peer请求,注意控制深度。可以扩大K-bucket桶的大小,降低二叉树的深度。

  6.在使用peer wire protocol过程中,因为运营商对P2P封锁,很多情况下下载种子失败,可以使用知名种子库进行info-hash下载。

  7.注意控制udp发包速度,以免被主机商防火墙误以为中毒。

  PT

  额外提一点,关于现在的PT,PT网络是禁止开启DHT,防止资源外泄。在PT站发布的种子都会包含PT站的私有tracker服务地址,每个会员下载的种子也会包含自己的私有token,当种子泄露到BT上时,PT管理员很容易封禁掉该会员的信息。PT致力于打造高端高活跃的P2P分享网络。

本文信息为网友自行发布旨在分享与大家阅读学习,文中的观点和立场与本站无关,如对文中内容有异议请联系处理。

本文链接:https://www.paituo.cc/tech/1004842.html

  • 小编推荐

    战斗故事片和8部真实事件改编的战争大片,太震撼了

    本文讲述战斗故事片和8部真实事件改编的战争大片,太震撼了,简介如下每次君君收集大家想看的影单类型,发现有类题材呼声最高。那就是战争片。君君以前推过很多很多战争电影。《拯救大兵瑞恩》、《血战钢锯岭》、《湄公河行动》、《兵临城下》...

    asp空间申请和香港ASP主机空间选择注意事项

    本文讲述asp空间申请和香港ASP主机空间选择注意事项,简介如下所谓的ASP空间,就是指支持ASP语言程序的主机空间,由于ASP语言只能运行在Windows操作系统之上。因此,一般情况下,我们也称作ASP空间为Windows...

    大熊猫是猫吗?和到底是猫,还是熊?

    本文讲述大熊猫是猫吗?和到底是猫,还是熊?,简介如下大熊猫有800万年生存史,正式得名只有83年,还是源自一次误读!大熊猫本名“猫熊”,后来因何改称“熊猫”?原来...

    茶叶属于商标的第几类和如何取名?怎么注册?

    本文讲述茶叶属于商标的第几类和如何取名?怎么注册?,简介如下我想注册一个自己的茶叶商标,注册哪一类?茶叶商标注册哪一类,茶叶商标注册什么内容?商标注册都有什么流程?商标注册如何进行?商标注册需要哪些资料?商标注册如何起名...

    男子抢完女子手机后加微信求原谅和还构成犯罪吗?

    本文讲述男子抢完女子手机后加微信求原谅和还构成犯罪吗?,简介如下【基本案情】5月7日21时许,家住十堰市张湾区发展大道的白女士下班回家,行至离小区还有百余米的公厕附近时,突然被一名陌生男子从背后捂住了嘴,并拖拽进了男厕所。男...

    问鼎天下君王和他想问鼎天下,却被鼎活活砸死

    本文讲述问鼎天下君王和他想问鼎天下,却被鼎活活砸死,简介如下嬴荡,姓嬴,名荡,是秦惠文王和惠文后的儿子,战国时期秦国的第二位王,史称秦武王。秦武王嬴荡,天生神力,从小就喜欢与武士做与力气有关的游戏。等到继位之后,尤其喜爱...

    华为和荣耀是什么关系和荣耀手机到底算不算华为手机

    本文讲述华为和荣耀是什么关系和荣耀手机到底算不算华为手机,简介如下最近还是有很多小伙伴在提问,这个荣耀手机到底算不算华为手机?因为很多线上商城或者是线下某些实体店依旧把荣耀和华为混为一谈。搞得很多小伙伴到现在还没搞清楚荣耀和华...

    什么是白皮书有什么用

    本文讲述什么是白皮书有什么用,简介如下近日热搜,我们发布白皮书,我们还听说过蓝皮书,这都是什么意思?这个白皮书说了什么?最后让我们看看那位德高望重的基辛格博士又说了什么。我们发布名为#台湾问题与新时...