[tor-dev] Pluggable transport idea: TLS session resumption
David Fifield
david at bamsoftware.com
Wed Sep 7 21:24:12 UTC 2016
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
More information about the tor-dev
mailing list