Secure communications is a core component of a robust security policy, and MySQL Server 5.7.10 – the first maintenance release of MySQL Server 5.7 – introduces needed improvements in this area. Support for TLS has been expanded from TLSv1.0 to include TLSv1.1 and TLSv1.2, default ciphers have been updated, and controls have been implemented allowing both server and client-side configuration of acceptable TLS protocol versions. This blog post will describe the changes, the context in which these changes were made, note important differences in capabilities between Community and Enterprise versions, and outline future plans.
SSL (Secure Sockets Layer) was superseded by TLS (Transport Layer Security) long ago, and TLSv1.0 has been the secure transport protocol used by MySQL Server for many years. This implementation was an effective firewall against vulnerabilities found in SSL (such as POODLE), but also prohibited timely adoption of subsequent iterations of the TLS protocol. TLSv1.0 is now also considered insufficiently secure, and the recently-released PCI DSS v3.1 standards prohibit use of TLSv1.0 as a security control, effective June 2016.
Complicating the urgent need to support TLSv1.1 and higher is the dependency MySQL Server has on two different TLS libraries. Due to license compatibility issues, OpenSSL is used in commercial-licensed MySQL Enterprise builds only, and yaSSL is leveraged to produce GPL-licensed MySQL Community builds. While yaSSL supports TLSv1.1, it lacks support for TLSv1.2. WolfSSL, the company behind yaSSL, offers another library (WolfSSL, originally known as CyaSSL). This library offers TLSv1.2 support, and WolfSSL helpfully offered Oracle patches to help mitigate the technical burden of migrating from yaSSL to the WolfSSL library. However, replacing TLS libraries is a substantial change to make, and we could not align this effort with the 5.7 release schedule.
Community and Enterprise differences
Support for TLSv1.2 is limited to builds that use the OpenSSL library. In addition to MySQL Enterprise builds produced by Oracle, MySQL Community can be built from source using OpenSSL. GPL-licensed MySQL Community builds from Oracle leverage yaSSL, and support TLSv1.0 and TLSv1.1. TLSv1.1 is sufficient for current PCI standards, though users of GPL-licensed MySQL Community may prefer to build MySQL Server from source to link OpenSSL and enable TLSv1.2.
OpenSSL-linked binaries prefer TLSv1.2 over other versions of TLS, and when TLS connections are made between a server and client that are linked to OpenSSL, TLSv1.2 will be used by default.
Better default ciphers
The default cipher used by earlier versions of MySQL Server is DHE-RSA-AES256-SHA. This is defined in RFC3268, an extension of TLSv1.0. It is also found in TLSv1.1, and is the default cipher used whenever legacy server or clients are involved, or when yaSSL-linked 5.7+ clients or servers are participants. When both client and server support TLSv1.2, the preferred cipher is DHE-RSA-AES128-GCM-SHA256.
MySQL allows control of allowed ciphers on both server and client ends using the –ssl-cipher option (which is somewhat confusingly exposed as the ssl-cipher-list status variable). The default values differ based on the library used. yaSSL-linked binaries have the following defaults:
Variable_name: Ssl_cipher_list Value: DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES128-RMD:DES-CBC3-RMD:DHE -RSA-AES256-RMD:DHE-RSA-AES128-RMD:DHE-RSA-DES-CBC3-RMD:AES256-SHA:RC4-SHA:RC4-M D5:DES-CBC3-SHA:DES-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC-SHA:AES128-SHA: AES256-RMD
OpenSSL-linked binaries use the following defaults:
Variable_name: Ssl_cipher_list Value: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE -RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECD HE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-A ES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128- SHA256:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ECD HE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256 -SHA:DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256: ECDH-ECDSA-AES128-GCM-SHA256:AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:AES1 28-SHA256:ECDH-ECDSA-AES128-SHA256:AES256-SHA256:ECDH-ECDSA-AES256-SHA384:AES128 -SHA:ECDH-ECDSA-AES128-SHA:AES256-SHA:ECDH-ECDSA-AES256-SHA:DHE-RSA-AES256-GCM-S HA384:ECDH-RSA-AES128-GCM-SHA256:ECDH-RSA-AES256-GCM-SHA384:ECDH-RSA-AES128-SHA2 56:ECDH-RSA-AES256-SHA384:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:DES-CBC3-SHA
In addition to the above, support for known weak ciphers has been removed (e.g., RC4-MD5, etc.). This helps reduce the possibility of MySQL 5.7 instances being compromised by exploits leveraging these older ciphers. In some cases, the weaker ciphers could not be seen in the ssl-cipher-list output, as that is truncated at 1024 characters.
Controlling TLS version
Even before PCI policy updates made this a requirement, security-minded MySQL community members have asked for the ability to enable or disable specific TLS versions, and MySQL 5.7.10 supports this using the new tls_version configuration option. Providing this option at startup allows users to enable only specified TLS versions, currently defined as:
Note that what I reference as TLSv1.0 is the TLSv1 option value. Thus, a configuration including tls_version=TLSv1.1,TLSv1.2 aligns with PCI DSS v3.1 guidelines.
Also worth noting, the tls_version configuration option triggers warnings – not errors – when invalid values are provided. This allows the same PCI-supporting configuration value of tls_version=TLSv1.1,TLSv1.2 to be used for both OpenSSL and yaSSL-based builds of MySQL Server, but the latter will enable only TLSv1.1. Currently, this also means that providing invalid values may result in TLS being disabled entirely (see bug reports).
The following matrix defines which TLS version will be negotiated by default by various combinations of legacy and 5.7.10+ yaSSL and OpenSSL-linked binaries. This applies not only to the standard MySQL command-line clients, but to drivers based on the libmysql client library.
|Pre-5.7.10 Server||5.7.10+ yaSSL-based Server||5.7.10+ OpenSSL-based Server|
|5.7.10+ yaSSL-based Client||TLSv1.0||TLSv1.1||TLSv1.1|
|5.7.10+ OpenSSL-based Client||TLSv1.0||TLSv1.1||TLSv1.2|
The tls_version configuration option is valid both for the MySQL Server as well as standard MySQL command-line clients. This makes it possible to restrict TLS to specific versions from either side of the connection.
Applications using the libmysql client library will find a new option – MYSQL_OPT_TLS_VERSION – which exposes the same control to applications or drivers which rely on this library.
The introduction of support for TLSv1.1 and TLSv1.2 was carefully planned to avoid incompatibilities. As a consequence, even though TLSv1.0 is no longer considered adequately secure, it remains enabled by default, as many clients and connectors leverage legacy client libraries which lack support for more recent versions. Users targeting PCI DSS v3.1 compliance will want to validate support for TLSv1.1+ for all clients/connectors, then disable TLSv1.0 on the server side.
One important aspect to consider is that failed TLS negotiation causes the server to terminate the connection request. This means that a client wanting a TLS connection, but only supporting TLSv1.0, attempting to connect to a server that supports only TLSv1.1 and TLSv1.2 will fail to connect entirely – the server won’t fail back to a non-TLS connection due to TLS negotiation failure. The following illustrates the results of attempting to connect the 5.7.9 mysql client – which prefers TLS over plain TCP/IP and only understands TLSv1.0 – with MySQL Server 5.7.10, configured for PCI compliance by setting tls_version=TLSv1.1:
D:\mysql-5.7.9-winx64>bin\mysql -uroot -P3310 ERROR 2026 (HY000): SSL connection error: protocol version mismatch
Visibility into TLS version
MySQL administrators looking to restrict TLS versions in support of PCI DSS v3.1 will want to assess potential impacts of removing TLSv1.0 support. As shown above, TLSv1.0 is required for compatibility with earlier versions of the libmysql client library, which is used by various application connectors as well as command-line tools. Removing support for TLSv1.0 may cause critical tools or systems to be unable to access MySQL Server.
Using PERFORMANCE_SCHEMA, it is easy for MySQL administrators to identify the TLS version in use for each connection. This allows critical tools and systems to be profiled by an administrator, and have visibility into what tools need to be updated prior to restricting TLSv1.0 support on the server side. Here is an example query:
mysql> SELECT -> variable_value AS tls_version, -> processlist_user AS user, -> processlist_host AS host -> FROM performance_schema.status_by_thread sbt -> JOIN performance_schema.threads t -> ON (t.thread_id = sbt.thread_id) -> WHERE variable_name = 'Ssl_version' -> ORDER BY tls_version; +-------------+------+-----------+ | tls_version | user | host | +-------------+------+-----------+ | | root | localhost | | TLSv1 | tv10 | localhost | | TLSv1.1 | tv11 | localhost | | TLSv1.2 | tv12 | localhost | +-------------+------+-----------+ 4 rows in set (0.00 sec)
This query is very similar to one I shared in a previous blog post, describing how to leverage PERFORMANCE_SCHEMA to see which TLS ciphers are being used by client connections. Both are useful tools for DBAs to evaluate potential impacts of proposed changes to improve security.
With support for TLSv1.1 and TLSv1.2 now in MySQL Server 5.7, a couple of questions remain unresolved.
Backporting to 5.6
MySQL Server 5.6 currently continues to support TLSv1.0 exclusively. Should the existing 5.7 functionality be back-ported to MySQL Server 5.6? This would decouple PCI compliance from a major server upgrade.
Adding TLSv1.2 for GPL-licensed builds
Adding support for TLSv1.2 in GPL-licensed builds means replacing yaSSL with an alternative library. Identifying and integrating another library is likely an invasive change, and it is unlikely that such a change can happen before the next major feature release of MySQL Server.
MySQL 5.7.10 provides TLS improvements necessary to support best security practices, including those mandated by recent updates to the PCI standards. There are notable differences between Enterprise and Community binaries, which are driven by library limitations, and Oracle is looking at alternative libraries to eliminate these differences in future feature releases. All TLS functionality is available to Community users who choose to build MySQL Server from source, linking against OpenSSL instead of yaSSL.
12 thoughts on “SSL/TLS Improvements in MySQL 5.7.10”
Does that mysqld support SNI?
Does mysqld support thousands certificates? (so single mysqld could be hosted under thousands of different dns names and still provide tls for users)
MySQL does not support the SNI extension to TLS, nor does it support multiple certificates at this time. I’ll add it to our list of features to consider for future releases – thanks for highlighting it!
Sorry, I don’t understand the sentence “This would decouple PCI compliance from a major server upgrade.” in the paragraph of back-porting to 5.6. Can you elaborate what would be wrong if the feature would be back-ported?
Also, would it be possible to just allow TLS 1.2 in 5.5/5.6, without backporting the rest?
As things stand right now, users who require TLSv1.1+ to be PCI compliant would have to upgrade to MySQL Server 5.7. My statement meant to articulate a reason we should consider back-porting to earlier versions – making users adopt 5.7 to get PCI compliance is sure to be problematic for some. As for what would be “wrong” with a back-port, I didn’t explicitly state it, so here goes: Enabling TLSv1.1+ support is more involved than changing a compilation switch, or anything like that. The code paths are different (there are TLSv1.0-specific methods used before; the addition of TLSv1.1+ support required using new methods), and we try to be sensitive to changes which might cause incompatibilities or regressions during maintenance cycles – especially those so far removed from GA.
It’s possible to back-port the TLSv1.1+ support to earlier versions. When you say “the rest”, it would probably need to include the tls_version configuration option, as well as the corresponding C API option. We’d want to be very careful about problems that might cause, of course. The PERFORMANCE_SCHEMA instrumentation can’t go back to earlier versions, which also reduces DBA visibility into problematic client TLS usage. We wouldn’t back-port auto-generation of TLS key material, or preference for TLS over plain TCP/IP in client libraries.
Should I interpret your comment as being in favor of back-porting this functionality to earlier versions?
Sorry, I can’t say I was in favor of doing the back-port, since security is really not my domain (as you see from my lame questions). I’m just looking at the patch proposed at https://bugs.mysql.com/bug.php?id=75239 and it seems to be simple enough to be back-ported to 5.5 and 5.6, just as a half-way solution. But I can’t fully understand the consequences here, whether it would make the older releases any better.
Thanks for clarifying the context in which your question is framed. I can’t speak to the particulars of the patch you referenced, but I can point to the actual core patch implemented and say that the actual implemented code is more involved than the proposed patch. Daniël is a very astute developer, and even without trying the patch, I’m sure it worked for his use case, and likely a number of others. In this case, though, we felt we needed to take a more comprehensive approach (e.g., without the –tls_version option, PCI compliance can’t be enforced).
Would that proposed patch be sufficient and non-disruptive on its own, if applied to 5.5/5.6 instead of the more comprehensive 5.7 patch? I don’t know at this point. If there’s strong interest in that approach over back-porting the 5.7 patch, it’s something which could be evaluated.
Thanks for your feedback – and thanks to Daniël for his bug report and patch!
Thanks for this helpful description – I enjoyed it!
However, I’d like to see an explicit statement about this:
Is the limitation to TLS v1.0 in the pre-5.7.10 software purely a yaSSL limitation, or does it also apply to “enterprise” binaries which are using OpenSSL?
From your remarks about backporting, I assume that even “enterprise” binaries of MySQL 5.6 are limited to TLS v1.0 – is my interpretation correct?
It’s a bit complicated – I’ll try to summarize:
yaSSL is used in 5.5 (all licenses), and 5.6 and 5.7 GPL-licensed builds. OpenSSL is used for commercial-licensed builds of 5.6 and 5.7.
yaSSL supports TLSv1.0 and TLSv1.1. OpenSSL supports TLSv1.0, TLSv1.1, and TLSv1.2.
Both libraries (yaSSL uses an OpenSSL API compatibility layer) have different methods for TLSv1.0 and all other versions. Code for all Server versions before 5.7.10 used the TLSv1.0 methods exclusively. Back-porting support for TLSv1.1 (and/or TLSv1.2 for OpenSSL-linked builds) is limited by the Server code which calls the TLS library, rather than limitations of the library itself. We haven’t back-ported this code to 5.6 or 5.5 yet, and as a result, these Server versions are limited to TLSv1.0 at this time (regardless of license type).
I hope that helps clarify – let me know if not.
thank you for making it so explicit!
So the limiting factor is not the library’s feature but rather the way it is called, and replacing or updating the library will not help.
This is quite close to what I had assumed, but I prefer to get it confirmed. Very helpful!
Thanks for the interesting post. Newer TLS versions are definitely something to be sought after for the increase in security that they can provide. It is good to see TLSv1.2 supported with MYSQL v 5.7.10.
Switching out yaSSL for wolfSSL would be a way of integrating a GPLv2 library that supports TLSv1.2. While the older yaSSL provides good security it lacks the recent features and additions that the more active wolfSSL project has. There is a free patch to download at https://github.com/wolfSSL/mysql-patch for MYSQL versions 5.6.22 and 5.6.23 that demonstrates this switch from yaSSL to wolfSSL.
Indeed, WolfSSL is one option to consider. It’s worth saying that WolfSSL has been very helpful in producing patches for 5.6 and 5.7 to ease a migration from yaSSL to WolfSSL.
Beside of not supporting TLSv1.2 protocol, Yassl also has other disadvantages:
– No ALPN (Application Layer Protocol Negotiation) support:
If the client specifies an unknown tls version (dwMinor > 2) in hello packet the handshake will fail since the client has no opportunity to send supported tls_protocols.
– No session caching
I also wonder why RC4-SHA cipher (which is considered to be unsecure) is still supported:
georg@linux-lw76:~/work/misc/mariadb_scan> ./sslscan –mariadb 127.0.0.1:13000
OpenSSL 1.0.2e-fips 3 Dec 2015
OpenSSL version does not support SSLv2
SSLv2 ciphers will not be detected
OpenSSL version does not support SSLv3
SSLv3 ciphers will not be detected
Server version: 5.7.10-debug-log
Testing SSL server 127.0.0.1 on port 13000
Session renegotiation not supported
TLS 1.2 not vulnerable to heartbleed
TLS 1.1 not vulnerable to heartbleed
TLS 1.0 not vulnerable to heartbleed
Supported Server Cipher(s):
Preferred TLSv1.1 256 bits DHE-RSA-AES256-SHA DHE 2048 bits
Accepted TLSv1.1 128 bits DHE-RSA-AES128-SHA DHE 2048 bits
Accepted TLSv1.1 256 bits AES256-SHA
Accepted TLSv1.1 128 bits RC4-SHA
Preferred TLSv1.0 256 bits DHE-RSA-AES256-SHA DHE 2048 bits
Accepted TLSv1.0 128 bits DHE-RSA-AES128-SHA DHE 2048 bits
Accepted TLSv1.0 256 bits AES256-SHA
Accepted TLSv1.0 128 bits RC4-SHA
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength: 2048
Not valid before: Dec 5 04:48:40 2014 GMT
Not valid after: Dec 1 04:48:40 2029 GMT
sslscan fork for scanning MariaDB/MySQL/Percona servers can be found here: https://github.com/9EOR9/sslscan.git