关于防火墙de研发

ice50303 2009-03-13 10:33:00
因种种原因,小弟最近要做一个 “个人PC防火墙”,自然是简单版的。

主要实现功能:1.端口扫描、监控; 2.实现包过滤功能

现在我思考到的是:
1.实现个人防火墙设计关键技术
2.个人防护墙设计所面临的困难

希望大侠们根据以上2点 或者其他的,给我提点提点。。。

一个人在这想来想去的,总觉得有的地方没想到,谢谢大家
...全文
171 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ice50303 2009-03-13
  • 打赏
  • 举报
回复
2楼~~~谢谢,

不过我实际上是想和大家探讨下,其中所要用的一些技术和一些需要注意的地方

然后最好有大侠给个扩展性的意见什么的~~
  • 打赏
  • 举报
回复
断口扫描的

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<math.h>

#include<netdb.h>
#include<unistd.h>
#include<sys/time.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in_systm.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>
#include<arpa/inet.h>
#include <time.h>


/*#define CHKADDRESS( _saddr_)
{
u_char *p =(char *)&(_saddr_);
if( (p[0] == 10) || (p[0] ==168 &&16<=p[1]&&p[1]<=31) ||(p[0] ==192 && p[1]==168)
{}
else
{

fprintf(stderr,"IP address error.\n");
exit(EXIT_FAILURE);
}
}*/

enum {CMD_NAME,DST_IP,START_PORT,LAST_PORT};

#define MAXBUFF 8192

int main(int argc,char *argv[])
{
clock_t start, finish;
struct icmp *icmp;
fd_set select_fd;
struct sockaddr_in send_sa;
int recv_sd;
int send_sd;
char buff[MAXBUFF];
int endport;
int startport;
int dstport;
struct timeval tv;
struct ip *ip;
int hlen,port;
int count;

if(argc!=4)
{
fprintf(stderr," usge:%s dst_ip start_port last_port\n",argv[CMD_NAME]);
exit(EXIT_FAILURE);
}
send_sa.sin_family = AF_INET;
send_sa.sin_addr.s_addr = inet_addr(argv[DST_IP]);

startport = atoi(argv[START_PORT]);
endport = atoi(argv[LAST_PORT]);
//CHKADDRESS(send_sa.sin_addr.s_addr);

if( (send_sd = socket(AF_INET,SOCK_DGRAM,0))<0)
{
perror(" socket (SOCK_DGRAM)");
exit(EXIT_FAILURE);
}

if( (recv_sd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0)
{
perror(" socket (SOCK_RAW)");
exit(EXIT_FAILURE);
}

for(dstport = startport;dstport<=endport;dstport++)
{
printf(" Scan port %d: %d times\r",dstport,count);
fflush(stdout);
send_sa.sin_port = htons (dstport);
sendto(send_sd,NULL,0,0,(void *) &send_sa,sizeof(send_sa));

tv.tv_sec=1;
tv.tv_usec=0;
count=0; //记录每次同一端口,ICMP包数量
start = clock();

while(1)
{
FD_ZERO(&select_fd);
FD_SET(recv_sd,&select_fd);

if(select (recv_sd+1,&select_fd,NULL,NULL,&tv)>0)
if(recvfrom(recv_sd,buff,MAXBUFF,0,NULL,NULL)!=56) //ICMP包,长度为56,IP+ICMP+IP+UDP
continue;
//intf("a new icmp ack\n");
if( ((finish=clock() )-start)>=2)
{
printf("2 sec no target icmp ack.\n");
struct servent *se_t;
se_t=getservbyport(htons (dstport)," udp");
printf("%5d %-20s\n",dstport,(se_t==NULL)?"unkown":se_t->s_name);
break;
}
ip=(struct ip *)buff;
hlen=ip->ip_hl<<2;
icmp=(struct icmp *)(buff+hlen);

port=ntohs(* (u_short *)(buff+20+8+20+2) );
if( (ip->ip_src.s_addr!=send_sa.sin_addr.s_addr) || (icmp->icmp_type!=ICMP_UNREACH) || (icmp->icmp_code!=ICMP_UNREACH_PORT) ||(port!=dstport))
{
if(count>10)
{
printf("port %d:icmp_type is %d;icmp_code is %d.\n",port,icmp->icmp_type,icmp->icmp_code);
break;
}
if(ip->ip_src.s_addr==send_sa.sin_addr.s_addr && port==dstport)
{
//printf(" %d times\r",count);
count++;
break;
}
//printf("Not target icmp packet.continue check port %d\n",dstport);
continue;
}
else
{
struct servent *se;
se=getservbyport(htons (dstport)," udp");
//if(se!=NULL)
printf("%5d %-20s\n",dstport,(se==NULL)?"unkown":se->s_name);
}
break;
}
}
return EXIT_SUCCESS;
}
Sou2012 2009-03-13
  • 打赏
  • 举报
回复
恩,参考 nmap的源码
chin_chen 2009-03-13
  • 打赏
  • 举报
回复
果你决定开发LINUX下的防火墙,你会找到很多免费的信息与源代码。但如果开发WINDOWS平台下的防火墙会有点困难,找到相关信息与代码都简直是不可能的任务。


因为关于此的文档很少并没有代码,我把使用它的成功方法写入文章,希望帮助你理解这种简单的方法。

Filter-Hook 驱动
像我刚才所说的,在Microsoft Windows 2000 DDK中介绍了Filter-Hook Driver, 事实上,它不是一种新的网络驱动,它只是扩展了IP过滤驱动(IP Filter Driver)的功能。
实际上,Filter-Hook Driver并不是网络驱动,它是一种内核模式驱动(Kernel Mode Driver). 大致上是这样的:在Filter-Hook Driver中我们提供回调函数(callback),然后使用IP Filter Driver注册回调函数。这样当数据包发送和接收时,IP Filter Driver会调用回调函数。那么我们到底该如何实现这些步骤呢?总结如下:


1) 建立Filter-Hook Driver.我们必须建立内核模式驱动,你可以选择名称,DOS名称和其它驱动特性,这些不是必须的,但我建议使用描述名称。

2) 如果我们要安装过滤函数,首先我们必须得到指向IP Filter Driver的指针,这是第二步。

3) 我们已经取得了指针,现在我们可以通过发送特殊的IRP来安装过滤函数,该"消息"传递的数据包含了过滤函数的指针。

4) 过滤数据包!!!

5) 当我们想结束过滤,我们必须撤销过滤函数。这通过传递null指针作为过滤函数指针来实现。

哦,只有五个步骤,这看起来非常容易,但...如何生成内核模式驱动?如何得到IP Filter Driver指针,如何..... 是的,请稍等,我现在将解释这些步骤并提供源代码:P


创建内核模式驱动(Kernel Mode Driver)

Filter-Hook Driver属于内核模式驱动,因此我们要创建内核模式驱动。这篇文章不是“如何仅用5分钟开发内核模式驱动” 这样的指南,因此我假设读者已经有了关于此的相关知识。

Filter-Hook Driver结构是典型的内核模式驱动的结构:

1) 一个创建设备的驱动程序入口,为通讯创建符号连接和处理IRPs(分派,加载,卸载,创建...)的标准例程。

2)在标准例程里管理IRPs.在开始编码前,我建议先思考一下哪些IOCTL你需要从设备驱动中暴露给应用程序。 在我的例子中,我实现了四个IOCTL代码:START_IP_HOOK(注册过滤函数),STOP_IP_HOOK(注销过滤函数), ADD_FILTER(安装新的过滤规则),CLEAR_FILTER(清除所有规则).

3)对于我们的驱动,我们必须实现多个用于过滤的函数。


我推荐你使用工具程序来产生内核驱动基本框架,这样你只需往里添加代码。例如,我在工程中使用的是QuickSYS。

下面是驱动结构的实现代码:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{

//....

dprintf("DrvFltIp.SYS: entering DriverEntry\n");

//我们必须创建设备
RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);

ntStatus = IoCreateDevice(DriverObject,
0,
&deviceNameUnicodeString,
FILE_DEVICE_DRVFLTIP,
0,
FALSE,
&deviceObject);



if ( NT_SUCCESS(ntStatus) )
{
// 创建符号连接使win32应用程序可以处理驱动与设备
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);

ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString,
&deviceNameUnicodeString);

//....

// 创建用于控制、创建、关闭的dispatch指针

DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
DriverObject->DriverUnload = DrvUnload;
}

if ( !NT_SUCCESS(ntStatus) )
{
dprintf("Error in initialization. Unloading...");

DrvUnload(DriverObject);
}

return ntStatus;
}

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

// ....

switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:

dprintf("DrvFltIp.SYS: IRP_MJ_CREATE\n");

break;

case IRP_MJ_CLOSE:

dprintf("DrvFltIp.SYS: IRP_MJ_CLOSE\n");

break;

case IRP_MJ_DEVICE_CONTROL:

dprintf("DrvFltIp.SYS: IRP_MJ_DEVICE_CONTROL\n");

ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

switch (ioControlCode)
{
// 启动过滤的ioctl代码
case START_IP_HOOK:
{
SetFilterFunction(cbFilterFunction);

break;
}

// 关闭过滤的ioctl
case STOP_IP_HOOK:
{
SetFilterFunction(NULL);

break;
}

// 添加过滤规则的ioctl
case ADD_FILTER:
{
if(inputBufferLength == sizeof(IPFilter))
{
IPFilter *nf;

nf = (IPFilter *)ioBuffer;

AddFilterToList(nf);
}

break;
}

// 释放过滤规则列表的ioctl
case CLEAR_FILTER:
{
ClearFilterList();

break;
}

default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

dprintf("DrvFltIp.SYS: unknown IRP_MJ_DEVICE_CONTROL\n");

break;
}

break;
}


ntStatus = Irp->IoStatus.Status;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

// 我们不会有未决的操作,所以总是返回状态码
return ntStatus;
}


VOID DrvUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;

dprintf("DrvFltIp.SYS: Unloading\n");

SetFilterFunction(NULL);

// 释放所有资源
ClearFilterList();

// 删除符号连接
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&deviceLinkUnicodeString);


// 删除设备对象
IoDeleteDevice(DriverObject->DeviceObject);
}

我们已经编写了驱动的主代码,下面我们继续实现Filter-Hook Driver


注册过滤函数

在上面的代码中,你已经看到了SetFilterFunction(..)函数。我在IP Filter Driver中执行这个函数来注册过滤函数,步骤如下:

1) 首先,我们必须得到IP Filter Driver的指针,这要求驱动已经安装并执行。为了保证IP Filter Driver已经安装并执行,在我的用户程序中,在加载本驱动前加载并启动IP Filter Driver。

2) 第二步,我们必须建立用IOCTL_PF_SET_EXTENSION_POINTER作为控制代码的IRP。我们必须传递PF_SET_EXTENSION_HOOK_INFO 参数,该参数结构中包含了指向过滤函数的指针。如果你要卸载该函数,你必须在同样的步骤里传递NULL作为过滤函数指针。

3) 向设备驱动发送创建IRP, 这里有一个大的问题,只有一个过滤函数可以安装,因此如果另外的应用程序已经安装了一个过滤函数,你就不能再安装了。

设置过滤函数的代码如下:

NTSTATUS SetFilterFunction
(PacketFilterExtensionPtr filterFunction)
{
NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS;
UNICODE_STRING filterName;
PDEVICE_OBJECT ipDeviceObject=NULL;
PFILE_OBJECT ipFileObject=NULL;

PF_SET_EXTENSION_HOOK_INFO filterData;

KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP irp;

dprintf("Getting pointer to IpFilterDriver\n");

//首先我们要得到IpFilterDriver Device的指针
RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME);
status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL,
&ipFileObject, &ipDeviceObject);

if(NT_SUCCESS(status))
{
//用过滤函数作为参数初始化PF_SET_EXTENSION_HOOK_INFO结构
filterData.ExtensionPointer = filterFunction;

//我们需要初始化事件,用于在完成工作后通知我们
KeInitializeEvent(&event, NotificationEvent, FALSE);

//创建用于设立过滤函数的IRP
irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
ipDeviceObject,
if(irp != NULL)
{
// 发送 IRP
status = IoCallDriver(ipDeviceObject, irp);

// 然后我们等待IpFilter Driver的回应
if (status == STATUS_PENDING)
{
waitStatus = KeWaitForSingleObject(&event,
Executive, KernelMode, FALSE, NULL);

if (waitStatus != STATUS_SUCCESS )
dprintf("Error waiting for IpFilterDriver response.");
}

status = ioStatus.Status;

if(!NT_SUCCESS(status))
dprintf("Error, IO error with ipFilterDriver\n");
}

else
{
//如果不能分配空间,返回相应的错误代码
status = STATUS_INSUFFICIENT_RESOURCES;

dprintf("Error building IpFilterDriver IRP\n");
}

if(ipFileObject != NULL)
ObDereferenceObject(ipFileObject);

ipFileObject = NULL;
ipDeviceObject = NULL;
}

else
dprintf("Error while getting the pointer\n");

return status;
}


当我们已经完成了建立过滤函数的工作,当取得设备驱动的指针后必须释放文件对象。我使用事件来通知IpFilter Driver 已经完成了IRP处理。

过滤函数

我们已经知道了如何开发驱动并安装过滤函数,但还不知道该过滤函数中的任何东西。当主机接收或发送一个数据包,该过滤函数总会被调用,系统会根据函数的返回值决定如何处理这个数据包。

函数的原型是这样的:

threeleafzerg007 2009-03-13
  • 打赏
  • 举报
回复
这个东东 要做的好 都不是很容易的事情

建议参考源码 :
1) nmap
2) iptable
  • 打赏
  • 举报
回复
防火墙,关键是你要做到什么程度,具体有那些功能,只做点包检测跟防洪水攻击就完全不一样了。同理,IDS这些你要不要考虑呢。
ice50303 2009-03-13
  • 打赏
  • 举报
回复
自己顶起来。。。~

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧