TLS


https://dev.mysql.com/doc/refman/8.4/en/using-encrypted-connections.html
https://dev.mysql.com/doc/refman/8.4/en/encrypted-connection-protocols-ciphers.html
https://dev.mysql.com/doc/refman/8.4/en/creating-ssl-rsa-files.html
https://dev.mysql.com/doc/refman/8.4/en/connection-options.html

1. Important Points#

MySQL 支持 TLS 加密连接。生产环境里,重点不是“能连上”,而是“强制加密 + 验证 CA + 验证主机名”。

server side:
    enable encrypted connections
    require secure transport for client connections

client side:
    use VERIFY_CA or VERIFY_IDENTITY
    pin CA certificate
    verify server hostname when possible

do not do this in production:
    ssl-mode=DISABLED
    rejectUnauthorized=false
    insecure_skip_verify

2. Server Configuration#

常见服务端配置:

[mysqld]
require_secure_transport=ON
tls_version=TLSv1.2,TLSv1.3
ssl_ca=/etc/mysql/certs/ca.pem
ssl_cert=/etc/mysql/certs/server-cert.pem
ssl_key=/etc/mysql/certs/server-key.pem
file layout:
    /etc/mysql/certs/ca.pem
    /etc/mysql/certs/server-cert.pem
    /etc/mysql/certs/server-key.pem

permissions:
    private key should be readable only by mysql process owner
    certificate files should not be world-writable

检查当前状态:

SHOW VARIABLES LIKE 'require_secure_transport';
SHOW VARIABLES LIKE 'tls_version';
SHOW VARIABLES LIKE 'have_ssl';
note:
    MySQL 8.4 supports TLSv1.2 and TLSv1.3 for connections

3. Client Configuration / Verify#

推荐用客户端显式验证:

mysql \
  --host=db.example.com \
  --user=shop_app \
  --password \
  --ssl-mode=VERIFY_IDENTITY \
  --ssl-ca=/etc/mysql/certs/ca.pem \
  -e "SHOW STATUS LIKE 'Ssl_cipher';"

如果不方便做主机名校验,最低也要做 CA 校验:

mysql \
  --host=db.example.com \
  --user=shop_app \
  --password \
  --ssl-mode=VERIFY_CA \
  --ssl-ca=/etc/mysql/certs/ca.pem

验证当前会话:

SHOW STATUS LIKE 'Ssl_cipher';
SHOW STATUS LIKE 'Ssl_version';

4. Java#

JDBC URL example:
    jdbc:mysql://db.example.com:3306/shop?sslMode=VERIFY_IDENTITY&enabledTLSProtocols=TLSv1.2,TLSv1.3

recommendation:
    trust the server CA
    keep hostname verification on

5. Python#

mysql-connector-python style:
    ssl_ca=/etc/mysql/certs/ca.pem
    ssl_verify_cert=True
    ssl_verify_identity=True

6. Go#

go-sql-driver/mysql style:
    register a tls.Config with RootCAs and ServerName
    use tls=custom in the DSN

7. Node.js#

mysql2 style:
    ssl:
        ca: fs.readFileSync('/etc/mysql/certs/ca.pem')
        rejectUnauthorized: true