Skip to content

Commit 7f86810

Browse files
authored
transport_socket(http_11_proxy): Add config for default proxy address (#42914)
This patch adds an optional config parameter for specifying a default proxy address to be used by the transport socket if a proxy address is not found in the filter state metadata. If the parameter is not set, behavior of the transport socket remains identical to before this patch. Risk Level: Low. New parameter. Testing: unit/integration Docs Changes: config documented Release Notes: done Platform Specific Features: n/a --------- Signed-off-by: Tony Allen <txallen@google.com> Signed-off-by: Tony Allen <tony@allen.gg>
1 parent 6714e71 commit 7f86810

12 files changed

Lines changed: 167 additions & 20 deletions

File tree

api/envoy/extensions/transport_sockets/http_11_proxy/v3/upstream_http_11_connect.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ syntax = "proto3";
22

33
package envoy.extensions.transport_sockets.http_11_proxy.v3;
44

5+
import "envoy/config/core/v3/address.proto";
56
import "envoy/config/core/v3/base.proto";
67

78
import "udpa/annotations/status.proto";
@@ -32,7 +33,14 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
3233
// using the key ``envoy.http11_proxy_transport_socket.proxy_address`` and the
3334
// proxy address in ``config::core::v3::Address`` format.
3435
//
36+
// If the ``default_proxy_address`` is set and proxy address is not found in
37+
// ``typed_filter_metadata``, the default proxy address is used.
38+
//
3539
message Http11ProxyUpstreamTransport {
3640
// The underlying transport socket being wrapped. Defaults to plaintext (raw_buffer) if unset.
3741
config.core.v3.TransportSocket transport_socket = 1;
42+
43+
// Specifies the default proxy address to use if the proxy address is not present in the
44+
// ``typed_filter_metadata`` of the endpoint.
45+
config.core.v3.Address default_proxy_address = 2;
3846
}

changelogs/current.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ new_features:
277277
change: |
278278
Added custom metrics (counters, gauges, histograms) support to load balancer dynamic modules.
279279
Modules can now define metrics during configuration and record them during host selection.
280+
- area: http_11_proxy
281+
change: |
282+
Added ability to configure a default proxy address that is used when the proxy address is not
283+
configured via metadata.
280284
- area: golang
281285
change: |
282286
Added ``DownstreamSslConnection()`` method to the Golang HTTP filter's ``StreamInfo`` interface,

envoy/network/transport_socket.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,13 @@ class UpstreamTransportSocketFactory : public virtual TransportSocketFactoryBase
314314
createTransportSocket(TransportSocketOptionsConstSharedPtr options,
315315
std::shared_ptr<const Upstream::HostDescription> host) const PURE;
316316

317+
/**
318+
* @return the default Http11ProxyInfo if configured, or nullopt.
319+
*/
320+
virtual OptRef<const TransportSocketOptions::Http11ProxyInfo> defaultHttp11ProxyInfo() const {
321+
return {};
322+
}
323+
317324
/**
318325
* Returns true if the transport socket created by this factory supports some form of ALPN
319326
* negotiation.

source/common/upstream/upstream_impl.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ Host::CreateConnectionData HostImplBase::createHealthCheckConnection(
575575

576576
absl::optional<Network::Address::InstanceConstSharedPtr> HostImplBase::maybeGetProxyRedirectAddress(
577577
const Network::TransportSocketOptionsConstSharedPtr transport_socket_options,
578-
HostDescriptionConstSharedPtr host) {
578+
HostDescriptionConstSharedPtr host,
579+
const Network::UpstreamTransportSocketFactory& socket_factory) {
579580
if (transport_socket_options && transport_socket_options->http11ProxyInfo().has_value()) {
580581
return transport_socket_options->http11ProxyInfo()->proxy_address;
581582
}
@@ -618,6 +619,11 @@ absl::optional<Network::Address::InstanceConstSharedPtr> HostImplBase::maybeGetP
618619
return resolve_status.value();
619620
}
620621

622+
// Proxy address was not found in the metadata. If a default proxy address is set, return that.
623+
if (socket_factory.defaultHttp11ProxyInfo().has_value()) {
624+
return socket_factory.defaultHttp11ProxyInfo()->proxy_address;
625+
}
626+
621627
return absl::nullopt;
622628
}
623629

@@ -632,7 +638,7 @@ Host::CreateConnectionData HostImplBase::createConnection(
632638
auto source_address_selector = cluster.getUpstreamLocalAddressSelector();
633639

634640
absl::optional<Network::Address::InstanceConstSharedPtr> proxy_address =
635-
maybeGetProxyRedirectAddress(transport_socket_options, host);
641+
maybeGetProxyRedirectAddress(transport_socket_options, host, socket_factory);
636642

637643
Network::ClientConnectionPtr connection;
638644
// If the transport socket options or endpoint/locality metadata indicate the connection should

source/common/upstream/upstream_impl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,8 @@ class HostImplBase : public Host,
450450
HostDescriptionConstSharedPtr host);
451451
static absl::optional<Network::Address::InstanceConstSharedPtr> maybeGetProxyRedirectAddress(
452452
const Network::TransportSocketOptionsConstSharedPtr transport_socket_options,
453-
HostDescriptionConstSharedPtr host);
453+
HostDescriptionConstSharedPtr host,
454+
const Network::UpstreamTransportSocketFactory& socket_factory);
454455

455456
private:
456457
// Helper function to check multiple health flags at once.

source/extensions/transport_sockets/http_11_proxy/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ envoy_cc_extension(
2222
"//envoy/registry",
2323
"//envoy/server:transport_socket_config_interface",
2424
"//source/common/config:utility_lib",
25+
"//source/common/network:resolver_lib",
2526
"@envoy_api//envoy/extensions/transport_sockets/http_11_proxy/v3:pkg_cc_proto",
2627
],
2728
)

source/extensions/transport_sockets/http_11_proxy/config.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "envoy/registry/registry.h"
66

77
#include "source/common/config/utility.h"
8+
#include "source/common/network/address_impl.h"
9+
#include "source/common/network/resolver_impl.h"
810
#include "source/extensions/transport_sockets/http_11_proxy/connect.h"
911

1012
namespace Envoy {
@@ -16,17 +18,30 @@ absl::StatusOr<Network::UpstreamTransportSocketFactoryPtr>
1618
UpstreamHttp11ConnectSocketConfigFactory::createTransportSocketFactory(
1719
const Protobuf::Message& message,
1820
Server::Configuration::TransportSocketFactoryContext& context) {
21+
1922
const auto& outer_config = MessageUtil::downcastAndValidate<
2023
const envoy::extensions::transport_sockets::http_11_proxy::v3::Http11ProxyUpstreamTransport&>(
2124
message, context.messageValidationVisitor());
25+
26+
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info;
27+
if (outer_config.has_default_proxy_address()) {
28+
auto address_or_error =
29+
Network::Address::resolveProtoAddress(outer_config.default_proxy_address());
30+
RETURN_IF_NOT_OK_REF(address_or_error.status());
31+
// Hostname is unknown here, so we leave it empty. It will be filled in
32+
// UpstreamHttp11ConnectSocket constructor from the host.
33+
proxy_info.emplace("", address_or_error.value());
34+
}
35+
2236
auto& inner_config_factory = Config::Utility::getAndCheckFactory<
2337
Server::Configuration::UpstreamTransportSocketConfigFactory>(outer_config.transport_socket());
2438
ProtobufTypes::MessagePtr inner_factory_config = Config::Utility::translateToFactoryConfig(
2539
outer_config.transport_socket(), context.messageValidationVisitor(), inner_config_factory);
2640
auto factory_or_error =
2741
inner_config_factory.createTransportSocketFactory(*inner_factory_config, context);
2842
RETURN_IF_NOT_OK_REF(factory_or_error.status());
29-
return std::make_unique<UpstreamHttp11ConnectSocketFactory>(std::move(factory_or_error.value()));
43+
return std::make_unique<UpstreamHttp11ConnectSocketFactory>(std::move(factory_or_error.value()),
44+
proxy_info);
3045
}
3146

3247
ProtobufTypes::MessagePtr UpstreamHttp11ConnectSocketConfigFactory::createEmptyConfigProto() {

source/extensions/transport_sockets/http_11_proxy/connect.cc

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,24 @@ bool UpstreamHttp11ConnectSocket::isValidConnectResponse(absl::string_view respo
3232
UpstreamHttp11ConnectSocket::UpstreamHttp11ConnectSocket(
3333
Network::TransportSocketPtr&& transport_socket,
3434
Network::TransportSocketOptionsConstSharedPtr options,
35-
std::shared_ptr<const Upstream::HostDescription> host)
35+
std::shared_ptr<const Upstream::HostDescription> host,
36+
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info)
3637
: PassthroughSocket(std::move(transport_socket)), options_(options) {
3738
// If the filter state metadata has populated the relevant entries in the transport socket
3839
// options, we want to maintain the original behavior of this transport socket.
3940
if (options_ && options_->http11ProxyInfo()) {
40-
handleProxyInfoConnect();
41+
handleProxyInfoConnect(options_->http11ProxyInfo().value());
42+
return;
43+
}
44+
45+
if (proxy_info.has_value()) {
46+
Network::TransportSocketOptions::Http11ProxyInfo actual_info = proxy_info.value();
47+
if (actual_info.hostname.empty() && host) {
48+
actual_info.hostname = host->hostname().empty() ? host->address()->asStringView()
49+
: absl::StrCat(host->hostname(), ":",
50+
host->address()->ip()->port());
51+
}
52+
handleProxyInfoConnect(actual_info);
4153
return;
4254
}
4355

@@ -61,11 +73,11 @@ std::string UpstreamHttp11ConnectSocket::formatConnectRequest(absl::string_view
6173
return absl::StrCat("CONNECT ", target, " HTTP/1.1\r\n", "Host: ", target, "\r\n\r\n");
6274
}
6375

64-
inline void UpstreamHttp11ConnectSocket::handleProxyInfoConnect() {
76+
inline void UpstreamHttp11ConnectSocket::handleProxyInfoConnect(
77+
const Network::TransportSocketOptions::Http11ProxyInfo& proxy_info) {
6578
if (transport_socket_->ssl()) {
6679
std::string target = absl::StrCat(
67-
options_->http11ProxyInfo()->hostname,
68-
Http::HeaderUtility::hostHasPort(options_->http11ProxyInfo()->hostname) ? "" : ":443");
80+
proxy_info.hostname, Http::HeaderUtility::hostHasPort(proxy_info.hostname) ? "" : ":443");
6981

7082
if (!Runtime::runtimeFeatureEnabled(
7183
"envoy.reloadable_features.http_11_proxy_connect_legacy_format")) {
@@ -192,8 +204,9 @@ Network::IoResult UpstreamHttp11ConnectSocket::writeHeader() {
192204
}
193205

194206
UpstreamHttp11ConnectSocketFactory::UpstreamHttp11ConnectSocketFactory(
195-
Network::UpstreamTransportSocketFactoryPtr transport_socket_factory)
196-
: PassthroughFactory(std::move(transport_socket_factory)) {}
207+
Network::UpstreamTransportSocketFactoryPtr transport_socket_factory,
208+
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info)
209+
: PassthroughFactory(std::move(transport_socket_factory)), proxy_info_(proxy_info) {}
197210

198211
Network::TransportSocketPtr UpstreamHttp11ConnectSocketFactory::createTransportSocket(
199212
Network::TransportSocketOptionsConstSharedPtr options,
@@ -202,7 +215,8 @@ Network::TransportSocketPtr UpstreamHttp11ConnectSocketFactory::createTransportS
202215
if (inner_socket == nullptr) {
203216
return nullptr;
204217
}
205-
return std::make_unique<UpstreamHttp11ConnectSocket>(std::move(inner_socket), options, host);
218+
return std::make_unique<UpstreamHttp11ConnectSocket>(std::move(inner_socket), options, host,
219+
proxy_info_);
206220
}
207221

208222
void UpstreamHttp11ConnectSocketFactory::hashKey(

source/extensions/transport_sockets/http_11_proxy/connect.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ class UpstreamHttp11ConnectSocket : public TransportSockets::PassthroughSocket,
3232
// @return a properly formatted CONNECT request string per RFC 9110 section 9.3.6.
3333
static std::string formatConnectRequest(absl::string_view target);
3434

35-
UpstreamHttp11ConnectSocket(Network::TransportSocketPtr&& transport_socket,
36-
Network::TransportSocketOptionsConstSharedPtr options,
37-
std::shared_ptr<const Upstream::HostDescription> host);
35+
UpstreamHttp11ConnectSocket(
36+
Network::TransportSocketPtr&& transport_socket,
37+
Network::TransportSocketOptionsConstSharedPtr options,
38+
std::shared_ptr<const Upstream::HostDescription> host,
39+
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info = absl::nullopt);
3840

3941
void setTransportSocketCallbacks(Network::TransportSocketCallbacks& callbacks) override;
4042
Network::IoResult doWrite(Buffer::Instance& buffer, bool end_stream) override;
@@ -44,7 +46,8 @@ class UpstreamHttp11ConnectSocket : public TransportSockets::PassthroughSocket,
4446
void generateHeader();
4547
Network::IoResult writeHeader();
4648

47-
inline void handleProxyInfoConnect();
49+
inline void
50+
handleProxyInfoConnect(const Network::TransportSocketOptions::Http11ProxyInfo& proxy_info);
4851
inline void handleHostMetadataConnect(std::shared_ptr<const Upstream::HostDescription> host);
4952

5053
Network::TransportSocketOptionsConstSharedPtr options_;
@@ -56,14 +59,26 @@ class UpstreamHttp11ConnectSocket : public TransportSockets::PassthroughSocket,
5659
class UpstreamHttp11ConnectSocketFactory : public PassthroughFactory {
5760
public:
5861
UpstreamHttp11ConnectSocketFactory(
59-
Network::UpstreamTransportSocketFactoryPtr transport_socket_factory);
62+
Network::UpstreamTransportSocketFactoryPtr transport_socket_factory,
63+
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info = absl::nullopt);
6064

6165
// Network::TransportSocketFactory
6266
Network::TransportSocketPtr
6367
createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options,
6468
std::shared_ptr<const Upstream::HostDescription> host) const override;
6569
void hashKey(std::vector<uint8_t>& key,
6670
Network::TransportSocketOptionsConstSharedPtr options) const override;
71+
72+
OptRef<const Network::TransportSocketOptions::Http11ProxyInfo>
73+
defaultHttp11ProxyInfo() const override {
74+
if (!proxy_info_.has_value()) {
75+
return {};
76+
}
77+
return {proxy_info_.value()};
78+
}
79+
80+
private:
81+
const absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info_;
6782
};
6883

6984
// This is a utility class for isValidConnectResponse. It is only exposed for

test/extensions/transport_sockets/http_11_proxy/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ envoy_extension_cc_test(
3434
extension_names = ["envoy.transport_sockets.http_11_proxy"],
3535
rbe_pool = "2core",
3636
deps = [
37+
"//source/common/network:utility_lib",
3738
"//source/extensions/clusters/dynamic_forward_proxy:cluster",
3839
"//source/extensions/filters/http/dynamic_forward_proxy:config",
3940
"//source/extensions/filters/network/tcp_proxy:config",

0 commit comments

Comments
 (0)