Самый простой способ grep’а IPv6 / самый короткий regex, который соответствует IPv6 (недействительный адрес не проблема)

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

Я хочу извлечь IPv6-адреса из файлов журнала, которые содержат только действительные IPv6-адреса, с которых кто-то подключился (а также содержат строки с IPv4 и многие другие строки без каких-либо IP, например, /var/log/secure).

Поэтому для этого регулярного выражения не так важно соответствовать только истинным действительным IPv6 согласно RFC, как это делают огромные регулярные выражения с https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses, но оно должно соответствовать всему, что хоть как-то напоминает IPv6, чтобы не выдавало слишком много ложных срабатываний, и должно быть как можно короче, чтобы его было легко запомнить и вводить.

Для быстрого ответа я бы сказал:

egrep "(::)?[0-9a-fA-F]{1,4}(::?[0-9a-fA-F]{1,4}){1,7}(::)?"

но вы должны предполагать, что адрес содержит как минимум две ‘секции’, например:
ff00:3456:: или ff00::3456, вот это: ff00:: не будет найдено.

Другим решением, которое я нашел, является это регулярное выражение:

^(\:\:)?[0-9a-fA-F]{1,4}(\:\:?[0-9a-fA-F]{1,4}){0,7}(\:\:)?$

но это приведет к ложным срабатываниям, таким как строки ‘aaaa’, ‘abc’, поэтому должна быть дополнительная проверка, такая как:

`^.*\:.*\:.*$`

В этом случае фрагмент bash-скрипта выглядит так:

if [[ "$col" =~ ^(\:\:)?[0-9a-fA-F]{1,4}(\:\:?[0-9a-fA-F]{1,4}){0,7}(\:\:)?$ ]] && \
   [[ "$col" =~ ^.*\:.*\:.*$ ]] ; then
    echo "Совпадение IPv6"
else
    echo "Нет совпадения"
fi

это для проверки, представляет ли $col IPv6 или нет. Здесь вам нужно будет разработать код, чтобы сначала разбить запись журнала на секции.

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

Для извлечения IPv6-адресов из лог-файлов, таких как /var/log/secure, можно использовать регулярные выражения различной сложности. В вашем случае, так как важно лишь извлечение адресов, которые хотя бы напоминают IPv6, можно предложить более простое и краткое регулярное выражение.

Вот одно из простых вариантов регулярного выражения для grep:

egrep -o "([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}|::"

Объяснение:

  • ([0-9a-fA-F]{1,4}:){1,7}: Это часть соответствует от одной до семи групп, содержащих от 1 до 4 шестнадцатеричных символов, за которыми следует двоеточие. Это соответствует форматам частей IPv6-адреса.
  • [0-9a-fA-F]{1,4}: Последняя часть соответствует одной части, которая содержит от 1 до 4 шестнадцатеричных символов.
  • |::: Это соответствует краткому представлению IPv6-адреса, где используются двойные двоеточия для обозначения последовательности нулевых частей.

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

Пример использования в bash:

Вот пример кода, который проверит, содержит ли строка действительный IPv6-адрес:

while read -r line; do
    if [[ "$line" =~ ([0-9a-fA-F]{1,4}:){1,7}[0-9a-fA-F]{1,4}|:: ]] && \
       [[ "$line" =~ [a-fA-F0-9]:.*:.* ]]; then
        echo "Найден IPv6 адрес: $line"
    fi
done < /var/log/secure

Объяснение кода:

  • while read -r line; do: Читает строки из файла.
  • [[ "$line" =~ ... ]]: Проверяет строку на совпадение с регулярным выражением для IPv6.
  • [[ "$line" =~ [a-fA-F0-9]:.*:.* ]]: Убеждается, что в строке содержатся хотя бы две части адреса, разделенные двоеточием.
  • echo "Найден IPv6 адрес: $line": Если обе проверки успешны, строка считается содержащей IPv6-адрес.

Это решение должно эффективно помогать в нахождении IPv6-адресов в логах, позволяя при этом исключить ложные срабатывания относительно некорректных строк.

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

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