使用加密連線來連線到適用於 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 設定的不同設定:
重要
根據 移除 TLS 1.0 和 TLS 1.1 通訊協定的支援,從 2024 年 9 月初開始,將不再允許新伺服器使用 TLS 1.0 或 1.1,而且不允許現有伺服器降級至這些版本。 從 2024 年 9 月中旬開始,我們將起始目前使用 TLS 1.0 或 1.1 到 TLS 1.2 的所有伺服器強制升級。 此升級程式預計將在 2024 年 9 月底之前完成。 強烈建議客戶確保其應用程式在 9 月底之前與 TLS 1.2 完全相容。
案例 | 伺服器參數設定 | 描述 |
---|---|---|
停用 SSL 強制執行 | require_secure_transport = OFF | 如果您的舊版應用程式不支援對適用於 MySQL 的 Azure 資料庫彈性伺服器的加密連線,則可藉由設定 require_secure_transport=OFF 來停用對適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體的加密連線強制執行。 |
使用 TLS < 1.2 版強制執行 SSL(將於 2024 年 9 月淘汰) | 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 的 Azure 資料庫彈性伺服器執行個體
- 停用 SSL
- 使用 TLS 版本強制執行 SSL
- 使用 mysql 命令列連線到適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體
- 停用加密連線
- 啟用加密連線
- 確認連線的加密狀態
- 使用各種應用程式架構,使用加密連線連接至適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體
停用適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上的 SSL 強制執行
如果您的用戶端應用程式不支援加密連線,您必須停用適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體上的加密連線強制執行。 若要停用加密連線強制執行,您必須如螢幕擷取畫面所示,將 require_secure_transport 伺服器參數設定為關閉,並儲存伺服器參數組態,使其生效。 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 設定為關閉並不表示伺服器端不支援加密連線。 如果您在適用於 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(將於 2024 年 9 月淘汰) TLS 1.2 | TLS 1.2 |
MySQL 8.0 | TLS 1.2、TLS 1.3 | TLS 1.2 |
使用 mysql 命令列用戶端搭配 TLS/SSL 連線
下載公用 SSL 憑證
若要搭配用戶端應用程式使用加密連線,您必須下載公用 SSL 憑證,此憑證也可以在 Azure 入口網站的 [網路] 窗格中取得,如下列螢幕擷取畫面所示。
注意
您必須為 Azure Government 雲端中的伺服器下載此 SSL 憑證。
儲存憑證檔案至慣用位置。 例如,本教學課程會在本地環境或託管應用程式所在的用戶端環境上使用 c:\ssl
或 \var\www\html\bin
。 這可讓應用程式透過 SSL 安全地連線到資料庫。
如果您使用私人存取 (VNet 整合) 建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體,就必須從與伺服器相同的 VNet 中的資源連線到伺服器。 您可以建立虛擬機器,並新增至使用您適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體建立的 VNet。
如果您使用公用存取 (允許的 IP 位址)建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體,可以將本機 IP 位址新增至伺服器上的防火牆規則清單。
您可以從本地環境中選擇 mysql.exe 或 MySQL 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='<password>',
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='<password>',
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;
});