Problem using filters with C#

Home Forums Discussions Support Problem using filters with C#

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #11251
    Riccardp
    Participant

      Hello,

      I’m experimenting with Winpkfilter in C# (using the ndisapi.net wrapper library provided at the official github repository), however I can’t figure out how to use filters properly.

      I’m able to set the adapter mode and analyze/block/forward packets correctly with (receiving mode):

      
      var filter = NdisApi.Open();
      if (!filter.IsValid)
          throw new ApplicationException("Cannot load driver.");
      
      filter.SetAdapterMode(networkAdapter, NdisApiDotNet.Native.NdisApi.MSTCP_FLAGS.MSTCP_FLAG_RECV_TUNNEL);

      where networkAdapter comes from GetNetworkAdapters().

      However, if I try to set up a TCP filter to block incoming traffic from ports 80 through 443, the filter is completely ignored.

      
      var filter = NdisApi.Open();
      if (!filter.IsValid)
          throw new ApplicationException("Cannot load driver.");
      
      // Filter table
      var ft = new NdisApiDotNet.Native.NdisApi.STATIC_FILTER_TABLE();
      ft.TableSize = 1;
      ft.StaticFilters = new NdisApiDotNet.Native.NdisApi.STATIC_FILTER[256];
      
      // First and only filter 
      var sf = ft.StaticFilters[0];
      sf.AdapterHandle = networkAdapter.Handle;
      sf.Direction = NdisApiDotNet.Native.NdisApi.PACKET_FLAG.PACKET_FLAG_ON_RECEIVE;
      sf.Action = NdisApiDotNet.Native.NdisApi.FILTER_PACKET_ACTION.FILTER_PACKET_DROP;
      sf.ValidFields = NdisApiDotNet.Native.NdisApi.STATIC_FILTER_FIELDS.NETWORK_LAYER_VALID | NdisApiDotNet.Native.NdisApi.STATIC_FILTER_FIELDS.TRANSPORT_LAYER_VALID;
      
      // Transport filter - PORT FROM 80 TO 443
      var tf = new NdisApiDotNet.Native.NdisApi.TRANSPORT_LAYER_FILTER();
      tf.Selector = NdisApiDotNet.Native.NdisApi.FILTER_SELECT_FLAGS.TCPUDP;
      var tuf = new NdisApiDotNet.Native.NdisApi.TCPUDP_FILTER();
      tuf.ValidFields = NdisApiDotNet.Native.NdisApi.TCPUDP_FILTER_FIELDS.TCPUDP_SRC_PORT;
      tuf.Source = new NdisApiDotNet.Native.NdisApi.PORT_RANGE(80, 443);
      tf.Filter = tuf;
      sf.TransportFilter = tf;
      
      // Network filter - TCP protocol
      var nf = new NdisApiDotNet.Native.NdisApi.NETWORK_LAYER_FILTER();
      nf.Selector = NdisApiDotNet.Native.NdisApi.FILTER_SELECT_FLAGS.IPV4;
      var ipf = new NdisApiDotNet.Native.NdisApi.IP_V4_FILTER();
      ipf.ValidFields = NdisApiDotNet.Native.NdisApi.IP_V4_FILTER_FIELDS.IP_V4_FILTER_PROTOCOL;
      ipf.NextProtocol = 6;
      nf.IPv4 = ipf;
      sf.NetworkFilter = nf;
      
      success = filter.SetPacketFilterTable(ft);
      if (!success) throw Exception("Error");

      I really don’t understand why the filters (every kind of filter I try) don’t work. It is true that I could simply redirect all the traffic and filter by inspecting the packet myself, but I’d prefer to redirect only the minimum amount of traffic required. I’m using Windows 10 Home 1909 and tried both x86 and x64 drivers.

      Thanks for the help.

      #11253
      Vadim Smirnov
      Keymaster

        Below sf assigned a copy of the ft.StaticFilters[0]

        var sf = ft.StaticFilters[0];

        and then the copy is initialized. So, you should assign it back after initialization or define sf as a reference to ft.StaticFilters[0]

        ref var sf = ref ft.StaticFilters[0];

        #11254
        Riccardp
        Participant

          Thank you Vadim, that was clearly a dumb mistake by me… now everything works.
          Just another quick question so that I completely understand how filtering works.

          From the experiments I did, the only way I found to redirect some packets and let everything else pass is to use MSTCP_FLAG_TUNNEL for the adapter mode and then specify 2 filters: the first with the action FILTER_PACKET_REDIRECT that intercepts the packets I’m interested in, and then a second filter with action FILTER_PACKET_PASS to let everything else pass through. Am I correct? Or is there a way for example to set the adapter mode in something like “let everything pass” and then use a single filter with the action FILTER_PACKET_REDIRECT?

          Thanks again for your help.

          #11255
          Vadim Smirnov
          Keymaster

            From the experiments I did, the only way I found to redirect some packets and let everything else pass is to use MSTCP_FLAG_TUNNEL for the adapter mode and then specify 2 filters: the first with the action FILTER_PACKET_REDIRECT that intercepts the packets I’m interested in, and then a second filter with action FILTER_PACKET_PASS to let everything else pass through. Am I correct?

            Yes, you are right! There is also an alternative approach, when adapter is in tunnel mode then REDIRECT is a default action, so you can load one or more filters to pass selected traffic over and everything else will be redirected to your application automatically.

            Or is there a way for example to set the adapter mode in something like “let everything pass” and then use a single filter with the action FILTER_PACKET_REDIRECT?

            No, it won’t work. Adapter mode defines if network interface is filtered or not (independently in each direction). If it is not then loaded filters are not applied and all the traffic is passed over.

            #11256
            Riccardp
            Participant

              Great, now I understand much better, thank you!

            Viewing 5 posts - 1 through 5 (of 5 total)
            • You must be logged in to reply to this topic.