I am working on integrating scapy with twisted, but I ran into this very weird bug on OSX that I can't seem to figure out.
Basically I am unable to send a valid TCP packet (inclusive of IP headers) via a raw socket. This is what I am doing:
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))
When I run this I get the following error:
outs.sendto(spkt1, ('127.0.0.1', 0))
socket.error: [Errno 22] Invalid argument
In case you don't have scapy on don't want to use it this is the packet base64 encoded:
import base64
spkt1 = base64.b64decode("RQAAKAABAABABvvOAAAAAH8AAAEAFABQAAAAAAAAAABQAiAAEH4AAA==")
The very strange thing is that a packet that is nearly identical appears to be sent properly:
spkt2 = base64.b64decode("RQBAAAWwAAACBgAAAAAAAH8AAAEAyAOEAAAAAAAAAACwAgDIAHsAAAIEBbQBAwMBAQEICk3PUjMAAAAABAIAAA==")
This is how the two packets look like:
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........
By checking them out in wireshark they only differ in the TCP part.
I have done a lot of different experiments and I was able in the end by setting certain specific TCP options to get the packet sent, but it does not make sense that such a packet should not work.
Does anybody have an idea why this may be happening?
EDIT:
This packet does appear to work:
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
If you don't add the zeros it does not work.
Socket programming is a way of connecting two nodes on a network to communicate with each other. One socket(node) listens on a particular port at an IP, while the other socket reaches out to the other to form a connection. The server forms the listener socket while the client reaches out to the server.
The raw socket interface provides direct access to lower layer protocols, such as the Internet Protocol (IP) and Internet Control Message Protocol (ICMP or ICMPv6). You can use raw sockets to test new protocol implementations.
In order to create a raw socket, a process must have the CAP_NET_RAW capability in the user namespace that governs its network namespace. All packets or errors matching the protocol number specified for the raw socket are passed to this socket.
Sockets have two primary properties controlling the way they send data: the address family controls the OSI network layer protocol used and the socket type controls the transport layer protocol. Python supports three address families. The most common, AF_INET, is used for IPv4 Internet addressing.
I ended up deciding that Raw Sockets are just to bugged to be usable. Especially since this software needs to be cross platform, quirks for OSX may not be applicable to other OSs.
For the time being I simply wrapped the "sockets" that are provided by scapy. In the future I will write something that only depends on libdnet (as that is what scapy does to write raw frames).
You can find this implemented here:
https://github.com/hellais/txscapy
An IP header is required to have a multiple of 32 bits to be valid. And there is also a padding area on the end.
So depending on the IP options set in the header — which occupies a variable amount of bits — one needs to count bits and padding.
Looks like different OSes handle this differently. One might consider that a clever OS would do this padding for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With