1. Overview
In this tutorial, we’ll look at the basics of Transport Layer Security (TLS). Then, we’ll learn how to check the required TLS version for a host in Linux.
2. Transport Layer Security
Transport Layer Security (TLS) is a cryptographic protocol that secures communication over a computer network between nodes.
With transport layer security, nodes exchange cryptographic specifications and parameters as part of the initialization. After exchanging the parameters, the nodes are able to encrypt their messages such that only the target node can decipher the message.
This prevents anyone on the network from eavesdropping on messages between the nodes.
2.1. TLS Version Negotiation
To set up a secure channel, the client and server perform negotiation on the TLS version to use as part of the initialization process.
Firstly, a client tells the server what TLS protocol versions it supports. Then, if the server can support the protocol version, it selects one and uses that throughout the entire session with the client.
On the other hand, the server rejects the connection if the server cannot support the TLS version the client asks for.
This negotiation process is an important step in the whole TLS handshake procedure. This is because it ensures that both client and server can agree upon the version that both support.
2.2. Which TLS Versions?
As the TLS specification evolves, new versions are introduced to accommodate better security and performance considerations. In the beginning, TLS was known as SSL and the versions are SSL 1.0, 2.0, and 3.0. However, all the SSL versions are deprecated as of 2015.
After SSL 3.0, the term SSL was dropped and replaced with TLS. In total, there are four different TLS versions, TLS 1.0, 1.1, 1.2, and 1.3. The TLS 1.0 and 1.1 have been deprecated as of 2021 with TLS 1.3 being the recommended TLS version.
With all these different versions, how can we as a client know which versions the host supports? In the following sections, we’ll look at some methods we can use to answer the question.
3. The openssl s_client Command
The openssl command is the command-line tool in Linux that allows us to use OpenSSL’s cryptography functions on the shell.
Within the openssl command, the s_client subcommand is an SSL/TLS client. Furthermore, the s_client subcommand offers several options that specify the TLS version we want to use when connecting to the host.
Using these options, we can iteratively try out different TLS versions and observe the server response. Through the response, we’ll be able to deduce the TLS versions that the host supports.
3.1. Installation
We can obtain the openssl s_client command by installing the openssl package using the package manager. Specifically, we can install it using the apt-get command in Ubuntu:
$ sudo apt-get install -y openssl
Then, we can verify our installation by printing the help page of s_client:
$ openssl s_client -help
Usage: s_client [options]
Valid options are:
-help Display this summary
...
3.2. Specifying the TLS Version Using Options
The s_client subcommand allows us to specify the specific TLS version to offer to the server using -tls1, -tls1_1, -tls1_2, -tls1_3 options. These options correspond to the TLS versions 1.0, 1.1, 1.2, and 1.3 respectively.
For example, we can initiate a TLS connection with google.com and offer only TLS version 1.1 to the server:
$ openssl s_client -connect google.com:443 -tls1_1
CONNECTED(00000005)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:CN = *.google.com
i:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
1 s:C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
i:C = US, O = Google Trust Services LLC, CN = GTS Root R1
2 s:C = US, O = Google Trust Services LLC, CN = GTS Root R1
i:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIOPDCCDSSgAwIBAgIRAIL1YOXCpi0SCR8u2Lz1CqMwDQYJKoZIhvcNAQELBQAw
...
The command above initiates a TLS connection to the host google.com on port 443. Additionally, using the -tls1_1, we are telling the host that as the client, we can only support up to TLS version 1.1.
In the first line of the output, the message CONNECTED(00000005) means that we’ve successfully established a secure channel between us and the host. In other words, the server has no problem supporting TLS version 1.1, as per our request.
What if the host doesn’t support the TLS version we request? Let’s now connect to the host api.stripe.com with TLS 1.1:
$ openssl s_client -connect api.stripe.com:443 -tls1_1
CONNECTED(00000005)
139944872509888:error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:../ssl/record/rec_layer_s3.c:1528:SSL alert number 70
---
no peer certificate available
---
No client certificate CA names sent
...
In the first line of the output, we can see that the command raises an error SSL alert number 70. Specifically, we’re hit by the protocol version error, as per the documentation. This means that the server rejected our request because it cannot support TLS version 1.1.
Let’s bump up the TLS version to 1.2 and try again:
$ openssl s_client -connect api.stripe.com:443 -tls1_2
CONNECTED(00000005)
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:jurisdictionC = US, jurisdictionST = Delaware, businessCategory = Private Organization, serialNumber = 4675506, C = US, ST = California, L = South San Francisco, O = "Stripe, Inc", CN = api.stripe.com
...
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHPTCCBiWgAwIBAgIQCHCQkCmNr9Kx8PXt7yIDzjANBgkqhkiG9w0BAQsFADB1
...
With TLS version 1.2, we can now connect to api.stripe.com successfully. From this quick experiment, we can conclude that the minimum TLS version api.stripe.com supports is TLS 1.2.
4. Using nmap ssl-enum-ciphers
The nmap command is a command-line tool for network exploration. It’s typically used for scanning large networks using network packets to discover and map the hosts on a network.
In addition to network scanning, it offers some convenient scripts for different networking purposes such as the ssl-enum-ciphers script.
The ssl-enum-ciphers script is a script that iteratively initiates a TLS connection to a host while enumerating different TLS versions. At the end of the execution, the script presents a report on the TLS version and ciphers that the host supports.
4.1. Installation
To obtain the nmap binary, we can install the nmap package using the package manager of our Linux system.
In Ubuntu Linux, we can run apt-get install nmap to install:
$ sudo apt-get install -y nmap
Then, we can verify our installation by checking the nmap version:
$ nmap --version
Nmap version 7.93 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.6 openssl-3.0.8 libssh2-1.10.0 libz-1.2.13 libpcre-8.39 libpcap-1.10.3 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select
4.2. Running ssl-enum-ciphers Script on Host
To run the ssl-enum-ciphers script, we pass the –script option to nmap, as well as the target host and port:
$ nmap --script ssl-enum-ciphers -p 443 google.com
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-15 03:49 UTC
Nmap scan report for google.com (216.58.199.238)
Host is up (0.0022s latency).
Other addresses for google.com (not scanned): ::ffff:216.58.199.238 2404:6800:4001:80b::200e
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.0:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| ...
| TLSv1.1:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| ...
| TLSv1.2:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| ...
| TLSv1.3:
| ciphers:
| TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| ...
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 1.04 seconds
The script reports a lot of TLS-related information, let’s unpack them.
Firstly, it prints a few headers that provide information like the nmap version, host IP, and the connection latency.
Then, the output presents us with a tree view of the TLS versions and a list of ciphers and compressions that the host supports. For the sake of brevity, this tutorial will only focus on the TLS versions that are shown.
From the output, every TLS version that is shown on the output is the TLS version supported by the host. In our example, the host google.com supports TLS version 1.0 and all the way up to version 1.3.
We can repeat the same command on api.stripe.com:
$ nmap --script ssl-enum-ciphers -p 443 api.stripe.com
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-15 03:43 UTC
...
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.2:
| ...
| TLSv1.3:
| ...
|_ least strength: A
Nmap done: 1 IP address (1 host up) scanned in 1.32 seconds
Indeed, from the output, we can see only the TLS versions 1.2 and 1.3. This means we’ll need at least TLS version 1.2 in order to establish a secure connection with the api.stripe.com host.
5. Using the ssllabs.com
The ssllabs.com/ssltest is a website that offers a detailed analysis of the TLS configurations of any public-facing host. Contrary to the previous methods we’ve looked at so far, this method doesn’t live on the shell and instead requires a GUI navigation.
To begin, we can open up any web browser and visit the website https://www.ssllabs.com/ssltest. Then, we’ll see an input box with the label Hostname. We can enter the hostname we want to analyze the TLS configuration for, such as google.com:
Once we submit, we’ll see all the servers that are available for this domain name. Then, we choose the server we want to check the report for and the site will navigate us to the report page.
On the top, we can see a summary report with a rating. To check out the detail, such as the TLS versions supported, we can scroll down to the Configuration section. Within that section, we can see that Protocols shows a list of SSL/TLS versions. The right-hand column shows a value of Yes to indicate that the server can support that TLS version and a No value, otherwise:
For the host google.com, we can see that it supports TLS 1.0 to TLS 1.3, as we’ve found out from previous sections.
6. Conclusion
In this article, we learned that TLS is a cryptographic protocol that allows nodes on a network to exchange messages securely. We saw that there are several different versions of the TLS and support for them varies between hosts.
Then, we looked at four different methods of how we can check the TLS version that is supported by a host.
Firstly, we iteratively tested out the TLS version supported using the openssl s_client command and its options like -tls1_1, -tls1_2. Then, we discussed how the nmap command-line tool offers the ssl-enum-ciphers script that automates the iterative process for us.
Finally, we looked at the ssllabs.com website, which offers the service for checking the TLS specification of a website.