Anonymizing IPs in Ruby

With the GDPR just around the corner, here are two useful ways to protect your users’ IP addresses.

Both support IPv4 and IPv6, and are included in the ip_anonymizer gem.

Masking

This is the approach Google Analytics uses for IP anonymization:

require "ipaddr"

def mask_ip(ip)
  addr = IPAddr.new(ip)
  if addr.ipv4?
    # set last octet to 0
    addr.mask(24).to_s
  else
    # set last 80 bits to zeros
    addr.mask(48).to_s
  end
end

Examples

mask_ip("8.8.4.4")
# => "8.8.4.0"

mask_ip("2001:4860:4860:0:0:0:0:8844")
# => "2001:4860:4860::"

Hashing

This transforms IP addresses with a keyed hash function (PBKDF2-HMAC-SHA256). If an unkeyed function is used (like SHA1), it’s trivial to build a rainbow table.

require "ipaddr"
require "openssl"

def hash_ip(ip, key:)
  addr = IPAddr.new(ip)
  key_len = addr.ipv4? ? 4 : 16
  family = addr.ipv4? ? Socket::AF_INET : Socket::AF_INET6

  keyed_hash = OpenSSL::PKCS5.pbkdf2_hmac(addr.to_s, key, 20000, key_len, "sha256")
  IPAddr.new(keyed_hash.bytes.inject {|a, b| (a << 8) + b }, family).to_s
end

Examples

hash_ip("8.8.4.4", key: "secret")
# => "114.124.40.57"

hash_ip("2001:4860:4860:0:0:0:0:8844", key: "secret")
# => "49a2:718:9704:cf11:2068:4c15:587c:1e15"

Published May 5, 2018 · Tweet


You might also enjoy

Bulk Upsert in Ruby/Rails

Client-Side Encryption with AWS and Ruby

Postgres SSLMODE Explained


All code examples are public domain.
Use them however you’d like (licensed under CC0).