Search code examples
pythonsocketstcpprotocolshandshake

"OSError: [WinError 10022] An invalid argument was supplied" when trying to send TCP SYN packet (python)


Currently trying to make handshake process on python using raw sockets but for some reason I can't send any packet with TCP protocol receiving OSError: [WinError 10022] An invalid argument was supplied. Here is my code:

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
s.sendto(packet, ('8.8.8.8', 80))

As packet I have tried to use scapy's TCP packet, TCP bytes from wireshark after successful sendings with other libraries and also hand-made byte strings:

def chksum(packet: bytes) -> int:
    if len(packet) % 2 != 0:
        packet += b'\0'

    res = sum(array.array("H", packet))
    res = (res >> 16) + (res & 0xffff)
    res += res >> 16

    return (~res) & 0xffff


class TCPPacket:
    def __init__(self,
                 src_host:  str,
                 src_port:  int,
                 dst_host:  str,
                 dst_port:  int,
                 flags:     int = 0):
        self.src_host = src_host
        self.src_port = src_port
        self.dst_host = dst_host
        self.dst_port = dst_port
        self.flags = flags

    def build(self) -> bytes:
        packet = struct.pack(
            '!HHIIBBHHH',
            self.src_port,  # Source Port
            self.dst_port,  # Destination Port
            0,              # Sequence Number
            0,              # Acknoledgement Number
            5 << 4,         # Data Offset
            self.flags,     # Flags
            8192,           # Window
            0,              # Checksum (initial value)
            0               # Urgent pointer
        )

        pseudo_hdr = struct.pack(
            '!4s4sHH',
            socket.inet_aton(self.src_host),    # Source Address
            socket.inet_aton(self.dst_host),    # Destination Address
            socket.IPPROTO_TCP,                 # PTCL
            len(packet)                         # TCP Length
        )

        checksum = chksum(pseudo_hdr + packet)

        packet = packet[:16] + struct.pack('H', checksum) + packet[18:]

        return packet

So literally no idea why my socket doesn't like any packet


Solution

  • I found out what is wrong. Windows doesn't allow to send TCP packets with raw sockets so this code will never work. Probably it is possible to write the same with scapy or using other libraries but that's not what I need so the only way to make it work is to run on linux. Still not sure if the packet creation is correct but TCP protocol with raw sockets sure works fine on linux.