Tap 设备阻止我的 VirtualBox 主机上的所有通信

Tap 设备阻止我的 VirtualBox 主机上的所有通信

我正在尝试创建一个用户空间网络堆栈以用于学习目的。

我想要做的是在装有 Windows 10 主机的 VirtualBox 机器上设置一个 Tap 设备。VirtualBox 在桥接网络上运行 Ubuntu 16.04。

我设置 Tap 设备的方式是通过在中创建一个 Tap /dev/net

sudo mknod /dev/net/tap c 10 200

我的程序正在运行tun_alloc

/*
 * Taken from Kernel Documentation/networking/tuntap.txt
 */

int tun_alloc(char *dev)
{
    struct ifreq ifr;
    int fd, err;

    /* Arguments taken by the function:
     *
     * char *dev: the name of an interface (or '\0'). MUST have enough
     *   space to hold the interface name if '\0' is passed
     * int flags: interface flags (eg, IFF_TUN etc.)
     */

    /* open the clone device */
    if ((fd = open("/dev/net/tap", O_RDWR)) < 0)
    {
        printf("Cannot open TUN/TAP dev\n");
        exit(1);
    }
    /* preparation of the struct ifr, of type "struct ifreq" */
    memset(&ifr, 0, sizeof(struct ifreq));

    /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
     *        IFF_TAP   - TAP device
     *
     *        IFF_NO_PI - Do not provide packet information
     */
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    if (*dev)
    {
        /* if a device name was specified, put it in the structure; otherwise,
         * the kernel will try to allocate the "next" device of the
         * specified type */
        strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    }

    /* try to create the device */
    if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0)
    {
        printf("ERR: Could not ioctl tun: %s\n", strerror(errno));
        close(fd);
        return err;
    }

    /* if the operation was successful, write back the name of the
     * interface to the variable "dev", so the caller can know
     * it. Note that the caller MUST reserve space in *dev (see calling
     * code below) */
    strcpy(dev, ifr.ifr_name);

    /* this is the special file descriptor that the caller will use to talk
     * with the virtual interface */
    return fd;
}

然后运行以下 shell 命令(来自程序):

ip link set dev tap0 up
ip route add dev tap0 192.168.1.0/24
ip address add dev tap0 local 192.168.1.21

当我运行这个时,我的ifconfig节目:

enp0s3    Link encap:Ethernet  HWaddr 08:00:27:2f:ba:f8  
          inet addr:192.168.1.36  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::445b:f137:4390:8b40/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:149 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1239 (1.2 KB)  TX bytes:24836 (24.8 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:68 errors:0 dropped:0 overruns:0 frame:0
          TX packets:68 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:5351 (5.3 KB)  TX bytes:5351 (5.3 KB)

tap0      Link encap:Ethernet  HWaddr e2:c8:48:94:af:9c  
          inet addr:192.168.1.21  Bcast:0.0.0.0  Mask:255.255.255.255
          inet6 addr: fe80::e0c8:48ff:fe94:af9c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:51 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:42 (42.0 B)  TX bytes:6078 (6.0 KB)

当我不运行该程序并且没有 tap0 接口时,我可以 ping 到我的主机,它也可以 ping 我。

但是当我运行此程序并且我的 Tap 设备已启动时,我突然与主机失去通信。此外,当我从主机 ping 到我的虚拟机时,我没有看到隧道读取任何数据包,事实上,当我检查我的 Windows 主机的 ARP 表时,我还看到enp0s3接口 MAC 地址已从此 ARP 表中删除。

需要明确的是,我确实看到了在 Tap 设备上接收到的其他数据包,但不是来自我的主机外部。

这是我在主机内部测试 ARP 请求时看到的内容:

arping -I tap0 192.168.1.21
ARPING 192.168.1.21 from 192.168.1.21 tap0
Unicast reply from 192.168.1.21 [00:0C:29:6D:50:25]  0.545ms
Unicast reply from 192.168.1.21 [00:0C:29:6D:50:25]  0.733ms

现在我的问题是:

  1. 为什么在运行我的 Tap 设备时,我看不到任何来自外部的数据包?

  2. 为什么我也无法 ping 通我的其他 (enp0s3) 接口?这其中有什么关系?

答案1

您的 LAN 段有重叠:enp0s3tap0都有 192.168.1.0/24。因此这行不通。

为您的tap0接口提供一个不重叠的范围,例如 192.168.2.0/24。

如果你想创建自己的网络堆栈,我建议你阅读有关 LAN 段、广播域和为什么它们在不同的网络适配器上都必须不同。

如果您想学习网络,我还建议您先尝试使用网络命名空间和虚拟以太网对。这样,您将能够设置自己的“模拟”网络,并获得网络方面的实践经验。这将使编写自己的网络堆栈变得容易得多。甚至还有 GUI 可以为您设置此类网络。

相关内容