Class: LogStash::Filters::RealIp
- Inherits:
-
Base
- Object
- Base
- LogStash::Filters::RealIp
- Defined in:
- lib/logstash/filters/real_ip.rb
Overview
Evaluate an HTTP request’s client address like Apache httpd’s mod_remoteip or Nginx’s realip module.
For an event like this…
- source,ruby
-
"remote_addr" => "10.1.1.1" "x_fwd_for" => ["1.2.3.4", "10.2.2.2"]
…an example configuration looks like so:
- source,ruby
-
filter {
real_ip { remote_address_field => "remote_addr" x_forwarded_for_field => "x_fwd_for" trusted_networks => [ "10.0.0.0/8", "192.168.0.0/16" ] }
}
This will evaluate the real client IP, writing it to a new field “realip”. For above example event that would be “1.2.3.4”
Often web servers don’t provide the value of the X-Forwarded-For header as an array. For ease of use the real_ip plugin provides capabilities to parse such a comma-separated string. To enable this feature, use the ‘x_forwarded_for_is_string` option.
For an event like this…
- source,ruby
-
"remote_addr" => "10.1.1.1" "x_fwd_for" => "1.2.3.4, 10.2.2.2"
…an example configuration looks like so:
- source,ruby
-
filter {
real_ip { remote_address_field => "remote_addr" x_forwarded_for_field => "x_fwd_for" x_forwarded_for_is_string => true trusted_networks => [ "10.0.0.0/8", "192.168.0.0/16" ] }
}
In case the plugin fails to evaluate the real client IP, it will add a tag to the event, by default ‘_real_ip_lookup_failure`. The plugin will fail if one of below it true:
-
The ‘remote_address` field is absent.
-
The ‘remote_address` field doesn’t contain an IP address.
-
The filter is configured using ‘x_forwarded_for_is_string = true`, but the
‘x_forwarded_for` field isn’t a string.
-
The ‘x_forwarded_for` field contains anything other that IP addresses.
Evaluation behavior ====
The plugin checks whether the ‘remote_address_field` is trusted, if not, it will be written to `target_field`, and evaluation ends.
Otherwise each IP in the ‘x_forwarded_for_field` is checked, from right to left until an untrusted IP is encountered, which will be written to `target_field` and evaluation ends at that point.
In case ‘remote_address_field` and all IPs in `x_forwarded_for_field` are trusted, the left-most IP of the `x_forwarded_for_field` is written to `target_field`.
Instance Method Summary collapse
Instance Method Details
#filter(event) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/logstash/filters/real_ip.rb', line 152 def filter(event) remote_addr = event.get(@remote_address_field) fwdfor = event.get(@x_forwarded_for_field) # check for presence of remote_address_field if remote_addr == nil @logger.warn("remote_address_field missing from event", :event => event) @tags_on_failure.each {|tag| event.tag(tag)} return end # check for presence of x_forwarded_for_field if fwdfor == nil @logger.debug? and @logger.debug("x_forwarded_for_field missing from event", :event => event) event.set(@target_field, remote_addr) filter_matched(event) return end begin ip = IPAddr.new(remote_addr) rescue ArgumentError => e @logger.warn("Invalid IP address in remote_addr field", :address => remote_addr, :event => event) @tags_on_failure.each {|tag| event.tag(tag)} return end # If remote_addr isn't trusted, we don't even have to look at the X-Forwarded-For header if match(ip) == false @logger.debug? and @logger.debug("remote_addr isn't trusted. evaluating to remote_addr", :address => remote_addr) event.set(@target_field, remote_addr) filter_matched(event) return end if @x_forwarded_for_is_string if not fwdfor.kind_of?(String) @logger.warn("x_forwarded_for_field isn't of type string", :event => event) @tags_on_failure.each {|tag| event.tag(tag)} return end fwdfor = fwdfor.gsub(/[ +]/, '').split(/,/) else # If there's only one IP in the X-Forwarded-For header, it's a string instead # of an Array. if not fwdfor.kind_of?(Array) @logger.debug? and @logger.debug("creating array from single string value xfwdfor", :xfwdfor => fwdfor) fwdfor = [fwdfor] end end # in case x_forwarded_for is empty if fwdfor.length == 0 event.set(@target_field, remote_addr) filter_matched(event) return end # In case X-Forwarded-For header is set, but zero-length string if fwdfor.length == 1 and fwdfor[0].length < 1 @logger.debug? and @logger.debug("xfwdfor header was present but empty, evaluate to remote_addr", :address => remote_addr) event.set(@target_field, remote_addr) filter_matched(event) return end found = false fatal = false target = [] # check each IP in x_forwarded_for_field from last to first (fwdfor.length - 1).downto(0) do |i| begin ip = IPAddr.new(fwdfor[i]) rescue ArgumentError => e @logger.warn("Invalid IP address", :address => fwdfor[i], :event => event) if not found @tags_on_failure.each {|tag| event.tag(tag)} fatal = true end @tags_in_invalid_ip.each {|tag| event.tag(tag)} next end target.unshift(ip.to_s()) if @need_all # return on the first non-match against our trusted networks if found == false and fatal == false and match(ip) == false event.set(@target_field, fwdfor[i]) filter_matched(event) return if not @need_all found = true end end event.set(@x_forwarded_for_target, target) if @need_all if found == false and fatal == false # in case remote_addr and all x_forwarded_for IPs are trusted, use the # left-most IP from x_forwarded_for event.set(@target_field, fwdfor[0]) filter_matched(event) return end end |
#register ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/logstash/filters/real_ip.rb', line 115 def register if @remote_address_field.length < 1 raise LogStash::ConfigurationError, I18n.t( "logstash.agent.configuration.invalid_plugin_register", :plugin => "filter", :type => "real_ip", :error => "The configuration option 'remote_address_field' must be a non-zero length string" ) end if @x_forwarded_for_field.length < 1 raise LogStash::ConfigurationError, I18n.t( "logstash.agent.configuration.invalid_plugin_register", :plugin => "filter", :type => "real_ip", :error => "The configuration option 'x_forwarded_for_field' must be a non-zero length string" ) end @trusted_networks.map! {|e| IPAddr.new(e)} @need_all = x_forwarded_for_target.length > 0 end |