4

Я использую IPSet для управления десятками тысяч диапазонов CIDR/ масок IPv4, которые затем связываются с правилами IPTables. Эта установка работает отлично, но я хотел бы получить хороший, высокоуровневый обзор количества IP-адресов хостов, которые IPSet использует для целей отчетности клиентов.

Форматирование записи IPSet постоянно выглядит следующим образом:

123.456.0.0/16 timeout 86400

Поэтому я могу выполнить поиск по строкам, у которых есть timeout чтобы получить значения для действия в диапазонах CIDR/ маска сети, которые содержатся в записи.

Например, если я сохраню вывод IPSet (через ipset -L -n > ipset-20181228.txt) в текстовый файл с именем ipset-20181228.txt а затем запустите комбинацию grep и wc -l следующим образом:

grep  "timeout" ipset-20181228.txt  | wc -l

Я получаю количество из 39 000+ предметов, что соответствует 39 000+ CIDR/ диапазонам маски. Но это (конечно) только подсчет диапазонов CIDR/ маска сети, а не полный подсчет IP-адресов хоста в этом диапазоне.

Я попытался использовать prips (который расширяет значения CIDR/ маска сети до фактических IP-адресов в Bash) с grep, чтобы исключить только элементы с диапазонами CIDR/ маска:

grep -oE '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([0-9]{1,2})' ipset-20181228.txt | awk 'NF { system( "prips " $0)  }' | wc -l

И после колоссальных 20-30 минут (!!!) на моем MacBook Air 2018 года (с включенными фанатами) счет, который я получил, составлял 736 000 000+, что я и собираюсь сделать… Но 20–30 минут - это слишком долго. Я хочу, чтобы это было настолько скриптовым и ненавязчивым, насколько это возможно, и я не могу доверять такой команде для запуска на производственном сервере без израсходования ресурсов; Я имею в виду, посмотрите, как он ведет себя на моей локальной установке для разработки MacBook Air 2018 года.

Есть ли какой-нибудь способ просто рассчитать количество диапазонов CIDR/ маска сети на основе просто значения CIDR/ маска сети? Я надеюсь, что есть какой-то инструмент командной строки - или опция в существующих инструментах, которые я использую - которые я не знаю, которые могут помочь.

2 ответа2

2

Если ваша команда grep выдает такие строки, как 123.456.0.0/16 , вам нужно передать их

awk -F / '{ count[$2]++ } END { for (mask in count) total+=count[mask]*2^(32-mask); print total }'

Команда извлекает только маски (то есть, что после /) и подсчитывает вхождения каждой маски. В конце число хостов вычисляется для каждой обнаруженной маски (2^(32-mask)), умножается на количество вхождений и суммируется.

Заметки:

  • Проверка работоспособности не выполняется. Например, ввод, такой как 1.2.3.4/40 будет принят, нецелочисленный вывод будет рассчитан. Улучшите ваш предварительный фильтр grep если это необходимо.
  • Каждый диапазон независимо вносит свой вклад в общее количество. Если ваши диапазоны перекрываются, вы получите завышенный результат (я думаю, что ваша попытка с prips была не лучше в этом).
0

Я думал, что что-то вроде этого будет работать, так как оригинальный постер использует grep для получения CIDR из строк с timeout:

awk -F'[ /]' '/timeout/ {hosts+=2^(32-$2)};ENDFILE{print "Hosts number in "FILENAME": "hosts;total+=hosts;hosts=0};END {print "Total: "total}' ipset*.txt

РЕДАКТИРОВАТЬ - Программа awk выше работает нормально только с GNU awk . ENDFILE - это расширение GNU.

Я предполагаю, что BSD awk игнорирует ENDFILE и запускает этот раздел, если он был частью основного раздела программы.

Это совместимо с GNU и BSD awk.

awk -F'[ /]' '{if (filename != FILENAME) hosts=0};/timeout/ {hosts+=2^(32-$2)};{filename=FILENAME;file_total[filename]=hosts};END{for (i in file_total) {print "Hosts number in "i": "file_total[i];total+=file_total[i]};{print "Total: "total};}' ipset*.txt

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .