TDIREDIR - TDI TCP Redirector Filter Driver Sample

Copyright © 2005 Printing Communications Assoc., Inc. (PCAUSA). All rights reserved.

New: V2.02.06.15 - March, 2005.

Overview

The goal of this TDI filter driver sample is to illustrate how to use TDI to redirect outbound TCP connections to a local proxy. To do this effectively two basic functions must be provided:

Connection Redirection
The proxy application must be able to specify rules that select TCP connections to be redirected and identify the local proxy port where the redirected TCP connection is to be accepted.
Original Destination Determination
The proxy must be able to determine the original remote address and port after it has accepted a redirected connection.

This sample consists of these components:

bulletTDIREDIR.sys - The TDI TCP Redirector Filter Driver.
bulletTTCPProxy.exe - This is a Win32 console application that builds example connection redirection rules and passes them to the TDIPBLKH driver. In addition, it serves as a partially-implemented proxy for TTCP traffic.
bulletPCATTCP.exe - A flexible TCP/UDP transmitter/receiver utility used to generate test traffic.

 

TDIREDIR - The TDI TCP Redirector Filter Driver

This driver is fairly simple and illustrates the basics of redirecting outbound TCP connection requests. The proxy application passes a buffer containing TCP redirection rules to the driver. The driver TDIH_TdiConnect routine is modified to search the rule buffer and apply the redirection if a match is found.

Connections can be redirected to a local proxy on 127.0.0.1 or to a different remote IP address and port.

The redirection rule design includes the ability to apply a filter on a specific process by name or to ignore the rule if the connection attempt is being made by a specific process name or process ID. The latter capability allows a proxy to make an outbound connection without being redirected.

The design includes a very basic mechanism that allows a proxy to determine the original remote address and port after it has accepted a redirected connection.

The driver filters only on \Device\Tcp. 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 redirect IPv6 TCP connections at all.

The TDI TCP Redirector sample driver (TDIREDIR) driver is derived from the base TDI Layered Filter sample driver (TDIPASSL).

 

TTCPProxy - The TTCP Proxy Application

PCAUSA uses the TTCP TCP/UDP Winsock application (described below) as a test traffic generator when testing TDI filters. In this case we have (partially) developed a proxy version of TTCP.

The TTCPProxy application is a modified version of the stock PCATTCP application. It is modified to load and start the TDIREDIR driver and then to build and pass a buffer containing TCP redirection rules to the driver. In addition, if TTCPProxy is running as a TCP receiver then it includes code to fetch and display the original destination after a redirected connection has been accepted.

TTCPProxy is not a complete TTCP proxy implementation. It does accept and handle the redirected connection and does know the original destination; however, it does not include the logic to establish the additional connection between the proxy and the original destination.

Testing the TCP redirector is done by running various combinations of TTCP and TTCPProxy applications to see if the specified redirection rules are followed.

 

PCATTCP - The TCP/UDP Traffic Generator

The 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:

bulletTCP Client (Transmitter)
bulletTCP Server (Receiver)
bulletUDP Client (Transmitter)
bulletUDP Server (Receiver)

TTCP tests can be configured using a command-line interface: 

bulletLength of buffers read from or written to the network.
bulletNumber of buffers to send.
bulletBuffer alignment and offset.
bulletSocket options, including: SO_SNDBUF, SO_RCVBUF, TCP_NODELAY.
bulletPort number.

PCATTCP is included in both executable and source form with the PCAUSA TDI samples.

 

Getting Familiar with the Rules

Outbound TCP Connection Redirection Rule for a Single Port

The TCP redirection rules are fairly simple. Each TCP redirection is specified by a TCP_REDIR_RULE structure, defined in common.h. rule contains this information:

bulletRemote IP Address Range - The rule applies if the remote address is within this range. A zero (0) address matches any remote address.
bulletRemote IP Network Mask - The network mask for matching.
bulletRemote Port - The rule applies if the remote port matches this port.
bulletRedirect-To Address - The IP address that will replace the original remote address if the rule is a match.
bulletRedirect-To Port - The port number that will replace the original port if the rule is a match.

In addition, each rule can contain Process Name matching information:

bulletProcess Name To Ignore - The rule is ignored if the connection is being made by this process name.
bulletProcess ID To Ignore - The rule is ignored if the connection is being made by this process ID.
bulletProcess Name To Redirect - The rule only applies if the connection is being made by this process name.

Only one of the two possible Process Name matching parameters is permitted in any given rule.

If a Process ID to ignore is specified, then the Process Name to Ignore is not used.

The controlling application builds a buffer containing multiple TCP redirection rules. The current implementation supports only one rule per remote port.

 

Building the TCP Connection Redirection Rules Buffer

A user-mode application passes TCP redirection rules to the driver by filling a buffer with an array of TCP_REDIR_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 TCP_REDIR_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 TCP_REDIR_RULE_BUFFER and the TCP_REDIR_RULE array. These include:

bulletTcpRedirector_AllocateRuleBuffer - Allocates an empty TCP_REDIR_RULE_BUFFER.
bulletTcpRedirector_FreeRuleBuffer - Frees a TCP_REDIR_RULE_BUFFER.
bulletTcpRedirector_AddPortRule - Add a new TCP redirection rule to the buffer.

The AddPortRule function automatically performs the necessary qsort after adding a new rule to the buffer.

Here is an example of adding a TCP redirection rule to a TCP_REDIR_RULE_BUFFER:

    // 192.168.1.20 - 192.168.1.100:5001 -> 127.0.0.1:5002
    //    Redirect Any Process Except "TTCPPROXY.EXE"
    pRuleBuffer = TcpRedirector_AddPortRule(
        pRuleBuffer,
        inet_addr( "192.168.1.20" ), // RemoteAddressRangeStart
        inet_addr( "192.168.1.100" ),// RemoteAddressRangeEnd
        inet_addr( "255.255.255.0" ),// RemoteNetMask
        5001,                        // RemotePort
        NULL,
        "ttcpproxy.exe",
        NULL,                       // ProcessIdToIgnore
        inet_addr( "127.0.0.1" ),   // RedirectToAddress
        5002                        // RedirectToPort
        );

This rule would redirect outbound TCP connections on port 5001 in the address range 192.168.1.20 through 192.168.1.100 to a local proxy on 127.0.0.1:5002 for all processes except TTCPPROXY.exe. TTCPPROXY.exe would be allowed to make an outbound connection on port 5001 without interference.

 

Passing TCP Connection Redirection Rules to the Driver

The user-mode IoApi.c module provides functions that open a control handle to the TDIREDIR driver and allow the application to manage TCP redirection rules:

bulletTcpRedirector_SetRedirectRules - Passes a TCP_REDIR_RULE_BUFFER to the driver using DeviceIoControl on IOCTL_SET_REDIRECTION_RULES.
bulletTcpRedirector_GetRedirectRules - Fetches the driver's TCP_REDIR_RULE_BUFFER using DeviceIoControl on IOCTL_GET_REDIRECTION_RULES.
bulletTcpRedirector_ClearRedirectRules - Clears the driver's copy of the current TCP redirection rules.

Each call to TdiRedirector_SetRedirectRules 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 TTCPProxy and TcpConnMan sample applications provides illustrations of the use of these user-mode API helper functions.

 

Fetching Original Destination in the Proxy

In order for a proxy to operate correctly it is necessary for the proxy to be able to determine the original destination of the redirected connection. This sample provides the TcpRedirector_GetOriginalDestination function for this purpose. TcpRedirector_GetOriginalDestination is called immediately after the proxy accepts a redirected connection and provides the following information:

bulletOriginal Remote IP Address
bulletOriginal Remote Port
bulletOriginator's Process Name
bulletOriginator's Process ID

Use of this function is illustrated in the TTCPProxy application.

I would have preferred a mechanism that provides an indication to the proxy before it accepts a connection. This is certainly possible by extending the features already illustrated in this sample. The approach would be to pend the TDI_CONNECT IRP in the TDIH_TdiConnect handler and pass the same information to the proxy before the accept. Having this information before accept would allow the proxy to dynamically provide redirection ports and would provide additional flexibility in managing connections. Unfortunately, that capability is left to a future more expensive product...

 

Other Driver Control Support Routines

The user-mode IoApi.c module provides additional support routines that allow the application to control the driver:

bulletTcpRedirector_Startup -Mandatory first application call that initializes app-driver interface.
bulletTcpRedirector_Shutdown - Mandatory call at application exit to close app-driver interface.
bulletTcpRedirector_IsDriverLoaded - Returns TRUE if TDIREDIR driver is loaded.

 

More Sophisticated Rule Enhancements

One can certainly envision the need for more sophisticated TCP redirection rules beyond the simple rules illustrated in this sample. Ideas for rule enhancements include:

bulletMultiple rules per port.
bulletPer-Process rules.
bulletMultiple ProcessNameToIgnore's per rule.
bulletOriginal Destination pre-accept indication (Described above).

If more sophisticated rules are required, then hopefully this sample will provide a foundation for their creation.

 

Example TCP Redirection to Proxy Test

This topic describes a representative TCP redirection test using the PCATTCP and TTCPProxy applications that are provided with the TDIREDIR driver.

In the table below the left column represents the Command Prompt window for PCATTCP and the right for TTCPProxy. Rows provide a relative indication of the steps in the test. Output of specific interest to the TCP connection redirection is marked in RED.

  1. The TTCP Proxy application is started as a TTCP Receiver on port 5002. It builds a rule to redirect outbound TCP connections in the address range 192.168.1.20 to 192.168.1.100 to it's listener port.
  2. The TTCP Client is started to transmit to a TTCP receiver at address 192.168.1.100:5001.
  3. The TDIREDIR driver redirects this connection attempt to the TTCP Proxy. Note that the TTCP Proxy does fetch the original destination information.
  4. The final row shows the statistics of both the TTCP Client and the TTCP Proxy as the data is transferred over the redirected connection.

 

TTCP Client Window

TTCP Proxy Window

 
C:>ttcpproxy -r -p 5002
PCAUSA TTCP Proxy V2.01.01.07
TDIREDIR Driver Loaded
Dumping 1 Rules
192.168.1.20 - 192.168.1.100:5001 -> 127.0.0.1:5002
   Redirect Any Process Except Process 1636

TCP Receive Test
  Local Host  : codebase
**************
  Listening...: On port 5002
C:>pcattcp -t 192.168.1.100
PCAUSA Test TCP Utility V2.01.01.07
TCP Transmit Test
  Transmit    : TCP -> 192.168.1.100:5001
  Buffer Size : 8192; Alignment: 16384/0
  TCP_NODELAY : DISABLED (0)
  Connect     : Connected to 192.168.1.100:5001
  Send Mode   : Send Pattern; Number of Buffers: 2048
  Statistics  : TCP -> 192.168.1.100:5001
 
 
Accept      : TCP <- 127.0.0.1:1106
Buffer Size : 8192; Alignment: 16384/0
Original    : TCP <- 192.168.1.100:5001 from PCATTCP.EXE (3816)
Receive Mode: Sinking (discarding) Data
Statistics  : TCP <- 127.0.0.1:1106
16777216 bytes in 0.17 real seconds = 95255.81 KB/sec +++
numCalls: 2048; msec/call: 0.09; calls/sec: 11906.98
16777216 bytes in 0.17 real seconds = 95255.81 KB/sec +++
numCalls: 2049; msec/call: 0.09; calls/sec: 11912.79

 

Driver Implementation Overview

User-Mode Interface

The 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 tcpredir.c:

bulletg_bIsRedirectionEnabled - A parameter that is TRUE if TCP connection redirection is enabled in the driver.
bulletg_pRuleBuffer - A pointer to the driver's copy of the current TCP_REDIR_RULE_BUFFER.

 

Redirecting Outbound TCP Connections

The TDIH_TdiConnect filter routine in TcpConn.c is called when the local host makes a TCP connection attempt. This routine includes the logic to search the TCP redirection rule buffer to find a rule that matches the connection attempt. If a match is found, then the original destination information is saved (to be fetched later by the proxy application) and the remote address and port are changed to values specified in the rule.

 

Filter Order Complications

It 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.

It is difficult to control the order that filters are processed. Windows anti-virus and firewall products often employ their own TDI filters.

You will have to test any product derived from this sample extensively to insure that it is compatible with possibly conflicting products.

 

 

 

PCAUSA Home · Privacy Statement · Products · Ordering · Support · Utilities · Resources
Mailing Lists  · PCAUSA Newsletter · PCAUSA Discussion List
 
Rawether for Windows and WinDis 32 are trademarks of Printing Communications Assoc., Inc. (PCAUSA)
Microsoft, MS, Windows, Windows 95, Windows 98, Windows Millennium, Windows 2000, and Win32 are registered trademarks and Visual C++ and Windows NT are trademarks of the Microsoft Corporation.
Send mail to webmaster@pcausa.com with questions or comments about this web site.
Copyright © 1996-2008 Printing Communications Assoc., Inc. (PCAUSA)
Last modified: December 31, 2007