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%E...
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%E... 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