diff --git a/lib/datadog/core/utils/network.rb b/lib/datadog/core/utils/network.rb index a3cc2403407..5a880833450 100644 --- a/lib/datadog/core/utils/network.rb +++ b/lib/datadog/core/utils/network.rb @@ -21,6 +21,8 @@ module Network cf-connecting-ipv6 ].freeze + CGNAT_IP_RANGE = IPAddr.new('100.64.0.0/10') + class << self # Returns a client IP associated with the request if it was # retrieved successfully. @@ -131,7 +133,7 @@ def strip_ipv4_port(ip) end def global_ip?(parsed_ip) - parsed_ip && !parsed_ip.private? && !parsed_ip.loopback? && !parsed_ip.link_local? + parsed_ip && !parsed_ip.private? && !parsed_ip.loopback? && !parsed_ip.link_local? && !CGNAT_IP_RANGE.include?(parsed_ip) end end end diff --git a/sig/datadog/core/utils/network.rbs b/sig/datadog/core/utils/network.rbs index 4ddc45cb08e..82dc43894de 100644 --- a/sig/datadog/core/utils/network.rbs +++ b/sig/datadog/core/utils/network.rbs @@ -4,6 +4,8 @@ module Datadog module Network DEFAULT_IP_HEADERS_NAMES: ::Array[::String] + CGNAT_IP_RANGE: ::IPAddr + def self.stripped_ip_from_request_headers: (Datadog::Core::HeaderCollection headers, ?::Array[::String] ip_headers_to_check) -> ::String? def self.stripped_ip: (::String ip) -> String? diff --git a/spec/datadog/core/utils/network_spec.rb b/spec/datadog/core/utils/network_spec.rb index a8e99663049..4d437095e01 100644 --- a/spec/datadog/core/utils/network_spec.rb +++ b/spec/datadog/core/utils/network_spec.rb @@ -25,6 +25,13 @@ result = described_class.stripped_ip_from_request_headers(headers) expect(result).to eq('43.43.43.43') end + + it 'does not return IPs from carrier-grade NAT IP range' do + headers = Datadog::Core::HeaderCollection.from_hash({'X-Forwarded-For' => '100.64.0.105,43.43.43.43,fe80::1'}) + + result = described_class.stripped_ip_from_request_headers(headers) + expect(result).to eq('43.43.43.43') + end end context 'with Forwaded header' do