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
@@ -40,36 +48,66 @@ def self.get_client_ip_from_request(request, options)
4048 end
4149
4250 begin
43- 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?
51+ header_value = request . env [ 'HTTP_X_FORWARDED_FOR' ]
52+ if header_value . include? ','
53+ header_value = ip . split ( ',' ) [ 0 ]
54+ end
55+ if self . validate_ip ( header_value )
56+ return header_value
57+ end
4558 rescue NoMethodError
4659 begin
47- 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?
60+ header_value = request [ 'HTTP_X_FORWARDED_FOR' ]
61+ if header_value . include? ','
62+ header_value = ip . split ( ',' ) [ 0 ]
63+ end
64+ if self . validate_ip ( header_value )
65+ return header_value
66+ end
4967 rescue NoMethodError
5068 # Ignored
5169 end
5270 end
5371
5472 begin
55- 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?
73+ header_value = request . env [ 'HTTP_X_REAL_IP' ]
74+ if header_value . include? ','
75+ header_value = ip . split ( ',' ) [ 0 ]
76+ end
77+ if self . validate_ip ( header_value )
78+ return header
79+ end
5780 rescue NoMethodError
5881 begin
59- 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?
82+ header_value = request [ 'HTTP_X_REAL_IP' ]
83+ if header_value . include? ','
84+ header_value = ip . split ( ',' ) [ 0 ]
85+ end
86+ if self . validate_ip ( header_value )
87+ return header_value
88+ end
6189 rescue NoMethodError
6290 # Ignored
6391 end
6492 end
6593
6694 begin
67- 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?
95+ header_value = request . env [ 'REMOTE_ADDR' ]
96+ if header_value . include? ','
97+ header_value = ip . split ( ',' ) [ 0 ]
98+ end
99+ if self . validate_ip ( header_value )
100+ return header_value
101+ end
69102 rescue NoMethodError
70103 begin
71- 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?
104+ header_value = request [ 'REMOTE_ADDR' ]
105+ if header_value . include? ','
106+ header_value = ip . split ( ',' ) [ 0 ]
107+ end
108+ if self . validate_ip ( header_value )
109+ return header_value
110+ end
73111 rescue NoMethodError
74112 # Ignored
75113 end
@@ -96,6 +134,35 @@ def self.parse_ip(headers)
96134 h = headers . gsub ( '-' , '_' )
97135 return PREFIX + h . upcase
98136 end
137+
138+ def self . parse_proxy_header ( headers , header_key )
139+ h = headers . gsub ( header_key + ': ' , '' )
140+ if headers . include? ','
141+ h = h . split ( ',' ) [ 0 ]
142+ end
143+ return h
144+ end
145+
146+ def self . validate_ip ( ip )
147+ if ip . nil?
148+ return false
149+ end
150+
151+ begin
152+ ipaddr = IPAddr . new ( ip )
153+ if ipaddr . ipv4?
154+ return true
155+ end
156+
157+ if ipaddr . ipv6?
158+ return true
159+ end
160+ rescue Exception
161+ # Ignored
162+ end
163+
164+ return false
165+ end
99166 end
100167 end
101168end
0 commit comments