2012-06-12 18 views
13

Sto lavorando per integrare scapy con twisted, ma mi sono imbattuto in questo strano bug su OSX che non riesco a capire.Raw socket e sendto in python

Fondamentalmente non riesco a inviare un pacchetto TCP valido (comprensivo di intestazioni IP) tramite un socket non elaborato. Questo è quello che sto facendo:

import socket 
from scapy.all import IP, TCP 
pkt = IP(src='0.0.0.0', dst='127.0.0.1')/TCP() 
spkt1 = str(pkt) 
outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 
outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1) 
outs.sendto(spkt1, ('127.0.0.1', 0)) 

Quando ho eseguito questo ricevo il seguente errore:

outs.sendto(spkt1, ('127.0.0.1', 0)) socket.error: [Errno 22] Invalid argument

Nel caso in cui non si dispone di Scapy sulla non vogliono usarlo in questo è il base64 pacchetti codificati:

import base64 
spkt1 = base64.b64decode("RQAAKAABAABABvvOAAAAAH8AAAEAFABQAAAAAAAAAABQAiAAEH4AAA==") 

La cosa strana è che un pacchetto che è quasi identico sembra essere stato inviato correttamente:

spkt2 = base64.b64decode("RQBAAAWwAAACBgAAAAAAAH8AAAEAyAOEAAAAAAAAAACwAgDIAHsAAAIEBbQBAwMBAQEICk3PUjMAAAAABAIAAA==") 

Ecco come i due pacchetti assomigliano:

SPKT1 
0000 45 00 00 28 00 01 00 00 40 06 FB CE 00 00 00 00 E..([email protected] 
0010 7F 00 00 01 00 14 00 50 00 00 00 00 00 00 00 00 .......P........ 
0020 50 02 20 00 10 7E 00 00       P. ..~.. 
SPKT2 
0000 45 00 40 00 05 B0 00 00 02 06 00 00 00 00 00 00 [email protected] 
0010 7F 00 00 01 00 C8 03 84 00 00 00 00 00 00 00 00 ................ 
0020 B0 02 00 C8 00 7B 00 00 02 04 05 B4 01 03 03 01 .....{.......... 
0030 01 01 08 0A 4D CF 52 33 00 00 00 00 04 02 00 00 ....M.R3........ 

Con loro check-out in Wireshark differiscono solo nella parte TCP.

Ho eseguito molti esperimenti diversi e alla fine sono riuscito a impostare determinate opzioni TCP specifiche per ottenere il pacchetto inviato, ma non ha senso che un tale pacchetto non funzioni.

Qualcuno ha un'idea del motivo per cui ciò potrebbe accadere?

EDIT:

viene visualizzato questo pacchetto a lavorare:

pkt = IP(len=16384, src='0.0.0.0', dst='127.0.0.1', 
    id=RandShort(), ttl=2)/TCP(sport=255, 
     dport=900, flags="S", window=200, 
     options=[('MSS', 1460), ('WScale', 2)]) 
spkt = bytes(pkt) 
spkt += '\x00'*20 

Se non si aggiungono gli zeri non funziona.

+0

Puoi correggere l'importazione nel tuo primo frammento di codice? (anche, fatto divertente mentre leggo la richiesta della tua domanda: puoi usare '" ... ".decode (" base64 ")' e '" ... ".encode (" base64 ")' invece di 'import base64') . Ok, mi dispiace, non posso aiutare con questo. Ma tu hai il mio upvote. –

+0

sì, risolto l'importazione. –

+0

FWIW, sto ricevendo lo stesso errore sul tuo codice. –

risposta

3

Ho finito per decidere che i Raw Sockets sono solo per essere sfruttati per essere utilizzabili. Soprattutto perché questo software deve essere multipiattaforma, i quirks per OSX potrebbero non essere applicabili ad altri sistemi operativi.

Per il momento ho semplicemente avvolto le "prese" fornite da scapy. In futuro scriverò qualcosa che dipende solo da libdnet (poiché questo è ciò che scapy fa per scrivere frame grezzi).

potete trovare qui questo implementata:

https://github.com/hellais/txscapy

0

0.0.0.0 non sembra un indirizzo IP valido per me. Cambiare questo valore con qualsiasi altro valore fa la differenza?

+0

Sembra che non faccia alcuna differenza. –

+0

no, non fa alcuna differenza. Stranamente questo pacchetto, ad esempio, sembra funzionare: pkt = IP (len = 16384, src = '0.0.0.0', dst = '127.0.0.1', id = RandShort(), ttl = 2)/TCP (sport = 255, dport = 900, flags = "S", finestra = 200, options = [('MSS', 1460), ('WScale', 2)]) spkt = byte (pkt) spkt + = '\ x00' * 20 Se non si aggiungono i 20 zeri fallisce come l'altro. (aggiungendo il pacchetto al post correttamente formattato) –

+0

Strano. Boh. Il mio prossimo pensiero è che il kernel OS X è pieno di bug oscuri come questo. ;) –

0
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import socket 
>>> from scapy.all import IP, TCP 
WARNING: No route found for IPv6 destination :: (no default route?) 
>>> pkt = IP(src='0.0.0.0', dst='127.0.0.1')/TCP() 
>>> spkt1 = str(pkt) 
>>> 
>>> outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 
>>> outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1) 
>>> outs.sendto(spkt1, ('127.0.0.1', 0)) 
40 

non sembra avere alcun errore di scrittura che specifica serie di pacchetti - sto usando x86_64 con un kernel 2.6.38- * GNU/Linux.

Forse il tuo problema è legato ad un danno cerebrale di Mac OS X con socket non elaborati?

0

Un altro problema correlato. Il modulo Python impacket ha lo script ping.py per eseguire il ping degli host.Su Mac OS X Lion ho ottenuto un errore durante l'utilizzo di questo script:

Traceback (most recent call last): 
    File "/private/var/www/env/bin/ping.py", line 73, in <module> 
    s.sendto(ip.get_packet(), (dst, 0)) 
socket.error: [Errno 22] Invalid argument 

Ma su Ubuntu tutto lavora benissimo e sto ottenendo risposte da host.

0

Non ho prove concrete, ma penso che questo potrebbe essere correlato alla dimensione del carico utile minimo di Ethernet.

Da wikipedia:

The minimum payload is 42 octets when 802.1Q tag is present and 46 octets when absent.

tuo esempio primo pacchetto era solo 40 byte, quindi sarebbe sotto del limite in entrambi i casi. Potresti provare a cambiare il padding da 20 byte a quei valori per verificare che smetta di funzionare su uno dei limiti.

In tal caso, il comportamento ha perfettamente senso; il sistema operativo sta rifiutando il pacchetto perché non gli stai dando abbastanza dati per costruire un pacchetto valido.

1

Un'intestazione IP è necessaria per avere un multiplo di 32 bit per essere valido. E c'è anche un'area imbottita alla fine.

Quindi, a seconda delle opzioni IP impostate nell'intestazione, che occupa una quantità variabile di bit, è necessario contare i bit e padding.

Sembra che sistemi operativi diversi lo gestiscano diversamente. Si potrebbe pensare che un sistema operativo intelligente farebbe questo riempimento per te.