如何设置MariaDB SSL和来自客户端的安全连接

时间:2020-01-09 10:39:45  来源:igfitidea点击:

如何为在Linux或类Unix系统上运行的MariaDB服务器和客户端启用SSL?
在本教程中,我将提供有关如何使用TLS/SSL设置MariaDB服务器以及如何通过控制台和PHP/Python脚本建立安全连接的说明。

MariaDB是一种数据库服务器,为MySQL服务器提供直接替换功能。

MariaDB由MySQL的一些原始作者构建,并得到了自由和开源软件开发人员的广泛支持。
除了MySQL的核心功能外,MariaDB还提供了一系列丰富的功能增强功能,包括其他存储引擎,服务器优化和补丁程序。

如何设置MariaDB SSL/TLS

我在RHEL/CentOS 7/8,Debian 9/10,Ubuntu 16.04/18.04/18.04 LTS,Arch Linux和FreeBSD上测试了这些说明。
但是,它也可以在其他Linux发行版上使用。

步骤1安装MariaDB

根据您的Linux或Unix变体执行命令。

在Ubuntu/Debian Linux上安装MariaDB服务器/客户端

执行以下apt-get命令或apt命令:

$ sudo apt-get install mariadb-server mariadb-client

在CentOS/RHEL/Fedora Linux上安装MariaDB服务器/客户端

执行以下yum命令:

$ sudo yum install mariadb-server mariadb

Fedora Linux用户执行以下dnf命令:

$ sudo dnf install mariadb-server mariadb

在Arch Linux上安装MariaDB服务器/客户端

输入以下pacman命令:

$ sudo pacman -S mariadb

在FreeBSD Unix上安装MariaDB服务器/客户端

要安装端口,请运行:

# cd /usr/ports/databases/mariadb100-server/ && make install clean
# cd /usr/ports/databases/mariadb100-client/ && make install clean

要添加二进制软件包,请执行:

# pkg install mariadb100-server mariadb100-client

步骤2保护MariaDB

执行以下命令:

$ mysql_secure_installation

步骤3建立CA凭证(TLS/SSL)

使用mkdir命令在/etc/mysql /目录中创建一个名为ssl的目录:

$ cd /etc/mysql
$ sudo mkdir ssl
$ cd ssl

注意:用于服务器和客户端证书/密钥的通用名称值必须分别与用于CA证书的通用名称值不同。
为避免出现任何问题,我将它们设置如下。
否则,您将得到认证验证失败的错误。
因此,将其设置如下:CA通用名称:MariaDB admin服务器通用名称:MariaDB服务器客户端通用名称:MariaDB客户端

执行以下命令以创建新的CA密钥:

$ sudo openssl genrsa 2048 > ca-key.pem

或者

$ sudo openssl genrsa 4096 > ca-key.pem

执行以下命令以使用该密钥生成证书:

$ sudo openssl req -new -x509 -nodes -days 365000 -key ca-key.pem -out ca-cert.pem

现在,您必须具有两个文件,如下所示:

  • /etc/mysql/ssl/ca-cert.pem证书颁发机构(CA)的证书文件。
  • /etc/mysql/ssl/ca-key.pem证书颁发机构(CA)的密钥文件。

我将使用这两个文件来生成服务器和客户端证书。

步骤4创建服务器SSL证书

要创建服务器密钥,请运行:

$ sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout server-key.pem -out server-req.pem

下一步处理服务器RSA密钥,执行:

$ sudo openssl rsa -in server-key.pem -out server-key.pem

输出示例:

writing RSA key

最后签署服务器证书,运行:

$ sudo openssl x509 -req -in server-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

输出示例:

Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=MariaDB server
Getting CA Private Key

现在,您必须具有其他文件:

  • /etc/mysql/ssl/server-cert.pemMariaDB服务器证书文件。
  • /etc/mysql/ssl/server-key.pemMariaDB服务器密钥文件。

您必须在MariaDB服务器本身以及将用于集群/复制流量的任何其他节点上使用以上两个文件。
这两个文件将确保服务器端通信的安全。

步骤5创建客户端TLS/SSL证书

mysql客户端,PHP/Python/Perl/Ruby应用程序将使用客户端证书来保护客户端连接。
您必须在所有客户端(包括Web服务器)上安装以下文件。

为MariaDB服务器创建客户端密钥

$ sudo openssl req -newkey rsa:2048 -days 365000 -nodes -keyout client-key.pem -out client-req.pem

接下来,处理客户端RSA密钥,执行:

$ sudo openssl rsa -in client-key.pem -out client-key.pem
`writing RSA key`

最后,签署客户端证书,运行:

$ sudo openssl x509 -req -in client-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

输出示例:

Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=MariaDB client
Getting CA Private Key

步骤6如何验证证书?

执行以下命令来验证证书,以确保所有内容均正确创建:

$ openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem

输出示例:

server-cert.pem: OK
client-cert.pem: OK

不应有任何错误,并且服务器和客户端证书都必须得到正确的答案。

步骤7将MariaDB服务器配置为使用SSL

编辑vi /etc/mysql/mariadb.conf.d/50-server.cnf或/etc/mysql/mariadb.cnf,如下所示:

$ sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf

在[mysqld]中追加/编辑,如下所示:

### MySQL Server ###
## Securing the Database with ssl option and certificates ##
## There is no control over the protocol level used. ##
##  mariadb will use TLSv1.0 or better.  ##
#ssl
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
## Set up TLS version here. For example TLS version 1.2 and 1.3 ##
tls_version = TLSv1.2,TLSv1.3

保存并关闭文件。
使用chmod命令/chown命令保护密钥:

## Assuming that mariadb (mysqld) server started by the mysql user ##
$ sudo chown -Rv mysql:root /etc/mysql/ssl/
changed ownership of '/etc/mysql/ssl/server-key.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/client-req.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/server-req.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/ca-key.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/server-cert.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/client-cert.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/ca-cert.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/client-key.pem' from root:root to mysql:root
changed ownership of '/etc/mysql/ssl/' from root:root to mysql:root

您可以按以下方式重新启动mariadb:

$ sudo /etc/init.d/mysql restart

对于基于systemd的Linux发行版,请使用systemctl命令:

$ sudo systemctl restart mysql

确保没有报告ssl错误。
这是使用grep命令验证的简单方法

$ sudo grep ssl /var/log/syslog
$ sudo grep ssl /var/log/syslog | grep key
$ sudo grep mysqld /var/log/syslog | grep -i ssl

步骤8将MariaDB客户端配置为使用SSL

将MariaDB客户端(例如192.168.1.200)配置为使用SSL(在/etc/mysql/mariadb.conf.d/50-mysql-clients.cnf中添加):

$ sudo vi /etc/mysql/mariadb.conf.d/50-mysql-clients.cnf

在[mysql]部分中添加/编辑:

## MySQL Client Configuration ##
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/client-cert.pem
ssl-key=/etc/mysql/ssl/client-key.pem
##  Force TLS version for client too
#tls_version = TLSv1.2,TLSv1.3
### This option is disabled by default ###
### ssl-verify-server-cert ###

保存并关闭文件。
您必须将/etc/mysql/ssl/ca-cert.pem、/etc/mysql/ssl/client-cert.pem和/etc/mysql/ssl/client-key.pem复制到所有客户端。
例如:

{Hyman@server}: rsync /etc/mysql/ssl/ca-cert.pem /etc/mysql/ssl/client-cert.pem /etc/mysql/ssl/client-key.pem \
user@client:/etc/mysql/ssl

步骤9验证

输入mysql命令命令:

$ mysql -u {User-Name-Here} -h {Server-IP-here} -p {DB-Name-Here}
$ mysql -u root -h 192.168.1.100 -p mysql
$ mysql -u root -h 127.0.0.1 -p mysql

在" MariaDB [(none)]>"提示符下执行以下" SHOW VARIABLES LIKE'%ssl%';"命令:

MariaDB [(none)]> SHOW VARIABLES LIKE '%ssl%';

或发出状态命令:

MariaDB [(none)]> status;

验证SSL与TLS连接。
由于ssl 3已配置并使用以下命令,因此以下命令应失败:

$ openssl s_client -connect 192.168.1.100:3306 -ssl3
`140510572795544:error:140A90C4:SSL routines:SSL_CTX_new:null ssl method passed:ssl_lib.c:1878:`

检查TLS v 1/1.1/1.2:

$ openssl s_client -connect 192.168.1.100:3306 -tls1
$ openssl s_client -connect 192.168.1.100:3306 -tls1_1
$ openssl s_client -connect 192.168.1.100:3306 -tls1_2

输出示例:

CONNECTED(00000003)
--
no peer certificate available
--
No client certificate CA names sent
--
SSL handshake has read 5 bytes and written 7 bytes
--
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS 不支持
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1485335036
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
--

如何读取tcpdump数据包捕获文件以验证安全通信

最后,您可以使用在命令行下运行的tcpdump命令数据包分析器来查看端口3306:

$ sudo tcpdump -i eth0 -s 65535 port 3306 -w /tmp/mysql.pcap

现在,从您的PHP/Python/Perl/Ruby mysql应用程序或控制台mysql应用程序连接:

$ mysql -u bar -h 192.168.1.100 -p foo

使用tcpdump验证服务器和客户端之间是否没有交换明文信息(包括密码),如下所示:

$ tcpdump -r /tmp/mysql.pcap | less

您可以使用tcpdump或其他工具(例如Wireshark)读取捕获的流量。

步骤10将用户添加到MariaDB服务器

执行以下命令:

$ mysql -u root -p

创建一个名为foo的数据库:

CREATE DATABASE foo;

为名为foo的数据库添加名为bar的用户:

GRANT ALL ON foo.* TO bar@localhost IDENTIFIED BY 'mypassword' REQUIRE SSL;

授予来自192.168.1.200托管的Web服务器的访问权限:

GRANT ALL ON foo.* TO [email protected] IDENTIFIED BY 'mypassword' REQUIRE SSL;

从bash shell建立安全连接

您可以从控制台登录,如下所示:

$ mysql -u bar -p -h 192.168.1.100 foo

通过Python建立安全连接

首先安装MySQL的Python接口:

$ sudo apt-get install python-mysql.connector

或适用于Python v3.x

$ sudo apt-get install python3-mysql.connector

这是使用SSL安全连接的示例Python代码:

#!/usr/bin/python
import MySQLdb
ssl = {'cert': '/etc/mysql/ssl/client-cert.pem', 'key': '/etc/mysql/ssl/client-key.pem'}
conn = MySQLdb.connect(host='192.168.1.100', user='bar', passwd='mypassword', ssl=ssl)
cursor = conn.cursor()
cursor.execute("SHOW STATUS LIKE 'Ssl_cipher'")
print cursor.fetchone()

或者

#!/usr/bin/python
# Note (Example is valid for Python v2 and v3)
from __future__ import print_function
import sys
 
import mysql.connector
from mysql.connector.constants import ClientFlag
 
config = {
    'user': 'bar',
    'password': 'mypassword',
    'host': '192.168.1.100',
    'client_flags': [ClientFlag.SSL],
    'ssl_ca': '/etc/mysql/ssl/ca-cert.pem',
    'ssl_cert': '/etc/mysql/ssl/client-cert.pem',
    'ssl_key': '/etc/mysql/ssl/client-key.pem',
}
 
cnx = mysql.connector.connect(**config)
cur = cnx.cursor(buffered=True)
cur.execute("SHOW STATUS LIKE 'Ssl_cipher'")
print(cur.fetchone())
cur.close()
cnx.close()

输出示例:

('Ssl_cipher', 'DHE-RSA-AES256-SHA')