it-swarm.com.de

Wie verwende ich Raw Socket in Python?

Ich schreibe eine Anwendung, um einen Netzwerktreiber für den Umgang mit beschädigten Daten zu testen. Ich habe daran gedacht, diese Daten mit einem Raw-Socket zu senden, damit sie nicht vom TCP-IP-Stack der sendenden Maschine korrigiert werden.

Ich schreibe diese Anwendung ausschließlich unter Linux. Ich habe Codebeispiele für die Verwendung von Raw-Sockets in Systemaufrufen, aber ich möchte meinen Test so dynamisch wie möglich halten und die meisten, wenn nicht alle, in Python schreiben.

Ich habe im Internet ein wenig nach Erklärungen und Beispielen für die Verwendung von Raw-Sockets in Python gegoogelt, aber nichts wirklich Aufschlussreiches gefunden. Nur ein sehr altes Codebeispiel, das die Idee demonstriert, aber keineswegs funktioniert.

Soweit ich weiß, ist die Verwendung von Raw Socket in Python in der Semantik fast identisch mit dem Raw-Socket von UNIX, jedoch ohne die structs, die die Paketstruktur definieren.

Ich habe mich gefragt, ob es noch besser wäre, den rohen Socket-Teil des Tests nicht in Python, sondern in C mit Systemaufrufen zu schreiben und ihn vom Python-Hauptcode aus aufzurufen.

32
Avihu Turzion

Du machst es so:

Deaktivieren Sie zunächst die automatische Prüfsumme Ihrer Netzwerkkarte:

Sudo ethtool -K eth1 tx off

Und dann senden Sie Ihr zwielichtiges Bild von Python 2 (Sie müssen selbst in Python 3 konvertieren):

#!/usr/bin/env python
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
s.bind(("eth1", 0))

# We're putting together an ethernet frame here, 
# but you could have anything you want instead
# Have a look at the 'struct' module for more 
# flexible packing/unpacking of binary data
# and 'binascii' for 32 bit CRC
src_addr = "\x01\x02\x03\x04\x05\x06"
dst_addr = "\x01\x02\x03\x04\x05\x06"
payload = ("["*30)+"PAYLOAD"+("]"*30)
checksum = "\x1a\x2b\x3c\x4d"
ethertype = "\x08\x01"

s.send(dst_addr+src_addr+ethertype+payload+checksum)

Erledigt.

42
brice

Sockets-Systemaufrufe (oder Winsocks unter Windows) sind bereits im Standardmodul socket: intro , reference eingeschlossen.

Ich habe noch nie Raw-Sockets verwendet, aber es sieht so aus, als könnten sie mit diesem Modul verwendet werden:

Das letzte Beispiel zeigt, wie ein .__ geschrieben wird. sehr einfacher Netzwerk-Sniffer mit RAW Steckdosen unter Windows. Das Beispiel erfordert Administratorrechte für Ändern Sie die Schnittstelle:

import socket

# the public network interface
Host = socket.gethostbyname(socket.gethostname())

# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((Host, 0))

# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# receive a package
print s.recvfrom(65565)

# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
10

Ist das der alte Code, den Sie erwähnt haben? Es sieht für mich vernünftig aus, aber ich habe es selbst nicht getestet (oder rohe Steckdosen verwendet). Dieses Beispiel aus der Dokumentation zeigt, wie Raw-Sockets zum Erfassen von Paketen verwendet werden, und es sieht ähnlich aus.

2
unwind

Die beste Lösung für diesen Fall war letztendlich, die gesamte Sache in C zu schreiben, da dies keine große Anwendung ist. Es wäre also mit höheren Kosten verbunden, wenn eine so kleine Sache in mehr als einer Sprache geschrieben würde.

Nachdem ich viel mit den C- und Python-RAW-Sockeln gespielt hatte, zog ich schließlich die C-RAW-Sockel vor. RAW-Sockets erfordern Modifikationen auf Bitebene von weniger als 8-Bit-Gruppen zum Schreiben der Paket-Header. Manchmal schreiben Sie nur 4 Bits oder weniger. python definiert dazu keine Unterstützung, während Linux C eine vollständige API dafür hat.

Aber ich bin der festen Überzeugung, dass, wenn nur dieses kleine bisschen Header-Initialisierung bequem in Python gehandhabt werden würde, ich hier niemals C verwendet hätte.

2
Avihu Turzion
s = socket(AF_PACKET, SOCK_RAW)
s = socket(PF_PACKET, SOCK_RAW)

ergebnis:

[[email protected] python]# tcpdump -i eth0

capture size 96 bytes
11:01:46.850438 

01:02:03:04:05:06 (oui Unknown) > 01:02:03:04:05:06 (oui Unknown), ethertype Unknown (0x0801), length 85:

        0x0000:  5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b  [[[[[[[[[[[[[[[[
        0x0010:  5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5041  [[[[[[[[[[[[[[PA
        0x0020:  594c 4f41 445d 5d5d 5d5d 5d5d 5d5d 5d5d  YLOAD]]]]]]]]]]]
        0x0030:  5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d  ]]]]]]]]]]]]]]]]
        0x0040:  5d5d 5d00 0000 00                        ]]]....
1
gteng

Die Socket-Klasse sollte helfen. Wenn nicht, müssen Sie entweder ein Python-Modul in C schreiben oder einfach C verwenden. Siehe http://mail.python.org/pipermail/python-list/2001-April/077454.html .

Basic Googling hat das gefunden.

Ich habe eigentlich das Codebeispiel ausprobiert, auf das "Abwickeln" hingewiesen hat. AF_PACKET hat für mich in Python 2.7.4 gearbeitet

0

Sie können diese Python-Bibliothek verwenden: rawsocketpy erlaubt die Verwendung von Raw-Sockets auf Layer 2 => Keine IP/TCP/UDP-Header.

#!/usr/bin/env python
from rawsocketpy import RawSocket

sock = RawSocket("wlp2s0", 0xEEFA)
sock.send("some data")
sock.send("personal data", dest="\xAA\xBB\xCC\xDD\xEE\xFF")

oder das Serverformular:

#!/usr/bin/env python
from rawsocketpy import RawRequestHandler, RawAsyncServerCallback
import time

def callback(handler, server):
    print("Testing")
    handler.setup()
    handler.handle()
    handler.finish()

class LongTaskTest(RawRequestHandler):
    def handle(self):
        time.sleep(1)
        print(self.packet)

    def finish(self):
        print("End")

    def setup(self):
        print("Begin") 

def main():
    rs = RawAsyncServerCallback("wlp2s0", 0xEEFA, LongTaskTest, callback)
    rs.spin()

if __== '__main__':
    main()
0
Alexis Paques

FTR, wenn Sie Zugriff auf Ebene 2 (Ethernet, RadioTap ...) möchten, ist dies unter Windows (ab heute) nicht möglich.

Wenn Sie mit einer plattformübergreifenden Methode auf diese zugreifen möchten, wählen Sie libpcap und dessen Python Bindungen (da Npcap/WinPcap Verwendet wird) unter Windows).

Sie haben eine Vielzahl von Python für libpcap verfügbaren Bindungen auf allen Ebenen (sehr hoch oder sehr niedrig).

Mein Rat wäre, die Sockets von scapy ( zu verwenden, auch wenn Sie es nicht zum Zerlegen verwenden ), die sowohl Native- als auch Libpcap-Aufrufe implementieren (und mit conf.use_pcap = True gegen sie entscheiden lassen)

from scapy.all import conf
# conf.use_pcap = True (will be automatic if required)
socket = conf.L2socket(iface="eth0")
# On any platforms, you have `get_if_list()` in `scapy.all` available, to see the ifaces available. You could also ignore it to use the default one
0
Cukic0d