diff options
-rw-r--r-- | .SRCINFO | 4 | ||||
-rw-r--r-- | PKGBUILD | 5 | ||||
-rw-r--r-- | telegram-http-proxy-fix.patch | 226 |
3 files changed, 233 insertions, 2 deletions
@@ -1,7 +1,7 @@ pkgbase = yass-proxy pkgdesc = lightweight http/socks proxy pkgver = 1.10.0 - pkgrel = 1 + pkgrel = 2 url = https://github.com/Chilledheart/yass arch = x86_64 license = GPL-2.0-only @@ -29,7 +29,9 @@ pkgbase = yass-proxy conflicts = yass-proxy-git source = https://github.com/Chilledheart/yass/releases/download/1.10.0/yass-1.10.0.tar.bz2 source = libcxx-gcc-14.patch + source = telegram-http-proxy-fix.patch sha256sums = 3140611a5f70148664fd54cb2db8aa6b178395eeec56ffdc6b5dd22b011e0a6f sha256sums = 72f55c55adb141d31dd9cd892cd04a08df2d95a1d94ad3a4b421a312075782e4 + sha256sums = 8d8ef6f29774609c5457354afc6b7a314eaef9eb753edcfd4a86cab8f20693ff pkgname = yass-proxy @@ -3,7 +3,7 @@ pkgname=yass-proxy pkgver=1.10.0 -pkgrel=1 +pkgrel=2 _pkgver=1.10.0 _pkgrel=1 pkgdesc="lightweight http/socks proxy" @@ -18,15 +18,18 @@ provides=(yass-proxy) conflicts=(yass-proxy-git) source=("https://github.com/Chilledheart/yass/releases/download/${_pkgver}/yass-${_pkgver}.tar.bz2" "libcxx-gcc-14.patch" + "telegram-http-proxy-fix.patch" ) sha256sums=('3140611a5f70148664fd54cb2db8aa6b178395eeec56ffdc6b5dd22b011e0a6f' '72f55c55adb141d31dd9cd892cd04a08df2d95a1d94ad3a4b421a312075782e4' + '8d8ef6f29774609c5457354afc6b7a314eaef9eb753edcfd4a86cab8f20693ff' ) prepare() { SRC_DIR="${srcdir}/yass-${_pkgver}" pushd $SRC_DIR patch --forward --strip=1 --input=../libcxx-gcc-14.patch + patch --forward --strip=1 --input=../telegram-http-proxy-fix.patch cd tools go build cd .. diff --git a/telegram-http-proxy-fix.patch b/telegram-http-proxy-fix.patch new file mode 100644 index 000000000000..5d59aef3bb79 --- /dev/null +++ b/telegram-http-proxy-fix.patch @@ -0,0 +1,226 @@ +diff --git a/src/cli/cli_connection.cpp b/src/cli/cli_connection.cpp +index 6384629d..aae9f7e2 100644 +--- a/src/cli/cli_connection.cpp ++++ b/src/cli/cli_connection.cpp +@@ -708,6 +708,8 @@ asio::error_code CliConnection::OnReadHttpRequest(std::shared_ptr<IOBuf> buf) { + << " http: " << std::string(reinterpret_cast<const char*>(buf->data()), nparsed); + } + ++ http_is_keep_alive_ = false; ++ + if (ok) { + buf->trimStart(nparsed); + buf->retreat(nparsed); +@@ -722,7 +724,10 @@ asio::error_code CliConnection::OnReadHttpRequest(std::shared_ptr<IOBuf> buf) { + buf->reserve(header.size(), 0); + buf->prepend(header.size()); + memcpy(buf->mutable_data(), header.c_str(), header.size()); +- VLOG(3) << "Connection (client) " << connection_id() << " Host: " << http_host_ << " PORT: " << http_port_; ++ http_is_keep_alive_ = absl::AsciiStrToLower(parser.connection()) == "keep-alive"; ++ http_keep_alive_remaining_bytes_ += parser.content_length() + header.size() - buf->length(); ++ VLOG(3) << "Connection (client) " << connection_id() << " Host: " << http_host_ << " PORT: " << http_port_ ++ << " KEEPALIVE: " << std::boolalpha << http_is_keep_alive_; + } else { + VLOG(3) << "Connection (client) " << connection_id() << " CONNECT: " << http_host_ << " PORT: " << http_port_; + } +@@ -1614,6 +1619,20 @@ std::shared_ptr<IOBuf> CliConnection::GetNextUpstreamBuf(asio::error_code& ec, s + return nullptr; + } + ++ if (http_is_keep_alive_) { ++ if (http_keep_alive_remaining_bytes_ < (int64_t)read) { ++ VLOG(1) << "Connection (client) " << connection_id() << " reused for keep-alive connection"; ++ // currently, we assume the host doesn't change ++ ec = OnReadHttpRequest(buf); ++ SetState(state_stream); ++ if (ec) { ++ return nullptr; ++ } ++ } else { ++ http_keep_alive_remaining_bytes_ -= read; ++ } ++ } ++ + #ifdef HAVE_QUICHE + if (adapter_) { + if (!data_frame_) { +@@ -2129,7 +2148,7 @@ void CliConnection::connected() { + std::string hdr = absl::StrFormat( + "CONNECT %s HTTP/1.1\r\n" + "Host: %s\r\n" +- "Proxy-Connection: Keep-Alive\r\n" ++ "Proxy-Connection: Close\r\n" + "\r\n", + hostname_and_port.c_str(), hostname_and_port.c_str()); + // write variable address directly as https header +diff --git a/src/cli/cli_connection.hpp b/src/cli/cli_connection.hpp +index e207b053..75a58c53 100644 +--- a/src/cli/cli_connection.hpp ++++ b/src/cli/cli_connection.hpp +@@ -348,6 +348,10 @@ class CliConnection : public RefCountedThreadSafe<CliConnection>, + bool http_is_connect_ = false; + /// copy of connect response + static const std::string_view http_connect_reply_; ++ /// copy of keep alive state ++ bool http_is_keep_alive_ = false; ++ /// copy of remaining bytes in keep alive cycle ++ int64_t http_keep_alive_remaining_bytes_ = 0; + + /// copy of upstream request + std::unique_ptr<ss::request> ss_request_; +diff --git a/src/net/http_parser.cpp b/src/net/http_parser.cpp +index 8c46ff9c..ce8e1adb 100644 +--- a/src/net/http_parser.cpp ++++ b/src/net/http_parser.cpp +@@ -49,6 +49,15 @@ static void ReforgeHttpRequestImpl(std::string* header, + if (key == "Proxy-Connection") { + continue; + } ++ if (key == "Proxy-Authorization") { ++ continue; ++ } ++ if (additional_headers) { ++ auto has_key = [&](const std::pair<std::string, std::string>& rhs) { return rhs.first == key; }; ++ if (std::find_if(additional_headers->begin(), additional_headers->end(), has_key) != additional_headers->end()) { ++ continue; ++ } ++ } + ss << key << ": " << value << "\r\n"; + } + if (additional_headers) { +@@ -265,6 +274,9 @@ void HttpRequestParser::ProcessHeaders(const quiche::BalsaHeaders& headers) { + if (key == "Content-Type") { + content_type_ = std::string(value); + } ++ if (key == "Connection") { ++ connection_ = std::string(value); ++ } + } + } + +@@ -315,6 +327,11 @@ void HttpRequestParser::OnRequestFirstLineInput(std::string_view /*line_input*/, + error_message_ = "HPE_INVALID_VERSION"; + return; + } ++ if (version_input == "HTTP/1.1") { ++ connection_ = "Keep-Alive"; ++ } else { ++ connection_ = "Close"; ++ } + } + + void HttpRequestParser::OnResponseFirstLineInput(std::string_view /*line_input*/, +@@ -481,6 +498,12 @@ int HttpRequestParser::OnReadHttpRequestURL(http_parser* p, const char* buf, siz + } + self->http_is_connect_ = true; + } ++ ++ if (p->http_major == 1 && p->http_minor == 1) { ++ self->connection_ = "Keep-Alive"; ++ } else { ++ self->connection_ = "Close"; ++ } + return 0; + } + +@@ -526,6 +549,9 @@ int HttpRequestParser::OnReadHttpRequestHeaderValue(http_parser* parser, const c + if (self->http_field_ == "Content-Type") { + self->content_type_ = std::string(buf, len); + } ++ if (self->http_field_ == "Connection") { ++ self->connection_ = std::string(buf, len); ++ } + return 0; + } + +diff --git a/src/net/http_parser.hpp b/src/net/http_parser.hpp +index 94ef4893..8146cbac 100644 +--- a/src/net/http_parser.hpp ++++ b/src/net/http_parser.hpp +@@ -49,6 +49,7 @@ class HttpRequestParser : public quiche::BalsaVisitorInterface { + bool is_connect() const { return http_is_connect_; } + uint64_t content_length() const { return content_length_; } + const std::string& content_type() const { return content_type_; } ++ const std::string& connection() const { return connection_; } + + void ReforgeHttpRequest(std::string* header, + const absl::flat_hash_map<std::string, std::string>* additional_headers = nullptr); +@@ -102,6 +103,8 @@ class HttpRequestParser : public quiche::BalsaVisitorInterface { + uint64_t content_length_ = 0; + /// copy of content type + std::string content_type_; ++ /// copy of connection ++ std::string connection_; + + bool first_byte_processed_ = false; + bool headers_done_ = false; +@@ -133,6 +136,7 @@ class HttpRequestParser { + bool is_connect() const { return http_is_connect_; } + uint64_t content_length() const { return content_length_; } + const std::string& content_type() const { return content_type_; } ++ const std::string& connection() const { return connection_; } + + int status_code() const; + +@@ -166,6 +170,8 @@ class HttpRequestParser { + uint64_t content_length_ = 0; + /// copy of content type + std::string content_type_; ++ /// copy of connection ++ std::string connection_; + }; + + class HttpResponseParser : public HttpRequestParser { +diff --git a/src/server/server_connection.cpp b/src/server/server_connection.cpp +index 68fd25a7..48f85b51 100644 +--- a/src/server/server_connection.cpp ++++ b/src/server/server_connection.cpp +@@ -626,19 +626,15 @@ void ServerConnection::OnReadHandshakeViaHttps() { + + if (!http_is_connect_) { + absl::flat_hash_map<std::string, std::string> via_headers; ++ via_headers["Connection"s] = "Close"s; + if (!absl::GetFlag(FLAGS_hide_ip)) { +- asio::error_code ec; +- auto peer_endpoint = peer_endpoint_; +- if (ec) { +- LOG(WARNING) << "Failed to retrieve remote endpoint: " << ec; +- } + std::ostringstream ss; +- ss << "for=\"" << peer_endpoint << "\""; ++ ss << "for=\"" << peer_endpoint_ << "\""; + via_headers["Forwarded"s] = ss.str(); + } + // https://datatracker.ietf.org/doc/html/rfc7230#section-5.7.1 + if (!absl::GetFlag(FLAGS_hide_via)) { +- via_headers["Via"s] = "1.1 asio"s; ++ via_headers["Via"s] = "YASS/" YASS_APP_PRODUCT_VERSION; + } + std::string header; + parser.ReforgeHttpRequest(&header, &via_headers); +diff --git a/src/ss_benchmark.cpp b/src/ss_benchmark.cpp +index 02976a5f..99a08c61 100644 +--- a/src/ss_benchmark.cpp ++++ b/src/ss_benchmark.cpp +@@ -223,7 +223,7 @@ void GenerateConnectRequest(std::string_view host, int port_num, IOBuf* buf) { + "CONNECT %s:%d HTTP/1.1\r\n" + "Host: packages.endpointdev.com:443\r\n" + "User-Agent: curl/7.77.0\r\n" +- "Proxy-Connection: Keep-Alive\r\n" ++ "Proxy-Connection: Close\r\n" + "\r\n", + host, port_num); + buf->reserve(request_header.size(), 0); +diff --git a/src/ss_test.cpp b/src/ss_test.cpp +index 201022c4..2c9a673c 100644 +--- a/src/ss_test.cpp ++++ b/src/ss_test.cpp +@@ -294,7 +294,7 @@ void GenerateConnectRequest(std::string_view host, int port_num, IOBuf* buf) { + "CONNECT %s:%d HTTP/1.1\r\n" + "Host: packages.endpointdev.com:443\r\n" + "User-Agent: curl/7.77.0\r\n" +- "Proxy-Connection: Keep-Alive\r\n" ++ "Proxy-Connection: Close\r\n" + "\r\n", + host, port_num); + buf->reserve(request_header.size(), 0); |