想玩虚拟网卡一定要玩TUN/TAP(以下简称TAP),想玩TAP一定要知道uIP。uIP是一个用户态实现的一个超级轻量级的麻雀虽小五脏俱全的TCP/IP协议栈,相比lwIP要好用好玩得多,具体怎么个意思,还是请教它的大帅哥作者吧。本文要说的只是它的一个应用,既如何将TUN模式的虚拟网卡适配成TAP模式的虚拟网卡,这个需求确实是需要的。
       到底什么时候需要把TUN模式的虚拟网卡装bi成一个TAP模式的虚拟网卡呢?在你想这么做的时候!我个人认为TAP模式的虚拟网卡特别适合做服务端,它可以任意桥接物理网段和虚拟网段,但是有些平台真的就是不支持TAP模式虚拟网卡,比如说Android系统,我一直都想知道为什么,但是得到就是一句sorry!作为一个开源的平台,我逐渐发现它不是那么的Free,任何平台都没有Linux那样任你随便蹂躏。Android限制API的使用,没有root,那么怎么在有限的API接口范围内达到效果呢?如果说OpenVPN的服务端使用的一直都是TAP模式的虚拟网卡,难道还要专门为Android单独启动一个TUN模式的服务吗?作为一个偏执的人,我绝不这么做!那么我会想方设法把Android的TUN网卡适配到TAP模式。
       TUN和TAP的区别是什么?无非就是少了一个以太网链路层,内核驱动层面不给实现,那么我自己在用户态实现行不?大家都知道,从TUN网卡对应的字符设备读取出来的东西以及写入的东西就是一个IP数据报,那么很简单,我只需要实现以下三点即可:
1.将数据从TUN字符设备读出来后封装一个以太头;
2.将数据写入TUN字符设备前去除其以太头。
3.实现一个ARP逻辑,应付ARP请求以及为了封装目标MAC地址而主动发送ARP请求。

很简单是吧。但是要是真的写起代码来,还真的要费些时间和精力。
       我早就承认我不是一个真正的程序员,然而我是猎手,我希望用现成的东西帮我完成以上这一切,能重用的东西为何不重用呢,做到这一点需要的是积累,如果你不知道有uIP这么一个东西,那么可能你现在真的需要自己写代码了。上周买了一本书,讲述iOS以及Mac OS X内核编程的,原因是我的苹果电脑已经成了垃圾玩具了,心想能像对待Linux内核那样蹂躏Mac OS内核,可是并不是那么回事,知识和能力需要积累,并不是想当然的,虽然操作系统原理都那回事,然而当你动手的时候,就会发现并非如此!
      还好,我自认对TAP虚拟网卡还算比较熟悉,因此我相信自己可以做到这件TUN适配到TAP的事情,由于自己比较懒,所有使用了uIP,如果不用uIP的话,凭着自己对以太帧结构以及ARP协议的理解,也是可以完成代码的,这个代码的关键并不是什么高深的算法或者深刻的理论知识,而是对协议格式的理解以及简单地掌握C语言内存操作的技巧,仅此而已。如果你还对uIP不熟悉,那就就花10分钟时间浏览一下,它是超级简单的,它把TAP网卡当成网线,在用户态实现了一个完整的TCP/IP协议栈。既然uIP在用户态实现了一个完整的协议栈,那么它肯定也实现了ARP逻辑以及以太帧的封装逻辑,而这正是TUN适配到TAP的时候所要用到的。
       那么该怎么办?很简单,修改uIP的代码便是,在给出具体的修改之前,首先说一下除了使用了uIP之外,还使用了simpletun,玩TAP虚拟网卡的如果一头扎进OpenVPN那就错了,应该先玩下simpletun,就一个C文件,直接gcc编译即可。我使用simpletun作为服务端:
simpletun -s -p 12345 -a -i zz0
我之所以使用zz0作为虚拟网卡的名字是因为这样在ifconfig的时候它会在最后,配置它的时候不用再拖动滚动条了。很显然,服务端使用的是TAP模式,那么客户端我准备使用修改后的uIP,由于标准的uIP使用的是TAP,于是我把它修改成TUN模式,只需要将tapdev_init中的IFF_TAP改为IFF_TUN即可。修改了虚拟网卡模式之后,剩下的就是重写读写逻辑了,之所以说是重写而不是修改是因为重写比修改更容易,uIP的好处在于其定义了很多好用的接口而不是它实现的现成逻辑,使用这些接口或者稍加改动的接口来实现一个新的逻辑或许更加容易。

和标准的uIP不同的是,tun2tap版本的uIP并不从虚拟网卡读取以太帧,而是从网络套接字读取以太帧,虚拟网卡只是tun2tap版本uIP的“上层”,这一点是和标准的uIP的unix/main.c逻辑完全相反的。以下就是新版的main逻辑代码:

int main(int argc, char **argv)
{.......// 设置本端的IP地址以及MAC,正常逻辑应该在获取虚拟IP地址以后再设置uip_ipaddr(ipaddr, 1,2,3,5);uip_sethostaddr(ipaddr);uip_ipaddr(ipaddr, 1,2,3,4);uip_setdraddr(ipaddr);uip_ipaddr(ipaddr, 255,255,255,0);uip_setnetmask(ipaddr);... // 设置MAC地址// 初始化和simpletun连接的套接字net_init();while(1) {char raw_tun[UIP_BUFSIZE];memset(uip_buf, 0, sizeof(uip_buf));// 从套接字读取数据,要么为ARP,要么为IPuip_len = net_read();if(uip_len > 0) {// 如果是IP的话,摘掉以太头送往TUN网卡if(BUF->type == htons(UIP_ETHTYPE_IP)) {char *buf2tun = BUF;buf2tun += sizeof(struct uip_eth_hdr);// 送往TUN虚拟网卡tapdev_send(buf2tun, uip_len-sizeof(struct uip_eth_hdr));// 如果是ARP的话,回复ARP请求或者...} else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {// 处理ARPuip_arp_arpin();if(uip_len > 0) {// 回复ARPnet_send();}}} else if(timer_expired(&periodic_timer)) {timer_reset(&periodic_timer);for(i = 0; i < UIP_CONNS; i++) {uip_periodic(i);if(uip_len > 0) {uip_arp_out();net_send();}}if(timer_expired(&arp_timer)) {timer_reset(&arp_timer);uip_arp_timer();}}// 继续处理TAP网卡读出的数据,封装上以太帧头memset(uip_buf, 0, sizeof(uip_buf));uip_len = tapdev_read(raw_tun,UIP_BUFSIZE);if(uip_len > 0) {memcpy(uip_buf+sizeof(struct uip_eth_hdr),raw_tun,uip_len);// 要么请求ARP,要么直接发送数据uip_arp_out();net_send();}}return 0;
}

以上代码基本就完成了TUN到TAP的适配,如此一来,OpenVPN的服务端就可以一直使用TAP模式,即便某些平台的OpenVPN必须使用TUN模式,也可以采用以上的方式实现一个用户态的以太层,在用户态封装/解封装以太帧。这样可以大大降低服务端的复杂性。
       起初,我希望能直接在网上找到TUN适配到TAP的现成代码,于是我搜索“TUN TAP 转化”,“TUN TAP 适配”均无结果,换英文搜还是未果,于是按照老外的常用命名逻辑搜索“tun2tap”,“tap2tun”也依然没找到什么,反而获取了几个reset...因此我写下此文,还是老想法,希望如果有人想做类似事情的时候,能帮上点什么,起码不像我一样一无所获,互联网上应该应有尽有才对。

使用uIP将TUN网卡适配到TAP网卡-tun2tap相关推荐

  1. 绑定多个TAP网卡与绑定多个TUN网卡-附带TUN/TAP适配

    TUN/TAP网卡是个好东西,不仅仅在Linux上,在所有支持它的操作系统上,都不愧为一件利器,虽不像瑞士军刀那么万能,然所涉及之处恢恢乎其于游刃必有余地矣.只是,在Windows上,其强大的功能埋没 ...

  2. CRTD--有关于intel芯片组和BCM4360网卡适配银河麒麟V10系统(适用于macbook)

    在intel芯片组上安装银河麒麟V10系统存在问题: 一开始登录界面瞬间从有亮度到亮度最低,屏幕变黑,当登录进去时,进入设置勉强看到亮度为100%.据分析,是此系统默认调光为系统亮度而不是intel_ ...

  3. 深度无盘服务器网卡,无盘服务器网卡

    无盘服务器网卡 内容精选 换一换 SAP HANA运行在HANA云服务器上.需要根据部署场景,创建一台或多台HANA云服务器,用于部署SAP HANA软件. ISO是一种光盘映像文件,通过特定的压缩方 ...

  4. linux删除旧网卡,如何删除旧网卡驱动

    解决方案 1.在"开始"菜单单击"运行",然后在"运行"对话框中输入"CMD"命令打开命令提示符窗口: 2.输入命令&q ...

  5. linux查看网卡物理编号_关于如何查看多网卡物理机中网卡序号与物理网卡的对应该关系...

    做软件开发的人都知道:接触真正底层系统驱动的的机会很少(做网络驱动的除外哦),上周和同事一起在一块物理机的办卡上安装centerOS6.5(至于为啥安装6.5版本的,只能说厂商要求的),遇到了一个持续 ...

  6. linux网卡顺序问题,linux网卡绑定及网卡顺序变更测试.docx

    Linux网卡顺序变更导致网卡绑定出错及解决办法测试 2012/2/21 描述:linux中新安装网卡会导致原网卡识别顺序紊乱,影响网络及网卡绑定正常工作,此时可以更改/etc/sysconfig/n ...

  7. Hyper-V虚拟机Redhat添加网卡找不到网卡配置文件解决方法

    Hyper-V虚拟机Redhat添加网卡找不到网卡配置文件解决方法 参考文章: (1)Hyper-V虚拟机Redhat添加网卡找不到网卡配置文件解决方法 (2)https://www.cnblogs. ...

  8. Linux下查看网卡信息及确定网卡位置以及更改网卡名称

    转载链接 : Linux下查看网卡信息及确定网卡位置 https://blog.51cto.com/liuqun/1981915 查看Linux网卡访问流量的方法 安装iftop命令(基于epel源) ...

  9. 设置双网卡mic linux,linux双网卡绑定为逻辑网卡

    网卡bond是通过多张网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡,在生产场景中是一种常用的技术. 生产环境服务器为:DELL 网卡为:光纤 bond需要修改涉及的网卡配置文件 /e ...

最新文章

  1. Apache源码包在LINUX(CENTOS6.8)中的安装(出现问题及解决)
  2. java积分签到功能_大河客户端积分商城上线,看新闻就能换取各种超实用奖品,来约...
  3. php新闻列表页模块,PHP开发简单新闻发布系统之新闻列表页整体功能实现
  4. auto cad 打印颜色变浅_CAD制图软件中如何设置CAD打印样式表(CTB)?
  5. 小白打基础一定要吃透的11类 Python 内置函数
  6. STM32工作笔记0017---ISP串口下载
  7. ubuntu sun-jdk
  8. 推荐几个好评率超高的公众号,有远见的程序员都关注了!
  9. ffdshow 源代码分析1 : 整体结构
  10. 停止MySQL正在执行的SQL语句
  11. ahb总线协议主机_AMBA总线协议之一文看懂AMBA2 AHB2与AMBA3 AHBLite总线协议的区别
  12. 梨花带雨音乐播放器3.91源码开源(网站添加背景音乐)
  13. 恒强系统服务器,恒强系统色码解析大全
  14. 百度之星程序设计大赛
  15. C++数据库编程 ODBC简介
  16. java简历校园经历_简历中的校园经历怎么写
  17. 基于php工程项目管理系统——计算机毕业设计
  18. 腾讯、京东、滴滴、字节跳动……15个大厂在数据治理和数据分析上的真实案例
  19. 恶意软件的历史和应对措施
  20. 自动部署项目,全靠它了!

热门文章

  1. 美团Java面试,java运算符重载
  2. android开机自动开启zram,android zram
  3. NI板卡新建仿真接口步骤
  4. 燕麦云何洋开讲丨东博会“走出去”,燕麦云信息安全技术护航
  5. 中国抗疫十大黑科技盘点!
  6. C#处理Word文档
  7. 2022年起重机司机(限桥式起重机)试题及在线模拟考试
  8. Word中繁体艺术字的两种制作方法(转)
  9. MySQL笔记(三)
  10. 搭建一个页面并备份用户上传的文件项目作业