简体   繁体   English

查明某个 IP 是否在 IP 范围内

[英]Find out if an IP is within a range of IPs

你怎么知道一个 ip,比如62.156.244.13是否在62.0.0.062.255.255.255的范围内

>> require "ipaddr"
=> true
>> low = IPAddr.new("62.0.0.0").to_i
=> 1040187392
>> high = IPAddr.new("62.255.255.255").to_i
=> 1056964607
>> ip = IPAddr.new("62.156.244.13").to_i
=> 1050473485
>> (low..high)===ip
=> true

If you are given the network instead of the start and end addresses, it is even simpler 如果为您提供网络而不是起始地址和结束地址,则更为简单

>> net = IPAddr.new("62.0.0.0/8")
=> #<IPAddr: IPv4:62.0.0.0/255.0.0.0>
>> net===IPAddr.new("62.156.244.13")
=> true

IPAddr will also work with IPv6 addresses IPAddr也可以使用IPv6地址

>> low = IPAddr.new('1::')
=> #<IPAddr: IPv6:0001:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
>> high = IPAddr.new('2::')
=> #<IPAddr: IPv6:0002:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
>> (low..high)===IPAddr.new('1::1')
=> true

I would use this killer little function to convert the IP addresses into integers, and then compare those. 我将使用此杀手级小功能将IP地址转换为整数,然后进行比较。

def ip_addr_in_range?(low, high, addr)
  int_addr = numeric_ip(addr)
  int_addr <= numeric_ip(high) && int_addr >= numeric_ip(low)
end

def numeric_ip(ip_str)
  ip_str.split('.').inject(0) { |ip_num, part| ( ip_num << 8 ) + part.to_i }
end

def test_ip_addr_in_range(low, high, addr, expected)
  result = ip_addr_in_range?(low, high, addr)
  puts "#{addr} #{(expected ? 'should' : 'should not')} be within #{low} and #{high}: #{(expected == result ? 'PASS' : 'FAIL')}"
end


test_ip_addr_in_range("192.168.0.0", "192.168.0.255", "192.168.0.200", true)
test_ip_addr_in_range("192.168.0.0", "192.168.0.155", "192.168.0.200", false)
test_ip_addr_in_range("192.168.0.0", "192.168.255.255", "192.168.100.200", true)
test_ip_addr_in_range("192.168.0.0", "192.168.100.255", "192.168.150.200", false)
test_ip_addr_in_range("192.168.255.255", "192.255.255.255", "192.200.100.100", true)
test_ip_addr_in_range("192.168.255.255", "192.255.255.255", "192.100.100.100", false)
test_ip_addr_in_range("192.168.255.255", "255.255.255.255", "200.200.100.100", true)
test_ip_addr_in_range("192.168.255.255", "255.255.255.255", "180.100.100.100", false)

$ ruby ip_range.rb
192.168.0.200 should be within 192.168.0.0 and 192.168.0.255: PASS
192.168.0.200 should not be within 192.168.0.0 and 192.168.0.155: PASS
192.168.100.200 should be within 192.168.0.0 and 192.168.255.255: PASS
192.168.150.200 should not be within 192.168.0.0 and 192.168.100.255: PASS
192.200.100.100 should be within 192.168.255.255 and 192.255.255.255: PASS
192.100.100.100 should not be within 192.168.255.255 and 192.255.255.255: PASS
200.200.100.100 should be within 192.168.255.255 and 255.255.255.255: PASS
180.100.100.100 should not be within 192.168.255.255 and 255.255.255.255: PASS

Inspired by jdl's answer, but with a Range: 受jdl的答案启发,但具有范围:

class String
  def to_ip
    split(".").inject(0) { |s, p| (s << 8) + p.to_i }
  end
end

("62.0.0.0".to_ip.."62.255.255.255".to_ip).include?("62.156.244.13".to_ip)

There is a method #include? #include?方法#include?

And you can do just: 您可以执行以下操作:

IPAddr.new("127.0.0.1/8").include? "127.1.10.200"

I prefer this approach for converting the IP address to an integer for range comparison: 我更喜欢这种将IP地址转换为整数以进行范围比较的方法:

# n_ip("192.1.1.23") will return the number 192001001023
def n_ip(input)
  input.split(".").collect{|p| p.rjust(3, "0")}.join.to_i
end

def ip_in_range?(from, to, given)
  (n_ip(from)..n_ip(to).include?(n_ip(given))
end

Now you can check the value as follows: 现在,您可以检查值,如下所示:

>> ip_in_range?("192.168.0.0",  "192.168.0.255","192.168.0.200")
ip_in_range?("192.168.0.0",  "192.168.0.255","192.168.0.200")
=> true
>> ip_in_range?("192.168.0.0",  "192.168.0.255", "192.168.1.200")
ip_in_range?("192.168.0.0",  "192.168.0.255", "192.168.1.200")
=> false

The integer returned is not a 32 bit representation of the IP address. 返回的整数不是IP地址的32位表示形式。 The logic will work for all valid IP addresses. 该逻辑适用于所有有效的IP地址。

I have been assigned a real tuff one.我被分配了一个真正的凝灰岩。 I have a table 7000 records with low and high ip address and I'm using the Rails ipaddr class works great if my request.remote_ip is found in the table low and high fields.Then I get the low and high and put them into the ipaddr from the query then run it and I get a true.我有一个表 7000 条记录的低和高 ip 地址,如果我的 request.remote_ip 在表低和高字段中找到,我正在使用 Rails ipaddr 类工作得很好。然后我得到低和高并将它们放入ipaddr 从查询然后运行它,我得到一个 true。 Now the tuff part im asked to do is if the remote_ip address doesn't exist in table but it falls into the low and high ip address range in the table to also get a true.现在我要求做的 tuff 部分是如果 remote_ip 地址不存在于表中,但它落在表中的低和高 ip 地址范围内,也能得到一个真。 Any ideas will be highly appreciated.任何想法将不胜感激。 Thanks谢谢

jdl's answer is good. jdl的回答很好。 I would make the in_range? 我会进入in_range吗? function a one-liner: 单线功能:

def ip_addr_in_range?(low, high, addr)
  (numeric_ip(low) .. numeric_ip(high)) === numeric_ip(addr)
end

Don't make it any harder than it has to be. 不要使其变得比原来更难。

def check_ip(ip)
  '62.0.0.0' < ip and ip < '62.255.255.255'
end

check_ip '62.156.244.13' #=> true

Edit: Or, if you're using Rails / ActiveSupport: 编辑:或者,如果您使用的是Rails / ActiveSupport:

def check_ip(ip)
  ip.starts_with? '62'
end

check_ip '62.156.244.13' #=> true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM