首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么来自BIO_do_connect()的OpenSSL不能正确地使用GDAX (a.k.a )。云彩)沙箱?

为什么来自BIO_do_connect()的OpenSSL不能正确地使用GDAX (a.k.a )。云彩)沙箱?
EN

Stack Overflow用户
提问于 2018-03-25 09:25:27
回答 1查看 441关注 0票数 1

我用C++编写了一些软件,目前我正在尝试获取GDAX /products列表(目前主要是作为一个测试)。

更新:我想补充的是,连接实际上是到cloudflare,而不是直接到。因此,这可能是cloudflare的一个问题,而不是直接的GDAX服务器。

只有,BIO_do_connect()函数每次返回-1。它并没有给我多少继续下去的机会。我在日志中写了以下内容。因此,主要的信息是发生在s23_clnt.c的第794行的错误。

336031996/20|119|252:[]:[]:[]:s23_clnt.c794(no OpenSSL详细信息)

我可以看出,这意味着TCP连接本身就会发生,但不知怎么的,它无法获得可接受的安全连接。我以前也见过类似的行为,当时机器只会使用一些旧的加密方法。但是我检查了nmap,连接肯定支持TLS1.2。我运行了以下命令并得到:

代码语言:javascript
复制
nmap --script ssl-enum-ciphers api-public.sandbox.gdax.com

得到以下输出,证明端口443是开放的,并且有所有必要的加密方案。

代码语言:javascript
复制
Starting Nmap 7.01 ( https://nmap.org ) at 2018-03-24 21:57 PDT
Nmap scan report for api-public.sandbox.gdax.com (104.28.30.142)
Host is up (0.016s latency).
Other addresses for api-public.sandbox.gdax.com (not scanned): 104.28.31.142
Not shown: 996 filtered ports
PORT     STATE SERVICE
80/tcp   open  http
443/tcp  open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: C
8080/tcp open  http-proxy
8443/tcp open  https-alt
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 8.07 seconds

现在,我用普通REST地址(api.gdax.com)和我自己的网站(www.m2osw.com)测试了我的代码,加密部分工作得很好。我真的不认为我会做错什么,除非它的api-public.sandbox.gdax.com设置很奇怪,否则沙箱URL ( sandbox )就会这样失败。

请注意,当我试图连接到端口80 (我知道这是错误的)时,它可以正常工作。也就是说,我得到了一个301,它的位置与协议HTTPS的地址相同。

有人在连接沙箱时遇到了问题吗?

所有函数都会被调用。在第1111行周围的Lib快照网站中的github上有完整的实现(bio_client构造函数)。

代码语言:javascript
复制
// called once on initialization
SSL_library_init();
ERR_load_crypto_strings();
ERR_load_SSL_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
crypto_thread_setup();

// call each time we connect
SSL_CTX * ssl_ctx = SSL_CTX_new(SSLv23_client_method();
SSL_CTX_set_verify_depth(ssl_ctx, 4);
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_COMPRESSION);

// just in case I tried with "ALL", but no difference
//SSL_CTX_set_cipher_list(ssl_ctx, "ALL");
SSL_CTX_set_cipher_list(ssl_ctx, "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4");

SSL_CTX_load_verify_locations(ssl_ctx, NULL, "/etc/ssl/certs");
BIO * bio = BIO_new_ssl_connect(ssl_ctx);
SSL * ssl(nullptr);
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(bio, const_cast<char *>(addr.c_str()));
BIO_set_conn_int_port(bio, &port);

int const cr(BIO_do_connect(bio));
// here cr == -1 when I use api-public.sandbox.gdax.com

同样,如果我使用cr > 0,那么这段代码就可以使用find和api.gdax.com了,所以我现在真的很困惑!?我知道TCP连接本身就发生了,因为它进入了s23_clnt.c,也就是在该部分发生之后。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-09 03:16:58

好的,我花了一整天(好的,半天)来比较我的代码和libcurl的代码,后者也使用了OpenSSL的SSL_CTXSSL结构。代码看起来非常相同.除了libcurl版本包括以下内容:

代码语言:javascript
复制
[...]
switch(data->set.ssl.version) {
case CURL_SSLVERSION_DEFAULT:
  [...]
  use_sni(TRUE);
  break;

[...]
if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
   (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
   sni &&
   !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
  infof(data, "WARNING: failed to configure server name indication (SNI) "
        "TLS extension\n");
[...]

正如我们所看到的,他们有一个叫做SNI的东西,如果是真的,他们会设置名为Hostname的TLS扩展。如果SSL HELLO消息中没有包含Hostname参数,那么GDAX服务器(或者很可能是cloudflare服务器)会立即拒绝连接。

因此,在我的终端上,我将强制SNI (服务器名称标识),这样它很可能在更多的服务器上工作。libcurl允许不包含它,但看起来您应该始终拥有它。至少不应该疼。

代码语言:javascript
复制
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
SSL_set_tlsext_host_name(ssl, const_cast<char *>(addr.c_str()));
BIO_set_conn_hostname(bio, const_cast<char *>(addr.c_str()));

注意,SSL_set_tlsext_host_name()函数必须给出正确的主机名,而不是IPv4或IPv6地址。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49474347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档