locked
WFP and closed vs filtered ports RRS feed

  • Question

  • I have filters applied to the ALE AUTH_RECV_ACCEPT and CONNECT layers, and I find that if no one is listening to the port, a portscan returns that the port is "closed" (ie, an RST is transmitted in response to a SYN), while if someone is listening the port is "filtered" (the SYN is dropped).  This begs a couple of questions.

     

    1. How can I cause closed ports to be filtered?  I know about the _DISCARD layers, can I just return ACTION_BLOCK at the discard layer (or add filters there), or is there some other way?
    2. How can I cause filtered ports to be closed?  Is there some way to change the discard reason when a block happens to make the tcp/ip stack respond as though nobody was listening, sending either an RST or an ICMP port unreachable?

    Is there any way to do the above using just usermode code, or will I need a custom callout?

     

    Thanks,

    Jeremy

    Monday, October 8, 2007 9:04 PM

Answers

  • 1.

     

    For TCP you can register a callout at INBOUND_TRANSPORT_V{4|6}_DISCARD and blocks the classify when the discard reason is InetDiscardEndpointNotFound. There is a built-in callout that does exact that so you can simply point your filter to FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V{4|6}_SILENT_DROP instead.

     

    For UDP you would need to register at INBOUND_IPPACKET_V{4|6}_DISCARD and blocks the classify when the discard reason is IpDiscardPortUnreachable. Unfortunately there is no built-in callout to perform such function.

     

    The difference between TCP and UDP is because in Vista the Transport Layer of the TCP/IP stack handles TCP RSTs while the Network Layer handles all ICMP responses. The decision whether to send RST/ICMP is made during inbound processing hence you would return BLOCK form the inbound layers above.

     

    Of course RST/ICMPs are just packets so you could instead block them at OUBOUND_TRANSPORT/IPPACKET or OUTBOUND_ICMP_ERROR layers. But that wouldn't be as efficient because the cost for generating the response messages would incur.

     

     

    2.

     

    This is not currently doable except you generate a RST or ICMP-error and send-inject it. (this is an interesting feedback though and I'll keep a note).

     

    Thanks,

    Biao.W.

    Tuesday, October 9, 2007 5:12 AM
  •  

    I see the online docs have changed significantly from what I downloaded in the Windows SDK Update for Vista.  There is actually a sample now on how to do the stealth discards.

     

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

     

    Thanks,

     

     

    Tuesday, October 9, 2007 7:09 PM

All replies

  • 1.

     

    For TCP you can register a callout at INBOUND_TRANSPORT_V{4|6}_DISCARD and blocks the classify when the discard reason is InetDiscardEndpointNotFound. There is a built-in callout that does exact that so you can simply point your filter to FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V{4|6}_SILENT_DROP instead.

     

    For UDP you would need to register at INBOUND_IPPACKET_V{4|6}_DISCARD and blocks the classify when the discard reason is IpDiscardPortUnreachable. Unfortunately there is no built-in callout to perform such function.

     

    The difference between TCP and UDP is because in Vista the Transport Layer of the TCP/IP stack handles TCP RSTs while the Network Layer handles all ICMP responses. The decision whether to send RST/ICMP is made during inbound processing hence you would return BLOCK form the inbound layers above.

     

    Of course RST/ICMPs are just packets so you could instead block them at OUBOUND_TRANSPORT/IPPACKET or OUTBOUND_ICMP_ERROR layers. But that wouldn't be as efficient because the cost for generating the response messages would incur.

     

     

    2.

     

    This is not currently doable except you generate a RST or ICMP-error and send-inject it. (this is an interesting feedback though and I'll keep a note).

     

    Thanks,

    Biao.W.

    Tuesday, October 9, 2007 5:12 AM
  •  

    I see the online docs have changed significantly from what I downloaded in the Windows SDK Update for Vista.  There is actually a sample now on how to do the stealth discards.

     

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

     

    Thanks,

     

     

    Tuesday, October 9, 2007 7:09 PM
  •  Biao Wang [MSFT] wrote:

    For TCP you can register a callout at INBOUND_TRANSPORT_V{4|6}_DISCARD and blocks the classify when the discard reason is InetDiscardEndpointNotFound. There is a built-in callout that does exact that so you can simply point your filter to FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V{4|6}_SILENT_DROP instead.

     

    That works great, thanks.

     

     Biao Wang [MSFT] wrote:

    For UDP you would need to register at INBOUND_IPPACKET_V{4|6}_DISCARD and blocks the classify when the discard reason is IpDiscardPortUnreachable. Unfortunately there is no built-in callout to perform such function.

     

    This also works, sort of.  At the IPPACKET_V{4|6}_DISCARD layers, it is not supported to filter on the local and remote ports.  If I only want global blocks (ie, all UDP or even all protocols), then this works out OK.

     

    This limitation also affects another callout of mine, which wants to know about failed connection attempts (which I talk about on the "INBOUND_TRANSPORT_V4 layer indications" thread).  I can get the information I need for TCP, but I cannot get the information for UDP, since I would have to register at the INBOUND_IPPACKET_V4_DISCARD layer, and then cannot get the local and remote port in my callout short of parsing the UDP header myself.

     

    You may want to look into, in future versions of WFP, indicating TCP and UDP "nobody's listening" failures to the same place, and providing full information for both.

    Wednesday, October 10, 2007 7:08 PM
  • Yup this makes sense.

     

    Copied-and-pasted this to the improvement thread upstairs.

     

    Thanks,

    Biao.W.

    Thursday, October 11, 2007 1:19 AM
  • Hello,

     sorry to wake up this old thread, but I have one more question about handling the discard callout for UDP. I need to know the UDP ports when processing the callout. As was already written, this information is not directly provided, because UDP must be handled at the IPPACKET level. Parsing the UDP header manually is easy, but there is another problem: the data offset position for INBOUND_IPPACKET_V4_DISCARD is said to be "variable". It seems that when the discard reason is IpDiscardPortUnreachable, the data offset position is always at the beginning of UDP header (after the IP header). But can we rely on this? Or is it possible to handle the variable offset in some reliable way? Iow, how can I reliably find the UDP header, when the offset is not known?

    Thanks in advance for Your answer,

    Ron
    Tuesday, October 13, 2009 2:25 PM
  • Ping.

    Sorry if I am impatient, I just don't want my question to get lost.
    Tuesday, October 20, 2009 3:14 PM