Zócalos crudos y sendto en pitón

Estoy trabajando en la integración de scapy con twisted, pero me encontré con un error muy extraño en OSX que parece que no puedo entender.

Básicamente, no puedo enviar un paquete TCP válido (incluidos los encabezados 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 tengas scapy activado, no quieres usarlo, este es el paquete base64 codificado:

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

Lo muy extraño es que un paquete que es casi idéntico parece que se envía correctamente:

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

Así es como se ven los dos paquetes:

SPKT1
0000   45 00 00 28 00 01 00 00  40 06 FB CE 00 00 00 00   E..(....@.......
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   E.@.............
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 revisarlos en Wirehark solo difieren en la parte TCP.

He realizado muchos experimentos diferentes y al final pude establecer ciertas opciones TCP específicas para que se enviara el paquete, pero no tiene sentido que un paquete así no funcione.

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

EDITAR:

Este paquete parece funcionar:

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 añades los ceros no funciona.

Respuestas a la pregunta(6)

Su respuesta a la pregunta