Curl 如何从代码中禁用服务器密钥交换?

Curl 如何从代码中禁用服务器密钥交换?,curl,openssl,http2,nghttp2,Curl,Openssl,Http2,Nghttp2,我在Ubuntu 15.04上运行了一个HTTP2服务器示例(libevent server.c)。我想使用Wireshark嗅探客户端服务器之间的HTTP2数据包 我不使用任何web浏览器作为客户端,因此有关如何在Wireshark中阅读HTTP2消息的提示不适用于我的项目。我使用libcurl 由于HTTP2数据包是TLS内部的应用层,Wireshark必须知道如何解密它;因此,我按照从的指南向Wireshark提供了钥匙。然而,指南警告说,“如果服务器发送ServerKeyExchange

我在Ubuntu 15.04上运行了一个HTTP2服务器示例(libevent server.c)。我想使用Wireshark嗅探客户端服务器之间的HTTP2数据包

我不使用任何web浏览器作为客户端,因此有关如何在Wireshark中阅读HTTP2消息的提示不适用于我的项目。我使用libcurl

由于HTTP2数据包是TLS内部的应用层,Wireshark必须知道如何解密它;因此,我按照从的指南向Wireshark提供了钥匙。然而,指南警告说,“如果服务器发送ServerKeyExchange消息,您将无法解密数据。”不幸的是,我的Wireshark显示服务器密钥交换是由服务器发送的

以下是libevent server.c代码片段:

 SSL_load_error_strings();
 SSL_library_init();
 OpenSSL_add_all_algorithms();
 OPENSSL_config(NULL);
在将
OPENSSL\u config(NULL)
更改为
OPENSSL\u no\u config()
后,我重新编译了代码,但仍发送了服务器密钥交换

如何禁用服务器密钥交换

我想使用Wireshark嗅探客户端服务器之间的HTTP2数据包

为此,您通常参考Wireshark Wiki上的


我的Wireshark显示服务器密钥交换是由服务器发送的

我相信Serer密钥交换消息总是被发送的。我认为您能做的最好的事情就是在服务器Hello中抑制服务器证书消息。通过仅启用匿名协议来实现这一点。匿名协议放弃服务器身份验证,并允许您拦截流量

我相信您要查找的密码字符串是
“ADH:AECDH”
“aNULL”
(通常,您明确声明
“!aNULL”
)。它需要在客户端和服务器上都可用。最后,您可以在OpenSSL手册页上获得令牌列表

大多数客户端断然拒绝匿名协议,因此可能很难真正进入该配置(并使所有内容都正常工作)。

正如几乎正确的解释,对于Wireshark(或任何其他被动窃听者)解密SSL/TLS握手必须使用普通RSA密钥交换,不是任何Diffie-Hellman选项(实际上是DHE或ECDHE)或“短暂的”RSA。(所谓“几乎”是指它说“RSA密钥已用于加密数据”。事实上,RSA keyexchange使用服务器RSA密钥加密premaster密钥,该密钥经过广泛转换以生成用于加密和验证数据的多个密钥。)

实际上,DHE或ECDHE是问题所在。这些密码套件提供了所谓的功能,这意味着即使窃听者捕获并记录了您的通信,并随后泄露了服务器密钥,他们也无法使用它对记录的加密数据进行追溯解密。尽管这些套件已经存在并得到了长期的支持,但更多的人(浏览器和其他应用程序和中间件制造商、系统管理员、网络管理员、CISO和审计员等)更加重视使用它们

“临时RSA”密钥交换仅用于SSL/TLS中一些早已过时的“导出”密码套件。大约从1995年起,人们就知道这些设备是不安全的,大多数关心它们的人很长一段时间都禁止使用它们,或者至少优先使用未损坏的套件,尽管怪物研究人员几个月前发现大约有5%(我想是一个样本)的公共服务器仍然支持它们(这使得他们的攻击能够工作)。我上次检查OpenSSL时,默认情况下仍然启用它们,但优先级最低

回答:因此,您应该配置您的客户端(此处
curl
使用
--密码
)或您的服务器(调用
SSL[CTX\uu]set\u cipher\u list
),或者如果您愿意,可以同时配置这两个服务器,以删除临时套件
默认值:!埃德:!EECDH:!导出
或直接要求“普通”RSA
RSA:!出口:!埃努尔:!SSLv2


这带来了另一个选项
:如果您只需要检查基于OpenSSL的客户端和您控制的服务器之间的通信量,如这里所示,您可以使用空加密套件。这些设计是不安全的,基本上是为了测试目的,或者可能是非常严格的法律/外部限制,这些限制在20世纪90年代被认为是可以想象的,并且没有得到许多实现的支持;OpenSSL支持它们,但默认情况下禁用它们,甚至在逻辑上可能希望包含它们的
ALL
中也未启用它们。要获得它们,您必须明确指定
eNULL
(更好的
eNULL+RSA
)或非常违反直觉的
对所有
的补充。然后,您可以在Wireshark中读取数据而无需解密。

如果您的目标是从Wireshark中的OpenSSL应用程序读取解密的应用程序数据,请注意RSA私钥是,您还可以传递到(预)主密钥的映射。此功能不限于SSL客户端,即使使用NSS的应用程序通常使用
SSLKEYLOGFILE

有关从OpenSSL客户端和服务器应用程序检索预主密钥的方法,请参阅(不需要更改应用程序)。如果希望在应用程序中嵌入此类调试功能,那么可以在握手完成时设置回调,从而更干净地完成此操作。例如:

// converts bytes to hex
void to_hex(unsigned char *dst, unsigned char *src, size_t len) {
  unsigned char hex[] = "0123456789abcdef";
  unsigned i;
  for (i = 0; i < len; i++) {
    unsigned char c = src[i];
    *dst++ = hex[c >> 4];
    *dst++ = hex[c & 0xf];
  }
  *dst = '\0';
}

static FILE *ssl_keylog;

void info_callback(const SSL *ssl, int where, int ret) {
  unsigned char rnd[SSL3_RANDOM_SIZE*2+1];
  unsigned char pmk[SSL_MAX_MASTER_KEY_LENGTH*2+1];

  // skip in case the session is invalid, or if it is not
  // a Handshake Done notification.
  if (!ssl || !ssl->session || !ssl->s3 || !(where & SSL_CB_HANDSHAKE_DONE)) {
     return;
  }

  // convert bytes to hex
  to_hex(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
  to_hex(pmk, ssl->session->master_key, ssl->session->master_key_length);

  // write to SSL keylog file
  fprintf(keylog_file, "CLIENT_RANDOM %s %s\n", rnd, pmk);
}

static void run(const char *service, const char *key_file,
                const char *cert_file) {
  SSL_CTX *ssl_ctx;
  ...

  ssl_ctx = create_ssl_ctx(key_file, cert_file);
  if (!keylog_file) {
    // open key log file if any.
    keylog_file = fopen("premaster.txt", "a");
  }
  // register callback (for SSL objects, use SSL_set_info_callback instead)
  SSL_CTX_set_info_callback(ssl_ctx, info_callback);
  ...
}
//将字节转换为十六进制
空到十六进制(无符号字符*dst,无符号字符*src,大小长度){
无符号字符十六进制[]=“0123456789abcdef”;
未签名的i;
对于(i=0;i>4];
*dst++=hex[c&0xf];
}
*dst='\0';
}
静态文件*ssl\U密钥日志;
无效信息回调(常量SSL*SSL,int-where,int-ret){
无符号字符rnd[SSL3_随机_大小*2+1];
无符号字符pmk[SSL_MAX_MASTER_KEY_LENGTH*2+1];
//如果会话无效或无效,请跳过
//a H