bt協議

BT協議

bt種子文件

編碼 bencode

bencode 有 4 種數據類型: string, integer, list 和 dictionary。

  1. string

    e.g.: <字符串長度>:<字符串>

  2. integer

    e.g.: i<整數>e

  3. list

    e.g.: l數據1數據2數據3e

  4. dictionary

    e.g.: d[key1][value1][key2][value2][…]e,其中 key 必須是 string 而且按照字母順序排序

種子文件結構

  • info 字典,描述種子內包含的文件列表信息,這里有兩種類型,一是單文件的,二是多文件的,具體看后面的說明。
  • announce 字節串,描述 Tracker 的 URL。
  • announce-list 列表,可選,這是一個對官方規范的擴展項,提供后向兼容。
  • creation date 字節串,可選,這是一個UNIX時間戳,表示種子文件的創建時間。
  • comment 字節串,可選,自由描述字段,一般描述種子的制作者。
  • created by 字節串,可選,描述用于制作這個種子文件的程序。
  • encoding 字節串,可選,描述 info.pieces 字段的編碼方式。

無論是單文件格式還是多文件格式種子文件,其 info 字段下都可以包含以下 3 個字段

  • piece length 整數,表示一個分片的長度(單位:字節),稱之為 分片單位
  • pieces 字節串,是由多個分片的 SHA-1校驗碼(20字節/個) 拼湊而成的字節串,因此其長度總是為20的倍數。
  • private 整數,可選,如果這個值被置為1,那么 BT客戶端 必須通過向 種子文件 中指定的 Tracker 匯報自身的存在,從而獲取其它 伙伴 的信息。反之如果置0客戶端 可以通過其它方法獲取其它伙伴,例如 PEXDHT。因此,private 字段也可以理解為“禁止通過其它途徑獲取伙伴信息”。

當種子內僅包含一個文件的信息時,其 info 字段 內必須包括如下字段

  • name 字節串,種子內包含的唯一文件的名稱,這不是強制性的命名,僅作參考。(下載時可以修改保存的文件名)
  • length 整數,種子內包含的唯一文件的大小,單位是字節。
  • md5sum 字節串,可選,這是一個32位的16進制字符串,表示種子內包含的唯一文件的 MD5 校驗值。盡管幾乎所有BT客戶端都未使用到這個字段,但是它仍被保留作為兼容性字段

當種子內包含多個文件的信息時,其 info 字段 內必須包括如下字段

  • name 字節串,種子內所有文件的總名稱,BT客戶端下載時默認使用它作為資源的目錄名稱,同理,這不是強制性的命名,僅作參考。(下載時可以修改保存的目錄名)

  • files列表,這是一個由多個字典組成的列表,每個字典對應一個文件的信息,這些字典的格式如下:

  • length 整數,文件的大小,單位是字節。
  • md5sum 字節串,可選,這是一個32位的16進制字符串,表示該文件的 MD5 校驗值。盡管幾乎所有BT客戶端都未使用到這個字段,但是它仍被保留作為兼容性字段
  • path 列表 這是一個特殊的文件路徑表示方式。假設一個文件在種子內對應的相對路徑是a/bb/ccc/hello.txt,那么將其根據 / 分割開,得到順序列表 [ 'a', 'bb', 'ccc', 'hello.txt' ],經過 BEncoding 編碼后就是 l1:a2:bb3:ccc9:hello.txte

Tracker服務器

一般有http和udp兩種

入參

  • info_hash:元信息文件中 20 字節的 SHA-1 散列值。注意此值會進入編碼字典中,如上述的信息關鍵字的定義所述。與不需編碼的 peer_id 相比,它總是被 URL 編碼。
  • peer_id:客戶端 ID ,客戶端用來唯一標識自己 ID 的 20 字節的串,它在客戶端啟動時生成。允許為任何值,包括二進制數據。目前沒有特定的算法來生成客戶端 ID。但是,人們會認為它至少對于自己的本地機器是唯一的,從而應該像進程 ID 一樣合并數據,也可能在啟動時由時標記錄。見本區域下面的一般客戶端編碼的 peer_id。
  • port:客戶端監聽的端口號。BitTorrent 所使用的典型端口是 6881-6889。如果此范圍的端口都無效,可以選擇其他的。
  • uploaded:從客戶端發送“已開始”事件到服務器算起的上傳總量,數值采用 10 進制的 ASCII。對于沒有在官方規范明確指出的,該值應為已上傳的字節總數。
  • downloaded:從客戶端發送“已開始”事件到服務器算起的下載總量,數值采用 10 進制的 ASCII。對于沒有在官方規范明確指出的,該值應為已下載的字節總數。
  • left:客戶端需要下載的字節數,以 10 進制 ASCII 編碼。
  • no_peer_id:客戶端接受一個緊密的響應。客戶端列表由客戶端串代替,此串中每個客戶端都編碼成 6 字節。前 4 字節是主機名(以網絡的字節順序),后兩個字節是端口號(同樣以網絡字節的順序)。
  • event:如果被指定,則是已開始已完成已停止中的一個,或者為空(表示未指定)。如果未指定,此請求為常規時間間隔中的一次運行。
    • started:向服務器發送的第一個請求,必須包含開始值的事件關鍵字。
    • stopped:如果客戶端關機則須發送到服務器上。
    • completed:完成下載時必須發送到服務器上。但是,當客戶端啟動時下載完成度為 100%(即:做種中)則不會發送。可能這是允許服務器增加“已完成下載”的方法。
  • ip:可選。客戶端的真實 IP 地址,以點分四元組格式或 RFC3513 中定義的 16 進制 IPv6 地址。注意:大體上此參數沒有客戶端地址重要,它能由 IP 地址決定,HTTP 請求也來自該處。僅在請求參與的 IP 地址不是客戶端的 IP 地址的情況下才需要。這種情況發生在客戶端通過代理服務器與服務器進行通信的情形。當客戶端和服務器同時處在本地 NAT 網關時也需要。原因是服務器會發出客戶端的內部地址(RFC1918),這是不可到達的。所以客戶端必須清楚地把自己的外部可到達的 IP 地址發送到其他客戶端中。不同的服務器對此參數的解釋有所不同。某些只有當請求參與的 IP 地址屬于 RFC1918 時才允許。有些無條件允許,但有些則完全忽略。如果使用 IPv6 地址(如:2001:db8:1:2::100),則表示客戶端能通過 IPv6 進行通信。
  • numwant:可選。客戶端想從服務器接收的用戶數目。允許此值為“0”。如果不用此項,則默認值為 50 個用戶。
  • key:可選。一個不與任何用戶共享的另外的標識。當 IP 地址改變后,允許客戶端證明它們的標識。
  • trackerid:可選。如果先前發布包含服務器的 id,它應放在這里。

響應

  • failure reason:如果當前使用此值,則其余關鍵字不會使用。該值是可讀的錯誤消息,包括請求失敗的原因。(字符串)
  • warning message:(新)與失敗原因相似,但響應仍然會被正常處理。警告消息看起來像錯誤。
  • interval:以秒計算,是客戶端發送規則請求到服務器之后等待的時間。(強制)
  • min interval:最小發布時間間隔。當前客戶重發間隔不能小于此值。
  • tracker id:一個客戶端應在下一個通告發回的字符串。如果沒有該值,先前通告會發出一個服務器 id ,不要丟棄舊的值,一直使用它。
  • complete:擁有完整文件的用戶數,即做種者(整數)
  • incomplete:非種子用戶的數目,也叫“吸血者”(整數)
  • peers:是字典的列表,每個值都有如下的關鍵字:
    • peer id:用戶的自選擇 ID,如上述用來發送服務器請求的(字符串)
    • ip:用戶的 IP 地址(IPv4 或 IPv6 格式)或域名(字符串)
    • port:用戶的端口號(整數)

DHT

概述 Overview

每個節點有一個全局唯一的標識符,作為 "node ID"。節點 ID 是一個隨機選擇的 160bit 空間,BitTorrent infohash[2] 也使用這樣的 160bit 空間。 "距離"用來比較兩個節點 ID 之間或者節點 ID 和 infohash 之間的"遠近"。節點必須維護一個路由表,路由表中含有一部分其它節點的聯系信息。其它節點距離自己越近時,路由表信息越詳細。因此每個節點都知道 DHT 中離自己很"近"的節點的聯系信息,而離自己非常遠的 ID 的聯系信息卻知道的很少。

在 Kademlia 網絡中,距離是通過異或(XOR)計算的,結果為無符號整數。distance(A, B) = |A xor B|,值越小表示越近。

當節點要為 torrent 尋找 peer 時,它將自己路由表中的節點 ID 和 torrent 的 infohash 進行"距離對比"。然后向路由表中離 infohash 最近的節點發送請求,問它們正在下載這個 torrent 的 peer 的聯系信息。如果一個被聯系的節點知道下載這個 torrent 的 peer 信息,那個 peer 的聯系信息將被回復給當前節點。否則,那個被聯系的節點則必須回復在它的路由表中離該 torrent 的 infohash 最近的節點的聯系信息。最初的節點重復地請求比目標 infohash 更近的節點,直到不能再找到更近的節點為止。查詢完了之后,客戶端把自己作為一個 peer 插入到所有回復節點中離種子最近的那個節點中。

請求 peer 的返回值包含一個不透明的值,稱之為"令牌(token)"。如果一個節點宣布它所控制的 peer 正在下載一個種子,它必須在回復請求節點的同時,附加上對方向我們發送的最近的"令牌(token)"。這樣當一個節點試圖"宣布"正在下載一個種子時,被請求的節點核對令牌和發出請求的節點的 IP 地址。這是為了防止惡意的主機登記其它主機的種子。由于令牌僅僅由請求節點返回給收到令牌的同一個節點,所以沒有規定他的具體實現。但是令牌必須在一個規定的時間內被接受,超時后令牌則失效。在 BitTorrent 的實現中,token 是在 IP 地址后面連接一個 secret(通常是一個隨機數),這個 secret 每五分鐘改變一次,其中 token 在十分鐘以內是可接受的。

路由表 Routing Table

每個節點維護一個路由表保存已知的好節點。路由表中的節點是用來作為在 DHT 中請求的起始點。路由表中的節點是在不斷的向其他節點請求過程中,對方節點回復的。

并不是我們在請求過程中收到得節點都是平等的,有的節點是好的,而另一些則不是。許多使用 DHT 協議的節點都可以發送請求并接收回復,但是不能主動回復其他節點的請求。節點的路由表只包含已知的好節點,這很重要。好節點是指在過去的 15 分鐘以內,曾經對我們的某一個請求給出過回復的節點,或者曾經對我們的請求給出過一個回復(不用在15分鐘以內),并且在過去的 15 分鐘給我們發送過請求。上述兩種情況都可將節點視為好節點。在 15 分鐘之后,對方沒有上述 2 種情況發生,這個節點將變為可疑的。當節點不能給我們的一系列請求給出回復時,這個節點將變為壞的。相比那些未知狀態的節點,已知的好節點會被給于更高的優先級。

路由表覆蓋從 0 到 2^160 全部的節點 ID 空間。路由表又被劃分為桶(bucket),每個桶包含一部分的 ID 空間。空的路由表只有一個桶,它的 ID 范圍從 min=0 到 max=2^160。當 ID 為 N 的節點插入到表中時,它將被放到 ID 范圍在 min <= N < max 的 桶 中。空的路由表只有一個桶,所以所有的節點都將被放到這個桶中。每個桶最多只能保存 K 個節點,當前 K=8。當一個桶放滿了好節點之后,將不再允許新的節點加入,除非我們自身的節點 ID 在這個桶的范圍內。在這樣的情況下,這個桶將被分裂為 2 個新的桶,每個新桶的范圍都是原來舊桶的一半。原來舊桶中的節點將被重新分配到這兩個新的桶中。如果一個新表只有一個桶,這個包含整個范圍的桶將總被分裂為 2 個新的桶,每個桶的覆蓋范圍從 0..2^159 和 2159..2160。

當桶裝滿了好節點,新的節點會被丟棄。一旦桶中的某個節點變為了壞的節點,那么我們就用新的節點來替換這個壞的節點。如果桶中有在 15 分鐘內都沒有活躍過的節點,我們將這樣的節點視為可疑的節點,這時我們向最久沒有聯系的節點發送 ping。如果被 ping 的節點給出了回復,那么我們向下一個可疑的節點發送 ping,不斷這樣循環下去,直到有某一個節點沒有給出 ping 的回復,或者當前桶中的所有節點都是好的(也就是所有節點都不是可疑節點,他們在過去 15 分鐘內都有活動)。如果桶中的某個節點沒有對我們的 ping 給出回復,我們最好再試一次(再發送一次 ping,因為這個節點也許仍然是活躍的,但由于網絡擁塞,所以發生了丟包現象,注意 DHT 的包都是 UDP 的),而不是立即丟棄這個節點或者直接用新節點來替代它。這樣,我們得路由表將充滿穩定的長時間在線的節點。

每個桶都應該維持一個 lastchange 字段來表明桶中節點的"新鮮"度。當桶中的節點被 ping 并給出了回復,或者一個節點被加入到了桶,或者一個節點被新的節點所替代,桶的 lastchange 字段都應當被更新。如果一個桶的 lastchange 在過去的 15 分鐘內都沒有變化,那么我們將更新它。這個更新桶操作是這樣完成的:從這個桶所覆蓋的范圍中隨機選擇一個 ID,并對這個 ID 執行 find_nodes查找操作。常常收到請求的節點通常不需要常常更新自己的桶,反之,不常常收到請求的節點常常需要周期性的執行更新所有桶的操作,這樣才能保證當我們用到 DHT 的時候,里面有足夠多的好的節點。

在插入第一個節點到路由表并啟動服務后,這個節點應試著查找 DHT 中離自己更近的節點,這個查找工作是通過不斷的發出find_node 消息給越來越近的節點來完成的,當不能找到更近的節點時,這個擴散工作就結束了。路由表應當被啟動工作和客戶端軟件保存(也就是啟動的時候從客戶端中讀取路由表信息,結束的時候客戶端軟件記錄到文件中)。

協議消息

Kademlia協議共有四種消息

1. PING消息: 用來測試節點是否仍然在線
2. STORE消息: 在某個節點中存儲一個鍵值對
3. FIND_NODE消息: 消息請求的接收者將返回自己桶中離請求鍵值最近的K個節點: 將請求者請求的節點HASH和自己的HASH進行XOR計算,將計算結果
4. FIND_VALUE消息: 與FIND_NODE一樣,不過當請求的接收者存有請求者所請求的鍵的時候,它將返回相應鍵的值

DHT嗅探器的原理

DHT這種對等分布式網絡在帶來抗DDOS的優點的同時,也帶來了一些缺點

1. 偽造攻擊: 有些不聽話的用戶可能會在DHT網絡里搗亂,譬如說撒謊,明明自己不是奧巴馬,卻偏說自己是奧巴馬,這樣會誤導其他人無法正常獲取想要的資源
2. 嗅探攻擊: 另外,用戶在DHT網絡里的隱私可能會被竊聽,因為在DHT網絡里跟其他用戶交換資源的時候,難免會暴露自己的IP地址,所以別人就會知道你有什么資源,你在請求什么資源了。這也是目前DHT網絡里一直存在的一個弱點

參考:

https://wiki.theory.org/index.php/BitTorrentSpecification#Notes

https://fenying.gitbooks.io/bittorrent-specification-chinese-edition/content/

https://segmentfault.com/a/1190000002528378

http://www.cnblogs.com/LittleHann/p/6180296.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 前言 做了一個磁力鏈接和BT種子的搜索引擎 {Magnet & Torrent},因此把 DHT 協議重新看了一遍...
    justjavac閱讀 8,732評論 1 24
  • 今早六點,天天還沒亮,獨自從寶石山莊南門出發,漫步草山。 草山的樹林。 草山的朝霞。 傳...
    好心情_4dea閱讀 518評論 0 0
  • 小鴨子 鐵路邊有一個小湖 小湖里有一群小鴨子 小鴨子在湖里 追呀追鬧啊鬧 不管鐵路向何方 一列一列的火車 連著車里...
    路雨飛飛閱讀 430評論 10 3
  • 我如此的期待你的到來,雖然我內心是如此的清楚,這對于你不公平,我的孩子! 我曾一度希望自己做好所有準備,變成理想中...
    病小喵閱讀 246評論 0 0