原始客户端 - 服务器套接字 python

reb*_*rid 0 python sockets client-server raw-sockets

我想在 Python 中实现一个 RAW 套接字,然后将数据从客户端发送到服务器。

与普通套接字不同,我尝试使用以下定义

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
Run Code Online (Sandbox Code Playgroud)

但命令为

s.listen(1), s.connect()
Run Code Online (Sandbox Code Playgroud)

不工作。我不知道如何对 Client.py 和 Server.py 进行编程。有人能帮我吗?

Tor*_*xed 5

那是因为原始套接字根本不使用以太网/TCP/IP 库。这是一个 RAW 套接字,您负责发送的任何数据。您还负责通过发送正确的 SYN/ACK 顺序连接到对等方。

传统套接字是一个“抽象”层,供您发送负载(数据)。这意味着您套接字连接到目的地,您告诉套接字要发送的数据,假设您使用的是基于 TCP 的套接字,您的数据将预先带有与 TCP 协议和版本相对应的标头,并且您的数据可能会根据以下内容进行分段您尝试推送多少数据。

所有这些都通过传统套接字自动发生。

这是 TCP 标头的大致样子(脱离上下文,但它会给您一个想法):

   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                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Run Code Online (Sandbox Code Playgroud)

请注意,数据是您通常所做的,但是在使用 RAW 套接字时,您需要将所有这些信息块发送到您的以太网电缆上

如果有人没有打败我,我可以在今晚晚些时候发布一些代码,但这是一个很好的简短用法示例:如何在 Python 中使用原始套接字?


tl;博士:

您需要构建一个以太网标头和一个 TCP 标头,并根据 RFC 标准将您的数据添加到其中(这可能是一个很好的起点:https : //tools.ietf.org/html/rfc793)。然后您需要“简单地”将其发送到您的“套接字”。RAW 套接字没有任何魔法,您可以使用源地址+目标地址构建标头,然后将有效负载发送到电缆上,希望您正确构建了数据包。

回复评论:

socket.accept()- 此函数用于传统套接字“存储”会话信息(源:端口 -> 目标:端口)。此函数从传入连接尝试的缓冲队列中获取客户端并“激活”它们。这不适用于原始套接字,原因是普通套接字的抽象层再次不存在。您的 RAW 套接字将侦听任何传入数据(而不是连接),这意味着您负责首先接收一个SYN数据包,您需要使用一个数据包进行响应SYN-ACK,您将在其中收到最终的ACK. 此时,您可以使用正确的信息(源端口等)在你们之间发送数据。

这是普通套接字中提供的抽象层的良好(ASCII)流程图:

                              +---------+ ---------\      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  |
                              +---------+                   +---------+
Run Code Online (Sandbox Code Playgroud)

这是一个服务器示例:

#!/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)
Run Code Online (Sandbox Code Playgroud)

发现一些我几乎没有开始使用的旧代码,可能会派上用场:https : //github.com/Torxed/Scripts/tree/master/python/Laboratory