Before, I tried to use PacketDrill to test the kernel network protocol stack (network protocol stack testing wizard – PacketDrill). Out of curiosity, I wanted to know how to realize its bottom layer, and followed the steps and finally learned the Linux virtual network device TUN/TAP.

TUN / TAP

TUN/TAP is a virtual network device in the Kernel of the Linux operating system. It provides data packet reception and transmission capabilities for user-space applications and enables simple point-to-point data packet transmission for applications. Different from common physical network transmission, the sender and receiver of data packets are user-space applications.

TUN/TAP is a virtualized network device. It is different from a physical network device in that one end is a kernel network protocol stack and the other end is a user-space application. TUN and TAP differ in that TUN works at Layer 3 and can operate IP packets. TAP works at layer 2 and can manipulate Ethernet frames.

We can simply compare the differences between physical devices and TUN/TAP during data transmission:

Device configuration

Generally, the Linux system creates the default tun device file under the directory /dev/net. If not, we can create one manually using Mknod.

// Create a tun character device file. C indicates the character device. 10 and 200 indicate the primary and secondary device numbers respectivelyCopy the code

Must the primary and secondary equipment numbers be 10 and 200?

Yes, it has to do with the device code definition of the kernel. In the device code defined by the kernel, the primary device id of the TUN/TAP device is 10 and the secondary device ID is 200. For more information, please refer to the documentation accompanying the kernel source code. In admin-guide/devices. TXT, the definitions of all device codes are recorded.

Next, we need to create the Tun virtual network appliance.

// Add the virtual network device tun. The mode is tun. By default, /dev/net/tun is used as the character device fileCopy the code

In this case, you can view the new network device Tun through ifconfig.

Is the name of the tun character device file or virtual network device fixed?

No, character device files and virtual network devices can use other names. I did a simple test, modifying the tun device path and name defined in the PacketDrill source code (ffices.h). After recompilation, the tun device with the new name is still valid. The following code examples also demonstrate that virtual network devices can be replaced by other names.

Interface development

We can create our own character device file through Mknod, and create a virtual network tun device through IP Tuntap, and operate through the normal device read and write interface.

For example, let’s implement the ICMP request response process with the TUN device, and let’s create the device in code instead. Let’s take a look at the whole process.

{:height=”500″ width=”500″}

First, you need to create a new device description file, /dev/net/mmq

// Create tun device description file mknod MMQ c 10 200Copy the code

Create virtual network device MMQ-ETH by code and associate it with device description file /dev/net/mmq.

int create_tun_device(char *dev_name, int flag) {
        struct ifreq ifr;
        int fd, err_code;

        // 创建 tun fd
        if ((fd = open("/dev/net/mmq", O_RDWR)) < 0) {
                printf("Tun device fd create error. (%d)\n", fd);
                return fd;
        }

        // 配置 ifreq,它是一个用于socket ioctl配置的结构
        memset(&ifr, 0, sizeof(ifr));
        strcpy(ifr.ifr_name, dev_name);
        ifr.ifr_flags |= flag;

        // 配置 tun 设备
        if ((err_code = ioctl(fd, TUNSETIFF, &ifr)) < 0) {
                printf("Tun device ioctl configure error. (%d)\n", err_code);
                close(fd);
                return err_code;
        }

        return fd;
}
Copy the code

Through the tun device file descriptor obtained, we can carry out basic read and write and complete the entire ICMP request and reply process.

Void main(int argc, char* argv[]) {// Create tun device int tun_fd = create_tun_device(" mmQ-eth ", IFF_TUN); if (tun_fd < 0) { return -1; } // try to read information from the device int ret_length = 0; unsigned char buf[1024]; while (1) { ret_length = read(tun_fd, buf, sizeof(buf)); if (ret_length < 0) { break; } // Parse the packet unsigned char src_ip[4]; unsigned char dst_ip[4]; memcpy(src_ip, &buf[16], 4); //16 to 19 are source IP addresses memcpy(dST_IP, &buf[20], 4); Memcpy (&buf[16], dST_IP, 4); memcpy(&buf[20], src_ip, 4); buf[24] = 0; Ret_length = write(tun_fd, buf, ret_length); } close(tun_fd); }Copy the code

After the program runs successfully, we can find the corresponding device in the network device list.

ifconfig -a
Copy the code

In this case, you need to send ICMP request packets to the MMQ-ETH. You need to enable the device first and create an IP route record to the device in the IP routing table.

// Enable the network device ifconfig mmq-eth up // Add IP route records route add-host 10.10.10.1 dev mmq-ethCopy the code

You can run the ping command to send packets and view the entire ICMP request response process.

(GitHub address: Taaang/tun_tap_test · GitHub)

conclusion

TUN/TAP is used for user space applications and provides data transmission at different layers of the network protocol stack. TUN provides simple point-to-point data transmission, and TAP transmits data frames at the Ethernet layer. It is mainly used for VPN, protocol encryption and compression, and tunnels.