Я пытаюсь создать пользовательский сетевой стек для учебных целей.
То, что я пытаюсь сделать, это настроить устройство на моем компьютере 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
Теперь мои вопросы таковы:
Почему, когда я запускаю мое устройство, я не вижу никаких пакетов, приходящих извне?
Почему я не могу пропинговать мой другой (enp0s3) интерфейс? какое отношение?