how-to-configure-ssl-tls-for-mysql-on-ubuntu-16-04
前書き
MySQLは、世界で最も人気のあるオープンソースのリレーショナルデータベース管理システムです。 最新のパッケージマネージャーは、MySQLを起動して実行する際の摩擦をある程度軽減しましたが、インストール後に実行する必要がある設定がまだあります。 余分な時間を費やす最も重要な分野の1つはセキュリティです。
デフォルトでは、MySQLはローカル接続のみを受け入れるように設定されています。 リモート接続を許可する必要がある場合は、安全に行うことが重要です。 このガイドでは、Ubuntu 16.04でMySQLを構成して、SSL / TLS暗号化によるリモート接続を受け入れる方法を示します。
前提条件
このガイドに従うには、* 2 * Ubuntu 16.04サーバーが必要です。 1つをMySQLサーバーとして使用し、もう1つをクライアントとして使用します。 これらの各サーバーで「+ sudo +」権限を持つ非ルートユーザーを作成します。 Ubuntu 16.04初期サーバー設定ガイドに従って、サーバーを適切な初期状態にします。
最初のマシンに、* MySQLサーバー*をインストールして構成する必要があります。 Ubuntu 16.04用MySQLインストールガイドに従って、ソフトウェアをインストールおよび構成します。
2番目のマシンで、* MySQLクライアント*パッケージをインストールします。 次のように入力して、 `+ apt +`パッケージインデックスを更新し、必要なソフトウェアをインストールできます。
sudo apt-get update
sudo apt-get install mysql-client
サーバーとクライアントの準備ができたら、以下に進みます。
現在のSSL / TLSステータスを確認する
開始する前に、* MySQLサーバー*インスタンスでSSL / TLSの現在のステータスを確認できます。
+ root +
MySQLユーザーを使用してMySQLセッションにログインします。 クライアントがローカルソケットファイルを使用する代わりにTCPで接続するように、「+-h +」を使用してIPv4ローカルループバックインターフェースを指定します。 これにより、TCP接続のSSLステータスを確認できます。
mysql -u root -p -h 127.0.0.1
インストールプロセス中に選択したMySQL `+ root`パスワードの入力を求められます。 その後、インタラクティブなMySQLセッションにドロップされます。
次のように入力して、SSL / TLS変数の状態を表示します。
SHOW VARIABLES LIKE '%ssl%';
Output+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | |
+---------------+----------+
9 rows in set (0.01 sec)
`+ have_openssl `と ` have_ssl `変数は両方とも ` DISABLED +`としてマークされています。 これは、SSL機能がサーバーにコンパイルされているが、まだ有効になっていないことを意味します。
現在の接続のステータスを確認して確認してください:
\s
Output--------------
mysql Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using EditLine wrapper
Connection id: 30
Current database:
Current user: [email protected]
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)
Protocol version: 10
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 3 hours 38 min 44 sec
Threads: 1 Questions: 70 Slow queries: 0 Opens: 121 Flush tables: 1 Open tables: 40 Queries per second avg: 0.005
--------------
上記の出力が示すように、TCPを介して接続されている場合でも、SSLは現在接続に使用されていません。
終了したら、現在のMySQLセッションを閉じます。
exit
これで、接続を保護するためにSSL用にMySQLの設定を開始できます。
SSL / TLS証明書とキーを生成する
MySQLへのSSL接続を有効にするには、まず適切な証明書とキーファイルを生成する必要があります。 このプロセスを簡素化するために、MySQL 5.7以降では「+ mysql_ssl_rsa_setup +」というユーティリティが提供されています。 Ubuntu 16.04にはMySQLの互換バージョンがあるため、このコマンドを使用して必要なファイルを生成できます。
ファイルは、 `+ / var / lib / mysql`にあるMySQLデータディレクトリに作成されます。 生成されたファイルを読み取るにはMySQLプロセスが必要なので、生成されたファイルを所有するユーザーとして `+ mysql +`を渡します。
sudo mysql_ssl_rsa_setup --uid=mysql
生成により、次のような出力が生成されます。
OutputGenerating a 2048 bit RSA private key
...................................+++
.....+++
writing new private key to 'ca-key.pem'
-----
Generating a 2048 bit RSA private key
......+++
.................................+++
writing new private key to 'server-key.pem'
-----
Generating a 2048 bit RSA private key
......................................................+++
.................................................................................+++
writing new private key to 'client-key.pem'
-----
次のように入力して、生成されたファイルを確認します。
sudo find /var/lib/mysql -name '*.pem' -ls
Output 256740 4 -rw-r--r-- 1 1078 Mar 17 17:24 /var/lib/mysql/
256735 4 -rw------- 1 1675 Mar 17 17:24 /var/lib/mysqlsql/
256739 4 -rw-r--r-- 1 451 Mar 17 17:24 /var/lib/mysqlsql/
256741 4 -rw------- 1 1679 Mar 17 17:24 /var/lib/mysqlsql/
256737 4 -rw-r--r-- 1 1074 Mar 17 17:24 /var/lib/mysqlsql/
256743 4 -rw-r--r-- 1 1078 Mar 17 17:24 /var/lib/mysqlsql/
256736 4 -rw------- 1 1675 Mar 17 17:24 /var/lib/mysqlsql/
256738 4 -rw------- 1 1675 Mar 17 17:24 /var/lib/mysqlsql/
最後の列には、生成されたファイル名が表示されます。 「mysql」を示す中央の列は、生成されたファイルが正しいユーザーおよびグループの所有権を持っていることを示しています。
これらのファイルは、認証局(「ca」で始まる)、MySQLサーバープロセス(「server」で始まる)、およびMySQLクライアント(「client」で始まる)のキーと証明書のペアです。 さらに、MySQLはSSLを使用しないときにパスワードを安全に転送するために、「+ private_key.pem 」および「 public_key.pem +」ファイルを使用します。
MySQLサーバーでSSL接続を有効にする
最新のMySQLバージョンは、サーバーの起動時にMySQLデータディレクトリ内で適切な証明書ファイルを探します。 このため、SSLを有効にするためにMySQL構成を実際に変更する必要はありません。
代わりに、MySQLサービスを再起動するだけです。
sudo systemctl restart mysql
再起動後、以前と同じコマンドを使用して新しいMySQLセッションを開きます。 サーバーがサポートしている場合、MySQLクライアントはSSLを使用して自動的に接続を試みます。
mysql -u root -p -h 127.0.0.1
前回リクエストしたのと同じ情報を見てみましょう。 SSL関連の変数の値を確認します。
SHOW VARIABLES LIKE '%ssl%';
Output+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | ca.pem |
| ssl_capath | |
| ssl_cert | server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | server-key.pem |
+---------------+-----------------+
9 rows in set (0.00 sec)
+ have_openssl +`および `+ have_ssl +`変数は、今回は「無効」ではなく「YES」になります。 さらに、 `+ ssl_ca +
、 + ssl_cert +
、および `+ ssl_key +`変数には、生成した関連証明書の名前が入力されています。
次に、接続の詳細をもう一度確認します。
\s
Output--------------
. . .
SSL:
. . .
. . .
--------------
今回は、特定のSSL暗号が表示され、接続を保護するためにSSLが使用されていることが示されます。
終了してシェルに戻ります。
exit
サーバーは暗号化を使用できるようになりましたが、リモートアクセスを許可し、セキュリティで保護された接続を使用するには、追加の構成が必要です。
リモートクライアントのセキュア接続の構成
サーバーでSSLを使用できるようになったので、安全なリモートアクセスの構成を開始できます。 これを行うには、次のことが必要です。
-
リモート接続にSSLを要求する
-
パブリックインターフェイスにバインドする
-
リモート接続用のMySQLユーザーを作成する
-
ファイアウォールルールを調整して外部接続を許可する
必須SSLを使用したリモートアクセスの構成
現在、MySQLサーバーはクライアントからのSSL接続を受け入れるように構成されています。 ただし、クライアントから要求された場合、暗号化されていない接続は引き続き許可されます。
これを修正するには、 `+ require_secure_transport +`オプションをオンにします。 これには、SSLまたはローカルUnixソケットのいずれかですべての接続を確立する必要があります。 Unixソケットはサーバー自体内からのみアクセスできるため、リモートユーザーに開かれている接続オプションはSSLのみです。
この設定を有効にするには、テキストエディターで `+ / etc / mysql / my.cnf +`ファイルを開きます:
sudo nano /etc/mysql/my.cnf
内部には、追加の設定ファイルのソースとして使用される2つの `+!includedir +`ディレクティブがあります。 これらの行の下に独自の構成を配置して、競合する設定を上書きする必要があります。
MySQLサーバープロセスを対象とする `+ [mysqld] `セクションを作成することから始めます。 セクションヘッダーの下で、「 require_secure_transport」を「+ ON +」に設定します。
/etc/mysql/my.cnf
. . .
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
その行は、安全な接続を実施するために必要な唯一の設定です。
デフォルトでは、MySQLはローカルコンピューターからの接続のみをリッスンするように構成されています。 リモート接続をリッスンするように設定するには、 `+ bind-address +`を別のインターフェースに設定できます。
MySQLがそのインターフェースのいずれかで接続を受け入れることができるようにするために、「+ bind-address +」を「0.0.0.0」に設定できます。
/etc/mysql/my.cnf
. . .
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
# Require clients to connect either using SSL
# or through a local socket file
require_secure_transport = ON
完了したら、ファイルを保存して閉じます。
次に、MySQLを再起動して新しい設定を適用します。
sudo systemctl restart mysql
次のように入力して、MySQLが「127.0.0.1」ではなく「0.0.0.0」でリッスンしていることを確認します。
sudo netstat -plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:* LISTEN 4330/
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1874/sshd
tcp6 0 0 :::22 :::* LISTEN 1874/sshd
上記の出力の「0.0.0.0」は、MySQLが使用可能なすべてのインターフェースで接続をリッスンしていることを示しています。
次に、ファイアウォールを介したMySQL接続を許可する必要があります。 次を入力して例外を作成します。
sudo ufw allow mysql
OutputRule added
Rule added (v6)
これで、リモート接続の試行がMySQLサーバーに到達できるはずです。
リモートMySQLユーザーを構成する
MySQLサーバーはリモート接続をリッスンしていますが、現在、外部コンピューターから接続できるユーザーは構成されていません。
`+ root +`ユーザーとしてMySQLにログインして開始します:
mysql -u root -p
内部では、 `+ CREATE USER +`コマンドを使用して新しいリモートユーザーを作成できます。 ユーザー仕様のホスト部分でクライアントマシンのIPアドレスを使用して、そのマシンへの接続を制限します。
将来的に「+ require_secure_transport 」オプションがオフになった場合の冗長性のために、アカウントの作成時に「 REQUIRE SSL +」句を含めることでこのユーザーがSSLを必要とすることも指定します。
CREATE USER ''@'' IDENTIFIED BY '' REQUIRE SSL;
次に、アクセスする必要のあるデータベースまたはテーブルに対するアクセス許可を新しいユーザーに付与します。 デモンストレーションのために、「+ example of」データベースを作成し、新しいユーザーの所有権を付与します。
CREATE DATABASE example;
GRANT ALL ON example.* TO ''@'';
次に、特権をフラッシュして、これらの設定をすぐに適用します。
FLUSH PRIVILEGES;
終了したら、シェルに戻って終了します。
exit
サーバーは、リモートユーザーへの接続を許可するように設定されています。
リモート接続のテスト
-
MySQLクライアント*マシンで、サーバーに正常に接続できることをテストして確認します。 リモートユーザーを指定するには「+ -u 」オプションを使用し、MySQLサーバーのIPアドレスを指定するには「 -h +」オプションを使用します。
mysql -u -p -h
パスワードを指定すると、リモートサーバーにログインします。
接続が安全であることを確認してください:
\s
Output--------------
. . .
. . .
. . .
--------------
終了してシェルに戻ります。
exit
次に、安全でない接続を試行します。
mysql -u -p -h --ssl-mode=disabled
パスワードの入力を求められたら、接続を拒否する必要があります。
OutputERROR 1045 (28000): Access denied for user 'remote_user'@'' (using password: YES)
これは私たちが目指していたものです。 SSL接続は許可され、暗号化されていない接続は拒否されることを示しています。
この時点で、MySQLサーバーはリモート接続を安全に受け入れるように構成されています。 これがセキュリティ要件を満たしている場合はここで停止できますが、セキュリティと信頼性をさらに高めるために追加できる部分がいくつかあります。
MySQL接続の検証の構成(オプション)
現在、MySQLサーバーは、ローカルで生成された認証局(CA)によって署名されたSSL証明書で構成されています。 サーバーの証明書とキーのペアは、着信接続を暗号化するのに十分です。
ただし、現在、認証局が提供できる信頼関係を活用していません。 CA証明書とクライアント証明書およびキーをクライアントに配布することにより、両方の当事者は、相互に信頼できる認証局によって証明書が署名されたことを証明できます。 これにより、悪意のあるサーバーへのなりすまし接続を防ぐことができます。
この追加のオプションのセーフガードを実装するには、次のことが必要です。
-
適切なSSLファイルをクライアントマシンに転送する
-
クライアント構成ファイルを作成する
-
リモートユーザーを変更して、信頼できる証明書を要求する
クライアント証明書をクライアントマシンに転送する
まず、MySQLサーバーからMySQL CAおよびクライアント証明書ファイルを取得して、MySQLクライアントに配置する必要があります。
まず、接続に使用するユーザーのホームディレクトリに* MySQLクライアント*のディレクトリを作成します。 この `+ client-ssl +`を呼び出します:
mkdir ~/client-ssl
証明書キーは機密であるため、現在のユーザーのみがアクセスできるように、このディレクトリへのアクセスをロックダウンする必要があります。
chmod 700 ~/client-ssl
これで、証明書情報を新しいディレクトリにコピーできます。
-
MySQLサーバー*マシンで、次を入力してCA証明書の内容を表示します。
sudo cat /var/lib/mysql/ca.pem
Output-----BEGIN CERTIFICATE-----
. . .
-----END CERTIFICATE-----
+ BEGIN CERTIFICATE`および
+ END CERTIFICATE& `行を含む出力全体をクリップボードにコピーします。
-
MySQLクライアント*で、新しいディレクトリ内に同じ名前のファイルを作成します。
nano ~/client-ssl/ca.pem
内部に、コピーした証明書の内容をクリップボードから貼り付けます。 完了したら、ファイルを保存して閉じます。
次に、* MySQLサーバー*でクライアント証明書を表示します。
sudo cat /var/lib/mysql/client-cert.pem
Output-----BEGIN CERTIFICATE-----
. . .
-----END CERTIFICATE-----
再度、内容をクリップボードにコピーします。 最初と最後の行を忘れずに含めてください。
`+ client-ssl +`ディレクトリ内の* MySQLクライアント*で同じ名前のファイルを開きます:
nano ~/client-ssl/client-cert.pem
クリップボードから内容を貼り付けます。 ファイルを保存して閉じます。
最後に、* MySQLサーバー*上のクライアントキーファイルの内容を表示します。
sudo cat /var/lib/mysql/client-key.pem
Output-----BEGIN RSA PRIVATE KEY-----
. . .
-----END RSA PRIVATE KEY-----
最初と最後の行を含む表示された内容をクリップボードにコピーします。
-
MySQLクライアント*で、 `+ client-ssl +`ディレクトリにある同じ名前のファイルを開きます:
nano ~/client-ssl/client-key.pem
クリップボードから内容を貼り付けます。 ファイルを保存して閉じます。
これで、クライアントマシンには、MySQLサーバーにアクセスするために必要なすべての資格情報が必要です。 次に、リモートユーザーを変更する必要があります。
リモートユーザーに信頼されたCAからの証明書を要求する
現在、MySQLクライアントには、接続時にサーバーに証明書を提示するために使用できるファイルがあります。 ただし、信頼されたCAからのクライアント証明書を要求するようにサーバーはまだセットアップされていません。
これを変更するには、* MySQLサーバー*でMySQLルートアカウントに再度ログインします。
mysql -u root -p
次に、リモートユーザーの要件を変更する必要があります。 `+ REQUIRE SSL `句の代わりに、 ` REQUIRE X509 +`句を適用する必要があります。 これは、以前の要件で提供されたすべてのセキュリティを意味しますが、さらに、MySQLサーバーが信頼する認証局によって署名された証明書を提示するために接続クライアントを必要とします。
ユーザー要件を調整するには、 `+ ALTER USER`コマンドを使用します:
ALTER USER ''@'' REQUIRE X509;
変更をフラッシュして、すぐに適用されるようにします。
FLUSH PRIVILEGES;
終了したら、終了してシェルに戻ります。
exit
次に、接続できることを確認するためにテストできます。
接続時の証明書検証のテスト
ここで、接続時に両方の当事者を検証できるかどうかを確認する良い機会です。
-
MySQLクライアント*で、最初にクライアント証明書を提供せずに接続を試みます。
mysql -u -p -h
OutputERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)
クライアント証明書を提供しないと、サーバーは接続を拒否します。
次に、 +-ssl-ca
、` -ssl-cert`、および `-ssl-key `オプションを使用して接続し、 `〜/ client-ssls`内の関連ファイルを指すようにしますディレクトリ:
mysql -u -p -h --ssl-ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem
正常にログインするはずです。 ログアウトして、シェルセッションへのアクセスを回復します。
exit
サーバーへのアクセスを確認したので、わずかな使いやすさの改善を実装できます。
MySQLクライアント構成ファイルを作成する
接続するたびに証明書ファイルを指定する必要を回避するために、単純なMySQLクライアント構成ファイルを作成できます。
-
MySQLクライアント*マシンのホームディレクトリ内で、 `+〜/ .my.cnf +`という隠しファイルを作成します。
nano ~/.my.cnf
ファイルの先頭に、「+ [client] 」というセクションを作成します。 その下で、サーバーからコピーしたファイルを指すように、「 ssl-ca」、「+ ssl-cert」、および「+ ssl-key」オプションを設定できます。 これは次のようになります。
〜/ .my.cnf
[client]
ssl-ca = ~/client-ssl/ca.pem
ssl-cert = ~/client-ssl/client-cert.pem
ssl-key = ~/client-ssl/client-key.pem
`+ ssl-ca +`オプションは、クライアントに、MySQLサーバーによって提示された証明書が、指定した認証局によって署名されていることを確認するように指示します。 これにより、クライアントは信頼されたMySQLサーバーに接続していることを信頼できます。
+ ssl-cert`および
+ ssl-key`オプションは、同じ認証局によって署名された証明書があることをMySQLサーバーに証明するために必要なファイルを指します。 クライアントがCAによっても信頼されていることをMySQLサーバーに確認させる場合、これが必要です。
完了したら、ファイルを保存して閉じます。
これで、コマンドラインに +-ssl-ca
、` -ssl-cert`、および `-ssl-key`オプションを追加せずにMySQLサーバーに接続できます:
mysql -u -p -h
接続をネゴシエートするときに、クライアントとサーバーはそれぞれ証明書を提示するはずです。 各パーティは、ローカルにあるCA証明書に対してリモート証明書を検証するように構成されています。
結論
これで、MySQLサーバーは、リモートクライアントに対してセキュリティで保護された接続を要求するように構成されます。 さらに、認証局を使用して接続を検証する手順に従った場合、リモートパーティーが正当であるという両側の信頼レベルが確立されます。