Använda Bind eller Connect för omdirigering

Funktionen för omdirigering av anslutning/bindning i Windows Filtering Platform (WFP) gör det möjligt för ALE-callouts (Application Layer Enforcement) att inspektera och, om så önskas, omdirigera anslutningar.

Den här funktionen är tillgänglig i Windows 7 och senare.

Observera Modulen ClassifyFunctions_ProxyCallouts.cpp i WFP-drivrutinsexemplet innehåller kod som visar omdirigering av anslutning/återkoppling.

En WFP-anslutningsomdirigering omdirigerar anslutningsbegäran från ett program så att programmet ansluter till en proxytjänst istället för det ursprungliga målet. Proxytjänsten har två socketar: en för den omdirigerade ursprungliga anslutningen och en för den nya utgående anslutningen.

En WFP-omdirigeringspost är en buffert med ogenomskinliga data som WFP måste ange för en utgående proxyanslutning vid FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 - och FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6-lagren , så att den omdirigerade anslutningen och den ursprungliga anslutningen är logiskt relaterade.

Det går bara att ändra den lokala adressen och porten för ett flöde i bindningsomdirigeringsskiktet. Den här funktionen stöds inte i anslutnings- och omdirigeringsskiktet.

Lager som används för omdirigering

Anropsdrivrutiner kan utföra dirigering i följande lager, som kallas "dirigeringslager":

  • FWPM_LAYER_ALE_BIND_REDIRECT_V4 (FWPS_LAYER_ALE_BIND_REDIRECT_V4)

  • FWPM_LAYER_ALE_BIND_REDIRECT_V6 (FWPS_LAYER_ALE_BIND_REDIRECT_V6)

  • FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 (FWPS_LAYER_ALE_CONNECT_REDIRECT_V4)

  • FWPM_LAYER_ALE_CONNECT_REDIRECT_V6 (FWPS_LAYER_ALE_CONNECT_REDIRECT_V6)

Det lager där omdirigering utförs avgör effekten av ändringen. Ändringar i anslutningslager påverkar endast flödet som ansluts. Ändringar i bindningslager påverkar alla anslutningar som använder socketen.

Omdirigeringsskikten är endast tillgängliga för Windows 7- och senare versioner av Windows. Callout-drivrutiner som stöder klassificering i dessa lager måste registreras med FwpsCalloutRegister1 eller högre, och inte den äldre funktionen FwpsCalloutRegister0.

Viktigt!

 Omdirigering är inte tillgängligt för användning med alla typer av nätverkstrafik. De typer av paket som stöds för omdirigering visas i följande lista:

  • TCP
  • UDP (User Datagram-protokollet)
  • Raw UDPv4 utan alternativet inkludera rubrik
  • Rå ICMP

Utföra omdirigering

För att omdirigera en anslutning måste callout-driver hämta en skrivbar kopia av TCP 4-tupelns information, göra nödvändiga ändringar och tillämpa dem. En uppsättning nya funktioner tillhandahålls för att hämta skrivbara lagerdata och tillämpa dem via motorn. Utropsdrivrutiner har möjlighet att göra ändringar antingen direkt i sina classifyFn-funktioner eller asynkront i en annan funktion.

Pratbubbledrivrutiner som implementerar omdirigering måste använda classifyFn1 eller senare i stället för classifyFn0 som klassificeringsanropsfunktion. Om du vill använda classifyFn1 eller senare måste utropet registreras med ett anrop till FwpsCalloutRegister1 eller senare, inte den äldre FwpsCalloutRegister0.

För att utföra omdirigering inline måste en anropsdrivrutin utföra följande steg i sin implementering av classifyFn:

  1. Anropa FwpsRedirectHandleCreate0 för att hämta en referens som kan användas för att omdirigera TCP-anslutningar. Det här handtaget ska cachelagras och användas för alla omdirigeringar. (Det här steget utelämnas för Windows 7 och tidigare.)

  2. I Windows 8 och senare måste du fråga om anslutningens omdirigeringstillstånd med hjälp av funktionen FwpsQueryConnectionRedirectState0 i din filterdrivrutin. Detta måste göras för att förhindra oändlig omdirigering.

  3. Anropa FwpsAcquireClassifyHandle0 för att hämta ett handtag som ska användas för efterföljande funktionsanrop.

  4. Anropa FwpsAcquireWritableLayerDataPointer0 för att hämta den skrivbara datastrukturen för det lager där classifyFn anropades. Casta den utgående parametern writableLayerData till den struktur som motsvarar lagret, antingen FWPS_BIND_REQUEST0 eller FWPS_CONNECT_REQUEST0.

    Från och med Windows 8, om din callout-drivrutin omdirigeras till en lokal tjänst, måste du anropa FwpsRedirectHandleCreate0 för att fylla i den localRedirectHandle-medlemmen i FWPS_CONNECT_REQUEST0-strukturen för att lokal proxy ska fungera.

  5. Gör ändringar i lagerdata efter behov:

    1. Spara det ursprungliga målet i den lokala omdirigeringskontexten enligt följande exempel:

      FWPS_CONNECT_REQUEST* connectRequest = redirectContext->connectRequest;
      // Replace "..." with your own redirect context size
      connectRequest->localRedirectContextSize = ...;
      // Store original destination IP/Port information in the localRedirectContext member
      connectRequest->localRedirectContext =    ExAllocatePoolWithTag(…);
      
    2. Ändra fjärradressen enligt följande exempel:

      // Ensure we don't need to worry about crossing any of the TCP/IP stack's zones
      if(INETADDR_ISANY((PSOCKADDR)&(connectRequest->localAddressAndPort)))
      {
         INETADDR_SETLOOPBACK((PSOCKADDR)&(connectRequest->remoteAddressAndPort));
      }
      else
      {
         INETADDR_SET_ADDRESS((PSOCKADDR)&(connectRequest->remoteAddressAndPort),
                               INETADDR_ADDRESS((PSOCKADDR)&(connectRequest->localAddressAndPort)));
      }
      INETADDR_SET_PORT((PSOCKADDR)&connectRequest->remoteAddressAndPort,
                        RtlUshortByteSwap(params->proxyPort));
      
    3. Om din callout-drivrutin omdirigerar till en lokal tjänst ska den ange den lokala proxy-PID i localRedirectTargetPID-medlemmen i FWPS_CONNECT_REQUEST0-strukturen.

    4. Om din callout-drivrutin omdirigeras till en lokal tjänst bör den ange omdirigeringshandtaget som returneras av FwpsRedirectHandleCreate0 i medlemmen localRedirectHandle i FWPS_CONNECT_REQUEST0-strukturen.

  6. Anropa FwpsApplyModifiedLayerData0 för att tillämpa ändringarna som gjorts på data.

  7. I proxytjänsten (som kan vara i användarläge eller kernelläge) måste du köra frågor mot omdirigeringsposter och kontexter enligt följande exempel:

    BYTE* redirectRecords;
    BYTE redirectContext[CONTEXT_SIZE];
    listenSock = WSASocket(…);
    result = bind(listenSock, …);
    result = listen(listenSock, …);
    clientSock = WSAAccept(listenSock, …);
    // opaque data to be set on proxy connection
    result = WSAIoctl(clientSock,
                      SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS,
                      redirectRecords, …);
    // callout allocated data, contains original destination information
    result = WSAIoctl(clientSock,
                      SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT,
                      redirectContext, …);
    // extract original destination IP and port from above context
    
  8. I din proxytjänst (som kan vara i användarläge eller kernelläge) måste du ställa in omdirigeringsinställningar på proxyanslutningens socket, som visas i följande exempel, för att skapa en ny utgående socket.

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. Anropa FwpsReleaseClassifyHandle0 för att släppa klassificeringshandtaget som erhölls i steg 2.

  10. Anropa FwpsRedirectHandleDestroy0 för att förstöra handtaget som erhölls i steg 1.

För att utföra omdirigering asynkront måste en callout-drivrutin utföra följande steg:

  1. Anropa FwpsRedirectHandleCreate0 för att hämta en referens som kan användas för att omdirigera TCP-anslutningar. (Det här steget utelämnas för Windows 7 och tidigare.)

  2. I Windows 8 och senare måste du fråga om anslutningens omdirigeringstillstånd med hjälp av funktionen FwpsQueryConnectionRedirectState0 i din filterdrivrutin.

  3. Anropa FwpsAcquireClassifyHandle0 för att hämta ett handtag som ska användas för efterföljande funktionsanrop. Det här steget och steg 2 och 3 utförs i anroparens funktion classifyFn.

  4. Anropa FwpsPendClassify0 för att placera klassificeringen i ett väntande tillstånd enligt följande exempel:

    FwpsPendClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_BLOCK;
    classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    

Anmärkning

Om du riktar in dig på Windows 7 måste du utföra följande steg i en separat arbetsfunktion. Om du riktar in dig på Windows 8 eller senare kan du utföra alla steg för asynkron omdirigering inifrån classifyFn och ignorera steg 5.

  1. Skicka klassificeringshandtaget och skrivbara lagerdata till en annan funktion för asynkron bearbetning. De återstående stegen utförs i den aktuella funktionen, inte i callout-drivarens implementering av classifyFn.

  2. Anropa FwpsAcquireWritableLayerDataPointer0 för att hämta den skrivbara datastrukturen för det lager där classifyFn anropades. Casta den utgående parametern writableLayerData till den struktur som motsvarar lagret, antingen FWPS_BIND_REQUEST0 eller FWPS_CONNECT_REQUEST0.

    Från och med Windows 8, om din callout-drivrutin omdirigerar lokalt, måste du anropa FwpsRedirectHandleCreate0 för att fylla i localRedirectHandle-medlemmen i FWPS_CONNECT_REQUEST0-strukturen så att proxyfunktionen kan fungera.

  3. Lagra eventuell utropSpecifik kontextinformation i en privat kontextstruktur enligt exemplet nedan:

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. Gör ändringar i lagerdata efter behov.

  5. Anropa FwpsApplyModifiedLayerData0 för att tillämpa ändringarna som gjorts på data. Ange FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS flagga om du vill bli omauktoriserad om ett annat pårop ändrar data ytterligare.

  6. Anropa FwpsCompleteClassify0 för att slutföra klassificeringsåtgärden asynkront enligt följande exempel:

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. Anropa FwpsReleaseClassifyHandle0 för att släppa klassificeringshandtaget som erhölls i steg 1.

Hantera omdirigering av anslutningar från flera anrop

Det är möjligt att fler än en callout-drivrutin initierar anslutningsomdirigering för samma dataflöde. Utrop som utför anslutningsomdirigering bör hantera andra förfrågningar korrekt.

Flaggan FWPS_RIGHT_ACTION_WRITE ska anges när som helst en callout sätter en klassificering i vänteläge. Utropet bör testa för flaggan FWPS_RIGHT_ACTION_WRITE för att kontrollera dess rättigheter att returnera en åtgärd. Om detta flagg inte är aktiverat kan ditt utrop fortfarande returnera en FWP_ACTION_BLOCK åtgärd för att vetoa en FWP_ACTION_PERMIT-åtgärd som returnerades av en tidigare utrop.

I Windows 8 och senare måste din callout-drivrutin fråga om omdirigeringsstatus för anslutningen (för att se om din callout-drivrutin eller en annan callout-drivrutin har ändrat den) med hjälp av funktionen FwpsQueryConnectionRedirectState0. Om anslutningen omdirigeras av din utropsdrivrutin, eller om den tidigare omdirigerades av din utropsdrivrutin, bör drivrutinen inte göra någonting. Annars bör den också söka efter lokal omdirigering enligt följande exempel:

FwpsAcquireWritableLayerDataPointer(...,(PVOID*)&connectRequest), ...);
if(connectRequest->previousVersion->modifierFilterId != filterId)
{
    if(connectRequest->previousVersion->localRedirectHandle)
    {
        classifyOut->actionType = FWP_ACTION_PERMIT;
        classifyOut->rights &= FWPS_RIGHT_ACTION_WRITE;
        FwpsApplyModifiedLayerData(
                classifyHandle,
                (PVOID)connectRequest,
                FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS);
    }
}

Om anslutningen är till en lokal proxy bör callout-drivrutinen inte försöka omdirigera den.

Callout-drivrutiner som använder anslutningsomdirigering bör registreras på ALE-auktoriseringsanslutningsskiktet (FWPS_LAYER_ALE_AUTH_CONNECT_V4 eller FWPS_LAYER_ALE_AUTH_CONNECT_V6) och kontrollera följande två metadatavärden för att identifiera var flaggan FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED är satt:

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID innehåller processidentifieraren för den process som ansvarar för det omdirigerade flödet.

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION innehåller adressen till det ursprungliga målet för flödet.

Den FWPS_CONNECT_REQUEST0 strukturen innehåller en medlem med namnet localRedirectTargetPID. För att omdirigering av loopback-anslutningar ska vara giltig måste det här fältet fyllas i med PID för den process som ansvarar för det omdirigerade flödet. Det här är samma data som motorn skickar som FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID i ALE-auktoriseringsanslutningslagren.

Från och med Windows 8 måste proxytjänsten utfärda SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS och SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTLs med hjälp av WSAIoctl mot proxytjänstens ursprungliga slutpunkt. Dessutom måste IOCTL SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS utfärdas med hjälp av WSAIoctl på den nya (proxyt) socketen.

WFP-Version-Independent namn och målinriktade specifika versioner av Windows