简体   繁体   English

在Python中使用原始套接字

[英]Using raw socket in 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

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. 我希望在这里使用原始套接字,以便能够从服务器的响应数据包中获取IP_ID字段,但我不知道如何。

No matter how much I read about it on the internet I did not find a good example of how to do it. 无论我在互联网上阅读了多少,我都没有找到如何做到这一点的好例子。

(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.) (只是为了澄清,我真的不需要向服务器发送原始数据包,我可以使用正常的SOCK_STREAM来发送消息,但我需要使用原始套接字来获取响应'IP_ID。)

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. 我设法找到的是我需要用socket.SOCK_RAW替换socket.SOCK_STREAM,但我仍然很远。

Thanks alot 非常感谢

Reading from a raw socket and parsing out the IP_ID is trivial: 从原始套接字读取并解析出IP_ID是微不足道的:

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

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. 我很确定你不能同时在原始模式和流模式下使用相同的套接字,所以你需要替换那个connectsend一堆更复杂的代码来构造和发送适当的TCP数据包以启动连接。 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. scapy这样的库可以为你做所有困难的事情,但是如果你想手动完成它,你只需要仔细阅读RFC 791RFC 793 ,做所有繁琐的事情(确保你获得所有的字节顺序) ),你正在路上。

On *BSD (including OS X), the kernel will fill in the IP length, TCP length, and, best of all, the TCP checksum. 在* BSD(包括OS X)上,内核将填写IP长度,TCP长度,最重要的是TCP校验和。 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.) (如果这在你的平台上不起作用,你可能会这样做,或者我搞砸了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

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. 每次我运行它,我得到一个nak(如果没有人正在侦听端口11000)或具有随机IP_ID ack数据包,就像你期望的那样。

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

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