Skip to main content

How to Make MySQL Refuse Unencrypted Connections

· 4 min read
Jagdish Kumawat
Founder @ Dewiride

A client can ask for TLS, but only the server can insist on it. require_secure_transport refuses any connection without it, for every account, so one wrong connection string can't quietly turn encryption off.

What You Need​

MySQL 9.7 with TLS working, which is the default, and an administrator's account, such as root. Before you turn this on, make sure everything that connects can use TLS.

Step 1: Turn It On​

mysql>
SET PERSIST require_secure_transport = ON;
SHOW VARIABLES LIKE 'require_secure_transport';
Output
Query OK, 0 rows affected (0.003 sec)

+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| require_secure_transport | ON |
+--------------------------+-------+
1 row in set (0.001 sec)

SET PERSIST changes the running server and saves the setting in the data folder, so it survives a restart. SET GLOBAL wouldn't. It applies to new connections: an unencrypted session that was already open kept working when I turned this on.

SET PERSIST turning require_secure_transport ON, and SHOW VARIABLES confirming it.

Step 2: Test It​

A client with TLS turned off, over TCP, is refused:

Terminal
docker compose exec mysql mysql --user=inventory_app --password --protocol=TCP --host=127.0.0.1 --ssl-mode=DISABLED --execute "SELECT 1"
Output
ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.

The first time after a restart, the same command says ERROR 2061 instead. Either way, it's refused.

From a .NET app with SslMode=Disabled:

Output
Unhandled exception. MySql.Data.MySqlClient.MySqlException (0x80004005): Authentication to host '127.0.0.1' for user 'inventory_app' using method 'caching_sha2_password' failed with message: Connections using insecure transport are prohibited while --require_secure_transport=ON.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Connections using insecure transport are prohibited while --require_secure_transport=ON.

With TLS, both work. Here's the .NET app with SslMode=Required:

Output
Connected as inventory_app@% to MySQL 9.7.4
TLS: TLSv1.2

What It Doesn't Stop​

A local socket counts as secure, so this still works inside the container:

Terminal
docker compose exec mysql mysql --user=inventory_app --password --execute "SELECT 1 AS over_the_socket"
Output
over_the_socket
1

So your Compose health check and docker compose exec sessions keep working. It's also not a check on who the server is: for that, clients need VerifyFull.

Step 3: Turn It Off, If You Need To​

RESET PERSIST forgets the saved value, and the running server needs its own change:

mysql>
RESET PERSIST require_secure_transport;
SET GLOBAL require_secure_transport = OFF;
SHOW VARIABLES LIKE 'require_secure_transport';
Output
Query OK, 0 rows affected (0.002 sec)

Query OK, 0 rows affected (0.000 sec)

+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| require_secure_transport | OFF |
+--------------------------+-------+
1 row in set (0.002 sec)

This or REQUIRE SSL?​

require_secure_transportALTER USER … REQUIRE SSL
Applies toEvery accountOne account
A local socketAllowedRefused
RefusalSays whyA plain Access denied

For most servers, this one is simpler and clearer. How to Require TLS for One MySQL Account covers the other.

Common Mistakes​

MistakeWhat happensDo this instead
Using SET GLOBAL to turn it onA restart turns it offUse SET PERSIST
Turning it on before checking your clientsSome stop connectingCheck SslMode in each one first
Testing over a socketThat was always allowedTest over TCP

Troubleshooting​

SymptomLikely causeFix
ERROR 3159A client without TLSThe fix
From .NET: Connections using insecure transport are prohibitedSslMode=Disabled or NoneThe fix
It's on again after you turned it offYou didn't RESET PERSISTHow to Undo SET PERSIST in MySQL
Nothing can connect over TCPThe server has no working TLSThe fix

Conclusion​

SET PERSIST require_secure_transport = ON makes the server refuse connections without TLS, and it survives a restart. Local sockets still work, so your own tools keep running.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.