我正在编写一个 C++ 客户端应用程序,使用 MariaDB C 连接器连接到 MariaDB 服务器。此代码有效:
this->mysql = mysql_init(0);
int timeout_sec = 10;
int ret = mysql_options(this->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout_sec);
assert(ret == 0);
auto ret_mysql = mysql_real_connect(this->mysql,
this->host.c_str(),
this->username.c_str(),
this->password.c_str(),
this->db_name.c_str(),
this->port,
nullptr,
0);
if (ret_mysql == nullptr) {
// An error occurred.
throw MyException("Database",mysql_error(this->mysql));
}
但是,我想启用 SSL,并且因为我使用的是具有自签名证书的服务器,所以我需要添加 CA 文件,因此我添加了(在连接之前):
int ret;
ret = mysql_options(this->pimpl->mysql, MYSQL_OPT_SSL_CA, ca_file.c_str());
assert(ret == 0);
但是,如果我添加这些行,mysql_real_connect 就会失败并显示“连接超时”。
补充说明:
服务器可以与其他客户端一起使用 SSL 正常工作
证书路径/文件没问题
如果我将超时值增加到 20,则会收到“连接已被对等方重置”
我尝试使用已弃用的
mysql_ssl_set()
但没有成功(相同的结果)
我也尝试设置
MYSQL_OPT_SSL_ENFORCE
/ MYSQL_OPT_SSL_VERIFY_SERVER_CERT
但没有成功
服务器日志显示:
[警告]中止连接 12345 到数据库:'未连接'用户:'未经身份验证'主机:'
知道可能是什么问题吗?也许,在连接之前还有其他函数需要调用?
--编辑--
显然,问题是由于证书公用名不匹配而导致的 SSL 错误。我解决了这个问题,现在它可以工作了。但是,为什么如果 SSL 出现问题,它会由对等方生成超时/连接重置,而不是按预期返回错误?
我将尝试回答更新的问题,猜测一些您帖子中没有的细节。如果这没有帮助,请发布当前完整的工作代码。
首先,我想您使用
mysql_errno()
或 mysql_error()
获取错误代码/消息。
mysql_real_connect()
记录的“错误”列表不包括“TLS/SSL 错误:SSL 服务器证书验证失败”。我猜你会得到一个 CR_SERVER_LOST
(“如果 connect_timeout > 0 并且连接到服务器的时间超过 connect_timeout 秒,或者服务器在执行 init 命令时死机。”)此错误与 直接相关MYSQL_OPT_CONNECT_TIMEOUT
你实际上正在使用。我认为当证书无效时,服务器只是忽略您的调用,这会导致客户端检测到超时(即客户端在等待响应过多后中止)。
我无法解释为什么当您增加超时时会收到“Connection Reset by Peer”,但是当服务器显式关闭通信通道(在客户端超时之前)时,客户端网络层会检测到此错误。
命令行“mysql”客户端可能正在使用对值为
MYSQL_OPT_SSL_MODE
的 SSL_MODE_VERIFY_CA
选项的显式调用。请检查https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode。