python - 在 Python 中使用原始套接字

标签 python sockets python-2.7 raw-sockets

我有这个简单的客户端代码,它向服务器发送消息,然后回显服务器响应。

import socket, sys, time


HOST = 'localhost'   
PORT = 11000             
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
msg = raw_input()
s.send(msg)
data = s.recv(len(msg))
s.close()
print 'Received: ', data

我希望在这里使用原始套接字,以便能够从服务器的响应数据包中获取 IP_ID 字段,但我不知道如何操作。

无论我在互联网上读了多少相关内容,我都没有找到如何做到这一点的好例子。

(澄清一下,我真的不需要向服务器发送原始数据包,我可以使用普通的 SOCK_STREAM 来发送消息,但我需要使用原始套接字来获取响应的 IP_ID。)

任何人都可以编辑我的代码并以最简单的方式向我展示如何做到这一点吗? 我设法发现的是我需要用socket.SOCK_RAW替换socket.SOCK_STREAM,但我还很远。

非常感谢

最佳答案

从原始套接字读取数据并解析出 IP_ID 非常简单:

response, addr = s.recvfrom(65535)
response_id = struct.unpack('!H', response[4:6])
print response_id

最困难的部分是让某人首先向您发送数据包。我很确定您不能同时在原始模式和流模式下使用相同的套接字,因此您需要替换 connectsend 使用一堆更复杂的代码来构造和发送适当的 TCP 数据包来启动连接。有像 scapy 这样的库可以为您完成所有这些困难的事情,但如果您想手动完成,您只需要阅读 RFC 791RFC 793小心翼翼地完成所有繁琐的事情(确保所有字节顺序正确),然后就可以上路了。

在 *BSD(包括 OS X)上,内核将填写 IP 长度、TCP 长度,以及最重要的是 TCP 校验和。如果你必须自己处理这些事情,那就会变得更加痛苦。 (如果这在你的平台上不起作用,你可能会这样做......或者那样,或者我搞砸了 OS X 自动为我修复的其他东西,而你的平台却不能。)

import socket
import struct

def make_ip(proto, srcip, dstip, ident=54321):
    saddr = socket.inet_aton(srcip)
    daddr = socket.inet_aton(dstip)
    ihl_ver = (4 << 4) | 5
    return struct.pack('!BBHHHBBH4s4s' , 
                       ihl_ver, 0, 0, ident, 0, 255, proto, 0, saddr, daddr)

def make_tcp(srcport, dstport, payload, seq=123, ackseq=0,
             fin=False, syn=True, rst=False, psh=False, ack=False, urg=False,
             window=5840):
    offset_res = (5 << 4) | 0
    flags = (fin | (syn << 1) | (rst << 2) | 
             (psh <<3) | (ack << 4) | (urg << 5))
    return struct.pack('!HHLLBBHHH', 
                       srcport, dstport, seq, ackseq, offset_res, 
                       flags, window, 0, 0)

srcip = dstip = '127.0.0.1'
srcport, dstport = 11001, 11000
payload = '[TESTING]\n'

ip = make_ip(socket.IPPROTO_TCP, srcip, dstip)
tcp = make_tcp(srcport, dstport, payload)
packet = ip + tcp + payload

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.sendto(packet, (dstip, 0))
response, addr = s.recvfrom(65535)
response_id = struct.unpack('!H', response[4:6])
print response_id

每次运行此命令时,我都会收到一个 nak(如果没有人在端口 11000 上监听)或带有随机 IP_ID 的 ack 数据包,正如您所期望的那样。

关于python - 在 Python 中使用原始套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20203549/

相关文章:

Python:日期时间格式

python - Python 网页抓取时的编码问题

Python 解析器/编译器与解释器,以及字符串连接编译时与运行时?

python - Flask 保持连接请求失败

c - 关于 getservbyname 的正确答案是什么?

python - 如何在 Python 中优化多处理

python - 在 Python 3 中使用 RSA,需要对消息进行签名(不对消息进行哈希处理)

Java客户端套接字:Cannot receive messages from server to client

c++ - HPUX 上的套接字未收到完整数据

python - "Flatten"列表中的一串单词