servers-linux
VPS в Европе: покупка и настройка за 20 минут
Покупка учебного VPS, обновления, отдельный пользователь и sudo, независимые SSH-ключи Linux и Android, безопасный запрет root/password и Fail2ban с проверками и восстановлением.
Фильтр только скрывает команды других контекстов, не меняет место их выполнения.
Параметры команд
203.0.113.10 — адрес из диапазона документации, не настоящий сервер. Замените его своим IPv4 или IPv6. Поддерживаются также частные адреса для VPN/LAN; доступность не проверяется. Примеры: operator, eu-vps, root. Первый пользователь может быть root или логином провайдера с sudo.
Сайт не выполняет команды. Проверьте контекст LOCAL / SERVER / MOBILE перед запуском. Без JavaScript замените примеры вручную и выделите нужный код для копирования.
Что понадобится
- Новый VPS без важных данных, публичный IPv4 и доступ к панели провайдера, независимой web/VNC-консоли и rescue-режиму.
- Первоначальный пользователь и способ входа из панели: root с паролем либо административный пользователь с sudo и уже зарегистрированным SSH-ключом.
- Компьютер с OpenSSH: Терминал macOS/Linux или Ubuntu в WSL на Windows. Команды LOCAL рассчитаны на sh/bash, не PowerShell.
- Телефон с Termux на Android либо SSH-клиентом с генерацией Ed25519 и экспортом публичного ключа; менеджер паролей для паролей и passphrase.
Что получится
- Обновлённая Linux-система с понятным hostname и проверенным возвращением после перезагрузки.
- Отдельный пользователь с sudo; независимые ключи компьютера и телефона проверены до запрета паролей.
- SSH принимает ключи, но не root, пароль или keyboard-interactive; эффективная конфигурация проверена для обоих подключений.
- Fail2ban читает журнал systemd; сохранена резервная копия SSH и есть команды восстановления из консоли.
Перед началом
15–20 минут — ориентир для активных действий, не гарантия. Покупка, обновления на 10 минут и дольше, настройка телефона и перезагрузки могут увеличить время. Инструкция рассчитана на Debian 12/13 и Ubuntu 24.04/26.04; сверена с документацией, но не выдаётся за испытание на реальном VPS каждой версии.
Укажите свой IP, имя нового пользователя, hostname и первоначального администратора в настройках команд. Примеры по умолчанию: 203.0.113.10, operator, eu-vps, root. Примерный IP не является вашим сервером. Имена пользователя и hostname — строчные латинские буквы, цифры и дефис, начинаются с буквы; новый пользователь должен отличаться от первоначального.
1. Купить VPS в Европе
- Выберите европейский дата-центр с приемлемой задержкой и правилами использования. Для учебного сервера ориентир — KVM, 1–2 vCPU, 1–2 ГБ RAM и 20–30 ГБ SSD; для тяжёлых приложений ресурсов потребуется больше.
- Проверьте полную цену с налогами, отдельную стоимость IPv4 и backups, лимит трафика, автопродление и способ окончательного удаления сервера. Выключенный VPS может продолжать тарифицироваться — это зависит от договора.
- Нужны web/VNC-консоль и rescue-режим, доступные без SSH. Проверьте способ входа в консоль, восстановления пароля и подключения диска в rescue до запрета root по SSH.
- Установите чистый Debian 12/13 либо Ubuntu 24.04/26.04 LTS без панели управления. Сохраните IP, первоначальный логин, пароль либо путь к приватному ключу, который соответствует публичному ключу в панели.
- Включите 2FA для аккаунта провайдера. Уточните расписание, хранение и восстановление backups; snapshot перед изменениями полезен, но не заменяет отдельную резервную копию данных.
Конкретный провайдер, цена и партнёрская ссылка не нужны для этих шагов. Покупайте по своим требованиям; условия и доступность образов проверяйте в панели перед оплатой.
2. Проверить сервер и войти впервые
Сначала откройте независимую консоль в панели и войдите локально. Для root выполните следующий блок; для администратора с sudo добавьте sudo перед ssh-keygen. Запишите SHA256-отпечаток ключа хоста. Он удостоверяет сервер, а не ваш пользовательский ключ.[2]
В независимой консоли провайдера: отпечаток Ed25519 сервера
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256На компьютере выберите одну ветку. Парольная: используйте пароль первоначального пользователя из панели. Ключевая: введите полный путь к уже зарегистрированному приватному ключу провайдера; путь не отправляется на сервер. Passphrase этого ключа и пароль сервера — разные вещи.
Ветка A: первоначальный вход по паролю
ssh -o HostKeyAlgorithms=ssh-ed25519 root@203.0.113.10Ветка B: первоначальный вход по существующему ключу
printf "Полный путь к существующему ключу провайдера: "
IFS= read -r provider_key
ssh -i "$provider_key" -o IdentitiesOnly=yes -o HostKeyAlgorithms=ssh-ed25519 root@203.0.113.10Если вошли как root, оставайтесь в этой сессии. Если вошли как ubuntu, debian или другой администратор с sudo, выполните sudo -i: дальше до конца шага 5 команды выполняются именно в полученной root-сессии. Если sudo недоступен, используйте root-консоль провайдера; не продолжайте без административного доступа.
Только для первоначального пользователя с sudo: перейти в root-сессию
sudo -iВ root-сессии: проверить права и установленную систему
id -u
cat /etc/os-release
uname -rid -u должен вывести 0, а os-release — выбранную систему. Оставьте эту сессию открытой.
3. Задать имя сервера
Root-сессия: установить и прочитать hostname
hostnamectl set-hostname eu-vps
hostnamectl --static
cat /etc/hostsПроверьте, что новое имя выводится правильно. Если /etc/hosts содержит строку 127.0.1.1 со старым hostname, замените только его на новое имя, сохранив остальные записи. Следующий блок делает это для короткого имени; если строки нет, добавляет её. Он не меняет DNS и публичный IP.
Root-сессия: согласовать локальное имя в /etc/hosts
python3 - <<'PY'
from pathlib import Path
p = Path("/etc/hosts")
lines = p.read_text().splitlines()
found = False
for i, line in enumerate(lines):
fields = line.split()
if fields and fields[0] == "127.0.1.1":
lines[i] = "127.0.1.1 eu-vps"
found = True
if not found:
lines.append("127.0.1.1 eu-vps")
p.write_text("\n".join(lines) + "\n")
PY
getent hosts eu-vps4. Обновить систему и проверить перезагрузку
apt update обновляет индекс, full-upgrade обновляет пакеты и при необходимости может удалить установленные пакеты. Читайте предлагаемый список до подтверждения: удаление openssh-server, sudo или критичных компонентов — повод остановиться. Это не переход Debian 12 → 13 или Ubuntu 24.04 → 26.04: источники пакетов не меняем.[7][8]
Root-сессия: обновления, затем минимальные административные инструменты
apt update && apt full-upgrade
# Следующую строку выполняйте только после успешного обновления.
apt install sudo adduser python3 needrestartНе используем -y: подтверждайте изменения осознанно. Если пакеты спрашивают про изменённый sshd_config, сохраните текущую рабочую конфигурацию и изучите diff. При занятой блокировке APT дождитесь завершения другого обновления; не удаляйте lock-файлы и не убивайте dpkg.[10]
Root-сессия: проверить пакеты и необходимость рестартов
dpkg --audit
needrestart -r l
if [ -f /var/run/reboot-required ]; then
cat /var/run/reboot-required
if [ -f /var/run/reboot-required.pkgs ]; then cat /var/run/reboot-required.pkgs; fi
fi
uname -rdpkg --audit не должен сообщать о незавершённых пакетах. needrestart -r l только перечисляет устаревшие процессы и проверяет ядро, не перезапускает службы.[11] Ubuntu может сигнализировать о перезагрузке через reboot-required; на Debian не считайте отсутствие этого файла доказательством, что перезагрузка не нужна. Для нового пустого VPS после успешного обновления здесь делаем одну плановую перезагрузку, чтобы проверить загрузку и доступ.
Root-сессия: только после завершения APT и с открытой консолью
systemctl rebootРазрыв SSH ожидаем. Дождитесь загрузки в панели и повторите свою команду первоначального входа из шага 2; отпечаток хоста не должен измениться. Снова получите root через sudo -i, если нужно, и выполните проверки. Если сервер не вернулся — переходите к восстановлению, не настраивайте защиту вслепую.
После повторного входа в root: проверить результат загрузки
hostnamectl --static
uname -r
uptime
systemctl is-active ssh.service
systemctl --failed
needrestart -r lДля ssh.service ожидается active. На Ubuntu может использоваться ssh.socket: это не повод менять socket activation или порт. Если служба не active, проверьте systemctl status ssh.service ssh.socket --no-pager и journalctl -u ssh.service -b --no-pager. Разберите failed units и предупреждения needrestart до следующего шага.
5. Создать отдельного пользователя с sudo
В root-сессии сначала проверьте, что выбранный новый логин ещё не занят. Если команда вывела существующую запись, выберите другое имя: не меняйте чужую учётную запись. adduser запросит новый пароль пользователя; сохраните его для sudo, даже если SSH будет принимать только ключи.
Root-сессия: создать только отсутствующего пользователя
if getent passwd operator; then
printf "Логин уже занят — остановитесь и выберите другой.\n"
else
adduser operator && usermod -aG sudo operator
fi
id operator
sudo -l -U operatorВ id должна присутствовать группа sudo, а sudo -l -U — разрешение выполнять административные команды. Это лишь проверка настройки: реальный sudo в новых SSH-сессиях проверим отдельно. Исходного администратора пока не удаляем.
6. Создать отдельный Ed25519-ключ на компьютере
В новом локальном терминале создайте ключ именно для этого VPS с именем id_ed25519_vps. Ed25519 рекомендован Ubuntu; ssh-keygen интерактивно запросит passphrase — задайте длинную непустую фразу.[3] Это защита приватного ключа на компьютере, не пароль Linux-пользователя.
Проверка существующих файлов без перезаписи и генерация нового ключа
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
key="$HOME/.ssh/id_ed25519_vps"
if [ -e "$key" ] || [ -L "$key" ] || [ -e "$key.pub" ] || [ -L "$key.pub" ]; then
printf "Ключ или .pub уже существует; не перезаписываем. Проверьте, что это нужная пара.\n"
else
ssh-keygen -t ed25519 -a 64 -f "$key" -C "vps-desktop"
fi
ssh-keygen -lf "$HOME/.ssh/id_ed25519_vps.pub" -E sha256
cat "$HOME/.ssh/id_ed25519_vps.pub"Если оба файла уже существуют и это ваша известная пара, используйте её; не соглашайтесь на overwrite. Если остался только приватный файл, восстановите .pub следующим блоком. Если остался только .pub, приватный ключ из него восстановить нельзя: остановитесь и разберитесь с файлами, не удаляя их.
Только если приватный ключ есть, а .pub отсутствует: восстановить публичный
if [ -f "$HOME/.ssh/id_ed25519_vps" ] && [ ! -e "$HOME/.ssh/id_ed25519_vps.pub" ] && [ ! -L "$HOME/.ssh/id_ed25519_vps.pub" ]; then
(umask 077; set -C; ssh-keygen -y -f "$HOME/.ssh/id_ed25519_vps" > "$HOME/.ssh/id_ed25519_vps.pub")
fi7. Установить ключ и проверить вход с компьютера
Выберите один способ установки. A: если сервер уже разрешает парольный SSH-вход нового пользователя, ssh-copy-id добавит только указанный .pub; введите пароль нового пользователя, не root.[5] Если ssh-copy-id не установлен или провайдер запрещает пароли, используйте B — не включайте пароли ради этой команды.
Способ A: при уже разрешённом парольном SSH-входе
ssh-copy-id -i "$HOME/.ssh/id_ed25519_vps.pub" operator@203.0.113.10Способ B: скопируйте одну полную строку из .pub. В исходной root-сессии администратора выполните блок ниже и вставьте её на запрос. Если вы остались в обычной sudo-сессии первоначального администратора, сначала выполните sudo -i. install здесь создаёт каталог с владельцем нового пользователя; authorized_keys дополняется, а не заменяется. Права 700/600 и отсутствие записи для группы/остальных нужны для безопасного использования ключей.[2]
Способ B: установка публичного ключа через исходного администратора, root-сессия
(
set -e
home_dir=$(getent passwd operator | cut -d: -f6)
user_group=$(id -gn operator)
test -n "$home_dir" && test -d "$home_dir"
printf "Вставьте одну полную строку публичного Ed25519-ключа: "
IFS= read -r public_key
case "$public_key" in
"ssh-ed25519 "*) ;;
*) printf "Это не публичный Ed25519-ключ — остановка.\n"; exit 1 ;;
esac
test ! -L "$home_dir/.ssh"
test ! -L "$home_dir/.ssh/authorized_keys"
install -d -m 700 -o operator -g "$user_group" "$home_dir/.ssh"
touch "$home_dir/.ssh/authorized_keys"
printf "\n%s\n" "$public_key" >> "$home_dir/.ssh/authorized_keys"
chown operator:"$user_group" "$home_dir/.ssh/authorized_keys"
chmod 600 "$home_dir/.ssh/authorized_keys"
chmod go-w "$home_dir"
)Теперь обязательно откройте отдельное новое соединение с указанным приватным ключом. -F /dev/null исключает неожиданные настройки клиента и multiplexing, IdentitiesOnly выбирает указанную идентичность, IdentityAgent=none исключает агент; PreferredAuthentications и оба запрета не дают незаметно перейти на пароль.[9] Passphrase локального ключа по-прежнему можно вводить.
Обязательный новый вход только по ключу компьютера
ssh -F /dev/null -i "$HOME/.ssh/id_ed25519_vps" -o IdentitiesOnly=yes -o IdentityAgent=none -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no operator@203.0.113.10В новой сессии пользователя с компьютера: настоящий sudo и права ключей
whoami
id
sudo -k
sudo -v && sudo whoami
stat -c "%U %a %n" "$HOME" "$HOME/.ssh" "$HOME/.ssh/authorized_keys"
printf "%s\n" "$SSH_CONNECTION"whoami должен показать нового пользователя, sudo whoami — root. Если sudo требует пароль, это пароль нового пользователя, не passphrase ключа; NOPASSWD в некоторых образах может не спрашивать его. У .ssh и authorized_keys ожидаются владелец — новый пользователь и права 700/600. Сохраните эту сессию.
8. Подключить телефон отдельным ключом
Android: установите Termux из источника, указанного в официальном README (например, F-Droid), не смешивайте приложение и плагины из разных источников.[14] Пакет openssh включает SSH и ssh-copy-id; SSH-сервер на самом телефоне запускать не требуется.[13]
Android / Termux: установить OpenSSH и создать неперезаписываемый отдельный ключ
pkg update && pkg install openssh
# Далее — только после успешной установки.
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
key="$HOME/.ssh/id_ed25519_vps_phone"
if [ -e "$key" ] || [ -L "$key" ] || [ -e "$key.pub" ] || [ -L "$key.pub" ]; then
printf "Ключ телефона или .pub уже существует — не перезаписываем.\n"
else
ssh-keygen -t ed25519 -a 64 -f "$key" -C "vps-phone"
fi
ssh-keygen -lf "$HOME/.ssh/id_ed25519_vps_phone.pub" -E sha256
cat "$HOME/.ssh/id_ed25519_vps_phone.pub"Задайте непустую passphrase. При существующей известной паре используйте её; только приватный файл позволяет восстановить .pub следующим блоком. Только .pub без приватного — остановка, как на компьютере.
Termux: только восстановление отсутствующего .pub из своего приватного ключа
if [ -f "$HOME/.ssh/id_ed25519_vps_phone" ] && [ ! -e "$HOME/.ssh/id_ed25519_vps_phone.pub" ] && [ ! -L "$HOME/.ssh/id_ed25519_vps_phone.pub" ]; then
(umask 077; set -C; ssh-keygen -y -f "$HOME/.ssh/id_ed25519_vps_phone" > "$HOME/.ssh/id_ed25519_vps_phone.pub")
fiЕсли парольный SSH уже разрешён, выполните ssh-copy-id ниже. Иначе скопируйте только строку публичного ключа телефона и повторите способ B из шага 7 в исходной root-сессии, вставляя новую строку. Первый fingerprint на телефоне сравните с той же независимой консолью, а не только с компьютером.
Termux: только при разрешённом парольном входе установить .pub
ssh-copy-id -i "$HOME/.ssh/id_ed25519_vps_phone.pub" operator@203.0.113.10Termux: новое соединение только по ключу телефона
ssh -F /dev/null -i "$HOME/.ssh/id_ed25519_vps_phone" -o IdentitiesOnly=yes -o IdentityAgent=none -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no operator@203.0.113.10В сессии нового пользователя с телефона: проверить sudo и сохранить контекст
whoami
sudo -k
sudo -v && sudo whoami
printf "%s\n" "$SSH_CONNECTION"9. Запретить root и парольный SSH-вход
Теперь работаем в новой sudo-сессии с компьютера, без sudo -i. У OpenSSH для большинства директив действует первое прочитанное значение; Include раскрывает файлы лексикографически, а не по принципу «последний победил».[1]
Debian и Ubuntu обычно подключают sshd_config.d в начале основного файла.[12][15][3] Поэтому 00-vps-first-20-minutes.conf обычно прочитается раньше 50-cloud-init.conf, но более ранний файл или параметры запуска службы могут изменить результат.
Новый пользователь с sudo: посмотреть реальные Include, Match и параметры службы
sudo cat /etc/ssh/sshd_config
sudo find /etc/ssh/sshd_config.d -maxdepth 1 -name "*.conf" -type f -print -exec cat {} \;
sudo systemctl cat ssh.service
sudo cat /etc/default/sshInclude должен действовать в глобальном контексте до нужных директив, не внутри Match. Match может отдельно разрешить пароли/root для определённых пользователей или адресов; глобального sshd -T недостаточно.[1][2] Следующий блок делает root-only копию всего /etc/ssh в стабильном месте, создаёт только новый 00-файл и добавляет явный Include этого файла первой строкой основного конфига. Это гарантирует глобальное чтение наших директив до cloud-init и других Include; существующие файлы провайдера не редактируются. Даже после этого Match обязательно проверяется.
Один раз: backup и отдельный глобальный конфиг без перезаписи
sudo python3 - <<'PY'
from pathlib import Path
import os
import shutil
backup = Path("/root/vps-first-20-minutes-backup")
custom = Path("/etc/ssh/sshd_config.d/00-vps-first-20-minutes.conf")
main = Path("/etc/ssh/sshd_config")
if os.path.lexists(backup) or os.path.lexists(custom):
raise SystemExit("STOP: backup или 00-файл уже существует; ничего не перезаписываем")
if main.is_symlink():
raise SystemExit("STOP: основной конфиг — symlink; нужен отдельный разбор")
original = main.read_bytes()
backup.mkdir(mode=0o700)
shutil.copytree("/etc/ssh", backup / "ssh", symlinks=True)
custom.parent.mkdir(mode=0o755, exist_ok=True)
with custom.open("x") as f:
f.write("PubkeyAuthentication yes\nPermitRootLogin no\nPasswordAuthentication no\nKbdInteractiveAuthentication no\nAuthenticationMethods publickey\n")
custom.chmod(0o644)
include = b"Include /etc/ssh/sshd_config.d/00-vps-first-20-minutes.conf\n"
main.write_bytes(include + original)
print("Backup:", backup / "ssh")
print("Created:", custom)
PYPubkeyAuthentication оставляет ключи; PermitRootLogin no запрещает root даже с ключом; PasswordAuthentication no и KbdInteractiveAuthentication no закрывают оба парольных пути; AuthenticationMethods publickey требует ключ.[1] Не меняем UsePAM: он используется также для учётных записей и сессий. Формат этих директив проверен в manpages Ubuntu 24.04 и 26.04.[17][18]
Выполните следующий блок отдельно в обеих уже открытых новых сессиях — с компьютера и телефона. SSH_CONNECTION содержит реальный адрес клиента, его порт, адрес сервера и порт сервера. host в -C — имя клиента, не hostname VPS; при UseDNS no это адрес клиента. Если конфигурация использует UseDNS yes и Match Host, сначала определите подтверждённое прямым/обратным DNS имя клиента и замените client_host; без этого не продолжайте. Контекстный образец: user=operator,host=198.51.100.25,addr=198.51.100.25 — это только пример, не результат проверки.[2]
В каждой новой сессии: sshd -t и реальные контекстные значения для пользователя и root
(
set -e
test -n "$SSH_CONNECTION"
set -- $SSH_CONNECTION
test "$#" -eq 4
client_addr=$1
server_addr=$3
server_port=$4
client_host=$client_addr
sudo /usr/sbin/sshd -t
for checked_user in operator root; do
printf "Контекст user=%s host=%s addr=%s laddr=%s lport=%s\n" "$checked_user" "$client_host" "$client_addr" "$server_addr" "$server_port"
effective=$(sudo /usr/sbin/sshd -t && sudo /usr/sbin/sshd -T -C "user=$checked_user,host=$client_host,addr=$client_addr,laddr=$server_addr,lport=$server_port")
printf "%s\n" "$effective" | grep -E "^(pubkeyauthentication|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|usedns) "
for expected in "pubkeyauthentication yes" "permitrootlogin no" "passwordauthentication no" "kbdinteractiveauthentication no" "authenticationmethods publickey"; do
printf "%s\n" "$effective" | grep -Fx "$expected" >/dev/null || { printf "STOP: не получено %s\n" "$expected"; exit 1; }
done
done
)Только после обеих контекстных проверок: применить без закрытия старых сессий
sudo /usr/sbin/sshd -t && sudo systemctl reload ssh.service
sudo systemctl is-active ssh.serviceПосле reload ещё раз выполните команды нового key-only входа из шагов 7 и 8 и sudo whoami на обоих устройствах. Не используйте для доказательства старое соединение. Если новый вход не работает, сохранённая сессия или консоль позволит восстановить конфигурацию. Reload обновляет демон для новых подключений; открытые сессии держите до конца.[2]
10. Включить Fail2ban для SSH
Fail2ban — дополнительный слой против повторных неудачных входов, не замена ключам и обновлениям. Настройки сохраняем в jail.d/*.local, а не в пакетном jail.conf.[4] backend=systemd читает journal и требует Python-модуль systemd; logpath для этого backend не задаём.[6]
Новый пользователь с sudo: установить Fail2ban и поддержку journal
sudo apt update && sudo apt install fail2ban python3-systemd
sudo python3 -c "from systemd import journal; print('systemd journal module: OK')"Создать только отсутствующий jail-файл: 5 ошибок за 10 минут, бан на 1 час
sudo python3 - <<'PY'
from pathlib import Path
p = Path("/etc/fail2ban/jail.d/99-vps-first-20-minutes.local")
with p.open("x") as f:
f.write("[sshd]\nenabled = true\nbackend = systemd\nport = ssh\nmaxretry = 5\nfindtime = 10m\nbantime = 1h\n")
p.chmod(0o644)
print("Created:", p)
PYЕсли файл существует, не перезаписывайте его: изучите содержимое. В отличие от OpenSSH, у Fail2ban поздние .local могут переопределять ранние; итог проверяем клиентом.[4] port=ssh здесь означает стандартный SSH-порт 22, а не его смену. Общую политику firewall не настраиваем, но механизм банов Fail2ban сам использует правила firewall.[16]
Проверить конфигурацию, включить службу и прочитать фактический jail
sudo fail2ban-client -t && sudo systemctl enable --now fail2ban
# Далее — только если тест и запуск успешны.
sudo fail2ban-client reload
sudo systemctl is-active fail2ban
sudo fail2ban-client ping
sudo fail2ban-client status sshd
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd bantime
sudo fail2ban-client get sshd journalmatchОжидаются active, Server replied: pong, существующий jail sshd, maxretry=5, findtime=600 и bantime=3600 секунд; status для systemd должен показывать Journal matches. Команды test/reload/ping/status описаны upstream.[19] Нулевое число банов нормально и не доказывает работу реального бана. Не проверяйте блокировку перебором паролей со своего единственного адреса.
Если служба или jail не работают: диагностика без изменения firewall
sudo systemctl status fail2ban --no-pager
sudo journalctl -u fail2ban -b -n 80 --no-pager
sudo journalctl -u ssh.service -b -n 40 --no-pager
sudo fail2ban-client -dПри ошибке запуска не считайте защиту включённой. Проверяйте наличие python3-systemd, конфликты других jail-файлов и ошибки выбранного пакетного ban action. Отсутствие /var/log/auth.log само по себе не ошибка при systemd backend. В минимальных образах состав пакетов и правила провайдера могут отличаться.
Финальная проверка
- После reload и запуска Fail2ban заново войдите с компьютера и телефона командами key-only из шагов 7–8. В обеих новых сессиях выполните whoami и sudo -k; sudo -v && sudo whoami. Пользователь — новый логин, sudo — root.
- В каждой новой сессии повторите контекстный блок sshd -t/-T из шага 9. Он должен подтвердить все пять значений для нового пользователя и root с реальными адресами обоих устройств.
- hostnamectl --static показывает ваше имя; dpkg --audit не сообщает о незавершённой настройке; ssh.service и fail2ban — active; jail sshd существует, параметры совпадают, журнал читается.
- Проверьте независимую консоль ещё раз. Сохраните путь /root/vps-first-20-minutes-backup/ssh, passphrase обоих ключей, пароль sudo и способ доступа к rescue. Backup содержит приватные ключи хоста — не публикуйте его.
- Только после всех успешных проверок закройте исходную административную сессию. Не удаляйте bootstrap-пользователя провайдера в рамках этой инструкции; отдельные ключи можно отозвать позже после проверки резервного доступа.
Новая sudo-сессия: итоговая диагностика
hostnamectl --static
sudo dpkg --audit
sudo systemctl is-active ssh.service fail2ban
sudo fail2ban-client status sshd
sudo journalctl -u ssh.service -u fail2ban -b -n 60 --no-pagerНеобязательная отрицательная проверка с компьютера: следующий единственный запрос должен получить Permission denied без приглашения пароля. Он исключает ключи и keyboard-interactive и проверяет запрет SSH-пароля. Сам отказ не заменяет успешные входы и sshd -T: он мог бы быть вызван другой причиной. Не повторяйте его циклом — это не тест бана.
Один запрос без ключей: парольная аутентификация должна быть отвергнута
ssh -F /dev/null -o PubkeyAuthentication=no -o PreferredAuthentications=password -o PasswordAuthentication=yes -o KbdInteractiveAuthentication=no -o BatchMode=yes operator@203.0.113.10Готова базовая система для дальнейших задач, а не полностью защищённый production-сервис. Перед размещением данных отдельно настройте резервное копирование, регулярные security updates и доступ только к нужным сервисам. Время и фактические результаты проверок фиксируйте по своему серверу.
Если доступ пропал: восстановление
Не переустанавливайте VPS и не закрывайте рабочую сессию. Используйте оставшуюся sudo/root-сессию либо независимую консоль панели. Запрет PermitRootLogin относится к SSH, не к локальному входу в консоль. Для администратора с sudo выполните sudo -i; следующие команды восстановления — в root-сессии.
Откат ниже предназначен именно для изменений этой статьи: переносит наш единственный 00-файл за пределы Include и возвращает основной sshd_config из конкретного backup. Другие текущие snippets и ключи хоста не удаляет и не перезаписывает. Если после backup вы отдельно меняли другие файлы, сравните их с /root/vps-first-20-minutes-backup/ssh перед восстановлением; не заменяйте целиком /etc/ssh вслепую.
Root в сохранённой сессии или консоли: точечный откат SSH
(
set -e
backup=/root/vps-first-20-minutes-backup
custom=/etc/ssh/sshd_config.d/00-vps-first-20-minutes.conf
disabled="$backup/00-vps-first-20-minutes.conf.disabled"
test -f "$backup/ssh/sshd_config"
test ! -L /etc/ssh/sshd_config
if [ -e "$custom" ] || [ -L "$custom" ]; then
test ! -e "$disabled" && test ! -L "$disabled"
mv "$custom" "$disabled"
fi
cp -a "$backup/ssh/sshd_config" /etc/ssh/sshd_config
/usr/sbin/sshd -t
if systemctl is-active --quiet ssh.service; then
systemctl reload ssh.service
else
systemctl start ssh.service
fi
systemctl status ssh.service --no-pager
)Теперь повторите первоначальный способ входа из шага 2. Этот откат возвращает прежнюю политику аутентификации — она может снова разрешать root/пароли. Исправьте причину, заново проверьте оба ключа и sudo, затем повторите проверку эффективной политики. Не удаляйте backup ради быстрого перезапуска шага 9.
Если причина — бан Fail2ban, в консоли задайте реальный внешний IP заблокированного устройства (из сохранённого SSH_CONNECTION или списка ban, не IP VPS) и снимите только его блокировку.[19]
Root в консоли: прочитать бан и снять его с одного адреса
fail2ban-client status sshd
printf "Внешний IP заблокированного клиента: "
IFS= read -r client_ip
fail2ban-client set sshd unbanip "$client_ip"Root в консоли: только если Fail2ban не отвечает или блокирует восстановление
systemctl stop fail2ban
journalctl -u fail2ban -b -n 80 --no-pagerОстановка временно убирает защиту Fail2ban. После исправления выполните fail2ban-client -t && systemctl start fail2ban, затем ping и status sshd из шага 10 и вновь проверьте оба входа. Не открывайте все порты и не очищайте firewall целиком.
Если система не загружается или консоль не позволяет войти, используйте rescue и инструкции именно вашего провайдера: имя диска и точка монтирования зависят от образа, универсальную опасную команду здесь не подставляем. На подключённом корневом диске backup расположен в /root/vps-first-20-minutes-backup/ssh; восстановите только sshd_config и уберите наш 00-файл, затем загрузитесь с обычного диска. При сбое диска/загрузчика восстановите проверенный snapshot/backup либо обратитесь к поддержке.
Только после независимой проверки нового fingerprint: удалить старую запись
ssh-keygen -R 203.0.113.10Источники
[1] OpenSSH: sshd_config(5): https://man.openbsd.org/sshd_config
[2] OpenSSH: sshd(8), проверка конфигурации и ключи: https://man.openbsd.org/sshd
[3] Ubuntu Server: OpenSSH server: https://documentation.ubuntu.com/server/how-to/security/openssh-server
[4] Debian 12 / Fail2ban: jail.conf(5): https://manpages.debian.org/bookworm/fail2ban/jail.conf.5.en.html
[5] Debian 12: ssh-copy-id(1): https://manpages.debian.org/bookworm/openssh-client/ssh-copy-id.1.en.html
[6] Fail2ban upstream: jail.conf, systemd backend: https://raw.githubusercontent.com/fail2ban/fail2ban/master/config/jail.conf
[7] Debian 13: apt(8): https://manpages.debian.org/trixie/apt/apt.8.en.html
[8] Ubuntu Server: управление пакетами: https://documentation.ubuntu.com/server/how-to/software/package-management
[9] OpenSSH: ssh_config(5), выбор идентичности: https://man.openbsd.org/ssh_config
[10] Ubuntu Server: automatic updates: https://documentation.ubuntu.com/server/how-to/software/automatic-updates
[11] Debian 12: needrestart(1): https://manpages.debian.org/bookworm/needrestart/needrestart.1.en.html
[12] Debian 13: sshd_config(5): https://manpages.debian.org/trixie/openssh-server/sshd_config.5.en.html
[13] Termux upstream: пакет openssh: https://raw.githubusercontent.com/termux/termux-packages/master/packages/openssh/build.sh
[14] Termux: официальная установка: https://github.com/termux/termux-app
[15] Debian 12: sshd_config(5): https://manpages.debian.org/bookworm/openssh-server/sshd_config.5.en.html
[16] Debian 12: fail2ban-client(1): https://manpages.debian.org/bookworm/fail2ban/fail2ban-client.1.en.html
[17] Ubuntu 24.04 LTS: sshd_config(5): https://manpages.ubuntu.com/manpages/noble/en/man5/sshd_config.5.html
[18] Ubuntu 26.04 LTS: sshd_config(5): https://manpages.ubuntu.com/manpages/resolute/man5/sshd_config.5.html
[19] Fail2ban upstream: fail2ban-client(1): https://raw.githubusercontent.com/fail2ban/fail2ban/master/man/fail2ban-client.1
← Все материалы KNOWLEDGE