Лог аутентификации SSH: что означает каждая строка отказа
Где в каждом дистрибутиве записываются неудачные входы по SSH, как расшифровать варианты сообщений и как отличить опечатку от ботнета, идущего по списку.
Где лог лежит на самом деле
На этом спотыкаются первым делом, потому что путь зависит от дистрибутива. Debian и Ubuntu пишут события аутентификации в /var/log/auth.log. RHEL, CentOS, AlmaLinux, Rocky и Fedora — в /var/log/secure. На системах, полностью перешедших на journald, ни того ни другого файла может не быть, и всё живёт в журнале.
Переносимый ответ — journalctl, он работает везде, где есть systemd:
# Переносимо: читать журнал самого sshd в реальном времени
journalctl -u ssh -f # имя юнита в Debian/Ubuntu
journalctl -u sshd -f # имя юнита в RHEL/Fedora
# Только отказы за последние сутки
journalctl -u ssh --since -24h | grep -E 'Failed|Invalid user'
# На дистрибутивах, которые всё ещё пишут файл:
grep -E 'Failed|Invalid user' /var/log/auth.log # Debian/Ubuntu
grep -E 'Failed|Invalid user' /var/log/secure # семейство RHELРасшифровка вариантов сообщений
sshd выдаёт небольшой набор сообщений об отказе, и каждое означает нечто конкретное. Этих пяти хватает почти на всё, что вы увидите:
- Failed password for <user> from <ip> port <n> ssh2 — учётная запись существует, пароль неверен. Либо реальный пользователь ошибся, либо бот угадал существующий логин.
- Failed password for invalid user <user> from <ip> — учётной записи не существует. Почти всегда атака: ваши пользователи знают свои логины. Обычно рядом идёт отдельная строка «Invalid user».
- Connection closed by authenticating user <user> <ip> port <n> [preauth] — клиент отвалился в середине аутентификации. Типично для сканеров, которым нужен был только баннер, и для серверов на ключах, отвергающих парольные попытки.
- Disconnected from authenticating user root <ip> port <n> [preauth] — попытка входа под root на сервере, где root запрещён. Большой объём здесь — самая частая сигнатура на открытом хосте.
- Maximum authentication attempts exceeded for <user> from <ip> — клиент упёрся в MaxAuthTries в рамках одного соединения. Часто это агент, предлагающий много ключей, но с незнакомого адреса — это бот, перебирающий учётные данные.
Как отличить атаку от опечатки
Различают три признака, и перед автоматическим действием нужны все три.
Темп и настойчивость. Человек делает две-три попытки за минуту, а потом либо входит, либо звонит вам. Бот держит ровный темп часами, всю ночь, без пауз.
Разнообразие учётных записей. Человек пробует одну — свою. Бот идёт по списку, и большинства этих записей не существует, что и даёт сигнатуру «invalid user» выше.
Источник. Ваши люди подключаются с нескольких известных адресов. Атаки приходят с хостинговых диапазонов, с нового адреса каждые несколько сотен попыток, нередко из нескольких стран за час.
Эта команда группирует отказы за сутки по адресу источника и показывает, какие имена он пробовал, — все три признака видны сразу:
journalctl -u ssh --since -24h --no-pager |
grep -oE 'Failed password for (invalid user )?[^ ]+ from [0-9.]+' |
awk '{ ip = $NF; user = $(NF-2); count[ip]++; users[ip] = users[ip] " " user }
END { for (i in count) printf "%6d %-16s %s\n", count[i], i, users[i] }' |
sort -rn | head -15Строка, о которой действительно надо оповещать
Неудачные входы — это шум. Есть одно сообщение, которое шумом не является, и оно заслуживает оповещения, а не дашборда:
Accepted password for <user> from <ip> — успешный вход по паролю. Если ваш сервер должен работать только по ключам, эта строка означает, что это не так, и у вас проблема с конфигурацией. Если пароли разрешены, такая строка с незнакомого адреса сразу после серии отказов с того же диапазона — это последовательность, которую вы никогда не хотите увидеть.
Рядом стоит следить за Accepted publickey с отпечатком ключа, который вы не узнаёте, и за любой sudo-сессией пользователя, у которого её быть не должно. И то и другое дёшево завести в оповещения, и значат они несравнимо больше, чем объём отказов.
# Все успешные входы за неделю, с методом и источником
journalctl -u ssh --since -7d --no-pager |
grep -E 'Accepted (password|publickey|keyboard-interactive)'От чтения к блокировке
Читать лог руками — это диагностика, а не защита: к моменту, когда вы запустите команду, атака идёт уже неделю. Что-то меняет только непрерывное выполнение этого цикла и превращение порога в правило фаервола.
Наивная версия читает журнал, считает отказы по источникам и вызывает nft, чтобы добавить адрес в блокирующее множество. Она работает — а потом упирается в те же проблемы, что и любой такой скрипт: множество растёт без ограничений, лог под нагрузкой ротируется и события теряются, юнит тихо умирает после обновления, а одно неудачное совпадение отрезает администратора от единственного входа.
SSH Protector выполняет этот цикл как служба: одно сводное множество nftables, белый список, который всегда приоритетнее блокировки, баны, восстанавливаемые при загрузке, и решение, принимаемое локально, — поэтому оно держится, когда сеть не держится. Он читает тот же поток, что показан выше, ничего от вас не пряча.
FAQ
- Где в Linux записываются неудачные входы по SSH?
- В Debian и Ubuntu — /var/log/auth.log. В RHEL, CentOS, AlmaLinux, Rocky и Fedora — /var/log/secure. На системах, полностью полагающихся на journald, ни того ни другого файла нет, и читать нужно журнал: journalctl -u ssh (или -u sshd, в зависимости от имени юнита в дистрибутиве) — это работает везде.
- Что означает «Failed password for invalid user»?
- Что кто-то попытался войти под учётной записью, которой на машине не существует. Ваши пользователи знают свои логины, так что эта строка почти всегда означает атаку — бот идёт по списку типовых имён вроде root, admin, ubuntu, test, git или oracle. Сам по себе объём не тревожен: это фоновый уровень на любом открытом хосте.
- Почему я вижу тысячи попыток входа под root?
- Потому что root — первое имя в любом атакующем списке, и у ботов нет способа узнать, что на вашем сервере он запрещён. При PermitRootLogin в no или prohibit-password они не могут добиться успеха, но и не прекращают попытки, поскольку попытка им ничего не стоит. Лечится объём блокировкой источников, а не политикой входа.
- Как посмотреть успешные входы по SSH?
- Искать в том же логе «Accepted» — Accepted publickey, Accepted password или Accepted keyboard-interactive, после чего идут имя пользователя, адрес источника и порт. Именно эта строка достойна оповещения: успешный вход по паролю на сервере, который должен работать только по ключам, — это ошибка конфигурации, а такой вход с незнакомого адреса после серии отказов — уже инцидент.
