beast: SSL through proxy, "handshake: wrong version number"
Version of Beast : 189
Hello everyone,
I’m trying to establish a TLS connection through my proxy server.
Setting up the tunnel using HTTP CONNECT works as expected. The code I use as a demo is:
net::io_context ioc{};
std::thread([&] {
ioc.run();
}).detach();
ssl::context ssl_context_{ssl::context::tls};
ssl_context_.set_default_verify_paths();
ssl_context_.add_verify_path("/opt/misc/certificates");
auto websocket_secure_ = std::make_shared<websocket::stream<ssl::stream<tcp::socket>>>(ioc, ssl_context_);
tcp::resolver resolver_{ioc};
auto const resolve_results = resolver_.resolve("www-my.proxy.int", "8080");
net::connect(websocket_secure_->next_layer().next_layer(), resolve_results.begin(), resolve_results.end());
const std::string HOST_TO_CONNECT_TO = "my.host.com:443";
http::request<http::string_body> request_connect{http::verb::connect, HOST_TO_CONNECT_TO, 11};
request_connect.insert(http::field::proxy_authorization, "Basic dXNlcm5hbWU6cGFzc3dvcmQ=");
request_connect.insert(http::field::host, HOST_TO_CONNECT_TO);
boost::beast::http::write(websocket_secure_->next_layer().next_layer(), request_connect);
As expected, Wireshark shows a HTTP CONNECT followed by a 200 response.
However, attempting to do the SSL handshake afterwards results in a thrown error: “handshake: wrong version number”.
try {
websocket_secure_->next_layer().handshake(ssl::stream_base::client);
} catch (boost::system::system_error& error) {
std::cout << error.what();
throw error;
}
Wireshark shows a Client Hello, followed by a Server Hello, Certificate, Server Key Exchange, Certificate Request, Server Hello Done. The trace looks fine to me and doesn’t differ from a request of my browser to that same website.
The SSL handshake works just fine if I don’t have to tunnel the requests through my proxy.
Why am i getting the thrown error inside my application? Thanks in advance for any help!
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (8 by maintainers)
Ahh I see, that would’ve taken me ages to find 😄 Thank you very much - it’s working as intended (for now) 😃
Ahh… I see. You have to tell Beast that you are not expecting a body, otherwise Beast has no way to know that you are reading the response to a CONNECT request. See: https://www.boost.org/doc/libs/1_71_0/libs/beast/doc/html/beast/ref/boost__beast__http__basic_parser/skip/overload2.html
I was using the approach you suggested, calling the http::read posted above right after writing the CONNECT request to the proxy server. However, read never returns, so I’m wondering if I might be using the wrong arguments to that function call? I was expecting to read back the 200 code.
Well, that’s why your program is failing. The SSL implementation is expecting to see a TLS record but instead, it is seeing the HTTP response from the proxy. You have to read the responds from the stream before you perform the TLS handshake.