在 Python 中使用原始套接字 [英] Using raw socket in Python

查看:117
本文介绍了在 Python 中使用原始套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have this simple client code which is sending a message to a server and then echoes the server response.

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 字段,但我不知道如何.

I wish to use raw socket here in order to be able to get the IP_ID field out of the server's response packet, but I have no idea how.

无论我在互联网上读了多少关于它的信息,我都没有找到一个很好的例子来说明如何去做.

No matter how much I read about it on the internet I did not find a good example of how to do it.

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

(Just to clarify, I don't really need to send a raw packet to the server, I can use the normal SOCK_STREAM to send the message, but I need to use raw socket to get the response' IP_ID.)

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

Can anyone just edit my code and show me, in the simpliest way, how to do it? All I managed to find out is that I need to replace socket.SOCK_STREAM with socket.SOCK_RAW, but im still far away.

非常感谢

推荐答案

从原始套接字读取并解析 IP_ID 很简单:

Reading from a raw socket and parsing out the IP_ID is trivial:

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

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

The hard part is getting someone to send you a packet in the first place. I'm pretty sure you can't use the same socket in raw mode and stream mode at the same time, so you're going to need to replace that connect and send with a bunch of much more complicated code that constructs and sends the appropriate TCP packets to initiate the connection. There are libraries like scapy that will do all that hard stuff for you, but if you want to do it manually, you just need to read RFC 791 and RFC 793 carefully, do all the tedious stuff (making sure you get all the endianness right), and you're on your way.

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

On *BSD (including OS X), the kernel will fill in the IP length, TCP length, and, best of all, the TCP checksum. It gets much more painful if you have to handle those yourself. (If this doesn't work on your platform, you probably do… either that, or I screwed up something else that OS X fixes for me automagically and your platform doesn't.)

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 数据包,正如您所期望的那样.

Each time I run this, I get a nak (if no one's listening on port 11000) or ack packet with a randomized IP_ID, just as you'd expect.

这篇关于在 Python 中使用原始套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆