1

Я пытаюсь создать пользовательский сетевой стек для учебных целей.

То, что я пытаюсь сделать, это настроить устройство на моем компьютере VirtualBox с хостом Windows 10. VirtualBox работает под управлением Ubuntu 16.04 в мостовой сети.

Я настраиваю устройство крана путем создания крана в /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;
}

И затем запускает следующие команды оболочки (из программы):

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 с хоста на свою виртуальную машину, я не вижу пакетов, считываемых туннелем, и фактически, когда проверяю таблицу ARP моего хоста Windows, я вижу, что MAC-адрес интерфейса enp0s3 также был удален из этот стол ARP.

Просто чтобы быть ясным, я вижу другие пакеты, полученные на устройстве крана, но не снаружи моего хоста.

Вот что я вижу, когда проверяю запросы 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. Почему, когда я запускаю мое устройство, я не вижу никаких пакетов, приходящих извне?

  2. Почему я не могу пропинговать мой другой (enp0s3) интерфейс? какое отношение?

1 ответ1

0

У вас есть перекрывающиеся сегменты локальной сети: и enp0s3 и tap0 имеют 192.168.1.0/24. Так что это не может работать.

Вместо этого дайте вашему интерфейсу tap0 непересекающийся диапазон, например, 192.168.2.0/24.

И если вы хотите создать свой собственный сетевой стек, я предлагаю прочитать о сегментах локальной сети, широковещательных доменах, и почему все они должны быть разными на разных сетевых адаптерах.

И если вы хотите научиться работать в сети, я также советую сначала поиграться с сетевым пространством имен и виртуальными парами Ethernet. Таким образом, вы сможете настроить свою собственную "симулированную" сеть и получить опыт работы в сети. Это значительно облегчит написание вашего собственного сетевого стека. Существуют даже графические интерфейсы, которые настраивают такие сети для вас.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .