Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ extensions/filters/common/original_src @snowp @klarose
/*/extensions/transport_sockets/common @alyssawilk @wez470
# starttls transport socket
/*/extensions/transport_sockets/starttls @cpakulski @lizan
# proxy transport socket
/*extensions/transport_sockets/http_11_proxy @alyssawilk @ryantheoptimist
# internal upstream transport socket
/*/extensions/transport_sockets/internal_upstream @kyessenov @lambdai
# sni_cluster extension
Expand Down
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ proto_library(
"//envoy/extensions/stat_sinks/graphite_statsd/v3:pkg",
"//envoy/extensions/stat_sinks/wasm/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
"//envoy/extensions/transport_sockets/http_11_proxy/v3:pkg",
"//envoy/extensions/transport_sockets/internal_upstream/v3:pkg",
"//envoy/extensions/transport_sockets/proxy_protocol/v3:pkg",
"//envoy/extensions/transport_sockets/quic/v3:pkg",
Expand Down
12 changes: 12 additions & 0 deletions api/envoy/extensions/transport_sockets/http_11_proxy/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = [
"//envoy/config/core/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
syntax = "proto3";

package envoy.extensions.transport_sockets.http_11_proxy.v3;

import "envoy/config/core/v3/base.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.transport_sockets.http_11_proxy.v3";
option java_outer_classname = "UpstreamHttp11ConnectProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/http_11_proxy/v3;http_11_proxyv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Upstream HTTP/1.1 Proxy]
// [#extension: envoy.transport_sockets.http_11_proxy]

// Configuration for HTTP/1.1 proxy transport sockets.
// This is intended for use in Envoy Mobile, though may eventually be extended
// for upstream Envoy use.
// If this transport socket is configured, and an intermediate filter adds the
// stream info necessary for proxying to the stream info (as the test filter
// does :repo:`here <test/integration/filters/header_to_proxy_filter.cc>`) then
//
// * Upstream connections will be directed to the specified proxy address rather
// than the host's address
// * Upstream TLS connections will have a raw HTTP/1.1 CONNECT header prefaced
// to the payload, and 200 response stripped (if less than 200 bytes)
// * Plaintext HTTP/1.1 connections will be sent with a fully qualified URL.
//
// This transport socket is not compatible with HTTP/3, plaintext HTTP/2, or raw TCP.
message Http11ProxyUpstreamTransport {
// The underlying transport socket being wrapped.
config.core.v3.TransportSocket transport_socket = 1 [(validate.rules).message = {required: true}];
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ proto_library(
"//envoy/extensions/stat_sinks/graphite_statsd/v3:pkg",
"//envoy/extensions/stat_sinks/wasm/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
"//envoy/extensions/transport_sockets/http_11_proxy/v3:pkg",
"//envoy/extensions/transport_sockets/internal_upstream/v3:pkg",
"//envoy/extensions/transport_sockets/proxy_protocol/v3:pkg",
"//envoy/extensions/transport_sockets/quic/v3:pkg",
Expand Down
17 changes: 17 additions & 0 deletions envoy/network/transport_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <vector>

#include "envoy/buffer/buffer.h"
#include "envoy/common/optref.h"
#include "envoy/common/pure.h"
#include "envoy/network/io_handle.h"
#include "envoy/network/listen_socket.h"
Expand Down Expand Up @@ -234,6 +235,22 @@ class TransportSocketOptions {
*/
virtual absl::optional<Network::ProxyProtocolData> proxyProtocolOptions() const PURE;

// Information for use by the http_11_proxy transport socket.
struct Http11ProxyInfo {
Http11ProxyInfo(std::string hostname, Network::Address::InstanceConstSharedPtr address)
: hostname(hostname), proxy_address(address) {}
// The hostname of the original request, to be used in CONNECT request if
// the underlying transport is TLS.
std::string hostname;
// The address of the proxy, where connections should be routed to.
Network::Address::InstanceConstSharedPtr proxy_address;
};

/**
* @return any proxy information if sending to an intermediate proxy over HTTP/1.1.
*/
virtual OptRef<const Http11ProxyInfo> http11ProxyInfo() const PURE;

/**
* @return filter state objects from the downstream request or connection
* that are marked as shared with the upstream connection.
Expand Down
24 changes: 16 additions & 8 deletions source/common/http/codec_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,22 +169,30 @@ void CodecClient::onData(Buffer::Instance& data) {
CodecClientProd::CodecClientProd(CodecType type, Network::ClientConnectionPtr&& connection,
Upstream::HostDescriptionConstSharedPtr host,
Event::Dispatcher& dispatcher,
Random::RandomGenerator& random_generator)
: NoConnectCodecClientProd(type, std::move(connection), host, dispatcher, random_generator) {
Random::RandomGenerator& random_generator,
const Network::TransportSocketOptionsConstSharedPtr& options)
: NoConnectCodecClientProd(type, std::move(connection), host, dispatcher, random_generator,
options) {
connect();
}

NoConnectCodecClientProd::NoConnectCodecClientProd(CodecType type,
Network::ClientConnectionPtr&& connection,
Upstream::HostDescriptionConstSharedPtr host,
Event::Dispatcher& dispatcher,
Random::RandomGenerator& random_generator)
NoConnectCodecClientProd::NoConnectCodecClientProd(
CodecType type, Network::ClientConnectionPtr&& connection,
Upstream::HostDescriptionConstSharedPtr host, Event::Dispatcher& dispatcher,
Random::RandomGenerator& random_generator,
const Network::TransportSocketOptionsConstSharedPtr& options)
: CodecClient(type, std::move(connection), host, dispatcher) {
switch (type) {
case CodecType::HTTP1: {
// If the transport socket indicates this is being proxied, inform the HTTP/1.1 codec. It will
// send fully qualified URLs iff the underlying transport is plaintext.
bool proxied = false;
if (options && options->http11ProxyInfo().has_value()) {
proxied = true;
}
codec_ = std::make_unique<Http1::ClientConnectionImpl>(
*connection_, host->cluster().http1CodecStats(), *this, host->cluster().http1Settings(),
host->cluster().maxResponseHeadersCount());
host->cluster().maxResponseHeadersCount(), proxied);
break;
}
case CodecType::HTTP2: {
Expand Down
7 changes: 4 additions & 3 deletions source/common/http/codec_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ class NoConnectCodecClientProd : public CodecClient {
public:
NoConnectCodecClientProd(CodecType type, Network::ClientConnectionPtr&& connection,
Upstream::HostDescriptionConstSharedPtr host,
Event::Dispatcher& dispatcher,
Random::RandomGenerator& random_generator);
Event::Dispatcher& dispatcher, Random::RandomGenerator& random_generator,
const Network::TransportSocketOptionsConstSharedPtr& options);
};

/**
Expand All @@ -292,7 +292,8 @@ class CodecClientProd : public NoConnectCodecClientProd {
public:
CodecClientProd(CodecType type, Network::ClientConnectionPtr&& connection,
Upstream::HostDescriptionConstSharedPtr host, Event::Dispatcher& dispatcher,
Random::RandomGenerator& random_generator);
Random::RandomGenerator& random_generator,
const Network::TransportSocketOptionsConstSharedPtr& options);
};

} // namespace Http
Expand Down
6 changes: 4 additions & 2 deletions source/common/http/http1/codec_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1325,13 +1325,15 @@ void ServerConnectionImpl::ActiveRequest::dumpState(std::ostream& os, int indent

ClientConnectionImpl::ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
ConnectionCallbacks&, const Http1Settings& settings,
const uint32_t max_response_headers_count)
const uint32_t max_response_headers_count,
bool passing_through_proxy)
: ConnectionImpl(connection, stats, settings, MessageType::Response, MAX_RESPONSE_HEADERS_KB,
max_response_headers_count),
owned_output_buffer_(connection.dispatcher().getWatermarkFactory().createBuffer(
[&]() -> void { this->onBelowLowWatermark(); },
[&]() -> void { this->onAboveHighWatermark(); },
[]() -> void { /* TODO(adisuissa): handle overflow watermark */ })) {
[]() -> void { /* TODO(adisuissa): handle overflow watermark */ })),
passing_through_proxy_(passing_through_proxy) {
owned_output_buffer_->setWatermarks(connection.bufferLimit());
// Inform parent
output_buffer_ = owned_output_buffer_.get();
Expand Down
17 changes: 15 additions & 2 deletions source/common/http/http1/codec_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ class ConnectionImpl : public virtual Connection,
* @return Network::Connection& the backing network connection.
*/
Network::Connection& connection() { return connection_; }
const Network::Connection& connection() const { return connection_; }

/**
* Called when the active encoder has completed encoding the outbound half of the stream.
Expand Down Expand Up @@ -230,7 +231,7 @@ class ConnectionImpl : public virtual Connection,
virtual void maybeAddSentinelBufferFragment(Buffer::Instance&) {}
CodecStats& stats() { return stats_; }
bool enableTrailers() const { return codec_settings_.enable_trailers_; }
bool sendFullyQualifiedUrl() const { return codec_settings_.send_fully_qualified_url_; }
virtual bool sendFullyQualifiedUrl() const { return codec_settings_.send_fully_qualified_url_; }
HeaderKeyFormatterOptConstRef formatter() const {
return makeOptRefFromPtr(encode_only_header_key_formatter_.get());
}
Expand Down Expand Up @@ -563,7 +564,8 @@ class ClientConnectionImpl : public ClientConnection, public ConnectionImpl {
public:
ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
ConnectionCallbacks& callbacks, const Http1Settings& settings,
const uint32_t max_response_headers_count);
const uint32_t max_response_headers_count,
bool passing_through_proxy = false);
// Http::ClientConnection
RequestEncoder& newStream(ResponseDecoder& response_decoder) override;

Expand All @@ -578,6 +580,13 @@ class ClientConnectionImpl : public ClientConnection, public ConnectionImpl {

bool cannotHaveBody();

bool sendFullyQualifiedUrl() const override {
// Send fully qualified URLs either if the parent connection is configured to do so or this
// stream is passing through a proxy and the underlying transport is plaintext.
return ConnectionImpl::sendFullyQualifiedUrl() ||
(passing_through_proxy_ && !connection().ssl());
}

// ParserCallbacks.
Status onUrlBase(const char*, size_t) override { return okStatus(); }
Status onStatusBase(const char* data, size_t length) override;
Expand Down Expand Up @@ -649,6 +658,10 @@ class ClientConnectionImpl : public ClientConnection, public ConnectionImpl {

// The default limit of 80 KiB is the vanilla http_parser behaviour.
static constexpr uint32_t MAX_RESPONSE_HEADERS_KB = 80;

// True if the upstream connection is pointed at an HTTP/1.1 proxy, and
// plaintext HTTP should be sent with fully qualified URLs.
bool passing_through_proxy_ = false;
};

} // namespace Http1
Expand Down
6 changes: 3 additions & 3 deletions source/common/http/http1/conn_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ allocateConnPool(Event::Dispatcher& dispatcher, Random::RandomGenerator& random_
return std::make_unique<ActiveClient>(*pool, absl::nullopt);
},
[](Upstream::Host::CreateConnectionData& data, HttpConnPoolImplBase* pool) {
CodecClientPtr codec{new CodecClientProd(CodecType::HTTP1, std::move(data.connection_),
data.host_description_, pool->dispatcher(),
pool->randomGenerator())};
CodecClientPtr codec{new CodecClientProd(
CodecType::HTTP1, std::move(data.connection_), data.host_description_,
pool->dispatcher(), pool->randomGenerator(), pool->transportSocketOptions())};
return codec;
},
std::vector<Protocol>{Protocol::Http11}, absl::nullopt, nullptr);
Expand Down
6 changes: 3 additions & 3 deletions source/common/http/http2/conn_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ allocateConnPool(Event::Dispatcher& dispatcher, Random::RandomGenerator& random_
return std::make_unique<ActiveClient>(*pool, absl::nullopt);
},
[](Upstream::Host::CreateConnectionData& data, HttpConnPoolImplBase* pool) {
CodecClientPtr codec{new CodecClientProd(CodecType::HTTP2, std::move(data.connection_),
data.host_description_, pool->dispatcher(),
pool->randomGenerator())};
CodecClientPtr codec{new CodecClientProd(
CodecType::HTTP2, std::move(data.connection_), data.host_description_,
pool->dispatcher(), pool->randomGenerator(), pool->transportSocketOptions())};
return codec;
},
std::vector<Protocol>{Protocol::Http2}, origin, cache);
Expand Down
8 changes: 4 additions & 4 deletions source/common/http/http3/conn_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,10 @@ allocateConnPool(Event::Dispatcher& dispatcher, Random::RandomGenerator& random_
"envoy.reloadable_features.postpone_h3_client_connect_to_next_loop")
? std::make_unique<NoConnectCodecClientProd>(
CodecType::HTTP3, std::move(data.connection_), data.host_description_,
pool->dispatcher(), pool->randomGenerator())
: std::make_unique<CodecClientProd>(CodecType::HTTP3, std::move(data.connection_),
data.host_description_, pool->dispatcher(),
pool->randomGenerator());
pool->dispatcher(), pool->randomGenerator(), pool->transportSocketOptions())
: std::make_unique<CodecClientProd>(
CodecType::HTTP3, std::move(data.connection_), data.host_description_,
pool->dispatcher(), pool->randomGenerator(), pool->transportSocketOptions());
return codec;
},
std::vector<Protocol>{Protocol::Http3}, connect_callback, quic_info);
Expand Down
3 changes: 2 additions & 1 deletion source/common/http/mixed_conn_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ CodecClientPtr
HttpConnPoolImplMixed::createCodecClient(Upstream::Host::CreateConnectionData& data) {
auto protocol = protocol_ == Protocol::Http11 ? CodecType::HTTP1 : CodecType::HTTP2;
CodecClientPtr codec{new CodecClientProd(protocol, std::move(data.connection_),
data.host_description_, dispatcher_, random_generator_)};
data.host_description_, dispatcher_, random_generator_,
transportSocketOptions())};
return codec;
}

Expand Down
12 changes: 12 additions & 0 deletions source/common/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ envoy_cc_library(
hdrs = ["transport_socket_options_impl.h"],
deps = [
":application_protocol_lib",
":filter_state_proxy_info_lib",
":proxy_protocol_filter_state_lib",
":upstream_server_name_lib",
":upstream_subject_alt_names_lib",
Expand All @@ -465,6 +466,17 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "filter_state_proxy_info_lib",
srcs = ["filter_state_proxy_info.cc"],
hdrs = ["filter_state_proxy_info.h"],
deps = [
"//envoy/network:address_interface",
"//envoy/stream_info:filter_state_interface",
"//source/common/common:macros",
],
)

envoy_cc_library(
name = "upstream_server_name_lib",
srcs = ["upstream_server_name.cc"],
Expand Down
11 changes: 11 additions & 0 deletions source/common/network/filter_state_proxy_info.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "source/common/network/filter_state_proxy_info.h"

namespace Envoy {
namespace Network {

const std::string& Http11ProxyInfoFilterState::key() {
CONSTRUCT_ON_FIRST_USE(std::string, "envoy.network.transport_socket.http_11_proxy.info");
}

} // namespace Network
} // namespace Envoy
34 changes: 34 additions & 0 deletions source/common/network/filter_state_proxy_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "envoy/network/address.h"
#include "envoy/stream_info/filter_state.h"

#include "absl/strings/string_view.h"

namespace Envoy {
namespace Network {

/**
* Information which filters can add if they detect the stream should go
* upstream through an HTTP/1.1 proxy.
*/
class Http11ProxyInfoFilterState : public StreamInfo::FilterState::Object {
public:
// Returns the key for looking up the Http11ProxyInfoFilterState in the FilterState.
static const std::string& key();

Http11ProxyInfoFilterState(absl::string_view hostname,
Network::Address::InstanceConstSharedPtr address)
: hostname_(hostname), address_(address) {}
Network::Address::InstanceConstSharedPtr address() const { return address_; }
const std::string& hostname() const { return hostname_; }

private:
// The hostname of this individual request.
const std::string hostname_;
// The address of the proxy.
const Network::Address::InstanceConstSharedPtr address_;
};

} // namespace Network
} // namespace Envoy
Loading