簡體   English   中英

在Python中使用原始套接字

[英]Using raw socket in Python

我有這個簡單的客戶端代碼,它將消息發送到服務器,然后回應服務器響應。

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數據包,就像你期望的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM