两个 Tap 设备无法通过 Bridge 进行通信

两个 Tap 设备无法通过 Bridge 进行通信

我想在两个TAP设备之间交换以太网数据包(用于在用户模式下实现TCP / IP协议栈)。

我遇到的问题是tap1和tap2只能通过网桥接收广播数据包,而不能接收点对点数据包!

例如,当我从 tap1 向 tap2 发送数据包时,tcmpdump 可以在 tap1 上捕获数据包,但 tap2 无法接收数据包。但是,当我将目标地址设置为“ff:ff:ff:ff:ff:ff”或任何未知的 mac 地址(这将触发广播)时,tap2 将接收数据包。

我的配置:

  1. 创建两个水龙头设备
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
  1. 建立桥梁
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)))

笔记:

  1. 虽然设备名称叫tun,但它的类型是tap
  2. 我同时运行两个测试代码,一个连接 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 之外的每个网卡。

以上只是我的一点粗浅的理解,不知道是否正确。

相关内容