basil00 / WinDivert

WinDivert: Windows Packet Divert
https://reqrypt.org/windivert.html
Other
2.56k stars 513 forks source link

In place drop some packets in a batch without copy/move #331

Open Lingxi-Li opened 1 year ago

Lingxi-Li commented 1 year ago

Consider the scenario where user

  1. receives a batch with WinDivertRecvEx,
  2. drops some packets in the batch,
  3. sends the rest with WinDivertSendEx.

I want to do this in place without expensive memory copy/move. I hoped to find a Drop flag in WINDIVERT_ADDRESS for WinDivertSendEx to ignore the corresponding packet in the data buffer. This way, I only need to set some Drop flags and pass the data/address buffer used for WinDivertRecvEx directly to WinDivertSendEx without any copy/move. Unfortunately, such a flag does not exist.

I've thought about some alternatives. E.g., redirect packets to drop to a special destination address and have another WinDivert handle capture them and drop like a blackhole. These alternatives are not ideal and incur performance overhead.

@basil00 Want to know your opinions on this. Thanks.

basil00 commented 1 year ago

I think adding a Drop flag is a good idea. I am not sure if it will make a big performance improvement in practice, but it cannot hurt.

Currently, the best you can do is (1) set the Impostor flag, (2) set ip.TTL (or ipv6.HopLimit) field to 0, and (3) ignore the ERROR_HOST_UNREACHABLE error returned by WinDivertRecvEx. However, this is probably less efficient, since WinDivert will still make a copy of the packet internally (including malloc+free) before dropping it.

Lingxi-Li commented 1 year ago

Thanks for the reply. Draining TTL is a much better alternative than what I've come up with. I'm not quite sure about the Impostor flag though. What if ip.TTL is set to 0 without setting Impostor? Is this for WinDivertSendEx to trap and handle the time exceeded ICMP reply (and hence the ERROR_HOST_UNREACHABLE error)?