阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

198次阅读
没有评论

共计 9144 个字符,预计需要花费 23 分钟才能阅读完成。

介绍

MySQL 是世界上最流行的开源关系数据库管理系统。虽然现代包管理器已经减少了启动和运行 MySQL 的一些摩擦,但是在安装它之后还应该执行一些进一步的配置。花费一些额外时间的最重要方面之一是安全性。

默认情况下,MySQL 配置为仅接受本地连接,或者来自安装 MySQL 的同一台机器的连接。如果您需要从远程位置访问 MySQL 数据库,那么安全地执行此操作非常重要。在本指南中,我们将演示如何在 Ubuntu 18.04 上配置 MySQL 以接受使用 SSL/TLS 加密的远程连接。

准备

要遵循本教程,您将需要 两台 Ubuntu 16.04 服务器。我们将使用一个作为 MySQL 服务器,另一个作为客户端。没有服务器的同学可以在这里购买,不过我个人更推荐您使用 免费 的腾讯云开发者实验室进行试验,学会安装后在购买服务器。

在第一台机器上,您应该安装并配置MySQL 服务器。按照我们的四步教你搭建保护 MySQL 服务器!教程来安装和配置软件。

在第二台计算机上,安装 MySQL 客户端软件包。您可以通过输入以下内容来更新 apt 软件包索引并安装必要的软件:

sudo apt-get update
sudo apt-get install mysql-client

当您的服务器和客户端准备就绪后,请继续。

检查当前的 SSL / TLS 状态

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

使用 root 用户登录 MySQL 会话。我们将使用-h 指定 IPv4 本地环回接口,以强制客户端与 TCP 连接。这将允许我们检查 TCP 连接的 SSL 状态:

mysql -u root -p -h 127.0.0.1

系统将提示您输入在安装过程中输入 MySQL root密码。之后,您将进入交互式 MySQL 会话。

输入以下内容显示 SSL / TLS 变量的状态:

SHOW VARIABLES LIKE '%ssl%';
+---------------+----------+
| 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_opensslhave_ssl 变量都标记为DISABLED。这意味着 SSL 功能已编译到服务器中,但尚未启用。

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

\s
--------------
mysql  Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using  EditLine wrapper
​
Connection id:      30
Current database:   
Current user:       root@localhost
SSL:         Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.7.17-0ubuntu0.16.04.1 (Ubuntu)
Protocol version:   10
Connection:      127.0.0.1 via TCP/IP
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
--------------

如上面的输出所示,SSL 尚未加密我们的链接

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

exit

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

生成 SSL / TLS 证书和密钥

要启用与 MySQL 的 SSL 连接,我们首先需要生成相应的证书和密钥文件。MySQL 5.7 及更高版本提供了一个被调用的程序 mysql_ssl_rsa_setup 来简化此过程。Ubuntu 16.04 具有兼容的 MySQL 版本,因此我们可以使用此命令生成必要的文件。

这些文件将在 MySQL 的数据目录中创建,位于 /var/lib/mysql。我们需要 MySQL 进程能够读取生成的文件所以我们将mysql 作为应该拥有生成文件的用户传递:

sudo mysql_ssl_rsa_setup --uid=mysql

将产生如下所示的输出:

Generating 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
256740      4 -rw-r--r--   1 mysql    mysql        1078 Mar 17 17:24 /var/lib/mysql/server-cert.pem
   256735      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/ca-key.pem<^>
   256739      4 -rw-r--r--   1 mysql    mysql         451 Mar 17 17:24 /var/lib/mysqlsql/public_key.pem<^>
   256741      4 -rw-------   1 mysql    mysql        1679 Mar 17 17:24 /var/lib/mysqlsql/client-key.pem<^>
   256737      4 -rw-r--r--   1 mysql    mysql        1074 Mar 17 17:24 /var/lib/mysqlsql/ca.pem<^>
   256743      4 -rw-r--r--   1 mysql    mysql        1078 Mar 17 17:24 /var/lib/mysqlsql/client-cert.pem<^>
   256736      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/private_key.pem<^>
   256738      4 -rw-------   1 mysql    mysql        1675 Mar 17 17:24 /var/lib/mysqlsql/server-key.pem<^>

最后一列显示生成的文件名。并表示生成的文件具有正确的用户和组所有权。

这些文件是证书颁发机构(以“ca”开头),MySQL 服务器进程(以“server”开头)和 MySQL 客户端(以“client”开头)的密钥和证书对。

在 MySQL 服务器上启用 SSL 连接

MySQL 版本将在服务器启动时在 MySQL 数据目录中查找相应的证书文件。因此,我们实际上不需要修改 MySQL 配置来启用 SSL。

我们可以改为重启 MySQL 服务:

sudo systemctl restart mysql

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

mysql -u root -p -h 127.0.0.1

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

SHOW VARIABLES LIKE '%ssl%';
+---------------+-----------------+
| 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_opensslhave_ssl变量读取“YES”而不是“DISABLED”。此外,ssl_cassl_cert,和 ssl_key 变量已填入我们产生的相关证书的名称。

接下来,再次检查连接详细信息:

\s
--------------
. . .
SSL:            Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      127.0.0.1 via TCP/IP
. . .
--------------

这次,将显示特定的 SSL 加密方式,表示正在使用 SSL 来保护我们的连接。

退出到 shell:

exit

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

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

现在我们已在服务器上使用 SSL,我们可以开始配置安全远程访问。为此,我们需要:

  • 要求 SSL 用于远程连接
  • 绑定到公共接口
  • 为远程连接创建 MySQL 用户
  • 调整防火墙规则以允许外部连接

使用强制 SSL 配置远程访问

目前,MySQL 服务器配置为接受来自客户端的 SSL 连接。但是,如果客户端请求,它仍将允许未加密的连接。

我们可以通过打开 require_secure_transport 选项来解决这个问题。这要求所有连接都使用 SSL。因此对远程用户开放的唯一连接选项将使用 SSL。

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

sudo nano /etc/mysql/my.cnf

在里面,将有两个 !includedir 指令用于获取其他配置文件。我们需要 这些行 下面 放置我们自己的配置 以便它们覆盖任何冲突的设置。

首先创建一个 [mysqld] 部分来定位 MySQL 服务器进程。将 require_secure_transport 设置为ON

. . .
​
!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 配置为仅侦听源自本地计算机的连接。要将其配置为侦听远程连接,我们可以将其 bind-address 设置为不同的接口。

要允许 MySQL 接受任何接口上的连接,我们可以将 bind-address 设置为“0.0.0.0”:

. . .
​
!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
bind-address = 0.0.0.0

完成后保存并关闭文件。

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

sudo systemctl restart mysql

通过输入以下内容验证 MySQL 是否正在侦听“0.0.0.0”而不是“127.0.0.1”:

sudo netstat -plunt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      4330/mysqld     
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
Rule added
Rule added (v6)

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

配置远程 MySQL 用户

MySQL 服务器现在正在侦听远程连接,但我们目前没有配置任何可以从外部计算机连接的用户。以 root 用户身份登录 MySQL 开始:

mysql -u root -p

在内部,您可以使用 CREATE USER 命令创建新的远程用户。我们将在用户规范的主机部分中使用客户端计算机的 IP 地址来限制与该计算机的连接。对于将来关闭 require_secure_transport 选项的某些冗余,我们还将在帐户创建期间指定此用户通过包含 REQUIRE SSL 子句来要求 SSL:

CREATE USER 'remote_user'@'mysql_client_IP' IDENTIFIED BY 'password' REQUIRE SSL;

接下来,为他们应该有权访问的数据库或表授予新用户权限。为了演示,我们将创建一个 example 数据库并赋予新的用户所有权:

CREATE DATABASE example;
GRANT ALL ON example.* TO 'remote_user'@'mysql_client_IP';

接下来,刷新权限立即应用这些设置:

FLUSH PRIVILEGES;

完成后退出到 shell:

exit

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

测试远程连接

MySQL 客户端 计算机上,进行测试以确保您可以成功连接到服务器。使用 - u 选项指定远程用户以及 - h 选项指定 MySQL 服务器 IP 地址:

mysql -u remote_user -p -h mysql_server_IP

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

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

\s
--------------
. . .
SSL:         Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      mysql_server_IP via TCP/IP
. . .
--------------

退出到 shell:

exit

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

mysql -u remote_user -p -h mysql_server_IP --ssl-mode=disabled

提示您输入密码后,应拒绝您的连接:

ERROR 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:

mkdir ~/client-ssl

我们应该锁定对此目录的访问权限,以便只有当前用户才能访问它:

chmod 700 ~/client-ssl

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

MySQL 服务器 计算机上,输入以下内容显示 CA 证书的内容:

sudo cat /var/lib/mysql/ca.pem
-----BEGIN CERTIFICATE-----
​
. . .
​
-----END CERTIFICATE-----

将整个输出(包括 BEGIN CERTIFICATEEND CERTIFICATE 行)复制到剪贴板。

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

nano ~/client-ssl/ca.pem

在里面,粘贴剪贴板中复制的证书内容。完成后保存并关闭文件。

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

sudo cat /var/lib/mysql/client-cert.pem
-----BEGIN CERTIFICATE-----
​
. . .
​
-----END CERTIFICATE-----

再次,将内容复制到剪贴板。

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

nano ~/client-ssl/client-cert.pem

粘贴剪贴板中的内容。保存并关闭文件。

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

sudo cat /var/lib/mysql/client-key.pem
-----BEGIN RSA PRIVATE KEY-----
​
. . .
​
-----END RSA PRIVATE KEY-----

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

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

nano ~/client-ssl/client-key.pem

粘贴剪贴板中的内容。保存并关闭文件。客户端计算机现在应具有访问 MySQL 服务器所需的所有凭据。接下来,我们需要改变我们的远程用户。

需要来自可信 CA 的远程用户证书

目前,MySQL 客户端具有可用于在连接时向服务器提供其证书的文件。但是,服务器仍未设置为要求来自受信任 CA 的客户端证书。

要更改此设置,请在 MySQL 服务器 上再次登录 MySQL root 帐户:

mysql -u root -p

接下来,我们需要更改远程用户的要求。我们需要应用 REQUIRE X509 而不是REQUIRE SSL。这意味着前一个要求提供的所有安全性,但另外要求连接客户端提供由 MySQL 服务器信任的证书颁发机构签名的证书。

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

ALTER USER 'remote_user'@'mysql_client_IP' REQUIRE X509;

刷新更改以应用它们:

FLUSH PRIVILEGES;

完成后退出到 shell:

exit

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

连接时测试证书验证

现在是检查我们是否可以在连接时验证双方的好时机。

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

mysql -u remote_user -p -h mysql_server_IP
ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)

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

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

mysql -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

您应该已成功登录。重新登录以重新获得对 shell 会话的访问权限:

exit

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

创建 MySQL 客户端配置文件

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

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

nano ~/.my.cnf

在文件的顶部,创建一个名为 [client] 的部分。下面,我们可以设置 ssl-cassl-certssl-key选项指向我们从服务器复制的文件。它如下所示:

[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-certssl-key 选项指向向 MySQL 服务器证明它也具有由相同证书颁发机构签名的证书所需的文件。如果我们希望 MySQL 服务器验证客户端也被 CA 信任,我们需要这个。

完成后保存并关闭文件。

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

mysql -u remote_user -p -h mysql_server_ip

您的客户端和服务器现在应该在协商连接时都提供证书。每一方都配置为根据其本地 CA 证书验证远程证书。

总结

您的 MySQL 服务器现在配置为需要来自远程客户端的安全连接。此外,如果您按照以下步骤使用证书颁发机构验证连接,则双方将建立某种程度的信任,即远程方是合法的。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计9144字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中