WFP过滤开发(一)

 如果要支持win8/Win10的驱动开发,建议搭建VS2015+WDK10的开发环境,搭建的时候注意SDK和WDK的版本一定要匹配,否则会出现找不到头文件的各种错误。
    https://docs.microsoft.com/zh-cn/windows-hardware/drivers/network/using-bind-or-connect-redirection(TCP重定向)

严格的按照这篇文件所描述的步骤进行实现即可:


#if(NTDDI_VERSION >= NTDDI_WIN8)   ----- 在win7中,这个实现机制不一样,win7就直接重定向过去了,没有再次进入到这个classfyfn中来, 而win8之后,还会进入到这里。

FWPS_CONNECTION_REDIRECT_STATE redirectionState = FWPS_CONNECTION_NOT_REDIRECTED;

if (FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_REDIRECT_RECORD_HANDLE))
{
VOID* pRedirectContext = NULL;

redirectionState = FwpsQueryConnectionRedirectState(inMetaValues->redirectRecords,
g_hredirecthandle,
&pRedirectContext);
}

switch (redirectionState)
{
/// Go ahead and continue with our redirection
case FWPS_CONNECTION_NOT_REDIRECTED:
case FWPS_CONNECTION_REDIRECTED_BY_OTHER:
{
KdPrint(("*AleConnectionRedirectClassify not redirected, goto redirect handler!"));
break;
}
/// We've already seen this, so let it through
case FWPS_CONNECTION_REDIRECTED_BY_SELF:
{
classifyOut->actionType = FWP_ACTION_PERMIT;
KdPrint(("*AleConnectionRedirectClassify redirect by self ,permit it !"));
goto Exit;
}
/// Must not perform redirection. In this case we are letting the last redirection action win.
case FWPS_CONNECTION_PREVIOUSLY_REDIRECTED_BY_SELF:
{
KdPrint(("*AleConnectionRedirectClassify redirect by self previously, exit!"));
goto Exit;
}
}
#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
    Status = FwpsAcquireClassifyHandle((void*)classifyContext,
        0,
        &ClassifyHandle);
    if (Status != STATUS_SUCCESS)
    {
        KdPrint(("FwpsAcquireClassifyHandle error!status=%#x\n", Status));
        goto Exit;
    }
    Status = FwpsAcquireWritableLayerDataPointer(ClassifyHandle,
                        filter->filterId,
                        0,
                        &WriteableLayerData,
                        classifyOut 
                        );
    if ( Status != STATUS_SUCCESS )
    {
        KdPrint(("FwpsAcquireWritableLayerDataPointer error!status=%#x\n", Status));

        goto Exit;
    }
    if (inFixedValues->incomingValue[FWPS_FIELD_ALE_CONNECT_REDIRECT_V4_FLAGS].value.uint32 & FWP_CONDITION_FLAG_IS_REAUTHORIZE)
    {
        pConnectRequest = ((FWPS_CONNECT_REQUEST*)(WriteableLayerData))->previousVersion;

        if ( pConnectRequest->modifierFilterId == filter->filterId )
        {
            classifyOut->actionType = FWP_ACTION_PERMIT;
            classifyOut->rights      |= FWPS_RIGHT_ACTION_WRITE;
            goto Exit;
        }
    }

    for (pConnectRequest = ((FWPS_CONNECT_REQUEST*)(WriteableLayerData))->previousVersion;
                pConnectRequest;
                pConnectRequest = pConnectRequest->previousVersion)
    {
        if (pConnectRequest->modifierFilterId == filter->filterId)
         timesRedirected++;

        if (timesRedirected > 3)
        {
         Status = STATUS_TOO_MANY_COMMANDS;
         goto Exit;
        }
    }

    pConnectRequest = (FWPS_CONNECT_REQUEST*)WriteableLayerData;

#if(NTDDI_VERSION >= NTDDI_WIN8)
/// Set redirectHandle only if proxying locally
if (g_hredirecthandle)
pConnectRequest->localRedirectHandle = g_hredirecthandle;


pSockAddrStorage = ExAllocatePool(NonPagedPool, 2 * sizeof(SOCKADDR_STORAGE));

/// Pass original remote destination values to query them in user mode
RtlCopyMemory(&(pSockAddrStorage[0]),
&(pConnectRequest->remoteAddressAndPort),
sizeof(SOCKADDR_STORAGE));

RtlCopyMemory(&(pSockAddrStorage[1]),
&(pConnectRequest->localAddressAndPort),
sizeof(SOCKADDR_STORAGE));

/// WFP will take ownership of this memory and free it when the flow / redirection terminates
pConnectRequest->localRedirectContext = pSockAddrStorage;
pConnectRequest->localRedirectContextSize = sizeof(SOCKADDR_STORAGE) * 2;

#endif /// (NTDDI_VERSION >= NTDDI_WIN8)

    remoteipaddr = ((PSOCKADDR_IN)&(pConnectRequest->remoteAddressAndPort))->sin_addr.S_un.S_addr;
    remotePort    = ((PSOCKADDR_IN)&(pConnectRequest->remoteAddressAndPort))->sin_port;
    localipaddr    = ((PSOCKADDR_IN)&(pConnectRequest->localAddressAndPort))->sin_addr.S_un.S_addr;
    localport       = ((PSOCKADDR_IN)&(pConnectRequest->localAddressAndPort))->sin_port;

DbgPrint("*AleConnectionRedirectClassify %8x:%d -->%08x:%d ,enable=[%d]",
localipaddr,ntohs(localport), remoteipaddr, ntohs(remotePort), gMatchEnable);
    if ( RULE_CHECK_OK ==  RuleEntryCheckIPIsMatch(remoteipaddr, Protocol) && (gMatchEnable == RULE_MATCH_ENABLE) )
    {
        DbgPrint("Ale Redirect connection Rule is Match![pto=%d] %08x:%d --> %08x:%d", 
                    Protocol, ntohl(localipaddr), ntohs(localport), 
                    ntohl(remoteipaddr), ntohs(remotePort));
        if (INETADDR_ISANY((PSOCKADDR)&(pConnectRequest->localAddressAndPort)))
        {
            INETADDR_SETLOOPBACK((PSOCKADDR)&(pConnectRequest->remoteAddressAndPort));
        }
        else
        {
            INETADDR_SET_ADDRESS((PSOCKADDR)&(pConnectRequest->remoteAddressAndPort),
            INETADDR_ADDRESS((PSOCKADDR)&(pConnectRequest->localAddressAndPort)));
        }
        
 INETADDR_SET_ADDRESS((PSOCKADDR)&(pConnectRequest->remoteAddressAndPort), (CHAR *)&gLocalSockaddr);
        INETADDR_SET_PORT((PSOCKADDR)&(pConnectRequest->remoteAddressAndPort), RegEditGetTcpLocalPort());
        pConnectRequest->localRedirectTargetPID = RegEditGetLocalServerPID();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值