虚拟网卡

Tun/Tap

较高版本的linux大都自带了tun/tap 驱动程序用以实现虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。利用tun/tap 驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。

Tun/Tap驱动程序工作原理

做为虚拟网卡驱动,Tun/Tap驱动程序的数据接收和发送并不直接和真实网卡打交道,他在Linux内核中添加了一个TUN/TAP虚拟网络设备的驱动程序和一个与之相关连的字符设备 /dev/net/tun,字符设备tun作为用户空间和内核空间交换数据的接口。当内核将数据包发送到虚拟网络设备时,数据包被保存在设备相关的一个队列中,直到用户空间程序通过打开的字符设备tun的描述符读取时,它才会被拷贝到用户空间的缓冲区中,其效果就相当于,数据包直接发送到了用户空间。通过系统调用write发送数据包时其原理与此类似。
在linux下,要实现内核空间和用户空间数据的交互,有多种方式: 
(1)可以通用socket创建特殊套接字,利用套接字实现数据交互; 
(2)通过proc文件系统创建文件来进行数据交互; 
(3)还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就是内核空间和用户空间的一个接口,Tun/tap驱动就是利用设备文件实现用户空间和内核空间的数据交互。 从结构上来说,Tun/tap驱动并不单纯是实现网卡驱动,同时它还实现了字符设备驱动部分。以字符设备的方式连接用户空间和内核空间。

Tun/tap 驱动程序中包含两个部分,一部分是字符设备驱动,还有一部分是网卡驱动部分。利用网卡驱动部分接收来自TCP/IP协议栈的网络分包并发送或者反过来将接收到的网络分包传给协议栈处理, 而字符驱动部分则将网络分包在用户空间和内核空间之间传送,模拟物理链路的数据接收和发送。Tun/tap驱动很好的实现了两种驱动的结合。

创建

创建虚拟网卡分两步,先生成一个这样tun设备:

int tun_open(const char * dev)
{struct ifreq ifr;int fd;assert(dev != NULL);fd = open("/dev/net/tun", O_RDWR);if (fd < 0) {perror("open");return -1;}memset(&ifr, 0, sizeof(struct ifreq));if (*dev)strncpy(ifr.ifr_name, dev, IFNAMSIZ);//ifr.ifr_flags |= IFF_TAP;    /* 以太网设备 */ifr.ifr_flags |= IFF_TUN;        /* 点对点设备 */if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0){close(fd);return -2;}/* 进程退出依旧保留网卡 1 */if(ioctl(fd, TUNSETPERSIST, 1) < 0) {printf("remain tun fail\n");}if (strcmp(ifr.ifr_name, dev) != 0)printf("tun name: %s\n", ifr.ifr_name);return fd;
}

然后还要可以设置需要的参数,如ip/mask、监听模式等:

int tun_setup(const char * dev, struct sockaddr_in * addr)
{struct ifreq ifr;int fd;if (NULL == dev || NULL == addr)return -1;fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd < 0) {perror("socket");goto err;}memset(&ifr, 0, sizeof(struct ifreq));strncpy(ifr.ifr_name, dev, IFNAMSIZ);/* get flag */if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {printf("get flag fail\n");goto err;}/* set the interface up */ifr.ifr_flags |= IFF_UP;if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {printf("set interface up fail\n");goto err;}/* 混杂模式 */ifr.ifr_flags |= IFF_PROMISC;if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {printf("set promisc\n");goto err;}/* set ip */memcpy(&ifr.ifr_addr, addr, sizeof(struct sockaddr));if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {printf("set ip fail\n");goto err;}/* set mask */inet_pton(AF_INET, "255.255.255.255", &addr->sin_addr.s_addr);memcpy(&ifr.ifr_netmask, addr, sizeof(struct sockaddr));if (ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) {printf("set mask fail\n");goto err;}close(fd);return 0;err:close(fd);return -1;
}

关闭的话直接调用close()就好了,毕竟一切皆文件。最后来简单的测试一下。我们从tun网卡read一下,并打印接收到的数据包协议编号:

int main()
{int tun_fd = -1;char buf[4096] = {0};const char * dev = "tun";struct sockaddr_in addr;tun_fd = tun_open(dev);if (tun_fd < 0){printf("create tun fail\n");return -1;}memset(&addr, 0, sizeof(struct sockaddr));addr.sin_family = AF_INET;inet_pton(AF_INET, "13.254.254.131", &addr.sin_addr.s_addr);if (tun_setup(dev, &addr) < 0)return -2;while (1){int ret;struct tun_pi * pi = NULL;ret = read(tun_fd, buf, sizeof(buf)-1);if (ret < 0){perror("read");break;}buf[ret] = 0;pi = (struct tun_pi *)buf;if (pi->flags == TUN_PKT_STRIP){printf("pkt is broken\n"); printf("proto:%d\n", pi->proto);continue;}printf("proto:%02x\n", ntohs(pi->proto));}tun_close(tun_fd);return 0;
}

运行一下,可以用ifconfig查看到刚刚创建的网卡:

还收到了一些包,看样子是icmpv6报文:

centos下创建虚拟网卡相关推荐

  1. Openwrt下WHR G300NV2 创建虚拟网卡失败可能原因

    G300NV2可以刷G301N的Openwrt固件,这个确实无疑.而且经过1天的使用,没发现什么问题. 开始刷的Openwrt的核心是3.2.5,联网装macvlan,结果是ip link add l ...

  2. win10系统怎么创建虚拟网卡?

    由于工作原因,下午需要重新在物理机上创建块虚拟网卡.因为不熟悉这一块,就百度了下,但是到选择"厂商"和"型号"这一步,却找不到"Microsoft&q ...

  3. linux ping 虚拟网卡_Linux下添加虚拟网卡,实现一块物理网卡绑定多个IP地址

    前言: 这个功能在实际生产环境中可能没有意义,但是在虚拟机里做实验的时候还是蛮实用的,可以直接在一个网卡上模拟出多个网段,这样就不用再添加单独的网卡啦. 配置方法: 以当前网卡的配置文件为模板创建虚拟 ...

  4. linux创建虚拟网卡vnet,Qemu之Network Device全虚拟方案二:虚拟网卡的创建

    当命令行传入nic相关参数时,Qemu就会解析网络相关的参数后进入虚拟网卡的创建流 程.而在上文中提到对于所有-net类型的设备,都视作一个net client来对待.而在net client的建立之 ...

  5. linux虚拟网卡tun,Centos7 创建虚拟网卡(tun/tap)

    创建网卡.创建网桥并建立桥接 [root@kolla ~]# cat create.sh create_br(){ tunctl -t storage -u root brctl addbr virb ...

  6. CentOS 7对虚拟网卡virbr0的处理

    在CentOS 7的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡,这个是因为在虚拟化中有使用到libvirtd服务生成的,如果不需要可 ...

  7. CentOS下创建配置RAID1

    最近工作站坏了一块硬盘,意识到数据备份的重要性,重新插入两块新的硬盘,然后做了个磁盘阵列,对数据进行备份,主要过程如下: 1.查看当前磁盘及磁盘分区 再windows下重新格式成NTFS也可以,亲测没 ...

  8. 查看uvp linux网卡状态,Centos下如何检测网卡状态

    由于ifconfig命令没法看到网卡的一些状态, 以下有5种方法查看网卡状态,是否连通网线 How to check physical Network Link Status on Linux (RH ...

  9. windows 创建虚拟网卡 修改MAC地址

    高云FPGA 软件 与 MAC地址绑定了,想要在另一个电脑上运行就得重新申请很麻烦,使用虚拟的网卡 设置同一个MAC地址,就可以通过认证. 1.下载 tap-windows 2.设备管理器->网 ...

最新文章

  1. 程序员如何打破35岁魔咒
  2. ViewPager的简单使用说明
  3. 网页设计千千万,网站建设万万千
  4. 我们究竟还要学习哪些Android知识?满满干货指导
  5. 拆分-洛谷P2745 [USACO5.3]窗体面积Window Area
  6. WINDOWS的SHELLCODE编写高级技巧
  7. 吉哥系列故事――完美队形II(HDU-4513)
  8. 论MVVM伪框架结构和MVC中M的实现机制
  9. linux shell 逻辑运算符、逻辑表达式
  10. MATLAB中如何生成指定范围的随机整数向量
  11. 谈谈Fragment的用法之Fragment实现Tab切换中的那些事
  12. 代理服务器的常用端口有哪些?
  13. 使用console配置线连接真机路由器
  14. laravel集合collect中的implode
  15. MCU 8080规格LCD屏斜线问题——Tear功能
  16. 计算机卡住了怎样恢复,电脑死机按什么键恢复
  17. 小提琴统计图_箱形图和小提琴图
  18. Docker系列:docker 容器命令: 删除 停止 启动 重启
  19. Sublime text代码补全插件(支持Javascript、JQuery、Bootstrap框架)
  20. React教程(五)——生命周期函数

热门文章

  1. NumPy入门讲座(3):操作数组
  2. 读取太阳紫外辐照谱数据
  3. 邵阳学院大学计算机基础实验报告答案,实验报告正文(大学计算机基础)
  4. 【连载】第三章刚体的定轴转动第三节——定轴转动刚体的角动量守恒定律
  5. 工业视觉需要时可抄的代码---持续更新
  6. DevOps实践|快速提升团队软件开发成熟度,提升研发效能
  7. 完整性+存储过程和函数——CHECK / CONSTRAINT / TRIGGER / PROCEDURE/ FUNCTION
  8. 用Python实现地理信息出图(含比例尺、指北针、图例)
  9. 云计算、大数据和人工智能之间的关系----详细说明
  10. matlab仿真实验报告,Matlab SIMULINK仿真实验报告.doc