如何在 Ubuntu 16.04 上为 MySQL 配置 SSL/TLS

介绍

MySQL 是世界上最受欢迎的开源关系数据库管理系统. 现代的包管理器已经减少了一些摩擦,以获得 MySQL 并运行,但仍有一些配置应该在安装后完成。

默认情况下,MySQL 已配置为仅接受本地连接. 如果您需要允许远程连接,重要的是要安全地这样做. 在本指南中,我们将展示如何在 Ubuntu 16.04 上配置 MySQL 以接受使用 SSL/TLS 加密的远程连接。

前提条件

要遵循本指南,您将需要两个**Ubuntu 16.04 服务器。我们将使用一个作为 MySQL 服务器和客户端。在每个服务器上创建一个具有)以使您的服务器进入适当的初始状态。

在第一台机器上,您应该安装和配置 MySQL 服务器 。 遵循我们的 Ubuntu 16.04 的 MySQL 安装指南来安装和配置软件。

在第二台机器上,安装 MySQL 客户端 包. 您可以通过键入更新 apt 包索引并安装所需的软件:

1[environment third]
2sudo apt-get update
3sudo apt-get install mysql-client

当您的服务器和客户端准备好了时,继续下方。

查看当前 SSL/TLS 状态

在我们开始之前,我们可以在我们的MySQL服务器**实例上检查SSL/TLS的当前状态。

使用 root MySQL 用户登录 MySQL 会话. 我们将使用-h 来指定 IPv4 局部路由接口,以便强迫客户端与 TCP 连接,而不是使用局部接口文件。

1[environment second]
2mysql -u root -p -h 127.0.0.1

您将被要求在安装过程中选择的MySQL密码,随后,您将被放入交互式MySQL会话。

通过键入显示 SSL/TLS 变量状态:

1SHOW VARIABLES LIKE '%ssl%';
2[environment second]
 1[secondary_label Output]
 2[environment second]
 3+---------------+----------+
 4| Variable_name | Value    |
 5+---------------+----------+
 6| have_openssl  | DISABLED |
 7| have_ssl      | DISABLED |
 8| ssl_ca        |          |
 9| ssl_capath    |          |
10| ssl_cert      |          |
11| ssl_cipher    |          |
12| ssl_crl       |          |
13| ssl_crlpath   |          |
14| ssl_key       |          |
15+---------------+----------+
169 rows in set (0.01 sec)

have_opensslhave_ssl变量都标记为DISABLED,这意味着SSL功能已被编译到服务器中,但尚未启用。

检查我们当前连接的状态以确认:

1[environment second]
2\s
 1[secondary_label Output]
 2[environment second]
 3--------------
 4mysql Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using EditLine wrapper
 5
 6Connection id:		30
 7Current database:	
 8Current user:		root@localhost
 9SSL:			Not in use
10Current pager:		stdout
11Using outfile:		''
12Using delimiter:	;
13Server version:		5.7.17-0ubuntu0.16.04.1 (Ubuntu)
14Protocol version:	10
15Connection:		127.0.0.1 via TCP/IP
16Server characterset:	latin1
17Db characterset:	latin1
18Client characterset:	utf8
19Conn. characterset:	utf8
20TCP port:		3306
21Uptime:			3 hours 38 min 44 sec
22
23Threads: 1 Questions: 70 Slow queries: 0 Opens: 121 Flush tables: 1 Open tables: 40 Queries per second avg: 0.005
24--------------

正如上面的输出所示,SSL目前没有用于我们的连接,即使我们通过TCP连接。

完成时关闭当前的 MySQL 会话:

1[environment second]
2exit

现在我们可以开始配置MySQL为SSL来保护我们的连接。

生成 SSL/TLS 证书和密钥

要启用SSL连接到MySQL,我们首先需要生成相应的证书和密钥文件。一个名为mysql_ssl_rsa_setup的实用程序与MySQL 5.7 和以上提供,以简化这个过程。

文件将创建在MySQL的数据目录中,位于 /var/lib/mysql. 我们需要MySQL过程才能读取生成的文件,所以我们将通过 mysql作为应该拥有生成的文件的用户:

1[environment second]
2sudo mysql_ssl_rsa_setup --uid=mysql

这一代将产生一个看起来像这样的输出:

 1[secondary_label Output]
 2[environment second]
 3Generating a 2048 bit RSA private key
 4...................................+++
 5.....+++
 6writing new private key to 'ca-key.pem'
 7-----
 8Generating a 2048 bit RSA private key
 9......+++
10.................................+++
11writing new private key to 'server-key.pem'
12-----
13Generating a 2048 bit RSA private key
14......................................................+++
15.................................................................................+++
16writing new private key to 'client-key.pem'
17-----

检查通过键入生成的文件:

1[environment second]
2sudo find /var/lib/mysql -name '*.pem' -ls
 1[secondary_label Output]
 2[environment second]
 3   256740 4 -rw-r--r--   1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysql/server-cert.pem
 4   256735 4 -rw-------   1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/ca-key.pem
 5   256739 4 -rw-r--r--   1 mysql mysql 451 Mar 17 17:24 /var/lib/mysqlsql/public_key.pem
 6   256741 4 -rw-------   1 mysql mysql 1679 Mar 17 17:24 /var/lib/mysqlsql/client-key.pem
 7   256737 4 -rw-r--r--   1 mysql mysql 1074 Mar 17 17:24 /var/lib/mysqlsql/ca.pem
 8   256743 4 -rw-r--r--   1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysqlsql/client-cert.pem
 9   256736 4 -rw-------   1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/private_key.pem
10   256738 4 -rw-------   1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/server-key.pem

最后一列显示了生成的文件名称. 显示mysql的中央列表明生成的文件具有正确的用户和组所有权。

这些文件是证书权限的密钥和证书对(从),MySQL服务器流程(从),以及MySQL客户端(从)。

在MySQL服务器上启用SSL连接

当服务器启动时,现代的MySQL版本将在MySQL数据目录中寻找相应的证书文件,因此我们不需要修改MySQL配置以启用SSL。

我们可以简单地重新启动MySQL服务:

1[environment second]
2sudo systemctl restart mysql

重新启动后,使用与以前相同的命令打开新的MySQL会话MySQL客户端将自动尝试使用SSL连接,如果服务器支持:

1[environment second]
2mysql -u root -p -h 127.0.0.1

让我们看看我们上次请求的相同信息. 检查 SSL 相关变量的值:

1[environment second]
2SHOW VARIABLES LIKE '%ssl%';
 1[secondary_label Output]
 2[environment second]
 3+---------------+-----------------+
 4| Variable_name | Value           |
 5+---------------+-----------------+
 6| have_openssl  | YES             |
 7| have_ssl      | YES             |
 8| ssl_ca        | ca.pem          |
 9| ssl_capath    |                 |
10| ssl_cert      | server-cert.pem |
11| ssl_cipher    |                 |
12| ssl_crl       |                 |
13| ssl_crlpath   |                 |
14| ssl_key       | server-key.pem  |
15+---------------+-----------------+
169 rows in set (0.00 sec)

have_opensslhave_ssl变量读取YES而不是DISABLED

接下来,再检查连接细节:

1[environment second]
2\s
1[secondary_label Output]
2[environment second]
3--------------
4. . .
5SSL:			Cipher in use is DHE-RSA-AES256-SHA
6. . .
7Connection:		127.0.0.1 via TCP/IP
8. . .
9--------------

这次,显示了特定SSL加密器,表示SSL正在被用来保护我们的连接。

退出回到壳:

1[environment second]
2exit

我们的服务器现在能够使用加密,但需要一些额外的配置来允许远程访问和授权使用安全连接。

配置远程客户端的安全连接

现在我们已经在服务器上拥有SSL,我们可以开始配置安全的远程访问。

  • 需要远程连接的 SSL * 连接到公共接口 * 创建远程连接的 MySQL 用户 * 调整我们的防火墙规则以允许外部连接

配置远程访问与强制性SSL

目前,MySQL服务器已配置为接受客户端的SSL连接,但如果客户端要求,它仍然允许未加密的连接。

我们可以通过打开require_secure_transport选项来解决这个问题,这需要使用SSL或本地Unix接口进行所有连接,因为Unix接口只能从服务器内部访问,所以唯一向远程用户开放的连接选项是SSL。

要启用此设置,请在文本编辑器中打开 /etc/mysql/my.cnf 文件:

1[environment second]
2sudo nano /etc/mysql/my.cnf

内部,将有两个 !includedir 指令用于来源额外的配置文件. 我们将需要将自己的配置 beneath 这些行,以便它们超出任何矛盾的设置。

首先,创建一个[mysqld]部分以瞄准MySQL服务器进程,在该部分标题下,将require_secure_transport设置为ON:

 1[label /etc/mysql/my.cnf]
 2[environment second]
 3. . .
 4
 5!includedir /etc/mysql/conf.d/
 6!includedir /etc/mysql/mysql.conf.d/
 7
 8[mysqld]
 9# Require clients to connect either using SSL
10# or through a local socket file
11require_secure_transport = ON

该行是执行安全连接所需的唯一设置。

默认情况下,MySQL 已配置为仅听取来自本地计算机的连接. 要将其配置为听取远程连接,我们可以将bind-address设置为不同的接口。

为了允许MySQL在其任何接口上接受连接,我们可以将bind-address设置为0.0.0.0:

 1[label /etc/mysql/my.cnf]
 2[environment second]
 3. . .
 4
 5!includedir /etc/mysql/conf.d/
 6!includedir /etc/mysql/mysql.conf.d/
 7
 8[mysqld]
 9# Require clients to connect either using SSL
10# or through a local socket file
11require_secure_transport = ON
12bind-address = 0.0.0.0

保存并关闭文件,当你完成。

接下来,重新启动MySQL以应用新的设置:

1[environment second]
2sudo systemctl restart mysql

检查MySQL是否正在听0.0.0.0而不是127.0.0.1,键入:

1[environment second]
2sudo netstat -plunt
1[secondary_label Output]
2[environment second]
3Active Internet connections (only servers)
4Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
5tcp 0 0 0.0.0.0:3306 0.0.0.0:*               LISTEN 4330/mysqld     
6tcp 0 0 0.0.0.0:22 0.0.0.0:*               LISTEN 1874/sshd       
7tcp6 0 0 :::22                   :::*                    LISTEN 1874/sshd

上面的输出中的0.0.0.0表示MySQL正在听取所有可用的接口上的连接。

接下来,我们需要通过我们的防火墙允许MySQL连接。

1[environment second]
2sudo ufw allow mysql
1[secondary_label Output]
2[environment second]
3Rule added
4Rule added (v6)

远程连接尝试现在应该能够到达我们的MySQL服务器。

配置远程 MySQL 用户

MySQL 服务器现在正在听取远程连接,但我们目前没有任何用户配置,可以从外部计算机连接。

登录 MySQL 作为用户开始:

1[environment second]
2mysql -u root -p

内部,您可以使用CREATE USER命令创建一个新的远程用户,我们将在用户规格的主机部分中使用客户端机器的IP地址来限制与该机器的连接。

若将来关闭了require_secure_transport选项,我们还将在帐户创建过程中通过包括REQUIRE SSL条款来指定该用户需要的SSL:

1[environment second]
2CREATE USER 'remote_user'@'mysql_client_IP' IDENTIFIED BY 'password' REQUIRE SSL;

接下来,向新用户授予他们应该访问的数据库或表的权限,以示范,我们将创建一个示例数据库,并授予我们的新用户所有权:

1[environment second]
2CREATE DATABASE example;
3GRANT ALL ON example.* TO 'remote_user'@'mysql_client_IP';

接下来,清除权限,立即应用这些设置:

1[environment second]
2FLUSH PRIVILEGES;

离开后回到壳,当你完成:

1[environment second]
2exit

我们的服务器设置为允许与我们的远程用户连接。

测试远程连接

在 MySQL 客户端机器上,测试以确保您可以成功连接到服务器. 使用 -u 选项来指定远程用户和 -h 选项来指定 MySQL 服务器的 IP 地址:

1[environment third]
2mysql -u remote_user -p -h mysql_server_IP

指定密码后,您将登录到远程服务器。

检查以确保您的连接安全:

1[environment third]
2\s
1[secondary_label Output]
2[environment third]
3--------------
4. . .
5SSL:			Cipher in use is DHE-RSA-AES256-SHA
6. . .
7Connection:		mysql_server_IP via TCP/IP
8. . .
9--------------

退出回到壳:

1[environment third]
2exit

接下来,尝试不安全地连接:

1[environment third]
2mysql -u remote_user -p -h mysql_server_IP --ssl-mode=disabled

在被要求提供您的密码后,您的连接应该被拒绝:

1[secondary_label Output]
2[environment third]
3ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_server_IP' (using password: YES)

它表明SSL连接是允许的,而未加密连接是拒绝的。

在此时,我们的MySQL服务器已被配置为安全地接受远程连接,如果你满足您的安全要求,您可以停留在这里,但我们可以设置一些额外的部件来进一步增加我们的安全性和信任。

配置 MySQL 连接验证(可选)

目前,我们的MySQL服务器配置了由本地生成的证书授权机构(CA)签署的SSL证书,服务器的证书和密钥对足以为接入连接提供加密。

然而,我们目前没有利用证书授权机构可以提供的信任关系。通过向客户分发CA证书以及客户证书和密钥,双方可以提供证据证明他们的证书是由相互信任的证书授权机构签署的。

为了实施这个额外的、可选的保护措施,我们将需要:

  • 将适当的 SSL 文件传输到客户端机器 * 创建客户端配置文件 * 更改我们的远程用户以要求一个可信证书

将客户端证书转移到客户端机器

首先,我们需要从MySQL服务器中获取MySQL CA和客户端证书文件,并将其放置在MySQL客户端上。

首先,在您要使用的用户的首页目录中创建一个目录在MySQL客户端上,称之为client-ssl:

1[environment third]
2mkdir ~/client-ssl

由于证书密钥敏感,我们应该锁定该目录的访问,以便只有当前用户才能访问它:

1[environment third]
2chmod 700 ~/client-ssl

现在,我们可以将证书信息复制到新目录中。

MySQL 服务器 机器上,通过键入显示 CA 证书的内容:

1[environment second]
2sudo cat /var/lib/mysql/ca.pem
1[secondary_label Output]
2[environment second]
3-----BEGIN CERTIFICATE-----
4
5. . .
6
7-----END CERTIFICATE-----

将整个输出,包括开始证书结束证书的行复制到剪辑板上。

MySQL 客户端 上,在新目录中创建一个具有相同名称的文件:

1[environment third]
2nano ~/client-ssl/ca.pem

在内部,粘贴复制的证书内容从你的剪辑板. 保存和关闭文件,当你完成。

接下来,在MySQL服务器上显示客户端证书:

1[environment second]
2sudo cat /var/lib/mysql/client-cert.pem
1[secondary_label Output]
2[environment second]
3-----BEGIN CERTIFICATE-----
4
5. . .
6
7-----END CERTIFICATE-----

再次,将内容复制到您的剪辑板. 请记住包括第一行和最后一行。

在客户端-ssl 目录中打开同名文件 MySQL 客户端 :

1[environment third]
2nano ~/client-ssl/client-cert.pem

将内容粘贴到您的剪辑板上. 保存并关闭文件。

最后,在MySQL服务器上显示客户端密钥文件的内容:

1[environment second]
2sudo cat /var/lib/mysql/client-key.pem
1[secondary_label Output]
2[environment second]
3-----BEGIN RSA PRIVATE KEY-----
4
5. . .
6
7-----END RSA PRIVATE KEY-----

将显示的内容,包括第一行和最后一行,复制到剪辑板。

MySQL 客户端 上,在client-ssl目录中打开具有相同名称的文件:

1[environment third]
2nano ~/client-ssl/client-key.pem

将内容粘贴到您的剪辑板上. 保存并关闭文件。

客户端机器现在应该拥有访问MySQL服务器所需的所有凭证,接下来,我们需要更改我们的远程用户。

要求远程用户获得信任 CA 的证书

目前,MySQL客户端有可用文件,可在连接时将其证书呈现给服务器,但是,服务器尚未设置以要求客户端证书从可信的CA。

若要更改此情况,请再次登录 MySQL 根帐户在 MySQL 服务器 :

1[environment second]
2mysql -u root -p

接下来,我们需要更改我们的远程用户的要求,而不是要求SSL条款,我们需要应用要求X509条款,这意味着以前的要求提供的所有安全性,但还要求连接客户端提供由MySQL服务器信任的证书授权机构签署的证书。

若要调整用户要求,请使用ALTER USER命令:

1[environment second]
2ALTER USER 'remote_user'@'mysql_client_IP' REQUIRE X509;

扫描这些更改,以确保它们立即应用:

1[environment second]
2FLUSH PRIVILEGES;

离开后回到壳,当你完成:

1[environment second]
2exit

接下来,我们可以测试以确保我们仍然可以连接。

连接时测试证书验证

现在是检查当我们连接时,我们是否能够验证双方的好时机。

在 MySQL 客户端上,先尝试连接而不提供客户端证书:

1[environment third]
2mysql -u remote_user -p -h mysql_server_IP
1[secondary_label Output]
2[environment third]
3ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)

如果不提供客户端证书,服务器会拒绝连接。

现在,使用--ssl-ca,--ssl-cert--ssl-key选项连接,以指向~/client-ssl目录中的相关文件:

1[environment third]
2mysql -u remote_user -p -h mysql_server_IP --ssl-ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem

您应该成功登录. 退出登录以恢复访问您的壳会话:

1[environment third]
2exit

现在我们已经确认了访问服务器,我们可以实施一个小小的可用性改进。

创建一个MySQL客户端配置文件

为了避免每次连接时需要指定证书文件,我们可以创建一个简单的MySQL客户端配置文件。

在您的主目录中,在MySQL客户端机器上,创建一个名为~/.my.cnf的隐藏文件:

1[environment third]
2nano ~/.my.cnf

在文件的顶部,创建一个名为[客户端]的部分。下面,我们可以设置ssl-ca,ssl-certssl-key选项,以指向我们从服务器上复制的文件。

1[label ~/.my.cnf]
2[environment third]
3[client]
4ssl-ca = ~/client-ssl/ca.pem
5ssl-cert = ~/client-ssl/client-cert.pem
6ssl-key = ~/client-ssl/client-key.pem

ssl-ca选项告诉客户端验证由MySQL服务器提供的证书是由我们指示的证书授权机构签署的,这允许客户端相信它正在连接到可信的MySQL服务器。

ssl-certssl-key选项指向所需的文件,以证明MySQL服务器也具有由同一证书授权机构签署的证书。

保存并关闭文件,当你完成。

现在,您可以连接到MySQL服务器,而无需在命令行中添加--ssl-ca,--ssl-cert--ssl-key选项:

1[environment third]
2mysql -u remote_user -p -h mysql_server_ip

您的客户端和服务器现在都应该在谈判连接时呈现证书,每方都配置为对其本地拥有的远程证书进行验证。

结论

您的 MySQL 服务器现在应该配置为需要远程客户端的安全连接,此外,如果您遵循使用证书权限验证连接的步骤,则双方都建立了一定的信任级别,即远程客户端是合法的。

Published At
Categories with 技术
comments powered by Disqus