|
|
|
TDIPBLKH - TDI Port Blocking Filter Driver SampleCopyright © 2005 Printing Communications Assoc., Inc. (PCAUSA). All rights reserved. New: V2.02.06.15 - March, 2005.
OverviewThe goal of this TDI filter sample is to illustrate how to use a TDI filter to selectively block inbound and outbound TCP connection attempts as well as inbound and outbound UDP datagrams. This sample consists of these components:
TDIPBLKH - The TDI Port Blocking Filter DriverThis driver is fairly simple and illustrates the basics of blocking TDI operations in a filter driver. The TDI filter driver is provided with an array of port blocking rules that it applies to selected TDI operations as they are encountered. The driver includes the capability to block the following operations:
These rules are based solely on the port number. The driver does not filter based on process information or on local or remote IP address. The driver does not illustrate techniques for interacting with the user to approve or disapprove traffic. The driver filters only on \Device\Tcp and \Device\Udp. The driver does not currently filter on \Device\RawIp, so it is possible for traffic to bypass this filter if the raw sockets interface or RawIp device is used. In addition, the driver does not currently filter IPv6 at all. The driver was derived from the Build 615 TDI Local Port Monitoring driver (TDILpbkH). It could also have been derived from the TDI PassThru driver (TDIPassH); however, the author had been working most recently with TDILpbkH and was most comfortable working with it.
PBlockMan - The Port Blocking Manager ApplicationThis Win32 console application is used to build and pass a buffer containing TDI port blocking rules to the driver. Testing the TDI port blocking filter is done by running various combinations of TCP and UDP traffic to see if the specified redirection rules are followed. The PCAUSA TTCP application is used to generate TCP and UDP traffic for most tests.
PCATTCP - The TCP/UDP Traffic GeneratorThe primary application used for initial testing PCAUSA TDI filters is TTCP. TTCP is a flexible Winsock utility that includes the capability to exercise the most common Internet protocols:
TTCP tests can be configured using a command-line interface:
PCATTCP is included in both executable and source form with the PCAUSA TDI samples.
Getting Familiar with the RulesBlocking Rule for a Single PortThe port blocking rules for a single port are specified in a FW_PORT_RULE structure, defined in common.h. Each rule contains these two fields:
The actions that can be specified are defined by an enumeration and MACROs defined in common.h. They include:
Passing Port Blocking Rules to the DriverA user-mode application passes port blocking rules to the driver by filling a buffer with an array of FW_PORT_RULE structures that have been sorted by qsort so the array elements are in ascending port number order. This is done so the driver can search the rule array using the bsearch facility. The buffer containing the rules includes the FW_PORT_RULE_BUFFER header that provides a sanity-checking prolog before the port blocking rule array. The user-mode IpApi.c module provides a number of helper functions for building a FW_PORT_RULE_BUFFER and the FW_PORT_RULE array. These include:
The AddPortRule function automatically performs the necessary qsort after adding a new rule to the buffer. Here is an example of adding a port blocking rule to a FW_PORT_RULE_BUFFER:
This rule would block inbound and outbound connections on port 5001. The user-mode IoApi.c module also provides functions that open a control handle to the TDIPBlkH driver and allows that application to control the driver:
Note that each call to TdiPortBlocker_SetBlockingRules will completely replace any existing rules that the driver may been given previously. It is not necessary to clear existing rules before passing new ones to the driver. The PBlockMan sample application provides a simple illustration of the use of these user-mode API helper functions.
Driver Implementation OverviewUser-Mode InterfaceThe driver ioctl.c module provides handlers for the user-mode DeviceIoControl API described in previous paragraphs. These handlers actually work on two variables that are declared in tdiblock.c:
Port Blocking Support RoutinesThe key driver function related to port blocking is BLK_FindPortRuleAction implemented in tdiblock.c. This routine performs a bsearch on the rule buffer to return the action to be performed on a port. There are other support routines implemented in tdiblock.c, including:
Blocking TCP ConnectionsOutbound TCP ConnectionsFor outbound traffic the driver determines the remote port address and then calls BLK_FilePortRuleAction for the remote port. If the action includes FW_BLOCK_TCP_OUTBOUND then the connect request is failed with status STATUS_REMOTE_NOT_LISTENING. This blocking is done in the FLT_OnConnect routine in handlers.c Inbound TCP ConnectionsFor inbound traffic the driver determines the local port address and then calls BLK_FilePortRuleAction for the local port. If the action includes FW_BLOCK_TCP_INBOUND then the listen request is failed with status INVALID_CONNECTION. This blocking is done in the FLT_OnListen routine in handlers.c
Blocking UDP DatagramsOutbound UDP DatagramsFor outbound datagrams the driver determines the remote port address and then calls BLK_FilePortRuleAction for the remote port. If the action includes FW_BLOCK_UDP_OUTBOUND then the send datagram request is failed with status STATUS_INVALID_ADDRESS. This blocking is done in the FLT_OnSendDatagram routine in handlers.c
Inbound UDP DatagramsFor inbound datagrams the driver determines the local port address and then calls BLK_FilePortRuleAction for the local port. If the action includes FW_BLOCK_UDP_INBOUND then the receive datagram request is failed with status STATUS_INVALID_ADDRESS. This blocking is done in the FLT_OnReceiveDatagram routine in handlers.c The driver also filters ClientEventReceiveDatagram and ClientEventChainedReceiveDatagram event handlers. The driver determines the local port address and then calls BLK_FilePortRuleAction for the local port. If the action includes FW_BLOCK_UDP_INBOUND then the receive datagram request is failed with status STATUS_DATA_NOT_ACCEPTED. Event receive blocking is done in the FLT_OnEventReceiveDatagram and FLT_OnEventChainedReceiveDatagram routines in handlers.c
Derivation of TDI Port Blocking DriverThe TDI Port Blocking driver (TDIPBlkH) was derived from the Build 614 TDI Local Port Monitoring driver (TDILpbkH). It could also have been derived from the TDI PassThru driver (TDIPassH); however, the author had been working most recently with TDILpbkH and was most comfortable working with it. The first step was to remove the logging function routines (those with "LF_" prefix) by deleting the tdilog.c and tdilog.h. New blocking functions (with "BLK_" prefix) are implemented in new module tdiblock.c and tdiblock.h. It is worth pointing out that there is a difference in the prototypes and parameters of several request-filtering routines in handlers.c in the TDIPBlkH driver when compared to the same routines in the base TDILpbkH driver. The base TDIxyzH drivers did not include a mechanism for a request filter routine (such as FLT_OnConnect) to block or fail a request for the BeforeOriginal CallOrdercase. Basically, the bCallOriginal parameter was not provided to routines that needed to block a request. This missing parameter was added to the FLT_xyz functions needed to implement port blocking. The missing bCallOriginal parameter was added to the FLT_xyz routines needed to implement the simple port blocking. To fail a request the FLT_xyz routine sets IoStatus to the desired failure status and clears the bCallOriginal parameter. Routines in filter.c that examine the bCallOriginal parameter will fail the request and call IoCompleteRequest with the failure status.
Filter Order ComplicationsIt is important to understand that a TDI filter can only filter TDI address and connection objects (or "sockets") that it observes when they are created or opened. For example, if you start an application that listens on port 5001 and then start a TDI filter, then that filter cannot filter the listen request (because it has already occurred...). This presents a special problem if it is necessary to redirect or block ports that are opened by the system very early in the startup process. Examples are ports 137, 138 and 139 opened by NetBIOS over TCP/IP (NetBT) or "NetBIOS-less" direct hosting of SMB over TCP/IP on port 445. If it is essential to redirect or block these ports then some fairly messy modifications to the driver load order registry settings must be made to insure that the TDI filter driver is loaded 1.) after TCP/IP is loaded but 2.) before NetBT opens ports. See the "Load Order Issues" topic in the TDI Samples Help File.
|
|
PCAUSA Home ·
Privacy Statement ·
Products ·
Ordering ·
Support ·
Utilities ·
Resources
|