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 docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Minor Behavior Changes
Bug Fixes
---------
*Changes expected to improve the state of the world and are unlikely to have negative effects*
* listener: fix crash when disabling or re-enabling listeners due to overload while processing LDS updates.
* proxy_proto: fixed a bug where the wrong downstream address got sent to upstream connections.

Removed Config or Runtime
-------------------------
Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Version history
:titlesonly:

current
v1.16.0
v1.15.2
v1.15.1
v1.15.0
Expand Down
6 changes: 5 additions & 1 deletion include/envoy/network/proxy_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ namespace Network {
struct ProxyProtocolData {
const Network::Address::InstanceConstSharedPtr src_addr_;
const Network::Address::InstanceConstSharedPtr dst_addr_;
std::string asStringForHash() const {
return std::string(src_addr_ ? src_addr_->asString() : "null") +
(dst_addr_ ? dst_addr_->asString() : "null");
}
};

} // namespace Network
} // namespace Envoy
} // namespace Envoy
16 changes: 12 additions & 4 deletions include/envoy/network/transport_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Envoy {
namespace Network {

class TransportSocketFactory;
class Connection;
enum class ConnectionEvent;

Expand Down Expand Up @@ -198,11 +199,13 @@ class TransportSocketOptions {
virtual absl::optional<Network::ProxyProtocolData> proxyProtocolOptions() const PURE;

/**
* @param vector of bytes to which the option should append hash key data that will be used
* to separate connections based on the option. Any data already in the key vector must
* not be modified.
* @param key supplies a vector of bytes to which the option should append hash key data that will
* be used to separate connections based on the option. Any data already in the key vector
* must not be modified.
* @param factory supplies the factor which will be used for creating the transport socket.
*/
virtual void hashKey(std::vector<uint8_t>& key) const PURE;
virtual void hashKey(std::vector<uint8_t>& key,
const Network::TransportSocketFactory& factory) const PURE;
};

// TODO(mattklein123): Rename to TransportSocketOptionsConstSharedPtr in a dedicated follow up.
Expand All @@ -226,6 +229,11 @@ class TransportSocketFactory {
*/
virtual TransportSocketPtr
createTransportSocket(TransportSocketOptionsSharedPtr options) const PURE;

/**
* @return bool whether the transport socket will use proxy protocol options.
*/
virtual bool usesProxyProtocolOptions() const PURE;
};

using TransportSocketFactoryPtr = std::unique_ptr<TransportSocketFactory>;
Expand Down
1 change: 1 addition & 0 deletions source/common/network/raw_buffer_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class RawBufferSocketFactory : public TransportSocketFactory {
// Network::TransportSocketFactory
TransportSocketPtr createTransportSocket(TransportSocketOptionsSharedPtr options) const override;
bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override { return false; }
};

} // namespace Network
Expand Down
22 changes: 17 additions & 5 deletions source/common/network/transport_socket_options_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
namespace Envoy {
namespace Network {
namespace {
void commonHashKey(const TransportSocketOptions& options, std::vector<std::uint8_t>& key) {
void commonHashKey(const TransportSocketOptions& options, std::vector<std::uint8_t>& key,
const Network::TransportSocketFactory& factory) {
const auto& server_name_overide = options.serverNameOverride();
if (server_name_overide.has_value()) {
pushScalarToByteVector(StringUtil::CaseInsensitiveHash()(server_name_overide.value()), key);
Expand All @@ -35,19 +36,30 @@ void commonHashKey(const TransportSocketOptions& options, std::vector<std::uint8
pushScalarToByteVector(StringUtil::CaseInsensitiveHash()(protocol), key);
}
}

const auto& alpn_fallback = options.applicationProtocolFallback();
if (alpn_fallback.has_value()) {
pushScalarToByteVector(StringUtil::CaseInsensitiveHash()(*alpn_fallback), key);
}

// Proxy protocol options should only be included in the hash if the upstream
// socket intends to use them.
const auto& proxy_protocol_options = options.proxyProtocolOptions();
if (proxy_protocol_options.has_value() && factory.usesProxyProtocolOptions()) {
pushScalarToByteVector(
StringUtil::CaseInsensitiveHash()(proxy_protocol_options.value().asStringForHash()), key);
}
}
} // namespace

void AlpnDecoratingTransportSocketOptions::hashKey(std::vector<uint8_t>& key) const {
commonHashKey(*this, key);
void AlpnDecoratingTransportSocketOptions::hashKey(
std::vector<uint8_t>& key, const Network::TransportSocketFactory& factory) const {
commonHashKey(*this, key, factory);
}

void TransportSocketOptionsImpl::hashKey(std::vector<uint8_t>& key) const {
commonHashKey(*this, key);
void TransportSocketOptionsImpl::hashKey(std::vector<uint8_t>& key,
const Network::TransportSocketFactory& factory) const {
commonHashKey(*this, key, factory);
}

TransportSocketOptionsSharedPtr
Expand Down
6 changes: 4 additions & 2 deletions source/common/network/transport_socket_options_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class AlpnDecoratingTransportSocketOptions : public TransportSocketOptions {
absl::optional<Network::ProxyProtocolData> proxyProtocolOptions() const override {
return inner_options_->proxyProtocolOptions();
}
void hashKey(std::vector<uint8_t>& key) const override;
void hashKey(std::vector<uint8_t>& key,
const Network::TransportSocketFactory& factory) const override;

private:
const absl::optional<std::string> alpn_fallback_;
Expand Down Expand Up @@ -67,7 +68,8 @@ class TransportSocketOptionsImpl : public TransportSocketOptions {
absl::optional<Network::ProxyProtocolData> proxyProtocolOptions() const override {
return proxy_protocol_options_;
}
void hashKey(std::vector<uint8_t>& key) const override;
void hashKey(std::vector<uint8_t>& key,
const Network::TransportSocketFactory& factory) const override;

private:
const absl::optional<std::string> override_server_name_;
Expand Down
4 changes: 2 additions & 2 deletions source/common/upstream/cluster_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::connPool(

bool have_transport_socket_options = false;
if (context && context->upstreamTransportSocketOptions()) {
context->upstreamTransportSocketOptions()->hashKey(hash_key);
context->upstreamTransportSocketOptions()->hashKey(hash_key, host->transportSocketFactory());
have_transport_socket_options = true;
}

Expand Down Expand Up @@ -1440,7 +1440,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::tcpConnPool(
bool have_transport_socket_options = false;
if (context != nullptr && context->upstreamTransportSocketOptions() != nullptr) {
have_transport_socket_options = true;
context->upstreamTransportSocketOptions()->hashKey(hash_key);
context->upstreamTransportSocketOptions()->hashKey(hash_key, host->transportSocketFactory());
}

TcpConnPoolsContainer& container = parent_.host_tcp_conn_pool_map_[host];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class QuicTransportSocketFactoryBase : public Network::TransportSocketFactory {
NOT_REACHED_GCOVR_EXCL_LINE;
}
bool implementsSecureTransport() const override { return true; }
bool usesProxyProtocolOptions() const override { return false; }
};

// TODO(danzh): when implement ProofSource, examine of it's necessary to
Expand Down
1 change: 1 addition & 0 deletions source/extensions/transport_sockets/alts/tsi_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class TsiSocketFactory : public Network::TransportSocketFactory {
TsiSocketFactory(HandshakerFactory handshaker_factory, HandshakeValidator handshake_validator);

bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override { return false; }
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class UpstreamProxyProtocolSocketFactory : public Network::TransportSocketFactor
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override;
bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override { return true; }

private:
Network::TransportSocketFactoryPtr transport_socket_factory_;
Expand All @@ -58,4 +59,4 @@ class UpstreamProxyProtocolSocketFactory : public Network::TransportSocketFactor
} // namespace ProxyProtocol
} // namespace TransportSockets
} // namespace Extensions
} // namespace Envoy
} // namespace Envoy
4 changes: 4 additions & 0 deletions source/extensions/transport_sockets/tap/tap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ bool TapSocketFactory::implementsSecureTransport() const {
return transport_socket_factory_->implementsSecureTransport();
}

bool TapSocketFactory::usesProxyProtocolOptions() const {
return transport_socket_factory_->usesProxyProtocolOptions();
}

} // namespace Tap
} // namespace TransportSockets
} // namespace Extensions
Expand Down
1 change: 1 addition & 0 deletions source/extensions/transport_sockets/tap/tap.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class TapSocketFactory : public Network::TransportSocketFactory,
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override;
bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override;

private:
Network::TransportSocketFactoryPtr transport_socket_factory_;
Expand Down
2 changes: 2 additions & 0 deletions source/extensions/transport_sockets/tls/ssl_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class ClientSslSocketFactory : public Network::TransportSocketFactory,
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override;
bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override { return false; }

// Secret::SecretCallbacks
void onAddOrUpdateSecret() override;
Expand All @@ -132,6 +133,7 @@ class ServerSslSocketFactory : public Network::TransportSocketFactory,
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override;
bool implementsSecureTransport() const override;
bool usesProxyProtocolOptions() const override { return false; }

// Secret::SecretCallbacks
void onAddOrUpdateSecret() override;
Expand Down
12 changes: 12 additions & 0 deletions source/server/connection_handler_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,18 @@ void ConnectionHandlerImpl::ActiveTcpListener::onAcceptWorker(
}
}

void ConnectionHandlerImpl::ActiveTcpListener::pauseListening() {
if (listener_ != nullptr) {
listener_->disable();
}
}

void ConnectionHandlerImpl::ActiveTcpListener::resumeListening() {
if (listener_ != nullptr) {
listener_->enable();
}
}

void ConnectionHandlerImpl::ActiveTcpListener::newConnection(
Network::ConnectionSocketPtr&& socket, std::unique_ptr<StreamInfo::StreamInfo> stream_info) {
// Find matching filter chain.
Expand Down
4 changes: 2 additions & 2 deletions source/server/connection_handler_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ class ConnectionHandlerImpl : public Network::ConnectionHandler,

// ActiveListenerImplBase
Network::Listener* listener() override { return listener_.get(); }
void pauseListening() override { listener_->disable(); }
void resumeListening() override { listener_->enable(); }
void pauseListening() override;
void resumeListening() override;
void shutdownListener() override { listener_.reset(); }

// Network::BalancedConnectionHandler
Expand Down
9 changes: 9 additions & 0 deletions test/common/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ envoy_cc_test(
],
)

envoy_cc_test(
name = "raw_buffer_socket_test",
srcs = ["raw_buffer_socket_test.cc"],
deps = [
"//source/common/network:raw_buffer_socket_lib",
"//test/test_common:network_utility_lib",
],
)

envoy_cc_test_library(
name = "udp_listener_impl_test_base_lib",
hdrs = ["udp_listener_impl_test_base.h"],
Expand Down
16 changes: 16 additions & 0 deletions test/common/network/raw_buffer_socket_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "common/network/raw_buffer_socket.h"

#include "test/test_common/network_utility.h"

#include "gtest/gtest.h"

namespace Envoy {
namespace Network {

TEST(RawBufferSocketFactory, RawBufferSocketFactory) {
TransportSocketFactoryPtr factory = Envoy::Network::Test::createRawBufferSocketFactory();
EXPECT_FALSE(factory->usesProxyProtocolOptions());
}

} // namespace Network
} // namespace Envoy
2 changes: 2 additions & 0 deletions test/common/upstream/transport_socket_matcher_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace {
class FakeTransportSocketFactory : public Network::TransportSocketFactory {
public:
MOCK_METHOD(bool, implementsSecureTransport, (), (const));
MOCK_METHOD(bool, usesProxyProtocolOptions, (), (const));
MOCK_METHOD(Network::TransportSocketPtr, createTransportSocket,
(Network::TransportSocketOptionsSharedPtr), (const));
FakeTransportSocketFactory(std::string id) : id_(std::move(id)) {}
Expand All @@ -46,6 +47,7 @@ class FooTransportSocketFactory
Logger::Loggable<Logger::Id::upstream> {
public:
MOCK_METHOD(bool, implementsSecureTransport, (), (const));
MOCK_METHOD(bool, usesProxyProtocolOptions, (), (const));
MOCK_METHOD(Network::TransportSocketPtr, createTransportSocket,
(Network::TransportSocketOptionsSharedPtr), (const));

Expand Down
6 changes: 5 additions & 1 deletion test/extensions/transport_sockets/alts/tsi_socket_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class TsiSocketTest : public testing::Test {
client_.tsi_socket_ =
std::make_unique<TsiSocket>(client_.handshaker_factory_, client_validator,
Network::TransportSocketPtr{client_.raw_socket_});

ON_CALL(client_.callbacks_.connection_, dispatcher()).WillByDefault(ReturnRef(dispatcher_));
ON_CALL(server_.callbacks_.connection_, dispatcher()).WillByDefault(ReturnRef(dispatcher_));

Expand Down Expand Up @@ -194,6 +193,7 @@ static const std::string ClientToServerData = "hello from client";
TEST_F(TsiSocketTest, DoesNotHaveSsl) {
initialize(nullptr, nullptr);
EXPECT_EQ(nullptr, client_.tsi_socket_->ssl());
EXPECT_FALSE(client_.tsi_socket_->canFlushClose());

const auto& socket_ = *client_.tsi_socket_;
EXPECT_EQ(nullptr, socket_.ssl());
Expand Down Expand Up @@ -406,6 +406,10 @@ TEST_F(TsiSocketFactoryTest, ImplementsSecureTransport) {
EXPECT_TRUE(socket_factory_->implementsSecureTransport());
}

TEST_F(TsiSocketFactoryTest, UsesProxyProtocolOptions) {
EXPECT_FALSE(socket_factory_->usesProxyProtocolOptions());
}

} // namespace
} // namespace Alts
} // namespace TransportSockets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,36 @@ TEST_P(ProxyProtocolIntegrationTest, TestV1ProxyProtocol) {
ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect());
}

TEST_P(ProxyProtocolIntegrationTest, TestV1ProxyProtocolMultipleConnections) {
if (GetParam() != Network::Address::IpVersion::v4) {
return;
}

setup(envoy::config::core::v3::ProxyProtocolConfig::V1, false,
"envoy.transport_sockets.raw_buffer");
initialize();
auto listener_port = lookupPort("listener_0");

auto loopback2 = Network::Utility::resolveUrl("tcp://127.0.0.2:0");
auto tcp_client2 = makeTcpConnection(listener_port, nullptr, loopback2);

auto tcp_client = makeTcpConnection(listener_port);

ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection_));
FakeRawConnectionPtr conn2;
ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(conn2));

std::string data1, data2;
ASSERT_TRUE(
fake_upstream_connection_->waitForData(FakeRawConnection::waitForAtLeastBytes(32), &data1));
ASSERT_TRUE(conn2->waitForData(FakeRawConnection::waitForAtLeastBytes(32), &data2));

EXPECT_NE(data1, data2);

tcp_client->close();
tcp_client2->close();
}

// Test header is sent unencrypted using a TLS inner socket
TEST_P(ProxyProtocolIntegrationTest, TestTLSSocket) {
setup(envoy::config::core::v3::ProxyProtocolConfig::V1, false, "envoy.transport_sockets.tls");
Expand Down Expand Up @@ -201,4 +231,4 @@ TEST_P(ProxyProtocolIntegrationTest, TestV2ProxyProtocol) {
}

} // namespace
} // namespace Envoy
} // namespace Envoy
Loading