添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
MySQL 从 5.7.27 升级到 5.7.30。完成后应用连接测试发现页面异常,mysql error 日志显示:
  1. 2020-05-05T22:10:57.976402+08:00 2 [Note] Bad handshake

没有报错,但这条 Note 级别的日志,引起了我的注意,之前从来没有见过。由于时间紧急,决定先回退 MySQL 版本。 回退后,问题未能解决。
Bad handshake,”不好的握手”,网上查了资料,发现和 SSL 可能有关。这时业务也发来应用日志,日志有明显的 SSL 相关报错。
然后,我们去检查了 jdbc 连接串,连接串使用了 useSSL=true ,改为 useSSL=false 后解决了。

5.7.27 版本

1. 默认关闭了 SSL
  1. mysql> select @@version;

  2. +------------+

  3. | @@version |

  4. +------------+

  5. | 5.7.27-log |

  6. +------------+

  7. 1 row in set (0.00 sec)


  8. mysql> show variables like '%ssl%';

  9. +---------------+----------+

  10. | Variable_name | Value |

  11. +---------------+----------+

  12. | have_openssl | DISABLED |

  13. | have_ssl | DISABLED |

  14. | ssl_ca | |

  15. | ssl_capath | |

  16. | ssl_cert | |

  17. | ssl_cipher | |

  18. | ssl_crl | |

  19. | ssl_crlpath | |

  20. | ssl_key | |

  21. +---------------+----------+

  22. 9 rows in set (0.00 sec)

5.7.28 版本

1. 升级后,默认居然开了 SSL
  1. mysql> show variables like '%ssl%';

  2. +---------------+-----------------+

  3. | Variable_name | Value |

  4. +---------------+-----------------+

  5. | have_openssl | YES |

  6. | have_ssl | YES |

  7. | ssl_ca | ca.pem |

  8. | ssl_capath | |

  9. | ssl_cert | server-cert.pem |

  10. | ssl_cipher | |

  11. | ssl_crl | |

  12. | ssl_crlpath | |

  13. | ssl_key | server-key.pem |

  14. +---------------+-----------------+

  15. 9 rows in set (0.00 sec)

  1. 上面日志,能看出是 SSL 相关异常。

  2. 并且能发现一个关键的报错,是握手异常,并且有证书相关的报错。


  3. Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors


  4. 后面我证实了,jdbc 连接要求 SSL 和 证书认证要一起使用。

4. 抓包显示有加密信息,没有抓取到 SQL
  1. [root@fander ~]# tcpdump -i ens33 port 3307 -l -s 0 -w - | strings

  2. tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes

  3. @8q=*

  4. 8q=+P

  5. @8q=+

  6. 5.7.30-log

  7. =LQIKF7

  8. mysql_native_password

  9. 8q=}P

  10. @8q=}

  11. B 8q=}P

  12. @8q=}

  13. @8q=}

  14. 0<1:08

  15. 1MySQL_Server_5.7.30_Auto_Generated_CA_Certificate0

  16. 200506110938Z

  17. 300504110938Z0@1>0<

  18. 5MySQL_Server_5.7.30_Auto_Generated_Server_Certificate0

  19. 2nh

  20. =zFx

  21. 3[x=

  22. o(*c0

  23. Ty5B

  24. 0A,IY

  25. -{u6

  26. 0<1:08

  27. 1MySQL_Server_5.7.30_Auto_Generated_CA_Certificate0

  28. 200506110938Z

  29. 300504110938Z0<1:08

  30. 1MySQL_Server_5.7.30_Auto_Generated_CA_Certificate0

  31. >*[]dG

  32. ^!!$

  33. y[(j

  34. kh(nPjd

  35. VU{h

  36. MMojb

  37. U38P

  38. 3.^Z

发现一切正常,但 tomcat 日志有以下的 warnings:
Wed May 06 20:54:47 CST 2020 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
翻译:
  • 不建议在未经服务器身份验证的情况下建立 SSL 连接。

  • 根据 MySQL 5.5.45+、5.6.26+ 和 5.7.6+ 的要求,如果未设置显式选项,则默认情况下必须建立 SSL 连接。

  • 为了符合不使用 SSL 的现有应用程序,verifyServerCertificate 属性设置为“false”。

  • 您需要通过设置 useSSL=false 显式禁用 SSL,

  • 或者设置 useSSL=true 并为服务器证书验证提供 truststore。

从这里的报错,我发现了另外一个连接串参数,verifyServerCertificate,这个参数默认为 true,表示要验证服务器证书。
2. 那么为什么 5.7.28 会自动生成这些文件?
  1. mysql --verbose --help |less

  2. --auto-generate-certs

  3. Auto generate SSL certificates at server startup if --ssl

  4. is set to ON and none of the other SSL system variables

  5. are specified and certificate/key files are not present

  6. in data directory.

  7. (Defaults to on; use --skip-auto-generate-certs to disable.)

在 5.7.28 版本,存在该服务器参数,但 5.7.27 未见此参数。
参数写的很清楚,默认是开的,用于自动生成”SSL 密钥和证书文件”,如果数据目录没有这堆文件的话。
相关的参数,还有这些:
  • auto _generate_ certs

  • sha256_ password_ auto_ generate_ rsa_keys

  • sha256_ password_ private_ key_ path

  • sha256_ password_ public_ key_ path

  • Rsa_ public_ key

官方文档并没有告诉我们这些参数是 5.7.28 新增的,原因是因为这些参数压根就不是新增的!这些参数是一直都有的!
如果你的 MySQL 源码编译时用 openssl,替代 yassl,那就有这些参数!

所以 Only OpenSSL 这个新特性,实际上影响比官方文档写的要大,因为他实际上影响了 MySQL 参数!影响了 MyS QL 默认开启了 SSL 的支持!

讨论解决办法

既然,有没有这堆文件,会导致实际上是否开启 SSL,那么解决办法可以是:
1. 删除这堆文件,然后重启 MySQL。
在回退后的 5.7.27 版本是可以这么操作,但我们总归要升级回去 5.7.28 的,而5.7.28 启动又会自动生成这堆文件,开启 SSL,所以这方法不行。
2. 删除这堆文件的某个文件,然后重启 MySQL。
这个方法看起来是可行的,例如删除了 ca.pem 这个文件,文件不全会导致 SSL disabled,并且 mysqld 判断数据目录有部分 pem 文件,于是不会重新生成。但这方法忽略了一个可能,就是如果数据库通过 Xtrabackup 物理热备重做数据库后,因为 Xtrabackup 实际上不会备份任何 pem 文件,所以数据库重做启动后,因 mysqld 判断数据目录没有”SSL 密钥和证书文件”,这堆文件会全部重新生成。所以这方法不可行。
3. 配置 auto_ generate_ certs=off
让不生成 cert 文件,即可默认 SSL disabled。