none
Filtering (ip adrr and mask, protocol(tcp/udp), source port range, destination port range) RRS feed

  • Question

  • I am new to WFP and writing a simple packet filter firewall (user mode)  and i wish to filter traffic based on ip address and mask(subnet), source and destination port ranges and protocol(tcp/udp)

    With the following code i am getting a FWP_E_CONDITION_NOT_FOUND not found error on FwpmFilterAdd0()

    What am i doing wrong? Am i adding it in the wrong layer? Are my filter conditions not valid in this layer. I have tried this in both

    FWPM_LAYER_OUTBOUND_TRANSPORT_V4
    and
    FWPM_LAYER_ALE_AUTH_CONNECT_V4
    layers

    Code:

    ///Some code....

    FWPM_FILTER0 NewFilter = {0};
            FWPM_FILTER_CONDITION0 Condition[4];
            //Assigning the port ranges to the conditions
            //Auto weighting by the BFE will give the more specific rule higher weightage.
            //////////////////////////////////////////////////////////////////////////////
            FWP_RANGE0 srcPortRange;
            FWP_RANGE0 dstPortRange;
            //Source port
            srcPortRange.valueLow.type = FWP_UINT16;
            srcPortRange.valueLow.uint16 = pConfig->m_srcPort;
            srcPortRange.valueHigh.type = FWP_UINT16;
            srcPortRange.valueHigh.uint16 = pConfig->m_srcPortRange;
            //Destination port
            dstPortRange.valueLow.type = FWP_UINT16;
            dstPortRange.valueLow.uint16 = pConfig->m_dstPort;
            dstPortRange.valueHigh.type = FWP_UINT16;
            dstPortRange.valueHigh.uint16 = pConfig->m_dstPortRange;
            UINT64 ui64FilterId;
            Condition[1].conditionValue.type = FWP_RANGE_TYPE;
            Condition[1].conditionValue.rangeValue = &srcPortRange;
            Condition[1].matchType = FWP_MATCH_RANGE;
            Condition[2].conditionValue.type = FWP_RANGE_TYPE;
            Condition[2].conditionValue.rangeValue = &dstPortRange;
            Condition[2].matchType = FWP_MATCH_RANGE;
            if(pConfig->m_bIn)
            {
                Condition[1].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
                Condition[2].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
            }
            else
            {
                Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
                Condition[2].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
            }
            ///////////////////////////////////////////////////////////////////////////////

            //Assining IP address and subnet to the condition
            ///////////////////////////////////////////////////////////////////////////////
            if(pConfig->m_dwIpVersion == AF_INET)
            {
                FWP_V4_ADDR_AND_MASK Addr;
               
                UINT32 IpAddr;
                UINT32 Mask;

                inet_pton( AF_INET, pConfig->m_szRemoteHost, &IpAddr );
                inet_pton( AF_INET, pConfig->m_szMask, &Mask );

                Addr.addr = ntohl(IpAddr);
                Addr.mask = ntohl(Mask);

                Condition[0].conditionValue.type = FWP_V4_ADDR_MASK;
                Condition[0].conditionValue.v4AddrMask = &Addr;
                if(pConfig->m_bIn)
                {
                    Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS_V4;   
                }
                else
                {
                    Condition[0].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS_V4;
                }
            }
            else if(pConfig->m_dwIpVersion == AF_INET6)
            {
                FWP_V6_ADDR_AND_MASK Addr;

                UINT8 IpAddrV6[FWP_V6_ADDR_SIZE];

                inet_pton( AF_INET6, pConfig->m_szRemoteHost, &IpAddrV6 );
               
                for(int i = 0; i <= FWP_V6_ADDR_SIZE - 1; i++)
                {
                    Addr.addr[i] = IpAddrV6[FWP_V6_ADDR_SIZE - 1 - i];
                }

                Addr.prefixLength = pConfig->m_ui8PrefixLength;

                Condition[0].conditionValue.type = FWP_V6_ADDR_MASK;
                Condition[0].conditionValue.v6AddrMask = &Addr;

                if(pConfig->m_bIn)
                {
                    Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS_V6;   
                }
                else
                {
                    Condition[0].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS_V6;
                }
            }
            else
            {
                return FALSE;
            }
            Condition[0].matchType = FWP_MATCH_EQUAL;
            ///////////////////////////////////////////////////////////////////////////////

            NewFilter.displayData.name = L"Custom Filter";
            NewFilter.displayData.description = L"Filter for TCP/UDP/IPSEC/ICMP etc.";
            NewFilter.flags = FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT;
            NewFilter.weight.type = FWP_UINT8;
               
            if(pConfig->m_bPermit)
            {
                NewFilter.action.type = FWP_ACTION_PERMIT;
                NewFilter.weight.uint8 = 0x06;
                NewFilter.subLayerKey = PermitSubLayer->subLayerKey;       
            }
            else
            {
                NewFilter.action.type = FWP_ACTION_BLOCK;
                NewFilter.weight.uint8 = 0x02;
                NewFilter.subLayerKey = BlockSubLayer->subLayerKey;
            }  

    ///some cases for ICMP traffic that i'm filtering based on ICMP type.....

    case VISTA_TCP:
                case VISTA_UDP:
                    if(pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET)
                    {
                        NewFilter.layerKey = FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
                    }
                    else if(pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET6)
                    {
                        NewFilter.layerKey = FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6;
                    }
                    else if(!pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET)
                    {
                        NewFilter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
                    }
                    else if(!pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET6)
                    {
                        NewFilter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
                    }
                    /*else if(pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET)
                    {
                        NewFilter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4;
                    }
                    else if(!pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET)
                    {
                        NewFilter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
                    }
                    else if(pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET6)
                    {
                        NewFilter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V6;
                    }
                    else if(!pConfig->m_bIn && pConfig->m_dwIpVersion == AF_INET6)
                    {
                        NewFilter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
                    }*/
                    else
                    {
                        return FALSE;
                    }

                    Condition[3].conditionValue.type = FWP_UINT8;
                    Condition[3].conditionValue.uint8 = pConfig->m_dwProtocols;
                    Condition[3].matchType = FWP_MATCH_EQUAL;
                    Condition[3].fieldKey = FWPM_CONDITION_IP_PROTOCOL;

                    NewFilter.numFilterConditions = 4;
                    NewFilter.filterCondition = Condition;
                   
    ///////////////////////////////////////////////////////////////////////////////////
    ////////////////////Failing here, Condition not found//////////////////////
    ///////////////////////////////////////////////////////////////////////////////////
                    dwFilterRes = FwpmFilterAdd0(
                            m_hEngine,
                            &NewFilter,
                            NULL,
                            &ui64FilterId
                        );

                    if(dwFilterRes != ERROR_SUCCESS)
                    {
                        dwTrxRes = FwpmTransactionAbort0(m_hEngine);
                        return FALSE;
                    }
    ////////////////////////////////////////////////////////////////////////////////////
                    break;


    Any help will be hugely appreciated. Thanks!


    Friday, March 13, 2009 7:48 AM

Answers

  • Hi Sujoyks,
    Please check http://msdn.microsoft.com/en-us/library/aa504900.aspx to understand what all conditions are available at any specififc layer. Your condition[0] looks wrong.

    • Marked as answer by sujoyks Friday, March 13, 2009 6:24 PM
    Friday, March 13, 2009 5:52 PM
  • Rather than a range using 1 - 65535, why not use FWP_MATCH_GREATER for that condition
    FWPM_FILTER_CONDITION0 portsFC = {0};
    portsFC.fieldKey              = FWPM_CONDITION_IP_REMOTE_PORT;
    portsFC.matchType             = FWP_MATCH_GREATER;
    portsFC.conditionValue.type   = FWP_UINT16;
    portsFC.conditionValue.uint16 = 0;

    FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT is only useful if using a callout.

    when you only pass the 1 filtercondition, do you change the numFilterConditions to 1?  FWP_E_INVALID_ENUMERATOR would be returned if the filterCondition.conditionValue.type is invalid.

    Filter arbitration is performed at each layer.  this allows you to have the conflicted filters.  So you can allow a packet at RECV, yet have it Blocked by INBOUND TRANSPORT.
    In a non-TCP case, INBOUND_IPPACKET gets invoked, then INBOUND_TRANSPORT which blocks the traffic.  THis means RECV_ACCEPT would not get invoked.
    http://msdn.microsoft.com/en-us/library/bb451831(VS.85).aspx has more information.


    Yes all of your filters can be placed in the same sublayer.  WFP will handle the weighting an all arbitration logic per the information you provided in teh FWPM_FILTER0 object.
    To ensure your filters have a "voice" in the filtering decision, you should create your own sublayer and place your filters in it.http://msdn.microsoft.com/en-us/library/aa364008(VS.85).aspx has more details.


    Dusty Harper [MSFT]
    • Marked as answer by sujoyks Saturday, March 14, 2009 6:26 AM
    Saturday, March 14, 2009 6:06 AM
    Moderator

All replies

  • Sorry. Just wanted to add that i am checking inbound and outbound flows and i gather the ALE layers are the ones i need to be in to filter traffic like this. Now, what happens if i have conflicting filters in FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_Vx and FWPM_LAYER_INBOUND_TRANSPORT_Vx? Which one is acted on?

    Can i add all my filters  in the same sublayer? Will BFE be able to assign the weights properly based on which one is more specific and and take care of all my filter arbitration from there?

    Example:

    Block traffic inbound on ports 80 to 8080 from ip address x.x.x.x subnet 255.255.255.0 if the protocol is TCP
    Allow traffic inbound on port 8000 from ip address x.x.x.y subnet 255.255.255.255 if the protocol is TCP

    Will it be able to resolve this if the filters are added to the same sublayer? right now i'm adding sublayer to add blocking filters which are more general. this sublayer has lower weight and doing similar thing for permitting filters which are more specific for specific exceptions and adding that to a sublayer with higher weight.... Is that a good practice and again should i be doing this in the same sublayer?

    How does giving the address and mask as 0.0.0.0 affect the behaviour of the filters? will it then block all traffic as it should?

    Phew! Ok Ok Ok... Sorry i added so much more but there aren't absolute clear cut answers in the documentation


    Friday, March 13, 2009 9:02 AM
  • Hi Sujoyks,
    Please check http://msdn.microsoft.com/en-us/library/aa504900.aspx to understand what all conditions are available at any specififc layer. Your condition[0] looks wrong.

    • Marked as answer by sujoyks Friday, March 13, 2009 6:24 PM
    Friday, March 13, 2009 5:52 PM
  • OOPS!!!

    It's FWPM_CONDITION_IP_LOCAL_ADDRESS
    and
    FWPM_CONDITION_IP_REMOTE_ADDRESS

    Not
    FWPM_CONDITION_IP_LOCAL_ADDRESS_Vx
    and
    FWPM_CONDITION_IP_REMOTE_ADDRESS_Vx

    Thanks!!!!

    Also can i just ask one more question(maybe more later) and could you please answer the other questions i asked.... Thanks

    If i add Condition[1] only i get a FWP_E_INVALID_ENUMERATOR error
    I'm giving port range as 1 to 65535. Does the rest of the code look  ok?

    Thanks for the quick and Effective reply
    Friday, March 13, 2009 6:24 PM
  • Rather than a range using 1 - 65535, why not use FWP_MATCH_GREATER for that condition
    FWPM_FILTER_CONDITION0 portsFC = {0};
    portsFC.fieldKey              = FWPM_CONDITION_IP_REMOTE_PORT;
    portsFC.matchType             = FWP_MATCH_GREATER;
    portsFC.conditionValue.type   = FWP_UINT16;
    portsFC.conditionValue.uint16 = 0;

    FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT is only useful if using a callout.

    when you only pass the 1 filtercondition, do you change the numFilterConditions to 1?  FWP_E_INVALID_ENUMERATOR would be returned if the filterCondition.conditionValue.type is invalid.

    Filter arbitration is performed at each layer.  this allows you to have the conflicted filters.  So you can allow a packet at RECV, yet have it Blocked by INBOUND TRANSPORT.
    In a non-TCP case, INBOUND_IPPACKET gets invoked, then INBOUND_TRANSPORT which blocks the traffic.  THis means RECV_ACCEPT would not get invoked.
    http://msdn.microsoft.com/en-us/library/bb451831(VS.85).aspx has more information.


    Yes all of your filters can be placed in the same sublayer.  WFP will handle the weighting an all arbitration logic per the information you provided in teh FWPM_FILTER0 object.
    To ensure your filters have a "voice" in the filtering decision, you should create your own sublayer and place your filters in it.http://msdn.microsoft.com/en-us/library/aa364008(VS.85).aspx has more details.


    Dusty Harper [MSFT]
    • Marked as answer by sujoyks Saturday, March 14, 2009 6:26 AM
    Saturday, March 14, 2009 6:06 AM
    Moderator
  • Thank you! Thanks again for the great reply.

    The reason i was using the range type is because this is code is part of a method to which i or user pass range of ports. Only in my case i was using 1-65535.

    FWP_RANGE0 srcPortRange;       
    srcPortRange.valueLow.type = FWP_UINT16;
    srcPortRange.valueLow.uint16 = pConfig->m_srcPort; //Lower port
    srcPortRange.valueHigh.type = FWP_UINT16;
    srcPortRange.valueHigh.uint16 = pConfig->m_srcPortRange; //Higher port
           
    Condition[1].conditionValue.type = FWP_RANGE_TYPE;
    Condition[1].conditionValue.rangeValue = &srcPortRange;
    Condition[1].matchType = FWP_MATCH_RANGE;

    Is that right? Actually i don't have access to my computer where i have the actual project so i can't check it's working right now...

    I guess i have it pretty much sorted out now anyway.

    Thanks a lot for all your help.
           
    Saturday, March 14, 2009 6:24 AM
  • Yes the creation of the FWP_RANGE is correct.  The comment was geared around populating it with the entire range.
    Dusty Harper [MSFT]
    Sunday, March 15, 2009 2:26 AM
    Moderator