LINUX.ORG.RU

Как с помощью sed вытащить IP из /var/log/secure*

 , , ,


1

4

Добрый день, коллеги!

Пожалуйста, помогите мне распутаться в задачке с выделением IP адресов неудавшихся интрудеров, которые отметились в /var/log/secure* (CentOS 7.3) при попытке войти по ssh при вЫключенной авторизации по паролю (/etc/ssh/sshd_config: PasswordAuthentification no)

Имеем:

  1. Строки, выбранные из /var/log/secure*, содержащие упоминание о попытке входа:
    grep 'BREAK-IN ATTEMPT' /var/lor/secure* > /tmp/break-in.log
    
  2. Попытку вытащить из квадратных скобок IP с помощью sed (как наиболее лёгкий и быстрый фильтр):
    sed -r 's/.* [^[]*\[([^]]*)\].*/\1/' /tmp/break-in.log > /tmp/break-in_ip.log
    

Беда в том, что там же в логе, в таких же квадратных скобках пишется ещё и порт источника (если я ничего не путаю). Как бы то ни было, первое числовое значение, упоминаемое в строке лога в квадратных скобках, нужно отбросить и забрать только сам IP, т.е. текст из ВТОРОЙ пары квадратых скобок.

Аналогичная задача для вычленения IP горе-интрудеров при включЁнной аутентификации у меня решается аналогично и проблем не вызывает:

grep 'Failed' /var/log/secure* | sed -n 's/.*from \([0-9.]\+\).*/\1/p'
Хотелось бы достичь аналогичного и на этот раз. Заранее благодарен за помощь!



Последнее исправление: root66 (всего исправлений: 1)

Ответ на: комментарий от vodz

Пример строки из лог-файла

Спасибо за Ваш отклик!

Поясню: мне нужно из строки вида

/var/log/secure-20170625:Jun 20 11:02:03 VPCEB1M1R sshd[18881]: reverse mapping checking getaddrinfo for 109.173.178.186.static.pichincha.andinanet.net [186.178.173.109] failed - POSSIBLE BREAK-IN ATTEMPT!
получить ТОЛЬКО IP адрес, с которого была предпринята попытка входа, т.е., в данном случае:
186.178.173.109

root66
() автор топика
Последнее исправление: root66 (всего исправлений: 2)
Ответ на: комментарий от joy4eg

Не всегда попадает в нужное поле

AWK, на мой взгляд, тяжелее sed и избыточен для таких задачек. Как бы то ни было, иногда эта конструкция действительно попадает на IP, в других случаях - произвольное слово (например «mapping»). Попробуйте сами :-)

root66
() автор топика
Последнее исправление: root66 (всего исправлений: 1)
Ответ на: комментарий от Jopich1

Спасибо, так я могу и на C написать интеллектуальный разборщик логов :-) Задача состоит в том, чтобы сделать это легко и красиво раз и навсегда.

root66
() автор топика

Из-за жадности, вроде, и так всё работает. Но можно сделать иначе и выбирать только последние скобки:

sed -r 's/^.*\[([^]]*)\][^][]*$/\1/'

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Спасибо огромное!

На всех логах ещё погоняю, но на одной строчке, вроде бы, это - именно то, что нужно. По крайней мере до тех пор, пока RedHat не поменяет формат своих логов :-)

root66
() автор топика
Ответ на: Спасибо огромное! от root66
[root@vpceb1m1r ~]# grep 'BREAK-IN ATTEMPT' /var/log/secure* | sed -r 's/^.*\[([^]]*)\][^][]*$/\1/'

Сначала идёт перечень портов :-( Только за ним - IP адреса. Аналогично той картине, которую я описывал в первом сообщении. Видимо, надо копать дальше... Но за пример конструкции всё равно спасибо! Где-нибудь, да пригодится :-)

root66
() автор топика
Последнее исправление: root66 (всего исправлений: 1)
Ответ на: комментарий от beastie

Этот вариант - живой, но есть в этом логе и строки другого формата:

/var/log/secure:Jul 17 03:22:29 VPCEB1M1R sshd[22273]: Address 190.50.221.203 maps to 190-50-221-203.speedy.com.ar, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!

И вот их он, по понятным причинам, выкидывет немного попорченными, но почти полностью.

26626]: Address 187.32.73.238 maps to 187-032-073-238.static.ctbctelecom.com.br, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!
Видимо, прийдётся строить цепочку sed'ов, фильртуя уже этот мусор.

root66
() автор топика

Пока сделал так:

#!/bin/bash

IPFAILED="/tmp/ip-failed_$(date +%Y-%m-%d).log"
SSHDFAILED="/tmp/sshd-failed_$(date +%Y-%m-%d).log"
SSHDBREAKIN="/tmp/sshd-break-in_$(date +%Y-%m-%d).log"
SSHDINVAIDUSER="/tmp/sshd-invalid-user_$(date +%Y-%m-%d).log"
TEMPFILE="$(mktemp /tmp/ip-failed.XXXXXXXX)"

[[ -n "$1" ]] && IPFAILED="$1"

grep 'Failed' /var/log/secure* > $SSHDFAILED
grep 'BREAK-IN ATTEMPT' /var/log/secure* > $SSHDBREAKIN
grep 'Invalid user' /var/log/secure* > $SSHDINVAIDUSER

sed -n 's/.*from \([0-9.]\+\).*/\1/p' $SSHDFAILED > $TEMPFILE
sed -n 's/.*Address \([0-9.]\+\).*/\1/p' $SSHDBREAKIN >> $TEMPFILE
sed 's/\] failed.*//;s/.*\[//' $SSHDBREAKIN | sed '/Address/d' >> $TEMPFILE
sed -n 's/.*from \([0-9.]\+\).*/\1/p' $SSHDINVAIDUSER >> $TEMPFILE

sort -u $TEMPFILE > $IPFAILED
rm -f "$TEMPFILE"

exit 0

Вероятно, не самое красивое решение из всех возможных, но оно пока работает.
Если кому-то ещё пригодится - буду рад.
Огромное спасибо всем откликнувшимся!

root66
() автор топика
Ответ на: Пока сделал так: от root66

можно и сразу в $TEMPFILE без всяких sed

grep 'BREAK-IN ATTEMPT' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]' >> $TEMPFILE

или даже без $TEMPFILE (чтоб лишний раз на диск не писать)

a=$(grep 'Failed' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]')
b=$(grep 'BREAK-IN ATTEMPT' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]')
echo -e "$a\n$b" | sort -u | grep -v "^$" > $IPFAILED
iTA05
()
Ответ на: Пока сделал так: от root66

upd: можно и без скобок конечно, но я бы грепал по скобкам в переменные (на всякий случай, чтобы не промахнуться), а скобки бы уже в конце убрал при выводе в $IPFAILED какнить так

echo -e "$a\n$b" | sort -u | grep -o -E '([0-9]{1,3}[\.]){3}[0-9]{1,3}' > $IPFAILED
в итоге скрипт укорачивается как-то так...
#!/bin/bash

IPFAILED="/tmp/ip-failed_$(date +%Y-%m-%d).log"

[[ -n "$1" ]] && IPFAILED="$1"

a=$(grep 'Failed' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]')
b=$(grep 'BREAK-IN ATTEMPT' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]')
c=$(grep 'Invalid user' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]')

echo -e "$a\n$b\n$c" | sort -u | grep -o -E '([0-9]{1,3}[\.]){3}[0-9]{1,3}' > $IPFAILED

exit 0

iTA05
()
Ответ на: комментарий от Bers666

:-)

Bers666, спасибо, что не остался равнодушным к моей просьбе о помощи!
Отдельное спасибо за то, что обратил внимание на «grep -o -E». Я не сторонник сильно сокращать тексты скриптов в ущерб их читабельности, т.к. комментарии в них, как правило, не пишу (как и все здесь присутствующие, подозреваю).
По поводу конструкции «а=$(grep...)», правильно я его понимаю - мы копируем блок строк в переменную и фильтруем уже её?

root66
() автор топика
Ответ на: комментарий от Bers666

Абсолютно верное предположение

Автоматизирую создание ACL для Wi-Fi роутеров LinkSys и ZyXEL на удалённых точках присутствия (типа - офисов).

root66
() автор топика
Ответ на: Абсолютно верное предположение от root66

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

Bers666 ★★★★★
()
Ответ на: комментарий от Bers666

Спасибо!

Посмотрю, как это можно поженить между собой.

root66
() автор топика
Ответ на: комментарий от iTA05

Проверил предложенную конструкцию "в бою"

Итог таков:

  • grep 'BREAK-IN ATTEMPT' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]'
    
    выдаёт IP адреса, обрамлённые квадратными скобками
  • grep 'Failed' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]'
    
    и
    grep 'Invalid user' /var/log/secure* | grep -o -E '\[([0-9]{1,3}[\.]){3}[0-9]{1,3}\]'
    
    не выдают ничего. Т.е. - вообще тишина.

Вывод: привлекательная лаконичность конструкций grep несёт в себе некоторые подводные камни, с которыми ещё предстоит разбираться.

root66
() автор топика
Последнее исправление: root66 (всего исправлений: 1)

выдаёт IP адреса, обрамлённые квадратными скобками

так и надо, при записи в $IPFAILED они убираются.

не выдают ничего. Т.е. - вообще тишина.

значит под условие адреса не попадают (не заключены в [ ] в логе), отбирайте их по другим условиям. Я для наглядности скриптик набросал, чтобы ход мысли был понятен.

iTA05
()
Ответ на: комментарий от iTA05

можно и сразу в $TEMPFILE без всяких sed

А можно сразу на bash без grep:

#!/bin/bash

for file in /var/log/secure* ; do
        while read l; do
          if [[ "$l" =~ 'BREAK-IN ATTEMPT' || "$l" =~ 'Failed' ]]; then
                if [[ "$l" =~ \[([0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?)\] ]]; then
                        echo "${BASH_REMATCH[1]}"
                fi
          fi
        done < "$file" | sort -nu
done

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.