python - 理解/解码收到的数据包

标签 python sockets networking packet tor

我在尝试弄清楚我收到了多少个数据包以及它们代表什么时遇到了一些问题。

我正在尝试将数据包发送到 Tor 节点并获取响应,其想法是这是连接过程的开始,让我创建一个节点链来使用该服务。

我从这个文档中获取了我的数据包结构:

3. Cell Packet format

   The basic unit of communication for onion routers and onion
   proxies is a fixed-width "cell".

   On a version 1 connection, each cell contains the following:
   fields:

        CircID                                [CIRCID_LEN bytes]
        Command                               [1 byte]
        Payload (padded with 0 bytes)         [PAYLOAD_LEN bytes]

   On a version 2 or higher connection, all cells are as in version 1
   connections, except for variable-length cells, whose format is:

        CircID                                [CIRCID_LEN octets]
        Command                               [1 octet]
        Length                                [2 octets; big-endian integer]
        Payload                               [Length bytes]

   On a version 2 connection, variable-length cells are indicated by a
   command byte equal to 7 ("VERSIONS").  On a version 3 or
   higher connection, variable-length cells are indicated by a command
   byte equal to 7 ("VERSIONS"), or greater than or equal to 128.

   CIRCID_LEN is 2 for link protocol versions 1, 2, and 3.  CIRCID_LEN
   is 4 for link protocol version 4 or higher.  The VERSIONS cell itself
   always has CIRCID_LEN == 2 for backward compatibility.

   The CircID field determines which circuit, if any, the cell is
   associated with.

   The 'Command' field of a fixed-length cell holds one of the following
   values:
         0 -- PADDING     (Padding)                 (See Sec 7.2)
         1 -- CREATE      (Create a circuit)        (See Sec 5.1)
         2 -- CREATED     (Acknowledge create)      (See Sec 5.1)
         3 -- RELAY       (End-to-end data)         (See Sec 5.5 and 6)
         4 -- DESTROY     (Stop using a circuit)    (See Sec 5.4)
         5 -- CREATE_FAST (Create a circuit, no PK) (See Sec 5.1)
         6 -- CREATED_FAST (Circuit created, no PK) (See Sec 5.1)
         8 -- NETINFO     (Time and address info)   (See Sec 4.5)
         9 -- RELAY_EARLY (End-to-end data; limited)(See Sec 5.6)
         10 -- CREATE2    (Extended CREATE cell)    (See Sec 5.1)
         11 -- CREATED2   (Extended CREATED cell)    (See Sec 5.1)

    Variable-length command values are:
         7 -- VERSIONS    (Negotiate proto version) (See Sec 4)
         128 -- VPADDING  (Variable-length padding) (See Sec 7.2)
         129 -- CERTS     (Certificates)            (See Sec 4.2)
         130 -- AUTH_CHALLENGE (Challenge value)    (See Sec 4.3)
         131 -- AUTHENTICATE (Client authentication)(See Sec 4.5)
         132 -- AUTHORIZE (Client authorization)    (Not yet used)

   The interpretation of 'Payload' depends on the type of the cell.
      PADDING: Payload is unused.
      CREATE:  Payload contains the handshake challenge.
      CREATED: Payload contains the handshake response.
      RELAY:   Payload contains the relay header and relay body.
      DESTROY: Payload contains a reason for closing the circuit.
               (see 5.4)
   Upon receiving any other value for the command field, an OR must
   drop the cell.  Since more cell types may be added in the future, ORs
   should generally not warn when encountering unrecognized commands.

   The payload is padded with 0 bytes.

   PADDING cells are currently used to implement connection keepalive.
   If there is no other traffic, ORs and OPs send one another a PADDING
   cell every few minutes.

   CREATE, CREATED, and DESTROY cells are used to manage circuits;
   see section 5 below.

   RELAY cells are used to send commands and data along a circuit; see
   section 6 below.

   VERSIONS and NETINFO cells are used to set up connections in link
   protocols v2 and higher; in link protocol v3 and higher, CERTS,
   AUTH_CHALLENGE, and AUTHENTICATE may also be used.  See section 4
   below.

https://gitweb.torproject.org/torspec.git?a=blob_plain;hb=HEAD;f=tor-spec.txt

我已成功将数据包发送到节点:

import ssl
import socket
import struct
import binascii

s = socket.socket()
ssl_sock = ssl.wrap_socket(s)
ssl_sock.connect(("", 443))

pkt = struct.pack(">HBHH", 0, 7, 2, 3)
ssl_sock.send(pkt)

recv_pkt = ssl_sock.recv(1500)
print ":".join("{:02x}".format(ord(c)) for c in recv_pkt)

这会向节点发送一个数据包,我会返回以下内容:

00:00:07:00:04:00:03:00:04:00:00:81:03:88:02:01:01:be:30:82:01:ba:30:82:01:23:a0:03:02:01:02:02:08:78:ef:3f:c3:c7:b8:06:ad:30:0d:06:09:2a:86:48:86:f7:0d:01:01:05:05:00:30:22:31:20:30:1e:06:03:55:04:03:13:17:77:77:77:2e:6b:7a:6e:79:74:72:7a:62:33:6e:6d:6e:32:63:68:2e:63:6f:6d:30:1e:17:0d:31:34:30:33:33:31:30:30:30:30:30:30:5a:17:0d:31:35:30:33:30:34:32:33:35:39:35:39:5a:30:1d:31:1b:30:19:06:03:55:04:03:13:12:77:77:77:2e:78:79:32:71:69:75:70:72:34:74:2e:6e:65:74:30:81:9f:30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:00:03:81:8d:00:30:81:89:02:81:81:00:d1:66:cd:6c:14:14:7b:ff:79:1a:5a:30:0e:2d:fd:d9:85:79:a9:38:5d:9e:c1:09:35:fb:59:c7:1f:5b:ab:cc:1d:65:03:ed:62:d1:58:38:a4:e3:35:97:da:29:04:41:1d:e0:fa:50:f5:48:ba:87:fc:b2:9a:b6:0e:93:b9:a3:2e:fa:13:d1:75:ae:51:0f:95:2c:9a:fc:fc:b8:77:49:19:2a:4e:cb:9d:61:e4:cf:ef:38:0c:1f:a7:91:fd:98:de:57:5c:0e:29:1d:d9:36:df:ac:17:0b:cb:a0:a2:02:29:93:8b:5f:48:66:95:56:b9:4d:c0:c0:77:41:9c:91:02:03:01:00:01:30:0d:06:09:2a:86:48:86:f7:0d:01:01:05:05:00:03:81:81:00:76:c2:9e:31:93:46:47:03:e7:da:6b:cb:6e:ea:a9:4b:4c:98:e7:78:91:59:13:2d:8f:cf:f4:3f:49:b5:79:2a:b9:f2:f7:ec:75:24:1d:a2:78:ec:af:07:75:01:c6:cd:55:4b:1f:6f:02:18:22:b6:13:4a:0c:ee:d2:69:d2:42:08:f3:e0:c1:a0:d0:b1:ba:cf:38:20:dc:14:77:01:cd:93:49:b4:23:ce:f3:a8:fb:cf:ea:2c:33:67:16:d8:71:53:30:d3:6d:13:3e:b3:db:9c:b7:be:c1:e8:b2:ab:56:c9:cb:33:02:96:8c:48:04:61:f9:a5:65:a7:13:0b:40:02:01:c3:30:82:01:bf:30:82:01:28:a0:03:02:01:02:02:08:0c:25:64:87:83:b0:53:b4:30:0d:06:09:2a:86:48:86:f7:0d:01:01:05:05:00:30:22:31:20:30:1e:06:03:55:04:03:13:17:77:77:77:2e:6b:7a:6e:79:74:72:7a:62:33:6e:6d:6e:32:63:68:2e:63:6f:6d:30:1e:17:0d:31:33:30:37:31:30:30:30:30:30:30:30:5a:17:0d:31:34:30:37:31:30:30:30:30:30:30:30:5a:30:22:31:20:30:1e:06:03:55:04:03:13:17:77:77:77:2e:6b:7a:6e:79:74:72:7a:62:33:6e:6d:6e:32:63:68:2e:63:6f:6d:30:81:9f:30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:00:03:81:8d:00:30:81:89:02:81:81:00:c4:20:57:68:17:2d:b5:e0:7a:c5:a0:78:0b:23:f0:fd:54:be:6f:f3:89:ba:c5:5e:ac:03:ab:6e:e5:2c:a3:60:58:66:06:5f:66:b1:dc:bc:93:de:7c:c8:d5:8e:68:2e:ce:24:3c:a4:ec:30:ce:5f:b7:d6:a8:93:07:f8:d7:b9:4a:a0:24:65:65:cf:69:b5:f4:5b:83:10:f1:f7:47:3d:1a:d5:95:9a:4a:e6:0e:f0:8a:69:ee:7d:4c:ca:17:22:21:9f:66:2c:16:4f:a2:8a:ab:96:66:f7:f1:6e:d8:89:77:07:6b:c7:1a:42:89:60:a8:b1:9a:20:49:44:aa:7f:02:03:01:00:01:30:0d:06:09:2a:86:48:86:f7:0d:01:01:05:05:00:03:81:81:00:a1:7f:4a:f8:51:3e:fe:34:1b:10:4a:42:15:d9:8c:39:f7:4b:7c:97:27:f6:96:67:45:f6:f8:95:91:f5:53:72:0b:ee:47:1a:94:b3:48:be:ab:0a:be:5b:52:45:05:ea:35:6f:50:85:ea:fb:88:3c:ee:33:04:76:55:7a:9f:69:eb:5d:c5:20:a6:3c:04:e0:62:1a:8d:21:fd:16:0a:85:93:ef:7a:3e:23:e5:36:3c:27:82:e1:d0:02:f7:d1:2d:0c:6f:f9:f7:a1:48:06:92:75:78:3f:c1:64:05:15:9f:db:f4:a6:22:f0:d6:95:56:83:c7:bf:03:cd:9f:dd:9c:00:00:82:00:24:be:24:79:44:ec:06:96:f9:dd:a5:77:16:53:f9:eb:90:20:e8:a4:37:7e:0a:8d:5f:6d:6a:45:a4:33:bd:72:ac:00:01:00:01:00:00:08:53:85:8e:a1:04:04:94:c5:86:ea:02:04:04:56:3b:15:26:06:10:20:01:08:58:00:02:00:02:aa:bb:00:00:56:3b:15:26:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00

我想弄清楚的是我上面收到了多少个数据包,以及它们包含哪些信息,我认为应该收到 4 个数据包,但我不确定如果有人可以提供帮助,这将是一个巨大的帮助,因为我真的确实需要尝试并理解这一点。

编辑:

这是我当前的代码,但在理解收到的数据时仍然存在问题:(

import ssl
import socket
import struct
import binascii

s = socket.socket()
ssl_sock = ssl.wrap_socket(s)
ssl_sock.connect((" ", 443))


pkt = struct.pack(">HBHH", 0, 7, 2, 3)
ssl_sock.send(pkt)

peerAddr= [int(x) for x in ssl_sock.getpeername()[0].split(".")]

#recv_pkt = sock.recv(payload_len)
#print recv_pkt

#All recieved data printed
recv_pkt = ssl_sock.recv(1500)
#print recv_pkt
print ":".join("{:02x}".format(ord(c)) for c in recv_pkt)
print "Data recieved is above"
#while len(recv_pkt)<= 512
# payload = struct.unpack(">H")

# 512 - COMMAND_LEN - PAYLOAD_LEN = 512 - 1 - 509 = 2
CIRCID_LEN = 2

# default to v1
PAYLOAD_LEN = 509

#currently locking up at this section
circ_id, command = ssl_sock.recv(CIRCID_LEN), ssl_sock.recv(1)
print circ_id
print command

# according to spec, command is 7 if not using v1
# -> if not v1
if command != 7:
    # Negotiate proto version and set PAYLOAD_LEN accordingly
    PAYLOAD_LEN = 0

# finally, get the entire payload, and just that
payload = ssl_sock.recv(PAYLOAD_LEN)

print payload

#CellNetInfo
#cnetinf = recv_pkt(ssl_sock, 'CellNetInfo')
#ssl_sock.send(cnetinf.pack())

最佳答案

我还没有对此进行测试,但它应该可以让您了解需要什么:

# Not sure if this is correct, I got it by:
# 512 - COMMAND_LEN - PAYLOAD_LEN = 512 - 1 - 509 = 2
CIRCID_LEN = 2

# default to v1
PAYLOAD_LEN = 509

circ_id, command = ssl_sock.recv(CIRCID_LEN), ssl_sock.recv(1)

# according to spec, command is 7 if not using v1
# -> if not v1
if command != 7:
    # Here you need to "Negotiate proto version"
    # Then, set PAYLOAD_LEN accordingly:
    PAYLOAD_LEN = 0

# finally, get the entire payload, and just that
payload = ssl_sock.recv(PAYLOAD_LEN)

此外,由于套接字的原因,最好有 try/except block 。

关于python - 理解/解码收到的数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23905531/

相关文章:

python - 如何在 Git 中只包含另一个存储库中的一个文件夹?

python - 试图使用正则表达式在python中实现功能以验证输入?

python - 为什么我的 Pandas 数据框选择的形状是错误的

javascript - 套接字 io 发射生成 'instanceof' 的右侧不是对象

c# - .net 的多线程网络 UDP 服务器库

docker - docker-compose无法与网络产生网络冲突,网络具有重叠的IPv4

python - 如何在 python Requests 库中使用基本的 HTTP 身份验证?

java - 通过对象序列化流发送具有不同字段的相同对象

减少 ggnet2 网络图中的空白空间

security - 如何唯一标识笔记本及其连接的无线接入点?