암호화된 연결을 사용하여 Azure Database for MySQL - 유연한 서버에 연결

적용 대상: Azure Database for MySQL - 유연한 서버

Azure Database for MySQL 유연한 서버는 TLS(전송 계층 보안) 암호화를 사용하는 SSL(Secure Sockets Layer)을 통해 클라이언트 애플리케이션을 Azure Database for MySQL 유연한 서버 인스턴스에 연결하도록 지원합니다. TLS는 데이터베이스 서버와 클라이언트 애플리케이션 간에 암호화된 네트워크 연결을 보장하여 규정 준수 요구 사항을 준수할 수 있도록 하는 업계 표준 프로토콜입니다.

Azure Database for MySQL 유연한 서버는 기본적으로 전송 계층 보안(TLS 1.2)을 사용하는 암호화된 연결을 지원하며 TLS 1.0 및 TLS 1.1을 사용하여 들어오는 연결은 기본적으로 모두 거부됩니다. 이 문서에서 설명하는 대로 유연한 서버에서 암호화된 연결 적용 또는 TLS 버전 구성을 변경할 수 있습니다.

다음은 Azure Database for MySQL 유연한 서버 인스턴스에 사용할 수 있는 다양한 SSL 및 TLS 설정 구성입니다.

시나리오 서버 매개 변수 설정 설명
SSL 적용 사용 안 함 require_secure_transport = OFF 레거시 애플리케이션이 Azure Database for MySQL 유연한 서버에 암호화된 연결을 지원하지 않는 경우 require_secure_transport=OFF를 설정하여 Azure Database for MySQL 유연한 서버 인스턴스에 암호화된 연결 적용을 사용하지 않도록 설정할 수 있습니다.
TLS 버전 1.2 미만으로 SSL 적용 require_secure_transport = ON 및 tls_version = TLS 1.0 또는 TLS 1.1 레거시 애플리케이션에서 암호화된 연결을 지원하지만 TLS 버전 <1.2 미만이 필요한 경우 암호화된 연결을 사용하도록 설정할 수 있지만 애플리케이션에서 지원하는 TLS 버전(1.0 또는 1.1)과의 연결을 허용하도록 Azure Database for MySQL 유연한 서버 인스턴스를 구성할 수 있습니다. Azure Database for MySQL 유연한 서버 버전 v5.7에서만 지원됨
TLS 버전 = 1.2를 사용하여 SSL 적용(기본 구성) require_secure_transport = ON 및 tls_version = TLS 1.2 이는 Azure Database for MySQL 유연한 서버에 권장되는 기본 구성입니다.
TLS 버전 = 1.3으로 SSL 적용 require_secure_transport = ON 및 tls_version = TLS 1.3 이는 새 애플리케이션 개발에 유용하며 권장됩니다. Azure Database for MySQL 유연한 서버 버전 v8.0에서만 지원됨

참고 항목

  • Azure Database for MySQL 유연한 서버에서 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 버전 지원도 중지합니다.

이 문서에서는 다음 방법을 설명합니다.

  • Azure Database for MySQL 유연한 서버 인스턴스 구성
    • SSL 사용 안 함
    • SSL이 TLS 버전에서 적용됨
  • MySQL 명령줄을 사용해 Azure Database for MySQL 유연한 서버 인스턴스에 연결
    • 암호화된 연결 사용 안 함
    • 암호화된 연결 사용
  • 연결에 대한 암호화 상태 확인
  • 다양한 애플리케이션 프레임워크를 사용하여 암호화된 연결로 Azure Database for MySQL 유연한 서버 인스턴스에 연결

Azure Database for MySQL 유연한 서버 인스턴스에서 SSL 적용 사용하지 않기

클라이언트 애플리케이션이 암호화된 연결을 지원하지 않는 경우 Azure Database for MySQL 유연한 서버 인스턴스에서 암호화된 연결 적용을 사용하지 않도록 설정해야 합니다. 암호화된 연결 적용을 사용하지 않도록 설정하려면 스크린샷에 표시된 대로 require_secure_transport 서버 매개 변수를 OFF로 설정하고 서버 매개 변수 구성을 저장하여 적용해야 합니다. 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

Important

require_secure_transport를 OFF로 설정한다고 해서 암호화된 연결이 서버 쪽에서 지원되지 않는다는 의미는 아닙니다. Azure Database for MySQL 유연한 서버 인스턴스에서 require_secure_transport를 OFF로 설정하였지만 클라이언트에서 암호화된 연결을 사용하여 연결하는 경우에도 계속 허용됩니다. require_secure_transport=OFF로 구성된 Azure Database for MySQL 유연한 서버 인스턴스에 mysql 클라이언트를 사용하는 다음 연결은 아래와 같이 작동합니다.

 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 설정은 Azure Database for MySQL 유연한 서버에서 암호화된 연결의 적용을 완화하고 암호화된 연결 외에도 클라이언트에서 서버로의 암호화되지 않은 연결을 허용합니다.

TLS 버전으로 SSL 적용

Azure Database for MySQL 유연한 서버 인스턴스에 TLS 버전을 설정하려면 *tls_version- 서버 매개 변수를 설정해야 합니다. TLS 프로토콜의 기본 설정은 TLS 1.2입니다. 애플리케이션이 SSL을 사용한 MySQL 서버에 대한 연결을 지원하지만 TLS 1.2 이외의 프로토콜이 필요한 경우 서버 매개 변수에서 TLS 버전을 설정해야 합니다. *tls_version-은 매개 변수를 적용하기 위해 서버를 다시 시작해야 하는 정적 서버 매개 변수입니다. 다음은 사용 가능한 버전의 Azure Database for MySQL 유연한 서버에 대해 지원되는 프로토콜입니다.

Azure Database for MySQL 유연한 서버 버전 지원되는 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

TLS/SSL과 함께 mysql 명령줄 클라이언트를 사용하여 연결

공용 SSL 인증서 다운로드

클라이언트 애플리케이션에서 암호화된 연결을 사용하려면 아래 스크린샷에 표시된 것처럼 Azure Portal 네트워킹 창에서 사용할 수 있는 퍼블릭 SSL 인증서를 다운로드해야 합니다.

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

참고 항목

Azure Government 클라우드의 서버에 대해 이 SSL 인증서를 다운로드해야 합니다.

인증서 파일을 원하는 위치에 저장합니다. 예를 들어 이 자습서에서는 애플리케이션이 호스트되는 로컬 환경 또는 클라이언트 환경에서 c:\ssl 또는 \var\www\html\bin을 사용합니다. 이렇게 하면 애플리케이션에서 SSL을 통해 데이터베이스에 안전하게 연결할 수 있습니다.

프라이빗 액세스(VNet 통합)를 사용하여 Azure Database for MySQL 유연한 서버 인스턴스를 만든 경우 서버와 동일한 VNet 내의 리소스에서 서버에 연결해야 합니다. 가상 머신을 만들고, Azure Database for MySQL 유연한 서버 인스턴스를 사용하여 만든 VNet에 이를 추가할 수 있습니다.

퍼블릭 액세스(허용된 IP 주소)를 사용하여 Azure Database for MySQL 유연한 서버 인스턴스를 만든 경우 로컬 IP 주소를 서버의 방화벽 규칙 목록에 추가할 수 있습니다.

mysql.exe 또는 MySQL 워크벤치를 선택하여--> 로컬 환경에서 서버에 연결할 수 있습니다.

다음 예제에서는 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: Cipher in use is 이 암호화 그룹은 예제를 표시하고 클라이언트를 기반으로 다른 암호화 그룹을 볼 수 있습니다.

서버에 구성된 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 Database for MySQL 유연한 서버 인스턴스에 연결

Azure Portal의 해당 서버에 사용 가능한 "연결 문자열" 페이지에서 미리 정의된 연결 문자열에는 TLS/SSL을 사용하여 데이터베이스 서버에 연결하기 위한 일반적인 언어에 대한 필수 매개 변수가 포함되어 있습니다. TLS/SSL 매개 변수는 커넥터에 따라 달라집니다. 예: "useSSL=true", "sslmode=required" 또는 "ssl_verify_cert=true" 및 기타 변형

애플리케이션에서 TLS/SSL을 통해 Azure Database for MySQL 유연한 서버 인스턴스에 대한 암호화된 연결을 설정하려면 다음 코드 샘플을 참조하세요.

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

다음 단계