Closed jjxtra closed 5 years ago
Alternatively, is there a way to simply mark a packet as dropped in place without copying memory or needing to recalculate checksums, etc.?
This would probably have been a good idea in hindsight.
Fortunately, you can use the following hack:
addr.*Checksum
fields to 1
.addr.Impostor
field to 1
.ip.TTL
or ipv6.HopLimit
to 0.The driver will ignore the packet, but will still inject all the others. You also need to ignore the ERROR_HOST_UNREACHABLE
error code returned by WinDivertSendEx
.
Do I have to set all 3 or just pick one?
Also I realize this is not a commercial license thread, but if I paid for a 500 USD commercial license, would that cover unlimited distribution for one software product? Or is it 500 USD per user?
Setting the flags is just to stop the driver from recalculating the checksums, since the packet is to be discarded anyway.
would that cover unlimited distribution for one software product?
The license is tied to a company/individual who can create and distribute any number of products that use WinDivert. Remember WinDivert is free (LGPL) anyway, so the commercial license is mainly for those that prefer to pay for a non-GPL license or want guaranteed support.
Thought I should tell you that I am matching Windows firewall performance with 300000 ip address ranges in a block rule. Takes a few hundred milliseconds to create the rules in my C# code vs 5 minutes to create the rules with Windows firewall COM API (WTF Microsoft). This is using filter 'inbound and tcp.Syn.'
I did the following, packets appear to still go through, but I commented in the other issue about my address struct possibly having the udp checksum bit set for a tcp packet so I assume my bit fields are not quite right. I worked on some embedded systems, we never used the C bit field syntax because it re-arranged things and made interop with other systems impossible. We always wrote methods to get and set bit fields.
Set the addr.*Checksum fields to 1. Set the addr.Impostor field to 1. Set the ip.TTL or ipv6.HopLimit to 0.
Basil doesn't do c#. That's why I write an unofficial wrapper. The structs can be done but its hard. Pinvoke assistant crashes on it so its all gotta be done by hand.
I think the problem with the address struct is that the C/C++ compiler has re-ordered some bit fields. Every other field besides flags looks correct.
It doesn't reorder the bits that's the whole point of the explicit field modifiers. You need to union on places, use the correct .net integral types, use explicit layouts and set field offsets.
Any such reordering happens on the .net side if you don't decorate the struct properly.
With sequential or explicit with and without field offset, flags is still not right. So either the udp bit is really the tcp ip bit or somehow a udp packet is sneaking through, I think it is the former given that the packet has a tcp and ipv4 header. Anyone using the windivert.h file would never be the wiser, but because I'm in C# it doesn't have the same bitfield logic I guess.
Same error in visual C++, looks like it may be a .dll problem. I will log a new issue.
I am using windivert 2.0 and enjoy the batching capability, however when filtering out packets things become a little tricky.
I can drop down to WinDivertSend and send each packet one by one, skipping any packets I want to filter or changing them to rst packets. This requires a kernel transition for each packet, defeating the purpose of batching.
One workaround I have is to slide memory over the top of the filtered packet and address buffer, effectively dropping it from the list. As long as no packets are filtered everything is fine, no performance impact. But when filtering a lot of packets, say from an attacker who is being persistent or ddos, this adds up to a lot of memcpy calls.
I'd love feedback on this idea, creating a new batching API for WinDivertSendEx that allows passing an array of pointers for the packets along with an array of pointers for the addresses. The array would be constructed by the caller. Any filtered pointers would simply not be added to the array, eliminating the memcpy problem at the expense of populating a small array with pointers, a big win in my opinion. This becomes even more performance intensive when using a whitelist strategy versus a blacklist strategy.
Alternatively, is there a way to simply mark a packet as dropped in place without copying memory or needing to recalculate checksums, etc.?