* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Implementation of the Gnutella protocol in Python
Survey
Document related concepts
Asynchronous Transfer Mode wikipedia , lookup
Airborne Networking wikipedia , lookup
TCP congestion control wikipedia , lookup
Deep packet inspection wikipedia , lookup
Wake-on-LAN wikipedia , lookup
Point-to-Point Protocol over Ethernet wikipedia , lookup
Internet protocol suite wikipedia , lookup
Zero-configuration networking wikipedia , lookup
List of wireless community networks by region wikipedia , lookup
IEEE 802.1aq wikipedia , lookup
Recursive InterNetwork Architecture (RINA) wikipedia , lookup
Cracking of wireless networks wikipedia , lookup
UniPro protocol stack wikipedia , lookup
Transcript
Implementation of the Gnutella protocol in Python Israel Herraiz Tabernero [email protected] (cc) 2005 Israel Herraiz Tabernero Some rights reserved. This work is licensed under the Creative Commons Attribution-ShareAlike License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/ or send a letter to Creative Commons, 559 Nathan Abbot Way, Stanford, California 94305, USA 2 Contents 1 Introduction 1 1.1 Description of the protocol . . . . . . . . . . . . . . . . . . . . 1 1.2 Payloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.1 Ping . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.2 Pong . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.3 Query . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.4 QueryHit . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.5 Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3 Routing algorithm . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 File downloads . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2 Examples of use 7 2.1 How to create a new servent . . . . . . . . . . . . . . . . . . . 7 2.2 Video examples . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.1 First video . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.2 Second video . . . . . . . . . . . . . . . . . . . . . . . 12 3 Description of the library 13 4 Analyzing the traffic with Ethereal 14 A pyGnutella traffic analyzed with Ethereal 16 References 24 i 1 Introduction This work describes the Gnutella protocol, and how it was implemented in the Python language. The implemented version is 0.4 (document revision 1.2). There is a project in SourceForge.net, for those who are willing to collaborate in the development. The project is at http://sf.net/projects/pygnutella. The last version of the library is available in the CVS repository of that project. As the protocol specification says [1], Gnutella is a protocol for distributed search. Each node of the network is at the same time a server and a client, and so they are named in the specification servents. The algorithm to try to find a resource in the network is flooding; each time a servent receives a query, it resends the query to the rest of nodes to which are connected, and if the resource is available in that node, sends a reply following the same path than the initial query. There are currently two versions of the protocol: the stable one, 0.4, which is the version implemented and described in this document, and the unstable one (when this document was written), 0.6, which includes some improvements (intelligent query routing [2], SHA-1 checksums, query hit transmission via UDP, querying via UDP, dynamic queries via UDP, file transfers via UDP, XML meta data, parallel downloading in slices). The version 0.4 is quite simple, and it is not intended to share files over a net, rather to look for that files. 1.1 Description of the protocol There are five descriptors which define the possible communications between the nodes: • Ping Used to actively discover hosts on the network. A servent receiving a Ping descriptor should respond with one or more Pong descriptors, and resend the ping to the rest of nodes. • Pong The response to a Ping. Includes the address of a connected Gnutella servent and information 1 • Query Used to look for resources (f.e., files) over the network. A servent receiving a Query, should respond with a QueryHit if the search criteria match with any resource of that node, and resend the query to the rest of nodes. • QueryHit The response to a Query. This descriptor provides the necessary information to obtain the searched resource from the source node. • Push A mechanism that allows a firewalled servent to provide resources to the network. A servent must connect to an existing node, in order to be part of the network. How to solve the address of an existing node is not part of the protocol, although hosts cache servers exist [3]. Once the address of an existing node is known, the node must establish a TCP/IP connection to the servent, and send the following ASCII string: GNUTELLA CONNECT/0.4\n\n If the existing node is ready, should respond with GNUTELLA OK\n\n Any other response means that the node has rejected the connection. The annotated version of the protocol [4] remarks that the servent should accept not only \n characters, but also \r or \r\n characters at the end of each string. In the version 0.6, this handshaking mechanism is a bit more complex, including some metadata (for example, User Agent). In theory, 0.6 version compliant nodes can accept connections from 0.4 compliant nodes, but in practice these nodes used to accept only connections from 0.6 nodes1 . 1 As the 0.6 specification says (section 2.1) [5], the details for how to accept connection requests, as well as how to select what other Gnutella hosts to connect to, are included in the appendix 4 of the specification, but at this moment that appendix is missing in the document. 2 Once the servent is connected to the network, it can send descriptors to the rest of nodes. Each descriptor has a header of 23 bytes, with the following fields: • Descriptor ID (16 bytes). Each descriptor should have an unique id. • Payload descriptor (1 byte). Ping, Pong, Push, Query or QueryHit. • Time to live (1 byte). It should be less than 127 if the node is on the Internet. • Hops (1 byte). It should be less than 127 if the node is on the Internet. • Payload length (4 bytes). The length of the descriptor immediately following this header. The packets are dropped when the Time to Live (TTL) expires. If the TTL is excessive, the amount of traffic in the network will be high, and then the performance low. The payload length is fundamental to identify the descriptors in the input stream. There are not characters remarking the beginning or end of the headers and descriptors. If a node loose the sync with the input stream, it should drop the connection and try to establish a new one. 1.2 1.2.1 Payloads Ping The descriptor for this payload is 0x00. Its length is zero. If a node receives a ping, should respond with a Pong, and try to resend the Ping to the rest of nodes if the TTL has not expired. 1.2.2 Pong The descriptor for this payload is 0x01. Its length is 14 bytes. It contains the following fields: 3 • Port (2 bytes). The port number on which the responding host can accept incoming connections. • IP (4 bytes). The IP address of the responding host (IPv4 format). • Number of files shared (4 bytes). • Number of kilobytes shared (4 bytes). Pong descriptors are only sent in response to a Ping descriptor. The servent can send more than one Pong descriptor; this is useful, for example, if the servent has cached the addresses of other nodes, because it can send one Pong for each address. The descriptor id in the header should be the same than the descriptor id in the original Ping. 1.2.3 Query The descriptor for this payload is 0x80. It has not a fixed length. It contains the following fields: • Minimum speed (2 bytes). The minimum speed (in kbps) of servents that should respond to this message. • Search criteria. A null (0x00) terminated string. The length of the payload (in spite of the null terminated string, that could be helpful to identify the end of the payload) should match the payload length field in the header. 1.2.4 QueryHit The descriptor for this payload is 0x81. It has not a fixed length. It contains the following fields: • Number of hits (1 byte). 4 • Port (2 bytes). • IP address (4 bytes). • Speed (4 bytes). The speed of the responding host, in kbps. • Result set. A set of responses to the corresponding query, with the following fields: – File index (4 bytes). An index assigned by the responding host. – File size (4 bytes). In bytes. – File name. A string finished in a double null (0x0000). This result set contains that structure as many times as the first field in the payload (Number of hits). • Servent identifier (16 bytes). This identifier should be unique for each host. It can be some function of the IP address of the host. This descriptor should be sent only in response to Query descriptors. The QueryHit is sent following the same path than the original Query. The descriptor id in the header should be the same than the descriptor id in the original Query. 1.2.5 Push The descriptor for this payload is 0x40. Its size is 26 bytes. It contains the following fields: • Servent identifier (16 bytes). This identifier should be unique for each host. It can be some function of the IP address of the host. In this case, it must be the identifier of the node that is behind the firewall. • File index (4 bytes). The index of the file that can not be shared because this node is behind a firewall. • IP address (4 bytes). • Port (2 bytes). 5 QueryHit Node server Node client Firewall Push Figure 1: Pushing procedure. A node behind a firewall can not act as a server but can act as a client. The QueryHit and the Push descriptors are sent by the same socket, corresponding to the initial connection from the firewalled servent to one node in the Gnutella network. A client node A sends a Query. The Query reaches a server node B which is behind a firewall. B responds with a QueryHit, but as it is behind a firewall, it can not share files2 , so the connection from A to B is not possible. Then A sends a Push to B, and then B begins the connection to A, in order to share the file that is in B. More details are given in the specification document [1]. 1.3 Routing algorithm Each servent must route each descriptor to the rest of nodes. The algorithm is quite simple. Ping and Query descriptors are send to all the nodes directly connected to the each node (except the one that delivered the incoming 2 Because this require to create a new connection from A to B, because the file downloads are made by a direct HTTP connection between the nodes, and not in the Gnutella network. 6 descriptor), until the TTL expires. Pong descriptors must be sent only along the same path than the incoming Ping. The Pong must have the same identifier than the incoming Ping. The same procedure applies to QueryHit and Query. In the case of Push descriptors, they must be sent following the same path than the incoming QueryHit descriptor. In each node, the TTL of each descriptor must be decremented in one unit, and the hops must be increased in one unit. If the TTL is zero, the node must drop that descriptor. If a servent receives a descriptor that it has received before, it should avoid to resend to other nodes, to avoid waste traffic in the network. If a servent receives a Pong or a QueryHit descriptor, and it has not seen a Ping or Query with the same identifier, it should drop the Pong or QueryHit descriptor. 1.4 File downloads The file downloads are made out of the Gnutella network. The client node establish a HTTP connection with the server node, in order to obtain the file. More details are given in the specification document [1]. 2 Examples of use In this section we show some examples of use of the library. The full documentation of the library is available at [6]. For the examples is required a Python console, and the pyGnutella module in one of the directories of the PYTHONPATH environment variable. 2.1 How to create a new servent First of all, let’s initiate a new Python console: 7 herraiz@arenales:~ $ python Python 2.4.1 (#2, Mar 30 2005, 21:51:10) [GCC 3.3.5 (Debian 1:3.3.5-8ubuntu2)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> From the console, let’s call the pyGnutella module, and create a new Servent: >>> from pygnutella import * >>> a = Servent() This node can act as a client and as a server. To begin the server, we must use the beginServer method: >>> a.beginServer() >>> DEBUG: *1* Server started By default, debug messages are shown. Now we can try to connect to this server using any client. For example, with a Telnet session from another console: herraiz@arenales:~ $ telnet localhost 6346 Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is ’^]’. At the same moment, in the Python console we must obtain a debug message: DEBUG: *1* Client connected to this server If we try to connect GNUTELLA CONNECT/0.4 (pressing Enter twice) another message is shown in the Python console 8 DEBUG: *1* Connection request succeded and in the Telnet session we obtain the next message GNUTELLA OK (plus two end of line characters) Each servent can accept any number of clients. For example, let’s create another servent from the Python console: >>> b = Servent() >>> b.connect(a.host_address) The following debug messages are shown: >>> DEBUG: DEBUG: *2* DEBUG: *1* DEBUG: *1* *2* Begin connection Trying to connect to (’127.0.0.1’, 6346) Client connected to this server Connection request succeded Now, if we send a Ping from a, the Telnet session and the b servent should receive the descriptor. In the Telnet session, we obtain: (Ping descriptor) (the string may differ, because the 16 byte identifier is random) and in the Python console, we can see the debug messages: >>> DEBUG: *2* Pong response because it is not mine, and it is the first time I s DEBUG: *2* Ping routing DEBUG: *1* Catched pong from socket 127.0.0.1:6346 The b servent has sent a Pong, which has been catched by a. The Telnet session has not responded. If the Ping is sent by b, 9 the Telnet session should also receive the Ping: (Ping descriptor) and in the Python console we obtain the next messages: >>> DEBUG: *1* Pong response because it is not mine, and it is the first time I s DEBUG: *1* Ping routing DEBUG: *2* Catched pong from socket 127.0.0.1:6346 As we can see, the two servents initiated in the Python console have the same address. As we have not initiated a server in b, there is not an immediate conflict, but the two servents could not share files because of this error. So let’s change the address of b, and initiate a new server on b >>> b.host_address = (’127.0.0.1’,6345) >>> b.beginServer() >>> DEBUG: *2* Server started Now, for example, we can begin a new Telnet session, to connect to this new server herraiz@arenales:~ $ telnet localhost 6345 Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is ’^]’. And in the Python console >>> DEBUG: *2* Client connected to this server By default, the servers wait until the connection is succeeded: 10 DEBUG: *2* Timeout while waiting for connection request DEBUG: *2* Timeout while waiting for connection request DEBUG: *2* Connection request succeded (in this case, some seconds have elapsed since the beginning of the session, and the request for a new connection to the servent). As all the nodes are connected, each Ping or Query should be received by all the nodes. For example: >>> b.sendQuery("mp3",512) DEBUG: *2* Query sent >>> DEBUG: *1* Query proccesed DEBUG: *1* 512 DEBUG: *1* mp3 DEBUG: *1* Query sent DEBUG: *1* Query routing DEBUG: *2* QueryHit processed DEBUG: Query Hit processed because it’s mine The descriptors have been received also in the two Telnet sessions: (Query descriptor)mp3 2.2 Video examples There are some videos showing the usage of the library. The videos are available at http://pygnutella.sf.net/videos/. 2.2.1 First video In the first video there are three nodes: • arenales • calibre 11 • gsyc016 In this case, arenales can not respond to the connection requests because it is overloaded3 . In the first step, we have opened a Python shell in each node, and created the Servents. Then, we started a server in gsyc016 and in arenales. After that, we tried to connect to these servers from calibre. The connection from calibre to gsyc016 is successful, but the one to arenales is not. Finally, a Ping is sent from calibre, and only gsyc016 is responding with a Pong. The Ping is not routed because the server is only attending one socket, which is the incoming socket. 2.2.2 Second video In the second video there are also three nodes: • gsyc048 • gsyc016 • calibre gsyc048 is acting as a server, and connections are initiated from gsyc016 and from calibre. gsyc016 is sending a Ping, and catching Pongs from gsyc048 and calibre. The Ping is routed by gsy048 to calibre, then calibre has sent a Pong following the same socket than the incoming Ping, the Pong has reached gsyc048, which has sent again the Pong following the same socket than the original Ping, and so finally the Pong descriptor has been received by the node which sent the Ping. Moreover, gsyc048 itself responds to the Ping with another Pong descriptor. calibre sends also another Ping, obtaining Pongs from the other two nodes. The algorithm is the same, but in this case the descriptors follow the opposite way. 3 It is recording the video. 12 After that the two nodes send Queries to the rest of the network, obtaining responses from the rest of nodes. The routing algorithm is the same than above (with Query and QueryHit instead of Ping and Pong). As Ping as Query descriptors are dropped when all the nodes have received the descriptors. The next step is a loop of five iterations, sending Pings from calibre. For each iteration, calibre receives a Pong from the each node of the rest of the network. The Ping descriptors are appropriately routed by gsyc048, which is the node in the middle. And again, the loop is repeated, this time with Query descriptors instead of Ping descriptors. 3 Description of the library The library has been implemented in Python language. The library is object oriented, and has five classes. Moreover, the library is multithread, so an arbitrary number of sockets can be handled in parallel. The classes of the library are the following: • AttendConnectionThread Objects of this type attend the incoming petitions, which a servent receive via each socket, once the connection has been established. Each object creates a new thread, so the main thread is not locked to attend the petitions of each socket, and so an arbitrary number of sockets can be attended in parallel by each servent. • ClientThread Objects of this type try to establish a new connection to a servent in a Gnutella network. Each object creates a new thread, so while the node is waiting for the response of the servent, the main thread is not locked. • ListenToConnectionsThread Objects of this type attend the petitions of each new connection. Each object creates a new thread, just after the first connection is estab13 lished. The number of simultaneous connections can be configured. Default value is 5. • Servent This is the main class of the library. Each object represents a node in a Gnutella network. Each node is able to accept incoming connections, to connect to other nodes, and to respond to the petitions included in the specification of the Gnutella protocol. Each object creates new threads when they are needed, in a transparent way (the developer should not care about the thread that are started or stopped). • ServerThread Each object of this type prepares the node to accept incoming connections, and accepts the first connection. Once the first connection is accepted and established, it creates two threads, one of the type AttendConnectionThread to attend the incoming petitions of the first connection, and one of the type ListenToConnectionsThread to accept new connections. The parent thread finish after the creation of these two threads. 4 Analyzing the traffic with Ethereal In this section, some data obtained using the protocol’s analyzer Ethereal are shown. Moreover, some comparisons with well known Gnutella clients are made. For capturing the data from pygnutella a few nodes were launched in an unique host, each node listening in a different port. Then some Pings and Queries were sent by some nodes, and the rest of nodes responded to that petitions. The whole traffic was captured meanwhile. In the appendix A a sample of packets generated by pyGnutella servents are shown: • The first is a Ping packet. In the Gnutella protocol section we can see that the TTL is 4 and the number of hops is 1, so the initial TTL was 5, and this packet has been resent by a node different than the node which originated the Ping. • The second is a Pong packet, with a TTL of 5 and a number of hops of 0, so it comes from its original servent. We can see that the responding node is sharing 0 files (for a total amount of 0 bytes). 14 • The third is a Query. We can see that the servent which created this petition is looking for “mp3”, but only coming from nodes which can serve at least at 512 kbps. • The next is a combination of a Pong and a Query. As the source and origin of the two descriptors were the same, and the time of generation was almost the same, Ethereal has joined the two descriptors in only one packet. But if we see the section Gnutella protocol, we can notice that in effect there are two descriptors with different headers. • The last packet is a QueryHit. In this case, the responding node is not sharing files, because the QueryHit was generated only due to debugging purposes. We captured also the traffic of some well known Gnutella clients. All the files are available at http://pygnutella.sf.net/ethereal/, but the clients tested were implementing the version 0.6 of the protocol. So we could not connect these clients with pyGnutella servents. Moreover, Ethereal (version 0.10.10) did not recognise the 0.6 traffic4 . In any case, Ethereal has recognised the traffic generated by pyGnutella as Gnutella traffic, and was able to extract the information from each packet, so we can think that our implementation is according to the specification. 4 It only remarked that it was Gnutella traffic, but it was not able to extract the information from the packet 15 A No. pyGnutella traffic analyzed with Ethereal Time 50 5.015690 Source Destination Protocol Info localhost.localdomain localhost.localdomain Gnutella Ping Frame 50 (77 bytes on wire, 77 bytes captured) Arrival Time: Aug 3, 2005 17:49:37.323556000 Time delta from previous packet: 5.015690000 seconds Time since reference or first frame: 5.015690000 seconds Frame Number: 50 Packet Length: 77 bytes Capture Length: 77 bytes Protocols in frame: eth:ip:tcp:gnutella Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00 Destination: 00:00:00:00:00:00 (00:00:00_00:00:00) Source: 00:00:00:00:00:00 (00:00:00_00:00:00) Type: IP (0x0800) Internet Protocol, Src Addr: localhost.localdomain (127.0.0.1), Dst Addr: localhost.localdomain Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 63 Identification: 0xa229 (41513) Flags: 0x04 (Don’t Fragment) 0... = Reserved bit: Not set .1.. = Don’t fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0x9a8d (correct) Source: localhost.localdomain (127.0.0.1) Destination: localhost.localdomain (127.0.0.1) Transmission Control Protocol, Src Port: 48228 (48228), Dst Port: gnutella-svc (6346), Seq: 23, Source port: 48228 (48228) Destination port: gnutella-svc (6346) Sequence number: 23 (relative sequence number) Next sequence number: 46 (relative sequence number) Acknowledgement number: 14 (relative ack number) Header length: 20 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set 16 .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 32767 Checksum: 0x5796 (correct) Gnutella Protocol Descriptor Header ID: 8F1157FEB71AA70BF76FFA578EAB34AE Payload: 0 (Ping) TTL: 4 Hops: 1 Length: 0 No. Time 57 5.018522 Source Destination Protocol Info localhost.localdomain localhost.localdomain Gnutella Pong Frame 57 (91 bytes on wire, 91 bytes captured) Arrival Time: Aug 3, 2005 17:49:37.326388000 Time delta from previous packet: 0.001166000 seconds Time since reference or first frame: 5.018522000 seconds Frame Number: 57 Packet Length: 91 bytes Capture Length: 91 bytes Protocols in frame: eth:ip:tcp:gnutella Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00 Destination: 00:00:00:00:00:00 (00:00:00_00:00:00) Source: 00:00:00:00:00:00 (00:00:00_00:00:00) Type: IP (0x0800) Internet Protocol, Src Addr: localhost.localdomain (127.0.0.1), Dst Addr: localhost.localdomain Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 77 Identification: 0x5eab (24235) Flags: 0x04 (Don’t Fragment) 0... = Reserved bit: Not set .1.. = Don’t fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0xddfd (correct) Source: localhost.localdomain (127.0.0.1) Destination: localhost.localdomain (127.0.0.1) Transmission Control Protocol, Src Port: gnutella-svc (6346), Dst Port: 48225 (48225), Seq: 14, 17 Source port: gnutella-svc (6346) Destination port: 48225 (48225) Sequence number: 14 (relative sequence number) Next sequence number: 51 (relative sequence number) Acknowledgement number: 46 (relative ack number) Header length: 20 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 32767 Checksum: 0xdaa6 (correct) Gnutella Protocol Descriptor Header ID: 8F1157FEB71AA70BF76FFA578EAB34AE Payload: 1 (Pong) TTL: 5 Hops: 0 Length: 14 Pong Port: 6346 IP: localhost.localdomain (127.0.0.1) Files Shared: 0 KBytes Shared: 0 No. Time 76 10.018983 Source Destination Protocol Info localhost.localdomain localhost.localdomain Gnutella Query Frame 76 (83 bytes on wire, 83 bytes captured) Arrival Time: Aug 3, 2005 17:49:42.326849000 Time delta from previous packet: 0.000171000 seconds Time since reference or first frame: 10.018983000 seconds Frame Number: 76 Packet Length: 83 bytes Capture Length: 83 bytes Protocols in frame: eth:ip:tcp:gnutella Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00 Destination: 00:00:00:00:00:00 (00:00:00_00:00:00) Source: 00:00:00:00:00:00 (00:00:00_00:00:00) Type: IP (0x0800) Internet Protocol, Src Addr: localhost.localdomain (127.0.0.1), Dst Addr: localhost.localdomain Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 18 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 69 Identification: 0x5eaf (24239) Flags: 0x04 (Don’t Fragment) 0... = Reserved bit: Not set .1.. = Don’t fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0xde01 (correct) Source: localhost.localdomain (127.0.0.1) Destination: localhost.localdomain (127.0.0.1) Transmission Control Protocol, Src Port: gnutella-svc (6346), Dst Port: 48225 (48225), Seq: 74, Source port: gnutella-svc (6346) Destination port: 48225 (48225) Sequence number: 74 (relative sequence number) Next sequence number: 103 (relative sequence number) Acknowledgement number: 46 (relative ack number) Header length: 20 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 32767 Checksum: 0x1e53 (correct) Gnutella Protocol Descriptor Header ID: EB98BB6A75D7318D4D3783CD31598E61 Payload: 128 (Query) TTL: 5 Hops: 0 Length: 6 Query Min Speed: 512 Search: mp3 No. Time 94 10.023551 Source Destination Protocol Info localhost.localdomain localhost.localdomain Gnutella Pong, Query Frame 94 (121 bytes on wire, 121 bytes captured) 19 Arrival Time: Aug 3, 2005 17:49:42.331417000 Time delta from previous packet: 0.000017000 seconds Time since reference or first frame: 10.023551000 seconds Frame Number: 94 Packet Length: 121 bytes Capture Length: 121 bytes Protocols in frame: eth:ip:tcp:gnutella Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00 Destination: 00:00:00:00:00:00 (00:00:00_00:00:00) Source: 00:00:00:00:00:00 (00:00:00_00:00:00) Type: IP (0x0800) Internet Protocol, Src Addr: localhost.localdomain (127.0.0.1), Dst Addr: localhost.localdomain Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 107 Identification: 0x55de (21982) Flags: 0x04 (Don’t Fragment) 0... = Reserved bit: Not set .1.. = Don’t fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0xe6ac (correct) Source: localhost.localdomain (127.0.0.1) Destination: localhost.localdomain (127.0.0.1) Transmission Control Protocol, Src Port: 48225 (48225), Dst Port: gnutella-svc (6346), Seq: 69, Source port: 48225 (48225) Destination port: gnutella-svc (6346) Sequence number: 69 (relative sequence number) Next sequence number: 136 (relative sequence number) Acknowledgement number: 133 (relative ack number) Header length: 20 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 32767 Checksum: 0xbb4b (correct) SEQ/ACK analysis 20 This is an ACK to the segment in frame: 93 The RTT to ACK the segment was: 0.000017000 seconds Gnutella Protocol Descriptor Header ID: FE0F5EEC9765B0C07F10D6F165C309E7 Payload: 1 (Pong) TTL: 5 Hops: 0 Length: 14 Pong Port: 6344 IP: localhost.localdomain (127.0.0.1) Files Shared: 0 KBytes Shared: 0 Gnutella Protocol Descriptor Header ID: DE1E2A7E5D6D9A3CA3222C1598A67F28 Payload: 128 (Query) TTL: 4 Hops: 1 Length: 7 Query Min Speed: 128 Search: hola No. Time 98 10.024246 Source Destination Protocol Info localhost.localdomain localhost.localdomain Gnutella QueryHit[Unreassembled Frame 98 (119 bytes on wire, 119 bytes captured) Arrival Time: Aug 3, 2005 17:49:42.332112000 Time delta from previous packet: 0.000017000 seconds Time since reference or first frame: 10.024246000 seconds Frame Number: 98 Packet Length: 119 bytes Capture Length: 119 bytes Protocols in frame: eth:ip:tcp:gnutella Ethernet II, Src: 00:00:00:00:00:00, Dst: 00:00:00:00:00:00 Destination: 00:00:00:00:00:00 (00:00:00_00:00:00) Source: 00:00:00:00:00:00 (00:00:00_00:00:00) Type: IP (0x0800) Internet Protocol, Src Addr: localhost.localdomain (127.0.0.1), Dst Addr: localhost.localdomain Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 105 21 Identification: 0xb6bf (46783) Flags: 0x04 (Don’t Fragment) 0... = Reserved bit: Not set .1.. = Don’t fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: TCP (0x06) Header checksum: 0x85cd (correct) Source: localhost.localdomain (127.0.0.1) Destination: localhost.localdomain (127.0.0.1) Transmission Control Protocol, Src Port: gnutella-svc (6346), Dst Port: 48227 (48227), Seq: 89, Source port: gnutella-svc (6346) Destination port: 48227 (48227) Sequence number: 89 (relative sequence number) Next sequence number: 154 (relative sequence number) Acknowledgement number: 113 (relative ack number) Header length: 20 bytes Flags: 0x0018 (PSH, ACK) 0... .... = Congestion Window Reduced (CWR): Not set .0.. .... = ECN-Echo: Not set ..0. .... = Urgent: Not set ...1 .... = Acknowledgment: Set .... 1... = Push: Set .... .0.. = Reset: Not set .... ..0. = Syn: Not set .... ...0 = Fin: Not set Window size: 32767 Checksum: 0x3489 (correct) SEQ/ACK analysis This is an ACK to the segment in frame: 97 The RTT to ACK the segment was: 0.000017000 seconds Gnutella Protocol Descriptor Header ID: DE1E2A7E5D6D9A3CA3222C1598A67F28 Payload: 129 (QueryHit) TTL: 5 Hops: 0 Length: 42 QueryHit Count: 1 Port: 6346 IP: localhost.localdomain (127.0.0.1) Speed: 128 Hit Index: 0 Size: 0 Name: null Extra: 3030CA187F 22 [Unreassembled Packet: GNUTELLA] 23 References [1] Clip2 Distributed Search Services, Gnutella Protocol Specification v0.4. http://www.stanford.edu/class/cs244b/gnutella protocol 0.4.pdf. [2] M. T. Prinkey, “An efficient scheme for query processing on peer-to-peer networks,” tech. rep., Aeolus Research, Inc., 2000. http://aeolusres.homestead.com/files/. [3] http://qtella.sourceforge.net/hosts.php. [4] The Gnutella Developer Forum, The Gnutella Protocol Specification v0.4. gnutella.sourceforge.net/developer/stable/index.html. Annotated http://rfc- [5] The Gnutella Developer Forum, The Gnutella Protocl Specification v0.6,. http://rfc-gnutella.sourceforge.net/developer/testing/index.html. [6] http://pygnutella.sourceforge.net/doc/refdoc.html. 24