Introduction to developing firewall based on Windows2000/XP
If you decide to develop a firewall for the Linux system, you will find a lot of related information and various free code. But when people want
It is a little difficult to develop a firewall on the Windows platform, so it is a little bit of information, as for free code, almost no
Possible.
So I decided to write this article about developing a simple function firewall on the Windows 2000/XP platform to help those who
People who are interested.
Background
Microsoft has included a new Network Driver Class in its Windows 2000 DDK: Filter-hook driver.
You can use it to create interfaces for filtering all communications.
Filter-hook driver
As I said earlier, the filter-hook driver was introduced in Microsoft's Windows 2000 DDK. But in fact it does
It is not a new network driver class, but a driver for IP address filtering.
In fact, the filter-hook driver is not a Network Driver Class. It belongs to the core drive model. In this filter-hook driver
We only implement a callback function. We just register this callback function in the filter-hook driver. When we implement and register
After the callback function is completed, the IP address filtering driver will call it when the data packet arrives and is sent.
The implementation steps are summarized as follows:
1. Create a filter-hook driver. Here you must create a core-mode driver, and you will choose either the name, DOS name, or its
Some of its attributes are not necessarily required, but I suggest you do this.
2. If you want to install the filter function, you must first obtain an IP address filter driver pointer. This is the second step.
3. We have obtained pointers. Now we can correctly install our filter function. We will send a specific IPR
Will include the pointer of our filter function.
4. filter packets !!!
5. After filtering, we must cancel the filtering function. We can register a null pointer to replace our filter function pointer.
.
Oh, the above five steps seem simple, but how can I generate a core mode driver? How to obtain IP address filter-driven
What about pointers? How ............, Wait a moment. I will explain all the above steps and list the source code examples.
Build a core model drive
Filter-hook driver is a core-mode driver, so we will build a core-mode driver. But this article
It is not a guide to "How to develop core drivers in five minutes", so I will assume that the reader has the above knowledge.
The filter-hook driver has a typical core driver structure.
1. We will create a typical DriverEntry for the driver and set the standard distribution routine (dispatch, load,
Unload, create...) to establish a symbolic connection to facilitate communication with applications.
2. The standard distribution routine manages IRPs. Before writing code, we recommend that you first create IOCTL so that the application can manipulate the driver. In my
In the example, I implemented four IOCTL codes: start_ip_hook (register a filtering function), stop_ip_hook (deregister filtering function)
Function), add_filter (install a new filter rule), clear_filter (clear all filter rules)
3. For our driver, we must implement one or more filter functions.
I recommend that you use a program to generate a typical core driver framework. Therefore, you only need to enter your function code in it.
For example, I used quicksys to generate my example project.
You will see the self-generated driver structure, as shown in the following code:
Ntstatus DriverEntry (in pdriver_object driverobject,
In punicode_string registrypath)
{
//....
Dprintf (drvfltip. SYS: Entering DriverEntry/N );
// We have to create the device
Rtlinitunicodestring (& devicenameunicodestring, nt_device_name );
Ntstatus = iocreatedevice (driverobject,
0,
& Devicenameunicodestring,
File_device_drvfltip,
0,
False,
& Deviceobject );
If (nt_success (ntstatus ))
{
// Create a symbolic link that Win32 apps can specify to gain access
// To this driver/Device
Rtlinitunicodestring (& devicelinkunicodestring, dos_device_name );
Ntstatus = iocreatesymboliclink (& devicelinkunicodestring,
& Devicenameunicodestring );
//....
// Create dispatch points for Device Control, create, close.
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)
{
//....
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 code to start filtering
Case start_ip_hook:
{
Setfilterfunction (cbfilterfunction );
Break;
}
// IOCTL to stop filtering
Case stop_ip_hook:
{
Setfilterfunction (null );
Break;
}
// IOCTL to add a filter rule
Case add_filter:
{
If (inputbufferlength = sizeof (ipfilter ))
{
Ipfilter * NF;
NF = (ipfilter *) iobuffer;
Addfiltertolist (NF );
}
Break;
}
// IOCTL to free filter rule list
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 );
// We never have pending operation so always return the status code.
Return ntstatus;
}
Void drvunload (in pdriver_object driverobject)
{
Unicode_string devicelinkunicodestring;
Dprintf (drvfltip. SYS: unloading/N );
Setfilterfunction (null );
// Free any resources
Clearfilterlist ();
// Delete the Symbolic Link
Rtlinitunicodestring (& devicelinkunicodestring, dos_device_name );
Iodeletesymboliclink (& devicelinkunicodestring );
// Delete the device object
Iodeletedevice (driverobject-> deviceobject );
}
We have completed the main driver code, and then we will filter the hook code.
Register the filter function
In the above Code, we have seen that the setfilterfunction (...) function is called, And now we will implement this IP address registration
Considering the function, he will implement it in the following steps.
1. First, we must get an IP address filter driver pointer. the driver must be correctly installed and run. Now assume that
Before this driver, my user application will load and start the IP Filter Driver.
2. We must create a specific IRP containing the ioctl_pf_set_extension_pointer control code. We have to transmit parameters.
For example, the pf_set_extension_hook_info structure contains the filter function pointer. If you want to uninstall the function, you have to take the same steps for transfer.
A null pointer to replace the filter function.
3. Send the newly created IRP to the device driver.
The major driver issue here is that only one filter function can be installed at a time. Therefore, if one of the other applications has been installed
You cannot install it.
The following code shows the function.
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;
Dprintf (getting pointer to ipfilterdriver/N );
// First of all, we have to get a pointer to ipfilterdriver Device
Rtlinitunicodestring (& filtername, dd_ipfltrdrvr_device_name );
Status = iogetdeviceobjectpointer (& filtername, standard_rights_all,
& Ipfileobject, & ipdeviceobject );
If (nt_success (Status ))
{
// Initialize the struct with functions Parameters
Filterdata. extensionpointer = filterfunction;
// We need initialize the event used later
// The ipfilterdriver to signal us
// When it finished its work
Keinitializeevent (& event, icationicationevent, false );
// We build the IRP needed to establish fitler Function
IRP = iobuilddeviceiocontrolrequest (ioctl_pf_set_extension_pointer,
Ipdeviceobject,
If (IRP! = NULL)
{
// We send the IRP
Status = iocalldriver (ipdeviceobject, IRP );
// And finally, we wait
// Acknowledge of 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
{
// If we cant allocate the space,
// We return the corresponding code error
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;
}
After processing the filter function, you can see that we must reference the file object to obtain the device driver pointer. When ipfilter
When the driver completes IRP processing, I use an event for notification.
Filter Functions
We understand how to develop the driver and install the filter function, but we do not know the filter function yet.
I have already said that this function is always called when data packets are transmitted or sent. The system depends on its return value to determine how to handle the number
Data Package.
The following is the declaration of the function.
Typedef pf_forward_action
(* Packetfilterextensionptr )(
// Ip packet header
In unsigned char * packetheader,
// Packet. Dont include header
In unsigned char * packet,
// Packet length. Dont include length of IP Header
In unsigned int packetlength,
// Index number for the interface adapter
// Over which the packet arrived
In unsigned int recvinterfaceindex,
// Index number for the interface adapter
// Over which the packet will be transmitted
In unsigned int sendinterfaceindex,
// Ip address for the interface
// Adapter that stores the packet
In ipaddr recvlinknexthop,
// Ip address for the interface adapter
// That will transmit the packet
In ipaddr sendlinknexthop
);
Pf_forward_action is an enumeration type.
Pf_forward: Specifies the IP address filtering driver to immediately return data packets to the IP stack. For packets sent to the local device, the IP address is sent to the top of the stack. If
Is to be sent to another computer, the IP package will also be sent immediately.
Pf_drop: the IP address filtering driver immediately discards the data packet from the IP address stack. This IP packet will be lost.
Pf_pass: Specify the IP address filtering driver to filter the package and return the response result to the IP stack. How the IP Filter Driver processes the packet depends on
Set the package filtering API. When the filter hook finds that the packet cannot be processed, it must be handed over to the IP Filter Driver to process the packet. This parameter is returned.
Although only the preceding three return values are described in the DDK text, when you view the pfhook. h file, you will find another value to be returned.
That is pf_icmp_no_drop. I guess this value is similar to the discarded packet and provides the ICMP packet error message.
As you can see in the definition of the filter function, both the packet and its header are transmitted in Pointer mode. So you can modify the package
Header or content before transmitting it. This is useful when writing a NAT program, for example. If we change the target address, then the packet
Will be transferred to the direction you have changed.
In my implementation, the filter function compares the rules defined by each filter rule function in the Rule linked list. This rule
The linked list will be created when the start_ip_hook control code is received during running. You will see it in the source code.
Code
In my first version, I only implemented a relatively simple version, so many people are asking me if I can help them develop
A more practical application. So now I have upgraded a relatively complex version. In this new example, there is a small package filtering application.
. In this new application, you can add some general firewall rules.
In the first version, this application consists of two parts.
User Application: it is an MFC Application to manage various filtering rules. This application sends various filtering rules to the application.
And decide when to start filtering. The filtering action is divided into three steps.
Set a filter rule based on your needs. Send the add or delete command to add or delete the filter rule.
Install rules. After you define a filter rule, press the installation button to send it to the driver.
Start filtering. You only need to press start to press the button to start filtering.
Filter Driver: The driver filters data packets sent and received according to the filter rules sent by the user application.
The filter hook driver must be in the same directory as the user application.
Why is this method used to develop a firewall?
Of course, it is not the only way to develop a firewall in windows, there are other NDIS firewalls, TDI firewalls, Winsock layer Fire Prevention
Wall, package filtering API, and so on from multiple methods. Therefore, I will describe some of the advantages and disadvantages of using the filter hook driver to develop the firewall.
Using the filter Hook method to develop firewall programs is more flexible. You can filter all IP packets before entering the IP stack. Of course
You can no longer filter data at the underlying level, such as hardware frames of the network card. Then you need to write the NDIS driver to filter it, then you will get better
But it is more difficult to develop.
Developing firewall programs based on the filter Hook method is a simple and effective method. Only a few simple steps are required to install and implement the firewall.
Process. Of course, the package filtering API will be simpler, but you will lose more flexibility and you cannot change the package content at will.
Conclusion: The filter hook driver is not the best way to develop a firewall, but it is not the worst. So why can't I list it as development?
What about commercial software?
The answer is simple, but this driver is not the best, but not the worst. I mentioned it again only because the filter hook driver can only
One installation at a time. We can develop a better one, which can be loaded at will to filter packets for hundreds of applications.
Filter programs conflict.
This method has another disadvantage in Microsoft documents. That is, although the DDK document says that you can send and receive all data packets
Whatever you want, but that is not true. You can change all received packets at will, but you can only change
Change. I don't know why?
Microsoft also introduced another unrestricted firewall hook driver for Windows XP. It is very simple to load, but Microsoft does
We do not recommend that you use it for development. Because it runs on the upper layer of the network stack, it is too high. This driver may be used in the next version of Windows.
Disappear.
Conclusion
OK. All are finished. I know this is not the best way to develop a firewall (I have mentioned its advantages and disadvantages ). But I think this is
All friends who are interested in firewall development have a good starting point, or they are more interested in firewall development after reading this article.
I hope you have understood the filter-hook driver and are ready to develop a more powerful firewall.