I'm writing a C++ application that uses WSAIoctl/WSARecv, passing the SIO_RCVALL flag to promiscuously intercept all traffic for the purposes of then statefully blocking traffic that does not meet certain criteria.
For the purposes of this example, the traffic should be thought of as UDP traffic on an arbitrary port, say 5000. The desired behaviour is to maintain monitoring capability while dropping the traffic from the perspective of other applications.
I've tried the following approach:
SIO_RCVALL matching rule?
fwpFilter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4;
fwpFilter.flags = FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT;
fwpFilter.action.type = FWP_ACTION_PERMIT;
fwpFilter.subLayerKey = GetSublayerKey();
fwpFilter.weight.type = FWP_UINT8;
fwpFilter.weight.uint8 = 0xF; // High weight
fwpFilter.numFilterConditions = 1;
fwpFilter.filterCondition = fwpFilterConditions;
fwpFilter.displayData.name = const_cast<wchar_t*>(L"Allow Promiscuous");
fwpFilter.displayData.description = const_cast<wchar_t*>(L"Support all traffic capture.");
fwpFilter.flags = FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT; // Prevent BLOCK by other rules/layers?
fwpFilterConditions[0].fieldKey = FWPM_CONDITION_FLAGS;
fwpFilterConditions[0].matchType = FWP_MATCH_FLAGS_ALL_SET;
fwpFilterConditions[0].conditionValue.type = FWP_UINT32;
fwpFilterConditions[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_RAW_ENDPOINT; // Match to raw socket with no further conditions
Traffic-specific rule:
fwpFilter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4;
fwpFilter.action.type = FWP_ACTION_BLOCK;
fwpFilter.subLayerKey = GetSublayerKey();
fwpFilter.weight.type = FWP_UINT8; // Medium Weight
fwpFilter.weight.uint8 = 0xA;
fwpFilter.numFilterConditions = 3;
fwpFilter.filterCondition = fwpFilterConditions;
fwpFilter.displayData.name = const_cast<wchar_t*>(L"Block specific");
fwpFilter.displayData.description = const_cast<wchar_t*>(L"Port/IP specific block.");
fwpFilterConditions[0].fieldKey = FWPM_CONDITION_FLAGS;
fwpFilterConditions[0].matchType = FWP_MATCH_FLAGS_NONE_SET;
fwpFilterConditions[0].conditionValue.type = FWP_UINT32;
fwpFilterConditions[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_RAW_ENDPOINT;
fwpFilterConditions[1].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
fwpFilterConditions[1].matchType = FWP_MATCH_EQUAL;
fwpFilterConditions[1].conditionValue.type = FWP_UINT16;
fwpFilterConditions[1].conditionValue.uint16 = sourcePort;
fwpFilterConditions[2].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS;
fwpFilterConditions[2].matchType = FWP_MATCH_EQUAL;
fwpFilterConditions[2].conditionValue.type = FWP_UINT32;
fwpFilterConditions[2].conditionValue.uint32 = sourceIP;
Some strange behaviour can then be observed: once the rules are in place, the traffic is blocked from all applications while an application is bound to the local port. Upon unbinding, traffic is captured by the application using SIO_RCVALL as expected.
And to clarify, I know this is a less efficient and flexible approach to using callouts, but I'm attempting to avoid utilizing a callout driver if possible. If it's just flat-out not an option, I'll have to explore that route, but I thought I'd sanity-check before heading down that rabbit hole.