Which cipher suites are offered by s_client when credentials are omitted?
0 reputation · 01 Oct 2023, 07:49 UTC
0 reputation · 01 Oct 2023, 07:49 UTC
When using openssl s_client to validate a server integration, it is often necessary to test the connection without providing production private keys or certificates via the -cert and -key flags.
In OpenSSL 3.x, the tool's behavior during the handshake depends heavily on the server's supported cipher suites and the client's default protocol configuration. If no credentials are supplied, the client may attempt to negotiate anonymous Diffie-Hellman (DH) or Elliptic Curve Diffie-Hellman (ECDH) suites. However, many modern servers disable these anonymous suites for security reasons, leading to a handshake failure.
There is uncertainty regarding how s_client handles the fallback mechanism when anonymous suites are rejected and no client certificate is provided, especially when comparing the default behavior of OpenSSL 1.1.1 against OpenSSL 3.0.
s_client attempt a specific sequence of anonymous suites before failing the handshake?33275 reputation · 01 Oct 2023, 16:55 UTC
When no -cert and -key are supplied, openssl s_client offers the same cipher suites it would offer with credentials. The absence of client certificates does not change the ClientHello cipher list. Client authentication is a server decision made after the ClientHello, via CertificateRequest, and is independent of which suites are advertised.
By default the tool uses the OpenSSL default cipher list. That list excludes anonymous and null encryption suites.
-cipher 'aNULL' is required to make s_client advertise anonymous suites.It is likely that the confusion about anonymous DH/ECDH fallback comes from older documentation and from the fact that servers can reject a handshake when client authentication is required. s_client will not automatically switch to an anonymous suite when a CertificateRequest is received and no client cert is available. The handshake will fail with a certificate error or alert from the server.
Uncertainty remains about the exact default string on a specific build because OpenSSL configuration files, OPENSSL_CONF, and command line overrides can change the effective list. The behavior also differs between protocol versions.
openssl ciphers -v 'DEFAULT@SECLEVEL=2'For OpenSSL 1.1.1 the equivalent default is often DEFAULT:@SECLEVEL=1.
openssl s_client -connect host:443 -tls1_2 -msgLook at the ClientHello cipher list in the output. The negotiated cipher after handshake can be checked with:
openssl s_client -connect host:443 -tls1_2 2>/dev/null | grep Cipheropenssl s_client -connect host:443 -cipher 'aNULL' -msgIf the server rejects anonymous suites, the handshake will fail.
To give a version-specific recommendation, the OpenSSL version in use is needed. The default security level and default cipher string change between 1.1.1 and 3.x, which changes the exact suite list offered.
Use comments to ask for clarification. Post a solution as an answer.
33,275 reputation · 01 Oct 2023, 10:47 UTC
It is important to clarify that in the TLS handshake, the offer of cipher suites occurs during the ClientHello, which precedes the server's request for client credentials. Consequently, s_client offers its full default suite of supported ciphers regardless of whether -cert or -key are provided.
The failure mentioned typically occurs later in the handshake: if the server requires mutual TLS (mTLS), it sends a CertificateRequest. If s_client has no credentials, it cannot respond with a valid certificate, leading to a handshake failure—not because the wrong ciphers were offered, but because the identity requirement was not met.
For TLS 1.3 (OpenSSL 3.x), this is even more distinct as cipher suites are decoupled from the key exchange. To verify exactly what is being sent, you can use the -msg flag:
openssl s_client -connect host:port -msg
This allows you to see the ClientHello and confirm that the cipher list remains consistent whether credentials are omitted or included.