热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python实现tun/tap虚拟设备

工作中用到了使用taptun设备实现虚拟网络,看到网上的例子都是用C实现的。便想试着用python实现一把,主要就是要重新用ctypes定义相关的结构定义。代码github地址:https:gi

工作中用到了使用tap/tun设备实现虚拟网络,看到网上的例子都是用C实现的。便想试着用python实现一把,主要就是要重新用ctypes定义相关的结构定义。

代码github地址:

https://github.com/happyAnger6/network_programming


这个git库里会不断的用python实现网络相关的编程。


if_tun.py:  主要是相关结构体定义。

import ctypes
import ioctl_def

TUNSETIFF=ioctl_def._IOW(ord('T'), 202, ctypes.c_int)
IFF_TUN=1
IFF_TAP=2

IFNAMSIZ=16

class SockAddr(ctypes.Structure):
_fields_=[("sa_family",ctypes.c_ushort),
("sa_data",ctypes.c_char*14)]

class IfMap(ctypes.Structure):
_fields_=[("mem_start", ctypes.c_ulong),
("mem_end", ctypes.c_ulong),
("base_addr", ctypes.c_ushort),
("irq", ctypes.c_char),
("dma", ctypes.c_char),
("port", ctypes.c_char)]

class Ifs_Ifsu(ctypes.Union):
_fields_=[("raw_hdlc", ctypes.c_void_p),
("cisco", ctypes.c_void_p),
("fr", ctypes.c_void_p),
("fr_pvc", ctypes.c_void_p),
("fr_pvc_info", ctypes.c_void_p),
("sync", ctypes.c_void_p),
("te1", ctypes.c_void_p)]

class IfSettings(ctypes.Structure):
_fields_=[("type", ctypes.c_uint),
("size", ctypes.c_uint),
("ifs_ifsu", Ifs_Ifsu)]

class Ifr_Ifru(ctypes.Union):
_fields_=[("ifru_addr", SockAddr),
("ifru_dstaddr", SockAddr),
("ifru_broadaddr", SockAddr),
("ifru_netmask", SockAddr),
("ifru_hwaddr", SockAddr),
("ifru_flags", ctypes.c_ushort),
("ifru_ivalue", ctypes.c_int),
("ifru_mtu", ctypes.c_int),
("ifru_map", IfMap),
("ifru_slave", ctypes.c_char * IFNAMSIZ),
("ifru_newname", ctypes.c_char * IFNAMSIZ),
("ifru_data", ctypes.c_void_p),
("ifru_settings", IfSettings)]

class Ifr_Ifrn(ctypes.Union):
_fields_=[("ifrn_name", ctypes.c_char * IFNAMSIZ)]

class IfReq(ctypes.Structure):
_fields_=[("ifr_ifrn", Ifr_Ifrn),
("ifr_ifru", Ifr_Ifru)]


if __name__ == "__main__":
ifreq = IfReq()
print(ctypes.sizeof(ifreq.ifr_ifrn))
print(ctypes.sizeof(ifreq.ifr_ifru))

ioctl_def.py:主要是ioctl命令字相关定义:

_IOC_NRBITS=8
_IOC_TYPEBITS=8
_IOC_SIZEBITS=14
_IOC_DIRBITS=2

_IOC_NRMASK=((1 <<_IOC_NRBITS) - 1)
_IOC_TYPEMASK=((1 <<_IOC_TYPEBITS) - 1)
_IOC_SIZEMASK=((1 <<_IOC_SIZEBITS) - 1)
_IOC_DIRMASK=((1 <<_IOC_DIRBITS) - 1)

_IOC_NRSHIFT=0
_IOC_TYPESHIFT=(_IOC_NRSHIFT + _IOC_NRBITS)
_IOC_SIZESHIFT=(_IOC_TYPESHIFT + _IOC_TYPEBITS)
_IOC_DIRSHIFT=(_IOC_SIZESHIFT + _IOC_SIZEBITS)

_IOC_NOnE=0
_IOC_WRITE=1
_IOC_READ=2

def _IOC(dir, type, nr, size):
return (((dir) <<_IOC_DIRSHIFT) | \
((type) <<_IOC_TYPESHIFT) | \
((nr) <<_IOC_NRSHIFT) | \
((size) <<_IOC_SIZESHIFT))

import ctypes
def _IOC_TYPECHECK(t):
return ctypes.sizeof(t)

def _IO(type, nr):
return _IOC(_IOC_NONE, type, nr, 0)

def _IOR(type, nr, size):
return _IOC(_IOC_READ, type, nr, _IOC_TYPECHECK(size))

def _IOW(type, nr, size):
return _IOC(_IOC_WRITE, type, nr, _IOC_TYPECHECK(size))

if __name__ == "__main__":
print(_IOC_TYPESHIFT,_IOC_SIZESHIFT,_IOC_DIRSHIFT)
print(_IOC())

tun_oper.py:创建tun设备并监听数据发送请求.

import fcntl
import os

import ctypes
import struct

from if_tun import IfReq, TUNSETIFF, IFF_TUN

def tun_create(devname, flags):
fd = -1
if not devname:
return -1
fd = os.open("/dev/net/tun", os.O_RDWR)
if fd <0:
print("open /dev/net/tun err!")
return fd
r=IfReq()
ctypes.memset(ctypes.byref(r), 0, ctypes.sizeof(r))
r.ifr_ifru.ifru_flags |= flags
r.ifr_ifrn.ifrn_name = devname.encode('utf-8')
try:
err = fcntl.ioctl(fd, TUNSETIFF, r)
except Exception as e:
print("err:",e)
os.close(fd)
return -1
return fd

if __name__ == "__main__":
fd = tun_create("tun3", IFF_TUN)
if fd <0:
raise OSError

MAXSIZE=4096
while(True):
buf = os.read(fd,MAXSIZE)
if not buf:
break
print("read size:%d" % len(buf))

测试:

  • 为tun3设备设置ip:

#ifconfig tun3 10.0.0.1 up

  • 添加静态路由,通过tun3转发:

#route add -net 10.0.0.2 netmask 255.255.255.255 dev tun3

  • ping一个地址向tun3发送数据:

#ping 10.0.0.2

  • tun3收到了数据:

read size:88
read size:88
read size:88
read size:88
read size:88
read size:88
read size:88
read size:88



推荐阅读
  • MSP430F5438 ADC12模块应用与学习心得
    在最近的实践中,我深入研究了MSP430F5438的ADC12模块。尽管该模块的功能相对简单,但通过实际操作,我对MSP430F5438A和MSP430F5438之间的差异有了更深刻的理解。本文将分享这些学习心得,并探讨如何更好地利用ADC12模块进行数据采集和处理。 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 最详尽的4K技术科普
    什么是4K?4K是一个分辨率的范畴,即40962160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 本文介绍了如何使用Python的Paramiko库批量更新多台服务器的登录密码。通过示例代码展示了具体实现方法,确保了操作的高效性和安全性。Paramiko库提供了强大的SSH2协议支持,使得远程服务器管理变得更加便捷。此外,文章还详细说明了代码的各个部分,帮助读者更好地理解和应用这一技术。 ... [详细]
  • Codeforces竞赛解析:Educational Round 84(Div. 2评级),题目A:奇数和问题
    Codeforces竞赛解析:Educational Round 84(Div. 2评级),题目A:奇数和问题 ... [详细]
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 在Linux系统中避免安装MySQL的简易指南
    在Linux系统中避免安装MySQL的简易指南 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文详细探讨了二元Probit模型及其在实际应用中的重要性。作为一种广义线性模型,Probit模型主要用于处理二分类问题,与Logistic模型类似,但其假设误差项服从标准正态分布。尽管Probit模型在某些领域应用较少,但在特定情境下仍具有独特优势。文章不仅介绍了模型的基本原理,还通过实例分析展示了其在经济学、社会学等领域的具体应用。 ... [详细]
  • 在C#编程中,数值结果的格式化展示是提高代码可读性和用户体验的重要手段。本文探讨了多种格式化方法和技巧,如使用格式说明符、自定义格式字符串等,以实现对数值结果的精确控制。通过实例演示,展示了如何灵活运用这些技术来满足不同的展示需求。 ... [详细]
  • 开发笔记:实现1353表达式中的括号匹配(栈的应用) ... [详细]
  • 在《Linux高性能服务器编程》一书中,第3.2节深入探讨了TCP报头的结构与功能。TCP报头是每个TCP数据段中不可或缺的部分,它不仅包含了源端口和目的端口的信息,还负责管理TCP连接的状态和控制。本节内容详尽地解析了TCP报头的各项字段及其作用,为读者提供了深入理解TCP协议的基础。 ... [详细]
author-avatar
椰子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有