理解linux虚拟网络设备tun

tun是linux的另一种虚拟网络设备,与前面讲过的veth类似,只是另一端连的不一样,veth设备是一端连着内核协议栈,另一端连着另一个netns的协议栈;而tun设备是一端连着内核协议栈,另一端连接着一个用户程序,任何时候从协议栈发到tun网卡的数据都能从用户程序中读到,而从用户程序写入/dev/net/tun的数据都会被内核协议栈收到。

当我们通过程序打开/dev/net/tun设备时,就会发现我们的主机上多了一张网卡,打开多次会新增多张网卡,命名依次为tun0/tun1/tun2…,我们读写tun网卡的方式与正常读写一个文件一样,下面通过示例来了解一下。

首先编写一个c程序,文件名为tun.c,代码如下:

#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <linux/if_tun.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{
    int tun_fd, nread, err;
    char buffer[1500];
    struct ifreq ifr;
    if ((tun_fd = open("/dev/net/tun", O_RDWR)) < 0) {
        return tun_fd;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
    if ((err = ioctl(tun_fd, TUNSETIFF, (void *) &ifr)) < 0) {
        close(tun_fd);
        return err;
    }
    printf("open tun device: %s for reading...\n", ifr.ifr_name);
    if (tun_fd < 0) {
        perror("opening tun error");
        exit(1);
    }
    while (1) {
        nread = read(tun_fd, buffer, sizeof(buffer));
        if (nread < 0) {
            perror("reading tun error");
            close(tun_fd);
            exit(1);
        }
        printf("read %d bytes from %s\n", nread,ifr.ifr_name);
    }
    return 0;
}

然后编译并执行:

[root@worker2 ~]# gcc tun.c -o tun
[root@worker2 ~]# ./tun
open tun device: tun0 for reading...

然后从另一个终端打开并查看网卡:

[root@worker2 ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:50:56:bb:16:db brd ff:ff:ff:ff:ff:ff
153: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 500
    link/none

发现已经多了一张tun0的网卡,我们给这个网卡配上地址,然后启动起来

[root@worker2 ~]# ip addr add 192.168.100.100/24 dev tun0
[root@worker2 ~]# ip link set tun0 up
[root@worker2 ~]# ip route
192.168.100.0/24 dev tun0 proto kernel scope link src 192.168.100.100

注意我们给tun0配上地址时,主机上会多一条路由

最后,ping一下192.168.100.101,正常应该没有回应,但观察打开的第一个终端,发现有收到数据包:

[root@worker2 ~]# ./tun
open tun device: tun0 for reading...
read 84 bytes from tun0
read 84 bytes from tun0
read 84 bytes from tun0
read 84 bytes from tun0
read 84 bytes from tun0

可以看到,我们的用户程序已经收到了ICMP包,注意这里PING的不是我们给tun0设置的地址,如果你去ping tun0的地址192.168.100.100,会发现有正常的ICMP包回应,而终端1却什么也没收到,为什么要PING一个不存在的地址才行呢?让我们来捋一捋:

我们在主机上ping tun0的地址,进入协议栈后,在ROUTING判决时,发现这是本机地址,于是从lo网卡发送出去了,所以tun0永远也收不到这个包,要想让tun0收到包,要ping一个和tun0同网段的地址,因为这样才会让协议栈让这个包从tun0发出去,另一端是我们的程序,我们的程序啥也没干,只是打印了一下结果,所以ping的那一端不会有回应。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本实验旨在通过创建虚拟网络设备,在Linux操作系统上进行广域网配置实验。以下是实验报告: 一、实验环境 1. 操作系统:Ubuntu 20.04 LTS 2. 虚拟机软件:VirtualBox 6.1.22 二、实验步骤 1. 创建两个虚拟机,分别命名为Router和Host,并设置虚拟机的网络适配器为“仅NAT网络”模式。 2. 在Router虚拟机上创建两个虚拟网络设备tun0和tun1。其中,tun0设备为本地网络连接,IP地址为192.168.1.1/24;tun1设备为广域网连接,IP地址为10.0.0.1/24。 ``` sudo ip tuntap add mode tun tun0 sudo ip tuntap add mode tun tun1 sudo ip link set dev tun0 up sudo ip link set dev tun1 up sudo ip addr add 192.168.1.1/24 dev tun0 sudo ip addr add 10.0.0.1/24 dev tun1 ``` 3. 在Host虚拟机上创建一个虚拟网络设备tun0,IP地址为192.168.1.2/24。 ``` sudo ip tuntap add mode tun tun0 sudo ip link set dev tun0 up sudo ip addr add 192.168.1.2/24 dev tun0 ``` 4. 在Router虚拟机上启用IP转发功能。 ``` sudo sysctl -w net.ipv4.ip_forward=1 ``` 5. 在Router虚拟机上设置路由,将Host虚拟机的数据包转发到tun1设备。 ``` sudo ip route add 192.168.1.0/24 dev tun0 sudo ip route add default via 10.0.0.2 dev tun1 ``` 6. 在Host虚拟机上设置默认网关为Router虚拟机的tun0设备。 ``` sudo ip route add default via 192.168.1.1 dev tun0 ``` 7. 测试网络连接,Host虚拟机可以ping通Router虚拟机的tun0设备和tun1设备。 三、实验总结 通过本实验,我们成功地创建了虚拟网络设备,在Linux操作系统上进行了广域网配置实验。我们可以通过创建虚拟网络设备,实现不同网络之间的连接,并进行数据传输。虚拟网络设备的创建和配置,是Linux系统网络配置的一个重要部分,也是进行网络编程和网络调试的必备技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值