网络安全大型作业
(Windows防火墙设计)
实验报告
班级:08计算机网络
姓名:
学号:V2008410
日期:20##-3-3
一、实验目的和要求
1、学习Windows下防火墙设计技术
2、实现一个简单的Windows下的防火墙软件
3、分析simpleFW软件不足之处
4、根据要求理解两个SPI程序,并自己进行扩展,增加新的功能
二、实验原理
1.Windows的Hook技术:Hook分为Hook消息和Hook函数调用
Hook函数调用是指截获特定进程或者系统对某个API函数的调用,使得API的执行流程转向特定的代码,后者称为注入代码,注入代码一般保存在注入DLL中。
2.Windows报文截获技术:原始套结字(Raw Socket)和替换系统自带的WINSOCK动态连接库
3.Windows SPI原理:Winsock2.0引入的一个功能就是允许开发者可以编写自己的服务提供者接口程序,即SPI程序。SPI以DLL方式存在,工作在应用层,为上层程序提供结构函数。
4.SimpleFW基本技术:Windows程序设计中几乎所有的动作都是利用消息来触发。但是消息是和窗口绑定在一起的,一般拥有窗口才能接收消息。在特殊情况下,线程也可以接收消息在SimpleFW中,当一个程序访问Winsock会弹出对话框,让用户选择是否允许访问。这个过程通过IP_Moniter.dll发送给UI一个用户自定义消息来实现。
三、实验环境和采用的工具
1、操作系统为Windows XP
2、编程工具为VC++ 6.0
四、简要分析实验原型软件(SimpleFW)的不足
1.原型软件不能记录访问规则,每次打开防火墙都需要用户重新设定,这样带来了很大的不便
2.原型软件不能灵活的对访问规则进行修改删除,这样一旦制定下来的规则都不能发生变化
3.原型软件没有自定义规则的功能,这样对于每一个应用程序第一次访问网络都需要进行询问,这样对用户使用来说比较不方便
4.原型软件没有基本的日志功能
5.原型软件不能对应用程序进行监控甚至是进行关键字匹配告警,只能进行简单的访问控制
6.原型软件只是简单的串行化,不能同时有多个应用程序访问
7.原型软件外观比较简陋,需要进一步修饰
8、原型软件没有流量监控功能,用户不知流量使用情况
9、原型软件缺少清理无用规则的功能
10、原型软件缺少修补系统漏洞的功能
五、在实验原型软件上新增的功能
5.1功能1
流量监控
5.1.1功能1描述
该功能可以实时监控用户当前使用的流量以及到目前为止用户设置时间内所使用的总流量
5.1.2功能1实现流程
#include "stdafx.h"
#include "MFNetTraffic.h"
#include "float.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "winperf.h"
// Construction/Destruction
MFNetTraffic::MFNetTraffic()
{
lasttraffic = 0.0;
CurrentInterface = -1;
CurrentTrafficType = AllTraffic;
GetInterfaces();
}
MFNetTraffic::~MFNetTraffic()
{
}
PERF_OBJECT_TYPE *FirstObject(PERF_DATA_BLOCK *dataBlock)
{
return (PERF_OBJECT_TYPE *) ((BYTE *)dataBlock + dataBlock->HeaderLength);
}
PERF_OBJECT_TYPE *NextObject(PERF_OBJECT_TYPE *act)
{
return (PERF_OBJECT_TYPE *) ((BYTE *)act + act->TotalByteLength);
}
PERF_COUNTER_DEFINITION *FirstCounter(PERF_OBJECT_TYPE *perfObject)
{
return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfObject + perfObject->HeaderLength);
}
PERF_COUNTER_DEFINITION *NextCounter(PERF_COUNTER_DEFINITION *perfCounter)
{
return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfCounter + perfCounter->ByteLength);
}
PERF_COUNTER_BLOCK *GetCounterBlock(PERF_INSTANCE_DEFINITION *pInstance)
{
return (PERF_COUNTER_BLOCK *) ((BYTE *)pInstance + pInstance->ByteLength);
}
PERF_INSTANCE_DEFINITION *FirstInstance (PERF_OBJECT_TYPE *pObject)
{
return (PERF_INSTANCE_DEFINITION *) ((BYTE *) pObject + pObject->DefinitionLength);
}
PERF_INSTANCE_DEFINITION *NextInstance (PERF_INSTANCE_DEFINITION *pInstance)
{
PERF_COUNTER_BLOCK *pCtrBlk = GetCounterBlock(pInstance);
return (PERF_INSTANCE_DEFINITION *) ((BYTE *)pInstance + pInstance->ByteLength + pCtrBlk->ByteLength);
}
char *WideToMulti(wchar_t *source, char *dest, int size)
{
WideCharToMultiByte(CP_ACP, 0, source, -1, dest, size, 0, 0);
return dest;
}
/*
Window NT/2000: When calling the RegQueryValueEx function with hKey set to the
HKEY_PERFORMANCE_DATA handle and a value string of a specified object, the
returned data structure sometimes has unrequested objects. Don't be surprised;
this is normal behavior. When calling the RegQueryValueEx function, you should
always expect to walk the returned data structure to look for the requested object.
*/
//得到接口号为interfaceNumber的接口流量
double MFNetTraffic::GetTraffic(int interfaceNumber)
{
try
{
#define DEFAULT_BUFFER_SIZE 40960L
POSITION pos;
CString InterfaceName;
pos = Interfaces.FindIndex(interfaceNumber);
if(pos==NULL)
return 0.0;
//得到当前的接口名字
InterfaceName = Interfaces.GetAt(pos);
//为性能数据缓冲
unsigned char *data = new unsigned char [DEFAULT_BUFFER_SIZE];
// 从RegQueryValueEx返回的值:本例中忽略改变量
DWORD type;
// 缓冲的尺寸
DWORD size = DEFAULT_BUFFER_SIZE;
// RegQueryValueEx返回的值
DWORD ret;
// 从网络对象(索引是510)查询性能数据
/*
HKEY_PERFORMANCE_DATA:
Windows NT/2000/XP: Registry entries subordinate to this key allow you to
access performance data. The data is not actually stored in the registry;
the registry functions cause the system to collect the data from its source.
*/
/*
*/
while((ret = RegQueryValueEx(
HKEY_PERFORMANCE_DATA, "510", NULL, &type, data, &size)) != ERROR_SUCCESS)
{
if(ret == ERROR_MORE_DATA)
{
// 缓冲尺寸太小,增加内存分配
size += DEFAULT_BUFFER_SIZE;
delete [] data;
data = new unsigned char [size];
}
else
{
// 未定义的错误
return 1;
}
}
//性能数据块
PERF_DATA_BLOCK *dataBlockPtr = (PERF_DATA_BLOCK *)data;
//枚举链表中第一个对象
PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
//遍历链表
for(int a=0 ; a<(int)dataBlockPtr->NumObjectTypes ; a++)
{
char nameBuffer[255];
// 判断是否是网络对象索引号是510
if(objectPtr->ObjectNameTitleIndex == 510)
{
// 偏移变量
DWORD processIdOffset = ULONG_MAX;
// 找到第一个计数器
PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
// 遍历链表
for(int b=0 ; b<(int)objectPtr->NumCounters ; b++)
{
// 判断接收的数据类型是否是我们需要的
if((int)counterPtr->CounterNameTitleIndex == CurrentTrafficType)
processIdOffset = counterPtr->CounterOffset;
// 下一个计数器
counterPtr = NextCounter(counterPtr);
}
//数据类型不是我们需要的
if(processIdOffset == ULONG_MAX) {
delete [] data;
return 1;
}
// 找到第一个实列(instance)
PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
DWORD fullTraffic;
DWORD traffic;
//遍历整个实列
for(b=0 ; b<objectPtr->NumInstances ; b++)
{
wchar_t *namePtr = (wchar_t *) ((BYTE *)instancePtr + instancePtr->NameOffset);
// 得到这个实列的PERF_COUNTER_BLOCK
PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
// 现在我们得到了接口的名字
char *pName = WideToMulti(namePtr, nameBuffer, sizeof(nameBuffer));
CString iName;
iName.Format("%s",pName);
POSITION pos = TotalTraffics.FindIndex(b);
if(pos!=NULL)
{
fullTraffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
TotalTraffics.SetAt(pos,fullTraffic);
}
// 如果当前的接口就是我们选择的接口
if(InterfaceName == iName)
{
traffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
double acttraffic = (double)traffic;
double trafficdelta;
// 判断处理的接口是否是新的
if(CurrentInterface != interfaceNumber)
{
lasttraffic = acttraffic;
trafficdelta = 0.0;
CurrentInterface = interfaceNumber;
}
else
{
trafficdelta = acttraffic - lasttraffic;
lasttraffic = acttraffic;
}
delete [] data;
return(trafficdelta);
}
//下一个实列
instancePtr = NextInstance(instancePtr);
}
}
// 下一个对象
objectPtr = NextObject(objectPtr);
}
delete [] data;
return 0;
}
catch(...)
{
return 0;
}
}
//枚举安装的接口
BOOL MFNetTraffic::GetInterfaces()
{
try
{
#define DEFAULT_BUFFER_SIZE 40960L
Interfaces.RemoveAll();
unsigned char *data = (unsigned char*)malloc(DEFAULT_BUFFER_SIZE);
DWORD type;
DWORD size = DEFAULT_BUFFER_SIZE;
DWORD ret;
char s_key[4096];
sprintf( s_key , "%d" , 510 );
//RegQueryValueEx的固定调用格式
while((ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, s_key, 0, &type, data, &size)) != ERROR_SUCCESS) {
while(ret == ERROR_MORE_DATA)
{
size += DEFAULT_BUFFER_SIZE;
data = (unsigned char*) realloc(data, size);
}
if(ret != ERROR_SUCCESS)
{
return FALSE;
}
}
//得到数据块
PERF_DATA_BLOCK *dataBlockPtr = (PERF_DATA_BLOCK *)data;
//得到第一个对象
PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
for(int a=0 ; a<(int)dataBlockPtr->NumObjectTypes ; a++)
{
char nameBuffer[255];
if(objectPtr->ObjectNameTitleIndex == 510)
{
DWORD processIdOffset = ULONG_MAX;
PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
for(int b=0 ; b<(int)objectPtr->NumCounters ; b++)
{
if(counterPtr->CounterNameTitleIndex == 520)
processIdOffset = counterPtr->CounterOffset;
counterPtr = NextCounter(counterPtr);
}
if(processIdOffset == ULONG_MAX) {
free(data);
return 1;
}
PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
for(b=0 ; b<objectPtr->NumInstances ; b++)
{
wchar_t *namePtr = (wchar_t *) ((BYTE *)instancePtr + instancePtr->NameOffset);
PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
char *pName = WideToMulti(namePtr, nameBuffer, sizeof(nameBuffer));
DWORD bandwith = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
DWORD tottraff = 0;
Interfaces.AddTail(CString(pName));
Bandwidths.AddTail(bandwith);
TotalTraffics.AddTail(tottraff); // initial 0, just for creating the list
instancePtr = NextInstance(instancePtr);
}
}
objectPtr = NextObject(objectPtr);
}
free(data);
return TRUE;
}
catch(...)
{
return FALSE;
}
}
//返回安装的接口数
int MFNetTraffic::GetNetworkInterfacesCount()
{
return Interfaces.GetCount()-1;
}
//返回接口名称
BOOL MFNetTraffic::GetNetworkInterfaceName(CString *InterfaceName, int index)
{
POSITION pos = Interfaces.FindIndex(index);
if(pos==NULL)
return FALSE;
InterfaceName->Format("%s",Interfaces.GetAt(pos));
return TRUE;
}
//返回接口带宽
DWORD MFNetTraffic::GetInterfaceBandwidth(int index)
{
POSITION pos = Bandwidths.FindIndex(index);
if(pos==NULL)
return 0;
else
return Bandwidths.GetAt(pos) / 8;
}
//具体接口接收和发送的数据量
DWORD MFNetTraffic::GetInterfaceTotalTraffic(int index)
{
DWORD totaltraffic = 0;
POSITION pos;
pos= TotalTraffics.FindIndex(index);
if(pos!=NULL)
{
totaltraffic = TotalTraffics.GetAt(pos);
if(totaltraffic == 0.0)
{
GetTraffic(index);
pos= TotalTraffics.FindIndex(index);
if(pos!=NULL)
{
totaltraffic = TotalTraffics.GetAt(pos);
}
}
}
return(totaltraffic);
}
void MFNetTraffic::SetTrafficType(int trafficType)
{
CurrentTrafficType = trafficType;
}
5.1.3功能1测试中遇到问题
在测试的过程中遇到的主要问题是源代码运行时出现的错误。
5.2功能2
防火墙规则设置功能
5.2.1功能2描述
防火墙规则设置功能可以对访问添加、修改或者删除自定义规则设置,亦可以对规则编号顺序进行移动,有股则名称、拦截设置和记录设置
5.2.2功能2实现
5.2.3功能2测试中遇到问题
在此次测试中遇到的问题有:一、局域网内共享的防火墙设置,对自定义IP规则不是很熟悉;二、设置规则开放WEB服务时遇到些许小问题;三、设置规则开放FTP服务的步骤 ;四、关闭或开放特定端口 ;五、设置规则屏蔽或开放IP 对进入防火墙自定义IP规则,增加规则时碰到问题