使用Python构造数据包

一、socket函数

在这里插入图片描述

1、socket函数参数及方法

1)参数

Python 中,用 socket()函数来创建套接字,语法格式如下

socket.socket([family[, type[, proto]]])

· family: 套接字家族可以使 AF_UNIX 或者 AF_INET。
· type: 套接字类型可以根据是面向连接的还是非连接分为 SOCK_STREAM 或 SOCK_DGRAM。
· protocol: 一般不填默认为 0。
https://gist.github.com/kevinkindom/108ffd675cb9253f8f71

2)方法

https://www.runoob.com/python/python-socket.html

2、TCP/UDP通讯

该方法自动补充MAC、IP、TCP包头,意味着我们需要填充的是包结构图中的 [ 数据 ]

1)send_udp_tcp.py

import argparse
import socket  
  
parser = argparse.ArgumentParser(description='Client')
parser.add_argument('--TCP_UDP', type=str, default='UDP')
parser.add_argument('--src_ip', type=str, default='172.16.200.1')
parser.add_argument('--dst_ip', type=str, default='172.16.200.2')
parser.add_argument('--dst_port', type=int, default=31500)
parser.add_argument('--send_times', type=int, default=10)
args = parser.parse_args()

if args.TCP_UDP == 'UDP':
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # s.bind((args.src_ip,0))                                                   # in windows
    s.setsockopt(socket.SOL_SOCKET, 25, 'ens3f0'.encode(encoding="utf-8"))      # in linux

    print("now using:"+str(args.TCP_UDP))
    print("src_ip:"+str(args.src_ip))
    print("dst_ip:"+str(args.dst_ip))
    print("dst_port:"+str(args.dst_port))
    print("send_times"+str(args.send_times))
    print("send data begin")

    for i in range(args.send_times):  
        s.sendto("test udp".encode(encoding="utf-8"), (args.dst_ip, args.dst_port)) 
    
    print("send ok")  
    s.close() 

elif args.TCP_UDP == 'TCP' : # TCP尚未测试
    print("now using:"+str(args.TCP_UDP))
    print("src_ip:"+str(args.src_ip))
    print("dst_ip:"+str(args.dst_ip))
    print("dst_port:"+str(args.dst_port))
    print("send_times"+str(args.send_times))
    print("send data begin")
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    try:
        s.connect((args.dst_ip, args.dst_port)) 
    except Exception:
        print("server port not connect!")
    
    for i in range(args.send_times):
        s.send('test tcp')

    print("send ok")
    s.close()

else:
    print("error TCP/UDP type")

2)recv_udp_tcp.py

import argparse
import socket  
  
parser = argparse.ArgumentParser(description='Server')
parser.add_argument('--TCP_UDP', type=str, default='UDP')
parser.add_argument('--my_ip', type=str, default='172.16.200.2')
parser.add_argument('--my_port', type=int, default=31500)
args = parser.parse_args()

if args.TCP_UDP == 'UDP':
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind((args.my_ip, args.my_port))

    print("now using:"+str(args.TCP_UDP))
    print("my_ip:"+str(args.my_ip))
    print("my_port:"+str(args.my_port))
    print("recv data begin")

    while True:  
        data, addr = s.recvfrom(2048)
        datas = str(data,encoding='utf-8')
        print("received:" + datas + "\n")
        # print("received:" + data + "\nfrom:" + addr)
    
    s.close()

elif args.TCP_UDP == 'TCP' : # TCP尚未测试
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    s.bind((args.my_ip, args.my_port)) 
    

    print("now using:"+str(args.TCP_UDP))
    print("my_ip:"+str(args.my_ip))
    print("my_port:"+str(args.my_port))
    print("recv data begin")

    s.listen(5)
    ss, addr = s.accept() # 被动接受TCP客户端连接,(阻塞式)等待连接的到来
    print('got connected from',addr)

    ra = ss.recv(512)
    print(ra)

    ss.close()
    s.close()

else:
    print("error TCP/UDP type")

3、自行构造数据包

1)自行构造TCP部分及后面数据

意味着我们需要填充的是包结构图中的 [ TCP包头 | 数据 ]

需要使用RAW SOCKET 通信,AF_INET表示使用IPv4协议(自动补充以太网和IPv4部分),socket.SOCK_RAW指TCP及后面自行构造,NGA_TYPE指IPv4部分协议类型,6表示下一个部分为TCP,17表示下一个部分为UDP,一般自行构造NGA_TYPE=18

import socket  
  
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, NGA_TYPE) 
nga = struct.pack( # ngaa包头部分
                '!IbbIbI',  # I 表示unsigned int(4byte), b表示signed char(1byte), !表示顺序解析
                worker_id,
                degree,
                0,
                aggindex,
                switch_id,
                sequence + pkt_id
            )
s.sendto(nga, (self.dst_ip, 0))

2)自行构造IP部分及以后

也即是说,需要填充的是上图中的 [ IP包头 | TCP包头 | 数据 ] 的内容

socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

3)完全自行构造

意味着我们需要填充的是上图中的 [ MAC包头 | IP包头 | TCP包头 | 数据 ] 的内容

socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

4、指定网卡

https://stackoverflow.com/questions/8437726/can-python-select-what-network-adapter-when-opening-a-socket

二、参考资料

https://www.cnblogs.com/JenningsMao/p/9487465.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值