MariaDB over SSL无法正常工作,"证书验证失败"

a c*_*der 4 ssl mariadb rhel7

使用本指南我正在尝试设置MariaDB(mysql)以在dbserverappclient之间使用SSL .

我根据指南在服务器上创建了服务器和客户端证书.然后我将三个必要的客户端文件复制到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
Run Code Online (Sandbox Code Playgroud)

这是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
Run Code Online (Sandbox Code Playgroud)

接下来,我测试了端口3306在dbserver上打开:

[root@appclient mysql]# telnet dbserver 3306
Connected to dbserver.
Escape character is '^]'.
R
5.5.52-MariaDB
Run Code Online (Sandbox Code Playgroud)

接下来,我在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  |
+---------------+------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

接下来我在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)
Run Code Online (Sandbox Code Playgroud)

这看起来像问题的开始/来源.

如果我尝试从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
Run Code Online (Sandbox Code Playgroud)

没有bueno.

使用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
Run Code Online (Sandbox Code Playgroud)

对于踢,我在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
Run Code Online (Sandbox Code Playgroud)

本教程只提到复制ca-cert.pem,client-cert.pemclient-key.pem给客户端,但以上几点未能缺少server-cert.pem客户端上.

我是否还需要在客户端上创建服务器 - *.pem文件?如果是这样,这些/etc/my.cnf文件在哪里?

a c*_*der 8

几个MySQL/MariaDB SSL设置指南中缺少的成分是确保ssl-ca证书文件包含服务器和客户端ca.

这是一个为我工作的分步指南:


这个答案假设有两台服务器

  1. dbserver(我们的数据库所在的位置)
  2. appclient(我们的应用程序所在的位置)

FWIW,两台服务器都是SELinux强制执行的.

首先,登录到dbserver

创建用于创建证书的临时目录.

mkdir /root/certs/mysql/ && cd /root/certs/mysql/
Run Code Online (Sandbox Code Playgroud)

创建服务器证书

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
Run Code Online (Sandbox Code Playgroud)

将服务器证书移动到/etc/pki/tls/certs/mysql/目录路径假定为CentOS或RHEL(根据其他发行版的需要进行调整):

mkdir /etc/pki/tls/certs/mysql/
cp /root/certs/mysql/* /etc/pki/tls/certs/mysql/
Run Code Online (Sandbox Code Playgroud)

务必设置文件夹和文件的权限.mysql需要完全的所有权和访问权限.

chown -R mysql:mysql /etc/pki/tls/certs/mysql
Run Code Online (Sandbox Code Playgroud)

现在配置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 
Run Code Online (Sandbox Code Playgroud)

然后

systemctl restart mariadb
Run Code Online (Sandbox Code Playgroud)

不要忘记打开防火墙以允许来自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.
Run Code Online (Sandbox Code Playgroud)

现在重启firewalld

service firewalld restart
Run Code Online (Sandbox Code Playgroud)

接下来,登录到dbserver的mysql服务器:

mysql -uroot -p 
Run Code Online (Sandbox Code Playgroud)

发出以下命令为客户端创建用户.请注意GRANT语句中的REQUIRE SSL.

GRANT ALL PRIVILEGES ON *.* TO ‘iamsecure’@’appclient’ IDENTIFIED BY ‘dingdingding’ REQUIRE SSL;
FLUSH PRIVILEGES; 
# quit mysql
Run Code Online (Sandbox Code Playgroud)

从第一步开始你仍然应该在/ 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
Run Code Online (Sandbox Code Playgroud)

注意:我对服务器和客户端证书使用了相同的通用名称.因人而异.

确保你仍然是/ root/certs/mysql /用于下一个命令

将服务器和客户端CA证书合并到一个文件中:

cat server-cert.pem client-cert.pem > ca.pem
Run Code Online (Sandbox Code Playgroud)

确保您看到两个证书:

cat ca.pem 
Run Code Online (Sandbox Code Playgroud)

现在结束服务器端工作.

打开另一个终端和

ssh appclient
Run Code Online (Sandbox Code Playgroud)

和以前一样,为客户端证书创建一个永久的主页

mkdir /etc/pki/tls/certs/mysql/
Run Code Online (Sandbox Code Playgroud)

现在,将客户端证书(在dbserver上创建)放在appclient上.您可以将它们scp,或者只是逐个复制和粘贴文件.

scp dbserver
# copy files from dbserver to appclient
# exit scp
Run Code Online (Sandbox Code Playgroud)

同样,请务必设置文件夹和文件的权限.mysql需要完全的所有权和访问权限.

chown -R mysql:mysql /etc/pki/tls/certs/mysql
Run Code Online (Sandbox Code Playgroud)

你应该有三个文件,每个文件都由用户mysql拥有:

/etc/pki/tls/certs/mysql/ca.pem
/etc/pki/tls/certs/mysql/client-cert.pem
/etc/pki/tls/certs/mysql/client-key.pem
Run Code Online (Sandbox Code Playgroud)

现在编辑appclient的MariaDB/MySQL配置[client].

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 
Run Code Online (Sandbox Code Playgroud)

重启appclient的mariadb服务:

systemctl restart mariadb
Run Code Online (Sandbox Code Playgroud)

仍然在这里的客户端

这应该返回:ssl TRUE

mysql --ssl --help
Run Code Online (Sandbox Code Playgroud)

现在,登录appclient的mysql实例

mysql -uroot -p
Run Code Online (Sandbox Code Playgroud)

应该在下面的两个变量中都看到YES

show variables LIKE '%ssl';
    have_openssl    YES
    have_ssl              YES
Run Code Online (Sandbox Code Playgroud)

我最初看到了

 have_openssl NO
Run Code Online (Sandbox Code Playgroud)

快速浏览mariadb.log显示:

SSL错误:无法从'/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
Run Code Online (Sandbox Code Playgroud)

如果需要,从上面的步骤重新启动mariadb

现在我们准备测试安全连接

我们仍然在这里appclient

尝试使用上面创建的帐户连接到dbserver的mysql实例.

mysql -h dbserver -u iamsecure -p
# enter password dingdingding (hopefully you changed that to something else)
Run Code Online (Sandbox Code Playgroud)

运气不错,您应该毫无错误地登录.

要确认您已启用SSL,请从MariaDB/MySQL提示符处发出以下命令:

\s 
Run Code Online (Sandbox Code Playgroud)

这是一个反斜杠,又名状态

这将显示您的连接状态,它应如下所示:

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
Run Code Online (Sandbox Code Playgroud)

如果您在连接尝试中获得权限被拒绝错误,请检查上面的GRANT语句以确保没有任何流浪字符或'标记.

如果您有SSL错误,请返回本指南以确保步骤有序.

这适用于RHEL7,也可能适用于CentOS7.无法确认这些确切步骤是否适用于其他地方.

希望这可以节省别人一点时间和恶化.

  • 这些指南一直让我困惑的是为什么客户端需要服务器的密钥或任何证书。TLS 证书的全部意义不就是证明服务器身份吗? (2认同)

小智 5

根据上述指南,您必须确保所有三个证书的“通用名称”都不同。

我遇到了同样的错误,因为我对所有三个证书使用了相同的 CN。使用不同的 CN 重新生成证书后,错误消失了。