cbeuw / GoQuiet

A Shadowsocks obfuscation plugin utilising domain fronting to evade deep packet inspection

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Better obuscation

cbeuw opened this issue · comments

Normally, an HTTPS server will only establish one TCP connection and handshake once with the client. In our case, one app-to-ss-local TCP connection corresponds to one ss-local-to-gq-client connection. gq-client projects each connection to one connection (and does one handshake) to gq-server. For example, when you are browsing a blocked website and the webpage needs to load external resources (which is almost all the cases), your browser will attempt to establish multiple connections to these resource sites, eventually causing gq-client to establish multiple TCP connections and perform multiple handshakes with gq-server - not a normal behavior, and it gives extra overhead.

The solution is multiplexing: squash all data streams into one TCP connection, and then demuxer the stream and dispatch the data to individual connections to Shadowsocks. This is easy and there are wheels readily available. However, the identification of which pack of data belongs to which connection pair relies on a streamID that's unique to each pair of connections. The streamID has to be included in the transmission, which, if sent in plaintext, will be significant to the GFW.

To solve this, we can use the approach used by our random field in ClientHello, whereby the streamID is encrypted by a block cipher and sent together with a random IV. However, this needs a mutual secret (for the AES key), which is not an issue in our case, but more importantly, this operation is quite expensive as one which needs to be done all the time. We would like a generic and elegant solution.

So what do we want? We want the streamID to appear differently in each transmission, i.e. the demuxer needs to be able to project many different values to one unique value. Mathematically speaking, the demuxer is using a many to one function, and it has to be invertible under a certain domain because the muxer needs to project one streamID to one of the many value. Periodic functions satisfy these conditions.

Consider

where streamID <= 1000000. And

where k is a random positive integer, so that there is no pattern in mux(x), so we send this with the data. And we have





Precision will be an issue since we are converting between discrete integers and continuous floats. This can be mitigated by keeping the value of k small and using double precision floats.

I will play around with this idea some time later.

Normally, an HTTPS server will only establish one TCP connection and handshake once with the client

That was a wrong assumption and I was overthinking. Lots of websites create multiple TCP connections to the same server. Multiplexing shouldn't be needed after all.