如果要支持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();
}