Skip to content

Commit

Permalink
add matching types for network streams
Browse files Browse the repository at this point in the history
Signed-off-by: Kuat Yessenov <kuat@google.com>
  • Loading branch information
kyessenov committed Jan 11, 2022
1 parent b2a9429 commit aea58eb
Show file tree
Hide file tree
Showing 6 changed files with 419 additions and 0 deletions.
83 changes: 83 additions & 0 deletions api/envoy/type/matcher/v3/network_inputs.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
syntax = "proto3";

package envoy.type.matcher.v3;

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

option java_package = "io.envoyproxy.envoy.type.matcher.v3";
option java_outer_classname = "NetworkInputsProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3;matcherv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Common Network Matching Inputs]

// Specifies that matching should be performed by the destination IP address.
message DestinationIPInput {
}

// Specifies that matching should be performed by the destination port.
message DestinationPortInput {
}

// Specifies that matching should be performed by the source IP address.
message SourceIPInput {
}

// Specifies that matching should be performed by the source port.
message SourcePortInput {
}

// Input that matches by the directly connected source IP address (this
// will only be different from the source IP address when using a listener
// filter that overrides the source address, such as the :ref:`Proxy Protocol
// listener filter <config_listener_filters_proxy_protocol>`).
message DirectSourceIPInput {
}

// Input that matches by the source IP type.
// Specifies the source IP match type. The values include:
//
// * ``local`` - matches a connection originating from the same host,
message SourceTypeInput {
}

// Input that matches by the requested server name (e.g. SNI in TLS), when detected by one of the listener filters.
//
// :ref:`TLS Inspector <config_listener_filters_tls_inspector>` provides the requested server name based on SNI.
message ServerNameInput {
}

// Input that matches by the transport protocol, when
// detected by one of the listener filters.
//
// Suggested values include:
//
// * ``raw_buffer`` - default, used when no transport protocol is detected,
// * ``tls`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>`
// when TLS protocol is detected.
message TransportProtocolInput {
}

// List of comma-separated requested application protocols, when detected by one of the listener filters.
//
// Suggested values in the list include:
//
// * ``http/1.1`` - set by :ref:`envoy.filters.listener.tls_inspector
// <config_listener_filters_tls_inspector>` and :ref:`envoy.filters.listener.http_inspector
// <config_listener_filters_http_inspector>`,
// * ``h2`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>`
// * ``h2c`` - set by :ref:`envoy.filters.listener.http_inspector <config_listener_filters_http_inspector>`
//
// .. attention::
//
// Currently, :ref:`TLS Inspector <config_listener_filters_tls_inspector>` provides
// application protocol detection based on the requested
// `ALPN <https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation>`_ values.
//
// However, the use of ALPN is pretty much limited to the HTTP/2 traffic on the Internet,
// and matching on values other than ``h2`` is going to lead to a lot of false negatives,
// unless all connecting clients are known to use ALPN.
message ApplicationProtocolInput {
}
4 changes: 4 additions & 0 deletions envoy/network/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ class FilterChainFactory {
class MatchingData {
public:
static absl::string_view name() { return "network"; }

virtual ~MatchingData() = default;

virtual const ConnectionSocket& socket() const PURE;
};

} // namespace Network
Expand Down
30 changes: 30 additions & 0 deletions source/common/network/matching/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

licenses(["notice"]) # Apache 2

envoy_package()

envoy_cc_library(
name = "data_impl_lib",
hdrs = ["data_impl.h"],
deps = [
"//envoy/network:filter_interface",
],
)

envoy_cc_library(
name = "inputs_lib",
srcs = ["inputs.cc"],
hdrs = ["inputs.h"],
deps = [
"//envoy/matcher:matcher_interface",
"//envoy/network:filter_interface",
"//envoy/registry",
"//source/common/network:utility_lib",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
)
27 changes: 27 additions & 0 deletions source/common/network/matching/data_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "envoy/network/filter.h"

namespace Envoy {
namespace Network {
namespace Matching {

/**
* Implementation of Network::MatchingData, providing connection-level data to
* the match tree.
*/
class MatchingDataImpl : public MatchingData {
public:
static absl::string_view name() { return "network"; }

void onSocket(const ConnectionSocket& socket) { socket_ = &socket; }

virtual const ConnectionSocket& socket() { return *socket_; }

private:
const ConnectionSocket* socket_{};
};

} // namespace Matching
} // namespace Network
} // namespace Envoy
99 changes: 99 additions & 0 deletions source/common/network/matching/inputs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "source/common/network/matching/inputs.h"

#include "envoy/registry/registry.h"

#include "source/common/network/utility.h"

#include "absl/strings/str_cat.h"

namespace Envoy {
namespace Network {
namespace Matching {

Matcher::DataInputGetResult DestinationIPInput::get(const MatchingData& data) const {
const auto& address = data.socket().connectionInfoProvider().localAddress();
if (address->type() != Network::Address::Type::Ip) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
address->ip()->addressAsString()};
}

Matcher::DataInputGetResult DestinationPortInput::get(const MatchingData& data) const {
const auto& address = data.socket().connectionInfoProvider().localAddress();
if (address->type() != Network::Address::Type::Ip) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
absl::StrCat(address->ip()->port())};
}

Matcher::DataInputGetResult SourceIPInput::get(const MatchingData& data) const {
const auto& address = data.socket().connectionInfoProvider().remoteAddress();
if (address->type() != Network::Address::Type::Ip) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
address->ip()->addressAsString()};
}

Matcher::DataInputGetResult SourcePortInput::get(const MatchingData& data) const {
const auto& address = data.socket().connectionInfoProvider().remoteAddress();
if (address->type() != Network::Address::Type::Ip) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
absl::StrCat(address->ip()->port())};
}

Matcher::DataInputGetResult DirectSourceIPInput::get(const MatchingData& data) const {
const auto& address = data.socket().connectionInfoProvider().directRemoteAddress();
if (address->type() != Network::Address::Type::Ip) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
address->ip()->addressAsString()};
}

Matcher::DataInputGetResult SourceTypeInput::get(const MatchingData& data) const {
const bool is_local_connection = Network::Utility::isSameIpOrLoopback(data.socket());
if (is_local_connection) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, "local"};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}

Matcher::DataInputGetResult ServerNameInput::get(const MatchingData& data) const {
if (!data.socket().requestedServerName().empty()) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
std::string(data.socket().requestedServerName())};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}

Matcher::DataInputGetResult TransportProtocolInput::get(const MatchingData& data) const {
if (!data.socket().detectedTransportProtocol().empty()) {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
std::string(data.socket().detectedTransportProtocol())};
}
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::nullopt};
}

Matcher::DataInputGetResult ApplicationProtocolInput::get(const MatchingData& data) const {
return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
absl::StrJoin(data.socket().requestedApplicationProtocols(), ",")};
}

REGISTER_FACTORY(DestinationIPInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(DestinationPortInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(SourceIPInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(SourcePortInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(DirectSourceIPInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(SourceTypeInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(ServerNameInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(TransportProtocolInputFactory, Matcher::DataInputFactory<MatchingData>);
REGISTER_FACTORY(ApplicationProtocolInputFactory, Matcher::DataInputFactory<MatchingData>);

} // namespace Matching
} // namespace Network
} // namespace Envoy
Loading

0 comments on commit aea58eb

Please sign in to comment.