IMFile

IMFile

A Free And Unlimited BT / HTTP / HTTPS / eD2k Download Software From Singapore

BitTorrent 的 UDP Tracker 協議

簡介#

為了在一個 BitTorrent 下載群體中找到其他的節點,一個客戶端會向一個追蹤器發出宣告自己的請求。這個請求使用 HTTP 協議,並包含一些參數,比如 info_hash 、 key 、 peer_id 、 port 、 downloaded 、 left 、 uploaded 和 compact 等。追蹤器會返回一組節點(主機和端口)以及其他一些信息給客戶端。這個請求和響應都非常簡短。由於使用的是 TCP 協議,需要在發送請求前打開連接,在完成請求後關閉連接,這會引入額外的開銷。

系統開銷#

使用 HTTP 協議會帶來很大的系統開銷,因為在以太網層、 IP 層、 TCP 層和 HTTP 層都會有開銷,並且一個請求加上響應包含 50 個節點需要使用大約 10 個數據包,總共使用的字節數約為 1206 。通過使用基於 UDP 的協議可以顯著減少這種開銷,本文提出的協議只需 4 個數據包和約 618 個字節,將流量減少了 50% 。雖然對於客戶端來說每小時節省 1KB 並不重要,但對於為百萬節點提供服務的 Tracker 來說,減少流量的 50% 非常重要。此外,基於 UDP 的二進制協議不需要複雜的解析器和連接處理,降低了 Tracker 代碼的複雜性並提高了其性能。

UDP 連接 / 欺騙攻擊#

在理想情況下,只需要兩個數據包就可以完成通信。在使用 UDP 協議時,由於 UDP 協議是無連接的,因此可能會存在偽造源地址的情況。因此,tracker 必須採取措施來確保不會出現欺騙行為。為了避免這種情況發生,Tracker(一個網絡中用來協調客戶端與其他 peer 之間數據共享的伺服器程序)採取一些措施。

當客戶端向 tracker 發送一個請求時,tracker 會生成一個隨機數(connection_id),並將其發送給客戶端。客戶端再次向 tracker 發送請求時,需要帶上這個 connection_id,以便 tracker 可以驗證請求的來源是否合法。如果客戶端偽造了源地址,則不可能收到 tracker 發回的 connection_id,從而請求會被 tracker 拒絕。

為了確保 connection_id 不被客戶端猜測到,tracker 可以採用類似於 TCP 握手和 syn-cookie 的方法,在伺服器端存儲 connection_id,並僅在特定情況下才返回給客戶端使用。一個 connection_id 可以用於多個請求,並且客戶端可以在接收到 connection_id 後的一分鐘內使用它。 tracker 應該在發出 connection_id 後的兩分鐘內接受它,並驗證來自客戶端的請求是否匹配這個 connection_id 。

超時#

UDP 是一種不保證數據包可靠傳輸的協議,這意味著如果在傳輸過程中丟失了數據包,UDP 不會自動重傳。相反,使用 UDP 的應用程序需要負責處理丟失的數據包,並在必要時進行重傳。

為了處理丟失的數據包,客戶端應該在發送請求後等待伺服器的響應。如果在 15 * 2 ^ n 秒後沒有收到響應,則客戶端應該重新發送請求。重新發送請求的時間間隔從 15 秒開始,每次嘗試都會加倍,最多嘗試 8 次,即 3840 秒。

需要注意的是,如果連接 ID 已經過期,在重新發送請求之前需要重新請求新的連接 ID 。這確保了請求將被正確地認證並由伺服器進行處理。

樣例#

常規廣播:

t = 0: connect request
t = 1: connect response
t = 2: announce request
t = 3: announce response

連接超時:

t = 0: connect request
t = 15: connect request
t = 45: connect request
t = 105: connect request
etc

廣播超時:

t = 0:
t = 0: connect request
t = 1: connect response
t = 2: announce request
t = 17: announce request
t = 47: announce request
t = 107: connect request (because connection ID expired)
t = 227: connect request
etc

多重請求:

t = 0: connect request
t = 1: connect response
t = 2: announce request
t = 3: announce response
t = 4: announce request
t = 5: announce response
t = 60: announce request
t = 61: announce response
t = 62: connect request
t = 63: connect response
t = 64: announce request
t = 64: scrape request
t = 64: scrape request
t = 64: announce request
t = 65: announce response
t = 66: announce response
t = 67: scrape response
t = 68: scrape response

UDP Tracker 協議#

所有數值(例如整數或浮點數)在發送時都應該按照網絡字節順序(大端序)進行編碼。此外,不應該預期每個數據包都具有確定的大小。因為將來可能會通過添加新功能來增加數據包的大小。

連接#

Before announcing or scraping, you have to obtain a connection ID.

  1. Choose a random transaction ID.
  2. Fill the connect request structure.
  3. Send the packet.

對於進行”announcing” 或 “scraping” 操作之前,需要先獲取一個連接 ID 的過程。步驟如下:

  1. 隨機生成一個 Transaction ID 作為唯一標識符。
  2. 填充連接請求結構體。
  3. 發送請求數據包。

連接請求:

Offset  Size            Name            Value
0       64-bit integer  protocol_id     0x41727101980 // magic constant
8       32-bit integer  action          0 // connect
12      32-bit integer  transaction_id
16
  1. 接收數據包。
  2. 檢查它的長度是否至少為 16 字節。
  3. 檢查接收到的數據包中的 Transaction ID 是否與之前發送請求時選擇的 ID 一致。
  4. 檢查數據包中的操作是否為”connect” 。
  5. 將數據包中的 Connection ID 存儲到本地,並用於後續操作。

連接響應:

Offset  Size            Name            Value
0       32-bit integer  action          0 // connect
4       32-bit integer  transaction_id
8       64-bit integer  connection_id
16

廣播#

  1. 從系統中隨機選擇一個 Transaction ID 。
  2. 填入一個廣播請求結構。
  3. 發送數據包。

IPv4 廣播請求:

Offset  Size    Name    Value
0       64-bit integer  connection_id
8       32-bit integer  action          1 // announce
12      32-bit integer  transaction_id
16      20-byte string  info_hash
36      20-byte string  peer_id
56      64-bit integer  downloaded
64      64-bit integer  left
72      64-bit integer  uploaded
80      32-bit integer  event           0 // 0: none; 1: completed; 2: started; 3: stopped
84      32-bit integer  IP address      0 // default
88      32-bit integer  key
92      32-bit integer  num_want        -1 // default
96      16-bit integer  port
98
  1. 接收數據包。
  2. 檢查數據包的長度是否至少為 20 字節。
  3. 檢查數據包中的交易 ID 是否與之前選擇的交易 ID 相等,以確保接收到的是之前發送的通告請求的響應。
  4. 檢查數據包中的操作是否為 “announce” 。
  5. 進行時間間隔檢查。如果與上次廣播請求時間不足一定時間間隔(interval 秒),則 不再進行廣播請求;否則,可以繼續進行廣播請求或等待事件觸發後再次請求。

大多數 Tracker 只在某些特定情況下才會考慮 IP 地址字段。

IPv4 廣播請求:

Offset      Size            Name            Value
0           32-bit integer  action          1 // announce
4           32-bit integer  transaction_id
8           32-bit integer  interval
12          32-bit integer  leechers
16          32-bit integer  seeders
20 + 6 * n  32-bit integer  IP address
24 + 6 * n  16-bit integer  TCP port
20 + 6 * N
IPv6#

IPv6 和 IPv4 在協議結構上的區別以及如何在使用中進行適配。其中,IPv6 和 IPv4 的消息格式基本相同,但是在回應消息中,<IP 地址、TCP 端口> 對的步進大小從 6 字節變成了 18 字節。此外,在請求消息中,IP 地址字段仍然是 32 位寬度,不能用於 IPv6,並且始終應該設置為 0 。

同時,該段落還提到了適配的方式:根據 UDP 包的地址族來確定所使用的格式,即來自 IPv4 地址的數據包使用 IPv4 格式,來自 IPv6 地址的數據包使用 IPv6 格式。最後,對於將主機名解析為 IPv4 和 IPv6 並向兩個傳輸使用相同密鑰的客戶端,需要確保跟蹤器能夠準確地匹配兩個通告,以實現準確統計。

抓取#

最多可以同時獲取約 74 個種子文件的信息。無法使用此協議完成完整的數據抓取。

  1. 隨機選擇一個 Transaction ID 。
  2. 填充抓取請求結構。
  3. 發送數據包。

抓取請求:

Offset          Size            Name            Value
0               64-bit integer  connection_id
8               32-bit integer  action          2 // scrape
12              32-bit integer  transaction_id
16 + 20 * n     20-byte string  info_hash
16 + 20 * N
  1. 接受數據包。
  2. 檢查數據包的長度是否至少為 8 字節。
  3. 檢查該數據包中的 Transaction ID 是否與之前你選擇的相同。
  4. 檢查數據包中的操作是否為 “scrape” 。

抓取響應:

Offset      Size            Name            Value
0           32-bit integer  action          2 // scrape
4           32-bit integer  transaction_id
8 + 12 * n  32-bit integer  seeders
12 + 12 * n 32-bit integer  completed
16 + 12 * n 32-bit integer  leechers
8 + 12 * N

如果 tracker 遇到錯誤,可能會發送一個錯誤數據包。

  1. 接受數據包。
  2. 檢查數據包的長度是否至少為 8 字節。
  3. 檢查該數據包中的 Transaction ID 是否與之前你選擇的相同。

錯誤#

錯誤響應:

Offset  Size            Name            Value
0       32-bit integer  action          3 // error
4       32-bit integer  transaction_id
8       string  message

現有實例#

IMFile,Azureus,libtorrent,opentracker,XBT Client 和 XBT Tracker 支持該協議。

插件#

為了保持協議的兼容性,一般不會在協議中包含擴展位或版本字段。客戶端和 Tracker 也不應該假定數據包的大小。這樣做可以在不破壞兼容性的情況下添加額外的字段。換句話說,通過避免固定數據包長度和格式,協議可以更容易地進行擴展和更新,並且可以保持向後兼容性。

總結#

UDP Tracker Protocol for BitTorrent 是一種用於點對點文件共享協議 BitTorrent 中的追蹤器通信協議。它是基於 UDP 協議的,相較於 HTTP 協議,可以更快地傳輸數據,同時也具有更好的擴展性和高效性。

通過 UDP Tracker Protocol,BitTorrent 客戶端可以向追蹤器發送請求,獲取連接到種子的其他用戶列表。這些用戶可以幫助下載者提供文件塊,提高下載速度。此外,追蹤器還可以提供有關特定種子的統計信息,如上傳和下載速度、剩餘時間等。

儘管 UDP Tracker Protocol 具有許多優點,但由於其本質上是無狀態的,因此在某些情況下可能會遇到一些問題,例如有時會丟失請求或響應。為了解決這些問題,很多 BitTorrent 客戶端還支持 HTTP Tracker Protocol,同時使用兩種不同的追蹤器通信協議以提高可靠性。

參考鏈接#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。