Skip to content

Commit d4c351c

Browse files
committed
External-IPs can be enabled just in one direction
1 parent ae32b56 commit d4c351c

File tree

8 files changed

+128
-56
lines changed

8 files changed

+128
-56
lines changed

collector/lib/CollectorConfig.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ constexpr const char* CollectorConfig::kSyscalls[];
9191
constexpr bool CollectorConfig::kEnableProcessesListeningOnPorts;
9292

9393
const UnorderedSet<L4ProtoPortPair> CollectorConfig::kIgnoredL4ProtoPortPairs = {{L4Proto::UDP, 9}};
94-
;
9594

9695
CollectorConfig::CollectorConfig() {
9796
// Set default configuration values
@@ -439,7 +438,7 @@ std::ostream& operator<<(std::ostream& os, const CollectorConfig& c) {
439438
<< ", set_import_users:" << c.ImportUsers()
440439
<< ", collect_connection_status:" << c.CollectConnectionStatus()
441440
<< ", enable_detailed_metrics:" << c.EnableDetailedMetrics()
442-
<< ", enable_external_ips:" << c.EnableExternalIPs()
441+
<< ", external_ips:" << c.ExternalIPsConf()
443442
<< ", track_send_recv:" << c.TrackingSendRecv();
444443
}
445444

@@ -545,4 +544,38 @@ std::pair<option::ArgStatus, std::string> CollectorConfig::CheckConfiguration(co
545544
return std::make_pair(ARG_OK, "");
546545
}
547546

547+
CollectorConfig::ExternalIPsConfig::ExternalIPsConfig(std::optional<sensor::CollectorConfig> runtime_config, bool default_enabled)
548+
: direction_enabled_(Direction::NONE) {
549+
if (runtime_config.has_value()) {
550+
if (runtime_config.value().networking().external_ips().enabled() == sensor::ExternalIpsEnabled::ENABLED) {
551+
switch (runtime_config.value().networking().external_ips().direction()) {
552+
case sensor::ExternalIpsDirection::INGRESS:
553+
direction_enabled_ = Direction::INGRESS;
554+
break;
555+
case sensor::ExternalIpsDirection::EGRESS:
556+
direction_enabled_ = Direction::EGRESS;
557+
break;
558+
default:
559+
direction_enabled_ = Direction::BOTH;
560+
break;
561+
}
562+
}
563+
} else if (default_enabled) {
564+
direction_enabled_ = Direction::BOTH;
565+
}
566+
}
567+
568+
std::ostream& operator<<(std::ostream& os, const collector::CollectorConfig::ExternalIPsConfig& config) {
569+
static std::unordered_map<collector::CollectorConfig::ExternalIPsConfig::Direction, std::string> mapping = {
570+
{CollectorConfig::ExternalIPsConfig::Direction::NONE, "NONE"},
571+
{CollectorConfig::ExternalIPsConfig::Direction::INGRESS, "INGRESS"},
572+
{CollectorConfig::ExternalIPsConfig::Direction::EGRESS, "EGRESS"},
573+
{CollectorConfig::ExternalIPsConfig::Direction::BOTH, "BOTH"},
574+
};
575+
576+
auto str = mapping.find(config.GetDirection());
577+
578+
return os << "direction(" << ((str == mapping.end()) ? "invalid" : (*str).second) << ")";
579+
}
580+
548581
} // namespace collector

collector/lib/CollectorConfig.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,39 @@ class CollectorConfig {
9494
bool ImportUsers() const { return import_users_; }
9595
bool CollectConnectionStatus() const { return collect_connection_status_; }
9696

97+
// Encapsulates the configuration of the External-IPs feature
98+
class ExternalIPsConfig {
99+
public:
100+
enum Direction {
101+
NONE = 0,
102+
INGRESS = 1 << 0,
103+
EGRESS = 1 << 1,
104+
BOTH = INGRESS | EGRESS,
105+
};
106+
107+
// Are External-IPs enabled in the provided direction ?
108+
bool IsEnabled(Direction direction) { return (direction & direction_enabled_) == direction; }
109+
110+
// Direction in which External-IPs are enabled
111+
Direction GetDirection() const { return direction_enabled_; }
112+
113+
// Extract the External-IPs configuration from the provided runtime-conf.
114+
// If the runtime-configuration is unset then 'default_enabled' is used
115+
// as a fallback to enable in both directions.
116+
// 'runtime_config' should be locked prior to calling.
117+
ExternalIPsConfig(std::optional<sensor::CollectorConfig> runtime_config, bool default_enabled);
118+
119+
private:
120+
Direction direction_enabled_;
121+
};
122+
97123
// EnableExternalIPs will check for the existence
98124
// of a runtime configuration, and defer to that value
99125
// otherwise, we rely on the feature flag (env var)
100-
bool EnableExternalIPs() const {
126+
ExternalIPsConfig ExternalIPsConf() const {
101127
auto lock = ReadLock();
102-
if (runtime_config_.has_value()) {
103-
return runtime_config_.value()
104-
.networking()
105-
.external_ips()
106-
.enabled() == sensor::ExternalIpsEnabled::ENABLED;
107-
}
108-
return enable_external_ips_;
128+
129+
return ExternalIPsConfig(runtime_config_, enable_external_ips_);
109130
}
110131

111132
void RuntimeConfigHeuristics() {
@@ -266,5 +287,6 @@ class CollectorConfig {
266287
};
267288

268289
std::ostream& operator<<(std::ostream& os, const CollectorConfig& c);
290+
std::ostream& operator<<(std::ostream& os, const collector::CollectorConfig::ExternalIPsConfig& config);
269291

270292
} // end namespace collector

collector/lib/ConnTracker.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ IPNet ConnectionTracker::NormalizeAddressNoLock(const Address& address, bool ena
112112
}
113113

114114
bool ConnectionTracker::ShouldNormalizeConnection(const Connection* conn) const {
115-
Endpoint local, remote = conn->remote();
115+
Endpoint remote = conn->remote();
116116
IPNet ipnet = NormalizeAddressNoLock(remote.address(), false);
117117

118118
return Address::IsCanonicalExternalIp(ipnet.address());
@@ -138,28 +138,35 @@ void ConnectionTracker::CloseConnections(ConnMap* old_conn_state, ConnMap* delta
138138

139139
/**
140140
* Closes connections that have the 255.255.255.255 external IP address
141+
* Affects only connections with a matching is_server property
141142
*/
142-
void ConnectionTracker::CloseNormalizedConnections(ConnMap* old_conn_state, ConnMap* delta_conn) {
143-
CloseConnections(old_conn_state, delta_conn, [](const Connection* conn) {
144-
return Address::IsCanonicalExternalIp(conn->remote().address());
143+
void ConnectionTracker::CloseNormalizedConnections(bool is_server, ConnMap* old_conn_state, ConnMap* delta_conn) {
144+
CloseConnections(old_conn_state, delta_conn, [is_server](const Connection* conn) {
145+
return conn->is_server() == is_server && Address::IsCanonicalExternalIp(conn->remote().address());
145146
});
146147
}
147148

148149
/**
149150
* Closes unnormalized connections that would be normalized to the canonical external
150151
* IP address if external IPs was enabled
152+
* Affects only connections with a matching is_server property
151153
*/
152-
void ConnectionTracker::CloseExternalUnnormalizedConnections(ConnMap* old_conn_state, ConnMap* delta_conn) {
153-
CloseConnections(old_conn_state, delta_conn, [this](const Connection* conn) {
154-
return ShouldNormalizeConnection(conn) && !Address::IsCanonicalExternalIp(conn->remote().address());
154+
void ConnectionTracker::CloseExternalUnnormalizedConnections(bool is_server, ConnMap* old_conn_state, ConnMap* delta_conn) {
155+
CloseConnections(old_conn_state, delta_conn, [this, is_server](const Connection* conn) {
156+
return conn->is_server() == is_server && ShouldNormalizeConnection(conn) && !Address::IsCanonicalExternalIp(conn->remote().address());
155157
});
156158
}
157159

158-
void ConnectionTracker::CloseConnectionsOnRuntimeConfigChange(ConnMap* old_conn_state, ConnMap* delta_conn, bool enableExternalIPs) {
159-
if (enableExternalIPs) {
160-
CloseNormalizedConnections(old_conn_state, delta_conn);
160+
void ConnectionTracker::CloseConnectionsOnRuntimeConfigChange(ConnMap* old_conn_state, ConnMap* delta_conn) {
161+
if (enable_external_ips_egress_) {
162+
CloseNormalizedConnections(/* egress is when we are not server */ false, old_conn_state, delta_conn);
161163
} else {
162-
CloseExternalUnnormalizedConnections(old_conn_state, delta_conn);
164+
CloseExternalUnnormalizedConnections(/* egress is when we are not server */ false, old_conn_state, delta_conn);
165+
}
166+
if (enable_external_ips_ingress_) {
167+
CloseNormalizedConnections(/* ingress is when we are server */ true, old_conn_state, delta_conn);
168+
} else {
169+
CloseExternalUnnormalizedConnections(/* ingress is when we are server */ true, old_conn_state, delta_conn);
163170
}
164171
}
165172

@@ -175,11 +182,11 @@ Connection ConnectionTracker::NormalizeConnectionNoLock(const Connection& conn)
175182
if (is_server) {
176183
// If this is the server, only the local port is relevant, while the remote port does not matter.
177184
local = Endpoint(IPNet(Address()), conn.local().port());
178-
remote = Endpoint(NormalizeAddressNoLock(conn.remote().address(), enable_external_ips_), 0);
185+
remote = Endpoint(NormalizeAddressNoLock(conn.remote().address(), enable_external_ips_ingress_), 0);
179186
} else {
180187
// If this is the client, the local port and address are not relevant.
181188
local = Endpoint();
182-
remote = Endpoint(NormalizeAddressNoLock(remote.address(), enable_external_ips_), remote.port());
189+
remote = Endpoint(NormalizeAddressNoLock(remote.address(), enable_external_ips_egress_), remote.port());
183190
}
184191

185192
return Connection(conn.container(), local, remote, conn.l4proto(), is_server);

collector/lib/ConnTracker.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ class ConnectionTracker {
101101
static void UpdateOldState(UnorderedMap<T, ConnStatus>* old_state, const UnorderedMap<T, ConnStatus>& new_state, int64_t time_micros, int64_t afterglow_period_micros);
102102

103103
void CloseConnections(ConnMap* old_conn_state, ConnMap* delta_conn, std::function<bool(const Connection*)> predicate);
104-
void CloseNormalizedConnections(ConnMap* old_conn_state, ConnMap* delta_conn);
105-
void CloseExternalUnnormalizedConnections(ConnMap* old_conn_state, ConnMap* delta_conn);
106-
void CloseConnectionsOnRuntimeConfigChange(ConnMap* old_conn_state, ConnMap* delta_conn, bool enableExternalIPs);
104+
void CloseNormalizedConnections(bool is_server, ConnMap* old_conn_state, ConnMap* delta_conn);
105+
void CloseExternalUnnormalizedConnections(bool is_server, ConnMap* old_conn_state, ConnMap* delta_conn);
106+
void CloseConnectionsOnRuntimeConfigChange(ConnMap* old_conn_state, ConnMap* delta_conn);
107107

108108
// ComputeDelta computes a diff between new_state and old_state
109109
template <typename T>
@@ -131,7 +131,10 @@ class ConnectionTracker {
131131

132132
void UpdateKnownPublicIPs(UnorderedSet<Address>&& known_public_ips);
133133
void UpdateKnownIPNetworks(UnorderedMap<Address::Family, std::vector<IPNet>>&& known_ip_networks);
134-
void EnableExternalIPs(bool enable) { enable_external_ips_ = enable; }
134+
void EnableExternalIPs(bool enable_ingress, bool enable_egress) {
135+
enable_external_ips_ingress_ = enable_ingress;
136+
enable_external_ips_egress_ = enable_egress;
137+
}
135138
void UpdateIgnoredL4ProtoPortPairs(UnorderedSet<L4ProtoPortPair>&& ignored_l4proto_port_pairs);
136139
void UpdateIgnoredNetworks(const std::vector<IPNet>& network_list);
137140
void UpdateNonAggregatedNetworks(const std::vector<IPNet>& network_list);
@@ -202,7 +205,8 @@ class ConnectionTracker {
202205

203206
UnorderedSet<Address> known_public_ips_;
204207
NRadixTree known_ip_networks_;
205-
bool enable_external_ips_ = false;
208+
bool enable_external_ips_ingress_ = false;
209+
bool enable_external_ips_egress_ = false;
206210
UnorderedMap<Address::Family, bool> known_private_networks_exists_;
207211
UnorderedSet<L4ProtoPortPair> ignored_l4proto_port_pairs_;
208212
NRadixTree ignored_networks_;

collector/lib/NetworkStatusNotifier.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace collector {
1616

1717
namespace {
1818

19+
using Direction = CollectorConfig::ExternalIPsConfig::Direction;
20+
1921
storage::L4Protocol TranslateL4Protocol(L4Proto proto) {
2022
switch (proto) {
2123
case L4Proto::TCP:
@@ -225,7 +227,7 @@ void NetworkStatusNotifier::RunSingle(IDuplexClientWriter<sensor::NetworkConnect
225227
auto next_scrape = std::chrono::system_clock::now();
226228
int64_t time_at_last_scrape = NowMicros();
227229

228-
bool prevEnableExternalIPs = config_.EnableExternalIPs();
230+
CollectorConfig::ExternalIPsConfig prevEnableExternalIPs = config_.ExternalIPsConf();
229231

230232
while (writer->Sleep(next_scrape)) {
231233
CLOG(DEBUG) << "Starting network status notification";
@@ -242,17 +244,19 @@ void NetworkStatusNotifier::RunSingle(IDuplexClientWriter<sensor::NetworkConnect
242244
const sensor::NetworkConnectionInfoMessage* msg;
243245
ConnMap new_conn_state, delta_conn;
244246
AdvertisedEndpointMap new_cep_state;
245-
bool enableExternalIPs = config_.EnableExternalIPs();
247+
CollectorConfig::ExternalIPsConfig externalIPsConfig = config_.ExternalIPsConf();
246248

247249
WITH_TIMER(CollectorStats::net_fetch_state) {
248-
conn_tracker_->EnableExternalIPs(enableExternalIPs);
250+
conn_tracker_->EnableExternalIPs(
251+
externalIPsConfig.IsEnabled(Direction::INGRESS),
252+
externalIPsConfig.IsEnabled(Direction::EGRESS));
249253

250254
new_conn_state = conn_tracker_->FetchConnState(true, true);
251255
if (config_.EnableAfterglow()) {
252256
ConnectionTracker::ComputeDeltaAfterglow(new_conn_state, old_conn_state, delta_conn, time_micros, time_at_last_scrape, config_.AfterglowPeriod());
253-
if (prevEnableExternalIPs != enableExternalIPs) {
254-
conn_tracker_->CloseConnectionsOnRuntimeConfigChange(&old_conn_state, &delta_conn, enableExternalIPs);
255-
prevEnableExternalIPs = enableExternalIPs;
257+
if (prevEnableExternalIPs.GetDirection() != externalIPsConfig.GetDirection()) {
258+
conn_tracker_->CloseConnectionsOnRuntimeConfigChange(&old_conn_state, &delta_conn);
259+
prevEnableExternalIPs = externalIPsConfig;
256260
}
257261
} else {
258262
ConnectionTracker::ComputeDelta(new_conn_state, &old_conn_state);

collector/test/CollectorConfigTest.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "gtest/gtest.h"
99

1010
using namespace testing;
11+
using Direction = collector::CollectorConfig::ExternalIPsConfig::Direction;
1112

1213
namespace collector {
1314

@@ -115,11 +116,11 @@ TEST(CollectorConfigTest, TestEnableExternalIpsFeatureFlag) {
115116

116117
config.MockSetEnableExternalIPs(false);
117118

118-
EXPECT_FALSE(config.EnableExternalIPs());
119+
EXPECT_EQ(Direction::NONE, config.ExternalIPsConf().GetDirection());
119120

120121
config.MockSetEnableExternalIPs(true);
121122

122-
EXPECT_TRUE(config.EnableExternalIPs());
123+
EXPECT_EQ(Direction::BOTH, config.ExternalIPsConf().GetDirection());
123124
}
124125

125126
TEST(CollectorConfigTest, TestEnableExternalIpsRuntimeConfig) {
@@ -138,14 +139,20 @@ TEST(CollectorConfigTest, TestEnableExternalIpsRuntimeConfig) {
138139

139140
config.SetRuntimeConfig(runtime_config);
140141

141-
EXPECT_FALSE(config.EnableExternalIPs());
142+
EXPECT_EQ(Direction::NONE, config.ExternalIPsConf().GetDirection());
143+
EXPECT_FALSE(config.ExternalIPsConf().IsEnabled(Direction::INGRESS));
144+
EXPECT_FALSE(config.ExternalIPsConf().IsEnabled(Direction::EGRESS));
145+
EXPECT_FALSE(config.ExternalIPsConf().IsEnabled(Direction::BOTH));
142146

143147
config.MockSetEnableExternalIPs(false);
144148

145149
external_ips_config->set_enabled(sensor::ExternalIpsEnabled::ENABLED);
146150
config.SetRuntimeConfig(runtime_config);
147151

148-
EXPECT_TRUE(config.EnableExternalIPs());
152+
EXPECT_EQ(CollectorConfig::ExternalIPsConfig::Direction::BOTH, config.ExternalIPsConf().GetDirection());
153+
EXPECT_TRUE(config.ExternalIPsConf().IsEnabled(Direction::INGRESS));
154+
EXPECT_TRUE(config.ExternalIPsConf().IsEnabled(Direction::EGRESS));
155+
EXPECT_TRUE(config.ExternalIPsConf().IsEnabled(Direction::BOTH));
149156
}
150157

151158
} // namespace collector

collector/test/ConfigLoaderTest.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace collector {
1313
using namespace google::protobuf::util;
14+
using Direction = CollectorConfig::ExternalIPsConfig::Direction;
1415

1516
std::string ErrorsToString(const std::vector<ParserError>& errors) {
1617
std::stringstream ss;
@@ -308,29 +309,28 @@ TEST(TestParserYaml, ValidationMode) {
308309
*/
309310

310311
TEST(CollectorConfigTest, TestYamlConfigToConfigMultiple) {
311-
std::vector<std::pair<std::string, bool>> tests = {
312+
std::vector<std::pair<std::string, Direction>> tests = {
312313
{R"(
313314
networking:
314315
externalIps:
315316
enabled: enabled
316317
)",
317-
true},
318+
Direction::BOTH},
318319
{R"(
319320
networking:
320321
externalIps:
321322
enabled: DISABLED
322323
)",
323-
false},
324+
Direction::NONE},
324325
{R"(
325326
networking:
326327
externalIps:
327328
)",
328-
false},
329-
{
330-
R"(
329+
Direction::NONE},
330+
{R"(
331331
networking:
332332
)",
333-
false},
333+
Direction::NONE},
334334
};
335335

336336
for (const auto& [yamlStr, expected] : tests) {
@@ -342,12 +342,7 @@ TEST(CollectorConfigTest, TestYamlConfigToConfigMultiple) {
342342

343343
EXPECT_TRUE(runtime_config.has_value());
344344

345-
bool enabled = runtime_config.value()
346-
.networking()
347-
.external_ips()
348-
.enabled() == sensor::ExternalIpsEnabled::ENABLED;
349-
EXPECT_EQ(enabled, expected);
350-
EXPECT_EQ(config.EnableExternalIPs(), expected);
345+
EXPECT_EQ(config.ExternalIPsConf().GetDirection(), expected);
351346
}
352347
}
353348

0 commit comments

Comments
 (0)