logstash-filter-real_ip 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03a6d392653c84b6e9979c4242b33addc2bef2b9edbc06a02ab12bf4b0e817eb
4
- data.tar.gz: b86af8b9cb8beeb0018548058bda54666cc96a8c9a79dfa808e537ea24910ef9
3
+ metadata.gz: df7a4bbe848333419b6bd9cdddcb6396caa6469e1e80db081282c0ce3d6afe1a
4
+ data.tar.gz: d56cd9f9f44694175f181777d3b25244236c80c97d129a8bd4eb90c42c8ad2c4
5
5
  SHA512:
6
- metadata.gz: 80d539a35dc6a9ae7957e2051e75a3440aed0a885ea52bc565d757d5166a6623f17e54a933d4c1440922d89a44d1b0d19ab98b4e9613d298a8a71ba979e0ba9c
7
- data.tar.gz: c8a5626f432719c803a2abd375f31ae4d23390702e124cd9ed90233dd9bbd32c9f2ab77569d5ba7155c18e16999123783c120360d6fd88686a33eed975677d73
6
+ metadata.gz: d2f799ae54fffe451882944901b007d426f6aaa2a9909ed339bf50f5112f38a186d49e48d667d4513eb0722035aea2f3a05b9da6ed0e2aa56444c5838e653d68
7
+ data.tar.gz: 7df5f2176930a09f686bc63a2f5841a9b9985acef23d33ce0f461b0d23f002c866a2b141545323af6636b2369d7c85e442dce1c0c74ef26b549df541775f9e20
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
1
 
2
+ ## 0.2.0
3
+ - Feature: Write all x-forwarded-for IPs as array in new field
4
+ and detect invalid IPs, tagging the event if necessary
5
+
2
6
  ## 0.1.1
3
7
  - fix: Fix edge case where x-forwarded-for is empty or only contains trusted IPs
4
8
 
@@ -98,6 +98,16 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base
98
98
  # address to.
99
99
  config :target_field, :validate => :string, :default => "real_ip"
100
100
 
101
+ # writes all valid IPs found in the x_forwarded_for header to this field
102
+ config :x_forwarded_for_target, :validate => :string, :default => ""
103
+
104
+ # In case any IPs processed are invalid IP addresses,
105
+ # write all of them as one string to the field specified.
106
+ config :target_on_invalid_ip, :validate => :string, :default => ""
107
+
108
+ # In case any IPs processed are invalid IP addresses, these tags will be set.
109
+ config :tags_in_invalid_ip, :valudate => :array, :default => ["_real_ip_invalid_ip"]
110
+
101
111
  # In case of error during evaluation, these tags will be set.
102
112
  config :tags_on_failure, :validate => :array, :default => ["_real_ip_lookup_failure"]
103
113
 
@@ -122,6 +132,7 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base
122
132
  end
123
133
 
124
134
  @trusted_networks.map! {|e| IPAddr.new(e)}
135
+ @need_all = x_forwarded_for_target.length > 0
125
136
  end # def register
126
137
 
127
138
  private
@@ -151,7 +162,7 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base
151
162
 
152
163
  # check for presence of x_forwarded_for_field
153
164
  if fwdfor == nil
154
- @logger.info("x_forwarded_for_field missing from event", :event => event)
165
+ @logger.debug? and @logger.debug("x_forwarded_for_field missing from event", :event => event)
155
166
  event.set(@target_field, remote_addr)
156
167
  filter_matched(event)
157
168
  return
@@ -206,29 +217,43 @@ class LogStash::Filters::RealIp < LogStash::Filters::Base
206
217
  return
207
218
  end
208
219
 
220
+ found = false
221
+ fatal = false
222
+ target = []
209
223
  # check each IP in x_forwarded_for_field from last to first
210
224
  (fwdfor.length - 1).downto(0) do |i|
211
225
  begin
212
226
  ip = IPAddr.new(fwdfor[i])
213
227
  rescue ArgumentError => e
214
228
  @logger.warn("Invalid IP address", :address => fwdfor[i], :event => event)
215
- @tags_on_failure.each {|tag| event.tag(tag)}
216
- return
229
+ if not found
230
+ @tags_on_failure.each {|tag| event.tag(tag)}
231
+ fatal = true
232
+ end
233
+ @tags_in_invalid_ip.each {|tag| event.tag(tag)}
234
+ next
217
235
  end
218
236
 
237
+ target.unshift(ip.to_s()) if @need_all
238
+
219
239
  # return on the first non-match against our trusted networks
220
- if match(ip) == false
240
+ if found == false and fatal == false and match(ip) == false
221
241
  event.set(@target_field, fwdfor[i])
222
242
  filter_matched(event)
223
- return
243
+ return if not @need_all
244
+ found = true
224
245
  end
225
246
  end
226
247
 
227
- # in case remote_addr and all x_forwarded_for IPs are trusted, use the
228
- # left-most IP from x_forwarded_for
229
- event.set(@target_field, fwdfor[0])
230
- filter_matched(event)
231
- return
248
+ event.set(@x_forwarded_for_target, target) if @need_all
249
+
250
+ if found == false and fatal == false
251
+ # in case remote_addr and all x_forwarded_for IPs are trusted, use the
252
+ # left-most IP from x_forwarded_for
253
+ event.set(@target_field, fwdfor[0])
254
+ filter_matched(event)
255
+ return
256
+ end
232
257
 
233
258
  end # def filter
234
259
  end # class LogStash::Filters::RealIp
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-filter-real_ip'
3
- s.version = '0.1.1'
3
+ s.version = '0.2.0'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = 'Evaluates real client IP from X-Forwarded-For header'
6
6
  s.description = 'See https://github.com/fholzer/logstash-filter-real_ip/blob/master/README.md for details.'
@@ -10,57 +10,81 @@ describe LogStash::Filters::RealIp do
10
10
  remote_address_field => "remote_addr"
11
11
  x_forwarded_for_field => "xfwdfor"
12
12
  trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
13
+ add_field => { "success" => "success" }
13
14
  }
14
15
  }
15
16
  CONFIG
16
17
  end
17
18
 
18
19
  sample("dummy") do
20
+ expect(subject).not_to include("success")
19
21
  expect(subject).to include("tags")
20
22
  expect(subject.get('tags')).to include("_real_ip_lookup_failure")
21
23
  end
22
24
 
23
25
  sample("remote_addr" => "1.2.3.4") do
24
- if subject.get('tags') then expect(subject.get('tags')).not_to include("_real_ip_lookup_failure") end
26
+ expect(subject).to include("success")
27
+ expect(subject).not_to include("tags")
25
28
  expect(subject).to include("real_ip")
26
29
  expect(subject.get('real_ip')).to eq('1.2.3.4')
27
30
  end
28
31
 
29
32
  sample("remote_addr" => "10.2.3.4") do
33
+ expect(subject).to include("success")
30
34
  expect(subject).not_to include("tags")
31
35
  expect(subject).to include("real_ip")
32
36
  expect(subject.get('real_ip')).to eq('10.2.3.4')
33
37
  end
34
38
 
35
39
  sample("remote_addr" => "1.2.3.4", "xfwdfor" => "") do
40
+ expect(subject).to include("success")
36
41
  expect(subject).not_to include("tags")
37
42
  expect(subject).to include("real_ip")
38
43
  expect(subject.get('real_ip')).to eq('1.2.3.4')
39
44
  end
40
45
 
41
46
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
42
- expect(subject.get("tags")).to eq(nil)
47
+ expect(subject).to include("success")
48
+ expect(subject).not_to include("tags")
43
49
  expect(subject).to include("real_ip")
44
50
  expect(subject.get('real_ip')).to eq('1.2.3.4')
45
51
  end
46
52
 
47
53
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "192.168.3.4"]) do
54
+ expect(subject).to include("success")
48
55
  expect(subject).not_to include("tags")
49
56
  expect(subject).to include("real_ip")
50
57
  expect(subject.get('real_ip')).to eq('1.2.3.4')
51
58
  end
52
59
 
53
60
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["192.168.5.6", "192.168.3.4"]) do
61
+ expect(subject).to include("success")
54
62
  expect(subject).not_to include("tags")
55
63
  expect(subject).to include("real_ip")
56
64
  expect(subject.get('real_ip')).to eq('192.168.5.6')
57
65
  end
58
66
 
59
67
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => []) do
68
+ expect(subject).to include("success")
60
69
  expect(subject).not_to include("tags")
61
70
  expect(subject).to include("real_ip")
62
71
  expect(subject.get('real_ip')).to eq('10.2.3.4')
63
72
  end
73
+
74
+ sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "1.2.3.4", "192.168.3.4"]) do
75
+ expect(subject).to include("success")
76
+ expect(subject).not_to include("tags")
77
+ expect(subject).to include("real_ip")
78
+ expect(subject.get('real_ip')).to eq('1.2.3.4')
79
+ end
80
+
81
+ sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "192.168.3.4"]) do
82
+ expect(subject).not_to include("success")
83
+ expect(subject).to include("tags")
84
+ expect(subject).not_to include("real_ip")
85
+ expect(subject.get('tags')).to include('_real_ip_invalid_ip')
86
+ expect(subject.get('tags')).to include('_real_ip_lookup_failure')
87
+ end
64
88
  end
65
89
 
66
90
  describe "Evaluates real IP correctly with flat string xfwfor" do
@@ -71,24 +95,28 @@ describe LogStash::Filters::RealIp do
71
95
  x_forwarded_for_field => "xfwdfor"
72
96
  x_forwarded_for_is_string => true
73
97
  trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
98
+ add_field => { "success" => "success" }
74
99
  }
75
100
  }
76
101
  CONFIG
77
102
  end
78
103
 
79
104
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
80
- expect(subject.get("tags")).to eq(nil)
105
+ expect(subject).to include("success")
106
+ expect(subject).not_to include("tags")
81
107
  expect(subject).to include("real_ip")
82
108
  expect(subject.get('real_ip')).to eq('1.2.3.4')
83
109
  end
84
110
 
85
111
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4,+192.168.3.4") do
112
+ expect(subject).to include("success")
86
113
  expect(subject).not_to include("tags")
87
114
  expect(subject).to include("real_ip")
88
115
  expect(subject.get('real_ip')).to eq('1.2.3.4')
89
116
  end
90
117
 
91
118
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4, 192.168.3.4,+ 192.168.4.5") do
119
+ expect(subject).to include("success")
92
120
  expect(subject).not_to include("tags")
93
121
  expect(subject).to include("real_ip")
94
122
  expect(subject.get('real_ip')).to eq('1.2.3.4')
@@ -103,30 +131,35 @@ describe LogStash::Filters::RealIp do
103
131
  x_forwarded_for_field => "xfwdfor"
104
132
  target_field => "evaluated_ip"
105
133
  trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
134
+ add_field => { "success" => "success" }
106
135
  }
107
136
  }
108
137
  CONFIG
109
138
  end
110
139
 
111
140
  sample("remote_addr" => "1.2.3.4") do
141
+ expect(subject).to include("success")
112
142
  expect(subject).not_to include("tags")
113
143
  expect(subject).to include("evaluated_ip")
114
144
  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
115
145
  end
116
146
 
117
147
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "") do
148
+ expect(subject).to include("success")
118
149
  expect(subject).not_to include("tags")
119
150
  expect(subject).to include("evaluated_ip")
120
151
  expect(subject.get('evaluated_ip')).to eq('10.2.3.4')
121
152
  end
122
153
 
123
154
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => "1.2.3.4") do
124
- expect(subject.get("tags")).to eq(nil)
155
+ expect(subject).to include("success")
156
+ expect(subject).not_to include("tags")
125
157
  expect(subject).to include("evaluated_ip")
126
158
  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
127
159
  end
128
160
 
129
161
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "192.168.3.4"]) do
162
+ expect(subject).to include("success")
130
163
  expect(subject).not_to include("tags")
131
164
  expect(subject).to include("evaluated_ip")
132
165
  expect(subject.get('evaluated_ip')).to eq('1.2.3.4')
@@ -140,15 +173,60 @@ describe LogStash::Filters::RealIp do
140
173
  remote_address_field => "remote_addr"
141
174
  x_forwarded_for_field => "xfwdfor"
142
175
  trusted_networks => ["10.0.0.0/8", "2606:2800:220:1:248:1893:25c8:1946/120"]
176
+ add_field => { "success" => "success" }
143
177
  }
144
178
  }
145
179
  CONFIG
146
180
  end
147
181
 
148
182
  sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["1.2.3.4", "2606:2800:220:1:248:1893:25c8:1946"]) do
183
+ expect(subject).to include("success")
184
+ expect(subject).not_to include("tags")
185
+ expect(subject).to include("real_ip")
186
+ expect(subject.get('real_ip')).to eq('1.2.3.4')
187
+ end
188
+ end
189
+
190
+ describe "writes IPs to target array" do
191
+ let(:config) do <<-CONFIG
192
+ filter {
193
+ real_ip {
194
+ remote_address_field => "remote_addr"
195
+ x_forwarded_for_field => "xfwdfor"
196
+ x_forwarded_for_target => "xtarget"
197
+ trusted_networks => ["10.0.0.0/8", "192.168.0.0/16"]
198
+ add_field => { "success" => "success" }
199
+ }
200
+ }
201
+ CONFIG
202
+ end
203
+
204
+ sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["5.6.7.8", "1.2.3.4", "192.168.3.4"]) do
205
+ expect(subject).to include("success")
149
206
  expect(subject).not_to include("tags")
150
207
  expect(subject).to include("real_ip")
151
208
  expect(subject.get('real_ip')).to eq('1.2.3.4')
209
+ expect(subject.get('xtarget')).to eq(["5.6.7.8", "1.2.3.4", "192.168.3.4"])
210
+ end
211
+
212
+ sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "1.2.3.4", "192.168.3.4"]) do
213
+ expect(subject).to include("success")
214
+ expect(subject).to include("tags")
215
+ expect(subject).to include("real_ip")
216
+ expect(subject.get('real_ip')).to eq('1.2.3.4')
217
+ expect(subject.get('xtarget')).to eq(["1.2.3.4", "192.168.3.4"])
218
+ expect(subject.get('tags')).to include('_real_ip_invalid_ip')
219
+ expect(subject.get('tags')).not_to include('_real_ip_lookup_failure')
220
+ end
221
+
222
+ sample("remote_addr" => "10.2.3.4", "xfwdfor" => ["10.5", "192.168.3.4"]) do
223
+ expect(subject).not_to include("success")
224
+ expect(subject).to include("tags")
225
+ expect(subject).not_to include("real_ip")
226
+ expect(subject.get('xtarget')).to eq(["192.168.3.4"])
227
+ expect(subject.get('tags')).to include('_real_ip_invalid_ip')
228
+ expect(subject.get('tags')).to include('_real_ip_lookup_failure')
152
229
  end
153
230
  end
231
+
154
232
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-real_ip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ferdinand Holzer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-04 00:00:00.000000000 Z
11
+ date: 2018-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement