locked
Conditions of filtering for back traffic (INBOUND_TRANSPORT_V4) RRS feed

  • Question

  • Hi,

    I have a question about conditions of filtering on INBOUND_TRANSPORT_V4 layer.

    I intend to implement injections for both outbound and inbound traffics.
    Each filter condition is as follows:
      outbound: Remote Address == 192.168.1.21 and Remote Port == 80
                (--> replace destination port with 81)
      inbound: Remote Address == 192.168.1.21 and Remote Port == 81
     
    Each of them seems to work as I expect at least separately when I test like below.

      When accessing http://192.168.1.21/
         ---> Outbound classifyFn is called by [SYN] packet, and injected to port 81.
      When accessing http://192.168.1.21:81/
         ---> Inbound classifyFn is called by [SYN, ACK] packet.

    In the first case, I expect the inbound filter will also be triggered on the back traffic,
    because its [SYN, ACK] packet has 192.168.1.21 as Source Address and 81 as Source Port.
    But inbound classifyFn seems to be never called in such case.

    I would like to know, this is expected or my code might have confusion.

    Thanks for any information.

    Wednesday, April 9, 2008 5:11 AM

Answers

  • Hi,

     

    Long thread and lots of questions , let me try to answer some of them.

     

    Yes WFP currently lacks connection proxy support and that is in our to-do list.

     

    However you should be able to proxy and un-proxy on a per packet basis. It seems that the proxy part of working for you.

     

    To un-proxy, you could register at TRANSPORT_DISCARD or INBOUND_IPPACKET, grab the packets that need to unproxy and recv-inject them using FwpsInjectTransportReceiveAsync0 or FwpsInjectNetworkReceiveAsync0.

     

    The data offset of packets differ when they are indicated to different layers -- For example, at INBOUND_IPPACKET the offset is at the beginning of Transport Header (after IP header); at INBOUND_TRANSPORT (including DISCARD), the offset is at the beginning of Transport Data (after IP header and Transport Header). the Recv- injection functions require the NBL be positioned at the beginning of the IP header.

     

    See see http://msdn2.microsoft.com/en-us/library/aa504926.aspx for more details.

     

    So from a high lever here is what you need to do (depending on your layer of choice) --

     

    At INBOUND_IPPACKET --

    1. Retreat oiginal NBL/NB by size of inMetaValues->ipHeaderSize
    2. make a clone
    3. Advance the clone by size of inMetaValues->ipHeaderSize
    4. call NdisGetDataBuffer, and this should now point to the TCP header
    5. modify the port; adjust the TCP checksum.
    6. Retreat the clone by the same amount as 3.
    7. Advance the original by the same amount as 1.
    8. FwpsInjectNetworkReceiveAsync0
    9. block and aborb the original NBL.

    At INBOUND_TRANSPORT_/DISCARD --

    1. Retreat oiginal NBL/NB by size of inMetaValues->ipHeaderSize + inMetaValues->transportHeaderSize
    2. make a clone
    3. Advance the clone by size of inMetaValues->ipHeaderSize
    4. call NdisGetDataBuffer, and this should now point to the TCP header
    5. modify the port; adjust the TCP checksum.
    6. Retreat the clone by the same amount as 3.
    7. Advance the original by the same amount as 1.
    8. FwpsInjectTransportReceiveAsync0
    9. block the original NBL.

    Hope this helps,

    Biao.W.

    Monday, April 14, 2008 9:10 PM

All replies

  •  

    Hi, I reply myself...

     

    I tried dividing outbound / inbound drivers separately.

    But no good results.

     

    Perhaps can invisible packets be found in INBOUND_TRANSPORT_V4_DISCARD layer?

    Now I'll try it..

    Thursday, April 10, 2008 8:44 AM
  • Hi.

     

    I found them there ...

     

    discardModule=1, discardReason=4,

    so InetDiscardEndpointNotFound ...

    That is "The endpoint specified in the packet's header could not be found."

    http://msdn2.microsoft.com/en-us/library/aa504876.aspx )

     

    But why? Your client port will welcome you!

     

     

    I'll appreciate any informations or explanations about this behavior ..

    Thanks.

     

     

    # Windows Firewall is disabled.

    Thursday, April 10, 2008 10:57 AM
  •  

    A certain thing was thought of.

     

    discardModule=1 means MODULE_TRANSPORT.

    http://msdn2.microsoft.com/en-us/library/bb727623.aspx )

     

    So maybe I can catch them in the lower layer (network layer: FWPM_LAYER_INBOUND_IPPACKET_V4 ) before discarded and modify their Source Ports to the original remote port, so that the local port may accept them ( = [SYN, ACK] ).

     

    Now I'll try it..

     

     

    # How about doing it in the DISCARD layer using FwpsInjectTransportReceiveAsync0()?

    # Of course I have tried, and got no effects.

    #

    # Injected packets return to the DISCARD layer with injectionState = 1 (FWPS_PACKET_INJECTED_BY_SELF) then.

    # So it seems to be hopeless to merely change layer.. but by way of precaution..

     

     

    Ideas to try are invited at the same time!

    Friday, April 11, 2008 9:27 AM
  •  

    I got to know one thing (and as I half expected).

     

    In the INBOUND_IPPACKET_V4 layer, we can get NO TCP Header yet.

    So we cannot modify Source Port there.

     

     

    classifyFn on FWPM_LAYER_INBOUND_IPPACKET_V4

    -------------------------------------------------------------------------------

       //
       // TODO: Perform modification to the cloned net buffer list here.
       //
        for (netBuffer = NET_BUFFER_LIST_FIRST_NB(clonedNetBufferList);
             netBuffer != NULL;
             netBuffer = NET_BUFFER_NEXT_NB(netBuffer))
        {
          TCP_HEADER* tcpHeader = NULL;

          NdisAdvanceNetBufferDataStart(
               netBuffer,
               inMetaValues->ipHeaderSize,
               FALSE,
               NULL
             );

          tcpHeader = NdisGetDataBuffer(
                          netBuffer,
                          sizeof(TCP_HEADER),
                          NULL,
                          sizeof(UINT16),
                          0
                          );

     

          VERIFY(tcpHeader != NULL)  <<<<<<<<< Ouch!

          NdisRetreatNetBufferDataStart(
               netBuffer,
               inMetaValues->ipHeaderSize,
               0,
               NULL
             );
      }

     

     

    .. Currently I am stuck again .

    Friday, April 11, 2008 12:47 PM
  •  

    Now I found a simple possibility.

     

     

    Code Snippet

     

    <<Syn>>
    +--------------+                     +-------------+
    |              |                     |             |
    |  Local Port ---> (Remote Port 80) ----// WFP     |
    |              |                     |             |
    |              |                     |          //----> (Remote Port 81)
    +--------------+                     +-------------+

     

    <<Syn, Ack>>
    +--------------+                     +-------------+
    |              |                     |             |
    |  Local Port (Waiting from 80?)     |     WFP     |
    |              |                     |             |
    |              |                     | DISCARDED // <-- (Remote Port 81)
    +--------------+                     +-------------+

     

     

     

    As I already attempted, discarded [Syn, Ack] cannot be received even after modifying its Source Port.
    Then how about SENDING anew instead of RECEIVING the modified packet?

     

    It sounds worth trying..

    I'll try it now.

    Saturday, April 12, 2008 3:33 AM
  •  

    Yes I tried.. and I'm tired.

     

    As result of FwpsInjectTransportSendAsync0() in DPC procedure, I got 0xC0000225 of netBufferList->Status in completionFn.

     

    In ntstatus.h I found the following definition:

    #define STATUS_NOT_FOUND    ((NTSTATUS)0xC0000225L)

     

    Please let me ask, What are you looking for?

     

    Out of my understanding.. First of all, I'm not sure if it is a valid procedure to call FwpsInjectTransportSendAsync0() in an INBOUND / INBOUND_DISCARD layer.

    (As long as what I have read about FwpsInjectTransportSendAsync0() in the documentations, it is not prohibited.)

     

    I need to check my parameters about this trial, nevertheless I believe still it is the most intuitive among my trials to let the [Syn, Ack] successfully received through FwpsInjectTransportReceiveAsync0() on INBOUND_DISCARD layer.

     

    Should I go back there?

     

    ...

    Or, I think I must use FWPS_LAYER_ALE_AUTH_CONNECT_V4 to control [Syn] and [Syn, Ack].

    With INBOUND/OUTBOUND_TRANSPORT_V4 we cannot do it.

    That sounds true.

    (Perhaps "TRANSPORT" means so? My English skill is not so good ...)

     

     

    Saturday, April 12, 2008 6:23 AM
  •  

    I reviewed "inspect" sample and following functions:

      FwpsPendOperation0()
      FwpsCompleteOperation0()

    to understand FWPS_LAYER_ALE_AUTH_CONNECT_V4.

     

    But how can I change the remote end point?
    Data Offset Positions (NET_BUFFER_LIST structure) at this layer is "Not applicable (For TCP traffic)."
    ( http://msdn2.microsoft.com/en-us/library/aa504926.aspx )

     

    All man can do at this layer is to pend and complete? Really..?


     

    Please tell me what I overlook.

    Thanks.
    Saturday, April 12, 2008 10:48 AM
  • Hi hydrawien,

     

    I think your case is a known bug of WFP about TCP injection.

    If you don't have time to research this issue, you can work it arround with TDI Filter, about which we can get much more informations and samples than WFP at this moment.

     

    Keep in mind, however, TDI Filter is not applicable for SMB 445 protocol on Vista.

     

    Simon

     

    Sunday, April 13, 2008 3:48 AM
  • Hi Simon,

    can you clarify for me this:
    i my oppinion TDI is still supported by Vista, but applications using WinSockets or WinInet can not be filtered by a TDI driver since the Winsock Interface is not implemented by using TDI function calls. Long ago (at least a year) i tried a TDI Filter (works with W2k and XP) under Vista but it didn't catched anything. If TDI is working for WinSock applications, whats about the Winsock Kernel Interface?

    Thanks,

    Jens.
    Monday, April 14, 2008 8:13 AM
  • Hi Jens,

     

    I don't think here is suitable to discuss about it, but I assume that TDI Filter itself is independent of clients' implementation, so that my filter works against browsers, mailers and FTP apps on Vista.

     

    Sorry, but I'm never expert about it and cannot say more.

     

    Thanks
    Simon

    Monday, April 14, 2008 11:49 AM
  •  

    Hi Simon,

     

    Thanks a lot for your reply.

    That is why I can find no examples or no concrete guidance of TCP Injection using WFP.

     

    But the situation is terrible for me, because I need to redirect also packets to 445 ... orz

     

     

     

    Thanks,

    hydrawien

    Monday, April 14, 2008 12:28 PM
  • Hi,

    just to let nobody run in the wrong direction:
    TDI is only supported for old driver using TDI Client interface. A Winsock application does not use TDI anymore, so a TDI filter will not work. (Please read this: http://blogs.msdn.com/wndp/archive/2006/02/24/538746.aspx).

    Jens
    Monday, April 14, 2008 2:27 PM
  • Hi,

     

    Long thread and lots of questions , let me try to answer some of them.

     

    Yes WFP currently lacks connection proxy support and that is in our to-do list.

     

    However you should be able to proxy and un-proxy on a per packet basis. It seems that the proxy part of working for you.

     

    To un-proxy, you could register at TRANSPORT_DISCARD or INBOUND_IPPACKET, grab the packets that need to unproxy and recv-inject them using FwpsInjectTransportReceiveAsync0 or FwpsInjectNetworkReceiveAsync0.

     

    The data offset of packets differ when they are indicated to different layers -- For example, at INBOUND_IPPACKET the offset is at the beginning of Transport Header (after IP header); at INBOUND_TRANSPORT (including DISCARD), the offset is at the beginning of Transport Data (after IP header and Transport Header). the Recv- injection functions require the NBL be positioned at the beginning of the IP header.

     

    See see http://msdn2.microsoft.com/en-us/library/aa504926.aspx for more details.

     

    So from a high lever here is what you need to do (depending on your layer of choice) --

     

    At INBOUND_IPPACKET --

    1. Retreat oiginal NBL/NB by size of inMetaValues->ipHeaderSize
    2. make a clone
    3. Advance the clone by size of inMetaValues->ipHeaderSize
    4. call NdisGetDataBuffer, and this should now point to the TCP header
    5. modify the port; adjust the TCP checksum.
    6. Retreat the clone by the same amount as 3.
    7. Advance the original by the same amount as 1.
    8. FwpsInjectNetworkReceiveAsync0
    9. block and aborb the original NBL.

    At INBOUND_TRANSPORT_/DISCARD --

    1. Retreat oiginal NBL/NB by size of inMetaValues->ipHeaderSize + inMetaValues->transportHeaderSize
    2. make a clone
    3. Advance the clone by size of inMetaValues->ipHeaderSize
    4. call NdisGetDataBuffer, and this should now point to the TCP header
    5. modify the port; adjust the TCP checksum.
    6. Retreat the clone by the same amount as 3.
    7. Advance the original by the same amount as 1.
    8. FwpsInjectTransportReceiveAsync0
    9. block the original NBL.

    Hope this helps,

    Biao.W.

    Monday, April 14, 2008 9:10 PM
  •  

    Hi Biao,

     

    Thanks a lot. Your information contains all that I need.

    If you write a book of WFP, it would be surely interesting (and useful).  

     

     

    Thanks,

    hydrawien

    Thursday, April 17, 2008 10:20 AM
  • It seems like quite a few people including myself are looking for a simple example on redirecting tcp traffic.  I have been fooling with the inspect sample, but cant figure out how to do it.  In my case, I need to create a driver (wfp) that takes all outbout TCP traffic (think browser) and forward it to a transparent proxy.  If you have tips or even better, sample driver that does this, it would be super helpful.

    Thanks,
    Ray
    Tuesday, February 10, 2009 8:32 PM
  • Hi,

    Can anyone tell me does all the tcp injections require a DPC or is it only for tansport injections

    Aravind

    Friday, August 21, 2009 10:19 AM
  • Biao,

    I am doing the same type of TCP proxy, I have it working using the inbound  TRANSPORT_DISCARD  to undo the proxy address so it looks like its coming from the original IP address but would prefer to use or INBOUND_IPPACKET at the network layer. If I do the unproxy and injection at the network layer and IPSec is enabled will the packets be encrypted? or does it get looped back before IPSec?

    Saturday, July 10, 2010 9:12 PM
  • This is an old thread but if you still care I got tcp to work but had to use the inbound transport discard for the unproxy. That was because the response for the sync ack is dropped and not provided to the inbound transport because  the ports were modified and I assume its because there is no flow information for that tuple. Inside the discard you can fixup the port and address so it looks like the orignal tuple then reinject to transport async recieve. Note the pointer did not point to where the docs said it should for the inbound transport discard. I dont have my code here but vaguley remember it pointed to the transport header not the data I could have this backwards.

    I used a work thread at passive level of my own creation to do the injections.

    Saturday, July 10, 2010 9:22 PM