作者:椰子 | 来源:互联网 | 2023-05-19 01:37
工作中用到了使用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))
测试:
#ifconfig tun3 10.0.0.1 up
#route add -net 10.0.0.2 netmask 255.255.255.255 dev tun3
#ping 10.0.0.2
read size:88
read size:88
read size:88
read size:88
read size:88
read size:88
read size:88
read size:88