簡體   English   中英

如何在 python 中發送原始以太網幀?

[英]How do I send a raw ethernet frame in python?

我需要在幾天內完成一個項目,它是一個基本的客戶端和服務器接口。 問題是它必須是所有原始套接字。 我創建它沒有問題,我只是堅持發送數據包。

首先,我嘗試將其綁定到接口“en1” ,但它一直給我一個錯誤nodename not known 當我將它綁定到我的本地 IP 地址時,它工作正常。 完成此操作后,我創建了一個原始數據包類,全部為十六進制。 然后我做了一個 sendto 調用以通過網絡發送它。

問題是當我使用wireshark捕獲數據包時,它顯示為ipv4數據包的有效負載。 我不希望它自動生成標題,這就是我的原始數據包類的用途。 你知道我有什么辦法可以取出這些標題嗎?

這是我的代碼 - 只有原始函數:

def raw():
    HOST = gethostbyname('192.168.1.10')

    s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)
    s.bind((HOST, 0))

    s.setsockopt(IPPROTO_IP, IP_HDRINCL, 0) #no headers - it wont work!!

    pckt = packet("\x68\x65\x6c\x6c\x6f")
    netpacket = pckt.getpacket()

    print "Sending.. "
    print ""

    s.sendto(netpacket, ('192.168.1.1', 80))
    data = s.recv(4096)
    print data

這是捕獲的數據包,最后帶有一個hello

007f 2809 6da2 28cf daee 2156 0800 4500 004d 1bfc 0000 4000 db59 c0a8 010a c0a8 0101* 007f     

2809 6da2 28cf daee 2156 0800 4500 0036 2352 4000 4006 0000 c0a8 010a c0a8 0101 15c0 0050 

0000 0000 0000 0000 8010 813b 0000 68656c6c6f -hello

*這( 0101 )是有效載荷的開始,即使它應該是數據包的開始。 另外我不會使用任何其他模塊,我必須使用套接字。

感謝對這個問題的評論,我設法與服務器建立了連接。 只需將地址族更改為 linux 中的 af_packet 即可。 然后我將它綁定到我的網卡並發送。 有效。 感謝人們的幫助! 這是一些示例代碼:

s = socket(AF_PACKET, SOCK_RAW)
s.bind(("en1", 0))
pckt = packet() #my class that initializes the raw hex
data = pckt.getpacket()
s.send(data)
message = s.recv(4096)
print s
print s.decode('hex')

它需要在linux或debian中。 據我所知,它在 mac osx 中不起作用。 對窗戶不以為然。 如果你有一個使用 pycap 或 scapy 的 mac,它們可以正常工作。

為了回答你的問題安德魯,這里有一個例子:

這個答案幫助我讓 WoL 工作。 在這種情況下,數據是:

preamble = bytearray((0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))
MAC = bytearray((0x00, 0x14, 0x85, 0xa4, 0x73, 0xce))
data = PREAMBLE + 16*MAC

此 Python 腳本允許在單獨的文件中發送以十六進制編寫的原始數據包(字節十六進制表示由空格或換行符分隔)。
用法是script_name.py interface packet_file

#!/bin/python

ETH_P_ALL = 0x0003
import socket
import sys

if __name__ == "__main__":
  interface = sys.argv[1]
  filename = sys.argv[2]

  with open(filename, 'r') as file:
    hexlist = [int(x, 16) for x in file.read().split()]

  packet = bytearray(hexlist)

  with socket.socket(socket.AF_PACKET, socket.SOCK_RAW) as rs:
    rs.bind((interface, ETH_P_ALL))
    sentbytes = rs.send(packet)

  print("Sent packet of length %d bytes" % sentbytes)

數據包文件示例(ARP Request who-has 192.168.1.2 tell 192.168.1.1):

 ff ff ff ff ff ff
 00 11 22 33 44 55
 08 06
 00 01 08 00 06 04
 00 01
 00 11 22 33 44 55
 C0 A8 01 02
 00 00 00 00 00 00
 C0 A8 01 01
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

請注意,由於十六進制字節之間的分隔符是空格或換行符,因此文件中的幀很容易分隔,這里前 3 行是 Ether 幀,接下來是 ARP 幀,最后一行是要到達的填充長度為 60 字節。

此文件名為my arp-packet.dat和 python 腳本名為send_raw_packet.py的用法示例:

host:~$ send_raw_packet.py eth0 arp_packet.dat
Sent packet of length 60 bytes

使用 tcpdump 捕獲顯示數據包已發送:

host:~$ tcpdump -i eth0 -Q out -tevvv -XX arp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:11:22:33:44:55 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.1.1 tell 192.168.1.2, length 46
0x0000:  ffff ffff ffff 0011 2233 4455 0806 0001  ........"3DU....
0x0010:  0800 0604 0001 0011 2233 4455 c0a8 0102  ........"3DU....
0x0020:  0000 0000 0000 c0a8 0101 0000 0000 0000  ................
0x0030:  0000 0000 0000 0000 0000 0000            ............
1 packet captured
1 packet received by filter
0 packets dropped by kernel

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM