WFP for Filtering TDI RRS feed

  • Question

  • I have just looked over some examples in the DDK and I can't get them to wotk on WS2K8.  I used the example from network\trans. So now I have several questions.


    1) Can I filter the TDI lawyer from WFP? What I want to do is to monitor TDI_CONNECT, TDI_SEND, TDI_RECEIVE and TDI_SET_EVENT_HANDLER. I want to be able to accept or reject connections. I am modeling this after a driver that hooked into the TDI stack. And as I understand it the new approved method is to use WFP.


    2) Can I accomplish this using a kernel mode driver ONLY?


    3) Are there any examples WITH documentation? I have looked for documentation on the network\trans driver sample but can't seem to find any.


    4) WFP will work with or without the firewall turned on, correct?




    Tuesday, July 31, 2007 4:27 PM


All replies


    WFP is the new network filtering API introduced in Windows Vista and WS08. TDI is the legacy filtering API that, while still supported in Vista for compatibility reasons, will be deprecated over time. WFP is slated to replace TDI over time.


    For connection-based filtering (as opposed to per packet), WFP exposes the ALE_CONNECT, ALE_RECV_ACCEPT layers to permit or block inbound or outbound connections. WFP also allows for per-packet inspection or modification at TRANSPORT, DATAGRAM_DATA, or IPPACKET layers. In addition, WFP supports TCP data filtering/modification at STREAM layer. Please refer to "Inspecting Packet and Stream Data" (http://msdn2.microsoft.com/en-us/library/aa938503.aspx) for a description of various layers.


    You need to be a kernel mode driver only if you need to inspect or modify the content or packets; otherwise you can block or permit traffic by adding filters from user-mode.


    And yes WFP is a platform technology that will function even if Windows Firewall is Off.


    Hope this helps,


    Wednesday, August 1, 2007 6:51 PM
  • I am trying to write the filter driver in Kernel Mode, so I decided to add the functionality to part of an exsiting driver. So, my first call is to Open a session to the Filter Engine. The call is as follows:


    Status = FwpmEngineOpen0( NULL, // The filter engine on the local system

        RPC_C_AUTHN_WINNT // Use the Windows authentication service

        NULL, // Use the calling thread's credential

        NULL, // There are no session-specific parameters

       &engineHandle // Pointer to a variable to receive the handle


    I get an error: C0020035 which is:

    #define EPT_NT_CANT_PERFORM_OP ((NTSTATUS)0xC0020035L)


    Can you tell me why? Am I on the right track?



    Friday, August 3, 2007 3:13 PM
  • I think this is because you are calling this from a boot time driver and by the time of this call WFP -- to be specific, the Base Filtering Engine (BFE) service -- has not yet started.


    You can subscribe for BFE state changes from the DriverEntry of your bootime driver via FwpmBfeStateSubscribeChanges0. And noce the state moves to FWPM_SERVICE_RUNNING, you can then try to open the engine.


    If you traffic needs to be inspected before BFE starts, you can look into using Bootime filters and/or callouts.



    Friday, August 3, 2007 6:41 PM
  • So if I have to protect the server from Boot are you saying that WFP does not support Boot Time drivers? Do I have to live with that vulnerability until the Filter Engine Starts? I reviewed the DDK documentation and I don't see any mention of Boot time Filter Drivers.


    Friday, August 3, 2007 9:07 PM
  • No. as I mentioned above you have the option of adding Boot-time filters/callouts, which would take effect before the tcpip stack can send/receive the very first packet.


    You can look into the documentation for FWPM_FILTER_FLAG_BOOTTIME to get started.




    Friday, August 3, 2007 9:28 PM
  • I looked up FWPM_FILTER_FLAG_BOOTTIME in the WDK 6001 and the only ocurrance is in an include file, with no explantion. The examples are of limited use and the documentation I have come across is not much help to me. Is there some training on WFP available?





    Tuesday, August 7, 2007 6:37 PM

    WFP management functions and data types (e.g. Fwpm*, FWPM_*, etc) are documented in the SDK. For example the boottime flag is documented here






    Tuesday, August 7, 2007 7:57 PM
  • I was able to call FwpmBfeStateSubscribeChanges0() and wait until the service was started before I opened the Engine and that worked fine. Now what I want to do is to define a filter that basically traps TDI_CONNECT, TDI_SEND, TDI_RECEIVE and TDI_SET_EVENT_HANDLER. Can I set a master filter to TRAP all TCP communications on all ports and then filter internally using my own rules?




    Tuesday, September 4, 2007 8:29 PM
  • If you need to permit/block traffic on a per connection basis, you will need to intercept inbound/outbound connect attempts at ALE layers (i.e. ALE_AUTH_CONNECT and ALE_AUTH_RECV_ACCEPT).


    If you also need to inspect every single packet associated with a TCP connection (including 3 way handshake), you will also need to intercept at INBOUND/OUTBOUND_TRANSPORT layers; however, if all you need to inspect is data segments, then you can inspect at STREAM layer.



    Tuesday, September 4, 2007 11:57 PM
  • Suppose I want to trap all ALE_AUTH_CONNECTs and all ALE_AUTH_RECV_ACCEPTs what conditions should I use. Can I trap on ALL ports? Would I then use FWPM_CONDITION_IP_LOCAL_PORT? And then use a port range? WIll that trap ALL protocols or just TCP/IP?



    Thursday, September 6, 2007 5:11 PM
  • If you want to trap all of them, use no conditions.  It will trap all protocols that indicate to the ALE layers (I know TCP and UDP work from personal experience).

    Thursday, September 6, 2007 8:54 PM
  • Now that I have established a filter and callout all in Kernel Mode I am getting callouts and I want to examine the data. Since I am looking at LISTEN and CONNECT at the ALE Layer I would like to know what



    Once I gather the data can I call another function in the callout that will evaluate our rules? Or do I have to pend the operation and sent then call the API? If I have to PEND the Operation how do I do that?





    Tuesday, September 11, 2007 8:50 PM
  • Layer data field ID can be mapped into filter condition. For example, FWPS_FIELD_ALE_AUTH_LISTEN_V4_ALE_USER_ID is mapped into FWPM_CONDITION_ALE_USER_ID, which has a type of FWP_SECURITY_DESCRIPTOR_TYPE. you can refer to





    You can use callout driver to inline or out-of-band evaluate the data. WDK has info for it.




    this page also has the pointer of how to use FwpsPendOperation0.



    Tuesday, September 11, 2007 9:21 PM
    • I have noticed on the LISTENI can not filter on the protocol type that I want TCP. I can filter on the protocol in the CONNECT Why?
    • Also I assume my callbacks are being called at IRQL DISPATCH or at least that should be a good assumption. Correct?
    • In order to PEND the Callback and process it later, I will need to first PEND the operation in the callback with FwpsPendOperation0, then send that context to a worker thread for making the decision. Will I need to reinject the Packet? This was not clear in the DDK documentation as it stated:

    A callout can call this function only to pend a packet that originates from the FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_Xxx, FWPM_LAYER_ALE_AUTH_LISTEN_Xxx, or FWPM_LAYER_ALE_AUTH_CONNECT_Xxx filtering layers. A callout can pend the current processing operation on a packet when the callout needs to perform processing on one of these layers that may take a long interval to complete or that should occur at IRQL = PASSIVE_LEVEL if the current IRQL > PASSIVE_LEVEL.

    To complete a connection that was previously pended at the FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_Xxx layer, the callout must reinject the packet that was cloned at that layer as well as call the FwpsCompleteOperation0 function.


    It mentions the ALE_AUTH_RECV_ACCEPT_Xxx layer, is that the only Level that would need to reinject the packet?

    Thursday, September 13, 2007 8:14 PM
  • ALE_AUTH_LISTEN is for TCP-only, hence the protocol field is not indicated. ALE_AUTH_CONNECT and ALE_AUTH_RECV_ACCEPT are shared by all protocols (except ICMP errors). For TCP, ALE_AUTH_CONNECT corresponds to the socket connect() call; for UDP it is invoked for every new remote flow (dest address, dest port). Similarly, for TCP, ALE_AUTH_RECV_ACCEPT corresponds to the socket accept() call; and for UDP it is invoked for every new inbound flow. When invoked for UDP, ALE_AUTH_CONNECT will indicate the UDP packet that's creating the flow.


    Once a flow is established, ALE_AUTH_CONNECT and ALE_AUTH_RECV_ACCEPT can be re-invoked by packets of either direction should a policy change occurs at the layer (i.e. new filter added/removed from the layer). In which case packets are indicated to these layers with the FWP_CONDITION_FLAG_IS_REAUTHORIZE bit set.


    classifyFn can be invoked at <= DISPATCH_LEVEL.


    You need to use FwpsPendOperation0/FwpsCompleteOperation0 to pend initial ALE_Xxx invocations. (re-auth triggered by policy change cannot and need not be pended). Whenever a packet is indicated to ALE_Xxx layers, it needs to be cloned and re-injected back after FwpsCompleteOperation0 using either FwpsInjectTransportSendAsync0/FwpsInjectTransportReceiveAsync0 depending on packet direction.


    With the exception of ALE_AUTH_RECV_ACCEPT, All other ALE_Xxx layers will be re-auth'ed following an FwpsCompleteOperation0 call and it is from this re-classify the inspection decision is to be returned. (Packet queued during the initial classify should only be re-injected back after this second classify is authorized). Callout drivers need to maintain enough states to associate the first and second classify and also to store the inspection result. Re-auth triggered by FwpsCompleteOperation0 can furthur be pended.


    For ALE_AUTH_RECV_ACCEPT, the inspection decision is implicit by whether the pended packet is re-injected back or not; hence there is no re-classify following FwpsCompleteOperation0 in this case.


    Hope this helps,


    Thursday, September 13, 2007 10:54 PM
  • Hi,

    I know the topic is very old, but I am surprised to read this.

    You say : "Packet queued during the initial classify should only be re-injected back after this second classify is authorized". In the WFP sampler, with Pend Authorization mode, the reinjection is performed by the function PrvCloneAuthorizedNBLAndInject, whose callstack is :


    This function is called just after the call to FwpsCompleteOperation (in KrnlHlprPendDataDestroy from PerformPendAuthorization) has been made...

    From my understanding, the WFP sampler does not do what you say : ALE_AUTH_RECV_ACCEPT is not injected after the reauthorization occured...

    What can we conclude ? Is it a bug in the WFP sampler ? Did the WFP framework evolve during time, and there is no more requirement on when reinjecting ? Does it apply only to 2k8 ?

    If someone could enlighten this, it would be very nice !


    Thursday, July 18, 2019 8:24 AM