适用于: Azure Database for MySQL - 灵活服务器

Azure Database for MySQL - 灵活服务器支持使用安全套接字层 (SSL) 和传输层安全性 (TLS) 加密将客户端应用程序连接到 MySQL 服务器。 TLS 是一种行业标准协议,可确保在数据库服务器与客户端应用程序之间实现加密的网络连接,使你能够满足合规性要求。

默认情况下,Azure Database for MySQL - 灵活服务器支持使用传输层安全性 (TLS 1.2) 的加密连接,并且拒绝所有使用 TLS 1.0 和 TLS 1.1 的传入连接。 你的灵活服务器上的加密连接强制要求或 TLS 版本配置可以按照本文中的说明进行更改。

下面是适用于灵活服务器的 SSL 和 TLS 设置的不同配置:

服务器参数设置 禁用 SSL 强制要求 require_secure_transport 设置为 OFF 如果旧版应用程序不支持与 MySQL 服务器建立加密连接,则可以通过将 require_secure_transport 设置为 OFF,来禁用与灵活服务器建立加密连接的强制要求。 强制使用 SSL 和低于 TLS 版本 1.2 的版本 require_secure_transport 设置为 ON,且 tls_version 设置为 TLS 1.0 或 TLS 1.1 如果旧版应用程序支持加密连接,但需要低于 TLS 版本 1.2 的版本,你可以启用加密连接,但将灵活服务器配置为允许连接使用应用程序支持的 TLS 版本(1.0 或 1.1)。 仅在 Azure Database for MySQL - 灵活服务器版本 v5.7 中受支持 强制使用 SSL 和 TLS 版本 1.2(默认配置) require_secure_transport 设置为 ON,且 tls_version 设置为 TLS 1.2 这是为灵活服务器建议的配置,同时也是默认配置。 强制使用 SSL 和 TLS 版本 1.3 require_secure_transport 设置为 ON,且 tls_version 设置为 TLS 1.3 这是为新应用程序开发建议的有用配置。 仅在 Azure Database for MySQL - 灵活服务器版本 v8.0 中受支持
  • 不支持对灵活服务器上的 SSL 密码进行更改。 将 tls_version 设置为 TLS 版本 1.2 时,默认强制使用 FIPS 密码套件。 对于版本 1.2 以外的其他 TLS 版本,SSL 密码将设为 MySQL 社区安装附带的默认设置。
  • 自 MySQL 版本 8.0.26 和 5.7.35 后的 MySQL 开源社区版本,TLS 1.0 和 TLS 1.1 协议已弃用。 这些协议分别发布于 1996 年和 2006 年,用于加密动态数据,现在被认为脆弱、过时且容易受到安全威胁。 有关详细信息,请参阅 取消对 TLS 1.0 和 TLS 1.1 协议的支持 。社区停止对该协议的支持时,Azure Database for MySQL - 灵活服务器也停止支持 TLS 版本,以满足新式安全标准。
  • 在本文中,学习如何:

  • 在以下条件下配置灵活服务器
    • 禁用 SSL
    • 强制使用 SSL 和 TLS 版本
    • 在以下条件下使用 mysql 命令行连接到灵活服务器
      • 禁用加密连接
      • 启用加密连接
      • 验证连接的加密状态
      • 使用各种应用程序框架以加密连接方式连接到灵活服务器
      • 在灵活服务器上禁用 SSL 强制要求

        如果客户端应用程序不支持加密连接,则需要在灵活服务器上禁用加密连接强制要求。 若要禁用加密连接强制要求,需要将 require_secure_transport 服务器参数设置为“OFF”(如屏幕截图所示),并保存服务器参数配置,以使其生效。 require_secure_transport 是一个动态服务器参数,它会立即生效,无需重启服务器。

        在禁用 SSL 的情况下使用 mysql 命令行客户端进行连接

        以下示例演示如何使用 mysql 命令行界面连接到服务器。 使用 --ssl-mode=DISABLED 连接字符串设置来禁用来自 mysql 客户端的 TLS/SSL 连接。 将值替换为实际的服务器名称和密码。

         mysql.exe -h mydemoserver.mysql.database.azure.com -u myadmin -p --ssl-mode=DISABLED
        

        将 require_secure_transport 设置为 OFF 并不意味着服务器端不支持加密连接。 如果在灵活服务器上将 require_secure_transport 设置为 OFF,则在客户端以加密连接方式连接时,仍然会被接受。 使用 mysql 客户端连接到配置了 require_secure_transport=OFF 的灵活服务器后,也可以正常工作,如下所示。

         mysql.exe -h mydemoserver.mysql.database.azure.com -u myadmin -p --ssl-mode=REQUIRED
        
        Welcome to the MySQL monitor.  Commands end with ; or \g.
        Your MySQL connection id is 17
        Server version: 5.7.29-log MySQL Community Server (GPL)
        Oracle is a registered trademark of Oracle Corporation and/or its
        affiliates. Other names may be trademarks of their respective
        owners.
        Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
        mysql> show global variables like '%require_secure_transport%';
        +--------------------------+-------+
        | Variable_name | Value |
        +--------------------------+-------+
        | require_secure_transport | OFF |
        +--------------------------+-------+
        1 row in set (0.02 sec)
        

        总之,require_secure_transport=OFF 设置放宽了在灵活服务器上强制执行加密连接的要求,除了加密连接之外,还允许从客户端到服务器的非加密连接。

        强制使用 SSL 和 TLS 版本

        若要在灵活服务器上设置 TLS 版本,需设置 *tls_version- 服务器参数。 TLS 协议的默认设置是 TLS 1.2。 如果应用程序支持使用 SSL 连接到 MySQL 服务器,但需要使用除 TLS 1.2 以外的任意协议,则需要在服务器参数中设置 TLS 版本。 *tls_version- 是静态服务器参数,需要重启服务器才能使该参数生效。 以下是 Azure Database for MySQL - 灵活服务器的可用版本所支持的协议

        灵活服务器版本 支持的 tls_version 值

        必须为 Azure 政府云中的服务器下载此 SSL 证书

        将证书文件保存到首选位置。 例如,本教程在本地环境或托管应用程序的客户端环境中使用 c:\ssl\var\www\html\bin。 这允许应用程序通过 SSL 安全连接到数据库。

        如果使用“专用访问(VNet 集成)”创建了灵活服务器,需要从与服务器相同的 VNet 中的资源连接到服务器。 可以创建虚拟机并将其添加到使用灵活服务器创建的 VNet 中。

        如果使用“公共访问(允许的 IP 地址)”创建了灵活服务器,可以将本地 IP 地址添加到服务器上的防火墙规则列表中。

        可以选择 mysql.exeMySQL Workbench,以从本地环境连接到服务器。

        以下示例演示如何使用 mysql 命令行界面连接到服务器。 使用 --ssl-mode=REQUIRED 连接字符串设置强制实施 TLS/SSL 证书验证。 将本地证书文件路径传递给 --ssl-ca 参数。 将值替换为实际的服务器名称和密码。

        sudo apt-get install mysql-client
        wget --no-check-certificate https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem
        mysql -h mydemoserver.mysql.database.azure.com -u mydemouser -p --ssl-mode=REQUIRED --ssl-ca=DigiCertGlobalRootCA.crt.pem
        

        确认传递给 --ssl-ca 的值与你保存的证书的文件路径匹配。 如果要使用 SSL 连接到 Azure Database for MySQL 灵活服务器,并通过一个选项使用证书主体名称执行完整验证 (sslmode=VERTIFY_IDENTITY),请在连接字符串中使用 <servername>.mysql.database.azure.com。

        如果你尝试以未加密的连接方式连接到你的服务器,将会出现错误,指示禁止使用不安全传输的连接,类似于以下内容:

        ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.
        

        验证 TLS/SSL 连接

        执行 mysql status 命令,验证是否已使用 TLS/SSL 连接到 MySQL 服务器:

        mysql> status
        

        查看输出,确认连接是否已加密,如果已加密,输出应显示为:“SSL: 使用的密码为”。 此密码套件显示了一个示例。你可能会看到不同的密码套件,具体取决于客户端。

        如何标识服务器上配置的 TLS 协议?

        你可以运行命令 SHOW GLOBAL VARIABLES LIKE 'tls_version';然后查看该值以了解所有协议的配置。

        mysql> SHOW GLOBAL VARIABLES LIKE 'tls_version';
        

        如何查找客户端正在使用哪个 TLS 协议连接到服务器?

        你可以运行以下命令并查看会话的 tls_version 以确定用于连接的 TLS 版本。

        SELECT sbt.variable_value AS tls_version,  t2.variable_value AS cipher,
        processlist_user AS user, processlist_host AS host
        FROM performance_schema.status_by_thread  AS sbt
        JOIN performance_schema.threads AS t ON t.thread_id = sbt.thread_id
        JOIN performance_schema.status_by_thread AS t2 ON t2.thread_id = t.thread_id
        WHERE sbt.variable_name = 'Ssl_version' and t2.variable_name = 'Ssl_cipher' ORDER BY tls_version;
        

        使用各种应用程序框架以加密连接方式连接到灵活服务器

        在 Azure 门户中,你的服务器的“连接字符串”页面中预定义了连接字符串。该字符串中包含以通用语言使用 TLS/SSL 连接到数据库服务器所需的参数。 TLS/SSL 参数因连接器而异。 例如,“useSSL=true”、“sslmode=required”或“ssl_verify_cert=true”以及其他变体。

        若要从应用程序通过 TLS/SSL 与灵活服务器建立加密连接,请参阅以下代码示例:

        WordPress

        下载 SSL 公共证书,在 wp-config.php 中的 // **MySQL settings - You can get this info from your web host** // 行之后添加以下几行。

        //** Connect with SSL ** //
        define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);
        //** SSL CERT **//
        define('MYSQL_SSL_CERT','/FULLPATH/on-client/to/DigiCertGlobalRootCA.crt.pem');
        
        $conn = mysqli_init();
        mysqli_ssl_set($conn,NULL,NULL, "/var/www/html/DigiCertGlobalRootCA.crt.pem", NULL, NULL);
        mysqli_real_connect($conn, 'mydemoserver.mysql.database.azure.com', 'myadmin', 'yourpassword', 'quickstartdb', 3306, MYSQLI_CLIENT_SSL);
        if (mysqli_connect_errno()) {
        die('Failed to connect to MySQL: '.mysqli_connect_error());
        

        PHP(使用 PDO)

        $options = array(
            PDO::MYSQL_ATTR_SSL_CA => '/var/www/html/DigiCertGlobalRootCA.crt.pem'
        $db = new PDO('mysql:host=mydemoserver.mysql.database.azure.com;port=3306;dbname=databasename', 'myadmin', 'yourpassword', $options);
        

        Python (MySQLConnector Python)

        conn = mysql.connector.connect(user='myadmin', password='yourpassword', database='quickstartdb', host='mydemoserver.mysql.database.azure.com', ssl_ca='/var/www/html/DigiCertGlobalRootCA.crt.pem') except mysql.connector.Error as err: print(err)

        Python (PyMySQL)

        conn = pymysql.connect(user='myadmin',
                               password='yourpassword',
                               database='quickstartdb',
                               host='mydemoserver.mysql.database.azure.com',
                               ssl={'ca': '/var/www/html/DigiCertGlobalRootCA.crt.pem'})
        

        Django (PyMySQL)

        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'quickstartdb',
                'USER': 'myadmin',
                'PASSWORD': 'yourpassword',
                'HOST': 'mydemoserver.mysql.database.azure.com',
                'PORT': '3306',
                'OPTIONS': {
                    'ssl': {'ca': '/var/www/html/DigiCertGlobalRootCA.crt.pem'}
        
        client = Mysql2::Client.new(
                :host     => 'mydemoserver.mysql.database.azure.com',
                :username => 'myadmin',
                :password => 'yourpassword',
                :database => 'quickstartdb',
                :sslca => '/var/www/html/DigiCertGlobalRootCA.crt.pem'
        

        Golang

        rootCertPool := x509.NewCertPool()
        pem, _ := ioutil.ReadFile("/var/www/html/DigiCertGlobalRootCA.crt.pem")
        if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
            log.Fatal("Failed to append PEM.")
        mysql.RegisterTLSConfig("custom", &tls.Config{RootCAs: rootCertPool})
        var connectionString string
        connectionString = fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?allowNativePasswords=true&tls=custom",'myadmin' , 'yourpassword', 'mydemoserver.mysql.database.azure.com', 'quickstartdb')
        db, _ := sql.Open("mysql", connectionString)
        

        Java(适用于 Java 的 MySQL 连接器)

        # generate truststore and keystore in code
        String importCert = " -import "+
            " -alias mysqlServerCACert "+
            " -file " + ssl_ca +
            " -keystore truststore "+
            " -trustcacerts " +
            " -storepass password -noprompt ";
        String genKey = " -genkey -keyalg rsa " +
            " -alias mysqlClientCertificate -keystore keystore " +
            " -storepass password123 -keypass password " +
            " -dname CN=MS ";
        sun.security.tools.keytool.Main.main(importCert.trim().split("\\s+"));
        sun.security.tools.keytool.Main.main(genKey.trim().split("\\s+"));
        # use the generated keystore and truststore
        System.setProperty("javax.net.ssl.keyStore","path_to_keystore_file");
        System.setProperty("javax.net.ssl.keyStorePassword","password");
        System.setProperty("javax.net.ssl.trustStore","path_to_truststore_file");
        System.setProperty("javax.net.ssl.trustStorePassword","password");
        url = String.format("jdbc:mysql://%s/%s?serverTimezone=UTC&useSSL=true", 'mydemoserver.mysql.database.azure.com', 'quickstartdb');
        properties.setProperty("user", 'myadmin');
        properties.setProperty("password", 'yourpassword');
        conn = DriverManager.getConnection(url, properties);
        

        Java(适用于 Java 的 MariaDB 连接器)

        # generate truststore and keystore in code
        String importCert = " -import "+
            " -alias mysqlServerCACert "+
            " -file " + ssl_ca +
            " -keystore truststore "+
            " -trustcacerts " +
            " -storepass password -noprompt ";
        String genKey = " -genkey -keyalg rsa " +
            " -alias mysqlClientCertificate -keystore keystore " +
            " -storepass password123 -keypass password " +
            " -dname CN=MS ";
        sun.security.tools.keytool.Main.main(importCert.trim().split("\\s+"));
        sun.security.tools.keytool.Main.main(genKey.trim().split("\\s+"));
        # use the generated keystore and truststore
        System.setProperty("javax.net.ssl.keyStore","path_to_keystore_file");
        System.setProperty("javax.net.ssl.keyStorePassword","password");
        System.setProperty("javax.net.ssl.trustStore","path_to_truststore_file");
        System.setProperty("javax.net.ssl.trustStorePassword","password");
        url = String.format("jdbc:mariadb://%s/%s?useSSL=true&trustServerCertificate=true", 'mydemoserver.mysql.database.azure.com', 'quickstartdb');
        properties.setProperty("user", 'myadmin');
        properties.setProperty("password", 'yourpassword');
        conn = DriverManager.getConnection(url, properties);
        

        .NET (MySqlConnector)

        var builder = new MySqlConnectionStringBuilder
            Server = "mydemoserver.mysql.database.azure.com",
            UserID = "myadmin",
            Password = "yourpassword",
            Database = "quickstartdb",
            SslMode = MySqlSslMode.VerifyCA,
            SslCa = "DigiCertGlobalRootCA.crt.pem",
        using (var connection = new MySqlConnection(builder.ConnectionString))
            connection.Open();
        

        Node.js

        var fs = require('fs');
        var mysql = require('mysql');
        const serverCa = [fs.readFileSync("/var/www/html/DigiCertGlobalRootCA.crt.pem", "utf8")];
        var conn=mysql.createConnection({
            host:"mydemoserver.mysql.database.azure.com",
            user:"myadmin",
            password:"yourpassword",
            database:"quickstartdb",
            port:3306,
            ssl: {
                rejectUnauthorized: true,
                ca: serverCa
        conn.connect(function(err) {
          if (err) throw err;
        
      • 使用 MySQL Workbench 连接到 Azure Database for MySQL - 灵活服务器并查询其中的数据
      • 使用 PHP 连接到 Azure Database for MySQL - 灵活服务器并查询其中的数据
      • 使用 Azure CLI 创建和管理 Azure Database for MySQL - 灵活服务器虚拟网络
      • 详细了解 Azure Database for MySQL - 灵活服务器中的网络
      • 详细了解 Azure Database for MySQL - 灵活服务器防火墙规则
  •