Raw socket linux python

RAW client-server socket python

are not working. I have no clue how to program both the Client.py and the Server.py. Can someone help me?

2 Answers 2

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):

 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 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).

Читайте также:  Управление sql данными linux

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

 +---------+ ---------\ active OPEN | CLOSED | \ ----------- +---------+| | | 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) 

Источник

# Sockets

Many programming languages use sockets to communicate across processes or between devices. This topic explains proper usage the the sockets module in Python to facilitate sending and receiving data over common networking protocols.

# Sending data via UDP

UDP is a connectionless protocol. Messages to other processes or computers are sent without establishing any sort of connection. There is no automatic confirmation if your message has been received. UDP is usually used in latency sensitive applications or in applications sending network wide broadcasts.

The following code sends a message to a process listening on localhost port 6667 using UDP

Note that there is no need to «close» the socket after the send, because UDP is connectionless

from socket import socket, AF_INET, SOCK_DGRAM s = socket(AF_INET, SOCK_DGRAM) msg = ("Hello you there!").encode('utf-8') # socket.sendto() takes bytes as input, hence we must encode the string first. s.sendto(msg, ('localhost', 6667)) 

# Receiving data via UDP

UDP is a connectionless protocol. This means that peers sending messages do not require establishing a connection before sending messages. socket.recvfrom thus returns a tuple ( msg [the message the socket received], addr [the address of the sender])

A UDP server using solely the socket module:

from socket import socket, AF_INET, SOCK_DGRAM sock = socket(AF_INET, SOCK_DGRAM) sock.bind(('localhost', 6667)) while True: msg, addr = sock.recvfrom(8192) # This is the amount of bytes to read at maximum print("Got message from %s: %s" % (addr, msg)) 

Below is an alternative implementation using socketserver.UDPServer :

from socketserver import BaseRequestHandler, UDPServer class MyHandler(BaseRequestHandler): def handle(self): print("Got connection from: %s" % self.client_address) msg, sock = self.request print("It said: %s" % msg) sock.sendto("Got your message!".encode(), self.client_address) # Send reply serv = UDPServer(('localhost', 6667), MyHandler) serv.serve_forever() 

By default, sockets block. This means that execution of the script will wait until the socket receives data.

# Sending data via TCP

Sending data over the internet is made possible using multiple modules. The sockets module provides low-level access to the underlying Operating System operations responsible for sending or receiving data from other computers or processes.

The following code sends the byte string b’Hello’ to a TCP server listening on port 6667 on the host localhost and closes the connection when finished:

from socket import socket, AF_INET, SOCK_STREAM s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost', 6667)) # The address of the TCP server listening s.send(b'Hello') s.close() 

Socket output is blocking by default, that means that the program will wait in the connect and send calls until the action is ‘completed’. For connect that means the server actually accepting the connection. For send it only means that the operating system has enough buffer space to queue the data to be send later.

Sockets should always be closed after use.

# Multi-threaded TCP Socket Server

When run with no arguments, this program starts a TCP socket server that listens for connections to 127.0.0.1 on port 5000 . The server handles each connection in a separate thread.

When run with the -c argument, this program connects to the server, reads the client list, and prints it out. The client list is transferred as a JSON string. The client name may be specified by passing the -n argument. By passing different names, the effect on the client list may be observed.

client_list.py

import argparse import json import socket import threading def handle_client(client_list, conn, address): name = conn.recv(1024) entry = dict(zip(['name', 'address', 'port'], [name, address[0], address[1]])) client_list[name] = entry conn.sendall(json.dumps(client_list)) conn.shutdown(socket.SHUT_RDWR) conn.close() def server(client_list): print "Starting server. " s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('127.0.0.1', 5000)) s.listen(5) while True: (conn, address) = s.accept() t = threading.Thread(target=handle_client, args=(client_list, conn, address)) t.daemon = True t.start() def client(name): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', 5000)) s.send(name) data = s.recv(1024) result = json.loads(data) print json.dumps(result, indent=4) def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument('-c', dest='client', action='store_true') parser.add_argument('-n', dest='name', type=str, default='name') result = parser.parse_args() return result def main(): client_list = dict() args = parse_arguments() if args.client: client(args.name) else: try: server(client_list) except KeyboardInterrupt: print "Keyboard interrupt" if __name__ == '__main__': main() 

Server Output

$ python client_list.py Starting server... 

Client Output

$ python client_list.py -c -n name1  "name1":  "address": "127.0.0.1", "port": 62210, "name": "name1" > > 

The receive buffers are limited to 1024 bytes. If the JSON string representation of the client list exceeds this size, it will be truncated. This will cause the following exception to be raised:

ValueError: Unterminated string starting at: line 1 column 1023 (char 1022) 

# Raw Sockets on Linux

First you disable your network card’s automatic checksumming:

sudo ethtool -K eth1 tx off 

Then send your packet, using a SOCK_RAW socket:

#!/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, # but you could have anything you want instead # Have a look at the 'struct' module for more # flexible packing/unpacking of binary data # and 'binascii' for 32 bit CRC 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) 

# Parameters

Parameter Description
socket.AF_UNIX UNIX Socket
socket.AF_INET IPv4
socket.AF_INET6 IPv6
socket.SOCK_STREAM TCP
socket.SOCK_DGRAM UDP

Источник

How Do I Use Raw Socket in Python?

I am writing an application to test a network driver for handling corrupted data. And I thought of sending this data using raw socket, so it will not be corrected by the sending machine’s TCP-IP stack. I am writing this application solely on Linux. I have code examples of using raw sockets in system-calls, but I would really like to keep my test as dynamic as possible, and write most if not all of it in Python. I have googled the web a bit for explanations and examples of the usage of raw sockets in python, but haven’t found anything really enlightening. Just a a very old code example that demonstrates the idea, but in no means work. From what I gathered, Raw Socket usage in Python is nearly identical in semantics to UNIX’s raw socket, but without the struct s that define the packets structure. I was wondering if it would even be better not to write the raw socket part of the test in Python, but in C with system-calls, and call it from the main Python code?

8 Answers 8

First you disable your network card’s automatic checksumming:

sudo ethtool -K eth1 tx off 

And then send your dodgy frame from python 2 (You’ll have to convert to Python 3 yourself):

#!/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, # but you could have anything you want instead # Have a look at the 'struct' module for more # flexible packing/unpacking of binary data # and 'binascii' for 32 bit CRC 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) 

Источник

Оцените статью
Adblock
detector