2012-06-12 17 views
13

Estoy trabajando en la integración de scapy con twisted, pero me encontré con este error muy extraño en OSX que no puedo entender.Sockets raw y sendto en python

Básicamente no puedo enviar un paquete TCP válido (incluidos los encabezados de IP) a través de un socket sin formato. Esto es lo que estoy haciendo:

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)) 

Cuando ejecuto esto me sale el siguiente error:

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

En caso de que no tiene en scapy no quieren usarlo de esta es el paquete codificado base 64:

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

lo extraño es que un paquete que es casi idéntica parece estar enviado correctamente:

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

Así es como los dos paquetes se ven como:

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........ 

Al marcar a cabo en Wireshark que sólo difieren en la parte TCP.

He hecho muchos experimentos diferentes y al final pude establecer ciertas opciones específicas de TCP para enviar el paquete, pero no tiene sentido que dicho paquete no funcione.

¿Alguien tiene una idea de por qué esto puede estar pasando?

EDIT:

parece este paquete a trabajar:

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 

Si no agrega los ceros no funciona.

+0

¿Podría corregir la 'importación' en su primer fragmento de código? (también, es un hecho divertido mientras leo la petición de su pregunta: puede usar '" ... ".decode (" base64 ")' y '" ... ".encode (" base64 ")' en lugar de 'import base64' . Ok, lo siento, no puedo ayudar con esto. Pero tienes mi voto positivo. –

+0

sí, solucionó la importación. –

+0

FWIW, estoy obteniendo el mismo error en su código. –

Respuesta

3

Terminé decidiendo que los sockets crudos solo tienen errores para poder usarlos. Especialmente dado que este software necesita ser multiplataforma, las peculiaridades para OSX pueden no ser aplicables a otros sistemas operativos.

Por el momento, simplemente envuelvo los "sockets" proporcionados por scapy. En el futuro escribiré algo que solo depende de libdnet (ya que eso es lo que Scapy hace para escribir marcos sin formato).

Usted puede encontrar esta implementado aquí:

https://github.com/hellais/txscapy

0

0.0.0.0 no se parece a una dirección de origen de IP válida para mí. ¿Cambiar esto a cualquier otro valor hace alguna diferencia?

+0

Parece que no hace ninguna diferencia. –

+0

no, no hace ninguna diferencia. Curiosamente, este paquete, por ejemplo, parece funcionar: pkt = IP (len = 16384, src = '0.0.0.0', dst = '127.0.0.1', id = RandShort(), ttl = 2)/TCP (deporte = 255, dport = 900, flags = "S", ventana = 200, options = [('MSS', 1460), ('WScale', 2)]) spkt = bytes (pkt) spkt + = '\ x00' * 20 Si no agrega los 20 ceros, falla como el otro. (agregando el paquete a la publicación con el formato correcto) –

+0

Weird. No sé. Mi siguiente pensamiento es que el kernel de OS X está lleno de errores desconocidos como este. ;) –

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 

no parecen tener ningún error al escribir ese conjunto específico de paquetes - Estoy usando x86_64 con un kernel 2.6.38- * GNU/Linux.

¿Quizás su problema está relacionado con algún daño cerebral en Mac OS X con conectores crudos?

0

Otro tema relacionado. El módulo Python impacket tiene una secuencia de comandos ping.py para hacer ping a los hosts.En Mac OS X Lion Tengo un error durante el uso de este 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 

Pero en Ubuntu todo funciona bien y yo estoy recibiendo respuestas de los ejércitos.

0

No tengo pruebas contundentes, pero creo que esto podría estar relacionado con el tamaño mínimo de carga útil de ethernet.

De wikipedia:

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

Su primer paquete ejemplo fue sólo 40 bytes, por lo que sería por debajo del límite en cualquiera de los casos. Podría experimentar cambiando el relleno de 20 bytes a esos valores para verificar que deja de funcionar en uno de los límites.

Si es así, el comportamiento tiene mucho sentido; el SO está rechazando el paquete porque no le está dando suficientes datos para construir un paquete válido.

1

Se requiere un encabezado IP para tener un múltiplo de 32 bits para que sea válido. Y también hay un área de relleno en el extremo.

Dependiendo de las opciones de IP configuradas en el encabezado, que ocupa una cantidad variable de bits, es necesario contar los bits y relleno.

Parece que los sistemas operativos diferentes manejan esto de manera diferente. Uno podría considerar que un sistema operativo inteligente haría este relleno para usted.