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

Thinking about building a covert TCP proxy that's based on DPI. But is it possible? #352

Open
golfvoyager1 opened this issue Apr 20, 2024 · 12 comments

Comments

@golfvoyager1
Copy link

I'm thinking about a covert TCP proxy that hides authentication message in ClientHello of TLSv1.3. The goal is to make it hard to detect such proxies for both passive attacker and active attacker.

                                 Auth fail             
             ClientHello        +--------->example.com 
                                |                      
Proxy Client--- TLSv1.3--->Proxy Server                
                                |                      
                                +--------->HTTPS Server
                                 Auth pass             

In the diagram above, "HTTPS Server" is an ordinary HTTPS server. "Proxy Client" establishes an HTTPS connection to "Proxy Server" with TLSv1.3. It hides authentication message in the ClientHello message. "Proxy Server" checks the ClientHello and looks for authentication message. If it passes checks, the "Proxy Server" forwards the TCP connection to the "HTTPS Server", otherwise it forwards it to a configured website (example.com) on the internet.

The Proxy Client can hide authentication message in various fields of ClientHello. But the authentication message should be indistinguishable from values from a normal ClientHello. One possible way is to set the Session ID to the HMAC of the whole ClientHello with Session ID set to 0s.

Since TLSv1.3 encrypts the server's cert, a passive attacker can only see "example.com". An attacker that probes Proxy Server will only see the real example.com. And an attacker that replays the ClientHello can not finish the handshake.

There can be some pitfalls in this setup. For example, one should not select an example.com that reveals client IP. And size of server cert may reveal some information. But I think with careful parroting, these pitfalls can be mitigated. Now I wonder whether this setup can reliably bypass those sophisticated firewalls (e.g. GFW).

@UjuiUjuMandan
Copy link

This is not new, someone has already implemented.

@mmmray
Copy link

mmmray commented Apr 20, 2024

I believe this might be possible using fallback in xray, but I am not sure. I can tell for sure though that even if this setup exists, it is not a widely deployed one.

Using a camouflaging website (example.com) is not new at all. But the idea of hiding authentication in ClientHello is interesting because I think that way, it could be possible to present as example.com with a valid ssl cert.
If I understand correctly, you want to forward the raw TCP from example.com after ClientHello.

Current attempts at camouflaging terminate the entire TLS session. This means that if authentication fails, they forward example.com back to the client, but with self-signed SSL certificate that is not valid for example.com. This makes it much easier to hide auth, but the camouflaging is imperfect this way.

@golfvoyager1
Copy link
Author

If I understand correctly, you want to forward the raw TCP from example.com after ClientHello.

Yes, if the auth fails, I want to forward the raw TCP to example.com.

@golfvoyager1
Copy link
Author

This is not new, someone has already implemented.

I'd like to learn more about that. Are there any details of that implementation?

@UjuiUjuMandan
Copy link

UjuiUjuMandan commented Apr 20, 2024

I'd like to learn more about that. Are there any details of that implementation?

HTTPS server fallback strategy:

Authentication through TLS ClientHello:

@ignoramous
Copy link

See also: https://github.com/sergeyfrolov/httpt

@wkrp
Copy link
Member

wkrp commented Apr 21, 2024

For steganographically encoding authentication data in TLS messages, see some "tagging" schemes using in refraction networking systems:

Decoy Routing §3.2

In this paper we describe a sentinel embedded within the TLS handshake. We assume that each client shares a secret key with the decoy proxy. This key is used to generate a set of time-varying nonces (or sentinels). To generate time-varying sentinels we apply an HMAC to the concatenation of the key, the current hour, and a per-hour sequence number. The sentinels may be used as part of the client random number field in the TLS Client Hello Messages sent by the client.

Telex §4

In this section, we describe how we implement the invisible tag for TLS connections, which only Telex stations can recognize. … Our tags must have two properties: they must be short, and they must be indistinguishable from a uniformly random string to anyone without the private key. Someone with the private key should be able to examine a random-looking value and efficiently decide whether the tag is present; if so, a shared secret key is derived for use later in the protocol.

The structure of the Telex tagging system is based on Diffie-Hellman: there is a generator g of a group of prime order.

As in normal TLS, the client sends a ClientHello message, but, in place of the 224-bit random value, it sends τ.

TapDance §4.2

In TapDance, we rely on elliptic curve Diffie-Hellman to agree on a per-connection shared secret between the client and station, which is used to encrypt the steganographic tag payload. The tag consists of the client’s connection-specific elliptic curve public key point (Q = eG), encoded as a string indistinguishable from uniform, followed by a variable-length encrypted payload used to communicate the client-server TLS master secret (and intent for proxying) to the station.

In order to properly disguise the client’s elliptic curve point, we use Elligator 2 over Curve25519. Elligator 2 is an efficient encoding function that transforms, for certain types of elliptic curves, exactly half of the points on the curve to strings that are indistinguishable from uniform random strings.

We insert the tag, composed of the encoded point and encrypted payload, into the ciphertext of the client’s incomplete request to the server using the chosen ciphertext steganographic channel described in Section 3.

Conjure §4.1 uses the same tagging scheme as TapDance.

A registration connection is sent to a registration decoy: any site that supports TLS behind the ISP relative to the client. The client completes the handshake, and sends a normal HTTPS request that embeds a ciphertext tag in the payload. Conjure leverages the same steganographic technique as TapDance to encode the ciphertext, however we send a complete request allowing the registration decoy to respond or close the connection.

@uuonda
Copy link

uuonda commented Apr 22, 2024

Implemented in XRay XTLS Reality. You get real valid signed response from example.com if authentication fails.

@mmmray
Copy link

mmmray commented Apr 22, 2024

from my understanding, hysteria2, xray reality and also HTTPT do not forward example.com as-is, and present a self-signed or otherwise invalid certificate when the camouflage website is opened.

HTTPS server fallbacks are generally extremely widespread because they can be achieved using 10 lines of nginx config (though xray and hysteria do not speak HTTP after auth, afaik)

@uuonda
Copy link

uuonda commented Apr 22, 2024

Not sure about Hysteria2 and Httpt but Xray in Reality mode does exactly what you want. Signed response from example.com as-is.

@chise0713
Copy link

chise0713 commented Apr 23, 2024

from my understanding, hysteria2, xray reality and also HTTPT do not forward example.com as-is, and present a self-signed or otherwise invalid certificate when the camouflage website is opened.

HTTPS server fallbacks are generally extremely widespread because they can be achieved using 10 lines of nginx config (though xray and hysteria do not speak HTTP after auth, afaik)

About REALITY:
https://t.me/projectXray/3522180
Refer https://github.com/XTLS/REALITY/blob/main/README.en.md
It always return the dest's certificate, only forward connection for invalid client at client failing the authentication.

@wkrp
Copy link
Member

wkrp commented Apr 23, 2024

You can also compare to "mask sites" in Conjure:

#18 (comment)

One of the possible covert proxy protocols, new in this work, is "mask sites" (§4.2.3, §5.3.2, §7.1). The overall idea is that the Conjure station forwards phantom-addressed TLS traffic to some actual web site running at its own address—until the Conjure station discovers that the client is using a special prearranged key, at which point the station hijacks the connection and begins forwarding it to an application proxy instead. The motivation here is that TLS makes a good covert channel, but has a few caveats: in order to look like a genuine TLS connection, the server needs to present a valid CA-signed certificate (not a problem with TLS 1.3), and the client needs to present a plausible SNI (even with TLS 1.3, at least until ESNI arrives). By always forwarding at least the first part of the TLS connection to a real site, the client is able to provide a plausible SNI (that of the mask site) and the Conjure station is able to provide a genuine certificate that matches that SNI (forwarded from the mask site).

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

7 participants