用C#開發(fā)網(wǎng)絡(luò)防火墻技術(shù)區(qū)分
發(fā)表時間:2024-01-05 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]N-Byte網(wǎng)絡(luò)守望者是一款單機版網(wǎng)絡(luò)安全工具,簡言之,就是一個用.NET開發(fā)的個人版防火墻。在N-Byte網(wǎng)絡(luò)守望者1.0版的開發(fā)中,使用了NDIS Hook Driver技術(shù)來實現(xiàn)網(wǎng)絡(luò)封包過濾功能,這使N-Byte網(wǎng)絡(luò)守望者能夠在網(wǎng)絡(luò)層過濾網(wǎng)絡(luò)封包,從而實現(xiàn)強大的功能。 由于軟件的主程序是...
N-Byte網(wǎng)絡(luò)守望者是一款單機版網(wǎng)絡(luò)安全工具,簡言之,就是一個用.NET開發(fā)的個人版防火墻。在N-Byte網(wǎng)絡(luò)守望者1.0版的開發(fā)中,使用了NDIS Hook Driver技術(shù)來實現(xiàn)網(wǎng)絡(luò)封包過濾功能,這使N-Byte網(wǎng)絡(luò)守望者能夠在網(wǎng)絡(luò)層過濾網(wǎng)絡(luò)封包,從而實現(xiàn)強大的功能。
由于軟件的主程序是用C#寫的,C#中沒有提供具有類似DeviceIoControl函數(shù)功能的驅(qū)動設(shè)備控制函數(shù),而NDIS Hook Driver技術(shù)下的驅(qū)動程序是用DDK下的C語言寫的,為了能夠?qū)崿F(xiàn)主程序?qū)︱?qū)動程序的控制和相互通信,采用了以下設(shè)計方案:
在以上方案中,需要一個負責(zé)主程序與NDIS Hook Driver驅(qū)動程序通信與控制的模塊DriverDll.dll,并用C#編寫的一個封裝驅(qū)動程序中封包信息的模塊,可以發(fā)送這個驅(qū)動程序信息到主程序,主程序可識別并操作模塊中的數(shù)據(jù)類型。
在.NET應(yīng)用程序使用驅(qū)動程序的問題上,面臨著兩個問題:
1.怎樣實現(xiàn).NET應(yīng)用程序控制驅(qū)動程序的功能?
2.怎樣從驅(qū)動程序向.NET應(yīng)用程序傳遞非托管的數(shù)據(jù)類型?
以下是我們就這些問題的詳細解決方法:
怎樣實現(xiàn).NET應(yīng)用程序控制驅(qū)動程序的功能?
使用托管C++編寫的DriverDll.dll來實現(xiàn)對驅(qū)動程序的直接控制,而主程序通過調(diào)用其中的方法來實現(xiàn)對驅(qū)動程序的間接控制。比如在NByte.h文件中定義了START_IP_HOOK常數(shù)用來作為傳給驅(qū)動程序用來開啟驅(qū)動程序封包過濾功能的參數(shù),下面在托管C++模塊中定義了IoCtrl托管類并定義了下面的向緩沖區(qū)寫入?yún)?shù)的方法:
//向緩沖區(qū)寫入數(shù)據(jù)。
DWORD WriteIo(DWORD code,PVOID buffer,DWORD count)
{
if(hDriverHandle == NULL)
return ERROR_DRIVER_HANDLE;
DWORD bytesReturned;
BOOL returnCode = DeviceIoControl(hDriverHandle,
code,
buffer,
count,
NULL,
0,
&bytesReturned,
NULL);
if(!returnCode)
return ERROR_IO_CTRL;
return SUCCESS;
}
當(dāng)然直接使用這個方法不太方便,所以定義一個公有函數(shù),用來提供給主程序調(diào)用:
//開始進行封包過濾
bool StartIpHook()
{
return (WriteIo(START_IP_HOOK, NULL, 0)==SUCCESS);
}
這樣,只要在主程序中聲明IoCtrl的對象ic,就可以通過ic.StartIpHook()就可以實現(xiàn)對驅(qū)動程序過濾功能的開啟,用同樣的方法也可以實現(xiàn)對驅(qū)動程序進行其它操作,比如添加、修改封包過濾規(guī)則等。
怎樣從驅(qū)動程序向.NET應(yīng)用程序傳遞非托管的數(shù)據(jù)類型?
為了能夠輸出安全日志,必須讓主程序獲得驅(qū)動程序中的封包信息。使用信號量機制可以很方便的實現(xiàn)驅(qū)動程序和非托管代碼間的信息傳遞,那么對托管代碼呢?這需要向.NET應(yīng)用程序傳遞非托管的數(shù)據(jù)類型ACCESS_INFO。在NByte.h中,是這樣定義這個ACCESS_INFO結(jié)構(gòu)的:
typedef struct _ACCESS_INFO
{
USHORT protocol;
ULONG sourceIp;
ULONG destinationIp;
USHORT sourcePort;
USHORT destinationPort;
}ACCESS_INFO;
顯然,直接傳遞非托管數(shù)據(jù)類型是不可以的,需要轉(zhuǎn)換一下。首先,在IoCtrl類中定義了幾個要傳遞的封包信息參數(shù):
public __gc class IoCtrl
{
public:
USHORT protocol; //網(wǎng)際協(xié)議類型
ULONG sourceIp; //源IP地址
ULONG destinationIp; //目的IP地址
USHORT sourcePort; //源端口
USHORT destinationPort; //目的端口
………………
}
然后,在GetAccessInfo()函數(shù)中來給這些參數(shù)賦值:
void GetAccessInfo()
{
ACCESS_INFO ai;
bool result=(ReadIo(GET_INFO,&ai,sizeof(ai))==SUCCESS);
this->protocol=ai.protocol;
this->sourceIp=ai.sourceIp;
this->destinationIp=ai.destinationIp;
this->sourcePort=ai.sourcePort;
this->destinationPort=ai.destinationPort;
}
既然在IoCtrl類中獲得了這些信息,但是需要把它們封裝成主程序容易處理的數(shù)據(jù)類型,這樣,用C#實現(xiàn)了InfoEvent類用來封裝這些信息:
//本類封裝了數(shù)據(jù)包的詳細信息,可以通過事件實現(xiàn)對它的模塊間傳遞。
public class InfoEvent:EventArgs
{
string sInfo; //用來存放輸出信息的私有成員
public int pLength; //CommonFunction.sPort數(shù)組的長度
public ushort protocol; //網(wǎng)絡(luò)通信協(xié)議類型
public uint sourceIp; //數(shù)據(jù)包的源IP
public uint destinationIp; //數(shù)據(jù)包的目的IP
public ushort sourcePort; //數(shù)據(jù)包的源端口
public ushort destinationPort; //數(shù)據(jù)包的目的端口
………………………………
}
下面在用托管C++實現(xiàn)的InfoProvider驅(qū)動程序信息提供者類中把個InfoEvent類的對象傳遞給主程序,需要使用一個委托生成一個事件:
//聲明委托事件,用來向主程序傳遞數(shù)據(jù)。
__delegate void DriverInfo(Object* sender, InfoEvent* e);
//聲明響應(yīng)事件函數(shù)。
__event DriverInfo* OnDriverInfo;
然后在InfoProvider驅(qū)動程序信息提供者類中定義一個方法,在主程序中以線程的方式運行這個方法,在這個方法中使用了事件函數(shù)OnDriverInfo:
//用來獲得驅(qū)動程序信息的進程,在主程序中將開啟該進程。
void GetInfoThreadProc()
{
this->hEvent=OpenEvent(SYNCHRONIZE,FALSE,"NBEvent");
if(!ic->GetDriverHandle())
{
return;
}
while(true)
{
f(!hEvent)
ExitThread(0);
WaitForSingleObject(this->hEvent,INFINITE);
nPackets++;
ic->GetAccessInfo();
ic->ResetEvent();
//定義一個主程序可以識別的對象,通過OnDriverInfo傳給主程序。
InfoEvent*ie=new InfoEvent(ic->protocol,ic->sourceIp,ic->destinationIp,ic->sourcePort,ic->destinationPort);
OnDriverInfo(this,ie);
}
ic->CloseDriverHandle();
return;
}
在主程序中,會開啟這個進程并定義了OnDriverInfo的處理函數(shù)DealWithInfo:
pInfo=new InfoProvider();
//開啟與驅(qū)動交換信息的進程
FilterThread=new Thread(new ThreadStart(pInfo.GetInfoThreadProc));
FilterThread.IsBackground=true;
FilterThread.Start();
pInfo.OnDriverInfo+=new InfoProvider.DriverInfo(DealWithInfo);
這樣主程序就可以在DealWithInfo函數(shù)中加入對InfoEvent對象的處理了?梢姡ㄟ^中間模塊IoCtrl的轉(zhuǎn)換,便實現(xiàn)了.NET主程序?qū)︱?qū)動程序中非托管數(shù)據(jù)類型的獲取和處理。