Uso di Bind o Connect Redirection
La funzionalità di reindirizzamento di connessione/associazione di Windows Filtering Platform (WFP) consente ai driver callout di applicazione (ALE) di controllare e, se necessario, reindirizzare le connessioni.
Questa funzionalità è disponibile in Windows 7 e versioni successive.
Nota Il modulo ClassifyFunctions_ProxyCallouts.cpp nell'esempio di driver WFP include codice che illustra il reindirizzamento di connessione/associazione.
Un callout di reindirizzamento della connessione WFP reindirizza la richiesta di connessione di un'applicazione in modo che l'applicazione si connetta a un servizio proxy anziché alla destinazione originale. Il servizio proxy ha due socket: uno per la connessione originale reindirizzata e uno per la nuova connessione in uscita proxied.
Un record di reindirizzamento WFP è un buffer di dati opachi che il WFP deve impostare su una connessione proxy in uscita ai livelli FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V4 e FWPM_LAYER_ALE_AUTH_CONNECT_REDIRECT_V6 , in modo che la connessione reindirizzata e la connessione originale siano correlate logicamente.
La modifica dell'indirizzo locale e della porta di un flusso è supportata solo nel livello bind-redirect. Questa funzionalità non è supportata nel livello di reindirizzamento della connessione.
Livelli usati per il reindirizzamento
I driver callout possono preformare il reindirizzamento ai livelli seguenti, denominati "livelli di reindirizzamento":
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)
Il livello in cui viene eseguito il reindirizzamento determina l'effetto della modifica. Le modifiche ai livelli di connessione influiscono solo sul flusso connesso. Le modifiche ai livelli di associazione influiscono su tutte le connessioni che usano tale socket.
I livelli di reindirizzamento sono disponibili solo per Windows 7 e versioni successive di Windows. I driver callout che supportano la classificazione a questi livelli devono registrarsi usando FwpsCalloutRegister1 o versione successiva, non la funzione FwpsCalloutRegister0 precedente.
Importante
Il reindirizzamento non è disponibile per l'uso con tutti i tipi di traffico di rete. I tipi di pacchetti supportati per il reindirizzamento sono visualizzati nell'elenco seguente:
- TCP
- UDP
- UDPv4 non elaborato senza l'opzione di inclusione dell'intestazione
- ICMP non elaborato
Esecuzione del reindirizzamento
Per reindirizzare una connessione, il driver callout deve ottenere una copia scrivibile delle informazioni sulla tupla TCP 4, apportare modifiche in base alle esigenze e applicare le modifiche. Viene fornito un set di nuove funzioni per ottenere dati di livello scrivibili e applicarli tramite il motore. I driver callout hanno la possibilità di apportare modifiche inline nelle funzioni classifyFn o in modo asincrono in un'altra funzione.
I driver callout che implementano il reindirizzamento devono usare classifyFn1 o versione successiva anziché classificareFn0 come funzione callout di classificazione. Per usare classifyFn1 o versione successiva, il callout deve essere registrato chiamando FwpsCalloutRegister1 o versione successiva, non il precedente FwpsCalloutRegister0.
Per eseguire il reindirizzamento inline di un driver callout, è necessario eseguire i passaggi seguenti nell'implementazione di classifyFn:
Chiamare FwpsRedirectHandleCreate0 per ottenere un handle che può essere usato per reindirizzare le connessioni TCP. Questo handle deve essere memorizzato nella cache e usato per tutti i reindirizzamenti. Questo passaggio viene omesso per Windows 7 e versioni precedenti.
In Windows 8 e versioni successive è necessario eseguire una query sullo stato di reindirizzamento della connessione usando la funzione FwpsQueryConnectionRedirectState0 nel driver di callout. Questa operazione deve essere eseguita per evitare il reindirizzamento infinito.
Chiamare FwpsAcquireClassifyHandle0 per ottenere un handle che verrà usato per le chiamate di funzione successive.
Chiamare FwpsAcquireWritableLayerDataPointer0 per ottenere la struttura dei dati scrivibile per il livello in cui è stato chiamato classifyFn . Eseguire il cast del parametro writableLayerData out alla struttura corrispondente al livello, FWPS_BIND_REQUEST0 o FWPS_CONNECT_REQUEST0.
A partire da Windows 8, se il driver del callout viene reindirizzato a un servizio locale, è necessario chiamare FwpsRedirectHandleCreate0 per compilare il membro localRedirectHandle della struttura FWPS_CONNECT_REQUEST0 per consentire il funzionamento del proxy locale.
Apportare modifiche ai dati del livello in base alle esigenze:
Salvare la destinazione originale nel contesto di reindirizzamento locale, come illustrato nell'esempio seguente:
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(…);
Modificare l'indirizzo remoto come illustrato nell'esempio seguente:
// 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));
Se il driver del callout viene reindirizzato a un servizio locale, deve impostare il PID proxy locale nel membro localRedirectTargetPID della struttura FWPS_CONNECT_REQUEST0 .
Se il driver del callout viene reindirizzato a un servizio locale, deve impostare l'handle di reindirizzamento restituito da FwpsRedirectHandleCreate0 nel membro localRedirectHandle della struttura FWPS_CONNECT_REQUEST0.
Chiama FwpsApplyModifiedLayerData0 per applicare le modifiche apportate ai dati.
Nel servizio proxy (che potrebbe essere in modalità utente o kernel), è necessario eseguire query su record e contesti di reindirizzamento, come illustrato nell'esempio seguente:
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
Nel servizio proxy (che potrebbe essere in modalità utente o kernel), è necessario impostare i record di reindirizzamento nel socket di connessione proxy, come illustrato nell'esempio seguente per creare un nuovo socket in uscita:
proxySock = WSASocket(…); result = WSAIoctl( proxySock, SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS, redirectRecords, …);
Chiamare FwpsReleaseClassifyHandle0 per rilasciare l'handle di classificazione ottenuto nel passaggio 2.
Chiamare FwpsRedirectHandleDestroy0 per eliminare definitivamente l'handle ottenuto nel passaggio 1.
Per eseguire il reindirizzamento in modo asincrono, un driver callout deve seguire questa procedura:
Chiamare FwpsRedirectHandleCreate0 per ottenere un handle che può essere usato per reindirizzare le connessioni TCP. Questo passaggio viene omesso per Windows 7 e versioni precedenti.
In Windows 8 e versioni successive è necessario eseguire una query sullo stato di reindirizzamento della connessione usando la funzione FwpsQueryConnectionRedirectState0 nel driver di callout.
Chiamare FwpsAcquireClassifyHandle0 per ottenere un handle che verrà usato per le chiamate di funzione successive. Questo passaggio e i passaggi 2 e 3 vengono eseguiti nella funzione di callout classifyFn del driver callout.
Chiamare FwpsPendClassify0 per inserire la classificazione in uno stato in sospeso, come illustrato nell'esempio seguente:
FwpsPendClassify( redirectContext->classifyHandle, 0, &redirectContext->classifyOut); classifyOut->actionType = FWP_ACTION_BLOCK; classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
Nota
Se si ha come destinazione Windows 7, è necessario eseguire i passaggi seguenti in una funzione di lavoro separata. Se si ha come destinazione Windows 8 o versione successiva, è possibile eseguire tutti i passaggi per il reindirizzamento asincrono dall'interno di classifyFn e ignorare il passaggio 5.
Inviare l'handle di classificazione e i dati del livello scrivibili a un'altra funzione per l'elaborazione asincrona. I passaggi rimanenti vengono eseguiti in tale funzione, non nell'implementazione del driver callout di classifyFn.
Chiamare FwpsAcquireWritableLayerDataPointer0 per ottenere la struttura dei dati scrivibile per il livello in cui è stato chiamato classifyFn . Eseguire il cast del parametro writableLayerData out alla struttura corrispondente al livello, FWPS_BIND_REQUEST0 o FWPS_CONNECT_REQUEST0.
A partire da Windows 8, se il driver del callout viene reindirizzato in locale, è necessario chiamare FwpsRedirectHandleCreate0 per compilare il membro localRedirectHandle della struttura FWPS_CONNECT_REQUEST0 per consentire il funzionamento del proxy.
Archiviare tutte le informazioni di contesto specifiche del callout in una struttura di contesto privato, come illustrato nell'esempio seguente:
redirectContext->classifyHandle = classifyHandle; redirectContext->connectRequest = connectRequest; redirectContext->classifyOut = *classifyOut; // deep copy // store original destination IP, port
Apportare modifiche ai dati del livello in base alle esigenze.
Chiama FwpsApplyModifiedLayerData0 per applicare le modifiche apportate ai dati. Impostare il flag FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS se si desidera essere nuovamente autorizzati nel caso in cui un altro callout modifichi ulteriormente i dati.
Chiamare FwpsCompleteClassify0 per completare l'operazione di classificazione in modo asincrono, come illustrato nell'esempio seguente:
FwpsCompleteClassify( redirectContext->classifyHandle, 0, &redirectContext->classifyOut); classifyOut->actionType = FWP_ACTION_PERMIT; classifyOut->rights |= FWPS_RIGHT_ACTION_WRITE;
Chiamare FwpsReleaseClassifyHandle0 per rilasciare l'handle di classificazione ottenuto nel passaggio 1.
Gestione del reindirizzamento della connessione da più callout
È possibile che più di un driver callout avvii il reindirizzamento della connessione per lo stesso flusso. I callout che eseguono il reindirizzamento della connessione devono essere consapevoli di altre richieste e rispondere in modo appropriato.
Il flag FWPS_RIGHT_ACTION_WRITE deve essere impostato ogni volta che un callout esegue una classificazione. Il callout deve verificare la presenza del flag FWPS_RIGHT_ACTION_WRITE per verificare i diritti del callout per restituire un'azione. Se questo flag non è impostato, il callout può comunque restituire un'azione FWP_ACTION_BLOCK per impostare un'azione di FWP_ACTION_PERMIT restituita da un callout precedente.
In Windows 8 e versioni successive, il driver callout deve eseguire una query sullo stato di reindirizzamento della connessione (per verificare se il driver callout o un altro driver callout lo ha modificato) usando la funzione FwpsQueryConnectionRedirectState0. Se la connessione viene reindirizzata dal driver callout o se è stata reindirizzata in precedenza dal driver callout, il driver callout non deve eseguire alcuna operazione. In caso contrario, deve anche verificare la presenza di reindirizzamento locale, come illustrato nell'esempio seguente:
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);
}
}
Se la connessione è a un proxy locale, il driver callout non deve tentare di reindirizzarlo.
I driver callout che usano il reindirizzamento della connessione devono registrarsi al livello di connessione dell'autorizzazione ALE (FWPS_LAYER_ALE_AUTH_CONNECT_V4 o FWPS_LAYER_ALE_AUTH_CONNECT_V6) e controllare i due valori di metadati seguenti per individuare le indicazioni in cui è impostato il flag di FWP_CONDITION_FLAG_IS_CONNECTION_REDIRECTED:
FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID contiene l'identificatore del processo responsabile del flusso reindirizzato.
FWPS_METADATA_FIELD_ORIGINAL_DESTINATION contiene l'indirizzo della destinazione originale per il flusso.
La struttura FWPS_CONNECT_REQUEST0 contiene un membro denominato localRedirectTargetPID. Affinché qualsiasi reindirizzamento della connessione loopback sia valido, questo campo deve essere popolato con il PID del processo che sarà responsabile del flusso reindirizzato. Si tratta degli stessi dati che il motore passa ai livelli di connessione dell'autorizzazione ALE come FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_ID.
A partire da Windows 8, il servizio proxy deve emettere i SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS e SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT IOCTLs, usando WSAIoctl, sull'endpoint originale del servizio proxy. Inoltre, il SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS IOCTL deve essere rilasciato, usando WSAIoctl, sul nuovo socket (proxy).
Argomenti correlati
Nomi indipendenti dalla versione WFP e destinazione di versioni specifiche di Windows