In my callout driver, I want to add filter conditions to filter HTTP/HTTPS
packets to a specified IP address. I set up a filter and add two conditions
with the fieldKey set to FWPM_CONDITION_IP_REMOTE_PORT that specify the
HTTP/HTTPS port values (0x50 or 0x1bb). According to the WDK documentation,
BFE should evaluate these conditions as an “OR” instead of “AND”.
The problem is I only see packets that match the first
FWPM_CONDITION_IP_REMOTE_PORT condition. If I set the first
FWPM_CONDITION_IP_REMOTE_PORT condition for HTTP, I get HTTP packets but not
HTTPS. If I set the first condition for HTTPS, I get HTTPS packets but not
HTTP.
I believe that I’m setting up the filter correctly, but can someone see what
is wrong? The following is the code, with proprietary settings (e.g.,
strings, etc.) removed:
// Initialize the locals.
RtlZeroMemory(&filter, sizeof(filter));
// Don’t set filter.filterKey. BFE will assign a unique one.
filter.displayData.name = L"My string1";
filter.displayData.description = L"My string2";
filter.flags = 0;
filter.providerKey = (GUID *)&MY_PROVIDER;
filter.providerData = blob;
filter.layerKey = *pLayerKey;
filter.subLayerKey = MY_SUBLAYER;
filter.weight.type = FWP_EMPTY; // auto-weight.
filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
filter.action.calloutKey = *pCalloutKey;
filter.rawContext = 0;
DBG_ASSERT(pRemoteAddr != NULL);
//
// Define the filter conditions.
// Filters at this layer are for TCP packets from a specified IP
address
//
RtlZeroMemory(filterConditions, sizeof(filterConditions));
numFilterConditions = 0;
filterConditions[numFilterConditions].fieldKey =
FWPM_CONDITION_IP_REMOTE_ADDRESS;
filterConditions[numFilterConditions].matchType = FWP_MATCH_EQUAL;
if (IsEqualGUID(pCalloutKey,
&STADRV_OUTBOUND_TRANSPORT_CALLOUT_V4))
{
filterConditions[numFilterConditions].conditionValue.type =
FWP_UINT32;
filterConditions[numFilterConditions].conditionValue.uint32 =
*(UINT32 *)pRemoteAddr;
}
else
{
filterConditions[numFilterConditions].conditionValue.type
= FWP_BYTE_ARRAY16_TYPE;
filterConditions[numFilterConditions].conditionValue.byteArray16
= (FWP_BYTE_ARRAY16 *)pRemoteAddr;
}
numFilterConditions++;
filterConditions[numFilterConditions].fieldKey =
FWPM_CONDITION_IP_PROTOCOL;
filterConditions[numFilterConditions].matchType =
FWP_MATCH_EQUAL;
filterConditions[numFilterConditions].conditionValue.type =
FWP_UINT8;
filterConditions[numFilterConditions].conditionValue.uint8 =
IPPROTO_TCP;
numFilterConditions++;
//
// Note: Our filters include two conditions for port inspection.
// For Windows 7 and later, we can combine these two conditions
// in the same filter object. For Vista and Vista SP1, these
require
// separate filter objects.
//
if (Globals.NdisVersion >= NDIS_VERSION_6_2)
{
//
// Starting with Windows 7, filter conditions with the same
fieldKey are interpreted as
// an “OR” condition.
//
filterConditions[numFilterConditions].fieldKey =
FWPM_CONDITION_IP_REMOTE_PORT;
filterConditions[numFilterConditions].matchType =
FWP_MATCH_EQUAL;
filterConditions[numFilterConditions].conditionValue.type =
FWP_UINT16;
filterConditions[numFilterConditions].conditionValue.uint16 =
TCP_PORT_HTTP;
numFilterConditions++;
filterConditions[numFilterConditions].fieldKey =
FWPM_CONDITION_IP_REMOTE_PORT;
filterConditions[numFilterConditions].matchType =
FWP_MATCH_EQUAL;
filterConditions[numFilterConditions].conditionValue.type =
FWP_UINT16;
filterConditions[numFilterConditions].conditionValue.uint16 =
TCP_PORT_HTTPS;
numFilterConditions++;
}
filter.filterCondition = filterConditions;
filter.numFilterConditions = numFilterConditions;
status = FwpmFilterAdd0(
pWfpInfo->EngineHandle,
&filter,
NULL,
&pFilterId);
if (!NT_SUCCESS(status))
{
goto exit;
}