首页 > 解决方案 > 使用 WFP 重定向 DNS 流量

问题描述

我是 StackOverflow 的新手。现在我面临着这篇文章中描述的类似问题:Cisco AnyConnect VPN 兼容性问题。我试图应用那里发布的解决方案,但我无法让它发挥作用,所以我希望能得到一些关于可能发生的事情以及如何让它发挥作用的指针。让我描述一下我正在尝试做的事情:

       void classifyFunc(...)
{
  NET_BUFFER_LIST * netBufferList = (NET_BUFFER_LIST *)layerData;
  // Verify that the packet wasn't injected before
  FWPS_PACKET_INJECTION_STATE packetState = FwpsQueryPacketInjectionState(injectionNetworkHandle, netBufferList, NULL);
  if (packetState == FWPS_PACKET_INJECTED_BY_SELF || packetState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF) 
  {
    classifyOut->actionType = FWP_ACTION_PERMIT;
    if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)
    {
        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    }
    return;
  }

  MetadataValues* metadataValues = ExAllocatePoolWithTag(NonPagedPool, sizeof(MetadataValues), SOME_TAG);
 // Get all information needed for redirection (compartmentId, interfaceIndex, subInterfaceIndex, IpHeaderSize, etc) and stored it on metadataValues

 // Block-adsorb the original NET_BUFFER_LIST and queued it to be processed by a worker thread
  FwpsReferenceNetBufferList(netBufferList, TRUE);
  classifyOut->actionType = FWP_ACTION_BLOCK;
  classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
  classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;

 // Queue the packet to be modified out of bounds by a worker thread.
  addPacketToWorkerQueue(netBufferList, metadataValues); 
}

void workerThreadFunc(NET_BUFFER_LIST * netBufferList, MetadataValues * metadataValues) //this Is the function that the worker thread executes to modify and re-inject the packet
{
   //Retread the NET_BUFFER_LIST by the amount specified in inMetadataValues->ipHeaderSize
   // Cloned it and advance the original NET_BUFFER_LIST to its original position.
   NET_BUFFER_LIST * clonedBufferList;
   NDIS_STATUS ndis_status = NdisRetreatNetBufferListDataStart(netBufferList, metadataValues->ipHeaderSize, 0, NULL, NULL);
   status = FwpsAllocateCloneNetBufferList(netBufferList, NULL, NULL, 0, &clonedBufferList);
   NdisAdvanceNetBufferListDataStart(netBufferList, metadataValues->ipHeaderSize, FALSE, NULL);

  // Advance the cloned NET_BUFFER_LIST to the transport header
  NET_BUFFER * netBuffer = NET_BUFFER_LIST_FIRST_NB(clonedBufferList);
  NdisAdvanceNetBufferDataStart(netBuffer, metadataValues->ipHeaderSize, FALSE, NULL); 
  // Get the UDP header and modify the source port
  UDP_HEADER * udpHeader = (UDP_HEADER *)NdisGetDataBuffer(netBuffer, sizeof(UDP_HEADER), NULL, sizeof(UINT16), 0);
  udpHeader->srcPort = RtlUshortByteSwap(53);
   // Go back to the beginning of the IP Header
  ndis_status = NdisRetreatNetBufferDataStart(netBuffer, metadataValues->ipHeaderSize, 0, NULL); 

  // Get the IP header and modify the source and destination ip addresses
  UINT32 source = RtlUlongByteSwap(originalDNS);
  UINT32 destiny = RtlUlongByteSwap(nicIpAddress);
  IP_HEADER_V4 * ipHeader = (IP_HEADER_V4 *)NdisGetDataBuffer(netBuffer, metadataValues->ipHeaderSize, NULL, sizeof(UINT16), 0);
  RtlCopyMemory(ipHeader->pSourceAddress, &source, sizeof(UINT32));
  RtlCopyMemory(ipHeader->pDestinationAddress, &destiny, sizeof(UINT32));

  // Finally fix the IpHeader Checksum
  fixIpChecksum(ipHeader, metadataValues->ipHeaderSize); 

  //Inject the modified NET_BUFFER_LIST

  FwpsInjectNetworkReceiveAsync(
         injectionNetworkHandle, //This injection handle was created using the FWPS_INJECTION_TYPE_NETWORK flag 
         NULL,
         0,
         metadataValues->compartmentId,
         metadataValues->interfaceIndex, 
         metadataValues->subInterfaceIndex, 
         clonedBuffer, 
         InjectToDNSClientCompleteFunc, 
         NULL); 
}
To recalculate the Ip Header checksum I am using this function:

void fixIpChecksum(IP_HEADER_V4* ipHeader, UINT32 size)
{
    UINT32            sum = 0;
    UINT32            words = size / 2;
    UINT16 UNALIGNED* pStart = (UINT16*)ipHeader;
    ipHeader->checksum = 0;
    for (UINT8 i = 0; i < words; i++)
    {
          sum += pStart[i];
    }
    sum = (sum & 0x0000ffff) + (sum >> 16);
    sum += (sum >> 16);
    ipHeader->checksum = (UINT16)~sum;
}

标签: javascriptioserror-handling

解决方案


推荐阅读