none
cannot get working tcp stream redirection on Windows7 using FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 RRS feed

  • Question

  • Hi all,

    I am trying redirect TCP request to a local proxy, based on the ddproxy sample. Using Win7 (32bit) and FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 layer. The code is below (status checks are removed).

    When the callout driver is started, I cannot ping to/from the machine where it's running (when it's stopped ping is ok both ways).

    The client is running on the machine with the callout returns error: "The requested address is not valid in its context 172.16.16.34:1350".

    What I possibly misused here? Do I have to call FwpmCalloutAdd0 after I called FwpsCalloutRegister1? At what sublayer I should set the filter if FWPM_SUBLAYER_UNIVERSAL is not correct? Is actiontype FWP_ACTION_PERMIT or FWP_ACTION_CALLOUT_INSPECTION ok to use for the filter?

    Thanks, Alex.

     

    DriverEntry(
    	IN PDRIVER_OBJECT driverObject,
    	IN PUNICODE_STRING registryPath ){
     NTSTATUS status = STATUS_SUCCESS;
     UNICODE_STRING deviceName;
    
     DDProxyLoadConfig(registryPath);
    
     RtlInitUnicodeString( &deviceName, L"\\Device\\StreamEitor" );
    
     status = IoCreateDevice(driverObject, 0, &deviceName, FILE_DEVICE_NETWORK, 0, FALSE, &gDeviceObject);
    
     status = RegisterCallouts(  gDeviceObject  );
    
     driverObject->DriverUnload = DriverUnload;
    
     if (!NT_SUCCESS(status)) {
     if (gEngineHandle != NULL) {
      DDProxyUnregisterCallouts();
     }
     if (gDeviceObject) {
      IoDeleteDevice(gDeviceObject);
     }
     }
     return status;
    }
    
    ---------------------
    RegisterCallouts( IN void* deviceObject ){
     NTSTATUS status = STATUS_SUCCESS;
     FWPM_SUBLAYER0 TCPRedirectorSubLayer;
     BOOLEAN engineOpened = FALSE;
     BOOLEAN inTransaction = FALSE;
     FWPM_SESSION0 session = {0};
     session.flags = FWPM_SESSION_FLAG_DYNAMIC;
    
     status = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &gEngineHandle );
     engineOpened = TRUE;
     status = FwpmTransactionBegin0(gEngineHandle, 0);
     inTransaction = TRUE;
     RtlZeroMemory(&TCPRedirectorSubLayer, sizeof(FWPM_SUBLAYER0)); 
    
     TCPRedirectorSubLayer.subLayerKey = TCP_REDIRECTOR_SUBLAYER;
     TCPRedirectorSubLayer.displayData.name = L"TCP redirector sub-layer";
     TCPRedirectorSubLayer.displayData.description = L"sub-layer for use by tcp redirector proxy callouts";
     TCPRedirectorSubLayer.flags = 0;
     TCPRedirectorSubLayer.weight = FWP_EMPTY; // auto-weight.;
    
     status = FwpmSubLayerAdd0(gEngineHandle, &TCPRedirectorSubLayer, NULL);
     status = ConnRedirectCallout(
      &FWPM_LAYER_ALE_CONNECT_REDIRECT_V4,
      &TCP_REDIRECTOR_CALLOUT_CONNECT_REDIRECT_V4,
      deviceObject,
      &gFlowEstablishedCalloutIdV4
      );
     status = FwpmTransactionCommit0(gEngineHandle);
     inTransaction = FALSE;
     return status;
    }
    -------------------
    ConnRedirectCallout(
    	IN const GUID* layerKey,
    	IN const GUID* calloutKey,
    	IN void* deviceObject,
    	OUT UINT32* calloutId ){
     NTSTATUS status = STATUS_SUCCESS;
     FWPS_CALLOUT1 sCallout = {0};
     FWPM_CALLOUT0 mCallout = {0};
     FWPM_DISPLAY_DATA0 displayData = {0};
     BOOLEAN calloutRegistered = FALSE;
    
     sCallout.calloutKey = *calloutKey;
     sCallout.classifyFn = TCPRedirectorClassify1;
     sCallout.notifyFn = TCPRedirectorNotify1;
    
     status = FwpsCalloutRegister1(
      deviceObject,
      &sCallout,
      calloutId
      );
     calloutRegistered = TRUE;
    
     displayData.name = L"TCP Redirector Callout";
     displayData.description = L"Streamwise redirector for TCP traffic";
    
     mCallout.calloutKey = *calloutKey;
     mCallout.displayData = displayData;
     mCallout.applicableLayer = *layerKey;
    
     status = FwpmCalloutAdd0(
      gEngineHandle,
      &mCallout,
      NULL,
      NULL
      );
     status = DDProxyAddFilter(
      L"TCP redirector Proxy Filter",
      L"Proxies destination address/port for TCP",
      configInspectDestAddrV4,
      configInspectDestPort,
      0,
      0,
      layerKey,
      calloutKey
      );
     return status;
    }
    --------------
    DDProxyAddFilter( IN const wchar_t* filterName,
     IN const wchar_t* filterDesc,
     IN const UINT8* remoteAddr,
     IN USHORT remotePort,
     IN FWP_DIRECTION direction,
     IN UINT64 context,
     IN const GUID* layerKey,
     IN const GUID* calloutKey ){

    NTSTATUS status = STATUS_SUCCESS;
    FWPM_FILTER0 filter = {0};
    RtlZeroMemory(&filter, sizeof(FWPM_FILTER0));
    filter.layerKey = *layerKey;
    filter.displayData.name = (wchar_t*)filterName;
    filter.displayData.description = (wchar_t*)filterDesc;
    filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;//FWP_ACTION_CALLOUT_TERMINATING;
    filter.action.calloutKey = *calloutKey;
    filter.weight.type = FWP_EMPTY; // auto-weight.
    filter.rawContext = context;
    filter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL;
    filter.numFilterConditions = 0;
    status = FwpmFilterAdd0(gEngineHandle, &filter, NULL, NULL);
    
    return status;
    }
    ---------------
    TCPRedirectorClassify1(
    	IN const FWPS_INCOMING_VALUES0* inFixedValues,
    	IN const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    	IN OUT void* layerData,
    	__in_opt const void *classifyContext,
    	IN const FWPS_FILTER1* filter,
    	IN UINT64 flowContext,
    	OUT FWPS_CLASSIFY_OUT0* classifyOut

    ){
    UINT64 classifyHandle;
    NTSTATUS status = STATUS_SUCCESS;
    FWPS_CONNECT_REQUEST0* modifiedLayerData;
    UNREFERENCED_PARAMETER(flowContext);
    UNREFERENCED_PARAMETER(layerData);
    
    status = FwpsAcquireClassifyHandle0(classifyContext, (UINT32)0, &classifyHandle);
    if (NT_SUCCESS(status)){
    status = FwpsAcquireWritableLayerDataPointer0(classifyHandle, filter->filterId, (UINT32)0, 
    (void*)&modifiedLayerData, classifyOut );
    if (NT_SUCCESS(status)){
    ((SOCKADDR_IN*)&modifiedLayerData->remoteAddressAndPort)->sin_addr.S_un.S_addr = configNewDestAddrV4;
    ((SOCKADDR_IN*)&modifiedLayerData->remoteAddressAndPort)->sin_port = RtlUshortByteSwap(configNewDestPort);
    ((SOCKADDR_IN*)&modifiedLayerData->localAddressAndPort)->sin_addr.S_un.S_addr = configInspectDestAddrV4;
    ((SOCKADDR_IN*)&modifiedLayerData->localAddressAndPort)->sin_port = RtlUshortByteSwap(configInspectDestPort);
    modifiedLayerData->localRedirectTargetPID = configLocalRedirectTargetPID; // local proxy's PID
    FwpsApplyModifiedLayerData0(
    classifyHandle,
    (PVOID)modifiedLayerData,
    FWPS_CLASSIFY_FLAG_REAUTHORIZE_IF_MODIFIED_BY_OTHERS
    );
    }
    
    FwpsReleaseClassifyHandle0( classifyHandle );
    }
    
    return;
    }
    
    

     

    Wednesday, September 8, 2010 2:01 PM

Answers

  • FwpsCalloutRegister makes BFE aware of what functions it needs to invoke for classification.  FwpmCalloutAdd creates a bridge between the filter and the registration.  by default if you add a callout without registering, BFE treats the classification as a block.  If you register the callout without adding it and referenceing it in a filter, then nothing is affected other than resources used for the registration.  So in short, yes you need to add the callout after you register it if you want it to be invoked.

    You should create your own sublayer and add your filters to this sublayer.  This will benefit you most when multiple providers are on the same machine competing for the decision.

    http://msdn.microsoft.com/en-us/library/ff571005.aspx

    Hope this helps


    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------
    • Marked as answer by Doolav Friday, November 19, 2010 1:51 PM
    Wednesday, September 8, 2010 8:29 PM
    Moderator

All replies

  • FwpsCalloutRegister makes BFE aware of what functions it needs to invoke for classification.  FwpmCalloutAdd creates a bridge between the filter and the registration.  by default if you add a callout without registering, BFE treats the classification as a block.  If you register the callout without adding it and referenceing it in a filter, then nothing is affected other than resources used for the registration.  So in short, yes you need to add the callout after you register it if you want it to be invoked.

    You should create your own sublayer and add your filters to this sublayer.  This will benefit you most when multiple providers are on the same machine competing for the decision.

    http://msdn.microsoft.com/en-us/library/ff571005.aspx

    Hope this helps


    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------
    • Marked as answer by Doolav Friday, November 19, 2010 1:51 PM
    Wednesday, September 8, 2010 8:29 PM
    Moderator
  • Hi Dusty,

    thanks, understood with the register and add.

    Now about the sublayer - but sublayer is created - it's TCPRedirectorSubLayer, although its weight=0 might that be a problem?

    Or is it this line

     

    filter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL

     

    where I assign to the filter a universal sublayer, while I really had to use the one I created (i.e. TCPRedirectorSubLayer)?

     

    Thanks for quick reply,

    Alex.

    Thursday, September 9, 2010 9:51 AM
  • - I just changed that bit, so it uses TCP_REDIRECTOR_SUBLAYER in place of FWPM_SUBLAYER_UNIVERSAL. Still cannot see that my callout's classify (TCPRedirectorClassify1) function being hit.
    Thursday, September 9, 2010 10:53 AM
  • I just tried to simplify this to the minimum... just a simple filter which would block all traffic. And it did not block. Then I tried a different filtering layer - (FWPM_LAYER_OUTBOUND_IPPACKET_V4 instead of FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 and FWPM_LAYER_ALE_BIND_REDIRECT_V4 ) - and traffic has been blocked.

    But I want to redirect a stream, so need to use FWPM_LAYER_ALE_CONNECT_REDIRECT_V4.

    Does stream redirection assume using filters? With what FWP_ACTION_...?

    Thursday, September 9, 2010 8:07 PM
  • Hi Dusty or whoever understands this issue, could you please comment on my previous questions - it's a bit confusing. How would one set a filter to work for FWPM_LAYER_ALE_CONNECT_REDIRECT_V4? Why my classifyFn would not trigger?

    I know Harry_NS had managed to get this working, but that was a while ago, not sure if he is reading this now, and there is not too many references on this available in the web.

    Monday, September 13, 2010 11:40 PM
  • http://msdn.microsoft.com/en-us/library/ff571005.aspx This layer requires a callout to be of any use. the above link explains the process in depth. Hope this helps
    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------
    Tuesday, September 14, 2010 4:02 AM
    Moderator
  • Thanks Dusty. Of course I did go through this link, and tried to follow it, however still something is missing.

    FWPS_LAYER_ALE_AUTH_CONNECT_V4 mentioned in this link - is this the filtering layer I should register my driver at (instead of FWPM_LAYER_OUTBOUND_IPPACKET_V4 or FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 or FWPM_LAYER_ALE_BIND_REDIRECT_V4)?

    Tuesday, September 14, 2010 8:36 AM
  • Your filter will sit at the ALE_CONNECT_REDIRECT layer. This will result in the invocation of your callout when the expected traffic is classified. AUTH_CONNECT is a means to see if anyone else is redirecting the same connection. Hope this helps
    Dusty Harper [MSFT]
    Microsoft Corporation
    ------------------------------------------------------------
    This posting is provided "AS IS", with NO warranties and confers NO rights
    ------------------------------------------------------------
    Tuesday, September 14, 2010 8:10 PM
    Moderator