apache-log-geo 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -1
- data/apache-log-geo +10 -10
- data/lib.rb +25 -0
- data/mmdb-lookup +16 -11
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5f696d02b3eea816384b389250916a180e3b219ad52ecc01ad8fcc42ce664de
|
4
|
+
data.tar.gz: 3b2c584d7cde234fd15918eca2826d4d674806d43bf8ea244b22022916b55dab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57bb8e647db969849aa7e341def0459ec28c0ccc7806e6cca6a5d6c63beb976bdd097621f6d4f66a8a65b7b780ab5a76653cf190fd83ceb99b3a1be2f96e81e5
|
7
|
+
data.tar.gz: d3341602fb3df5c81af39f1dfcbdbf83576472bdc4bcc1208538db93497e6153f18c2afe50b73787524aa524d428e0a3c2e1310dc1b248e28b48fed5fd3109ff
|
data/README.md
CHANGED
@@ -17,6 +17,12 @@ key & install geoipupdate to fetch the db file.
|
|
17
17
|
|
18
18
|
gem install apache-log-geo
|
19
19
|
|
20
|
+
It uses a C extension [geoip2_c][], instead of the official maxmind-db
|
21
|
+
gem, for in my local tests, the latter (in conjunction with the Ruby
|
22
|
+
IO) is 9 (nine) times slower!
|
23
|
+
|
24
|
+
[geoip2_c]: https://github.com/fluent-plugins-nursery/geoip2_c
|
25
|
+
|
20
26
|
## Usage
|
21
27
|
|
22
28
|
The pkg contains 2 CLI utils only. There's no reusable library code.
|
@@ -33,6 +39,7 @@ Usage: apache-log-geo [-d GeoLite2-City.mmdb] [-v] [--key val ...]
|
|
33
39
|
--city regexp
|
34
40
|
--country regexp
|
35
41
|
--cc str 2 letter country code
|
42
|
+
--eu is an EU member?
|
36
43
|
--continent regexp
|
37
44
|
--postcode regexp
|
38
45
|
--sub regexp subdivisions
|
@@ -96,7 +103,7 @@ Kyiv City
|
|
96
103
|
Replicate `apache-log-geo` util--print only the requests from the Irish
|
97
104
|
(the example requires `npm -g json`):
|
98
105
|
|
99
|
-
$
|
106
|
+
$ cat test/access.log | ./mmdb-lookup | json -c 'this.country_code == "IE"' -a ip | grep -h -f - test/access.log
|
100
107
|
|
101
108
|
## Exit status
|
102
109
|
|
data/apache-log-geo
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
require 'mmdb'
|
5
4
|
require_relative 'lib'
|
6
5
|
include ApacheLogGeo
|
7
6
|
|
8
|
-
# exact match: country_code, postcode
|
9
|
-
# regexp: continent, country, subdivisions, city
|
10
|
-
#
|
11
7
|
# conditions are anded. no conditions == true
|
12
8
|
def match_by_geo info, query
|
13
9
|
query.each do |k,v|
|
10
|
+
if k == :eu # --eu is a boolean
|
11
|
+
return false unless info[k]
|
12
|
+
end
|
13
|
+
|
14
14
|
if k == :subdivisions # it's an array, one match of its elements is enough
|
15
15
|
return false unless (info[k] || []).any? {|val| val.to_s =~ /#{v}/i }
|
16
16
|
end
|
@@ -39,25 +39,25 @@ OptionParser.new do |o|
|
|
39
39
|
end
|
40
40
|
opt[:query][:country_code] = v
|
41
41
|
}
|
42
|
+
o.on("--eu", "is an EU member?") { opt[:query][:eu] = true }
|
42
43
|
o.on("--continent regexp") { |v| opt[:query][:continent] = v }
|
43
44
|
o.on("--postcode regexp") { |v| opt[:query][:postcode] = v }
|
44
45
|
o.on("--sub regexp", "subdivisions") { |v| opt[:query][:subdivisions] = v }
|
45
46
|
end.parse!
|
46
47
|
|
47
48
|
begin
|
48
|
-
geo =
|
49
|
+
geo = GeoDB.new opt[:db]
|
49
50
|
rescue
|
50
|
-
errx 2,
|
51
|
+
errx 2, $!
|
51
52
|
end
|
52
53
|
|
53
54
|
found_anything = false
|
54
55
|
$stdin.each_line do |line|
|
55
56
|
next if line =~ /^\s*$/
|
56
57
|
ip = line.split[0]
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
warnx "no data, filtering the entry out: `${ip[0..15]}`"
|
58
|
+
info = geo.get ip
|
59
|
+
unless info
|
60
|
+
warnx "line #{$stdin.lineno}: no data, filtering out: #{ip[0..15]}"
|
61
61
|
next
|
62
62
|
end
|
63
63
|
|
data/lib.rb
CHANGED
@@ -273,3 +273,28 @@ module ApacheLogGeo
|
|
273
273
|
"ZW" => "Zimbabwe"
|
274
274
|
}
|
275
275
|
end
|
276
|
+
|
277
|
+
require 'geoip2'
|
278
|
+
|
279
|
+
class ApacheLogGeo::GeoDB
|
280
|
+
def initialize path
|
281
|
+
@db = GeoIP2::Database.new path
|
282
|
+
end
|
283
|
+
|
284
|
+
def get ip
|
285
|
+
r = @db.lookup ip rescue nil
|
286
|
+
return nil unless r
|
287
|
+
|
288
|
+
{
|
289
|
+
city: r.dig('city', 'names', 'en'),
|
290
|
+
continent: r.dig('continent', 'names', 'en'),
|
291
|
+
country: r.dig('country', 'names', 'en'),
|
292
|
+
country_code: r.dig('country', 'iso_code'),
|
293
|
+
eu: r.dig('country', 'is_in_european_union'),
|
294
|
+
latitude: r.dig('location', 'latitude'),
|
295
|
+
longitude: r.dig('location', 'longitude'),
|
296
|
+
postcode: r.dig('postal', 'code'),
|
297
|
+
subdivisions: r.dig('subdivisions')&.map {|v| v&.dig('names', 'en') }&.compact
|
298
|
+
}
|
299
|
+
end
|
300
|
+
end
|
data/mmdb-lookup
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
require 'mmdb'
|
5
4
|
require_relative 'lib'
|
6
5
|
include ApacheLogGeo
|
7
6
|
|
@@ -17,7 +16,7 @@ class FMT
|
|
17
16
|
ip = @input.to_enum.next.split.first
|
18
17
|
r = ["ip=#{ip.shellescape}"]
|
19
18
|
|
20
|
-
info = @geo.
|
19
|
+
info = @geo.get ip
|
21
20
|
if !info
|
22
21
|
r << "error=#{@errors += 1}"
|
23
22
|
else
|
@@ -30,13 +29,19 @@ class FMT
|
|
30
29
|
|
31
30
|
def json
|
32
31
|
require 'json'
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
trans = -> (ip) do
|
33
|
+
r = {ip: ip}
|
34
|
+
info = @geo.get ip
|
35
|
+
info ? r.merge(info) : r.merge({error: @errors += 1})
|
36
|
+
end
|
37
|
+
|
38
|
+
if @input.is_a?(IO) # stdin, in which we expect an apache log
|
39
|
+
@input.map { |line| trans.call line.split[0] }.to_json
|
40
|
+
else # argv
|
41
|
+
@input.map do |list|
|
42
|
+
list.split.map { |ip| trans.call ip }
|
43
|
+
end.flatten.to_json
|
44
|
+
end
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -53,9 +58,9 @@ OptionParser.new do |o|
|
|
53
58
|
end.parse!
|
54
59
|
|
55
60
|
begin
|
56
|
-
geo =
|
61
|
+
geo = GeoDB.new opt[:db]
|
57
62
|
rescue
|
58
|
-
errx 2,
|
63
|
+
errx 2, $!
|
59
64
|
end
|
60
65
|
|
61
66
|
fmt = FMT.new (ARGV.size > 0 ? ARGV : $stdin), geo
|
metadata
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apache-log-geo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Gromnitsky
|
8
8
|
autorequire:
|
9
9
|
bindir: "."
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: geoip2_c
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.3.
|
19
|
+
version: 0.3.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.3.
|
26
|
+
version: 0.3.3
|
27
27
|
description: |
|
28
|
+
An offline GeoIP CLI filter for Apache (common, combined) logs.
|
28
29
|
It's like grep but with a knowledge about what data an ip
|
29
30
|
holds. Requires MaxMind's GeoLite2 DB (GeoLite2-City.mmdb) installed.
|
30
31
|
email: alexander.gromnitsky@gmail.com
|