Share via


Verwenden der Bindungs- oder Verbindungsumleitung

Das Feature zum Verbinden/Binden der Umleitung der Windows-Filterplattform (Windows Filtering Platform, WFP) ermöglicht es ALE-Legendentreibern (Application Layer Enforcement), Verbindungen zu überprüfen und bei Bedarf umzuleiten.

Dieses Feature ist in Windows 7 und höher verfügbar.

Hinweis Das modul ClassifyFunctions_ProxyCallouts.cpp im WFP-Treiberbeispiel enthält Code, der die Verbindungs-/Bindungsumleitung veranschaulicht.

Eine WFP-Verbindungsumleitungs-Legende leitet die Verbindungsanforderung einer Anwendung um, sodass die Anwendung eine Verbindung mit einem Proxydienst anstelle des ursprünglichen Ziels herstellt. Der Proxydienst verfügt über zwei Sockets: einen für die umgeleitete ursprüngliche Verbindung und einen für die neue proxied ausgehende Verbindung.

Ein WFP-Umleitungsdatensatz ist ein Puffer undurchsichtiger Daten, den WFP für eine ausgehende Proxyverbindung auf den FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 - und FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6-Ebenen festlegen muss, damit die umgeleitete Verbindung und die ursprüngliche Verbindung logisch miteinander verknüpft sind.

Das Ändern der lokalen Adresse und des Ports eines Flows wird nur in der Bind-Redirect-Schicht unterstützt. Dies wird auf der Verbindungsumleitungsebene nicht unterstützt.

Ebenen, die für die Umleitung verwendet werden

Die Umleitung kann von Legendentreibern auf den folgenden Ebenen ausgeführt werden, die als "Umleitungsebenen" bezeichnet werden:

  • 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)

Die Ebene, auf der die Umleitung durchgeführt wird, bestimmt die Auswirkung der Änderung. Änderungen an Verbindungsebenen wirken sich nur auf den verbundenen Flow aus. Änderungen an Bindungsebenen wirken sich auf alle Verbindungen aus, die diesen Socket verwenden.

Die Umleitungsebenen sind nur für Windows 7 und höhere Versionen von Windows verfügbar. Legendentreiber, die die Klassifizierung auf diesen Ebenen unterstützen, müssen sich mit FwpsCalloutRegister1 oder höher und nicht mit der älteren FwpsCalloutRegister0-Funktion registrieren.

Wichtig

 Die Umleitung ist nicht für die Verwendung mit allen Arten von Netzwerkdatenverkehr verfügbar. Die Pakettypen, die für die Umleitung unterstützt werden, sind in der folgenden Liste aufgeführt:

  • TCP
  • UDP
  • Unformatierte UDPv4 ohne header include-Option
  • Raw ICMP

Durchführen der Umleitung

Um eine Verbindung umzuleiten, muss der Legendentreiber eine beschreibbare Kopie der TCP 4-Tupelinformationen abrufen, bei Bedarf Änderungen daran vornehmen und die Änderungen anwenden. Es werden eine Reihe neuer Funktionen bereitgestellt, um beschreibbare Schichtdaten abzurufen und über die Engine anzuwenden. Legendentreiber haben die Möglichkeit, Änderungen entweder inline in ihren klassifizierenFn-Funktionen oder asynchron in einer anderen Funktion vorzunehmen.

Legendentreiber, die die Umleitung implementieren, müssen klassifizierenFn1 oder höher anstelle von klassifizierenFn0 als Klassifizierungsfunktion verwenden. Um klassifizierenFn1 oder höher zu verwenden, muss die Legende registriert werden, indem Sie FwpsCalloutRegister1 oder höher aufrufen, nicht das ältere FwpsCalloutRegister0.

Um die Umleitung inline auszuführen, muss ein Legendentreiber in seiner Implementierung von klassifizierenFn die folgenden Schritte ausführen:

  1. Rufen Sie fwpsRedirectHandleCreate0 auf, um ein Handle abzurufen, das zum Umleiten von TCP-Verbindungen verwendet werden kann. Dieses Handle sollte zwischengespeichert und für alle Umleitungen verwendet werden. (Dieser Schritt wird für Windows 7 und früher nicht angegeben.)

  2. In Windows 8 und höher müssen Sie den Umleitungsstatus der Verbindung mithilfe der Funktion FwpsQueryConnectionRedirectState0 in Ihrem Legendentreiber abfragen. Dies muss geschehen, um unendliche Umleitungen zu verhindern.

  3. Rufen Sie fwpsAcquireClassifyHandle0 auf, um ein Handle abzurufen, das für nachfolgende Funktionsaufrufe verwendet wird.

  4. Rufen Sie fwpsAcquireWritableLayerDataPointer0 auf, um die beschreibbare Datenstruktur für die Ebene abzurufen, in der klassifizierenFn aufgerufen wurde. Wandeln Sie den writableLayerData-Parameter in die Struktur um, die der Ebene entspricht, entweder FWPS_BIND_REQUEST0 oder FWPS_CONNECT_REQUEST0.

    Ab Windows 8 müssen Sie fwpsRedirectHandleCreate0 aufrufen, um das localRedirectHandleHandleCreate-Element der FWPS_CONNECT_REQUEST0-Struktur auszufüllen, damit die lokale Proxyerstellung funktioniert.

  5. Nehmen Sie bei Bedarf Änderungen an den Ebenendaten vor:

    1. Speichern Sie das ursprüngliche Ziel im lokalen Umleitungskontext, wie im folgenden Beispiel gezeigt:

      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. Ändern Sie die Remoteadresse wie im folgenden Beispiel gezeigt:

      // 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. Wenn Ihr Legendentreiber zu einem lokalen Dienst umleitet, sollte er die lokale Proxy-PID im localRedirectTargetPID-Member der FWPS_CONNECT_REQUEST0-Struktur festlegen.

    4. Wenn Ihr Legendentreiber zu einem lokalen Dienst umgeleitet wird, sollte er das von FwpsRedirectHandleCreate0 zurückgegebene Umleitungshandle im localRedirectHandle-Member der FWPS_CONNECT_REQUEST0-Struktur festlegen.

  6. Rufen Sie fwpsApplyModifiedLayerData0 auf, um die vorgenommenen Änderungen auf die Daten anzuwenden.

  7. In Ihrem Proxydienst (der sich im Benutzer- oder Kernelmodus befinden kann) müssen Sie Umleitungsdatensätze und -kontexte abfragen, wie im folgenden Beispiel gezeigt:

    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. In Ihrem Proxydienst (der sich im Benutzermodus oder Kernelmodus befinden kann) müssen Sie Umleitungsdatensätze für den Proxyverbindungssocket festlegen, wie im folgenden Beispiel gezeigt, um einen neuen ausgehenden Socket zu erstellen:

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. Rufen Sie FwpsReleaseClassifyHandle0 auf, um das in Schritt 2 abgerufene Klassifizierungshandle freizugeben.

  10. Rufen Sie FwpsRedirectHandleDestroy0 auf, um das Handle zu zerstören, das in Schritt 1 abgerufen wurde.

Um die Umleitung asynchron auszuführen, muss ein Legendentreiber die folgenden Schritte ausführen:

  1. Rufen Sie fwpsRedirectHandleCreate0 auf, um ein Handle abzurufen, das zum Umleiten von TCP-Verbindungen verwendet werden kann. (Dieser Schritt wird für Windows 7 und früher nicht angegeben.)

  2. In Windows 8 und höher müssen Sie den Umleitungsstatus der Verbindung mithilfe der Funktion FwpsQueryConnectionRedirectState0 in Ihrem Legendentreiber abfragen.

  3. Rufen Sie fwpsAcquireClassifyHandle0 auf, um ein Handle abzurufen, das für nachfolgende Funktionsaufrufe verwendet wird. Dieser Schritt und die Schritte 2 und 3 werden in der Legendentreiberfunktion klassifizierenFn ausgeführt.

  4. Rufen Sie FwpsPendClassify0 auf, um die Klassifizierung in einen ausstehenden Zustand zu versetzen, wie im folgenden Beispiel gezeigt:

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

Hinweis

Wenn Sie Windows 7 als Ziel verwenden, müssen Sie die folgenden Schritte in einer separaten Workerfunktion ausführen. Wenn Sie Windows 8 oder höher anvisieren, können Sie alle Schritte für die asynchrone Umleitung aus dem klassifizierenFn ausführen und Schritt 5 ignorieren.

  1. Senden Sie den Klassifizierungshandle und die beschreibbaren Schichtdaten zur asynchronen Verarbeitung an eine andere Funktion. Die restlichen Schritte werden in dieser Funktion ausgeführt, nicht in der Implementierung von klassifizierenFn durch den Legendentreiber.

  2. Rufen Sie fwpsAcquireWritableLayerDataPointer0 auf, um die beschreibbare Datenstruktur für die Ebene abzurufen, in der klassifizierenFn aufgerufen wurde. Wandeln Sie den writableLayerData-Parameter in die Struktur um, die der Ebene entspricht, entweder FWPS_BIND_REQUEST0 oder FWPS_CONNECT_REQUEST0.

    Ab Windows 8 müssen Sie fwpsRedirectHandleCreate0 aufrufen, wenn Ihr Legendentreiber lokal umgeleitet wird, um das localRedirectHandle-Element der FWPS_CONNECT_REQUEST0-Struktur auszufüllen, damit die Proxyfunktion funktioniert.

  3. Speichern Sie alle legendenspezifischen Kontextinformationen in einer privaten Kontextstruktur, wie im folgenden Beispiel gezeigt:

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. Nehmen Sie bei Bedarf Änderungen an den Ebenendaten vor.

  5. Rufen Sie fwpsApplyModifiedLayerData0 auf, um die vorgenommenen Änderungen auf die Daten anzuwenden. Legen Sie das flag FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS fest, wenn Sie erneut autorisiert werden möchten, falls eine andere Legende die Daten weiter ändert.

  6. Rufen Sie fwpsCompleteClassify0 auf, um den Klassifizierungsvorgang asynchron abzuschließen, wie im folgenden Beispiel gezeigt:

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. Rufen Sie FwpsReleaseClassifyHandle0 auf, um das in Schritt 1 abgerufene Klassifizierungshandle freizugeben.

Behandeln der Verbindungsumleitung aus mehreren Legenden

Es ist möglich, dass mehrere Legendentreiber die Verbindungsumleitung für denselben Flow initiieren. Legenden, die die Verbindungsumleitung durchführen, sollten andere Anforderungen kennen und entsprechend reagieren.

Das FWPS_RIGHT_ACTION_WRITE-Flag sollte immer dann festgelegt werden, wenn eine Legende eine Klassifizierung angibt. Ihre Legende sollte testen , ob das flag FWPS_RIGHT_ACTION_WRITE , um die Rechte für Ihre Legende zu überprüfen, um eine Aktion zurückzugeben. Wenn dieses Flag nicht festgelegt ist, kann ihre Legende trotzdem eine FWP_ACTION_BLOCK Aktion zurückgeben, um ein Veto gegen eine FWP_ACTION_PERMIT Aktion einlegen zu können, die von einer vorherigen Legende zurückgegeben wurde.

In Windows 8 und höher muss Ihr Legendentreiber den Umleitungsstatus der Verbindung abfragen (um zu ermitteln, ob Ihr Legendentreiber oder ein anderer Legendentreiber ihn geändert hat) mithilfe der Funktion FwpsQueryConnectionRedirectState0. Wenn die Verbindung von Ihrem Legendentreiber umgeleitet wird oder wenn sie zuvor von Ihrem Legendentreiber umgeleitet wurde, sollte der Legendentreiber nichts tun. Andernfalls sollte auch die lokale Umleitung überprüft werden, wie im folgenden Beispiel gezeigt:

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);
    }
}

Wenn die Verbindung mit einem lokalen Proxy besteht, sollte Ihr Legendentreiber nicht versuchen, ihn umzuleiten.

Legendentreiber, die die Verbindungsumleitung verwenden, sollten sich auf der ALE-Autorisierungsverbindungsebene (FWPS_LAYER_ALE_AUTH_CONNECT_V4 oder FWPS_LAYER_ALE_AUTH_CONNECT_V6) registrieren und die folgenden beiden Metadatenwerte auf Hinweise überprüfen, auf denen das FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED-Flag festgelegt ist:

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID enthält den Prozessbezeichner für den Prozess, der für den umgeleiteten Flow verantwortlich ist.

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION enthält die Adresse des ursprünglichen Ziels für den Flow.

Die FWPS_CONNECT_REQUEST0-Struktur enthält ein Element namens localRedirectTargetPID. Damit die Loopback-Verbindungsumleitung gültig ist, muss dieses Feld mit der PID des Prozesses aufgefüllt werden, der für den umgeleiteten Flow verantwortlich ist. Dies sind dieselben Daten, die das Modul bei den ALE-Autorisierungsverbindungsebenen als FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID übergibt.

Ab Windows 8 muss der Proxydienst die SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS und SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTLs mithilfe von WSAIoctl für den ursprünglichen Endpunkt des Proxydiensts ausgeben. Darüber hinaus muss die SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL mit WSAIoctl auf dem neuen (proxied) Socket ausgestellt werden.

WFP Version-Independent Namen und Zielgruppenspezifische Windows-Versionen