diff --git a/cilium/bpf_metadata.cc b/cilium/bpf_metadata.cc index 365aec4fa..bd9cbdec9 100644 --- a/cilium/bpf_metadata.cc +++ b/cilium/bpf_metadata.cc @@ -462,16 +462,18 @@ Config::extractSocketMetadata(Network::ConnectionSocket& socket) { // North/south L7 LB, assume the source security identity of the configured source addresses, // if any and policy for this identity exists. - // Pick the local ingress source address of the same family as the incoming connection - const Network::Address::Ip* ingress_ip = selectIpVersion(sip->version(), source_addresses); + // Pick the local ingress source address of the same family as the destination connection. + // The incoming source family may differ when an IPv6 client reaches an IPv4-only load-balancer + // path via PROXY protocol. + const Network::Address::Ip* ingress_ip = selectIpVersion(dip->version(), source_addresses); if (!ingress_ip) { - // IP family of the connection has no configured local ingress source address + // IP family of the destination has no configured local ingress source address ENVOY_LOG( warn, "cilium.bpf_metadata (north/south L7 LB): No local Ingress IP source address configured " "for the family of {}", - sip->addressAsString()); + dip->addressAsString()); return absl::nullopt; } diff --git a/tests/bpf_metadata_config_test.cc b/tests/bpf_metadata_config_test.cc index aa3d9bc14..da8479774 100644 --- a/tests/bpf_metadata_config_test.cc +++ b/tests/bpf_metadata_config_test.cc @@ -326,6 +326,48 @@ TEST_F(MetadataConfigTest, NorthSouthL7LbMetadata) { (cilium_mark_socket_option->mark_ >> 16) == 8); } +TEST_F(MetadataConfigTest, NorthSouthL7LbMetadataMixedSourceAndDestinationFamily) { + // Use external IPv6 remote address, as seen after a TCP load-balancer forwards + // an IPv6 client address via PROXY protocol to an IPv4-only node path. + remote_address_ = + std::make_shared("2003:fa:c701:ff01::10f6", 12345); + + ::cilium::BpfMetadata config{}; + config.set_is_l7lb(true); + config.set_ipv4_source_address("10.1.1.42"); + + EXPECT_NO_THROW(initialize(config)); + + auto socket_metadata = config_->extractSocketMetadata(socket_); + EXPECT_TRUE(socket_metadata); + + auto policy_fs = socket_metadata->buildCiliumPolicyFilterState(); + EXPECT_NE(nullptr, policy_fs); + + EXPECT_EQ(8, policy_fs->source_identity_); + EXPECT_EQ(false, policy_fs->ingress_); + EXPECT_EQ(true, policy_fs->is_l7lb_); + EXPECT_EQ(80, policy_fs->port_); + EXPECT_EQ("", policy_fs->pod_ip_); + EXPECT_EQ("", policy_fs->ingress_policy_name_); + EXPECT_EQ(0, policy_fs->ingress_source_identity_); + + auto source_addresses_socket_option = socket_metadata->buildSourceAddressSocketOption(-1); + EXPECT_NE(nullptr, source_addresses_socket_option); + EXPECT_EQ(-1, source_addresses_socket_option->linger_time_); + + EXPECT_EQ(nullptr, source_addresses_socket_option->original_source_address_); + EXPECT_EQ("10.1.1.42:0", source_addresses_socket_option->ipv4_source_address_->asString()); + EXPECT_EQ(nullptr, source_addresses_socket_option->ipv6_source_address_); + + auto cilium_mark_socket_option = socket_metadata->buildCiliumMarkSocketOption(); + EXPECT_NE(nullptr, cilium_mark_socket_option); + + // Check that Ingress security ID is used in the socket mark. + EXPECT_TRUE((cilium_mark_socket_option->mark_ & 0xffff) == 0x0B00 && + (cilium_mark_socket_option->mark_ >> 16) == 8); +} + TEST_F(MetadataConfigTest, NorthSouthL7LbIngressEnforcedMetadata) { // Use external remote address remote_address_ = std::make_shared("192.168.1.1", 12345);