Pluggable transport idea: TLS session resumption

Showing 1-1 of 1 messages
Pluggable transport idea: TLS session resumption David Fifield 9/7/16 2:24 PM
Here's an idea for a new pluggable transport. It's just a TLS tunnel,
but with a twist that allows the server's certificate to be omitted,
depriving the censor of many classification features, such as whether
the certificate is signed by a CA, the certificate's lifetime, and
whether the commonName matches the server's IP address. I got the idea
from ShadowsocksR:
https://github.com/breakwa11/shadowsocks-rss/blob/master/ssr.md#2%E6%B7%B7%E6%B7%86%E6%8F%92%E4%BB%B6

The trick that makes it work is RFC 5077 session tickets. How it's
supposed to work is, the client makes a TLS connection as usual, and the
server sends back a session ticket before beginning the flow of
application data. The session ticket is just a random blob from the
client's point of view; from the server's point of view it's an
authenticated ciphertext that encodes session parameters such as the
ciphersuite and master secret. The next time the client connects to the
same server, it sends the session ticket along with its ClientHello and
the server can skip sending its certificate.

Here's a simple way to adapt session tickets for circumvention. The
client *always* sends a session ticket when making a connection, even
the very first time. The ticket doesn't come from a previous
communication with the server; the client generates the ticket itself.
The ticket could for instance be a random string--the censor wouldn't be
able to distinguish--but we can also use those bits for other purposes.
When the server receives the ClientHello, it *pretends* that the ticket
was a valid one, and finishes the handshake using hardcoded session
parameters, just statically configuring what it would have encoded into
a session ticket.

The protocol as just described would be vulnerable to active probing;
the censor could test for servers by sending them garbage session
tickets and seeing how they respond. But that's easy to fix. We can, for
example, let the client and server have a shared secret, and have the
server treat the session ticket as the client part of an obfs4
handshake--which conveniently resembles a random blob. If the session
ticket doesn't pass obfs4 authentication, then the TLS server can
respond as it naturally would if a client sent an invalid session
ticket; i.e., issue a new ticket and do a full handshake (then send
dummy data, I guess). The server can also honor its own legitimately
issued tickets, but still send dummy data in response. Only clients who
know the shared secret will be able to access the proxy functionality of
the server.

In order to block such a transport, the censor will have to look at
features other than the server certificate. It could, for example:
 * block all session tickets (dunno how costly that would be)
 * statefully track which tickets servers have issued, and block
   connections that use an unknown ticket.
 * track the fraction of connections that use session tickets on each
   TLS server.
 * active-probe the server in order to get a certificate, and then look
   at certificate features.
We'd have to do some research to find out the distribution of session
ticket sizes in the wild. (RFC 5077 recommends a specific format:
https://tools.ietf.org/html/rfc5077#section-4.)

I didn't think of this idea; it comes from ShadowsocksR and its
tls1.2_ticket_auth plugin.
https://github.com/breakwa11/shadowsocks-rss/blob/master/ssr.md#2%E6%B7%B7%E6%B7%86%E6%8F%92%E4%BB%B6
The documentation is in Chinese. Here is what Google Translate says in
English:
        Analog TLS1.2 handshake at client has a session ticket situation
        is connected. Currently complete analog implementation, software
        testing through capture perfectly disguised as TLS1.2. Because
        there is no ticket so send certificates and other complicated
        steps, so the firewall can not make a judgment based on the
        certificate. At the same time it comes with the ability of
        certain anti-replay attacks. In case of a replay attack is
        searched end log in to the service, you can grep "replay attack"
        search, you can use this plug-in found in your area there is no
        line of interference for TLS. TLS relatively powerless firewall,
        anti-blocking ability than other plug-ins should be strong, but
        may also encounter a lot of interference, but the agreement
        itself will check out any interference, then disconnect
        encounter interference, to avoid long waits, so that customers
        end browser or reconnect themselves. This plug-in is compatible
        with the original agreement (the server is configured to require
        tls1.2_ticket_auth_compatible), one more than the original
        protocol handshake causes the connection will take longer, use C
        # client open automatically reconnect when performed better than
        the other plug-ins. Support for custom parameters, parameters
        SNI, it sends the host name field, this function is very similar
        to the TOR meet widget, for example, is set to cloudfront.net
        disguised as a cloud server requests, you can use a comma
        separate multiple host such as a.com, b.net, c.org (C # supports
        only), then it will randomly use. Note that error settings for
        this parameter may cause the connection to be disconnected even
        IP is blocked, such as how to set clear then please leave it
        blank. Recommended customized parameter settings to
        cloudflare.com or cloudfront.net.

This is how a normal ticketless handshake looks
(https://tools.ietf.org/html/rfc5246#section-7.3):
      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data


This is how the ticket-using transport would look:
(https://tools.ietf.org/html/rfc5077#section-3.1):
      ClientHello
      (SessionTicket extension)     -------->
                                                       ServerHello
                                                  NewSessionTicket
                                                [ChangeCipherSpec]
                                    <--------             Finished
      [ChangeCipherSpec]
      Finished                      -------->
      Application Data              <------->     Application Data