gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 22:41:37 25 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,其位置与协议(protocol) HTTPS 相同。

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

有所有被调用的函数。完整的实现可在 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

同样,此代码可以找到和 cr > 0如果我使用 api.gdax.com所以我现在真的很茫然!?而且我知道 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 扩展。如果该主机名参数未包含在 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/72643696/

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