Uso de enlace o redireccionamiento de conexión
La característica de redirección de conexión y enlace de la Plataforma de filtrado de Windows (PMA) permite a los controladores de llamada de cumplimiento de nivel de aplicación (ALE) inspeccionar, si lo desean, y redirigir las conexiones.
Esta función está disponible en las versiones de Windows 7 y posteriores.
Nota El módulo ClassifyFunctions_ProxyCallouts.cpp del ejemplo de controlador WFP incluye código que muestra la redirección de conexión y enlace.
Una llamada de redirección de conexión de WFP redirige la solicitud de conexión de una aplicación para que la aplicación se conecte a un servicio proxy en lugar del destino original. El servicio proxy tiene dos sockets: uno para la conexión original redirigida y otro para la nueva conexión saliente con proxy.
Un registro de redirección de WFP es un búfer de datos opacos que el WFP debe establecer en una conexión proxy saliente en las capas FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 y FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6, de modo que la conexión redirigida y la conexión original estén relacionadas lógicamente.
El cambio de la dirección local y el puerto de un flujo solo se admite en la capa de redirección de enlace. Esta funcionalidad no se admite en la capa de redirección de conexión.
Capas usadas para la redirección
Los controladores de llamada pueden realizar la redirección en las siguientes capas, que se denominan "capas de redirección":
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 capa en la que se realiza la redirección determina el efecto del cambio. Los cambios en las capas de conexión afectan solo al flujo que se está conectando. Los cambios en las capas de enlace afectan a todas las conexiones que usan ese socket.
Las capas de redirección solo están disponibles para Windows 7 y versiones posteriores de Windows. Los controladores de llamada que admiten la clasificación en estas capas deben registrarse con FwpsCalloutRegister1 o superior, no con la función FwpsCalloutRegister0 anterior.
Importante
La redirección no está disponible para su uso con todos los tipos de tráfico de red. Los tipos de paquetes que se admiten para la redirección se muestran en la lista siguiente:
- TCP
- UDP
- UDPv4 sin formato sin la opción de inclusión del encabezado
- ICMP sin formato
Realización de la redirección
Para redirigir una conexión, el controlador de llamada debe obtener una copia grabable de la información de tupla TCP 4, realizar cambios en ella según sea necesario y aplicar los cambios. Se proporciona un conjunto de funciones nuevas para obtener datos de capa grabables y aplicarlos a través del motor. Los controladores de llamada tienen la opción de realizar cambios en línea en sus funciones classifyFn o de forma asincrónica en otra función.
Los controladores de llamada que implementan la redirección deben usar classifyFn1 o posterior en lugar de classifyFn0 como su función de llamada de clasificación. Para usar classifyFn1 o posterior, la llamada debe registrarse llamando a FwpsCalloutRegister1 o posterior, no a FwpsCalloutRegister0 anterior.
Para realizar la redirección insertada, un controlador de llamada debe realizar los pasos siguientes en su implementación de classifyFn:
Llamar a FwpsRedirectHandleCreate0 para obtener un identificador que se puede usar para redirigir las conexiones TCP. Este identificador debe almacenarse en caché y usarse para todas las redirecciones. (Este paso se omite para Windows 7 y versiones anteriores).
En Windows 8 y versiones posteriores, debe consultar el estado de redirección de la conexión mediante la función FwpsQueryConnectionRedirectState0 en el controlador de llamada. Esto debe hacerse para evitar la redirección infinita.
Llamar a FwpsAcquireClassifyHandle0 para obtener un identificador que se usará para las llamadas de función posteriores.
Llamar a FwpsAcquireWritableLayerDataPointer0 para obtener la estructura de datos grabable para la capa en la que se llamó a classifyFn. Convertir el parámetro writableLayerData en la estructura correspondiente a la capa, ya sea FWPS_BIND_REQUEST0 o FWPS_CONNECT_REQUEST0.
A partir de Windows 8, si el controlador de llamada se redirige a un servicio local, debe llamar a FwpsRedirectHandleCreate0 para rellenar el miembro localRedirectHandle de la estructura FWPS_CONNECT_REQUEST0 para que funcione el proxy local.
Realice cambios en los datos de capa según sea necesario:
Guarde el destino original en el contexto de redirección local, como se muestra en el ejemplo siguiente:
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(…);
Modifique la dirección remota como se muestra en el ejemplo siguiente:
// 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));
Si el controlador de llamada redirige a un servicio local, debe establecer el PID del proxy local en el miembro localRedirectTargetPID de la estructura FWPS_CONNECT_REQUEST0.
Si el controlador de llamada redirige a un servicio local, debe establecer el identificador de redireccionamiento devuelto por FwpsRedirectHandleCreate0 en el miembro localRedirectHandle de la estructura FWPS_CONNECT_REQUEST0.
Llamar a FwpsApplyModifiedLayerData0 para aplicar los cambios realizados a los datos.
En el servicio proxy (que podría estar en modo de usuario o modo kernel), debe consultar registros y contextos de redirección, como se muestra en el ejemplo siguiente:
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
En el servicio proxy (que podría estar en modo de usuario o modo de kernel), debe establecer registros de redirección en el socket de conexión proxy, como se muestra en el ejemplo siguiente para crear un nuevo socket de salida:
proxySock = WSASocket(…); result = WSAIoctl( proxySock, SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS, redirectRecords, …);
Llamar a FwpsReleaseClassifyHandle0 para liberar el identificador de clasificación obtenido en el paso 2.
Llamar a FwpsRedirectHandleDestroy0 para destruir el identificador obtenido en el paso 1.
Para realizar el redireccionamiento de forma asincrónica, un controlador de llamada debe realizar los pasos siguientes:
Llamar a FwpsRedirectHandleCreate0 para obtener un identificador que se puede usar para redirigir las conexiones TCP. (Este paso se omite para Windows 7 y versiones anteriores).
En Windows 8 y versiones posteriores, debe consultar el estado de redirección de la conexión mediante la función FwpsQueryConnectionRedirectState0 en el controlador de llamada.
Llamar a FwpsAcquireClassifyHandle0 para obtener un identificador que se usará para las llamadas de función posteriores. Este paso y los pasos 2 y 3 se realizan en la función de llamada classifyFn del controlador de llamada.
Llamar a FwpsPendClassify0 para colocar la clasificación en un estado pendiente, como se muestra en el ejemplo siguiente:
FwpsPendClassify( redirectContext->classifyHandle, 0, &redirectContext->classifyOut); classifyOut->actionType = FWP_ACTION_BLOCK; classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
Nota:
Si tiene como destino Windows 7, debe realizar los pasos siguientes en una función de trabajo independiente. Si tiene como destino Windows 8 o posterior, puede realizar todos los pasos para la redirección asincrónica desde classifyFn y omitir el paso 5.
Enviar el identificador de clasificación y los datos de la capa grabable a otra función para el procesamiento asincrónico. Los pasos restantes se realizan en esa función, no en la implementación del controlador de llamada de classifyFn.
Llamar a FwpsAcquireWritableLayerDataPointer0 para obtener la estructura de datos grabable para la capa en la que se llamó a classifyFn. Convertir el parámetro writableLayerData en la estructura correspondiente a la capa, ya sea FWPS_BIND_REQUEST0 o FWPS_CONNECT_REQUEST0.
A partir de Windows 8, si el controlador de llamada se redirige localmente, debe llamar a FwpsRedirectHandleCreate0 para rellenar el miembro localRedirectHandle de la estructura FWPS_CONNECT_REQUEST0 para que funcione el proxy local.
Almacenar cualquier información de contexto específica de la llamada en una estructura de contexto privado, como se muestra en el ejemplo siguiente:
redirectContext->classifyHandle = classifyHandle; redirectContext->connectRequest = connectRequest; redirectContext->classifyOut = *classifyOut; // deep copy // store original destination IP, port
Realizar cambios en los datos de capa según sea necesario.
Llamar a FwpsApplyModifiedLayerData0 para aplicar los cambios realizados a los datos. Establece la marca FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS si desea volver a autorizarse en caso de que otra llamada modifique los datos.
Llamar a FwpsCompleteClassify0 para completar la operación de clasificación de forma asincrónica, como se muestra en el ejemplo siguiente:
FwpsCompleteClassify( redirectContext->classifyHandle, 0, &redirectContext->classifyOut); classifyOut->actionType = FWP_ACTION_PERMIT; classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
Llamar a FwpsReleaseClassifyHandle0 para liberar el identificador de clasificación obtenido en el paso 1.
Control de la redirección de conexión desde varias llamadas
Es posible que más de un controlador de llamada inicie la redirección de conexión para el mismo flujo. Las llamadas que realizan la redirección de conexión deben tener en cuenta otras solicitudes y responder correctamente.
La marca FWPS_RIGHT_ACTION_WRITE debe establecerse cada vez que una llamada escribe una clasificación. La llamada debe probar la marca FWPS_RIGHT_ACTION_WRITE para comprobar los derechos de la llamada para devolver una acción. Si no se establece esta marca, la llamada puede seguir devolviendo una acción de FWP_ACTION_BLOCK con el fin de vetar una acción FWP_ACTION_PERMIT que devolvió una llamada anterior.
En Windows 8 y versiones posteriores, el controlador de llamada debe consultar el estado de redirección de la conexión (para ver si el controlador de llamada u otro controlador de llamada lo ha modificado) mediante la función FwpsQueryConnectionRedirectState0. Si el controlador de llamada redirige la conexión o si el controlador de llamada la redirigió anteriormente, el controlador de llamada no debería hacer nada. De lo contrario, también debe comprobar si hay redirección local, como se muestra en el ejemplo siguiente:
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 conexión es a un proxy local, el controlador de llamada no debe intentar redirigirla.
Los controladores de llamada que usan la redirección de conexión deben registrarse en la capa de conexión de autorización de ALE (FWPS_LAYER_ALE_AUTH_CONNECT_V4 o FWPS_LAYER_ALE_AUTH_CONNECT_V6) y comprobar los dos valores de metadatos siguientes para ver las indicaciones en las que se establece la marca FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED:
FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID contiene el identificador de proceso del proceso responsable del flujo redirigido.
FWPS_METADATA_FIELD_ORIGINAL_DESTINATION contiene la dirección del destino original del flujo.
La estructura FWPS_CONNECT_REQUEST0 contiene un miembro denominado localRedirectTargetPID. Para que cualquier redirección de conexión de bucle invertido sea válida, este campo debe rellenarse con el PID del proceso que será responsable del flujo redirigido. Estos son los mismos datos que el motor pasa en las capas de conexión de autorización de ALE como FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID.
A partir de Windows 8, el servicio de proxy debe emitir los IOCTL SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS y SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT mediante WSAIoctl, en el punto de conexión original del servicio de proxy. Además, se debe emitir el IOCTL SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS, mediante WSAIoctl, en el nuevo socket (proxy).
Temas relacionados
Nombres independientes de la versión de WFP y versiones específicas de destino de Windows