Вопрос или проблема
У нас есть список CIDR’ов
1.10.10.0/24
5.154.0.0/16
5.181.219.0/24
23.90.68.0/24
31.40.214.0/24
Я хочу проверить, принадлежит ли IP, например: 23.90.68.56 к любому из вышеперечисленных CIDR’ов. Если да, то мы получаем вывод этого CIDR.
Согласно приведенному выше примеру, вывод должен быть 23.90.68.0/24
Я пытался использовать grepcidr, но не знаю, как мы можем вывести этот конкретный CIDR.
Я создаю bash-скрипт для этого, но может ли кто-то помочь мне с этой проблемой вывода? Я пытался искать в интернете, но не нашел ничего полезного.
Вероятно, у вас есть Python:
#!/usr/bin/env python3
import argparse
import ipaddress
import sys
parser = argparse.ArgumentParser()
parser.add_argument("address")
args = parser.parse_args()
addr = ipaddress.ip_address(args.address)
for line in sys.stdin:
cidr = ipaddress.ip_network(line.strip())
if addr in cidr:
print(cidr)
exit(0)
exit(1)
Вот мое решение, обновляющее решение Уолтера Вехоувена выше.
#!/bin/bash
function is_ip_in_cidr()
{
local ip=$1
local cidr=$2
#Сначала обрабатываем CIDR
local network=$(echo $cidr | cut -d/ -f1)
local mask=$(echo $cidr | cut -d/ -f2)
#Квадратная точечная нотация имеет 4 поля. Сдвигаем и добавляем, чтобы получить десятичное число
local network_dec=$(echo $network | awk -F. '{printf("%d\n", (($1 * 256 +$2) * 256 + $3) * 256 + $4) }')
#ТЕСТ echo "network_dec: $network_dec"
#Сдвигаем битовую маску на правильное количество мест для заданной маски
local mask_dec=$((0xffffffff << (32 - $mask)))
#ТЕСТ local mask_dec=$((0x0000000f << (32 - $mask)))
#ТЕСТ printf "mask_dec: %x\n", $mask_dec
#Но ограничиваем битовую маску до 32 бит или 8 шестнадцатеричных разрядов.
local mask_dec2=$((0xffffffff & $mask_dec))
#ТЕСТ printf "mask_dec2: %x\n", $mask_dec2
#Применяем маску к сетевому адресу, чтобы получить биты для проверки
local net1=$(( $mask_dec2 & $network_dec ))
#ТЕСТ printf "net1: %x\n", $net1
#Обрабатываем IP-адрес. Снова Квадратная точечная нотация, сдвигаем и добавляем.
local ip_dec=$(echo $ip | awk -F. '{printf("%d\n", (($1 * 256 +$2) * 256 + $3) * 256 + $4) }')
#ТЕСТ echo "IP DEC: $ip_dec"
#Применяем ту же маску к IP-адресу
local net2=$(( $mask_dec2 & $ip_dec ))
#ТЕСТ printf "net2: %x\n", $net2
#Теперь два сетевых компонента могут быть сравнены
if [[ $net1 == $net2 ]]; then
return 0
else
return 1
fi
}
# Тестируем функцию с примером IP-адреса и CIDR
ip="192.168.1.5"
cidr="192.168.1.0/24"
if $(is_ip_in_cidr $ip $cidr); then
echo "ДА, $ip находится в $cidr"
else
echo "НЕТ, $ip не находится в $cidr"
fi
echo ""
ip="192.168.1.5"
cidr="192.168.0.0/24"
if $(is_ip_in_cidr $ip $cidr); then
echo "ДА, $ip находится в $cidr"
else
echo "НЕТ, $ip не находится в $cidr"
fi
Возможный shell-скрипт:
#!/bin/bash
ip=$1
shift; shift
for net in "$@"
do
nmap -sL -n $net | grep -q $ip && echo $net
done
Если вам нужен список CIDR'ов в файле, используйте ./название_скрипта ip_для_проверки $(cat имя_файла)
. Возможно, это бесполезное использование cat.
./cidr.sh 23.90.68.56 $(cat cidrs.txt)
в python это будет:
import socket
def is_ip_in_cidr(ip, cidr):
network, mask = cidr.split("/")
mask = int(mask)
ip_int = int.from_bytes(socket.inet_aton(ip), "big")
network_int = int.from_bytes(socket.inet_aton(network), "big")
network_mask = (0xFFFFFFFF << (32 - mask)) & 0xFFFFFFFF
return (ip_int & network_mask) == network_int
# Тестируем функцию с примером IP-адреса и CIDR
ip = "192.168.0.5"
cidr = "192.168.0.0/24"
if is_ip_in_cidr(ip, cidr):
print(f"{ip} находится в {cidr}")
else:
print(f"{ip} НЕ находится в {cidr}")
если вы можете использовать предоставленный список как фиксированный набор для проверки так:
import socket
def is_ip_in_cidr(ip, cidrs):
for cidr in cidrs:
network, mask = cidr.split("/")
mask = int(mask)
ip_int = int.from_bytes(socket.inet_aton(ip), "big")
network_int = int.from_bytes(socket.inet_aton(network), "big")
network_mask = (0xFFFFFFFF << (32 - mask)) & 0xFFFFFFFF
if (ip_int & network_mask) == network_int:
return True
return False
# Тестируем функцию с примером IP-адреса и списком CIDR'ов
ip = "192.168.0.5"
cidrs = ["1.10.10.0/24", "5.154.0.0/16", "5.181.219.0/24", "23.90.68.0/24", "31.40.214.0/24"]
if is_ip_in_cidr(ip, cidrs):
print(f"{ip} находится в одном из {cidrs}")
else:
print(f"{ip} НЕ находится ни в одном из {cidrs}")
в bash
#!/bin/bash
function is_ip_in_cidr {
local ip=$1
local cidr=$2
local network=$(echo $cidr | cut -d/ -f1)
local mask=$(echo $cidr | cut -d/ -f2)
local network_dec=$(echo $network | awk -F. '{printf("%d\n", ($1 * 256 + $2) * 256 + $3)}')
local ip_dec=$(echo $ip | awk -F. '{printf("%d\n", ($1 * 256 + $2) * 256 + $3)}')
local mask_dec=$((0xffffffff << (32 - $mask)))
if [[ $((ip_dec & mask_dec)) -eq $((network_dec & mask_dec)) ]]; then
echo "true"
else
echo "false"
fi
}
# Тестируем функцию с примером IP-адреса и CIDR
ip="192.168.0.5"
cidr="192.168.0.0/24"
if $(is_ip_in_cidr $ip $cidr); then
echo "$ip находится в $cidr"
else
echo "$ip НЕ находится в $cidr"
fi
Я вижу, что некоторые из решений, предоставленных здесь, очень медленные, и никто не использует grepcidr.
Чтобы ответить на вопрос:
Я пытался использовать grepcidr, но не знаю, как мы можем вывести этот конкретный CIDR.
Вот как вы можете использовать grepcidr для обратного поиска:
cat << EOF > /tmp/list_of_CIDRs
5.154.0.0/16
5.181.219.0/24
23.90.68.0/24
31.40.214.0/24
EOF
cat << EOF > /tmp/list_of_IPs
1.1.1.1
5.181.219.42
23.90.68.56
23.90.68.98
EOF
cat /tmp/list_of_CIDRs | while read CIDR
do
if MATCH=$(grepcidr $CIDR < /tmp/list_of_IPs)
then
echo $CIDR содержит $MATCH
fi
done
Выход:
5.181.219.0/24 содержит 5.181.219.42
23.90.68.0/24 содержит 23.90.68.56 23.90.68.98
Ответ или решение
Проверка принадлежности IP-адреса к подсети в формате CIDR
Ситуация, когда необходимо проверить, принадлежит ли IP-адрес определенной подсети в формате CIDR (Classless Inter-Domain Routing), довольно распространена в области информационных технологий. В данной статье детально рассмотрим, как можно решить эту задачу с помощью bash-скрипта, Python и утилиты grepcidr
.
Цели и предпосылки
Мы имеем список CIDR и желаем проверить, принадлежит ли указанный IP-адрес к какому-либо из них. В качестве примера, приведем следующие CIDR:
1.10.10.0/24
5.154.0.0/16
5.181.219.0/24
23.90.68.0/24
31.40.214.0/24
И мы хотим проверить IP-адрес 23.90.68.56
. Ожидаемый результат: 23.90.68.0/24
.
Использование Bash
Для проверки принадлежности IP-адреса к CIDR с помощью bash можно использовать следующий скрипт:
#!/bin/bash
function is_ip_in_cidr() {
local ip=$1
local cidr=$2
local network=$(echo $cidr | cut -d/ -f1)
local mask=$(echo $cidr | cut -d/ -f2)
local network_dec=$(echo $network | awk -F. '{printf("%d\n", (($1 * 256 + $2) * 256 + $3) * 256 + $4))}')
local mask_dec=$((0xffffffff << (32 - $mask)))
local net1=$(( $network_dec & $mask_dec ))
local ip_dec=$(echo $ip | awk -F. '{printf("%d\n", (($1 * 256 + $2) * 256 + $3) * 256 + $4))}')
local net2=$(( $ip_dec & $mask_dec ))
[[ $net1 == $net2 ]]
}
ip="23.90.68.56"
for cidr in 1.10.10.0/24 5.154.0.0/16 5.181.219.0/24 23.90.68.0/24 31.40.214.0/24; do
if is_ip_in_cidr "$ip" "$cidr"; then
echo "$ip принадлежит $cidr"
fi
done
Эта функция проверяет, принадлежит ли IP-адрес к заданной подсети, используя побитовые операции.
Использование Python
Если предположить, что более удобно использовать Python, то следующим образом можно реализовать задачу:
import ipaddress
def is_ip_in_cidr(ip, cidrs):
addr = ipaddress.ip_address(ip)
for cidr in cidrs:
if addr in ipaddress.ip_network(cidr):
print(f"{ip} принадлежит {cidr}")
return
print(f"{ip} не принадлежит ни одной из подсетей")
ip_address = "23.90.68.56"
cidr_list = [
"1.10.10.0/24",
"5.154.0.0/16",
"5.181.219.0/24",
"23.90.68.0/24",
"31.40.214.0/24",
]
is_ip_in_cidr(ip_address, cidr_list)
Использование grepcidr
Если вы хотите использовать утилиту grepcidr
, чтобы упростить проверку, вы можете сделать следующее:
echo "23.90.68.56" | grepcidr -f <(printf "1.10.10.0/24\n5.154.0.0/16\n5.181.219.0/24\n23.90.68.0/24\n31.40.214.0/24")
Эта команда проверит, принадлежит ли IP-адрес к одной из предоставленных подсетей и выведет соответствующие CIDR.
Заключение
Таким образом, существует несколько способов проверки принадлежности IP-адреса к подсетям в формате CIDR. Используйте bash, Python или утилиты командной строки в зависимости от ваших предпочтений и условий работы. Каждый из этих методов позволяет эффективно проверять IP-адреса и может быть адаптирован под конкретные требования вашего проекта.