Reputation: 181
I'm trying to find a way to prevent an OpenSSL based server (1.0.2g) from asking a client to move from TLS1.0 to TLS1.2.
This is a proprietary server. I need to do this through openssl directly through an openssl API call, OP flag, compile option, etc.
I have no access to modify the client connecting to my server. This particular client currently consists of a decent percentage of traffic to my server but has a bug which causes it to effectively hang after that negotiation.
If my server is compiled against an older version of OpenSSL (eg. 1.0.0d), the server doesn't try to bump the protocol to TLS1.2, leaves it at TLS1.0, and everything works peachy.
I need to move to a recent version of OpenSSL, though, for security reasons. Is there a way to prevent the server from asking the client with TLS1.0 to move to TLS1.2, while still allowing TLS1.2 clients to stay with TLS1.2?
(these older clients are deprecated and will eventually disappear. newer clients already come in at TLS1.2 by default)
Upvotes: 1
Views: 6075
Reputation: 102376
Prevent TLS version negotiation...
There's a fundamental misunderstanding that's occurring. The TLS version is not negotiated per se.
When a ClientHello
is sent, there's one version of TLS and that's it. The client's TLS protocol version is usually referred to as ClientHello.client_version
. There's a ServerHello
and a ServerHello.server_version
, too.
From RFC 5246, The Transport Layer Security (TLS) Protocol Version 1.2, page 40:
struct {
ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites<2..2^16-2>;
CompressionMethod compression_methods<1..2^8-1>;
select (extensions_present) {
case false:
struct {};
case true:
Extension extensions<0..2^16-1>;
};
} ClientHello;
Assuming the client is fully capable, clients are supposed to try TLS 1.2. If the server fails the connection, the the client tries TLS 1.1. If the server fails the connection, the the client tries TLS 1.0.
The multiple-client-retries is exactly what the browsers do, and its the reason for TLS_FALLBACK_SCSV
from RFC 7507, TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks. TLS_FALLBACK_SCSV
allows a client to detect when an attacker is trying to force a downgrade on the connection.
What happens in practice is there's a Record Layer and a Payload Layer. The record layer carries the TLS payload and allows fragmentation on transports that don't have the feature. Clients use a SSLv3 record layer so that it passes through least-capable middleware boxes, and a TLS 1.2 payload layer (from the handshake hello's) to get the stronger encryption. Some server interpret it to mean the client is capable of SSL v3.0 through TLS v1.2.
And to muddy the waters even further, there's a version associated with Compression too, when its available. So there could be three different versions in play.
I'm trying to find a way to prevent an OpenSSL based server (1.0.2g) from asking a client to move from TLS1.0 to TLS1.2.
OK, given the discussion above, servers don't ask anything. If the client advertises TLS v1.2 in its ClientHello.client_version
, then that's what the server uses by responding with the same version in its ServerHello.server_version
.
I think you may be able to use the following to get what you need. But you will need to thoroughly test this since I suspect it will cause a fair amount of interop problems:
// Record and payload layer
const SSL_METHOD* method = TLSv1_method();
SSL_CTX* context = SSL_CTX_new(method);
...
The above is what OpenSSL's test programs s_client
and s_server
do when you do something like openssl s_client -connect ... -tls
. You can find the source code in <openssl src dir>/apps
.
If you use the SSLv23_method
, then you get the SSLv2 compatible ClientHello
, and you need to do things like Jim is showing you.
Also see SSL/TLS Client on the OpenSSL wiki.
Here's what a HTTPS connection looks like using TLS 1.0 only. The trace to Yahoo was created with openssl s_client -connect www.yahoo.com:443 -tls1 -servername www.yahoo.com
. I used Yahoo rather than Stack Overflow because I needed a fresh connection.
Upvotes: 3
Reputation: 8487
What are you using for SSL_CTX_new?
You can
SSL_CTX_new(SSLv23_method())
and then
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3)
Now clients that only support TLS 1.0, will use TLS 1.0. Clients that can support TLS 1.2, will negotiate to TLS 1.2. Isn't this what you want?
I have not tried this, but you can probably:
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1)
which eliminates any TLS 1.1, leaving only 1.0 or 1.2 as options.
Upvotes: 1
Reputation: 3089
Assuming you have access to an SSL_CTX
in the source code, the following should disable support/offering of TLS 1.2):
SSL_CTX *ssl_ctx;
...
#ifdef SSL_OP_NO_TLSv1_2
/* Disable TLSv1.2 */
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
#endif
Similarly, if you need to disable offering/use of TLSv1.1 for any reason, you'd use the SSL_OP_NO_TLSv1_1
option (and, depending on your OpenSSL versions, similar #ifdef
guards).
Hope this helps!
Upvotes: 0