我创建了一个 Python 3.6 脚本,该脚本通过以太网创建原始 UDP 数据包到具有已知 MAC 地址和 IPv4 地址的系统。该脚本在 Beaglebone Black (BBB) 上运行,该 BBB 通过以太网直接连接到运行 Ubuntu 16.04 的笔记本电脑。该脚本也在Ubuntu系统上运行(src和dst地址明显改变)。我还通过串行连接访问 BBB 终端。 BBB 可以成功 ping 笔记本电脑,反之亦然。当笔记本电脑运行Python脚本时,数据包显示为Wireshark发送的,以太网端口灯闪烁,然后tcpdump
BBB上运行的实例确认数据包已发送。但是在BBB上运行脚本时, tcpdump
BBB上的实例显示数据包已发送;但以太网端口灯不亮,笔记本电脑没有收到数据包。在两个系统启动时,当我运行时ifconfig
,两个以太网接口都没有 IP 地址,因此我必须将它们设置为任意地址(即使在我这样做之前,数据包也会将笔记本电脑发送到 BBB,而不是相反)。
笔记本电脑的 MAC 地址为 AX:XX:XX:XX:XX:XA,其 IP 为 192.168.1.XA BBB 的 MAC 地址为 BX:XX:XX:XX:XX:XB,其 IP 为 192.168.1.XB我使用端口 1235 进行所有操作。
ifconfig
在笔记本电脑上调用会给出:
enp0s31f6 Link encap:Ethernet HWaddr AX:XX:XX:XX:XX:XA
inet addr:192.168.1.XA Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::56ee:75ff:fece:4227/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:537 errors:0 dropped:0 overruns:0 frame:0
TX packets:2912 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:154829 (154.8 KB) TX bytes:516547 (516.5 KB)
Interrupt:16 Memory:f2200000-f2220000
调用ifconfig
BBB 会给出:
eth0 Link encap:Ethernet HWaddr BX:XX:XX:XX:XX:XB
inet addr:192.168.1.XB Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::6a3:16ff:feba:676a%132688/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2124 errors:0 dropped:0 overruns:0 frame:0
TX packets:669 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:402654 (393.2 KiB) TX bytes:173920 (169.8 KiB)
Interrupt:174
当脚本在笔记本电脑上运行时,BBBtcpdump -n udp -vv -X
如下所示:
04:47:15.179497 IP (tos 0x0, ttl 64, id 52223, offset 0, flags [DF], proto UDP (17), length 33)
192.168.1.XA.1235 > 192.168.1.XB.1235: [no cksum] UDP, length 5
0x0000: 4500 0021 cbff 4000 4011 ea79 c0a8 017f E..!..@[email protected]....
0x0010: c0a8 0183 04d3 04d3 000d 0000 0003 020f ................
0x0020: 0f00 0000 0000 0000 0000 0000 0000 ..............
当脚本在BBB上运行时,笔记本电脑没有收到它,但tcpdump -n udp -vv -X
BBB上的显示已发送:
04:51:31.613740 IP (tos 0x0, ttl 64, id 34794, offset 0, flags [DF], proto UDP (17), length 33)
192.168.1.XB.1235 > 192.168.1.XA.1235: [no cksum] UDP, length 5
0x0000: 4500 0021 87ea 4000 4011 2e8f c0a8 0183 E..!..@.@.......
0x0010: c0a8 017f 04d3 04d3 000d 0000 0003 020f ................
0x0020: 0f .
在笔记本电脑和 BBB 上运行的 python3.6 脚本是:
import socket
import time
import struct
import random
#the following lists are specified as [src, dst]
#The order of the elements of these two element lists are reversed for the BBB
MAC = ["AX XX XX XX XX XA", "BX XX XX XX XX XB"]
IP = ["192.168.1.XA", "192.168.1.XB"]
port = [1235, 1235]
address = (IP[1], port[1])
#iface = 'eth0' for the BBB, 'enp0s31f6' for Laptop running Ubuntu 16.04
iface = 'enp0s31f6'
def shex(str):
result = hex(int(str))
return result[2:].zfill(2)
def ipToHex(ip):
a = ip.split('.')
return '{:02X} {:02X} {:02X} {:02X}'.format(*map(int, a))
def checksum(hdr):
hdr = "".join(hdr.split())
hdr = " ".join(hdr[i:i + 2] for i in range(0, len(hdr), 2)).split()
hdr = list(map(lambda x: int(x, 16), hdr))
hdr = struct.pack("%dB" % len(hdr), *hdr)
cksum = 0
for i in range(0, len(hdr), 2):
word = hdr[i] + (hdr[i + 1] << 8)
temp = cksum + word
cksum = (temp & 0xFFFF) + (temp >> 16)
res = ~cksum & 0xFFFF
return '{:04X}'.format(((res << 8) & 0xFF00) | ((res >> 8) & 0x00FF))
class EthernetPacket:
def __init__(self, mac, payload):
self.srcMAC = mac[0]
self.dstMAC = mac[1]
self.type = '{:04X}'.format(0x0800)
self.payload = payload
def send(self, sock):
sock.send(bytes.fromhex(self.srcMAC + self.dstMAC + self.type + self.payload.construct()))
time.sleep(0.005)
class IPv4Packet:
def __init__(self, ip, payload):
self.srcIP = ipToHex(ip[0])
self.dstIP = ipToHex(ip[1])
self.ver = "45 00"
self.id = '{:04X}'.format(0xFFFF & random.randrange(0, 65536)) + " 40 00 40 11"
self.length = payload.length + 20
self.payload = payload
hdr = self.ver + '{:04X}'.format(self.length) + self.id + "0000" + self.srcIP + self.dstIP
self.checksum = checksum(hdr)
def construct(self):
return self.ver + '{:04X}'.format(
self.length) + self.id + self.checksum + self.srcIP + self.dstIP + self.payload.construct()
class UDPPacket:
def __init__(self, port, payload):
self.srcPort = '{:04X}'.format(port[0])
self.dstPort = '{:04X}'.format(port[1])
self.checksum = "0000"
self.length = len(bytes.fromhex(payload)) + 8
self.payload = payload
def construct(self):
return self.srcPort + self.dstPort + '{:04X}'.format(self.length) + self.checksum + self.payload
def main():
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
sock.bind((iface, 1235))
msg = 0
cmd = input("Enter Command: ")
task = cmd.split()
if not task:
task = ['null']
while task[0] != 'exit' and task[0] != 'quit' and task[0] != 'close':
if task[0] == 'light':
param1, param2 = shex('00') + ' ', shex('00')
if len(task) > 1:
param1 = shex(task[1]) + ' '
if len(task) > 2:
param2 = shex(task[2])
msg = '00 03 02 ' + param1 + param2
u = UDPPacket(port, msg)
i = IPv4Packet(IP, u)
e = EthernetPacket(MAC, i)
e.send(sock)
cmd = input("Enter Command: ")
task = cmd.split()
sock.close()
if __name__ == "__main__":
main()
任何帮助表示赞赏。