ip_anonymizer 0.1.0 → 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 +4 -4
- data/CHANGELOG.md +9 -1
- data/LICENSE.txt +1 -1
- data/README.md +23 -9
- data/lib/ip_anonymizer/hash_ip.rb +13 -2
- data/lib/ip_anonymizer/mask_ip.rb +12 -2
- data/lib/ip_anonymizer/version.rb +1 -1
- data/lib/ip_anonymizer.rb +4 -2
- metadata +12 -76
- data/.gitignore +0 -8
- data/.travis.yml +0 -11
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -24
- data/Rakefile +0 -19
- data/ip_anonymizer.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f454e201a3d9c2f4289e2b0c6e367bffbed093f74dbcc6feeb1325ca39aa7a84
|
4
|
+
data.tar.gz: 312f1dcaf7e753febe323c9aed56b5847d1c1bfba84a2231fa79b73e34d8ec5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e5ad0bba1c72b3753e4b9218af6139df2cc0833cb3334e7b508740771ae6d3e3201773674ee2442d242807bf943cd46d93e75ce85271fb8a13fb7e499245ea0
|
7
|
+
data.tar.gz: e800b290819f4854464d21bd73451a2a5c39ea5598155267323c34a59552f3efb1139eb4881b2a2e952f08b4435c07e2113ababf85061da9e399d9d89365fa38
|
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# IP Anonymizer
|
2
2
|
|
3
|
-
:earth_americas: IP address anonymizer for Ruby
|
3
|
+
:earth_americas: IP address anonymizer for Ruby and Rails
|
4
4
|
|
5
|
-
Works with IPv4 and IPv6
|
5
|
+
Works with IPv4 and IPv6
|
6
|
+
|
7
|
+
Designed to help with [GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation) compliance
|
8
|
+
|
9
|
+
[](https://github.com/ankane/ip_anonymizer/actions)
|
6
10
|
|
7
11
|
## Getting Started
|
8
12
|
|
9
13
|
Add these lines to your application’s Gemfile:
|
10
14
|
|
11
15
|
```ruby
|
12
|
-
gem
|
16
|
+
gem "ip_anonymizer"
|
13
17
|
```
|
14
18
|
|
15
19
|
There are two strategies for anonymizing IPs.
|
@@ -18,8 +22,8 @@ There are two strategies for anonymizing IPs.
|
|
18
22
|
|
19
23
|
This is the approach [Google Analytics uses for IP anonymization](https://support.google.com/analytics/answer/2763052):
|
20
24
|
|
21
|
-
- For IPv4, the last octet
|
22
|
-
- For IPv6, the last 80 bits
|
25
|
+
- For IPv4, set the last octet to 0
|
26
|
+
- For IPv6, set the last 80 bits to zeros
|
23
27
|
|
24
28
|
```ruby
|
25
29
|
IpAnonymizer.mask_ip("8.8.4.4")
|
@@ -29,7 +33,7 @@ IpAnonymizer.mask_ip("2001:4860:4860:0:0:0:0:8844")
|
|
29
33
|
# => "2001:4860:4860::"
|
30
34
|
```
|
31
35
|
|
32
|
-
An advantange of this approach is geocoding will still work, only with slightly less accuracy.
|
36
|
+
An advantange of this approach is geocoding will still work, only with slightly less accuracy. A potential disadvantage is different IPs will have the same mask (`8.8.4.4` and `8.8.4.5` both become `8.8.4.0`).
|
33
37
|
|
34
38
|
### Hashing
|
35
39
|
|
@@ -43,7 +47,13 @@ IpAnonymizer.hash_ip("2001:4860:4860:0:0:0:0:8844", key: "secret")
|
|
43
47
|
# => "f6e4:a4fe:32dc:2f39:3e47:84cc:e85e:865c"
|
44
48
|
```
|
45
49
|
|
46
|
-
|
50
|
+
An advantage of this approach is different IPs will have different hashes (with the exception of collisions).
|
51
|
+
|
52
|
+
Make sure the key is kept secret and at least 30 random characters. Otherwise, a rainbow table can be constructed. You can generate a good key with:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
SecureRandom.hex(32)
|
56
|
+
```
|
47
57
|
|
48
58
|
## Rails
|
49
59
|
|
@@ -61,6 +71,10 @@ For hashing, use:
|
|
61
71
|
config.middleware.insert_after ActionDispatch::RemoteIp, IpAnonymizer::HashIp, key: "secret"
|
62
72
|
```
|
63
73
|
|
74
|
+
## Related Projects
|
75
|
+
|
76
|
+
- [Logstop](https://github.com/ankane/logstop) - Keep personally identifiable information (PII) out of your logs
|
77
|
+
|
64
78
|
## History
|
65
79
|
|
66
80
|
View the [changelog](https://github.com/ankane/ip_anonymizer/blob/master/CHANGELOG.md)
|
@@ -74,11 +88,11 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
74
88
|
- Write, clarify, or fix documentation
|
75
89
|
- Suggest or add new features
|
76
90
|
|
77
|
-
To get started with development
|
91
|
+
To get started with development:
|
78
92
|
|
79
93
|
```sh
|
80
94
|
git clone https://github.com/ankane/ip_anonymizer.git
|
81
95
|
cd ip_anonymizer
|
82
96
|
bundle install
|
83
|
-
rake test
|
97
|
+
bundle exec rake test
|
84
98
|
```
|
@@ -7,9 +7,20 @@ module IpAnonymizer
|
|
7
7
|
|
8
8
|
def call(env)
|
9
9
|
req = ActionDispatch::Request.new(env)
|
10
|
-
#
|
11
|
-
req.remote_ip =
|
10
|
+
# get header directly to preserve ActionDispatch::RemoteIp lazy loading
|
11
|
+
req.remote_ip = GetIp.new(req.get_header("action_dispatch.remote_ip".freeze), @key)
|
12
12
|
@app.call(req.env)
|
13
13
|
end
|
14
|
+
|
15
|
+
class GetIp
|
16
|
+
def initialize(remote_ip, key)
|
17
|
+
@remote_ip = remote_ip
|
18
|
+
@key = key
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
@ip ||= IpAnonymizer.hash_ip(@remote_ip, key: @key)
|
23
|
+
end
|
24
|
+
end
|
14
25
|
end
|
15
26
|
end
|
@@ -6,9 +6,19 @@ module IpAnonymizer
|
|
6
6
|
|
7
7
|
def call(env)
|
8
8
|
req = ActionDispatch::Request.new(env)
|
9
|
-
#
|
10
|
-
req.remote_ip =
|
9
|
+
# get header directly to preserve ActionDispatch::RemoteIp lazy loading
|
10
|
+
req.remote_ip = GetIp.new(req.get_header("action_dispatch.remote_ip".freeze))
|
11
11
|
@app.call(req.env)
|
12
12
|
end
|
13
|
+
|
14
|
+
class GetIp
|
15
|
+
def initialize(remote_ip)
|
16
|
+
@remote_ip = remote_ip
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@ip ||= IpAnonymizer.mask_ip(@remote_ip)
|
21
|
+
end
|
22
|
+
end
|
13
23
|
end
|
14
24
|
end
|
data/lib/ip_anonymizer.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
# stdlib
|
1
2
|
require "ipaddr"
|
2
3
|
require "openssl"
|
3
4
|
|
5
|
+
# modules
|
4
6
|
require "ip_anonymizer/hash_ip"
|
5
7
|
require "ip_anonymizer/mask_ip"
|
6
8
|
require "ip_anonymizer/version"
|
7
9
|
|
8
10
|
module IpAnonymizer
|
9
11
|
def self.mask_ip(ip)
|
10
|
-
addr = IPAddr.new(ip)
|
12
|
+
addr = IPAddr.new(ip.to_s)
|
11
13
|
if addr.ipv4?
|
12
14
|
# set last octet to 0
|
13
15
|
addr.mask(24).to_s
|
@@ -18,7 +20,7 @@ module IpAnonymizer
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def self.hash_ip(ip, key:, iterations: 1)
|
21
|
-
addr = IPAddr.new(ip)
|
23
|
+
addr = IPAddr.new(ip.to_s)
|
22
24
|
key_len = addr.ipv4? ? 4 : 16
|
23
25
|
family = addr.ipv4? ? Socket::AF_INET : Socket::AF_INET6
|
24
26
|
|
metadata
CHANGED
@@ -1,87 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ip_anonymizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
description:
|
70
|
-
email:
|
71
|
-
- andrew@chartkick.com
|
11
|
+
date: 2022-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: andrew@ankane.org
|
72
15
|
executables: []
|
73
16
|
extensions: []
|
74
17
|
extra_rdoc_files: []
|
75
18
|
files:
|
76
|
-
- ".gitignore"
|
77
|
-
- ".travis.yml"
|
78
19
|
- CHANGELOG.md
|
79
|
-
- Gemfile
|
80
|
-
- Gemfile.lock
|
81
20
|
- LICENSE.txt
|
82
21
|
- README.md
|
83
|
-
- Rakefile
|
84
|
-
- ip_anonymizer.gemspec
|
85
22
|
- lib/ip_anonymizer.rb
|
86
23
|
- lib/ip_anonymizer/hash_ip.rb
|
87
24
|
- lib/ip_anonymizer/mask_ip.rb
|
@@ -90,7 +27,7 @@ homepage: https://github.com/ankane/ip_anonymizer
|
|
90
27
|
licenses:
|
91
28
|
- MIT
|
92
29
|
metadata: {}
|
93
|
-
post_install_message:
|
30
|
+
post_install_message:
|
94
31
|
rdoc_options: []
|
95
32
|
require_paths:
|
96
33
|
- lib
|
@@ -98,16 +35,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
35
|
requirements:
|
99
36
|
- - ">="
|
100
37
|
- !ruby/object:Gem::Version
|
101
|
-
version: 2.
|
38
|
+
version: '2.7'
|
102
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
40
|
requirements:
|
104
41
|
- - ">="
|
105
42
|
- !ruby/object:Gem::Version
|
106
43
|
version: '0'
|
107
44
|
requirements: []
|
108
|
-
|
109
|
-
|
110
|
-
signing_key:
|
45
|
+
rubygems_version: 3.3.7
|
46
|
+
signing_key:
|
111
47
|
specification_version: 4
|
112
|
-
summary: IP address anonymizer for Ruby
|
48
|
+
summary: IP address anonymizer for Ruby and Rails
|
113
49
|
test_files: []
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
ip_anonymizer (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
benchmark-ips (2.7.2)
|
10
|
-
minitest (5.11.3)
|
11
|
-
rake (12.3.1)
|
12
|
-
|
13
|
-
PLATFORMS
|
14
|
-
ruby
|
15
|
-
|
16
|
-
DEPENDENCIES
|
17
|
-
benchmark-ips
|
18
|
-
bundler
|
19
|
-
ip_anonymizer!
|
20
|
-
minitest
|
21
|
-
rake
|
22
|
-
|
23
|
-
BUNDLED WITH
|
24
|
-
1.16.1
|
data/Rakefile
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
|
-
require "benchmark/ips"
|
4
|
-
|
5
|
-
Rake::TestTask.new(:test) do |t|
|
6
|
-
t.libs << "test"
|
7
|
-
t.libs << "lib"
|
8
|
-
t.test_files = FileList["test/**/*_test.rb"]
|
9
|
-
end
|
10
|
-
|
11
|
-
task default: :test
|
12
|
-
|
13
|
-
task :benchmark do
|
14
|
-
require "ip_anonymizer"
|
15
|
-
Benchmark.ips do |x|
|
16
|
-
x.report("mask_ip") { IpAnonymizer.mask_ip("8.8.4.4") }
|
17
|
-
x.report("hash_ip") { IpAnonymizer.hash_ip("8.8.4.4", key: "secret") }
|
18
|
-
end
|
19
|
-
end
|
data/ip_anonymizer.gemspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "ip_anonymizer/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "ip_anonymizer"
|
8
|
-
spec.version = IpAnonymizer::VERSION
|
9
|
-
spec.authors = ["Andrew Kane"]
|
10
|
-
spec.email = ["andrew@chartkick.com"]
|
11
|
-
|
12
|
-
spec.summary = "IP address anonymizer for Ruby"
|
13
|
-
spec.homepage = "https://github.com/ankane/ip_anonymizer"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
-
f.match(%r{^(test|spec|features)/})
|
18
|
-
end
|
19
|
-
spec.bindir = "exe"
|
20
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = ["lib"]
|
22
|
-
|
23
|
-
spec.required_ruby_version = ">= 2.2.0"
|
24
|
-
|
25
|
-
spec.add_development_dependency "benchmark-ips"
|
26
|
-
spec.add_development_dependency "bundler"
|
27
|
-
spec.add_development_dependency "minitest"
|
28
|
-
spec.add_development_dependency "rake"
|
29
|
-
end
|