MariaDB over SSL 不工作,"certificate verify failed"
MariaDB over SSL not working, "certificate verify failed"
使用 this guide 我正在尝试设置 MariaDB (mysql) 在 dbserver 和 appclient[= 之间使用 SSL 60=]。
我按照指南在服务器上创建了服务器和客户端证书。然后我将三个必要的客户端文件复制到 appclient 并设置所有权和权限:
[root@appclient mysql]# ll /etc/pki/tls/certs/
drwxr-xr-x. 2 mysql mysql 88 Feb 9 13:31 mysql
[root@appclient mysql]# ll /etc/pki/tls/certs/mysql/
-rw-------. 1 mysql mysql 1372 Feb 9 13:31 ca-cert.pem
-rw-------. 1 mysql mysql 1230 Feb 9 14:16 client-cert.pem
-rw-------. 1 mysql mysql 1705 Feb 9 14:16 client-key.pem
这是 appclient 上的完整 my.cnf:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
[client]
ssl-ca=/etc/pki/tls/certs/mysql/ca-cert.pem
ssl-cert=/etc/pki/tls/certs/mysql/client-cert.pem
ssl-key=/etc/pki/tls/certs/mysql/client-key.pem
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
!includedir /etc/my.cnf.d
接下来我在dbserver上测试了3306端口是开放的:
[root@appclient mysql]# telnet dbserver 3306
Connected to dbserver.
Escape character is '^]'.
R
5.5.52-MariaDB
接下来我检查了 dbserver 上的 MariaDB (mysql) ssl 变量:
MariaDB [(none)]> show variables like '%ssl%';
+---------------+------------------------------------------+
| Variable_name | Value |
+---------------+------------------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/pki/tls/certs/mysql/ca-cert.pem |
| ssl_capath | |
| ssl_cert | /etc/pki/tls/certs/mysql/server-cert.pem |
| ssl_cipher | |
| ssl_key | /etc/pki/tls/certs/mysql/server-key.pem |
+---------------+------------------------------------------+
接下来我检查了 appclient 上的 MariaDB (mysql) ssl 变量:
MariaDB [(none)]> show variables LIKE '%ssl%';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_key | |
+---------------+----------+
7 rows in set (0.00 sec)
这看起来像问题的 start/source。
如果我尝试从 appclient 连接到 dbserver:
[root@appclient mysql]# mysql -h dbserver -u ssluser -p
Enter password:
ERROR 2026 (HY000): SSL connection error: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
没有布埃诺。
正在使用 openssl 检查 appclient 的证书...
[root@appclient mysql]# cd /etc/pki/tls/certs/mysql/
[root@appclient mysql]# openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
Error opening certificate file server-cert.pem
139864320337824:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen('server-cert.pem','r')
139864320337824:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
unable to load certificate
client-cert.pem: OK
为了好玩,我 运行 在 dbserver:
上进行了相同的 openssl 测试
[root@dbserver mysql]# openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
server-cert.pem: C = XX, ST = XX, L = CityName, O = MyOrganization, OU = MyGroup, CN = dbserver
error 18 at 0 depth lookup:self signed certificate
OK
client-cert.pem: OK
教程只提到将ca-cert.pem
、client-cert.pem
和client-key.pem
复制到客户端,但上述失败表明客户端缺少server-cert.pem
。
我是否还需要在客户端上创建 server-*.pem 文件?如果是这样,这些在 /etc/my.cnf
文件中的什么位置?
几个 MySQL/MariaDB SSL 设置指南中缺失的部分是确保 ssl-ca
证书文件同时包含服务器和客户端 ca。
这是对我有用的分步指南:
这个答案假设有两个服务器:
- dbserver(我们的数据库所在的位置)
- appclient(我们的应用程序所在的地方)
FWIW,两台服务器都强制执行 SELinux。
首先,登录数据库服务器
创建用于创建证书的临时目录。
mkdir /root/certs/mysql/ && cd /root/certs/mysql/
创建服务器证书
openssl genrsa 2048 > ca-key.pem
openssl req -sha1 -new -x509 -nodes -days 3650 -key ca-key.pem > ca-cert.pem
openssl req -sha1 -newkey rsa:2048 -days 730 -nodes -keyout server-key.pem > server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -sha1 -req -in server-req.pem -days 730 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
将服务器证书移至 /etc/pki/tls/certs/mysql/
目录路径假定为 CentOS 或 RHEL(根据其他发行版的需要进行调整):
mkdir /etc/pki/tls/certs/mysql/
cp /root/certs/mysql/* /etc/pki/tls/certs/mysql/
一定要设置文件夹和文件的权限。 mysql 需要完全的所有权和访问权限。
chown -R mysql:mysql /etc/pki/tls/certs/mysql
现在配置MySQL/MariaDB
# vi /etc/my.cnf
# i
[mysqld]
bind-address=*
ssl-ca=/etc/pki/tls/certs/ca-cert.pem
ssl-cert=/etc/pki/tls/certs/server-cert.pem
ssl-key=/etc/pki/tls/certs/server-key.pem
# :wq
然后
systemctl restart mariadb
不要忘记打开防火墙以允许来自 appclient 的连接(使用 IP 1.2.3.4)
firewall-cmd --zone=drop --permanent --add-rich-rule 'rule family="ipv4" source address="1.2.3.4" service name="mysql" accept'
# I force everything to the drop zone. Season the above command to taste.
现在重新启动 firewalld
service firewalld restart
接下来,登录到dbserver的mysql服务器:
mysql -uroot -p
发出以下命令为客户端创建一个用户。请注意 GRANT 语句中的 REQUIRE SSL。
GRANT ALL PRIVILEGES ON *.* TO ‘iamsecure’@’appclient’ IDENTIFIED BY ‘dingdingding’ REQUIRE SSL;
FLUSH PRIVILEGES;
# quit mysql
从第一步开始,您应该仍在 /root/certs/mysql。如果没有,请 cd 返回它以执行以下命令之一。
创建客户端证书
openssl req -sha1 -newkey rsa:2048 -days 730 -nodes -keyout client-key.pem > client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -sha1 -req -in client-req.pem -days 730 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem
注意:我为服务器和客户端证书使用了相同的通用名称。 YMMV。
请确保您仍处于 /root/certs/mysql/ 下一个命令
将服务器和客户端 CA 证书合并到一个文件中:
cat server-cert.pem client-cert.pem > ca.pem
确保您看到两个证书:
cat ca.pem
现在服务器端工作结束。
打开另一个终端并
ssh appclient
和以前一样,为客户端证书创建一个永久的家
mkdir /etc/pki/tls/certs/mysql/
现在,将客户端证书(在 dbserver 上创建)放在 appclient 上。
您可以对它们进行 scp,或者只是将文件一个一个地复制和粘贴。
scp dbserver
# copy files from dbserver to appclient
# exit scp
同样,一定要设置文件夹和文件的权限。 mysql 需要完全的所有权和访问权限。
chown -R mysql:mysql /etc/pki/tls/certs/mysql
您应该拥有三个文件,每个文件都属于用户 mysql:
/etc/pki/tls/certs/mysql/ca.pem
/etc/pki/tls/certs/mysql/client-cert.pem
/etc/pki/tls/certs/mysql/client-key.pem
现在在 [client]
部分编辑 appclient 的 MariaDB/MySQL 配置。
vi /etc/my.cnf
# i
[client]
ssl-ca=/etc/pki/tls/certs/mysql/ca.pem
ssl-cert=/etc/pki/tls/certs/mysql/client-cert.pem
ssl-key=/etc/pki/tls/certs/mysql/client-key.pem
# :wq
重启appclient的mariadb服务:
systemctl restart mariadb
这里还是客户端
这应该 return: ssl TRUE
mysql --ssl --help
现在,登录appclient的mysql实例
mysql -uroot -p
下面的两个变量应该都是 YES
show variables LIKE '%ssl';
have_openssl YES
have_ssl YES
最初我看到
have_openssl NO
快速查看 mariadb.log 发现:
SSL error: Unable to get certificate from
'/etc/pki/tls/certs/mysql/client-cert.pem'
问题是 root 拥有 client-cert.pem 和包含的文件夹。
解决方案是将 /etc/pki/tls/certs/mysql/ 的所有权设置为 mysql.
chown -R mysql:mysql /etc/pki/tls/certs/mysql
如果需要,请从上面的步骤重新启动 mariadb
现在我们已准备好测试安全连接
我们还在appclient上
尝试使用上面创建的帐户连接到 dbserver 的 mysql 实例。
mysql -h dbserver -u iamsecure -p
# enter password dingdingding (hopefully you changed that to something else)
运气好的话,您应该可以正确登录。
要确认您已启用 SSL 连接,请在 MariaDB/MySQL 提示符下发出以下命令:
\s
这是一个反斜杠 s,又名状态
这将显示您的连接状态,应该如下所示:
Connection id: 4
Current database:
Current user: iamsecure@appclient
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 5.X.X-MariaDB MariaDB Server
Protocol version: 10
Connection: dbserver via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 42 min 13 sec
如果您在尝试连接时遇到权限被拒绝的错误,请检查上面的 GRANT 语句以确保没有任何杂散字符或 ' 标记。
如果您遇到 SSL 错误,请返回阅读本指南以确保这些步骤是有序的。
这适用于 RHEL7,也可能适用于 CentOS7。无法确认这些具体步骤是否适用于其他地方。
希望这能为其他人节省一点时间和麻烦。
根据 mentioned guide,您必须确保所有三个证书的 "Common name" 都不同。
我遇到了同样的错误,因为我对所有三个证书使用了相同的 CN。使用不同的 CN 重新生成证书后,错误消失了。
使用 this guide 我正在尝试设置 MariaDB (mysql) 在 dbserver 和 appclient[= 之间使用 SSL 60=]。
我按照指南在服务器上创建了服务器和客户端证书。然后我将三个必要的客户端文件复制到 appclient 并设置所有权和权限:
[root@appclient mysql]# ll /etc/pki/tls/certs/
drwxr-xr-x. 2 mysql mysql 88 Feb 9 13:31 mysql
[root@appclient mysql]# ll /etc/pki/tls/certs/mysql/
-rw-------. 1 mysql mysql 1372 Feb 9 13:31 ca-cert.pem
-rw-------. 1 mysql mysql 1230 Feb 9 14:16 client-cert.pem
-rw-------. 1 mysql mysql 1705 Feb 9 14:16 client-key.pem
这是 appclient 上的完整 my.cnf:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
[client]
ssl-ca=/etc/pki/tls/certs/mysql/ca-cert.pem
ssl-cert=/etc/pki/tls/certs/mysql/client-cert.pem
ssl-key=/etc/pki/tls/certs/mysql/client-key.pem
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
!includedir /etc/my.cnf.d
接下来我在dbserver上测试了3306端口是开放的:
[root@appclient mysql]# telnet dbserver 3306
Connected to dbserver.
Escape character is '^]'.
R
5.5.52-MariaDB
接下来我检查了 dbserver 上的 MariaDB (mysql) ssl 变量:
MariaDB [(none)]> show variables like '%ssl%';
+---------------+------------------------------------------+
| Variable_name | Value |
+---------------+------------------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/pki/tls/certs/mysql/ca-cert.pem |
| ssl_capath | |
| ssl_cert | /etc/pki/tls/certs/mysql/server-cert.pem |
| ssl_cipher | |
| ssl_key | /etc/pki/tls/certs/mysql/server-key.pem |
+---------------+------------------------------------------+
接下来我检查了 appclient 上的 MariaDB (mysql) ssl 变量:
MariaDB [(none)]> show variables LIKE '%ssl%';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_key | |
+---------------+----------+
7 rows in set (0.00 sec)
这看起来像问题的 start/source。
如果我尝试从 appclient 连接到 dbserver:
[root@appclient mysql]# mysql -h dbserver -u ssluser -p
Enter password:
ERROR 2026 (HY000): SSL connection error: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
没有布埃诺。
正在使用 openssl 检查 appclient 的证书...
[root@appclient mysql]# cd /etc/pki/tls/certs/mysql/
[root@appclient mysql]# openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
Error opening certificate file server-cert.pem
139864320337824:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen('server-cert.pem','r')
139864320337824:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
unable to load certificate
client-cert.pem: OK
为了好玩,我 运行 在 dbserver:
上进行了相同的 openssl 测试[root@dbserver mysql]# openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
server-cert.pem: C = XX, ST = XX, L = CityName, O = MyOrganization, OU = MyGroup, CN = dbserver
error 18 at 0 depth lookup:self signed certificate
OK
client-cert.pem: OK
教程只提到将ca-cert.pem
、client-cert.pem
和client-key.pem
复制到客户端,但上述失败表明客户端缺少server-cert.pem
。
我是否还需要在客户端上创建 server-*.pem 文件?如果是这样,这些在 /etc/my.cnf
文件中的什么位置?
几个 MySQL/MariaDB SSL 设置指南中缺失的部分是确保 ssl-ca
证书文件同时包含服务器和客户端 ca。
这是对我有用的分步指南:
这个答案假设有两个服务器:
- dbserver(我们的数据库所在的位置)
- appclient(我们的应用程序所在的地方)
FWIW,两台服务器都强制执行 SELinux。
首先,登录数据库服务器
创建用于创建证书的临时目录。
mkdir /root/certs/mysql/ && cd /root/certs/mysql/
创建服务器证书
openssl genrsa 2048 > ca-key.pem
openssl req -sha1 -new -x509 -nodes -days 3650 -key ca-key.pem > ca-cert.pem
openssl req -sha1 -newkey rsa:2048 -days 730 -nodes -keyout server-key.pem > server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -sha1 -req -in server-req.pem -days 730 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
将服务器证书移至 /etc/pki/tls/certs/mysql/
目录路径假定为 CentOS 或 RHEL(根据其他发行版的需要进行调整):
mkdir /etc/pki/tls/certs/mysql/
cp /root/certs/mysql/* /etc/pki/tls/certs/mysql/
一定要设置文件夹和文件的权限。 mysql 需要完全的所有权和访问权限。
chown -R mysql:mysql /etc/pki/tls/certs/mysql
现在配置MySQL/MariaDB
# vi /etc/my.cnf
# i
[mysqld]
bind-address=*
ssl-ca=/etc/pki/tls/certs/ca-cert.pem
ssl-cert=/etc/pki/tls/certs/server-cert.pem
ssl-key=/etc/pki/tls/certs/server-key.pem
# :wq
然后
systemctl restart mariadb
不要忘记打开防火墙以允许来自 appclient 的连接(使用 IP 1.2.3.4)
firewall-cmd --zone=drop --permanent --add-rich-rule 'rule family="ipv4" source address="1.2.3.4" service name="mysql" accept'
# I force everything to the drop zone. Season the above command to taste.
现在重新启动 firewalld
service firewalld restart
接下来,登录到dbserver的mysql服务器:
mysql -uroot -p
发出以下命令为客户端创建一个用户。请注意 GRANT 语句中的 REQUIRE SSL。
GRANT ALL PRIVILEGES ON *.* TO ‘iamsecure’@’appclient’ IDENTIFIED BY ‘dingdingding’ REQUIRE SSL;
FLUSH PRIVILEGES;
# quit mysql
从第一步开始,您应该仍在 /root/certs/mysql。如果没有,请 cd 返回它以执行以下命令之一。
创建客户端证书
openssl req -sha1 -newkey rsa:2048 -days 730 -nodes -keyout client-key.pem > client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -sha1 -req -in client-req.pem -days 730 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem
注意:我为服务器和客户端证书使用了相同的通用名称。 YMMV。
请确保您仍处于 /root/certs/mysql/ 下一个命令
将服务器和客户端 CA 证书合并到一个文件中:
cat server-cert.pem client-cert.pem > ca.pem
确保您看到两个证书:
cat ca.pem
现在服务器端工作结束。
打开另一个终端并
ssh appclient
和以前一样,为客户端证书创建一个永久的家
mkdir /etc/pki/tls/certs/mysql/
现在,将客户端证书(在 dbserver 上创建)放在 appclient 上。 您可以对它们进行 scp,或者只是将文件一个一个地复制和粘贴。
scp dbserver
# copy files from dbserver to appclient
# exit scp
同样,一定要设置文件夹和文件的权限。 mysql 需要完全的所有权和访问权限。
chown -R mysql:mysql /etc/pki/tls/certs/mysql
您应该拥有三个文件,每个文件都属于用户 mysql:
/etc/pki/tls/certs/mysql/ca.pem
/etc/pki/tls/certs/mysql/client-cert.pem
/etc/pki/tls/certs/mysql/client-key.pem
现在在 [client]
部分编辑 appclient 的 MariaDB/MySQL 配置。
vi /etc/my.cnf
# i
[client]
ssl-ca=/etc/pki/tls/certs/mysql/ca.pem
ssl-cert=/etc/pki/tls/certs/mysql/client-cert.pem
ssl-key=/etc/pki/tls/certs/mysql/client-key.pem
# :wq
重启appclient的mariadb服务:
systemctl restart mariadb
这里还是客户端
这应该 return: ssl TRUE
mysql --ssl --help
现在,登录appclient的mysql实例
mysql -uroot -p
下面的两个变量应该都是 YES
show variables LIKE '%ssl';
have_openssl YES
have_ssl YES
最初我看到
have_openssl NO
快速查看 mariadb.log 发现:
SSL error: Unable to get certificate from '/etc/pki/tls/certs/mysql/client-cert.pem'
问题是 root 拥有 client-cert.pem 和包含的文件夹。 解决方案是将 /etc/pki/tls/certs/mysql/ 的所有权设置为 mysql.
chown -R mysql:mysql /etc/pki/tls/certs/mysql
如果需要,请从上面的步骤重新启动 mariadb
现在我们已准备好测试安全连接
我们还在appclient上
尝试使用上面创建的帐户连接到 dbserver 的 mysql 实例。
mysql -h dbserver -u iamsecure -p
# enter password dingdingding (hopefully you changed that to something else)
运气好的话,您应该可以正确登录。
要确认您已启用 SSL 连接,请在 MariaDB/MySQL 提示符下发出以下命令:
\s
这是一个反斜杠 s,又名状态
这将显示您的连接状态,应该如下所示:
Connection id: 4
Current database:
Current user: iamsecure@appclient
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 5.X.X-MariaDB MariaDB Server
Protocol version: 10
Connection: dbserver via TCP/IP
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 42 min 13 sec
如果您在尝试连接时遇到权限被拒绝的错误,请检查上面的 GRANT 语句以确保没有任何杂散字符或 ' 标记。
如果您遇到 SSL 错误,请返回阅读本指南以确保这些步骤是有序的。
这适用于 RHEL7,也可能适用于 CentOS7。无法确认这些具体步骤是否适用于其他地方。
希望这能为其他人节省一点时间和麻烦。
根据 mentioned guide,您必须确保所有三个证书的 "Common name" 都不同。
我遇到了同样的错误,因为我对所有三个证书使用了相同的 CN。使用不同的 CN 重新生成证书后,错误消失了。