File tree Expand file tree Collapse file tree 3 files changed +22
-5
lines changed
api/envoy/extensions/http/original_ip_detection/xff/v3
test/extensions/http/original_ip_detection/xff Expand file tree Collapse file tree 3 files changed +22
-5
lines changed Original file line number Diff line number Diff line change @@ -41,7 +41,8 @@ message XffConfig {
4141 //
4242 // If ``recurse`` is set the :ref:`config_http_conn_man_headers_x-forwarded-for`
4343 // header is also evaluated against the trusted CIDR list, and the last non-trusted
44- // address is used as the original client address.
44+ // address is used as the original client address. If all addresses in ``x-forwarded-for``
45+ // are within the trusted list, the first entry is used.
4546 //
4647 // This is typically used when requests are proxied by a
4748 // `CDN <https://en.wikipedia.org/wiki/Content_delivery_network>`_.
@@ -55,8 +56,9 @@ message XffTrustedCidrs {
5556 // connections are considered trusted.
5657 repeated config.core.v3.CidrRange cidrs = 1 ;
5758
58- // If ``true``, recurse through the :ref:`config_http_conn_man_headers_x-forwarded-for`
59- // HTTP header to find the first (from the right) non-trusted IP address; otherwise
60- // the last address in ``x-forwarded-for`` is used.
59+ // If ``true``, recurse backwards through the :ref:`config_http_conn_man_headers_x-forwarded-for`
60+ // HTTP header to find the first (from the right) non-trusted IP address. If all addresses
61+ // are trusted, the last (from the right) IP address is returned.
62+ // Otherwise the last address in ``x-forwarded-for`` is used.
6163 google.protobuf.BoolValue recurse = 2 ;
6264}
Original file line number Diff line number Diff line change @@ -805,12 +805,14 @@ Utility::GetLastAddressFromXffInfo Utility::getLastNonTrustedAddressFromXFF(
805805 static constexpr absl::string_view separator (" ," );
806806
807807 const auto xff_entries = StringUtil::splitToken (xff_string, separator, false , true );
808+ Network::Address::InstanceConstSharedPtr last_valid_addr;
808809
809810 for (auto it = xff_entries.rbegin (); it != xff_entries.rend (); it++) {
810811 auto addr = Network::Utility::parseInternetAddressNoThrow (std::string (*it));
811812 if (addr == nullptr ) {
812813 continue ;
813814 }
815+ last_valid_addr = addr;
814816
815817 bool trusted = false ;
816818 for (const auto & cidr : trusted_cidrs) {
@@ -834,7 +836,9 @@ Utility::GetLastAddressFromXffInfo Utility::getLastNonTrustedAddressFromXFF(
834836 }
835837 return {addr, true };
836838 }
837- return {nullptr , false };
839+ // If we reach this point all addresses in XFF were considered trusted, so return
840+ // first IP in XFF (the last in the reverse-evaluated chain).
841+ return {last_valid_addr, true };
838842}
839843
840844Utility::GetLastAddressFromXffInfo
Original file line number Diff line number Diff line change @@ -129,6 +129,17 @@ TEST_F(XffTrustedCidrsRecurseTest, Recurse) {
129129 EXPECT_EQ (" 2.2.2.2" , result.detected_remote_address ->ip ()->addressAsString ());
130130}
131131
132+ TEST_F (XffTrustedCidrsRecurseTest, RecurseAllAddressesTrusted) {
133+ Envoy::Http::TestRequestHeaderMapImpl headers{
134+ {" x-forwarded-for" , " 192.0.2.4,192.0.2.5, 198.51.100.1" }};
135+
136+ auto remote_address = std::make_shared<Network::Address::Ipv4Instance>(" 192.0.2.11" );
137+ Envoy::Http::OriginalIPDetectionParams params = {headers, remote_address};
138+ auto result = xff_extension_->detect (params);
139+ ASSERT_NE (result.detected_remote_address , nullptr );
140+ EXPECT_EQ (" 192.0.2.4" , result.detected_remote_address ->ip ()->addressAsString ());
141+ }
142+
132143} // namespace Xff
133144} // namespace OriginalIPDetection
134145} // namespace Http
You can’t perform that action at this time.
0 commit comments