Как лучше всего добавить CIDR из файлов в набор?

Вопрос или проблема

Итак, у меня есть несколько файлов, которые содержат CIDR записи (такие как 1.1.1.0/24). Задача состоит в том, чтобы добавить записи из этих файлов в один NFTables набор, используя bash-скрипт. При этом я ограничен утилитами OpenWRT.

Проблема в том, что в этих файлах может быть много записей, и они могут исчерпать лимит 4096 символов на команду. А также эти файлы автоматически обновляются с помощью cron, поэтому набор нужно периодически стирать и заполнять заново.

Мне кажется, что есть более простой способ сделать это, чем я уже сделал. Я также хочу уменьшить время выполнения этого процесса. Вот моя попытка сделать это.

nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }

Вот еще один вопрос: если в моем файле очень большое количество записей, превысит ли лимит в 4096 символов на команду? И еще один последний вопрос: займет ли это много времени, чтобы сформировать набор, если я добавляю записи по одной в цикле?

Я в первую очередь жду ответов с хорошей практикой.

awk может сформировать строку для выполнения, которая может быть удержана ниже
определенной длины; это несомненно будет более эффективно, чем
xargs, который должен создавать echo ... | tr конвейер.

#!/usr/bin/env awk
{
    len = length()
    if (len > limit) {
        if (length(outbuf)) {
            system("echo " ENVIRON["TARGET_SET"] outbuf)
        }
        outbuf = $0
        limit = 6
    } else {
        outbuf = outbuf "," $0
    }
    limit -= len + 1
}
END {
    if (length(outbuf)) {
        system("echo " ENVIRON["TARGET_SET"] outbuf)
    }
}

"echo " в этом скрипте предназначены для тестирования, вместо этого следует запустить подходящую команду nft .... TARGET_SET должен быть
экспортирован, чтобы awk мог считать его из окружения.

Где вы читали о лимите в 4096 символов в командах nftables? Если у меня есть список из 4000 диапазонов CIDR (это почти 64,000 символов), я могу выполнить вашу команду без ошибок:

# wc -l ranges.txt
400.0 ranges.txt
# export TARGET_SET=example_set
# export CUSTOM_CIDRS_FILE=ranges.txt
# nft add set ip filter $TARGET_SET { type ipv4_addr\; flags interval\; }
# nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }

Команды nft add выполняются за примерно 0.003 секунды с 4000 элементами.

Кажется, что в какой-то момент мы можем столкнуться с ограничениями длины командной строки в Linux, в этом случае мы можем сгруппировать команды. Это добавит элементы партиями по 1000:

xargs -n1000 sh -c '
  nft add element ip filter $TARGET_SET { $(
    echo "$@" | tr " " ","
  ) }' -- < $CUSTOM_CIDRS_FILE

(Обратите внимание, что вышеуказанное предполагает, что TARGET_SET является переменной окружения, а не переменной оболочки.)

Это выполняется за примерно 0.1 секунды для тех же 4000 элементов.

Вы можете использовать директиву nft -f:

echo add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") } | nft -f -

nft возьмет сгенерированную директиву add element из stdin, тем самым преодолевая лимит длины командной строки.

В моем тестировании этого метода на Raspberry Pi 4B добавление списка, содержащего 39065 IPv4 адресов, занимает около 0.5 секунд.

Ответ или решение

Для добавления CIDR-адресов из файлов в набор NFTables с использованием OpenWRT и при наличии ограничений на длину команд в 4096 символов, существует несколько методов. Давайте рассмотрим, как эффективно решить эту задачу, сразу учитывая автоматическое обновление файлов с помощью cron и необходимость периодической очистки набора.

1. Оптимизация процесса добавления CIDR

Для начала определим, как можно организовать добавление адресов из файлов. Ваша задача состоит в том, чтобы избежать превышения ограничения по количеству символов в команде и снизить время выполнения скрипта.

Использование AWK для обработки

Можно использовать awk для обработки файла с CIDR-адресами и создания команды, которая будет разбираться на части в соответствии с ограничениями. Пример скрипта выглядит следующим образом:

#!/usr/bin/env awk
{
    len = length($0)
    if (len > limit) {
        if (length(outbuf)) {
            system("nft add element " ENVIRON["TARGET_SET"] " { " outbuf " }")
        }
        outbuf = $0
        limit = 4096 - 60  # учитываем длину остальных частей команды
    } else {
        outbuf = outbuf "," $0
    }
    limit -= len + 1
}
END {
    if (length(outbuf)) {
        system("nft add element " ENVIRON["TARGET_SET"] " { " outbuf " }")
    }
}

Этот скрипт позволит обрабатывать адреса из файла и добавлять их в набор, избегая превышения лимита на размер команды.

Пакетная обработка с xargs

Это еще один способ, который позволяет избежать ограничения на длину команды, выполняя добавление в пакетах:

export TARGET_SET="example_set"
export CUSTOM_CIDRS_FILE="cidrs.txt"

xargs -n1000 sh -c '
  nft add element ip filter $TARGET_SET { $(
    echo "$@" | tr " " ","
  ) }' -- < $CUSTOM_CIDRS_FILE

Такой подход позволит добавлять элементы по 1000 за раз, что значительно уменьшит нагрузку на командную строку.

2. Очистка набора перед обновлением

Поскольку файлы обновляются автоматически с помощью cron, важно включить процесс очистки набора. Это можно сделать следующим образом:

nft flush set ip filter $TARGET_SET

Запустите эту команду перед добавлением новых элементов, чтобы гарантировать, что предыдущие адреса не будут мешать актуальным данным.

3. Запуск скрипта каждый раз

Чтобы автоматизировать процесс, можно создать bash-скрипт и настроить его запуск с помощью cron. Скрипт будет включать этапы чтения файла CIDR, очистки набора и добавления новых элементов:

#!/bin/bash

TARGET_SET="example_set"
CUSTOM_CIDRS_FILE="cidrs.txt"

# Очистить набор
nft flush set ip filter $TARGET_SET

# Добавить новые CIDR
awk '...' < "$CUSTOM_CIDRS_FILE"

Заключение

Используя предложенные методы, вы сможете эффективно добавлять CIDR-адреса в набор NFTables без риска превышения лимитов командной строки и с минимизацией времени выполнения. Автоматизация процесса улучшит актуальность данных, а использование awk и xargs обеспечит высокую скорость обработки.

Такие подходы не только упрощают процесс управления сетевыми правилами, но и повышают надежность и скорость работы вашего сетевого окружения в OpenWRT.

Оцените материал
Добавить комментарий

Капча загружается...