Add --key_proxy option to masque_tcp_server This doesn't make much sense given a traditional OHTTP architecture, but it helps us work around a bug where the OHTTP key fetch requires mTLS. PiperOrigin-RevId: 847140885
diff --git a/quiche/quic/masque/masque_tcp_server_bin.cc b/quiche/quic/masque/masque_tcp_server_bin.cc index f43e9d2..83a7baa 100644 --- a/quiche/quic/masque/masque_tcp_server_bin.cc +++ b/quiche/quic/masque/masque_tcp_server_bin.cc
@@ -85,6 +85,14 @@ "\"/foo>https://foo.example:8443/|/bar>https://example.com/bar\"."); DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, key_proxy, "", + "Enables and configures proxying of OHTTP key requests. The format is a " + "list of (path, URL) pairs where each local path is proxied to the " + "corresponding " + "URL, formatted as \"path1>url1|path2>url2\". For example: " + "\"/foo>https://foo.example:8443/|/bar>https://example.com/bar\"."); + +DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, disable_certificate_verification, false, "If true, don't verify the server certificate."); @@ -546,6 +554,26 @@ return absl::OkStatus(); } + absl::Status HandleOhttpKeyProxyRequest(MasqueH2Connection* connection, + int32_t stream_id, + const QuicUrl& key_proxy_url) { + Message request; + request.headers[":method"] = "GET"; + request.headers[":scheme"] = key_proxy_url.scheme(); + request.headers[":authority"] = key_proxy_url.HostPort(); + request.headers[":path"] = key_proxy_url.path(); + request.headers["accept"] = "application/ohttp-keys"; + absl::StatusOr<RequestId> request_id = + connection_pool_.SendRequest(request); + QUICHE_RETURN_IF_ERROR(request_id.status()); + QUICHE_LOG(INFO) << "Sent relayed request"; + PendingRequest pending_request; + pending_request.connection = connection; + pending_request.stream_id = stream_id; + pending_requests_.insert({*request_id, std::move(pending_request)}); + return absl::OkStatus(); + } + void OnRequest(MasqueH2Connection* connection, int32_t stream_id, const quiche::HttpHeaderBlock& headers, const std::string& body) override { @@ -566,6 +594,21 @@ response_headers[":status"] = "200"; response_headers["content-type"] = "application/ohttp-keys"; response_body = masque_ohttp_gateway_->concatenated_keys(); + } else if (auto key_proxy_pair = key_proxy_urls_.find(path_pair->second); + key_proxy_pair != key_proxy_urls_.end() && + method_pair->second == "GET" && accept_pair != headers.end() && + accept_pair->second == "application/ohttp-keys" && + body.empty()) { + absl::Status status = HandleOhttpKeyProxyRequest(connection, stream_id, + key_proxy_pair->second); + if (status.ok()) { + return; + } else { + QUICHE_LOG(ERROR) << "Failed to handle OHTTP key proxy request for " + << path_pair->second << ": " << status; + response_headers[":status"] = "500"; + response_body = status.message(); + } } else if (auto relay_pair = relay_gateway_urls_.find(path_pair->second); relay_pair != relay_gateway_urls_.end() && method_pair->second == "POST" && @@ -697,6 +740,35 @@ return true; } + bool SetupKeyProxy(const std::string& key_proxy) { + if (key_proxy.empty()) { + return true; + } + std::vector<absl::string_view> key_proxy_split = + absl::StrSplit(key_proxy, '|'); + for (absl::string_view key_proxy_param : key_proxy_split) { + std::vector<absl::string_view> key_proxy_param_split = + absl::StrSplit(key_proxy_param, '>'); + if (key_proxy_param_split.size() != 2) { + QUICHE_LOG(ERROR) << "Invalid key proxy parameter: \"" + << key_proxy_param + << "\". It should be in the format of \"path>url\""; + return false; + } + absl::string_view path = key_proxy_param_split[0]; + absl::string_view key_proxy_url = key_proxy_param_split[1]; + auto [it, inserted] = key_proxy_urls_.insert( + {std::string(path), QuicUrl(key_proxy_url, "https")}); + if (!inserted) { + QUICHE_LOG(ERROR) << "Duplicate relay path: \"" << path << "\""; + return false; + } + QUICHE_LOG(INFO) << "Added key proxy for " << path << ": " + << key_proxy_url; + } + return true; + } + void SavePendingGatewayRequest( MasqueH2Connection* connection, int32_t stream_id, MasqueConnectionPool::RequestId request_id, @@ -748,6 +820,8 @@ std::vector<std::unique_ptr<MasqueH2SocketConnection>> connections_; // Maps from local paths to remote gateway URLs. absl::flat_hash_map<std::string, QuicUrl> relay_gateway_urls_; + // Maps from local paths to remote key fetch URLs. + absl::flat_hash_map<std::string, QuicUrl> key_proxy_urls_; MasqueConnectionPool connection_pool_; absl::flat_hash_map<RequestId, PendingRequest> pending_requests_; }; @@ -830,6 +904,11 @@ QUICHE_LOG(ERROR) << "Invalid --relay input"; return 1; } + if (!server.SetupKeyProxy( + quiche::GetQuicheCommandLineFlag(FLAGS_key_proxy))) { + QUICHE_LOG(ERROR) << "Invalid --key_proxy input"; + return 1; + } if (!server.SetupSslCtx(server_certificate_file, server_key_file, client_root_ca_file)) { QUICHE_LOG(ERROR) << "Failed to setup SSL context";