Skip to content

Commit 101d324

Browse files
committed
chore: bump version to 0.7.13 and enhance CloudTunnel connection security
- Updated version number to 0.7.13 in VERSION file. - Improved CloudTunnel connection handling by pinning TLS version to 1.2 to avoid issues with certain edge cases in application data transmission. - Set ALPN to "http/1.1" in the TLS ClientHello to prevent bot-like fingerprinting and ensure compatibility with Cloudflare and other edge networks. - Added User-Agent header to WebSocket requests for better identification in cloud-side logs.
1 parent b09ab7f commit 101d324

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.7.12
1+
0.7.13

src/daemon/cloud_tunnel.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,34 @@ bool CloudTunnel::Connect(std::string* error) {
594594
if (error) *error = "SSL_CTX_new failed";
595595
return false;
596596
}
597+
// Pin TLS 1.2 (both ends). Why not 1.3:
598+
// In TLS 1.3 the client is allowed to start sending application
599+
// data ("1-RTT early write") immediately after its Finished,
600+
// without waiting for the server to acknowledge. OpenSSL takes
601+
// advantage of this and packs Finished + the first SSL_write()
602+
// call into the same TLS record. Cloudflare's edge has been
603+
// observed to reset (TCP RST after a tiny encrypted alert) when
604+
// the very first byte of application data lands in that same
605+
// record on certain hostnames, even though the behaviour is
606+
// spec-compliant. Forcing TLS 1.2 here removes that window:
607+
// in 1.2 the client must wait for the server's CCS+Finished
608+
// before any application data, so the GET ... Upgrade reaches
609+
// CF in a clean record and the WebSocket handshake completes.
610+
//
611+
// We still keep the 1.2 floor we already had, so older edge
612+
// middleboxes are also fine. If CF ever requires 1.3, revisit
613+
// by adding a manual post-handshake read or SSL_set_mode flag
614+
// that disables the coalescing.
597615
SSL_CTX_set_min_proto_version(ssl_ctx_, TLS1_2_VERSION);
616+
SSL_CTX_set_max_proto_version(ssl_ctx_, TLS1_2_VERSION);
598617
SSL_CTX_set_default_verify_paths(ssl_ctx_);
599618
SSL_CTX_set_verify(ssl_ctx_, SSL_VERIFY_PEER, nullptr);
619+
// Advertise ALPN "http/1.1" on the TLS ClientHello. CF and other
620+
// edges sometimes treat a missing ALPN as a bot-like fingerprint;
621+
// browsers + curl always send one. Pinning http/1.1 also keeps
622+
// us off any future h2/h3 negotiation path we don't speak.
623+
static const unsigned char kAlpnHttp11[] = {8, 'h','t','t','p','/','1','.','1'};
624+
SSL_CTX_set_alpn_protos(ssl_ctx_, kAlpnHttp11, sizeof(kAlpnHttp11));
600625
ssl_ = SSL_new(ssl_ctx_);
601626
if (!ssl_) {
602627
Disconnect();
@@ -630,7 +655,12 @@ bool CloudTunnel::Connect(std::string* error) {
630655
const bool default_port = (url.tls && url.port == "443") ||
631656
(!url.tls && url.port == "80");
632657
if (!default_port) request << ":" << url.port;
658+
// User-Agent identifies us in cloud-side logs and avoids any edge
659+
// network (Cloudflare bot fight mode etc.) that disfavours
660+
// UA-less clients. Format follows the tenboxd/<version> convention
661+
// used by host_updater's apt invocation.
633662
request << "\r\n"
663+
<< "User-Agent: tenboxd/" << TENBOX_VERSION << "\r\n"
634664
<< "Upgrade: websocket\r\n"
635665
<< "Connection: Upgrade\r\n"
636666
<< "Sec-WebSocket-Version: 13\r\n"

0 commit comments

Comments
 (0)