Soquetes brutos e sendto em python

Eu estou trabalhando na integração do scapy com o twisted, mas eu me deparei com esse bug muito estranho no OSX que eu não consigo descobrir.

Basicamente eu sou incapaz de enviar um pacote TCP válido (inclusive de cabeçalhos IP) através de um socket bruto. Isso é o que estou fazendo:

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 eu executo isso, recebo o seguinte erro:

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

Caso você não tenha scapy em não quer usá-lo este é o pacote base64 codificado:

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

O mais estranho é que um pacote quase idêntico parece ser enviado corretamente:

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

É assim que os dois pacotes se parecem:

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

Ao verificá-los no wireshark, eles diferem apenas na parte TCP.

Eu fiz um monte de experimentos diferentes e consegui, no final, definir certas opções TCP específicas para obter o pacote enviado, mas não faz sentido que tal pacote não funcione.

Alguém tem uma ideia de por que isso pode estar acontecendo?

EDITAR:

Este pacote 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

Se você não adicionar os zeros, isso não funcionará.

questionAnswers(6)

yourAnswerToTheQuestion