Gowee / noisy-shuttle

Secure proxy service indistinguishable from whitelisted TLS website
146 stars 16 forks source link

Use the same ephemeral key for Noise and TLS key exchange #1

Open Gowee opened 1 year ago

Gowee commented 1 year ago

For simplicity of implementation and flexibility of ClientHello fingerprint, the tunnel implementation till now (v0.2.1) puts Noise ephemeral public key into client random. This provides no protection against active probing with replay attack aiming to distinguish camouflaged handshakes & traffic from authentic TLS stream, because the server has no way to tell whether the client actually owns the private key before sending back a responding Noise handshake. To mitigate it, the tunnel maintains a time-based LRU replay filter.

It is possible to use the same ephemeral key for both Noise and TLS key exchange (TLS 1.3 KeyShare or TLS 1.2 ClientKeyExchange). In this way, replayed ephemeral key and AEAD tag won't be effective by nature since a malicious client who has no corresponding private key won't able to finish the TLS handshake or verify any encrypted traffic at all.

The new proposed idea is more complex than the previous one to implement. And it does introduce some compatibility issues. Here are some considerations.

For the second point, to allow session resumption, a possible workaround is to maintain an association of TLS session tokens (ticket/id/PSK) and the session key negotiated by Noise on server-side in addition to the session storage of client-side TLS implementation. When initiating a TLS handshake, the client signs (HMAC) its session token. Whenever the server determines a TLS session is resumed, it extracts the Noise session key for encryption of later traffic from its association storage. A malicious client who attempts to replay previously-recorded resumption would have no TLS session key cached for the corresponding TLS session token, preventing it from verifying server response in order to distinguish anything. But maintaining the extra session association seems not to be easier than maintaining the current replay filter LRU, not to mention the case where the server forgets a session token sent by a legit client (e.g. after a server restarting).