我想在两个TAP设备之间交换以太网数据包(用于在用户模式下实现TCP / IP协议栈)。
我遇到的问题是tap1和tap2只能通过网桥接收广播数据包,而不能接收点对点数据包!
例如,当我从 tap1 向 tap2 发送数据包时,tcmpdump 可以在 tap1 上捕获数据包,但 tap2 无法接收数据包。但是,当我将目标地址设置为“ff:ff:ff:ff:ff:ff”或任何未知的 mac 地址(这将触发广播)时,tap2 将接收数据包。
我的配置:
- 创建两个水龙头设备
ip tuntap add mode tap tun1
ip tuntap add mode tap tun2
# assign ip address for implmenting arp protocol
ip addr add 172.19.16.1 dev tun1
ip addr add 172.19.16.2 dev tun2
ip link set tun1 up
ip link set tun2 up
- 建立桥梁
brctl addbr br0
brctl addif br0 tun1
brctl addif br0 tun2
ip link set br0 up
以下是bridge和tap接口的状态:macs:
port no mac addr is local? ageing timer
2 46:44:6e:55:9b:c5 yes 0.00
2 46:44:6e:55:9b:c5 yes 0.00
1 f2:6b:68:c9:60:6b yes 0.00
1 f2:6b:68:c9:60:6b yes 0.00
状态:
br0
bridge id 8000.46446e559bc5
designated root 8000.46446e559bc5
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 89.77
flags
tun1 (1)
port id 8001 state forwarding
designated root 8000.46446e559bc5 path cost 100
designated bridge 8000.46446e559bc5 message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
tun2 (2)
port id 8002 state forwarding
designated root 8000.46446e559bc5 path cost 100
designated bridge 8000.46446e559bc5 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
以下是我的测试代码:
import fcntl
import os
import if_tun
import ctypes
import struct
from scapy.all import *
from if_tun import IfReq, TUNSETIFF, IFF_TUN
def register_tun(name: str):
fd = os.open("/dev/net/tun",os.O_RDWR)
if fd < 0:
return fd
r = IfReq()
ctypes.memset(ctypes.byref(r), 0, ctypes.sizeof(r))
r.ifr_ifru.ifru_flags = 0x0002 | 0x1000
r.ifr_ifrn.ifrn_name = name.encode("utf-8")
fcntl.ioctl(fd, TUNSETIFF,r)
return fd
if __name__ == "__main__":
name = input("input device name")
fd = register_tun(name)
if fd < 0:
print("error")
if name == "tun2":
while True:
buf = os.read(fd,1024)
print(f"receive {len(buf)} data")
Ether(raw(buf)).show()
mac1 = "f2:6b:68:c9:60:6b"
mac2 = "46:44:6e:55:9b:c5"
while True:
type = input()
a = Ether(dst=mac2,src=mac1)/ARP(pdst="172.19.16.1",psrc="172.19.16.2")
a.show()
print("write:")
print(os.write(fd, raw(a)))
笔记:
- 虽然设备名称叫tun,但它的类型是tap
- 我同时运行两个测试代码,一个连接 tun1,另一个连接 tun2。因此两个设备都处于 LOWWER_UP 状态
答案1
也许我知道原因了。
Tap/Tun链接网络堆栈和用户程序。用户程序可以接收任何数据由网络堆栈写入 Tap 卡。
假设我们有程序 1 监听 tap1(mac1),程序 2 监听 tap2(mac2)。
如果 program1 将一个以太数据包(src=mac1,dst=mac2)写入 tap1,则网络堆栈将接收该数据包。只有网络堆栈将数据包写入 tap2 时,Program2 才能接收该数据包。
这显然是不可能的!Mac-Frame 没有路由功能。而且,该数据包属于当前主机。
但是,当我们编写广播包时,网络堆栈会将数据包转发到除 tap1 之外的每个网卡。
以上只是我的一点粗浅的理解,不知道是否正确。