raw socket - aber wie?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

Hallo Pythonfreunde,

Ich möchte die Netzwerkpakete von einem Server inspizieren. In der Pythondokumentation habe ich auch ein Beispiel gefunden:

import socket
HOST = socket.gethostbyname(socket.gethostname())
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
print (s.recvfrom(65565))
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

Dieser Quelltext läuft aber auf meinem Debian unter Python 3.1 nicht. Durch Googln habe ich herrausgefunden das der Quelltext uralt wäre und angepasst werden müsste.
AF_INET soll man nicht nehmen, sondern AF_PACKET
Statt dem HOST soll man den Ethernetadapter eintragen
Anschließend sieht der Quelltext so aus:

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind(("eth0", 0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
print (s.recvfrom(65565))
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

Dann bekomme ich aber diese Fehlermeldung wenn ich das Script als root ausführe:

s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
File "<string>", line 1, in setsockopt
socket.error: [Errno 92] Protocol not available

Was mache ich falsch? Anscheinend ging das ja mal in Python irgendwie. Sachen wie Impacket, Scapy, Pycap oder wie der ganze Mist heisst möchte ich nicht verwenden.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Du solltest dir mal die Dokumentation für Python 3.1 zu sockets ansehen. (Unten gibt es auch ein paar gute Beispiele)
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

Der Quelltext ist doch von der Seite die du gepostet hast :roll:
read the fucking manual und intensives googln hat leider nicht weiter geholfen. Deshalb habe ich mich doch an das Forum gewendet.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Sieht mir aber nicht ganz danach aus, woher hast du AF_PACKET und wieso sollte man bei HOST "eth0" angeben - in der Dokumentation steht etwas anderes. Auch wenn du irgendwo etwas anderes findest, so gibt es nicht auf einmal mehr Konstanten, wie deine gegoogelte AF_PACKET.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

Also wenn ich den Quelltext in der Dokumentation ausführe (also mein erstes Quelltextbeispiel ganz oben) bekomme ich diese Fehlermeldung.

Traceback (most recent call last):
File "test.py", line 3, in <module>
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
File "/usr/lib/python3.1/socket.py", line 184, in __init__
_sock = _realsocket(family, type, proto)
socket.error: [Errno 93] Protocol not supported

Nach rumgoogeln der Fehlermeldungen habe ich diese Tipps mit AF_PACKET und HOST bekommen. Das hat aber auch nicht geholfen :cry:
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

AF_INET ist für IPv4, vieleicht brauchst du AF_INET6. - steht weiter oben in der Dokumentation. Und der Host ist immer eine IP-Adresse.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

Ich brauch schon IPv4. IPV6 hab ich garnicht
Als HOST hab ich schon alles versucht. 'localhost' '127.0.0.1' '192.168.0.2' oder 'squeeze'
geht alles nicht.

Also wie gesagt. Ich habe mich exakt an die Dokumentation gehalten. Dieser Quelltext ist ja sogar aus der aktuellen Pythondokumentation:

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)

mit der Fehlermeldung

Traceback (most recent call last):
File "test.py", line 3, in <module>
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
File "/usr/lib/python3.1/socket.py", line 89, in __init__
_socket.socket.__init__(self, family, type, proto, fileno)
socket.error: [Errno 93] Protocol not supported

Läuft denn der Quelltext aus der Dokumentation bei dir?
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Jupp, bei mir läuft der ohne Probleme, wieso auch nicht :K (habe allerdings keine Debaindistro zur Hand. Aber das Problem ist ja, dass das Protokoll nicht unterstützt wird und es gibt nur ein paar verschiedene AF-Protokolle und ich nehme an du hast diese alle schon ausprobiert und nicht einfach gleich abgetan?

Lass dir die Daten doch mal ausgeben mit: socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC)
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

Uiii. Bei dir läuft das echt? Interessante Info. Also muss der Fehler ja bei mir im System liegen.
Ja. Habe anstatt socket.AF_INET schon probiert:

socket.AF_UNIX¶
socket.AF_INET¶
socket.AF_INET6¶

Das interessante ist vielleicht das wenn ich AF_UNIX verwende kommt diese Fehlermeldung:

Traceback (most recent call last):
File "test.py", line 6, in <module>
s.bind((HOST, 0))
TypeError: argument must be bytes or read-only buffer, not tuple

socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC) gibt folgendes zurück
[(2, 1, 6, '', ('192.168.0.1', 0)), (2, 2, 17, '', ('192.168.0.1', 0)), (2, 3, 0, '', ('192.168.0.1', 0))]
Zuletzt geändert von aluis am Mittwoch 11. Mai 2011, 09:18, insgesamt 1-mal geändert.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Gib dir mal HOST aus, ist warscheinlich ein tuple.
Und was sind die Zahlen davor, die Funktion gibt dir family, socktype, proto, canonname, sockaddr zurück. "family" ist das entsprechende Protokoll.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC) gibt folgendes zurück
[(2, 1, 6, '', ('192.168.0.1', 0)), (2, 2, 17, '', ('192.168.0.1', 0)), (2, 3, 0, '', ('192.168.0.1', 0))]
was auch meiner IP adresse entspricht
BlackJack

@aluis: Zum Beispiel aus der Dokumentation mal ein Zitat aus der Dokumentation (Hervorhebung von mir):
http://docs.python.org/release/3.1.3/library/socket.html#example hat geschrieben:The last example shows how to write a very simple network sniffer with raw sockets on Windows.
Benutzeravatar
aluis
User
Beiträge: 7
Registriert: Mittwoch 11. Mai 2011, 05:09

OH NEIN! Ich dummer Idiot. Wer lesen kann ist klar im Vorteil. :evil:
Tut mir leid wenn ich eure Zeit verschwendet hab. Aber trotzdem danke für die schnelle hilfe!
*schmeisst seine Tastatur aus dem Fenster*
BlackJack

@aluis: Unter Linux *musst* Du anstelle von `IPPROTO_IP` anscheinend ein konkreteres Protokoll angeben, wie zum Beispiel `IPPROTO_ICMP`, `IPPROTO_UDP`, oder `IPPROTO_TCP`. Und bekommst dann auch nur Pakete zu diesem Protokoll über die Socket.

Du kannst übrigens auch nach Dokumentation zu "raw sockets" unter C suchen, denn das `socket`-Modul ist nur ein ganz dünner Wrapper um die entsprechenden C-Funktionen.
Antworten