繁体   English   中英

了解原始套接字数据包头

[英]Understanding raw socket packet header

我已经使用此代码在Python中编写了一个套接字数据包嗅探器。

import socket, struct

# Setup socket object
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s.bind((socket.gethostbyname(socket.gethostname()), 0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

Id = 0
while (True):
    data = s.recvfrom(65565)
    packet = data[0]
    address = data[1]
    header = struct.unpack("!BBHHHBBHBBBBBBBB", packet[:20])

    if (header[6] == 6):
        protocol = "TCP"
    elif (header[6] == 17):
        protocol = "UDP"

    print("Number: ", Id, end="\t")
    print("Protocol: ", protocol, end="\t")
    print("Address: ", address, end="")
    print("Header: ", header)
    #print("Data: ", data)
    print()
    Id += 1
  1. 我知道我可以在数据变量的索引0(data [0])上找到接收方的IP地址,但是在数据包的哪里可以找到发送方的IP地址和端口号?
  2. 标头元组中的所有整数是什么意思? 我知道header [6]是协议TCP / UDP,但是其余的呢?

    标头:(69、0、61、1541、0、128、17、0、192、168、56、1、255、255、255、255)

IP标头具有定义明确的结构RFC 您决定用字节和短裤拆包。 一般来说,您希望将每个字段的大小与正确的数据类型进行匹配。 查看适当的标头大小,您可以看到各个细分:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这可以通过编程方式完成:

struct.unpack('!BBHHHBBHII')
# alternatively:
struct.unpack('!BBHHHBBH4s4s')

我喜欢后者,因为您可以轻松地将其转换为IP地址:

示例以太网头:

0000   3c 4a 92 1f 04 00 74 c6 3b 8d 82 69 08 00 45 00  <J....t.;..i..E.
0010   00 3c 0a 24 40 00 40 06 23 76 0a 14 01 0d 01 01  .<.$@.@.#v......
0020   01 01 e7 7a 04 d2 a2 5e 0c d2 00 00 00 00 a0 02  ...z...^........
0030   72 10 0d 51 00 00 02 04 05 b4 04 02 08 0a 9c d4  r..Q............
0040   c0 c0 00 00 00 00 01 03 03 07                    ..........

20字节的IPv4标头存在于packet[14:34] 使用上述格式将其解压缩会产生以下结果:

>>> header = struct.unpack('!BBHHHBBH4s4s', packet[14:34])
>>> header
(69, 0, 60, 2596, 16384, 64, 6, 9078, b'\n\x14\x01\r', b'\x01\x01\x01\x01')

标记8和9分别是源IP和目标IP。 因为它们是字节,所以我们可以将它们转换为int ,然后转换为str以获得字符串格式的IP:

# Note: Python 3 only
>>> ip_src = '.'.join(map(str, header[8]))  # 10.20.1.13
>>> ip_dst = '.'.join(map(str, header[9]))  # 1.1.1.1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM