Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request in nfqws : add delay option, and multiple copy of rst packet #49

Closed
ccaapton opened this issue Mar 18, 2020 · 12 comments
Closed

Comments

@ccaapton
Copy link

Hi, thanks a lot for this project, it is quite helpful. I have some feature suggestion for nfqws:

  1. Adding a delay parameter, and sleep for that delay before accept verdict. Otherwise the injected packet may fall behind the original packet in congested network environment.
  2. Adding a multi-copy parameter for rst packet. When the network condition is suboptimal and packet drop rate is high, our injected packet may get dropped before hit the DPI, so I hope to send multiple copies of it just in case.

Would you mind adding these feature?

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

  1. Simple sleep is unacceptable, because its blocking. To implement delay some queuing mechanism is required in another thread. In current version its possible to utilize OS built-in retransmission mechanism in fake/rst/rstack modes using --dpi-desync-retrans=1 option. First retransmission happens after 0.2 sec. OS kernel itself does what you request.
    2.Is it your real experience or just your thoughts ? In Russia DPIs are located on ISP level. ISP local connection is very stable. Theoretically there may be drops on the path to DPI in countries like China or Iran with centralized firewall. But I also think country intranet is much more stable than outside world. Or you are on a bad radio channel with high drop rate ?

@ccaapton
Copy link
Author

Indeed, naive sleeping is not acceptable. In terms of user experience, I can feel a significant slowdown when retransmission is enabled, perhapse 0.2 second is too long for each packet, especially when every packet in the stream will go through the queue. In contrast, delay of 2ms is enough for the injected packets to go ahead of the original one.

I'm not in Russia, and the peak packet drop rate here is crazy even for domestic traffic, so multiple copy of rst will be quite helpful.

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

No, not every packet is processed by desync. Only http requests (can be multiple) or TLS clienthello (only single per connection). It adds some delays but not too long.
If your drop rate is high then its your greater headache. With high packet loss everything will be damn slow.

Its not hard to add fake packet retransmission. if you want I'll do it.
But first I'd like you to test if it really helps.

At the end of desync.c find this code :

		if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
			return res;

and copy-paste it as many times as you want, then recompile

@ccaapton
Copy link
Author

I made three copies of rstack, and the success rate goes from 90% to 100% on 20 trial.

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

OK, i added --dpi-desync-repeats option. It resends every packet generated by nfqws N times

@ccaapton
Copy link
Author

When I am looking at the tcpdump of the final packets, I noticed that not only the fake packet is send multiple times, but also the original packet. Isn't it very strange? The original packet should be verdict as accept, how come it is also duplicated?

FYI, I'm testing on openwrt using POSTROUTING, curl from both openwrt itself or PC, the result of tcpdump looks the same.

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

Yes, its my mistake, i already fixed it in last commit
With retrans=0 nfqws reinjects original packet with nfq drop verdict
with retrans=1 is the same, but with no reinjection, leaving the os to retransmit it after 0.2s

@ccaapton
Copy link
Author

Thanks for the clarification!
I'm also curious about the ipv6 implementation. I didn't see the unbinding/rebinding of AF_INET6 in the code, yet it did work on v6, how does this work? I searched and here says you must bind on both. Will it have some hidden problem?

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

I dont know how it works. But it has always worked. With AF_INET queue receives both 4 and 6.

From docs :
Binds the given queue connection handle to process packets belonging to the given protocol family (ie. PF_INET, PF_INET6, etc). This call is obsolete, Linux kernels from 3.8 onwards ignore it.

This could explanation. But I tested this on centos 6 with 2.6 kernel and it also worked. Dont know why

@bol-van
Copy link
Owner

bol-van commented Mar 18, 2020

I rechecked and confirm it really does not work on older kernels.
Fixed in last commit

@ccaapton
Copy link
Author

An alternative command line design would be allow multiple modes like this:

nfqws --dpi-desync=rstack,rstack,disorder,rst 

Then nfqws sends the corresponding packets according to the order specified. This not only allow for duplicated fake packets, but also a combination of approaches in case a single desync method is not robust enough. What do you think?

@bol-van
Copy link
Owner

bol-van commented Mar 19, 2020

Not all actions are compatible with each other.
Now each dpi-desync mode represents complete strategy for evading DPI.
There's another software called geneva https://geneva.cs.umd.edu/papers/geneva_ccs19.pdf
it has universal strategy constructor and genetic algorithm for testing and finding working strategies.
Unfortunately its written in python, very slow and ineffective language, not for soho routers.
I'm not going to rewrite its functionality, but i'm ready to pre-program working evading strategies

@bol-van bol-van closed this as completed Mar 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants