Udostępnij przez


Używanie przekierowania za pomocą poleceń Bind lub Connect

Funkcja przekierowywania połączeń/powiązania platformy filtrowania systemu Windows (WFP) umożliwia sterownikom wywołań warstwy aplikacji (ALE) sprawdzanie połączeń i, w razie potrzeby, ich przekierowanie.

Ta funkcja jest dostępna w systemie Windows 7 lub nowszym.

Uwaga Moduł ClassifyFunctions_ProxyCallouts.cpp w przykładowym sterowniku WFP zawiera kod, który demonstruje przekierowanie połączeń/wiązań.

Wywołanie przekierowania połączenia WFP przekierowuje żądanie połączenia aplikacji, tak aby aplikacja łączyła się z usługą proxy zamiast z oryginalnym miejscem docelowym. Usługa serwera proxy ma dwa gniazda: jedno dla przekierowanego oryginalnego połączenia i jedno dla nowego połączenia wychodzącego.

Rekord przekierowania WFP jest buforem nieprzejrzystych danych, które WFP musi ustawić na połączeniu wychodzącym z serwera proxy w warstwach FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 i FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6, aby przekierowane połączenie i oryginalne połączenie były logicznie powiązane.

Zmiana adresu lokalnego i portu przepływu jest obsługiwana tylko w warstwie przekierowania powiązania. Ta funkcja nie jest obsługiwana w warstwie połączenia-przekierowania.

Warstwy używane do przekierowywania

Sterowniki wywołania mogą realizować przekierowanie w następujących warstwach, zwanych "warstwami przekierowania":

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

Warstwa, w której jest wykonywane przekierowanie, określa efekt zmiany. Zmiany w warstwach łączenia mają wpływ tylko na połączony przepływ. Zmiany w warstwach powiązania mają wpływ na wszystkie połączenia korzystające z tego gniazda.

Warstwy przekierowania są dostępne tylko dla systemu Windows 7 i późniejszych wersji systemu Windows. Sterowniki wywołań, które obsługują klasyfikację w tych warstwach, muszą rejestrować się przy użyciu FwpsCalloutRegister1 lub nowszej, a nie starszej FwpsCalloutRegister0.

Ważne

 Przekierowanie nie jest dostępne do użycia ze wszystkimi typami ruchu sieciowego. Typy pakietów obsługiwanych na potrzeby przekierowania są wyświetlane na poniższej liście:

  • TCP
  • protokół UDP
  • Surowy UDPv4 bez opcji dołączenia nagłówka
  • Nieprzetworzone ICMP

Wykonywanie przekierowania

Aby przekierować połączenie, sterownik wywołania musi uzyskać zapisywalną kopię czworaczka TCP 4, wprowadzić w niej zmiany w razie potrzeby i zastosować zmiany. Udostępniono zestaw nowych funkcji w celu uzyskania zapisywalnych danych warstwy i zastosowania ich za pośrednictwem silnika. Sterowniki połączeń wywoławczych mają możliwość wprowadzać zmiany w miejscu w swoich funkcjach classifyFn lub asynchronicznie w innej funkcji.

Sterowniki wywołań implementujące przekierowanie muszą używać classifyFn1 lub nowszej zamiast classifyFn0 jako funkcji klasyfikacji wywołań. Aby użyć classifyFn1 lub nowszego, wywołanie musi być zarejestrowane za pomocą funkcji FwpsCalloutRegister1 lub nowszej, a nie starszej FwpsCalloutRegister0.

Aby wykonać przekierowanie inline, sterownik wywołania musi wykonać następujące kroki w implementacji classifyFn:

  1. Wywołaj metodę FwpsRedirectHandleCreate0 , aby uzyskać uchwyt, który może służyć do przekierowywania połączeń TCP. Ten uchwyt powinien być buforowany i używany dla wszystkich przekierowań. (Ten krok zostanie pominięty dla systemu Windows 7 i starszych).

  2. W systemie Windows 8 lub nowszym należy wykonać zapytanie o stan przekierowania połączenia przy użyciu funkcji FwpsQueryConnectionRedirectState0 w sterowniku wywołania. Należy to zrobić, aby zapobiec nieskończonemu przekierowywaniu.

  3. Wywołaj metodę FwpsAcquireClassifyHandle0 , aby uzyskać dojście, które będzie używane do kolejnych wywołań funkcji.

  4. Wywołaj metodę FwpsAcquireWritableLayerDataPointer0 , aby uzyskać zapisywalną strukturę danych dla warstwy, w której wywołano klasyfikowanieFn . Rzutuj parametr wyjściowy writableLayerData na strukturę odpowiadającą warstwie, FWPS_BIND_REQUEST0 lub FWPS_CONNECT_REQUEST0.

    Począwszy od systemu Windows 8, jeśli sterownik wywołań przekierowuje do usługi lokalnej, należy wywołać metodę FwpsRedirectHandleCreate0, aby wypełnić członek localRedirectHandle struktury FWPS_CONNECT_REQUEST0, umożliwiając działanie lokalnego serwera proxy.

  5. Wprowadź zmiany w danych warstwy zgodnie z potrzebami:

    1. Zapisz oryginalne miejsce docelowe w kontekście przekierowania lokalnego, jak pokazano w poniższym przykładzie:

      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. Zmodyfikuj adres zdalny, jak pokazano w poniższym przykładzie:

      // 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. Jeśli sterownik wywołujący przekierowuje do usługi lokalnej, powinien ustawić identyfikator PID lokalnego proxy w elemencie localRedirectTargetPID struktury FWPS_CONNECT_REQUEST0.

    4. Jeśli sterownik wywołań przekierowuje do usługi lokalnej, powinien ustawić uchwyt przekierowania zwrócony przez FwpsRedirectHandleCreate0 w członku localRedirectHandle struktury FWPS_CONNECT_REQUEST0.

  6. Wywołaj metodę FwpsApplyModifiedLayerData0 , aby zastosować zmiany wprowadzone w danych.

  7. W usłudze serwera proxy (która może być w trybie użytkownika lub w trybie jądra), należy wykonać zapytanie dotyczące rekordów i kontekstów przekierowania, jak pokazano w poniższym przykładzie:

    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. W usłudze serwera proxy (która może być w trybie użytkownika lub w trybie jądra), należy ustawić rekordy przekierowania w gniazdie połączenia serwera proxy, jak pokazano w poniższym przykładzie, aby utworzyć nowe gniazdo wychodzące:

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. Wywołaj metodę FwpsReleaseClassifyHandle0 , aby zwolnić dojście klasyfikacji uzyskane w kroku 2.

  10. Wywołaj metodę FwpsRedirectHandleDestroy0 , aby zniszczyć uchwyt uzyskany w kroku 1.

Aby wykonać przekierowanie asynchronicznie, sterownik wywołujący musi wykonać następujące czynności:

  1. Wywołaj metodę FwpsRedirectHandleCreate0 , aby uzyskać uchwyt, który może służyć do przekierowywania połączeń TCP. (Ten krok zostanie pominięty dla systemu Windows 7 i starszych).

  2. W systemie Windows 8 lub nowszym należy wykonać zapytanie o stan przekierowania połączenia przy użyciu funkcji FwpsQueryConnectionRedirectState0 w sterowniku wywołania.

  3. Wywołaj metodę FwpsAcquireClassifyHandle0 , aby uzyskać dojście, które będzie używane do kolejnych wywołań funkcji. Ten krok i kroki 2 i 3 są wykonywane w funkcji wywołania klasyfikujFn sterownika wywołania.

  4. Wywołaj metodę FwpsPendClassify0 , aby umieścić klasyfikację w stanie oczekiwania, jak pokazano w poniższym przykładzie:

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

Uwaga / Notatka

Jeśli celem jest Windows 7, musisz wykonać następujące kroki w oddzielnej funkcji roboczej. Jeśli używasz systemu Windows 8 lub nowszego, możesz wykonać wszystkie kroki dla asynchronicznego przekierowania z poziomu klasyfikatoraFn i zignorować krok 5.

  1. Wyślij dojście klasyfikacji i zapisywalne dane warstwy do innej funkcji na potrzeby przetwarzania asynchronicznego. Pozostałe kroki są wykonywane w tej funkcji, a nie w implementacji sterownika funkcji wywołania classifyFn.

  2. Wywołaj metodę FwpsAcquireWritableLayerDataPointer0 , aby uzyskać zapisywalną strukturę danych dla warstwy, w której wywołano klasyfikowanieFn . Rzutuj parametr wyjściowy writableLayerData na strukturę odpowiadającą warstwie, FWPS_BIND_REQUEST0 lub FWPS_CONNECT_REQUEST0.

    Począwszy od systemu Windows 8, jeśli sterownik wywołań przekierowuje lokalnie, należy wywołać FwpsRedirectHandleCreate0, aby wypełnić członek localRedirectHandle struktury FWPS_CONNECT_REQUEST0, żeby umożliwić działanie proxy.

  3. Przechowuj wszystkie informacje kontekstowe specyficzne dla adnotacji w prywatnej strukturze kontekstu, jak pokazano w poniższym przykładzie.

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. Wprowadź zmiany w danych warstwy zgodnie z potrzebami.

  5. Wywołaj metodę FwpsApplyModifiedLayerData0 , aby zastosować zmiany wprowadzone w danych. Ustaw flagę FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS, jeśli chcesz zostać ponownie autoryzowany w przypadku dalszego modyfikowania danych przez inną wywołanie.

  6. Wywołaj metodę FwpsCompleteClassify0 , aby ukończyć operację klasyfikowania asynchronicznie, jak pokazano w poniższym przykładzie:

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. Wywołaj metodę FwpsReleaseClassifyHandle0 , aby zwolnić uchwyt klasyfikacji uzyskany w kroku 1.

Obsługa przekierowania połączenia z wielu powiadomień

Istnieje możliwość, że więcej niż jeden sterownik wywołania zainicjuje przekierowanie połączenia dla tego samego strumienia. Komunikaty, które wykonują przekierowanie połączenia, powinny być świadome innych żądań i odpowiednio reagować.

Flaga FWPS_RIGHT_ACTION_WRITE powinna być ustawiana za każdym razem, gdy wezwanie opóźnia klasyfikację. Wywołanie powinno przetestować flagę FWPS_RIGHT_ACTION_WRITE, aby sprawdzić prawa do zwrócenia akcji przez wywołanie. Jeśli ta flaga nie jest ustawiona, wywołanie nadal może zwrócić akcję FWP_ACTION_BLOCK w celu przerwania akcji FWP_ACTION_PERMIT zwróconej przez poprzednie wywołanie.

W systemie Windows 8 lub nowszym sterownik objaśnienia musi wykonywać zapytania dotyczące stanu przekierowania połączenia (aby sprawdzić, czy sterownik objaśnienia lub inny sterownik objaśnienia go zmodyfikował) przy użyciu funkcji FwpsQueryConnectionRedirectState0 . Jeśli połączenie jest przekierowywane przez sterownik wywołujący lub jeśli zostało wcześniej przekierowane przez sterownik wywołujący, sterownik wywołujący nie powinien nic robić. W przeciwnym razie należy również sprawdzić, czy nie ma przekierowania lokalnego, jak pokazano w poniższym przykładzie:

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

pl-PL: Jeśli połączenie jest do lokalnego serwera proxy, sterownik wezwania nie powinien próbować go przekierować.

Sterowniki wywołań używające przekierowania połączenia powinny rejestrować się w warstwie autoryzacji połączenia ALE (FWPS_LAYER_ALE_AUTH_CONNECT_V4 lub FWPS_LAYER_ALE_AUTH_CONNECT_V6) i sprawdzić następujące dwie wartości metadanych w celu wskazania, gdzie ustawiono flagę FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED :

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID zawiera identyfikator procesu, który odpowiada za przekierowanie strumienia.

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION zawiera adres oryginalnego miejsca docelowego przepływu.

Struktura FWPS_CONNECT_REQUEST0 zawiera element członkowski o nazwie localRedirectTargetPID. Aby przekierowanie połączenia zwrotnego było prawidłowe, to pole musi zostać wypełnione identyfikatorem PID procesu odpowiedzialnego za przekierowany przepływ. Są to te same dane, które silnik przekazuje w warstwach połączenia autoryzacji ALE jako FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID.

Począwszy od systemu Windows 8, usługa proxy musi wydawać SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS i SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTL, używając WSAIoctl, na oryginalny punkt końcowy usługi proxy. Ponadto należy wydać SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL przy użyciu WSAIoctl, na nowym zaproksiedowanym gnieździe.

WFP Version-Independent nazewnictwo i docelowe wersje systemu Windows