检查IP是否在子网范围文件中(bash)

4

I've a list of subnet range in a file:

2.32.0.0-2.47.255.255-255.240.0.0
2.112.0.0-2.119.255.255-255.248.0.0
2.156.0.0-2.159.255.255-255.252.0.0
2.192.0.0-2.199.255.255-255.248.0.0
...

文件格式为:{起始IP地址}-{结束IP地址}-{子网掩码}

我需要检查一个IP是否包含在文件中的任意一个子网中。


1
为什么不直接用 grep 查找呢? - Politank-Z
什么是样本输入和您期望的输出? - anubhava
@Politank-Z grep?具体怎么用? - Stefano Guarella
@anubhava 输入是我需要搜索的IP,输出只需为“true”或“false”。 - Stefano Guarella
由于您有startip和endIp,因此可以使用awksplit和转换字符串为整数... - myaut
@myaut,你能给我一个可用的例子吗? - Stefano Guarella
6个回答

3
您可以使用awk来实现这个功能:
echo '127.0.0.0-127.255.255.255-255.0.0.0' | awk -F- '
    BEGIN { ip[1] = 127; ip[2] = 0; ip[3] = 0; ip[4] = 1; } 
    { split($1, startIp, "."); split($2, endIp, ".");
        for(i = 1; i <= 4; i++) {
            if(ip[i] < int(startIp[i]) || ip[i] > int(endIp[i]))
                break;
        }

        if(i == 5)
            print "matching line: ", $0; }'

在BEGIN子句中,搜索IP最初被设置为数组。在for循环中比较每一行,如果每个八位字节都位于startIpendIp之间,则打印“匹配行”。


以下是一些基于Python 3的胡言乱语,依赖于3.3版本中的ipaddress模块(可用于2.6/2.7):

python3 -c 'from ipaddress import ip_address as IP; list(
    map(print, ((startip, endip) for startip, endip, _ in 
            (ip.split("-") for ip in open("tmp/iplist.txt")) 
            if IP(startip) < IP("127.0.0.1") < IP(endip))))'

以下是以下脚本的一行版本:

import sys
from ipaddress import ip_address as IP

ip = IP(sys.argv[1])

with open(sys.argv[2]) as f:
    for line in f:
        startIp, endIp, _ = line.split('-')
        if IP(startIp) < ip < IP(endIp):
            print(line)

这可以像这样使用:

$ python3 ipcheck.py 127.0.0.1 iplist.txt

非常感谢你!;) - Stefano Guarella

1

试试这个:

BEGIN {
    FS="."
    ex = "false"
    split(address, ip, ".")
}
{
    split($0, range, "[-.]")
    for (i=1; i<5; i++) {
        if (ip[i] < range[i] || ip[i] > range[i+4])
            break;
        else if ((ip[i] > range[i] && ip[i] < range[i+4]) || i == 4)
            ex = "true"
    }
}
END {
    print ex
}

像这样调用这个 awk 脚本(checkIP.awk):

$ awk -v address="2.156.0.5" -f checkIP.awk /path/to/ip/ranges/file
true
$ awk -v address="0.0.0.0" -f checkIP.awk /path/to/ip/ranges/file
false

非常感谢ShellFish,但不幸的是它不能与某些IP一起使用,我给你一个例子:31.207.96.0-31.207.127.255-255.255.224.0$ awk -v address="31.207.96.5" -f checkIP.awk itaIP.list false $ awk -v address="31.207.97.5" -f checkIP.awk itaIP.list false - Stefano Guarella
它完美地运行了,你太棒了!!非常感谢你,ShellFish ; ) - Stefano Guarella

1
您可以使用这个awk脚本:

awk -F- -v arg='2.158.1.2' 'function ipval(arg) {
   split(arg, arr, ".");
   s=0;
   for (i=1; i<=length(arr); i++)
      s += arr[i] * (10**(6-i));
   return s   
}
ipval(arg) >= ipval($1) && ipval(arg) <= ipval($2)' file
2.156.0.0-2.159.255.255-255.252.0.0

ipval将给定的IP地址转换为数字值,以便可以使用算术运算符轻松比较。


1
非常感谢你!;) - Stefano Guarella

1

检查IP地址是否有效并且是否在本地连接中:

if ! ip route get ${ip} | grep -v via > /dev/null;then echo "bad IP";fi

1

grepcidr 命令行工具可以帮助处理这类任务。

COMMAND USAGE
-------------
Usage:
        grepcidr [-V] [-cCDvhais] PATTERN [FILE ...]
        grepcidr [-V]  [-V] [-cCDvhais] [-e PATTERN | -f FILE] [FILE ...]

Each pattern, whether on the command line or inside a file, may be:
CIDR format a.b.c.d/xx or aa:bb::cc::dd/xx
IP range    a.b.c.d-e.f.g.h
Single IP   a.b.c.d or aa:bb:cc::dd

0

我认为上述脚本的这个变体更有用:

function ipval()
{
  RES=`awk -F- -v arg="$1" '{
    split(arg, arr, ".");
    s=0;
    for (i=1; i<=length(arr); i++) { s += arr[i] * (256**(4-i)); }
    print s
  }' <<< '' `
  return $RES
}

read -p "IP:" IP
ipval "$IP"
echo "RES=$RES"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接