Subnets

Subnets is a C-extension for Ruby with IPv4 and IPv6 address and network classes. The motivating goal is to provide a fast test whether a given set of subnets includes a given IP.

Subnets.include?(subnets, '192.168.1.1')

Rack::Request#ip and ActionDispatch::Request#remote_ip perform such a test. ActionDispatch, which uses ipaddr by default, explicitly calls out that the technique is too slow to run on every request. Rack uses a regular expression of IPv4 and IPv6 private address spaces which, while comparably fast, is not easily extended to support arbitrary subnets.

(See also this answer explaining request.ip vs. request.remote_ip)

A benchmark tests if a random IP (75% private IPs) is within any of the private IPv4 ranges. Lower is better. Plotted on logscale. (Ruby 2.5.0p0, 2.5 GHz Intel Core i7).

$ bundle exec rake benchmark TEST=test/private_networks_benchmark
    
 ipaddr         : 46.25μs/ip ██████████████████████████████████▋
 ipaddress      : 63.88μs/ip ██████████████████████████████████████▏
 netaddr        : 31.03μs/ip ██████████████████████████████▎
*subnets        :  4.19μs/ip ████████▏
 rack (regexp)  :  5.25μs/ip ██████████▋
                             '         '       '      '         '
                             2         5       10     20        50

Usage

require 'subnets'

subnets = %w(127.0.0.1/32 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
  ::1/128 fc00::/7).map(&Subnets.method(:parse))

Subnets.include?(subnets, '192.168.1.1') #=> true
Subnets.include?(subnets, '203.0.113.12') #=> false

Similar Gems

There are several IP gems, all of which are implemented in pure-Ruby and not performance oriented.

Production Ready?

This has not been used in production.

Safe?

The IPv4 and IPv6 parsers are written in C. In addition to the unit test suite, the parsers have had minimal (16+ hours) of fuzzing with American fuzzy lop. There is medium confidence that the parsers will not read out-of-bounds.

Correct?

The unit test suite tests parsing of a variety of valid and invalid IPv4 and IPv6 networks.

Fast?

Yes, for checking if an array of subnets includes a given IP at least.