Ruby IPAddr:查找地址掩码

Ruby IPAddr: find address mask

我有一个处理大量 IP 地址的应用程序(分析 Checkpoint 防火墙规则集)。有一次我想检查一个特定的地址对象是 /32 还是 'network'.

目前我是这样做的:

next unless ip.inspect.match(/\/255\.255\.255\.255/)

它有效,但似乎有点低效,但我看不到任何从地址对象中提取掩码的方法。

Ruby 核心库的某些部分有时只是草拟,IPAddr 似乎是其中之一,不幸的是,有点不完整。

不用担心。你可以用一个简单的 monkey-patch:

来解决这个问题
class IPAddr
  def cidr_mask
    case (@family)
    when Socket::AF_INET
      32 - Math.log2((1<<32) - @mask_addr).to_i
    when Socket::AF_INET6
      128 - Math.log2((1<<128) - @mask_addr).to_i
    else
      raise AddressFamilyError, "unsupported address family"
    end
  end
end

应该处理 IPv4 和 IPv6 地址:

IPAddr.new('151.101.65.69').cidr_mask
# => 32

IPAddr.new('151.101.65.69/26').cidr_mask
# => 26

IPAddr.new('151.101.65.69/255.255.255.0').cidr_mask
# => 24

IPAddr.new('2607:f8b0:4006:800::200e').cidr_mask
# => 128

IPAddr.new('2607:f8b0:4006:800::200e/100').cidr_mask
# => 100

这里不一定是最好的解决方案,但它确实有效。

我知道这是一个 3 年前的问题,但这是我在 Google 上搜索时的第一个结果,所以我想提供一个新答案。

我今天在控制台上玩,注意到 IPAddr 对象 returns cidr 掩码上的 prefix 方法是一个整数。

因此,例如:

ip = IPAddr.new("192.168.1.0/24")
ip.prefix 
  # => 24

事实证明,类型强制为您提供了地址和掩码的整数表示,因此您可以对 to_ito_json、[=17= 的输出进行数学计算] 或 instance_values.

网络地址示例:

ip.to_i 
  # => 3232235776

ip.to_i.to_s(2) 
  # => "11000000101010000000000100000000"

还有一个带有网络掩码:

ip.as_json 
  # => {"family"=>2, "addr"=>3232235776, "mask_addr"=>4294967040}

ip.as_json["mask_addr"].to_s(2) 
  # => 11111111111111111111111100000000

ip.as_json["mask_addr"].to_s(2).count("1")
  # => 24