TechnikEmpire / CitadelCore.Windows

Citadel Core platform-specific implementation for Windows
Mozilla Public License 2.0
23 stars 16 forks source link

Proxy intercepting is unstable #16

Closed hitgubmitt closed 4 years ago

hitgubmitt commented 4 years ago

It seems that WinDivert driver doesn't intercept traffic for processes started after CitadelCore. For example, all browsers need to be restarter if they were launched before the CitadelCore. I am not able to reproduce this issue on all occasions, but it happens very often.

Is this a bug or a known limitation?

TechnikEmpire commented 4 years ago

This is due to the fact that the browser holds open connections and recycles them and the logic of the windiverter class is to consider intercepting whenever you see a new TCP syn, which of course won't happen for those existing connections.

Same thing happens if you go down into the wfp stack and do connection interception. I've written a driver that suffers the same way but I don't care because my app launches at PC startup as a service so it doesn't affect me.

What you can easily do is modify the windiverter class (c#) to send RST packets back to connections you don't recognise. That'll solve this issue but also means you implement at least a crude form of connection tracking.

TechnikEmpire commented 4 years ago

Another way you could easily solve this actually is to hit the tcptable2, get a list of all open local tcp ports on startup and if the apps are in your filtering list, fire off RSTs at those ports. No connection tracking required, ez pz. The code to pinvoke the tcptable iirc is already in the code. It might be suffering a memory leak though I can't remember as I've discontinued dev publicly. If the signature is a byte array youre good. If not you need to change it to byte array, pin it on return and marshal pointer to structure to avoid the leak.

hitgubmitt commented 4 years ago

For almost 2 months, running CitadelCore as a service was all I needed. Unfortunately the issue came back and bite me so I returned to this question.

For killing TCP connections, sending RST seems to be the best option, because there is no SetTcpEntry that accepts MIB_TCP6ROW structure and so you are limited to only be able to kill IPv4 conns. To the best of my understanding.. to send a valid RST, you need to also send acknowledgement number. That means you need to wait for a packet to be sent over the wire, grab it's ACK number, drop it and send a RST. If there is no packet, then it is not possible to create a valid ACK number. Is there some other way around it?

Also, in https://github.com/TechnikEmpire/WinDivertSharp/blob/master/WinDivertSharpTests/TestData.cs all packet byte arrays are hardcoded. Did you coin the arrays directly from looking at specs or do you recommend some library for building packets? Converting from host to network order always gives me headaches.

TechnikEmpire commented 4 years ago

@hitgubmitt Those tests and their data is copied directly from the WinDivert project here on Github. What I've done when necessary is fired up wireshark and captured the type of packets I'm after, then copy the raw bytes out of the capture file.

I have an idea, why don't you just simply turn off network connectivity and then turn it back on programattically? For example:

https://stackoverflow.com/questions/172875/how-to-disable-enable-network-connection-in-c-sharp

That will make those TCP connections die and thus have to be re-established. I have no idea why I never thought of that before myself, but I'll be using it. Clean, no headache involved.