【发布时间】:2016-11-19 13:36:49
【问题描述】:
我用 C++ 和 OpenSSL 开发了一个应用程序来监控 MySQL 数据包。我的应用程序充当代理。在没有 SSL 连接的情况下一切正常,但是当我使用 SSL 连接时,它在收到 Client Hello 后正好面临“握手失败”。
我使用 openssl 开发了一个 ssl 服务器并使其阻塞并在正确的时间等待接受 ssl 连接。
Wireshark 截图
140167999850080:错误:1408A0C1:SSL 例程:SSL3_GET_CLIENT_HELLO:没有共享密码:s3_srvr.c:1352:
140167999850080:错误:1408A0C1:SSL 例程:SSL3_GET_CLIENT_HELLO:没有共享密码:s3_srvr.c:1352:
已编辑:这是在检测到 ssl 连接选项打开时与客户端交互的代码的一部分。收到登录请求包后,此代码将运行。
void mysqlNegotiation(X509* cert, EVP_PKEY* key, int fd) {
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
SSL_CTX* context = SSL_CTX_new(TLSv1_server_method());
SSL_CTX_use_certificate(context, cert);
SSL_CTX_use_PrivateKey(context, key);
SSL_CTX_check_private_key(context);
SSL_CTX_set_ecdh_auto(context, 1);
SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
SSL_CTX_set_verify_depth(context, 4);
SSL_CTX_load_verify_locations(context, "ca-cert.pem", "/etc/mysql/");
SSL* ssl = SSL_new(context);
SSL_set_fd(ssl, fd);
int r = SSL_accept(ssl);
if (r != 1) {
ERR_print_errors_fp(stderr);
int err_SSL_get_error = SSL_get_error(ssl, r);
switch (err_SSL_get_error) {
case SSL_ERROR_NONE:
printf("%d", 0);
break;
case SSL_ERROR_SSL:
printf("%d", 1);
break;
case SSL_ERROR_WANT_READ:
printf("%d", 2);
break;
case SSL_ERROR_WANT_WRITE:
printf("%d", 3);
break;
default:
printf("%d", -1);
break;
}
}
}
【问题讨论】:
-
我怀疑这段代码是否正确:` SSL_CTX* context = = SSL_CTX_new(TLSv1_server_method()); `。它甚至可能无法编译。请制作一个可用于重现问题的实际工作示例。
-
您是否查看过客户端提供了哪些密码?也许进行数据包捕获?例如,如果客户端只提供 DH 密码,这将失败,因为您没有设置任何 DH(不是 ECDH)参数。
-
源代码修改!是的,两者都提供相同的密码列表
-
您如何检查服务器提供的密码?您是如何检查客户的?
-
您的代理使用什么类型的证书,代理两端启用的密码套件列表是什么?这也强制客户端使用客户端证书 (IIRC):
SSL_VERIFY_FAIL_IF_NO_PEER_CERT。最后,你看过 OpenSSL wiki 上的 TLS Client 吗?