python在数据链路层使用原始套接字(rawsocket)发送接收数据

最近工作上有一项任务需要使用python在数据链路层上收发数据,遇到了很多坑,在此记录一下
注: 该脚本只能运行在 linux 系统上,windows 上无法使用原始套接字在数据链路层收发数据(socket.AF_PACKET在 windows 系统上无效)

代码如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:chenyanzhi
# datetime:2020/11/20 17:16
# software: PyCharm
import binascii
import socket
import uuid


def get_mac_address():
    """获取本机MAC地址"""
    mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
    return ''.join([mac[e:e + 2] for e in range(0, 11, 2)])


def get_resp(src_mac, raw_socket):
    """获取目标设备响应。

    数据链路层收到的是整个网卡的数据报文,需要过滤一下才能获取到发送的数据帧所对应的响应报文。
    """
    resp = raw_socket.recv(4096).hex()
    flag = 100
    while True:
        if resp[:12] == src_mac or resp[:12] == dst_mac:
            return resp
        elif flag == 0:
            raise Exception("没有收到正确响应")
        else:
            flag -= 1
            resp = raw_socket.recv(4096).hex()

ETH_P_ALL = 3
dst_mac = '00:1b:1b:e6:10:ff'.replace(':', '')
src_mac = get_mac_address()
nameOfStation = '53656375726974792e636865636b'  # Security.check

raw_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
raw_socket.bind(('eth0', ETH_P_ALL))

pn_dcp = (f'{dst_mac}{src_mac}810000008892fefd0400040000040000001a020200100001'
          f'{nameOfStation}05020002000000000000')
payload = binascii.unhexlify(pn_dcp)

print(f'send packet: {pn_dcp}')
raw_socket.send(payload)
print('ready to receive')
resp = get_resp(src_mac, raw_socket)
print(f'resp is: {resp}')

raw_socket.close()

参考资料:https://stackoverflow.com/questions/1117958/how-do-i-use-raw-socket-in-python
参考资料: https://github.com/devkid/profinet


版权声明:本文为qq_35793285原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。