【发布时间】:2022-01-21 01:58:10
【问题描述】:
我正在使用 python-pytun 创建两个 TUN 接口(tun0 和 tun1)。我的目标是在两个接口上创建数据包接收器,因此当数据包进入其网络时,它们将创建适当的响应。我使用 ICMP 帧作为初始测试。 tun0网络为10.8.0.0/29,tun1网络为10.8.1.0/29。
当我运行代码时,我使用 sendp 将数据包从 tun0 发送到 tun1。奇怪的是,tun0 接收器回调触发,我最终看到了这个输出:
[0] 新数据包:10.8.0.1 -> 10.8.1.2
在程序仍在运行的情况下(因为存在无限循环),我可以使用另一个终端向该接口发送 ping。从那个终端我发出这个命令:
ping -I 10.8.0.1 10.8.1.2
哪个(我认为)生成与 python 代码相同的数据包。无论如何,当我这样做时,我的 python 程序看起来就像它正在触发正确的接收器回调,如下所示:
[1] 新数据包:10.8.0.1 -> 10.8.1.2
有什么想法吗?这是供参考的代码。感谢您的任何意见!
#!/usr/bin/env python3
from pytun import TunTapDevice, IFF_TAP
import os
from scapy.all import *
from threading import Thread
from time import sleep
# Make sure we're running as root, otherwise report an error and exit
if os.geteuid() != 0:
exit("Please run as root")
class Sniffer(Thread):
def __init__(self, interface, receive_callback):
super().__init__()
self.interface = interface
self.receive_callback = receive_callback
def run(self):
print("Interface: {}".format(self.interface))
sniff(iface=self.interface, filter="ip", prn=self.receive_callback)
class InterfaceFactory:
def __init__(self):
self.interfaces = []
def create_tun_interface(self, interface, addr, dstaddr, prefixLen, receive_callback=None):
# Looks like a TAP interface isn't what I want, but I'll leave the code here for now just in case
#tun = TunTapDevice(name=interface, flags=IFF_TAP)
# Create the TUN interface with the given name
tun = TunTapDevice(name=interface)
# Convert the prefix length to a subnet mask string in the form xxx.xxx.xxx.xxx
netmask = '.'.join([str((m>>(3-i)*8)&0xff) for i,m in enumerate([-1<<(32-prefixLen)]*4)])
# Assign network characteristics to the new TUN interface
tun.addr = addr
tun.netmask = netmask
tun.mtu = 1500
tun.dstaddr = dstaddr
# I don't think I need to set the MAC address, one seems to be assigned anyway,
# leaving the code here for debugging purposes.
#tun.hwaddr = b'\x00\x11\x22\x33\x44\x55'
# Bring the new TUN interface up
tun.up()
# Register the callback function if one was specified
if receive_callback:
sniffer = Sniffer(interface, receive_callback)
sniffer.start()
# Append the new interface to a member list to keep it within scope,
# otherwise it would remove the interface from the system
self.interfaces.append(tun)
def get_tun_interface_handle(self, interface):
for iface in self.interfaces:
if iface.name == interface:
return iface
return None
interfaceFactory = InterfaceFactory()
def tun0_receive_callback(packet):
ip_layer = packet.getlayer(IP)
print("[0] New Packet: {src} -> {dst}".format(src=ip_layer.src, dst=ip_layer.dst))
#packet.show2()
#if packet.haslayer(ICMP):
def tun1_receive_callback(packet):
ip_layer = packet.getlayer(IP)
print("[1] New Packet: {src} -> {dst}".format(src=ip_layer.src, dst=ip_layer.dst))
#packet.show2()
#if packet.haslayer(ICMP):
interfaceFactory.create_tun_interface("tun0", "10.8.0.1", "10.8.0.0", 29, tun0_receive_callback)
interfaceFactory.create_tun_interface("tun1", "10.8.1.1", "10.8.1.0", 29, tun1_receive_callback)
# Wait a second for the sniffer class to do what it needs to do
# not waiting will prevent the callback from firing
sleep(1)
# Send packet from tun0 to tun1, ICMP type 8 is Echo. Note: type 0 is Echo Reply
# More info here: https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml#icmp-parameters-types
data = bytes(16)
frame = IP(src='10.8.0.1', dst='10.8.1.2')/ICMP(type=8)/Raw(load=data)
sendp(frame, iface="tun0")
try:
while True:
#frame.show2()
sleep(2)
except KeyboardInterrupt:
sniffer.join()
【问题讨论】:
标签: python python-3.x networking ethernet icmp