Skip to content Skip to sidebar Skip to footer

Raw Client-server Socket Python

I would like to realize a RAW socket in Python and then send data from the Client to the Server. Unlike a normal socket I've tried to use the following definition s = socket.socket

Solution 1:

That's because a raw socket doesn't utelize the Ethernet/TCP/IP library at all. It's a RAW socket, you're in charge of whatever data you send. You're also in charge of connecting to your peer by sending the right SYN/ACK order.

Traditional sockets is an "abstraction" layer for you to send your payload (data). Meaning you connect your socket to a destination, you tell the socket what data to send, assuming you're using a TCP based socket your data will be prepended with a header corresponding to the TCP protocol and version and your data might get segmented based on how much data you're trying to push through.

All this happens automatically with a traditional socket.

This is what a TCP header looks like, roughly (taken out of context but it will give you an idea):

012301234567890123456789012345678901
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          SourcePort          |       DestinationPort        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        SequenceNumber                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    AcknowledgmentNumber                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         UrgentPointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Note that data is what you normally do, but when working with RAW sockets, you need to send all these information blocks on to your Ethernet cable.

I could post some code later tonight perhaps if someone doesn't beat me to it, but here's a good short usage example: How Do I Use Raw Socket in Python?


tl;dr:

You need to build a Ethernet header and a TCP header and add your data to it according to the RFC standard (this might be a good place to start: https://www.rfc-editor.org/rfc/rfc793). Then you need to "simply" send that out on to your "socket". There's no magic involved with RAW sockets, you build your header with a source+destination address, and you send your payload out onto the cable hoping you built the packet correctly.

Answer to comments:

socket.accept() - This function is used in traditional sockets to "store" session information (Source:Port -> Destination:Port). This function takes clients from a buffered queue of incoming connection attempts and "activates" them. This does not apply to raw sockets, the reason being is that the abstraction layer from normal sockets is again, not present. Your RAW socket will listen to any incoming data (not connections), meaning you're in charge of receiving first a SYN packet which you need to respond with a SYN-ACK in which you'll receive a final ACK. At this point, you're good to go for sending data between you with the correct information (source port etc).

Here's a good (ASCII) flow-chart of the abstraction layer provided in a normal socket:

+---------+ ---------\      active OPEN  |  CLOSED |            \    -----------  +---------+<---------\   \   create TCB  |^              \   \  snd SYN    
                   passive OPEN||CLOSE        \   \           
                   ------------ |     | ----------       \   \         create TCB  ||delete TCB         \   \       
                                V     |                      \   \     
                              +---------+            CLOSE    |    \   |  LISTEN |---------- |     |  +---------+          delete TCB |     |  
                   rcv SYN      ||     SEND              ||-----------   |     |    -------            |     V  +---------+      snd SYN,ACK  /       \   snd SYN          +---------+||<-----------------           ------------------>|         ||   SYN   |                    rcv SYN                     |   SYN   ||   RCVD  |<-----------------------------------------------|   SENT  |||                    snd ACK                     ||||------------------           -------------------|         |+---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+|--------------   |     |   -----------                  |                  x         ||     snd ACK                    
   |                            V     V                                
   |CLOSE+---------+                              |-------                  |  ESTAB  |                              | snd FIN                  +---------+                              |CLOSE||    rcv FIN                     
   V                  -------   |     |    -------                     +---------+          snd FIN  /       \   snd ACK          +---------+|  FIN    |<-----------------           ------------------>|  CLOSE  || WAIT-1|------------------                              |   WAIT  |+---------+          rcv FIN  \                            +---------+| rcv ACK of FIN   -------   |                            CLOSE  |  |--------------   snd ACK   |                           ------- |  
   V        x                   V                           snd FIN V  
 +---------+                  +---------+                   +---------+|FINWAIT-2|| CLOSING ||LAST-ACK|+---------+                  +---------+                   +---------+|                rcv ACK of FIN |                 rcv ACK of FIN ||  rcv FIN       -------------- |    Timeout=2MSL -------------- |  |-------              x       V    ------------        x       V  
    \ snd ACK                 +---------+delete TCB         +---------+------------------------>|TIME WAIT|------------------>| CLOSED  |+---------+                   +---------+

Here's a server example:

#!/usr/bin/env python
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
#s.bind(("eth1", 0))# We're putting together an ethernet frame here, # NOTE: Not a full TCP frame, this is important to remember!
src_addr = "\x01\x02\x03\x04\x05\x06"
dst_addr = "\x01\x02\x03\x04\x05\x06"
payload = ("["*30)+"PAYLOAD"+("]"*30)
checksum = "\x1a\x2b\x3c\x4d"
ethertype = "\x08\x01"

s.send(dst_addr+src_addr+ethertype+payload+checksum)

Found some old code that I barely got started on, might come in handy: https://github.com/Torxed/Scripts/tree/master/python/Laboratory

Solution 2:

Raw sockets are connectionless, meaning that listen and accept will not work. Yet, you can use this Python library: rawsocketpy it allows using raw sockets on Layer 2 and implements a server like option.

#!/usr/bin/env pythonfrom rawsocketpy import RawSocket

sock = RawSocket("wlp2s0", 0xEEFA)
sock.send("some data")
sock.send("personal data", dest="\xAA\xBB\xCC\xDD\xEE\xFF")

or the server form:

#!/usr/bin/env pythonfrom rawsocketpy import RawRequestHandler, RawAsyncServerCallback
import time

defcallback(handler, server):
    print("Testing")
    handler.setup()
    handler.handle()
    handler.finish()

classLongTaskTest(RawRequestHandler):
    defhandle(self):
        time.sleep(1)
        print(self.packet)

    deffinish(self):
        print("End")

    defsetup(self):
        print("Begin") 

defmain():
    rs = RawAsyncServerCallback("wlp2s0", 0xEEFA, LongTaskTest, callback)
    rs.spin()

if __name__ == '__main__':
    main()

Post a Comment for "Raw Client-server Socket Python"