Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following sample code demonstrates how to prevent port scanning using stealth discards and silent drops.
#include <windows.h>
#include <fwpmu.h>
#include <stdio.h>
#pragma comment(lib, "fwpuclnt.lib")
#define EXIT_ON_ERROR(fnName) \
if (result != ERROR_SUCCESS) \
{ \
printf(#fnName " = 0x%08X\n", result); \
goto CLEANUP; \
}
DWORD BlockPortScanning(
__in HANDLE engine,
__in PCWSTR filterName,
__in_opt const GUID* providerKey,
__in_opt const GUID* subLayerKey
)
{
DWORD result = ERROR_SUCCESS;
FWPM_FILTER_CONDITION0 conds[1];
FWPM_FILTER0 filter;
BOOL txnInProgress = FALSE;
// Fill in the common fields shared by all our filters.
memset(&filter, 0, sizeof(filter));
// For MUI compatibility, object names should be indirect strings. See
// SHLoadIndirectString for details.
filter.displayData.name = (PWSTR)filterName;
// Link all our objects to our provider. When multiple providers are
// installed on a computer, this makes it easy to determine who added what.
filter.providerKey = (GUID*)providerKey;
// Generally, it's best to add filters to our own sublayer, so we don't have
// to worry about being overridden by filters added by another provider.
if (subLayerKey != NULL)
{
filter.subLayerKey = *subLayerKey;
}
filter.numFilterConditions = 1;
filter.filterCondition = conds;
// We add all the objects from within a single transaction to make it easy
// to clean up partial results in error paths.
result = FwpmTransactionBegin0(engine, 0);
EXIT_ON_ERROR(FwpmTransactionBegin0);
txnInProgress = TRUE;
//////////
// Block outbound ICMP Destination Unreachable to prevent UDP port scanning.
//////////
// ICMP Type == Destination Unreachable.
conds[0].fieldKey = FWPM_CONDITION_ICMP_TYPE;
conds[0].matchType = FWP_MATCH_EQUAL;
conds[0].conditionValue.type = FWP_UINT16;
conds[0].conditionValue.uint16 = 3;
filter.action.type = FWP_ACTION_BLOCK;
// Add the IPv4 filter.
filter.layerKey = FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Add the IPv6 filter.
filter.layerKey = FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
//////////
// Block outbound TCP RST to prevent TCP port scanning.
//////////
// We don't want to block TCP RST for loopback, so use a condition that
// matches everything but loopback.
conds[0].fieldKey = FWPM_CONDITION_FLAGS;
conds[0].matchType = FWP_MATCH_FLAGS_NONE_SET;
conds[0].conditionValue.type = FWP_UINT32;
conds[0].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK;
filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
// Add the IPv4 filter.
filter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD;
filter.action.calloutKey = FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V4_SILENT_DROP;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Add the IPv6 filter.
filter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD;
filter.action.calloutKey = FWPM_CALLOUT_WFP_TRANSPORT_LAYER_V6_SILENT_DROP;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Once all the adds have succeeded, we commit the transaction to atomically
// add all the new objects.
result = FwpmTransactionCommit0(engine);
EXIT_ON_ERROR(FwpmTransactionCommit0);
txnInProgress = FALSE;
CLEANUP:
if (txnInProgress)
{
// Abort any transaction still in progress to clean up partial results.
FwpmTransactionAbort0(engine);
}
return result;
}
Related topics