dht find_node 无回应
dht find_node no response
我正在编写一个 dht 服务器并遇到了一些问题。
我将 find_node 请求发送给 bootstraps,他们 return 给我一些紧凑的节点信息(416 字节),其中包含 16 个节点信息
然后我解码并存储 ip 地址和端口,继续向这些节点发送 find_node 请求,但我没有收到任何响应。
服务器代码在这里(接收数据包并启动一个新线程将节点添加到列表中)
public void run() {
try {
while (true) {
byte[] buffer_rcv = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(buffer_rcv, buffer_rcv.length);
socket.receive(recvPacket);
System.out.println("get!!!");
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
LinkedList<Node> nodes = BDecode.bdecode_find_node(recvPacket);
for (Node n : nodes) {
table.add_node(n);
}
System.out.println("table size" + table.get_all_nodes().size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
System.out.println("waiting new packet!!!!!!!");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我从 sourceforge 下载了 jbittorrent api 并用它来 bdecode
public static LinkedList<Node> bdecode_find_node(DatagramPacket recvPacket) throws IOException {
byte[]nodes_compact_info = (byte[]) ((Map) new BDecoder().decodeByteArray(recvPacket.getData()).get("r")).get("nodes");
byte[]node_info = new byte[26];
byte[]node_id = new byte[20];
byte[]ip_byte = new byte[4];
byte[]port_byte = new byte[2];
int port;
LinkedList<Node> nodes = new LinkedList<>();
//System.out.println("nodes_compact_info.length"+nodes_compact_info.length);
for (int i = 0;i<nodes_compact_info.length/26;i++) { //416 = 16 * 26byte_per_node
//0-19 id 20 21 22 23 ip 24 25 port
node_info = Utils.subArray(nodes_compact_info, i*26, 26);
node_id=Utils.subArray(node_info, 0, 20);
ip_byte = Utils.subArray(node_info, 20, 4);
String ip = "";
for (int j = 0;j<ip_byte.length;j++) {
ip+=Utils.byteToUnsignedInt(node_info[j]);
ip+=".";
}
ip = ip.substring(0, ip.length()-1);
//System.out.println(ip);
port_byte = Utils.subArray(node_info, 24, 2);
port = Utils.byteArrayToInt(port_byte);
nodes.add(new Node(node_id, ip, port, new Date()));
}
return nodes;
}
最后我向列表
中的每个节点发送find_node请求
public void get_neighbor() {
ArrayList<Node> nodes = table.get_all_nodes();
System.out.println("*********get_neighbor!!!");
for (Node n : nodes) {
try {
byte[] find_node_query = BEncode.find_node(this.id, this.id);
DatagramPacket sendPacket = new DatagramPacket(find_node_query, find_node_query.length,
InetAddress.getByName(n.getIp()), n.getPort());
for (int i = 0;i<5;i++)
socket.send(sendPacket);
System.out.println("packet send to " + n.getIp() + ":" + n.getPort());
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
System.out.println("UnknownHostException" + n.getIp());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("cant send packet");
}
}
}
卡了好几天了,试了很多方法都找不到哪里不对,求大神指点。
node compact info
这是 return 编辑自 bootstrap 并在 bdecoding node compact info
之后
capture
send find_node to bootstrap
response from bootstrap
udp packet to node
I just found something. I fix the socket on port 6881, but when i send the packet, the port changes
是的,这是一个问题。您应该绑定一个 UDP 套接字,然后继续重用该套接字。根据 BEP 45 它也应该绑定到一个特定的地址。
.pcap file
数据包 #2,来自 bootstrap 节点的响应包含 16 个联系人。第一个联系人是id: 0f9c86a1085677f9f1edb519bfc16b626f19fb11, IPv4/Port: 92.255.216.47:29501
数据包 #18 尝试联系 47.216.255.92:29501
所以你在解码 IP 地址时交换字节。 Contacts are encoded in network byte order,即大端。
您不需要为此使用字符串处理,InetAddress.getByAddress 有一个采用字节数组的重载
我通过查看 .pcap 文件中的这四个数据包发现了一些问题
110 48.444854 10.3.157.234 82.221.103.244 BT-DHT 134
...
113 48.844328 82.221.103.244 10.3.157.234 BT-DHT 528 reply=16 nodes
114 48.911670 10.3.157.234 47.152.12.43 BT-DHT 134
115 48.912589 10.3.157.234 181.39.146.92 BT-DHT 134
这是发送到bootstrap节点的find_node请求:router.utorrent.com[82.221.103.244]
Frame 110: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 82.221.103.244
User Datagram Protocol, Src Port: 6883, Dst Port: 6881
BitTorrent DHT Protocol
Transaction ID: 7473
Key: t
Value: 7473
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: ef417ba2c490541a8981d7905036c814364750a6
Key: id
Value: ef417ba2c490541a8981d7905036c814364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
节点发送了 id
和 target
设置值:ef417ba2c490541a8981d7905036c814364750a6
所以这应该是它的 node_id .
这有一个小问题,因为编码字典中的键必须排序,但大多数实现无论如何都会接受请求。
d1:t2:ts1:y1:q1:q9:find_node1:ad2:id20:.A....T.....P6..6GP.6:target20:.A....T.....P6..6GP.ee
应该是:
d1:ad2:id20:.A....T.....P6..6GP.6:target20:.A....T.....P6..6GP.e1:q9:find_node1:t2:ts1:y1:qe
这是 bootstrap 节点的响应:
Frame 113: 528 bytes on wire (4224 bits), 528 bytes captured (4224 bits)
Ethernet II, Src: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0), Dst: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36)
Internet Protocol Version 4, Src: 82.221.103.244, Dst: 10.3.157.234
User Datagram Protocol, Src Port: 6881, Dst Port: 6883
BitTorrent DHT Protocol
ip: def983017ed6
Key: ip
Value: def983017ed6
Response values: Dictionary...
Key: r
Value: Dictionary...
id: ebff36697351ff4aec29cdbaabf2fbe3467cc267
Key: id
Value: ebff36697351ff4aec29cdbaabf2fbe3467cc267
nodes: 16
Key: nodes
Value: 16 nodes
Node 1 (id: 2f980c2befa8ae85856bfabd44fb76137c50e39e, IP/Port: 184.148.185.216:43611)
Node 2 (id: b527925cd9b0f4610904dd2d75aa8c5aa6c900e3, IP/Port: 201.92.140.89:63505)
Node 3 (id: 454d423032343241433131303030325858587a63, IP/Port: 119.136.154.198:23493)
Node 4 (id: 4dbe732bad993048936a71ae2c7be49dc9ab24f9, IP/Port: 27.209.68.82:16001)
Node 5 (id: 39a36bc7f75c494b90395113ab2fd5833c6d684c, IP/Port: 171.239.30.38:1035)
Node 6 (id: a5ac55cdfdf231bf35e4e68e3b89b5430f0eedd7, IP/Port: 109.154.41.107:58580)
Node 7 (id: 8f05d55f2129e53c4a1f87b13199b598c479b0aa, IP/Port: 189.78.63.188:27070)
Node 8 (id: d1bd0a25de085c18d8c45c60f681f7074b9e0458, IP/Port: 95.81.104.30:27196)
Node 9 (id: 30f0086f8618d7aa5a53b8ac0e3d5b080351fb9a, IP/Port: 70.118.138.155:26085)
Node 10 (id: dd4797facea363d908b629ce93183c241f08f478, IP/Port: 189.83.128.160:45381)
Node 11 (id: 0801a40c0e72581bc76e00262350243fc38d21af, IP/Port: 218.210.40.82:31021)
Node 12 (id: cacf92f943a69abcc24891919d80953b3e70526d, IP/Port: 120.148.25.109:59348)
Node 13 (id: 3f3834ab54f4215248f0f47d0d0265317d320b48, IP/Port: 189.62.200.109:49307)
Node 14 (id: fd81b802855925bee2b2ed89134788babe2328bb, IP/Port: 189.152.39.89:43529)
Node 15 (id: cef348726b9c1278675db1b1da4b605016aab4f8, IP/Port: 189.163.183.249:49937)
Node 16 (id: 96f24f9a50ee407836fd124932f69e7d49dcad32, IP/Port: 178.77.35.128:34304)
Transaction ID: 7473
Key: t
Value: 7473
Message type: Response
Key: y
Value: r
一个有 16 个节点的列表。
这是发送到列表中第一个节点的find_node请求:
Node 1 (id: 2f980c2befa8ae85856bfabd44fb76137c50e39e, IP/Port: 184.148.185.216:43611)
Frame 114: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 47.152.12.43
User Datagram Protocol, Src Port: 6883, Dst Port: 43611
BitTorrent DHT Protocol
Transaction ID: 6476
Key: t
Value: 6476
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: 2f980c2befa8ae85856bfabd44fb7614364750a6
Key: id
Value: 2f980c2befa8ae85856bfabd44fb7614364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
这里有更多问题:port
和 target
是正确的,
但是 id
是错误的。是查询节点id=2f980c2befa8ae85856bfabd44fb7614364750a6
而不是 查询节点 id =ef417ba2c490541a8981d7905036c814364750a6
,因为它应该是。
节点可能不会响应 'id thieves'.
IP
也是错误的,而不是 184.148.185.216
它是 47.152.12.43 = 0x2f980c2b
这是 查询节点 id 中的前四个字节。发错IP当然是致命问题
编码键未排序。
这是发送到列表中第二个节点的find_node请求:
Node 2 (id: b527925cd9b0f4610904dd2d75aa8c5aa6c900e3, IP/Port: 201.92.140.89:63505)
Frame 115: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 181.39.146.92
User Datagram Protocol, Src Port: 6883, Dst Port: 63505
BitTorrent DHT Protocol
Transaction ID: 6f69
Key: t
Value: 6f69
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: b527925cd9b0f4610904dd2d75aa8c14364750a6
Key: id
Value: b527925cd9b0f4610904dd2d75aa8c14364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
与第一个节点有相同的问题。以下所有请求都有相同的问题。
我正在编写一个 dht 服务器并遇到了一些问题。 我将 find_node 请求发送给 bootstraps,他们 return 给我一些紧凑的节点信息(416 字节),其中包含 16 个节点信息 然后我解码并存储 ip 地址和端口,继续向这些节点发送 find_node 请求,但我没有收到任何响应。
服务器代码在这里(接收数据包并启动一个新线程将节点添加到列表中)
public void run() {
try {
while (true) {
byte[] buffer_rcv = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(buffer_rcv, buffer_rcv.length);
socket.receive(recvPacket);
System.out.println("get!!!");
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
LinkedList<Node> nodes = BDecode.bdecode_find_node(recvPacket);
for (Node n : nodes) {
table.add_node(n);
}
System.out.println("table size" + table.get_all_nodes().size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
System.out.println("waiting new packet!!!!!!!");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我从 sourceforge 下载了 jbittorrent api 并用它来 bdecode
public static LinkedList<Node> bdecode_find_node(DatagramPacket recvPacket) throws IOException {
byte[]nodes_compact_info = (byte[]) ((Map) new BDecoder().decodeByteArray(recvPacket.getData()).get("r")).get("nodes");
byte[]node_info = new byte[26];
byte[]node_id = new byte[20];
byte[]ip_byte = new byte[4];
byte[]port_byte = new byte[2];
int port;
LinkedList<Node> nodes = new LinkedList<>();
//System.out.println("nodes_compact_info.length"+nodes_compact_info.length);
for (int i = 0;i<nodes_compact_info.length/26;i++) { //416 = 16 * 26byte_per_node
//0-19 id 20 21 22 23 ip 24 25 port
node_info = Utils.subArray(nodes_compact_info, i*26, 26);
node_id=Utils.subArray(node_info, 0, 20);
ip_byte = Utils.subArray(node_info, 20, 4);
String ip = "";
for (int j = 0;j<ip_byte.length;j++) {
ip+=Utils.byteToUnsignedInt(node_info[j]);
ip+=".";
}
ip = ip.substring(0, ip.length()-1);
//System.out.println(ip);
port_byte = Utils.subArray(node_info, 24, 2);
port = Utils.byteArrayToInt(port_byte);
nodes.add(new Node(node_id, ip, port, new Date()));
}
return nodes;
}
最后我向列表
中的每个节点发送find_node请求public void get_neighbor() {
ArrayList<Node> nodes = table.get_all_nodes();
System.out.println("*********get_neighbor!!!");
for (Node n : nodes) {
try {
byte[] find_node_query = BEncode.find_node(this.id, this.id);
DatagramPacket sendPacket = new DatagramPacket(find_node_query, find_node_query.length,
InetAddress.getByName(n.getIp()), n.getPort());
for (int i = 0;i<5;i++)
socket.send(sendPacket);
System.out.println("packet send to " + n.getIp() + ":" + n.getPort());
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
System.out.println("UnknownHostException" + n.getIp());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("cant send packet");
}
}
}
卡了好几天了,试了很多方法都找不到哪里不对,求大神指点。
node compact info
这是 return 编辑自 bootstrap 并在 bdecoding node compact info
之后capture
send find_node to bootstrap
response from bootstrap
udp packet to node
I just found something. I fix the socket on port 6881, but when i send the packet, the port changes
是的,这是一个问题。您应该绑定一个 UDP 套接字,然后继续重用该套接字。根据 BEP 45 它也应该绑定到一个特定的地址。
.pcap file
数据包 #2,来自 bootstrap 节点的响应包含 16 个联系人。第一个联系人是id: 0f9c86a1085677f9f1edb519bfc16b626f19fb11, IPv4/Port: 92.255.216.47:29501
数据包 #18 尝试联系 47.216.255.92:29501
所以你在解码 IP 地址时交换字节。 Contacts are encoded in network byte order,即大端。
您不需要为此使用字符串处理,InetAddress.getByAddress 有一个采用字节数组的重载
我通过查看 .pcap 文件中的这四个数据包发现了一些问题
110 48.444854 10.3.157.234 82.221.103.244 BT-DHT 134
...
113 48.844328 82.221.103.244 10.3.157.234 BT-DHT 528 reply=16 nodes
114 48.911670 10.3.157.234 47.152.12.43 BT-DHT 134
115 48.912589 10.3.157.234 181.39.146.92 BT-DHT 134
这是发送到bootstrap节点的find_node请求:router.utorrent.com[82.221.103.244]
Frame 110: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 82.221.103.244
User Datagram Protocol, Src Port: 6883, Dst Port: 6881
BitTorrent DHT Protocol
Transaction ID: 7473
Key: t
Value: 7473
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: ef417ba2c490541a8981d7905036c814364750a6
Key: id
Value: ef417ba2c490541a8981d7905036c814364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
节点发送了 id
和 target
设置值:ef417ba2c490541a8981d7905036c814364750a6
所以这应该是它的 node_id .
这有一个小问题,因为编码字典中的键必须排序,但大多数实现无论如何都会接受请求。
d1:t2:ts1:y1:q1:q9:find_node1:ad2:id20:.A....T.....P6..6GP.6:target20:.A....T.....P6..6GP.ee
应该是:
d1:ad2:id20:.A....T.....P6..6GP.6:target20:.A....T.....P6..6GP.e1:q9:find_node1:t2:ts1:y1:qe
这是 bootstrap 节点的响应:
Frame 113: 528 bytes on wire (4224 bits), 528 bytes captured (4224 bits)
Ethernet II, Src: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0), Dst: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36)
Internet Protocol Version 4, Src: 82.221.103.244, Dst: 10.3.157.234
User Datagram Protocol, Src Port: 6881, Dst Port: 6883
BitTorrent DHT Protocol
ip: def983017ed6
Key: ip
Value: def983017ed6
Response values: Dictionary...
Key: r
Value: Dictionary...
id: ebff36697351ff4aec29cdbaabf2fbe3467cc267
Key: id
Value: ebff36697351ff4aec29cdbaabf2fbe3467cc267
nodes: 16
Key: nodes
Value: 16 nodes
Node 1 (id: 2f980c2befa8ae85856bfabd44fb76137c50e39e, IP/Port: 184.148.185.216:43611)
Node 2 (id: b527925cd9b0f4610904dd2d75aa8c5aa6c900e3, IP/Port: 201.92.140.89:63505)
Node 3 (id: 454d423032343241433131303030325858587a63, IP/Port: 119.136.154.198:23493)
Node 4 (id: 4dbe732bad993048936a71ae2c7be49dc9ab24f9, IP/Port: 27.209.68.82:16001)
Node 5 (id: 39a36bc7f75c494b90395113ab2fd5833c6d684c, IP/Port: 171.239.30.38:1035)
Node 6 (id: a5ac55cdfdf231bf35e4e68e3b89b5430f0eedd7, IP/Port: 109.154.41.107:58580)
Node 7 (id: 8f05d55f2129e53c4a1f87b13199b598c479b0aa, IP/Port: 189.78.63.188:27070)
Node 8 (id: d1bd0a25de085c18d8c45c60f681f7074b9e0458, IP/Port: 95.81.104.30:27196)
Node 9 (id: 30f0086f8618d7aa5a53b8ac0e3d5b080351fb9a, IP/Port: 70.118.138.155:26085)
Node 10 (id: dd4797facea363d908b629ce93183c241f08f478, IP/Port: 189.83.128.160:45381)
Node 11 (id: 0801a40c0e72581bc76e00262350243fc38d21af, IP/Port: 218.210.40.82:31021)
Node 12 (id: cacf92f943a69abcc24891919d80953b3e70526d, IP/Port: 120.148.25.109:59348)
Node 13 (id: 3f3834ab54f4215248f0f47d0d0265317d320b48, IP/Port: 189.62.200.109:49307)
Node 14 (id: fd81b802855925bee2b2ed89134788babe2328bb, IP/Port: 189.152.39.89:43529)
Node 15 (id: cef348726b9c1278675db1b1da4b605016aab4f8, IP/Port: 189.163.183.249:49937)
Node 16 (id: 96f24f9a50ee407836fd124932f69e7d49dcad32, IP/Port: 178.77.35.128:34304)
Transaction ID: 7473
Key: t
Value: 7473
Message type: Response
Key: y
Value: r
一个有 16 个节点的列表。
这是发送到列表中第一个节点的find_node请求:
Node 1 (id: 2f980c2befa8ae85856bfabd44fb76137c50e39e, IP/Port: 184.148.185.216:43611)
Frame 114: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 47.152.12.43
User Datagram Protocol, Src Port: 6883, Dst Port: 43611
BitTorrent DHT Protocol
Transaction ID: 6476
Key: t
Value: 6476
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: 2f980c2befa8ae85856bfabd44fb7614364750a6
Key: id
Value: 2f980c2befa8ae85856bfabd44fb7614364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
这里有更多问题:port
和 target
是正确的,
但是 id
是错误的。是查询节点id=2f980c2befa8ae85856bfabd44fb7614364750a6
而不是 查询节点 id =ef417ba2c490541a8981d7905036c814364750a6
,因为它应该是。
节点可能不会响应 'id thieves'.
IP
也是错误的,而不是 184.148.185.216
它是 47.152.12.43 = 0x2f980c2b
这是 查询节点 id 中的前四个字节。发错IP当然是致命问题
编码键未排序。
这是发送到列表中第二个节点的find_node请求:
Node 2 (id: b527925cd9b0f4610904dd2d75aa8c5aa6c900e3, IP/Port: 201.92.140.89:63505)
Frame 115: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits)
Ethernet II, Src: IntelCor_1d:89:36 (5c:e0:c5:1d:89:36), Dst: Hangzhou_bf:8e:b0 (d4:61:fe:bf:8e:b0)
Internet Protocol Version 4, Src: 10.3.157.234, Dst: 181.39.146.92
User Datagram Protocol, Src Port: 6883, Dst Port: 63505
BitTorrent DHT Protocol
Transaction ID: 6f69
Key: t
Value: 6f69
Message type: Request
Key: y
Value: q
Request type: find_node
Key: q
Value: find_node
Request arguments: Dictionary...
Key: a
Value: Dictionary...
id: b527925cd9b0f4610904dd2d75aa8c14364750a6
Key: id
Value: b527925cd9b0f4610904dd2d75aa8c14364750a6
target: ef417ba2c490541a8981d7905036c814364750a6
Key: target
Value: ef417ba2c490541a8981d7905036c814364750a6
与第一个节点有相同的问题。以下所有请求都有相同的问题。