gpt4 book ai didi

ssl - 为什么 OpenSSL 的 BIO_do_connect() 不能与 GDAX(又名 cloudflare)沙箱一起工作?

转载 作者:太空宇宙 更新时间:2023-11-03 14:34:18 28 4
gpt4 key购买 nike

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

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

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

OpenSSL: [336031996/20|119|252]:[]:[]:[]:[s23_clnt.c]:[794]:[(no details)]

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

nmap --script ssl-enum-ciphers api-public.sandbox.gdax.com

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

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 地址 (api.gdax.com) 和我自己的网站 (www.m2osw.com) 和加密测试了我的代码部分工作正常。我真的不明白我会做错什么,除非它的 SSL 设置很奇怪,否则它会像沙盒 URL (api-public.sandbox.gdax.com) 那样失败。

请注意,当我尝试连接到端口 80 时(我知道这是错误的),它会按预期工作。也就是说,我得到一个 301,其 Location 指向使用 HTTPS 协议(protocol)的同一地址。

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

有所有被调用的函数。完整的实现可以在 github 上的 libsnapwebsites 中找到。此时大约在第 1111 行(bio_client 构造函数)。

// 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

同样,如果我使用 api.gdax.com,此代码可以找到并 cr > 0 所以我现在真的很茫然!?而且我知道 TCP 连接本身会发生,因为它进入了 s23_clnt.c,这是在该部分发生之后。

最佳答案

好吧,我花了一整天(好吧大约半天)来研究这个,将我的代码与 libcurl 进行比较的代码也使用了 SSL_CTXSSL OpenSSL 的结构。代码看起来非常相似...除了 libcurl版本包括:

[...]
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 扩展。如果 Hostname 参数不包含在 SSL HELLO 中消息,然后 GDAX 服务器(或者很可能是 cloudflare 服务器)立即拒绝连接。

因此,就我而言,我将强制使用 SNI(服务器名称标识),这样它可能会在更多服务器上运行。 libcurl允许不包括它,但看起来你应该总是拥有它。至少应该不会痛。

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 地址。

关于ssl - 为什么 OpenSSL 的 BIO_do_connect() 不能与 GDAX(又名 cloudflare)沙箱一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49474347/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com