使用加密連線來連線到適用於 MySQL 的 Azure 資料庫 (彈性伺服器)

適用於:適用於 MySQL 的 Azure 資料庫 - 彈性伺服器

適用於 MySQL 的 Azure 資料庫彈性伺服器支援使用安全通訊端層 (SSL) 搭配傳輸層安全性 (TLS) 加密,將用戶端應用程式連線到適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體。 TLS 為業界標準通訊協定,可確保資料庫伺服器與用戶端應用程式之間的網路連線經過加密,讓您遵守合規性需求。

適用於 MySQL 的 Azure 資料庫彈性伺服器預設支援使用傳輸層安全性 (TLS 1.2) 的加密連線,且預設會拒絕所有使用 TLS 1.0 和 TLS 1.1 的連入連線。 您可以如本文所述,變更彈性伺服器上的加密連線強制執行或 TLS 版本設定。

以下是適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體可用 SSL 和 TLS 設定的不同設定:

案例 伺服器參數設定 描述
停用 SSL 強制執行 require_secure_transport = OFF 如果您的舊版應用程式不支援對適用於 MySQL 的 Azure 資料庫彈性伺服器的加密連線,則可藉由設定 require_secure_transport=OFF 來停用對適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體的加密連線強制執行。
強制使用 TLS 版本 < 1.2 版的 SSL require_secure_transport = ON 以及 tls_version = TLS 1.0 或 TLS 1.1 如果您的舊版應用程式支援加密連線,但需要 TLS 版本 < 1.2 版,您可以啟用加密連線,但設定適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體以允許與支援 TLS 版本 (1.0 或 1.1) 的連線。 僅支援適用於 MySQL 的 Azure 資料庫彈性伺服器 5.7 版
強制 SSL 使用 TLS 版本 = 1.2 (預設設定) require_secure_transport = ON 以及 tls_version = TLS 1.2 這是適用於 MySQL 的 Azure 資料庫彈性伺服器的建議和預設組態。
強制 SSL 使用 TLS 版本 = 1.3 require_secure_transport = ON 以及 tls_version = TLS 1.3 此設定對於新應用程式的開發很實用,建議使用。 僅支援適用於 MySQL 的 Azure 資料庫彈性伺服器 8.0 版

注意

  • 不支援變更適用於 MySQL 的 Azure 資料庫彈性伺服器上的 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 通訊協定的支援。 適用於 MySQL 的 Azure 資料庫彈性伺服器也會在社群停止支援通訊協定後停止支援 TLS 版本,以符合新式安全性標準。

在本文中,您將學會如何:

  • 設定您的適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體
    • 停用 SSL
    • 使用 TLS 版本強制執行 SSL
  • 使用 mysql 命令列連線到適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體
    • 停用加密連線
    • 啟用加密連線
  • 確認連線的加密狀態
  • 使用各種應用程式架構,使用加密連線連接至適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體

停用適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上的 SSL 強制執行

如果您的用戶端應用程式不支援加密連線,您必須停用適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上的加密連線強制執行。 若要停用加密連線強制執行,您必須如螢幕擷取畫面所示,將 require_secure_transport 伺服器參數設定為關閉,並儲存伺服器參數組態,使其生效。 require_secure_transport 是動態伺服器參數,會立即生效,而且不需要將伺服器重新開機,即會生效。

Screenshot showing how to disable SSL with Azure Database for MySQL flexible server.

在 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 設定為關閉並不表示伺服器端不支援加密連線。 如果您在適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上將 require_secure_transport 設定為關閉,但如果用戶端與加密連線連線,則仍會接受該連線。 下列使用 mysql 用戶端連線到使用 require_secure_transport=OFF 設定的適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體也會運作,如下所示。

 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)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

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 設定會放寬適用於 MySQL 的 Azure 資料庫彈性伺服器上加密連線的強制執行,並允許從用戶端對伺服器的未加密連線。

強制 SSL 使用 TLS 版本

若要在適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上設定 TLS 版本,您必須設定 *tls_version- 伺服器參數。 TLS 通訊協定的預設設定為 TLS 1.2。 如果您的應用程式支援使用 SSL 連線到 MySQL 伺服器,但需要 TLS 1.2 以外的任何通訊協定,您必須在伺服器參數中設定 TLS 版本。 *tls_version- 是靜態伺服器參數,需要將伺服器重新啟動,參數才會生效。 以下是適用於 MySQL 的 Azure 資料庫彈性伺服器可用版本的支援通訊協定。

適用於 MySQL 的 Azure 資料庫彈性伺服器版本 支援的 tls_version 值 預設設定
MySQL 5.7 TLS 1.0、TLS 1.1、TLS 1.2 TLS 1.2
MySQL 8.0 TLS 1.2、TLS 1.3 TLS 1.2

使用 mysql 命令列用戶端搭配 TLS/SSL 連線

下載公用 SSL 憑證

若要搭配用戶端應用程式使用加密連線,您必須下載公用 SSL 憑證,此憑證也可以在 Azure 入口網站的 [網路] 窗格中取得,如下列螢幕擷取畫面所示。

Screenshot showing how to download public SSL certificate from Azure portal.

注意

您必須為 Azure Government 雲端中的伺服器下載此 SSL 憑證

儲存憑證檔案至慣用位置。 例如,本教學課程會在本地環境或託管應用程式所在的用戶端環境上使用 c:\ssl\var\www\html\bin。 這可讓應用程式透過 SSL 安全地連線到資料庫。

如果您使用私人存取 (VNet 整合) 建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體,就必須從與伺服器相同的 VNet 中的資源連線到伺服器。 您可以建立虛擬機器,並新增至使用您適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體建立的 VNet。

如果您使用公用存取 (允許的 IP 位址)建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體,可以將本機 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 的值與您所儲存憑證的檔案路徑相符。 如果您要連線到適用於 MySQL 的 Azure 資料庫 - 彈性伺服器搭配 SSL 連線,並使用選項來執行憑證主體名稱的完整驗證 (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;

使用各種應用程式架構,使用加密連線連接至適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體

在 Azure 入口網站中,您的伺服器可用的 [連接字串] 頁面中所預先定義的連接字串,也包含通用語言使用 TLS/SSL 連線至資料庫伺服器所需的參數。 TLS/SSL 參數會根據連接器而有所不同。 例如,「useSSL=true」、「sslmode=required」或「ssl_verify_cert=true」和其他變化。

若要從透過 TLS/SSL 從應用程式建立與適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體的加密連線,請參閱下列程式碼範例:

WordPress

下載 SSL 公開憑證,並在行 // **MySQL settings - You can get this info from your web host** // 之後於 wp-config.php 中新增下列幾行。

//** Connect with SSL ** //
define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);
//** SSL CERT **//
define('MYSQL_SSL_CERT','/FULLPATH/on-client/to/DigiCertGlobalRootCA.crt.pem');

PHP

$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)

try:
    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'}
        }
    }
}

Ruby

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;
});

下一步