Partager via


Utilisation de la redirection de liaison ou de connexion

La fonctionnalité de redirection de connexion/liaison de la plateforme de filtrage Windows (PAM) permet aux pilotes de légende ale (Application Layer Enforcement) d’inspecter et, si vous le souhaitez, de rediriger les connexions.

Cette fonctionnalité est disponible dans Windows 7 et versions ultérieures.

Note Le module ClassifyFunctions_ProxyCallouts.cpp de l’exemple de pilote PAM inclut du code qui illustre la redirection de connexion/liaison.

Une légende de redirection de connexion PAM redirige la demande de connexion d’une application afin que l’application se connecte à un service proxy au lieu de la destination d’origine. Le service proxy a deux sockets : l’un pour la connexion d’origine redirigée et l’autre pour la nouvelle connexion sortante proxiée.

Un enregistrement de redirection PAM est une mémoire tampon de données opaques que PAM doit définir sur une connexion proxy sortante aux couches FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 et FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6 , de sorte que la connexion redirigée et la connexion d’origine soient logiquement liées.

La modification de l’adresse locale et du port d’un flux est uniquement prise en charge dans la couche liaison-redirection. Cela n’est pas pris en charge dans la couche connexion-redirection.

Couches utilisées pour la redirection

La redirection peut être effectuée par les pilotes de légende aux couches suivantes, appelées « couches de redirection » :

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

La couche au niveau de laquelle la redirection est effectuée détermine l’effet de la modification. Les modifications apportées aux couches de connexion affectent uniquement le flux connecté. Les modifications apportées aux couches de liaison affectent toutes les connexions qui utilisent ce socket.

Les couches de redirection sont disponibles uniquement pour Windows 7 et les versions ultérieures de Windows. Les pilotes de légende qui prennent en charge la classification au niveau de ces couches doivent s’inscrire à l’aide de FwpsCalloutRegister1 ou version ultérieure, et non de l’ancienne fonction FwpsCalloutRegister0 .

Important

 La redirection n’est pas disponible pour une utilisation avec tous les types de trafic réseau. Les types de paquets pris en charge pour la redirection sont indiqués dans la liste suivante :

  • TCP
  • UDP
  • UDPv4 brut sans l’option include d’en-tête
  • ICMP brut

Exécution de la redirection

Pour rediriger une connexion, le pilote de légende doit obtenir une copie accessible en écriture des informations tcp 4-tuple, y apporter les modifications nécessaires et appliquer les modifications. Un ensemble de nouvelles fonctions sont fournies pour obtenir des données de couche accessibles en écriture et les appliquer via le moteur. Les pilotes de légende ont la possibilité d’apporter des modifications inline dans leurs fonctions classifyFn ou de manière asynchrone dans une autre fonction.

Les pilotes de légende qui implémentent la redirection doivent utiliser classifyFn1 ou une version ultérieure au lieu de classifyFn0 comme fonction de légende de classification. Pour utiliser classFn1 ou une version ultérieure, la légende doit être inscrite en appelant FwpsCalloutRegister1 ou version ultérieure, et non l’ancienne FwpsCalloutRegister0.

Pour effectuer la redirection inline, un pilote de légende doit effectuer les étapes suivantes dans son implémentation de classifyFn :

  1. Appelez FwpsRedirectHandleCreate0 pour obtenir un handle qui peut être utilisé pour rediriger les connexions TCP. Ce handle doit être mis en cache et utilisé pour toutes les redirections. (Cette étape est omise pour Windows 7 et versions antérieures.)

  2. Dans Windows 8 et versions ultérieures, vous devez interroger l’état de redirection de la connexion à l’aide de la fonction FwpsQueryConnectionRedirectState0 dans votre pilote de légende. Cette opération doit être effectuée pour empêcher la redirection infinie.

  3. Appelez FwpsAcquireClassifyHandle0 pour obtenir un handle qui sera utilisé pour les appels de fonction suivants.

  4. Appelez FwpsAcquireWritableLayerDataPointer0 pour obtenir la structure de données accessible en écriture pour la couche dans laquelle classifiFn a été appelé. Cassez le paramètre writableLayerData vers la structure correspondant à la couche, FWPS_BIND_REQUEST0 ou FWPS_CONNECT_REQUEST0.

    À compter de Windows 8, si votre pilote de légende redirige vers un service local, vous devez appeler FwpsRedirectHandleCreate0 pour renseigner le membre localRedirectHandle de la structure FWPS_CONNECT_REQUEST0 afin de faire fonctionner le proxy local.

  5. Apportez des modifications aux données de couche en fonction des besoins :

    1. Enregistrez la destination d’origine dans le contexte de redirection local, comme illustré dans l’exemple suivant :

      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. Modifiez l’adresse distante comme indiqué dans l’exemple suivant :

      // 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. Si votre pilote de légende redirige vers un service local, il doit définir le PID du proxy local dans le membre localRedirectTargetPID de la structure FWPS_CONNECT_REQUEST0 .

    4. Si votre pilote de légende redirige vers un service local, il doit définir le handle de redirection retourné par FwpsRedirectHandleCreate0 dans le membre localRedirectHandle de la structure FWPS_CONNECT_REQUEST0.

  6. Appelez FwpsApplyModifiedLayerData0 pour appliquer les modifications apportées aux données.

  7. Dans votre service proxy (qui peut être en mode utilisateur ou en mode noyau), vous devez interroger les enregistrements de redirection et les contextes, comme indiqué dans l’exemple suivant :

    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. Dans votre service proxy (qui peut être en mode utilisateur ou en mode noyau), vous devez définir des enregistrements de redirection sur le socket de connexion proxy, comme indiqué dans l’exemple suivant pour créer un socket sortant :

    proxySock = WSASocket(…);
    result = WSAIoctl(
                 proxySock,
                 SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
                 redirectRecords, …);
    
  9. Appelez FwpsReleaseClassifyHandle0 pour libérer le handle de classification obtenu à l’étape 2.

  10. Appelez FwpsRedirectHandleDestroy0 pour détruire le handle obtenu à l’étape 1.

Pour effectuer la redirection de manière asynchrone, un pilote de légende doit effectuer les étapes suivantes :

  1. Appelez FwpsRedirectHandleCreate0 pour obtenir un handle qui peut être utilisé pour rediriger les connexions TCP. (Cette étape est omise pour Windows 7 et versions antérieures.)

  2. Dans Windows 8 et versions ultérieures, vous devez interroger l’état de redirection de la connexion à l’aide de la fonction FwpsQueryConnectionRedirectState0 dans votre pilote de légende.

  3. Appelez FwpsAcquireClassifyHandle0 pour obtenir un handle qui sera utilisé pour les appels de fonction suivants. Cette étape et les étapes 2 et 3 sont effectuées dans la fonction de légende classifyFn du pilote de légende.

  4. Appelez FwpsPendClassify0 pour placer la classification dans un état en attente, comme illustré dans l’exemple suivant :

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

Notes

Si vous ciblez Windows 7, vous devez effectuer les étapes suivantes dans une fonction de travail distincte. Si vous ciblez Windows 8 ou une version ultérieure, vous pouvez effectuer toutes les étapes pour la redirection asynchrone à partir de l’élément classifyFn et ignorer l’étape 5.

  1. Envoyez le handle de classification et les données de couche accessibles en écriture à une autre fonction pour un traitement asynchrone. Les étapes restantes sont effectuées dans cette fonction, et non dans l’implémentation du pilote de légende de classifyFn.

  2. Appelez FwpsAcquireWritableLayerDataPointer0 pour obtenir la structure de données accessible en écriture pour la couche dans laquelle classifiFn a été appelé. Cassez le paramètre writableLayerData vers la structure correspondant à la couche, FWPS_BIND_REQUEST0 ou FWPS_CONNECT_REQUEST0.

    À compter de Windows 8, si votre pilote de légende redirige localement, vous devez appeler FwpsRedirectHandleCreate0 pour renseigner le membre localRedirectHandle de la structure FWPS_CONNECT_REQUEST0 afin de faire fonctionner le proxy.

  3. Stockez toutes les informations de contexte spécifiques à une légende dans une structure de contexte privée, comme illustré dans l’exemple suivant :

    redirectContext->classifyHandle = classifyHandle;
    redirectContext->connectRequest = connectRequest;
    redirectContext->classifyOut = *classifyOut; // deep copy
    // store original destination IP, port
    
  4. Apportez des modifications aux données de couche en fonction des besoins.

  5. Appelez FwpsApplyModifiedLayerData0 pour appliquer les modifications apportées aux données. Définissez l’indicateur FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS si vous souhaitez être à nouveau autorisé dans le cas où une autre légende modifie davantage les données.

  6. Appelez FwpsCompleteClassify0 pour terminer l’opération de classification de manière asynchrone, comme illustré dans l’exemple suivant :

    FwpsCompleteClassify(
            redirectContext->classifyHandle,
            0,
            &redirectContext->classifyOut);
    classifyOut->actionType = FWP_ACTION_PERMIT;
    classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
    
  7. Appelez FwpsReleaseClassifyHandle0 pour libérer le handle de classification obtenu à l’étape 1.

Gestion de la redirection de connexion à partir de plusieurs légendes

Il est possible que plusieurs pilotes de légende lancent la redirection de connexion pour le même flux. Les légendes qui effectuent la redirection de connexion doivent connaître les autres demandes et y répondre de manière appropriée.

L’indicateur FWPS_RIGHT_ACTION_WRITE doit être défini chaque fois qu’une légende pend une classification. Votre légende doit tester l’indicateur FWPS_RIGHT_ACTION_WRITE pour case activée les droits permettant à votre légende de retourner une action. Si cet indicateur n’est pas défini, votre légende peut toujours retourner une action FWP_ACTION_BLOCK afin d’opposer son veto à une action FWP_ACTION_PERMIT qui a été retournée par une légende précédente.

Dans Windows 8 et versions ultérieures, votre pilote de légende doit interroger l’état de redirection de la connexion (pour voir si votre pilote de légende ou un autre pilote de légende l’a modifié) à l’aide de la fonction FwpsQueryConnectionRedirectState0. Si la connexion est redirigée par votre pilote de légende, ou si elle a été précédemment redirigée par votre pilote de légende, le pilote de légende ne doit rien faire. Sinon, il doit également case activée pour la redirection locale, comme illustré dans l’exemple suivant :

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

Si la connexion est à un proxy local, votre pilote de légende ne doit pas tenter de la rediriger.

Les pilotes de légende qui utilisent la redirection de connexion doivent s’inscrire au niveau de la couche de connexion d’autorisation ALE (FWPS_LAYER_ALE_AUTH_CONNECT_V4 ou FWPS_LAYER_ALE_AUTH_CONNECT_V6) et case activée les deux valeurs de métadonnées suivantes pour les indications où l’indicateur FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED est défini :

  • FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID contient l’identificateur du processus responsable du flux redirigé.

  • FWPS_METADATA_FIELD_ORIGINAL_DESTINATION contient l’adresse de la destination d’origine pour le flux.

La structure FWPS_CONNECT_REQUEST0 contient un membre appelé localRedirectTargetPID. Pour que toute redirection de connexion de bouclage soit valide, ce champ doit être rempli avec le PID du processus qui sera responsable du flux redirigé. Il s’agit des mêmes données que celles que le moteur transmet aux couches de connexion d’autorisation ALE en tant que FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID.

À compter de Windows 8, le service proxy doit émettre les SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS et SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTL, à l’aide de WSAIoctl, sur le point de terminaison d’origine du service proxy. En outre, le SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL doit être émis, à l’aide de WSAIoctl, sur le nouveau socket (proxié).

PAM Version-Independent noms et ciblage de versions spécifiques de Windows