February 4, 2020 at 2:47 pm #11251
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; // First and only filter var sf = ft.StaticFilters; 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.February 4, 2020 at 3:35 pm #11253Vadim SmirnovModerator
Below sf assigned a copy of the ft.StaticFilters
var sf = ft.StaticFilters;
and then the copy is initialized. So, you should assign it back after initialization or define sf as a reference to ft.StaticFilters
ref var sf = ref ft.StaticFilters;February 5, 2020 at 9:58 am #11254
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_TUNNELfor the adapter mode and then specify 2 filters: the first with the action
FILTER_PACKET_REDIRECTthat intercepts the packets I’m interested in, and then a second filter with action
FILTER_PACKET_PASSto 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
Thanks again for your help.February 5, 2020 at 2:08 pm #11255Vadim SmirnovModerator
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.February 5, 2020 at 2:24 pm #11256
Great, now I understand much better, thank you!
- You must be logged in to reply to this topic.