我正在嘗試使用 Asio 和 OpenSSL 發送 https 網路請求。我的代碼在我嘗試過的大多數網站上都運行良好,但在其他一些網站上,我在握手期間出現錯誤handshake: wrong version number (SSL routines, ssl3_get_record)。
我發現有些人遇到這個問題是因為他們在代理后面,或者因為他們試圖連接到埠 80 而不是埠 443,但這里不是這種情況(據我所知),因為完全相同的代碼(見下文舉個例子)適用于我嘗試過的大多數網站。
我試圖用wireshark檢查,看看我是否能發現有錯誤的案例和沒有錯誤的案例之間的區別。這是我發現的:
- 當它作業時,使用 TLSv1.2 或 1.3,當它不作業時,它是 TLSv1
- 當它不起作用時,DNS 查詢會顯示云端 cname 重定向,但用于套接字的端點與重定向匹配
基于這些觀察,我知道我的代碼能夠使用 TLSv1.3,并且我認為使用 TLSv1 是問題所在。asio::ssl::context::tlsv13_client因此,我嘗試在創建背景關系時或通過添加到 set_options 時強制 asio 使用版本 > 1 的 TLS asio::ssl::context::no_tlsv1,但wireshark 仍然顯示使用了 TLSv1 協議。
對于第二點,我對網路東西不太熟悉,所以我不確定我能得出什么結論,或者即使它與問題相關。
最小的作業示例:
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <iostream>
int main(int argc, char* argv[])
{
try
{
asio::io_context io_context;
asio::ip::tcp::resolver resolver(io_context);
asio::ip::tcp::resolver::results_type endpoints = resolver.resolve("google.com", "https"); //not working with "api.minecraftservices.com" for example
asio::ssl::context ctx(asio::ssl::context::sslv23); // also tried tlsv13_client to force v1.3, without success
ctx.set_default_verify_paths();
ctx.set_options(asio::ssl::context::default_workarounds | asio::ssl::context::verify_none);
asio::ssl::stream<asio::ip::tcp::socket> socket(io_context, ctx);
socket.set_verify_mode(asio::ssl::verify_none);
socket.set_verify_callback([](bool, asio::ssl::verify_context&) {return true; });
asio::connect(socket.lowest_layer(), endpoints);
socket.handshake(socket.client);
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
return -1;
}
return 0;
}
uj5u.com熱心網友回復:
您需要更具體地了解您嘗試連接的服務器:
住在科利魯
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
namespace ssl = boost::asio::ssl;
using boost::asio::ip::tcp;
int main() {
try {
boost::asio::io_context io_context;
tcp::resolver resolver(io_context);
ssl::context ctx(ssl::context::sslv23); // also tried tlsv13_client to
// force v1.3, without success
ctx.set_default_verify_paths();
ctx.set_options(ssl::context::default_workarounds |
ssl::context::verify_none);
ssl::stream<tcp::socket> socket(io_context, ctx);
socket.set_verify_mode(ssl::verify_none);
socket.set_verify_callback([](auto&&...) { return true; });
#ifndef COLIRU
connect(socket.lowest_layer(), resolver.resolve("d7uri8nf7uskq.cloudfront.net", "https"));
#else
socket.lowest_layer().connect({boost::asio::ip::address_v4::from_string("65.9.84.220"), 443});
#endif
std::cout << "Connected to " << socket.lowest_layer().remote_endpoint() << "\n";
socket.handshake(socket.client);
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
return -1;
}
}
印刷
Connected to 65.9.84.220:443
更新
事實上,使用 api.minecraftservices.com:443 確實可以列印
Connected to 65.9.78.95:443
handshake: wrong version number (SSL routines, ssl3_get_record) [asio.ssl:336130315]
事實證明你需要SNI:
SSL_set_tlsext_host_name(socket.native_handle(), "api.minecraftservices.com");
然后它就可以作業了(使用不同的 IP 解析度)
Connected to 65.9.78.23:443
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/427965.html
