Share via


使用系結或連線重新導向

Windows 篩選平台 (的連線/系結重新導向功能) 可讓應用層強制執行 (ALE) 圖說文字驅動程式,並視需要重新導向連線。

此功能適用于 Windows 7 和更新版本。

注意 在一個CLASSIFYFUNCTIONS_PROXYCALLOUTS.cpp 模組中 ,此驅動程式範例 包含示範連線/系結重新導向的程式碼。

一個有一個一個「一個」「一個」的「一個」連線重新導向圖說文字會重新導向應用程式的連線要求,讓應用程式連線到 Proxy 服務,而不是原始目的地。 Proxy 服務有兩個通訊端:一個用於重新導向的原始連線,另一個用於新的 Proxy 輸出連線。

此為一種不透明資料的緩衝區,在 FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 層和 FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6 層的輸出 Proxy 連線上必須設定此緩衝區,以便重新導向的連線和原始連線以邏輯方式相關。

只有在系結-重新導向層中才支援變更流程的本機位址和埠。 連線-重新導向層不支援此功能。

用於重新導向的圖層

重新導向可由下列層級的圖說文字驅動程式執行,稱為「重新導向層」:

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

執行重新導向的圖層會決定變更的效果。 連線層的變更只會影響所連接的流程。 系結層的變更會影響使用該通訊端的所有連線。

重新導向層僅適用于 Windows 7 和更新版本的 Windows。 支援這些層級分類的圖說文字驅動程式必須使用 FwpsCalloutRegister1 或更新版本進行註冊,而不是舊版 FwpsCalloutRegister0 函式。

重要

 重新導向不適用於所有類型的網路流量。 重新導向支援的封包類型會顯示在下列清單中:

  • TCP
  • UDP
  • 沒有標頭 include 選項的原始 UDPv4
  • 原始 ICMP

執行重新導向

若要重新導向連線,圖說文字驅動程式必須取得 TCP 4 元組資訊的可寫入複本、視需要對它進行變更,以及套用變更。 系統會提供一組新的函式來取得可寫入的圖層資料,並透過引擎套用它。 圖說文字驅動程式可以選擇在其 classifyFn 函式中內嵌進行變更,或在另一個函式中以非同步方式進行變更。

實作重新導向的圖說文字驅動程式必須使用 classificationFn1 或更新版本,而不是 將Fn0 分類 為其分類圖說文字函式。 若要使用 classifyFn1 或更新版本,必須呼叫 FwpsCalloutRegister1 或更新版本來註冊圖說文字,而不是舊的 FwpsCalloutRegister0

若要執行內嵌圖說文字驅動程式的重新導向,必須在 其分類Fn的實作中執行下列步驟:

  1. 呼叫 FwpsRedirectHandleCreate0 以取得可用來重新導向 TCP 連線的控制碼。 此控制碼應該快取並用於所有重新導向。 (針對 Windows 7 和更早版本省略此步驟。)

  2. 在Windows 8和更新版本中,您必須在圖說文字驅動程式中使用FwpsQueryConnectionRedirectState0函式來查詢連線的重新導向狀態。 這必須完成,才能防止無限重新導向。

  3. 呼叫 FwpsAcquireClassifyHandle0 以取得將用於後續函式呼叫的控制碼。

  4. 呼叫 FwpsAcquireWritableLayerDataPointer0 以取得 呼叫 classifyFn 之圖層的可寫入資料結構。 將 writableLayerData out 參數轉換成對應至圖層的結構, FWPS_BIND_REQUEST0FWPS_CONNECT_REQUEST0

    從 Windows 8 開始,如果您的圖說文字驅動程式重新導向至本機服務,您必須呼叫FwpsRedirectHandleCreate0以填入FWPS_CONNECT_REQUEST0結構的localRedirectHandle成員,才能讓本機 Proxy 正常運作。

  5. 視需要變更圖層資料:

    1. 將原始目的地儲存在本機重新導向內容中,如下列範例所示:

      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. 修改遠端位址,如下列範例所示:

      // 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. 如果您的圖說文字驅動程式重新導向至本機服務,它應該在 FWPS_CONNECT_REQUEST0 結構的 localRedirectTargetPID 成員中設定 本機 Proxy PID。

    4. 如果您的圖說文字驅動程式重新導向至本機服務,它應該在 FWPS_CONNECT_REQUEST0 結構的 localRedirectHandle 成員中設定 FwpsRedirectHandleCreate0 所傳回的重新導向控制碼。

  6. 呼叫 FwpsApplyModifiedLayerData0 以套用對資料所做的變更。

  7. 在您的 Proxy 服務 (可能位於使用者模式或核心模式) 中,您必須查詢重新導向記錄和內容,如下列範例所示:

    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. 在您的 Proxy 服務 (可能是使用者模式或核心模式) ,您必須在 Proxy 連線通訊端上設定重新導向記錄,如下列範例所示,才能建立新的輸出通訊端:

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. 呼叫 FwpsReleaseClassifyHandle0 以釋放步驟 2 中取得的分類控制碼。

  10. 呼叫 FwpsRedirectHandleDestroy0 以終結步驟 1 中取得的控制碼。

若要以非同步方式執行重新導向,圖說文字驅動程式必須執行下列步驟:

  1. 呼叫 FwpsRedirectHandleCreate0 以取得可用來重新導向 TCP 連線的控制碼。 (針對 Windows 7 和更早版本省略此步驟。)

  2. 在Windows 8和更新版本中,您必須在圖說文字驅動程式中使用FwpsQueryConnectionRedirectState0函式來查詢連線的重新導向狀態。

  3. 呼叫 FwpsAcquireClassifyHandle0 以取得將用於後續函式呼叫的控制碼。 此步驟和步驟 2 和 3 是在圖說文字驅動程式 的 classifyFn 圖說文字函式中執行。

  4. 呼叫 FwpsPendClassify0 以將分類置於擱置狀態,如下列範例所示:

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

注意

如果您是以 Windows 7 為目標,則必須在不同的背景工作角色函式中執行下列步驟。 如果您的目標是Windows 8或更新版本,您可以從classifyFn內執行非同步重新導向的所有步驟,並忽略步驟 5。

  1. 將分類控制碼和可寫入的圖層資料傳送至另一個函式,以進行非同步處理。 其餘步驟會在該函式中執行,而不是 在 callout 驅動程式的 classifyFn實作中執行。

  2. 呼叫 FwpsAcquireWritableLayerDataPointer0 以取得 呼叫 classifyFn 之圖層的可寫入資料結構。 將 writableLayerData out 參數轉換成對應至圖層的結構, FWPS_BIND_REQUEST0FWPS_CONNECT_REQUEST0

    從 Windows 8 開始,如果您的圖說文字驅動程式在本機重新導向,您必須呼叫FwpsRedirectHandleCreate0以填入FWPS_CONNECT_REQUEST0結構的localRedirectHandle成員,才能進行 Proxy 處理工作。

  3. 將任何注標特定內容資訊儲存在私人內容結構中,如下列範例所示:

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. 視需要變更圖層資料。

  5. 呼叫 FwpsApplyModifiedLayerData0 以套用對資料所做的變更。 如果您想要在另一個圖說文字進一步修改資料時重新授權,請設定 FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS 旗標。

  6. 呼叫 FwpsCompleteClassify0 以非同步方式完成分類作業,如下列範例所示:

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. 呼叫 FwpsReleaseClassifyHandle0 以釋放步驟 1 中取得的分類控制碼。

處理多個圖說文字的連線重新導向

一個以上的圖說文字驅動程式可能會起始相同流程的連線重新導向。 執行連線重新導向的圖說文字應該注意其他要求並適當地回應。

每當圖說文字畫上分類時,應該設定 FWPS_RIGHT_ACTION_WRITE 旗標。 您的圖說文字應該測試 FWPS_RIGHT_ACTION_WRITE 旗標,以檢查圖說文字傳回動作的許可權。 如果未設定此旗標,您的圖說文字仍然可以傳回 FWP_ACTION_BLOCK 動作,以保留先前圖說文字所傳回 的FWP_ACTION_PERMIT 動作。

在Windows 8和更新版本中,您的圖說文字驅動程式必須查詢連線的重新導向狀態 (,以查看您的圖說文字驅動程式或其他圖說文字驅動程式是否已使用FwpsQueryConnectionRedirectState0函式來修改它) 。 如果圖說驅動程式重新導向連線,或先前由圖說文字驅動程式重新導向,圖說文字驅動程式應該不會執行任何動作。 否則,它也應該檢查本機重新導向,如下列範例所示:

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

如果連線是本機 Proxy,您的圖說文字驅動程式不應該嘗試重新導向它。

使用連線重新導向的圖說文字驅動程式應該在 ALE 授權連接層註冊 (FWPS_LAYER_ALE_AUTH_CONNECT_V4FWPS_LAYER_ALE_AUTH_CONNECT_V6) ,並檢查下列兩個中繼資料值,以取得設定 FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED 旗標的指示:

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID 包含負責重新導向流程之進程的進程識別碼。

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION 包含流程原始目的地的位址。

FWPS_CONNECT_REQUEST0結構包含名為localRedirectTargetPID的成員。 若要讓任何回送連線重新導向有效,此欄位必須填入將負責重新導向流程之程式的 PID。 這是引擎在 ALE 授權連接層上以 FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID傳遞的相同資料。

從 Windows 8 開始,Proxy 服務必須使用WSAIoctl對 Proxy 服務的原始端點發出SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDSSIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTL。 此外,必須在新的 ( Proxyed) 通訊端上使用 WSAIoctl發出SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL。

Version-Independent名稱和以特定 Windows 版本為目標