mysql ssl

【1】SSL简介

(1.1)SSL简介

安全一直是不可不重视的问题。目前MySQL这方面应大方向上技术手段都具备。如:网络链接,权限控制,key秘钥认证,数据加密脱敏 等方式。

综合考虑,虽然很多环境无法所有这些安全策略全部应用上,但在可控范围内尽量做到一定的防范实施。

其中SSL是属于加密连接方式,提供以下安全服务:

  • 客户机和服务器之间的,通过使用公开密钥和对称密钥技术以达到信息保密。
  • 信息完整性,确保SSL业务全部达到目的。应确保服务器和客户机之间的信息内容免受破坏。
  • 双向认证,客户机和服务器相互识别的过程。它们的识别号用公开密钥编码,并在SSL握手时交换各自的识别号。
  • 安全性服务对终端用户来讲做到尽可能透明。

  

(1.2)TLS OR SSL?

SSL(Secure Socket Layer 安全套接层):是基于 HTTPS 下的一个协议加密层,最初是由网景公司(Netscape)研发,后被 IETF(The Internet Engineering Task Force - 互联网工程任务组)标准化后写入(RFCRequest For Comments 请求注释),RFC 里包含了很多互联网技术的规范。

SSL(Secure Sockets Layer)是一种用于安全地传输数据的加密协议。在MySQL中,SSL可以用于加密客户端与服务器之间的通信,以防止数据被窃取或篡改。SSL通过以下方式实现数据的加密和身份验证:

- **加密通信**:SSL使用非对称加密和对称加密相结合的方式来加密通信。在连接建立阶段,服务器使用自己的私钥对公钥加密进行通信的对称加密密钥进行加密,然后将加密后的密钥发送给客户端。客户端使用私钥解密服务器发送的密钥,从而获取通信所使用的对称加密密钥。之后,客户端和服务器使用对称加密密钥对数据进行加密和解密。

- **身份验证**:SSL还用于验证服务器的身份。服务器使用数字证书来证明自己的身份。数字证书包含了服务器的公钥以及其他与服务器相关的信息,并由可信的第三方证书颁发机构(CA)签名。客户端在连接建立阶段会验证服务器的证书,以确保连接的安全性和合法性。

- **数据加密**:SSL使用对称加密和非对称加密相结合的方式来加密通信。在连接建立过程中,服务器使用私钥对公钥加密进行通信的对称加密密钥,然后将加密后的密钥发送给客户端。客户端使用私钥解密服务器发送的密钥,从而获取通信所使用的对称加密密钥。之后,客户端和服务器使用对称加密密钥对数据进行加密和解密。

起初是因为HTTP在传输数据时使用的是明文(虽然说 POST 提交的数据时放在报体里看不到的,但是还是可以通过抓包工具窃取到)是不安全的,为了解决这一隐患网景公司推出了SSL安全套接字协议层,SSL 是基于 HTTP 之下 TCP 之上的一个协议层,基于 HTTP 标准并对 TCP 传输数据时进行加密,所以 HTTPS 是 HTTP+SSL/TCP的简称。

由于 HTTPS 的推出受到了很多人的欢迎,在 SSL 更新到 3.0 时,IETF 对 SSL3.0 进行了标准化,并添加了少数机制(但是几乎和 SSL3.0无差异),标准化后的 IETF 更名为 TLS1.0(Transport Layer Security 安全传输层协议),可以说 TLS 就是 SSL 的新版本 3.1 。

TLS(Transport Layer Security):是更为安全的升级版 SSL。但 SSL 这一术语更为常用,实际上 MySQL 使用的就是 TLS 协议,而不是 SSL 协议。

(1.3)SSL证书

SSL安全证书是由权威认证机构颁发的,是CA机构将公钥和相关信息写入一个文件,CA机构用私钥对公钥和相关信息进行签名后,将签名信息也写入这个文件后生成的一个文件。

简单理解就是客户申请后,签发机构给一个唯一的文件,然后客户安装到服务器上进行使用,这个唯一的文件就是SSL证书。

备注:
  X.509:是一种证书格式,对X.509证书来说,认证者总是CA或由CA指定的人,一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。
  OpenSSL 相当于SSL的一个实现,如果把SSL规范看成接口,那么OpenSSL则认为是接口的实现。

(1.4)SSL的安全问题

尽管SSL可以提供一定程度的安全保障,但它也存在一些安全问题。主要包括以下几点:

1、证书信任问题。SSL协议中使用的证书是由受信任的第三方CA机构颁发的,用来证明服务器的身份和合法性。但是,如果服务器使用的证书是自签名的、过期的或被吊销的,那么客户端就难以判断服务器的真实性,这就容易被中间人攻击。

2、算法安全问题。SSL协议使用的加密算法对于现代计算机来说已经不够安全,比如DES、RC4等算法,容易被黑客攻击破解。因此,SSL协议现在已经推荐使用AES算法等更安全的加密算法。

3、协议升级问题。SSL协议的早期版本存在一些安全漏洞,如SSL 2.0版本中存在Poodle漏洞、HeartBleed漏洞等。因此,MySQL用户需要及时升级SSL协议版本,避免被攻击。

4、性能问题。由于SSL协议需要进行加密和解密,因此在高并发服务器中,SSL协议会对服务器性能造成一定的影响。所以,在使用SSL协议时,需要根据具体应用场景选择合适的算法和配置参数,以兼顾安全性与性能。

【SSL握手过程】

(1)证书用处

1》证书的用处,要看下面SSL握手过程

├── ca-key.pem
├── ca.pem
├── client-cert.pem
├── client-key.pem
├── server-cert.pem
└── server-key.pem

 

    

 

(2)密钥算法

对称密钥算法:数据加密和解密时使用相同的密钥。

非对称密钥算法:数据加密和解密时使用不同的密钥,一个是公开的公钥,一个是由用户秘密保存的私钥。利用公钥(或私钥)加密的数据只能用相应的私钥(或公钥)才能解密。

与非对称密钥算法相比,对称密钥算法具有计算速度快的优点,通常用于对大量信息进行加密(如对所有报文加密);而非对称密钥算法,一般用于数字签名和对较少的信息进行加密。

注意:SSL/TLS 协议就是使用对称密钥算法进行数据加密,使用非对称密钥算法进行”对称密钥“的加密。其过程为:

  1. 上图中,Server端发送了公钥给客户端,私钥自己保存,这是非对称密钥算法中的公钥、私钥对;
  2. 客户端会创建一个密钥,这个就是对称加密算法中的密钥。然后用 Server 端的公钥对这个密钥加密,发送给 Server 端;
  3. Server 端收到客户端发送过来的加密过的密钥,使用自己的私钥进行解密,得到加密前的密钥;
  4. 接下来传输数据则使用“对称密钥”进加密和解密。

这个就是利用非对称密钥算法保证对称密钥本身的安全

(3)数字证书-如何保证公钥的真实性?

如果有攻击者伪造了 Server 端的公钥并发了客户端,客户端会访问到假网站被窃取信息。显然保证客户端收到的 Server 端的公钥是真实的,是保证整个加密连接可靠性的第一道防线。

数字证书由权威机构 CA(Certification Authority) 签发,签发过程为:

  1. 用户首先产生自己的密钥对,并将公钥及部分个人身份信息传送给 CA ;
  2. CA 核实用户身份(将执行一些必要的步骤,以确信请求确实由用户发送而来);
  3. CA 对用户的所有信息(公钥、所有者、有效期...)进行 Hash 计算,得到一个 Hash 值,然后再使用私钥对 Hash 值进行加密得到签名,就得到了数字证书。该证书包含:用户的公钥、所有者、有效期等信息,同时还附有CA的签名信息。

数字证书的验证流程:

  1. 客户端会使用同样的 Hash 算法获取该数字证书的 Hash 值 H1;
  2. 通常浏览器和操作系统中集成了 CA 证书(包含 CA 公钥、所有者),客户端取得这个CA证书,使用其中的 CA 公钥解密签名,得到一个 Hash 值 H2 ;
  3. 比较 H1 和 H2,如果值相同,则数字证书可信。

上述签发和验证流程见下图(参考自网络):

   

如果 CA 证书不在浏览器和操作系统的可信任区,这种 CA 证书通常被称为自签名 CA 证书(MySQL 自动生成的就是自签名证书,详见下文)。

  要完成数字证书的验证,则必须事先将自签名 CA 证书放到客户端,并在客户端发起连接时指定这个 CA 证书文件;

  或者事先将自签名 CA 证书导入到客户端的操作系统可信任区,这样在 TLS 握手过程中也能自动获取到这个 CA 证书。

另外:验证证书在 SSL/TLS 协议中不一定是必须的,比如 mysql 客户端只有指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY 时才验证 CA 证书。

  如果 --ssl-mode=REQUIRED,则不验证 CA 证书,只要求 MySQL Server 端发送公钥给客户端,这就无法保证服务端公钥是真实属于 MySQL server 的。详细见下文。

【2】mysql ssl

(2.1)查看是否已经开启SSL

-- 查看所有会话连接哪些用了加密连接,VARIABLE_VALUE='' 的为未加密

select t2.PROCESSLIST_ID,t2.PROCESSLIST_USER,t2.PROCESSLIST_HOST,t1.VARIABLE_NAME,t1.VARIABLE_VALUE 
from performance_schema.status_by_thread t1 
join performance_schema.threads t2 on t1.THREAD_ID=t2.THREAD_ID  
where t1.VARIABLE_NAME like 'Ssl_cipher' ;

-- 当前session
SHOW SESSION STATUS LIKE 'Ssl_cipher';

show variables like '%ssl%';

  

yes是已经打开了,如果是DISABLE则表示没有。

TLS查看:

  

(2.2)如何开启ssl

前提:没有开启ssl,没有生成证书 (一般mysql 5.7.5以上版本,以及8.0都会默认开启)

步骤1:关闭mysql

步骤2:使用  mysql_ssl_rsa_setup,生成证书。

  mysql_ssl_rsa_setup --datadir=/opt/data8.0 --verbose    (不写参数也行,会存放到默认的 datadir 下)

  

 安装完成后:一般在 datadir 目录下会有( 注意这些密钥的权限问题,如果需要则执行:chown -R mysql.mysql *.pem)

[root mysql_data]# ll *.pem
-rw------- 1 mysql mysql 1675 Jun 12 17:22 ca-key.pem         #CA私钥
-rw-r--r-- 1 mysql mysql 1074 Jun 12 17:22 ca.pem             #自签的CA证书,客户端连接也需要提供
-rw-r--r-- 1 mysql mysql 1078 Jun 12 17:22 client-cert.pem    #客户端连接服务器端需要提供的证书文件
-rw------- 1 mysql mysql 1675 Jun 12 17:22 client-key.pem     #客户端连接服务器端需要提供的私钥文件
-rw------- 1 mysql mysql 1675 Jun 12 17:22 private_key.pem    #私钥/公钥对的私有成员
-rw-r--r-- 1 mysql mysql 451 Jun 12 17:22  public_key.pem     #私钥/公钥对的共有成员
-rw-r--r-- 1 mysql mysql 1078 Jun 12 17:22 server-cert.pem    #服务器端证书文件
-rw------- 1 mysql mysql 1675 Jun 12 17:22 server-key.pem     #服务器端私钥文件

步骤3:配置文件里加入SSL变量参数

[mysqld]
ssl-ca=/usr/local/mysql/data/ca.pem
ssl-cert=/usr/local/mysql/data/client-cert.pem
ssl-key=/usr/local/mysql/data/client-key.pem
 
[mysql]
ssl-ca=/usr/local/mysql/data/ca.pem
ssl-cert=/usr/local/mysql/data/client-cert.pem
ssl-key=/usr/local/mysql/data/client-key.pem

步骤4:重启 mysql,核验

service mysqld restart

SHOW SESSION STATUS LIKE 'Ssl_cipher';
\s

如下图,成功;

  

(2.3)mysql客户端配置

MySQL 客户端连接 Server 时,通过 --ssl-mode 参数指定:

  • --ssl-mode=PREFFERED,默认行为,client 端尝试使用加密进行连接,如果无法构建加密连接,则会退回到未加密的连接
  • --ssl-mode=REQUIRED时,Client 端需要加密连接,如果无法构建连接,则 Client 端将失败
  • --ssl-mode=DISABLED,Client 端使用未加密的连接
  • --ssl-mode=VERIFY_CA,Client 端需要加密连接,并且还对 CA 证书进行验证
  • --ssl-mode=VERIFY_IDENTITY,Client 端需要加密的连接,并且还针对 CA 证书和其证书中的服务器主机名执行验证

注意:主机名身份验证 VERIFY_IDENTITY 不适用于由服务器自动创建或使用 mysql_ssl_rsa_setup 手动创建的自签名CA证书。

如果没有使用ssl,则显示为Not in use

如果不想使用ssl则增加--ssl=0选项或--ssl-mode=DISABLED

一般localhost环境默认是不开启ssl的,如果想强制使用ssl,则增加--ssl-mode=REQUIRED 选项

mysql -uroot -proot --ssl=0
mysql -uroot -proot --ssl-mode=DISABLED   # 5.7及之后新版本建议使用该参数
mysql -uroot -proot --ssl-mode=REQUIRED # 5.7及之后新版本建议使用该参数

  

(2.4)如何强制必须使用 SSL?

如果要所有的均必须开启,则修改 my.cnf

[mysqld]
require_secure_transport=ON

(2.5)如何强制用户必须使用 SSL加密方式连接?

//新建用户
mysql> grant select on *.* to 'dba'@'%' identified by 'xxx' REQUIRE SSL; 
//修改用户
mysql> ALTER USER 'dba'@'%' REQUIRE SSL; 
flush privileges;

【3】mysql 复制使用 SSL

(3.1)mysql ssl握手过程

上述示例已有详细说明,这里再简要总结一下:

  1. 客户端发起 ssl 连接请求;

  2. MySQL Server 发送数字证书 server-cert.pem 给客户端(server-cert.pem包含:服务器公钥、CA签名信息);

  3. 客户端使用CA 证书 ca.pem(由于这是 MySQL 自签名的CA证书,无法从操作系统的可信任区获取(压根不在这里边),所以事先必须在客户端本地保存 CA 证书文件)中的 CA 公钥解密 server-cert.pem 中的签名,进行验证;

  4. 验证通过后,生成对称密钥,使用 server-cert.pem 中的公钥加密“对称密钥”,发送给 MySQL Server;

  5. MySQL Server 使用自己保留的私钥 server-key.pem 解密,得到“对称密钥”;

  6. 接下来传输数据则使用“对称密钥”进加密和解密。

如果仅指定 --ssl-mode=REQUIRED,不指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY,则不需要步骤3。

(3.2)复制通道SSL开启加密连接

理由:MySQL主从复制也会使用 TCP/IP 协议传输数据,同样为了减少数据泄漏的风险,建议为主从复制或者组复制配置 SSL 加密。 检查方法:
  1. 在从库执行 select Enabled_ssl,Ssl_ca,Ssl_verify_server_cert from mysql.slave_master_info;

  • Enabled_ssl 表示复制线程是否开启了 ssl 连接

  • Ssl_ca 表示是否配置了主库的 CA 证书文件,需从主库拷贝到从库服务器上,验证 CA 证书可以避免中间人攻击,建议配置(SSL中验证证书不是必须的,但是建议验证)

  • Ssl_verify_server_cert 表示是否要求验证 CA 身份,开启时自签名证书无法通过验证,必须购买受信任的CA机构颁发的数字证书

 

使用方法:

(前提:主库已开启 SSL 功能,允许客户端创建 SSL 加密连接)

 

##只开启 ssl

change master to master_ssl=1;

##开启 ssl,并验证 CA 证书(需拷贝主库上的 CA 证书)

change master to master_ssl=1,master_ssl_ca='/tmp/ca.pem';

##开启 ssl,验证 CA 证书并要求验证 CA 身份,这个需要购买受信任的CA机构颁发的数字证书,服务器和浏览器都会有权威CA机构的信任列表,可以自动获取,不再需要配置 master_ssl_ca

change master to master_ssl=1,master_ssl_verify_server_cert=1;

 

 

 

【4】JDBC 如何配置 SSL

(1)jdbc 开启 ssl 连接

首先 MySQL Server 端必须生成 SSL 证书和密钥文件,并且在启动时指定启动参数:--ssl(一般将其写到 my.cnf 中)。

MySQL8.0 启动时会自动生成SSL 证书和密钥文件,并默认使用 --ssl 参数。

JDBC 开启 ssl 连接示例:jdbc:mysql://localhost:3306/hucq?useSSL=true

JDBC 关闭 ssl 连接示例:jdbc:mysql://localhost:3306/hucq?useSSL=false

如果 MySQL Server 使用 caching_sha2_password(MySQL8.0默认的认证插件)、sha256_password 认证插件,则还必须指定 AllowPublicKeyRetrieval=True。

  因为 caching_sha2_password 插件要求交换密码时必须使用 RSA 公钥加密(在没有使用SSL加密连接的情况下),AllowPublicKeyRetrieval=True 参数作用是请求 MySQL Server 端发送 RSA 公钥给客户端。

  如果不请求 RSA 公钥并且又没有指定客户端本地RSA公钥文件(先从 MySQL 服务器上拷贝 RSA 公钥到本地),则连接会报错。

  应该配置:jdbc:mysql://localhost:3306/hucq?useSSL=false&AllowPublicKeyRetrieval=True(8.0)

JDBC 开启 SSL 连接,意味着要求安全连接,则应该开启 CA 证书认证,跟 mysql 客户端一样,需要将 MySQL 的自签名 CA 证书导入到客户端,或者放到 ftp 上,再通过 JDBC 参数指定 CA 证书路径,比较复杂.

请参考官方文档:https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html

(2)配置JDBC 的几种方法

mysql使用ssl连接官方文档:https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-using-ssl.html

第一种方法(自定义密钥库):

1、如果直接配置了连接属性verifyServerCertificate=true&useSSL=true&requireSSL=true,启动项目会报错,缺少证书

  

2、所以我们需要把服务器端的data/ca.pem文件拿到客户端,再执行命令,添加到truststore密钥库

  keytool -importcert -alias MySQLCACert -file ca.pem -keystore truststore -storepass mypassword

    

执行完毕会在当前文件夹生成一个truststore文件

3、然后把该文件的路径配置到连接属性&trustCertificateKeyStorePassword=mypassword&trustCertificateKeyStoreUrl=file:///Users/sumengnan/fsdownload/truststore

  或是直接增加java启动参数-Djavax.net.ssl.trustStore=/Users/sumengnan/fsdownload/truststore -Djavax.net.ssl.trustStorePassword=mypassword

4、如果mysql配置了双向认证,则参考https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-using-ssl.html

  如果不想使用服务器生成的客户端密钥和证书文件,也可以手动使用openssl创建密钥:https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-rsa-files.html

  这种方法缺点是,java会放弃原来的cacerts默认密钥库,如果你用到了其他的证书,那在truststore密钥库没有证书,会报错的。

 

第二种方法(添加到cacerts默认密钥库):

数据库连接增加属性verifyServerCertificate=true&useSSL=true&requireSSL=true

提示:默认密钥库位置:$JAVA_HOME/jre/lib/security/cacerts

keytool -importcert -alias MySQLCACert -file /Users/sumengnan/fsdownload/ca.pem -keystore cacerts(一条命令搞定,连密码和连接配置都不需要了)

默认的密钥库口令是:"changeit"

  

 【参考文档】

https://www.jianshu.com/p/75b098430508

https://blog.csdn.net/sumengnan/article/details/114086217

 

posted @ 2023-08-02 11:02  郭大侠1  阅读(580)  评论(0编辑  收藏  举报