TAPDriver是一种基于OpenVPN虚拟网卡的驱动程序。通过虚拟网卡,TAPDriver可以截获各种通讯协议,并对感兴趣的协议进行调整或者
篡改。在这里主要是针对Windows 2000无法调整VPN的通讯端口所特制的通讯程序。使用TAPDriver,可以让Windows
2000对本地TAPDriver进行VPN通讯,再由TAPDriver与外部实际VPN服务器进行通讯。
TAPDriver主要是通过虚拟网卡设备,给基于L2TP的VPN通道提供便利。
一、
主要文件
TAPDriver的主要文件有:Global.h、TAPDriver.h和TAPDriver.lib。
1.1
Global.h
全局定义文件,主要是对一些常量进行了重新规范化定义。
例如:
//INT8
typedef char _INT8;
//Unsigned INT8
typedef unsigned
char _UINT8;
//INT16
typedef short _INT16;
//Unsigned INT16
typedef unsigned
short _UINT16;
//INT32
typedef int _INT32;
//Unsigned INT32
typedef unsigned
int _UINT32;
1.2 TAPDriver.h
TAPDriver驱动的主要函数定义文件。
1.2.1 InitializeTAPDriver
初始化TAPDriver的运行环境。包括启动日志、启动Socket功能、查找注册表等等。在使用TAP设备前,必须运行该函数。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
_BOOL
|
如果初始化成功,则返回_TRUE;否则返回_FALSE。
|
注意:无论该函数是否返回成功或者失败,都必须调用UninitializeTAPDriver。
1.2.2 UninitializeTAPDriver
释放TAPDriver的运行环境。包括释放注册表内容、释放Socket功能、关闭文件日志等等。在程序退出之前必须调用此函数,否则可能导致内存泄漏。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
void
|
|
1.2.3 SetVirtualAddress
设置TAPDriver的虚拟IP地址。
|
参数名
|
类型
|
备注
|
|
lpstrLocalIPAddress
|
_STRING
|
本地IP地址。
例如:10.7.0.6。
|
|
lpstrLocalNetmask
|
_STRING
|
本地IP地址的掩码。
例如:255.0.0.0。
|
|
lpstrRemoteIPAddress
|
_STRING
|
远程IP地址。
例如:10.7.0.5。
|
|
返回值类型
|
备注
|
|
void
|
|
在初始化TAPDriver运行环境后,且在开启TAPDriver之前,可以调用此函数来设置虚拟本地和远程地址。此地址必须配对使用,具体的要求可以参考openvpn。常用配置见上表。
1.2.4 SetL2TPServer
设置L2TP服务器的远程地址和端口。
|
参数名
|
类型
|
备注
|
|
lpstrIPAddress
|
_STRING
|
远程IP地址。
例如:60.28.160.110。
|
|
nPort
|
_UINT16
|
远程端口。
例如:1701。
|
|
返回值类型
|
备注
|
|
void
|
|
在初始化TAPDriver运行环境后,且在开启TAPDriver之前,可以调用此函数来设置L2TP服务器的IP地址和端口。
1.2.5 TAPDriverExists
检查TAPDriver是否注册。
|
参数名
|
类型
|
备注
|
|
lpstrAdapterName
|
_STRING
|
设备名。
例如:“tap0801”。
|
|
|
|
|
|
返回值类型
|
备注
|
|
_BOOL
|
如果在注册表中可以找到相关设备,则返回_TRUE;否则返回_FALSE。
|
在初始化TAPDriver运行环境后,且在开启TAPDriver之前,可以用此函数检测TAPDriver是否注册。如果已经注册,可以选择开启TAPDriver;如果没有注册,可以选择提示安装或者放弃开启TAPDriver。
1.2.6 OpenTAPDriver
开启TAPDriver。开启TAPDriver将包括建立Socket通道、打开设备、建立读写机制等等。
|
参数名
|
类型
|
备注
|
|
lpstrAdapterName
|
_STRING
|
设备名。
例如:“tap0801”。
|
|
|
|
|
|
返回值类型
|
备注
|
|
_BOOL
|
如果开启设备成功,则返回_TRUE;否则返回开启设备失败。
|
注意:无论开启设备是否成功或者失败,都需要调用CloseTAPDriver。否则可能会导致内存泄漏,某些设备或者通讯未关闭的情况。
1.2.7 CloseTAPDriver
关闭TAPDriver。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
void
|
|
1.2.8 IsTAPDriverRunning
检查TAPDriver是否正常运行。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
_BOOL
|
如果正常运行则返回_TRUE;否则返回_FALSE。
|
在开启TAPDriver以后,通过此函数可以检测读写线程的工作情况。如果任何一个线程出现异常,将会导致此函数返回_FALSE。此时可以选择关闭设备,再重新打开。
1.2.9 GetTAPDriverInputSize
输入数据计数器。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
_UINT32
|
返回自TAPDriver开启以后,TAPDriver接收到的来自机器的L2TP请求的字节数。
|
在开启TAPDriver以后,可以通过此函数检测从本机发往远程主机的数据情况。
1.2.10 GetTAPDriverOutputSize
输出数据计数器。
|
参数名
|
类型
|
备注
|
|
(无)
|
|
|
|
|
|
|
|
返回值类型
|
备注
|
|
_UINT32
|
返回自TAPDriver开启以后,TAPDriver写入到本机的L2TP请求的字节数。
|
在开启TAPDriver以后,可以通过此函数检测从远程主机发往本机的数据情况。
1.2.11 SetTAPDriverLog
日志开关
|
参数名
|
类型
|
备注
|
|
bLog
|
_BOOL
|
如果需要打开日志,则设置bLog为_TRUE;如果需要关闭,则设置bLog为_FALSE。
|
|
|
|
|
|
返回值类型
|
备注
|
|
void
|
|
1.3基本例程
////////////////////////////////////////////////////////////////////////////////
//
// General including
files.
//
// Including the files
for the system.
//
// These including
files are generally used in different operation system.
//
////////////////////////////////////////////////////////////////////////////////
//包括类型定义文件
#include "Global.h"
//包括驱动基本函数文件
#include "TAPDriver.h"
//For windows.
#ifdef _MICROSOFT_WINDOWS
#include <windows.h>
#endif
//Import Library
//引入库文件。
#pragma comment(lib,"TAPDriver.lib")
//TAP Driver Name
//缺省的TAPDriver的名字。
#define TAP_DRIVER_NAME "tap0801"
////////////////////////////////////////////////////////////////////////////////
//
// Main function.
//
////////////////////////////////////////////////////////////////////////////////
_INT32 main(_INT32
argc,_STRING argv[])
{
//Initialize TAP driver.
//初始化TAPDriver的运行环境。
//在启动TAPDriver之前必须调用此函数。
if(InitializeTAPDriver())
{
//Check existance.
//检查TAPDriver是否注册。
//如果没有发现注册,则放弃启动。
if(TAPDriverExists(TAP_DRIVER_NAME))
{
//Set address.
//设置虚拟地址,包括本地虚拟地址、网络掩码和远程虚拟地址。
SetVirtualAddress("10.7.0.6","255.0.0.0","10.7.0.5");
//Set L2TP server.
//设置L2TP服务器的参数,包括远程地址和端口。
SetL2TPServer("60.28.160.110",1701);
//Open TAP
driver.
//打开TAPDriver设备。
if(OpenTAPDriver(TAP_DRIVER_NAME))
{
//Do process.
do
{
//Check keyboard.
if(kbhit())
{
//Get
a char.
_CHAR
c = getchar();
//Get
a char.
if(c
== 'Q')
{
break;
}
else
if(c == 'A')
{
//打开TAPDriver日志
SetTAPDriverLog(_TRUE);
}
else
if(c == 'X')
{
//关闭TAPDriver日志
SetTAPDriverLog(_FALSE);
}
else
{
//Print information.
printf("Main::main
: press \"Q\" for exit !");
}
}
//Print.
printf("Output
= %dByte(s),Input = %dByte(s)\r",
GetTAPDriverOutputSize(),GetTAPDriverInputSize());
//Sleep
//通过休眠来释放CPU的占有率。
Sleep(1);
//检查设备是否在运行
}while(IsTAPDriverRunning());
}
else
{
#ifdef _DEBUG
printf("Main::main
: fail to open TAP driver !");
#endif
}
//Close TAP driver.
//关闭TAPDriver设备。
//无论开启是否成功,该函数都必须被调用。
CloseTAPDriver();
}
else
{
#ifdef _DEBUG
printf("Main::main
: TAP driver not exists !");
#endif
}
}
else
{
#ifdef _DEBUG
printf("Main::main
: fail to initialize TAP driver !");
#endif
}
//Uninitialize TAP driver.
//释放TAPDriver运行环境。
//无论初始化是否成功,该函数都必须被调用。
UninitializeTAPDriver();
#ifdef _DEBUG
printf("Main::main
: successfully done !");
#endif
//Return success.
return
_SUCCESS;
}
1.4常见问题
1.4.1 TAPDriver的安装
在TAPDriver安装以后,必须重新启动机器,才可以启动该驱动程序。否则会导致打开设备失败。具体返回错误为31。原因是:系统没有找到新安装设备的ARP设备表入口。
1.4.2 TAPDriver的名字
TAPDriver安装后的常见注册名为“tap0801”。一般使用这个名字开启设备。如果原始驱动有变化,则该名字也会产生变化。
1.4.3 L2TP拨号
有时候TAPDriver开启以后,L2TP第一拨号可能会失败。可以再超时以后,重新再拨号一次即可正常使用。
1.4.4 默认网关的问题
在TAPDriver开启以及L2TP拨号成功以后,如果使用“远程默认网关地址”将可能导致大量发包,使得CPU占用至100%。取消此项目以后,则恢复到正常状态。
1.4.5 TAPDriver的日志
系统会自动在当前工作目录下建立一个log目录,所有相关日志会记录在此文件夹当中。如果日志开放,则可能会影响通讯速度。请根据实际情况选择使用。