11# frozen_string_literal: true
22
3+ require 'ipaddr'
4+
35module SecureNative
46 module Utils
57 class RequestUtils
@@ -24,14 +26,20 @@ def self.get_client_ip_from_request(request, options)
2426 if h . nil?
2527 h = request . env [ self . parse_ip ( header ) ]
2628 end
27- return h . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless h . nil?
29+ parsed = self . parse_proxy_header ( h , header )
30+ if self . validate_ip ( parsed )
31+ return parsed
32+ end
2833 rescue NoMethodError
2934 begin
3035 h = request [ header ]
3136 if h . nil?
3237 h = request . env [ self . parse_ip ( header ) ]
3338 end
34- return h . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless h . nil?
39+ parsed = self . parse_proxy_header ( h , header )
40+ if self . validate_ip ( parsed )
41+ return parsed
42+ end
3543 rescue NoMethodError
3644 # Ignored
3745 end
@@ -41,35 +49,47 @@ def self.get_client_ip_from_request(request, options)
4149
4250 begin
4351 x_forwarded_for = request . env [ 'HTTP_X_FORWARDED_FOR' ]
44- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
52+ if self . validate_ip ( x_forwarded_for )
53+ return x_forwarded_for
54+ end
4555 rescue NoMethodError
4656 begin
4757 x_forwarded_for = request [ 'HTTP_X_FORWARDED_FOR' ]
48- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
58+ if self . validate_ip ( x_forwarded_for )
59+ return x_forwarded_for
60+ end
4961 rescue NoMethodError
5062 # Ignored
5163 end
5264 end
5365
5466 begin
5567 x_forwarded_for = request . env [ 'HTTP_X_REAL_IP' ]
56- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
68+ if self . validate_ip ( x_forwarded_for )
69+ return x_forwarded_for
70+ end
5771 rescue NoMethodError
5872 begin
5973 x_forwarded_for = request [ 'HTTP_X_REAL_IP' ]
60- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
74+ if self . validate_ip ( x_forwarded_for )
75+ return x_forwarded_for
76+ end
6177 rescue NoMethodError
6278 # Ignored
6379 end
6480 end
6581
6682 begin
6783 x_forwarded_for = request . env [ 'REMOTE_ADDR' ]
68- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
84+ if self . validate_ip ( x_forwarded_for )
85+ return x_forwarded_for
86+ end
6987 rescue NoMethodError
7088 begin
7189 x_forwarded_for = request [ 'REMOTE_ADDR' ]
72- return x_forwarded_for . scan ( /\b (?:[0-9]{1,3}\. ){3}[0-9]{1,3}\b / ) [ 0 ] unless x_forwarded_for . nil?
90+ if self . validate_ip ( x_forwarded_for )
91+ return x_forwarded_for
92+ end
7393 rescue NoMethodError
7494 # Ignored
7595 end
@@ -96,6 +116,32 @@ def self.parse_ip(headers)
96116 h = headers . gsub ( '-' , '_' )
97117 return PREFIX + h . upcase
98118 end
119+
120+ def self . parse_proxy_header ( headers , header_key )
121+ h = headers . gsub ( header_key + ': ' , '' )
122+ return h
123+ end
124+
125+ def self . validate_ip ( ip )
126+ if ip . nil?
127+ return false
128+ end
129+
130+ begin
131+ ipaddr = IPAddr . new ( ip )
132+ if ipaddr . ipv4?
133+ return true
134+ end
135+
136+ if ipaddr . ipv6?
137+ return true
138+ end
139+ rescue Exception
140+ # Ignored
141+ end
142+
143+ return false
144+ end
99145 end
100146 end
101147end
0 commit comments