diff --git a/content/posts/ubuntu-24-base-hardening/index.md b/content/posts/ubuntu-24-base-hardening/index.md new file mode 100644 index 0000000..b87454b --- /dev/null +++ b/content/posts/ubuntu-24-base-hardening/index.md @@ -0,0 +1,1143 @@ +--- +title: "Ubuntu 24.04: базовая настройка и hardening для production" +date: 2026-07-07 +draft: false +description: "Пошаговая настройка Ubuntu 24.04 LTS (Noble Numbat) для production: SSH, firewall, fail2ban, swap, sysctl, автообновления, логи, бэкап конфигов." +tags: ["ubuntu-24.04", "security", "hardening", "ssh", "ufw", "fail2ban", "sysctl", "production", "linux"] +categories: ["Безопасность"] +series: ["Linux Hardening"] +series_order: 3 +--- + +# Ubuntu 24.04: базовая настройка и hardening для production + +Ubuntu 24.04 LTS - production-ready дистрибутив с поддержкой до 2029 года (стандартная) и до 2034 года (расширенная через Ubuntu Pro). Из коробки он безопаснее голого Debian - UFW предустановлен, `unattended-upgrades` работает сразу - но настройки по умолчанию далеки от production-ready. + +Статья покрывает всё что нужно для сервера без контейнеров. Docker - отдельная тема. + +**Что получишь на выходе:** +- SSH доступен только по ключам с нестандартного порта +- Firewall блокирует всё лишнее +- Fail2ban режет брутфорс +- Swap настроен как файл (гибко, без переразбивки диска) +- Ядро защищено от базовых сетевых атак +- Автообновления безопасности без ручного вмешательства +- Ненужные сервисы отключены +- Логи ротируются, диск не забивается +- Конфиги забэкаплены + +## Исходные данные + +- Чистый Ubuntu 24.04 LTS (Noble Numbat) +- Root доступ или пользователь с sudo +- Статический IP + +Проверь версию: + +```bash +lsb_release -a +``` + +Ожидаемый вывод: +``` +Distributor ID: Ubuntu +Release: 24.04 +Codename: noble +``` + +**Про пользователя:** Ubuntu при установке создаёт непривилегированного пользователя с sudo. Если устанавливал с таким пользователем - используй его. Если получил root-only сервер (облако, VPS) - создадим пользователя в разделе SSH. + +Все команды выполняются с `sudo` если не указано иное. Если работаешь от root - `sudo` можно опустить. + +## Обновление системы + +```bash +sudo apt update +sudo apt upgrade -y +sudo apt dist-upgrade -y +sudo apt autoremove -y +``` + +Ubuntu использует `needrestart` - после обновления сам сообщит какие сервисы нужно перезапустить. Если обновилось ядро, предложит перезагрузиться. + +Проверь явно: + +```bash +[ -f /var/run/reboot-required ] && echo "Reboot needed" || echo "No reboot needed" +``` + +Если нужна: + +```bash +sudo reboot +``` + +### Snap пакеты + +Ubuntu активно использует snap. Обнови snap пакеты отдельно: + +```bash +sudo snap refresh +``` + +Посмотри что установлено из snap: + +```bash +snap list +``` + +Удали ненужное - каждый snap это отдельный процесс и место на диске: + +```bash +# Пример удаления +sudo snap remove lxd +sudo snap remove multipass +``` + +На минимальной серверной установке snap пакетов обычно нет или только `core` - это нормально. + +## Базовые утилиты + +```bash +sudo apt install -y \ + curl wget git vim htop iotop iftop \ + net-tools dnsutils tcpdump \ + screen tmux \ + rsync unzip \ + ca-certificates gnupg2 lsb-release \ + smartmontools +``` + +## Настройка системы + +### Hostname + +```bash +sudo hostnamectl set-hostname srv01.example.com +``` + +Добавь в `/etc/hosts`: + +```bash +sudo nano /etc/hosts +``` + +``` +127.0.0.1 localhost +YOUR_IP srv01.example.com srv01 + +::1 localhost ip6-localhost ip6-loopback +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +``` + +Замени `YOUR_IP` на реальный IP сервера. + +### Timezone + +```bash +sudo timedatectl set-timezone Europe/Moscow +``` + +Проверь: + +```bash +timedatectl +``` + +Ubuntu 24.04 использует `systemd-timesyncd` для синхронизации времени - он работает из коробки. Проверь: + +```bash +timedatectl show-timesync +``` + +Если нужен `ntpd` вместо `timesyncd` - это отдельная история. Для большинства серверов `timesyncd` достаточен. + +### Локаль + +```bash +sudo apt install -y locales +sudo dpkg-reconfigure locales +``` + +Выбери `en_US.UTF-8` как основную. Добавь `ru_RU.UTF-8` если нужна кириллица. + +Проверь: + +```bash +locale +``` + +Должно быть `LANG=en_US.UTF-8`. + +### DNS и systemd-resolved + +Ubuntu 24.04 использует `systemd-resolved` - DNS резолвер работает на `127.0.0.53`. `/etc/resolv.conf` это симлинк. + +Проверь: + +```bash +resolvectl status +``` + +Посмотри на какой файл указывает симлинк: + +```bash +ls -la /etc/resolv.conf +``` + +Это нормально - не трогай если резолвинг работает. Если настраиваешь статический DNS: + +```bash +sudo nano /etc/systemd/resolved.conf +``` + +```ini +[Resolve] +DNS=8.8.8.8 8.8.4.4 +FallbackDNS=1.1.1.1 +``` + +```bash +sudo systemctl restart systemd-resolved +``` + +**Важно:** Docker контейнеры не могут использовать `127.0.0.53` - это адрес loopback недоступный из контейнера. Для Docker-хоста это решается отдельно в следующей статье серии. + +## Пользователь и SSH + +### Создание пользователя (если нет) + +Если получил сервер без непривилегированного пользователя: + +```bash +adduser admin +usermod -aG sudo admin +``` + +Проверь: + +```bash +groups admin +# admin : admin sudo +``` + +### SSH ключи + +На своей рабочей машине сгенерируй ключ: + +```bash +# Linux/macOS +ssh-keygen -t ed25519 -C "admin@srv01" +``` + +```powershell +# Windows +ssh-keygen -t ed25519 +``` + +Скопируй публичный ключ на сервер: + +```bash +# Linux/macOS +ssh-copy-id admin@YOUR_IP +``` + +```powershell +# Windows +type $env:userprofile\.ssh\id_ed25519.pub | ssh admin@YOUR_IP "mkdir -m 700 -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" +``` + +Проверь вход по ключу - не должен спрашивать пароль: + +```bash +ssh admin@YOUR_IP +``` + +### SSH hardening + +Ubuntu 24.04 хранит конфигурацию SSH в `/etc/ssh/sshd_config.d/` - основной файл не трогаем. + +Создай файл с настройками: + +```bash +sudo nano /etc/ssh/sshd_config.d/99-hardening.conf +``` + +``` +# Нестандартный порт - отсекает большинство ботов +Port 2222 + +# Только ключи, без паролей +PubkeyAuthentication yes +AuthorizedKeysFile .ssh/authorized_keys +PasswordAuthentication no +PermitEmptyPasswords no +ChallengeResponseAuthentication no +KbdInteractiveAuthentication no + +# Запретить root логин +PermitRootLogin no + +# Ограничения сессий +MaxAuthTries 3 +MaxSessions 3 +LoginGraceTime 30 + +# Таймауты +ClientAliveInterval 300 +ClientAliveCountMax 2 + +# Отключить лишнее +X11Forwarding no +PrintMotd no +AcceptEnv LANG LC_* + +# Только IPv4 (убери если используешь IPv6) +AddressFamily inet +``` + +**Важно:** Ubuntu 24.04 использует socket-активацию через `ssh.socket` - порт слушает не sshd напрямую, а сокет-юнит. Обычный `systemctl restart ssh` перезапускает только сервис, порт остаётся прежним. Для применения нового порта нужно перезапускать именно сокет. + +**КРИТИЧНО:** Перед перезапуском открой вторую сессию и не закрывай её. + +Проверь конфиг на ошибки: + +```bash +sudo sshd -t +``` + +Нет вывода - нет ошибок. Примени: + +```bash +sudo systemctl daemon-reload +sudo systemctl restart ssh.socket +``` + +Проверь что сервис поднялся на новом порту: + +```bash +sudo ss -tlnp | grep sshd +``` + +Ожидаемый вывод: +``` +LISTEN 0 4096 0.0.0.0:2222 +``` + +Убедись что конфиг сокета подхватил изменение: + +```bash +sudo systemctl cat ssh.socket +``` + +Строка `ListenStream=0.0.0.0:2222` подтверждает что порт применился. + +В новом терминале проверь подключение: + +```bash +ssh -p 2222 admin@YOUR_IP +``` + +Если работает - старые сессии можно закрывать. + + +### SSH banner (опционально) + +```bash +sudo nano /etc/ssh/banner +``` + +``` +############################################################################### +# Доступ только для авторизованных пользователей. # +# Все действия логируются. # +# Несанкционированный доступ преследуется по понятиям! # +############################################################################### +``` + +Добавь в `/etc/ssh/sshd_config.d/99-hardening.conf`: + +``` +Banner /etc/ssh/banner +``` + +Перезапусти: + +```bash +sudo systemctl restart ssh +``` + +## Firewall (UFW) + +UFW в Ubuntu предустановлен, но **по умолчанию выключен**. + +Проверь статус: + +```bash +sudo ufw status +``` + +Скорее всего увидишь `Status: inactive`. + +### Настройка правил + +**Важно:** сначала правила, потом включение. Иначе заблокируешь себя. + +```bash +# Блокировать все входящие +sudo ufw default deny incoming + +# Разрешить все исходящие +sudo ufw default allow outgoing +``` + +Разрешаем SSH на новом порту: + +```bash +# Замени 2222 на свой порт +sudo ufw allow 2222/tcp comment 'SSH' +``` + +Rate limiting на SSH: + +```bash +sudo ufw limit 2222/tcp comment 'SSH rate limit' +``` + +Включаем: + +```bash +sudo ufw enable +``` + +Проверь: + +```bash +sudo ufw status verbose +``` + +Ожидаемый вывод: +``` +Status: active +Logging: on (low) +Default: deny (incoming), allow (outgoing), disabled (routed) +New profiles: skip + +To Action From +-- ------ ---- +2222/tcp LIMIT IN Anywhere # SSH rate limit +2222/tcp (v6) LIMIT IN Anywhere (v6) # SSH rate limit +``` + +### Открытие дополнительных портов (опционально) + +```bash +# HTTP/HTTPS +sudo ufw allow 80/tcp comment 'HTTP' +sudo ufw allow 443/tcp comment 'HTTPS' + +# PostgreSQL только с конкретного IP +sudo ufw allow from 192.168.1.10 to any port 5432 comment 'PostgreSQL' +``` + +Проверь открытые порты на хосте: + +```bash +ss -tulnp +``` + +## Fail2ban + +```bash +sudo apt install -y fail2ban +``` + +Создай локальный конфиг: + +```bash +sudo nano /etc/fail2ban/jail.local +``` + +```ini +[DEFAULT] +# Бан на 1 час +bantime = 3600 +# За 10 минут +findtime = 600 +# После 3 неудачных попыток +maxretry = 3 +# Не банить свои IP +ignoreip = 127.0.0.1/8 ::1 + +[sshd] +enabled = true +port = 2222 +filter = sshd +logpath = /var/log/auth.log +maxretry = 3 +bantime = 3600 +``` + +Замени `2222` на свой SSH порт. + +**Особенность Ubuntu 24.04:** `systemd-journald` по умолчанию не пишет в `/var/log/auth.log`. Если файл отсутствует или пустой: + +```bash +ls -la /var/log/auth.log +``` + +Включи запись в файл: + +```bash +sudo nano /etc/rsyslog.d/50-default.conf +``` + +Убедись что строка не закомментирована: + +``` +auth,authpriv.* /var/log/auth.log +``` + +Перезапусти rsyslog: + +```bash +sudo systemctl restart rsyslog +``` + +Или используй journald backend в fail2ban - он умеет читать логи напрямую из journald без файлов: + +```bash +sudo nano /etc/fail2ban/jail.local +``` + +Добавь в секцию `[sshd]`: + +```ini +[sshd] +enabled = true +port = 2222 +filter = sshd +backend = systemd +maxretry = 3 +bantime = 3600 +``` + +При `backend = systemd` параметр `logpath` не нужен - fail2ban читает journald напрямую. + +Запусти: + +```bash +sudo systemctl enable fail2ban +sudo systemctl start fail2ban +``` + +Проверь статус: + +```bash +sudo fail2ban-client status +sudo fail2ban-client status sshd +``` + +## Swap + +Swap в виде файла - гибче раздела: можно увеличить или уменьшить без переразбивки диска. + +### Создание swap файла + +Проверь текущий swap: + +```bash +free -h +swapon --show +``` + +Ожидаемый вывод если swap отсутствует: +``` +Swap: 0B 0B 0B +``` + +Создай файл (пример - 2GB): + +```bash +sudo fallocate -l 2G /swapfile +``` + +Если `fallocate` не поддерживается файловой системой (например btrfs): + +```bash +sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress +``` + +Установи права: + +```bash +sudo chmod 600 /swapfile +``` + +Инициализируй и активируй: + +```bash +sudo mkswap /swapfile +sudo swapon /swapfile +``` + +Проверь: + +```bash +free -h +swapon --show +``` + +Ожидаемый вывод: +``` + total used free shared buff/cache available +Mem: 1.9Gi 860Mi 240Mi 2.5Mi 1.0Gi 1.1Gi +Swap: 2.0Gi 0B 2.0Gi + +NAME TYPE SIZE USED PRIO +/swapfile file 2G 0B -2 +``` + +Добавь в `/etc/fstab` для автомонтирования после перезагрузки: + +```bash +echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab +``` + +### Настройка swappiness + +`swappiness` определяет агрессивность использования swap. Для production - снижаем: + +```bash +cat /proc/sys/vm/swappiness +# по умолчанию 60 +``` + +Установи постоянно: + +```bash +echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-swap.conf +sudo sysctl -p /etc/sysctl.d/99-swap.conf +``` + +Значение `10` - swap используется только когда RAM заполнена на 90%+. + +### Изменение размера swap + +Нельзя перезаписать активный swap файл - ядро блокирует его пока он используется: + +``` +$ sudo fallocate -l 4G /swapfile +fallocate: fallocate failed: Text file busy + +$ sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress +dd: failed to open '/swapfile': Text file busy +``` + +Сначала отключи swap, затем меняй размер: + +```bash +sudo swapoff /swapfile +``` + +```bash +sudo fallocate -l 4G /swapfile +``` + +```bash +sudo mkswap /swapfile +``` + +```bash +sudo swapon /swapfile +``` + +Проверь результат: + +```bash +free -h +``` + +Ожидаемый вывод: +``` + total used free shared buff/cache available +Mem: 1.9Gi 872Mi 227Mi 2.5Mi 1.0Gi 1.1Gi +Swap: 4.0Gi 0B 4.0Gi +``` + +Запись в `/etc/fstab` менять не нужно - путь тот же. + +### Удаление swap + +```bash +sudo swapoff /swapfile +``` + +```bash +sudo rm /swapfile +``` + +Удали строку из `/etc/fstab`: + +```bash +sudo nano /etc/fstab +# удали строку: /swapfile none swap sw 0 0 +``` + +## Sysctl - защита ядра + +```bash +sudo nano /etc/sysctl.d/99-hardening.conf +``` + +``` +# Защита от SYN flood +net.ipv4.tcp_syncookies = 1 +net.ipv4.tcp_max_syn_backlog = 2048 +net.ipv4.tcp_synack_retries = 2 + +# Игнорировать ICMP redirects (защита от MITM) +net.ipv4.conf.all.accept_redirects = 0 +net.ipv4.conf.default.accept_redirects = 0 +net.ipv6.conf.all.accept_redirects = 0 +net.ipv6.conf.default.accept_redirects = 0 + +# Не отправлять ICMP redirects +net.ipv4.conf.all.send_redirects = 0 +net.ipv4.conf.default.send_redirects = 0 + +# Игнорировать source routed packets +net.ipv4.conf.all.accept_source_route = 0 +net.ipv6.conf.all.accept_source_route = 0 + +# Защита от IP spoofing +net.ipv4.conf.all.rp_filter = 1 +net.ipv4.conf.default.rp_filter = 1 + +# Логировать подозрительные пакеты +net.ipv4.conf.all.log_martians = 1 + +# Защита от time-wait assassination +net.ipv4.tcp_rfc1337 = 1 + +# Отключить IPv6 если не используешь +# net.ipv6.conf.all.disable_ipv6 = 1 +# net.ipv6.conf.default.disable_ipv6 = 1 +``` + +Примени: + +```bash +sudo sysctl -p /etc/sysctl.d/99-hardening.conf +``` + +Проверь: + +```bash +sudo sysctl net.ipv4.tcp_syncookies +# net.ipv4.tcp_syncookies = 1 +``` + +## Автообновления безопасности + +Ubuntu 24.04 устанавливает `unattended-upgrades` автоматически. Проверь: + +```bash +sudo systemctl status unattended-upgrades +``` + +Если не установлен: + +```bash +sudo apt install -y unattended-upgrades apt-listchanges +sudo dpkg-reconfigure -plow unattended-upgrades +``` + +Настрой конфиг: + +```bash +sudo nano /etc/apt/apt.conf.d/50unattended-upgrades +``` + +Убедись что раскомментированы (или добавь): + +``` +Unattended-Upgrade::Mail "root"; +Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; +Unattended-Upgrade::Remove-Unused-Dependencies "true"; +Unattended-Upgrade::Automatic-Reboot "false"; +``` + +`Automatic-Reboot "false"` - перезагрузку после обновления ядра делаешь вручную в удобное время. + +Расписание: + +```bash +sudo nano /etc/apt/apt.conf.d/10periodic +``` + +``` +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Download-Upgradeable-Packages "1"; +APT::Periodic::AutocleanInterval "7"; +APT::Periodic::Unattended-Upgrade "1"; +``` + +## Отключение ненужных сервисов + +Посмотри что запущено: + +```bash +systemctl list-units --type=service --state=running +``` + +Ubuntu 24.04 по умолчанию запускает больше сервисов чем Debian. Кандидаты на отключение: + +```bash +# Bluetooth - на сервере не нужен +sudo systemctl disable --now bluetooth.service + +# avahi-daemon - mDNS/DNS-SD, нужен редко +sudo systemctl disable --now avahi-daemon.service + +# ModemManager - управление модемами +sudo systemctl disable --now ModemManager.service + +# snapd - если не используешь snap пакеты +# ОСТОРОЖНО: некоторые облачные образы зависят от snap +sudo systemctl disable --now snapd.service snapd.socket +``` + +**По поводу snapd:** если сервер облачный и ты не знаешь точно что использует snap - не отключай. Проверь сначала: + +```bash +snap list +``` + +Если кроме `core` и `snapd` ничего нет - можно отключать. + +Проверь открытые порты: + +```bash +ss -tulnp +``` + +## Логи и ротация + +### Ограничение journald + +```bash +sudo nano /etc/systemd/journald.conf +``` + +``` +SystemMaxUse=500M +SystemMaxFileSize=100M +MaxRetentionSec=1month +``` + +Перезапусти: + +```bash +sudo systemctl restart systemd-journald +``` + +Проверь размер: + +```bash +sudo journalctl --disk-usage +``` + +### Ротация rsyslog + +```bash +sudo nano /etc/logrotate.d/rsyslog +``` + +``` +/var/log/syslog +/var/log/mail.log +/var/log/kern.log +/var/log/auth.log +/var/log/user.log +/var/log/cron.log +{ + su root syslog + rotate 7 + daily + missingok + notifempty + compress + delaycompress + sharedscripts + postrotate + /usr/lib/rsyslog/rsyslog-rotate + endscript +} +``` + +Директива `su root syslog` обязательна - без неё logrotate отказывается ротировать файлы в `/var/log`, потому что директория доступна на запись группе `syslog`, что считается небезопасным. + +Проверь конфиг dry run: + +```bash +sudo logrotate -d /etc/logrotate.d/rsyslog +``` + +Ожидаемый вывод: + +``` +... +rotating pattern: /var/log/syslog +/var/log/mail.log +/var/log/kern.log +/var/log/auth.log +/var/log/user.log +/var/log/cron.log + after 1 days (7 rotations) +empty log files are not rotated, old logs are removed +switching euid from 0 to 0 and egid from 0 to 104 (pid 76669) +... +``` + +## Мониторинг диска + +### Определение имени диска + +Имя диска зависит от окружения - не хардкодь `/dev/sda`: + +```bash +lsblk +``` + +Ожидаемый вывод (ориентировочный) на физическом сервере: +``` +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 500G 0 disk +├─sda1 8:1 0 1G 0 part /boot +└─sda2 8:2 0 499G 0 part / +``` + +Ожидаемый вывод на виртуальной машине (KVM/Proxmox): +``` +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +vda 253:0 0 30G 0 disk +├─vda1 253:1 0 1M 0 part +└─vda2 253:2 0 30G 0 part / +``` + +`vda` - virtio-диск на гипервизоре. `sda` - физический диск или SCSI-эмуляция. + +### Физический сервер - SMART + +На физическом сервере SMART даёт ранние признаки деградации диска: + +```bash +sudo smartctl -H /dev/sda +``` + +Ожидаемый вывод: +``` +SMART overall-health self-assessment test result: PASSED +``` + +Детали: + +```bash +sudo smartctl -a /dev/sda +``` + +Обращай внимание на три атрибута - если ненулевые, диск проблемный: +- `Reallocated_Sector_Ct` - переназначенные секторы +- `Pending_Sector_Count` - ожидающие переназначения +- `Offline_Uncorrectable` - неисправимые ошибки + +### Виртуальная машина - SMART недоступен + +На VM `smartctl` не работает - гипервизор не пробрасывает SMART данные гостю: + +``` +/dev/vda: Unable to detect device type +Please specify device type with the -d option. +``` + +Это нормально. SMART мониторинг на виртуальных дисках делается на уровне гипервизора - в Proxmox через Datacenter → Node → Disks. Внутри VM контролируй заполнение и I/O: + +```bash +df -h +``` + +```bash +iostat -x 1 3 +``` + +`iostat` входит в пакет `sysstat`: + +```bash +sudo apt install -y sysstat +``` + +Обращай внимание на `%util` в выводе `iostat` - значения близкие к 100% означают что диск перегружен. + +## Бэкап конфигов + +Скрипт архивирует `/etc/`, SSH ключи и список установленных пакетов. + +```bash +sudo nano /root/backup-configs.sh +``` + +```bash +#!/bin/bash + +BACKUP_DIR="/root/backups" +DATE=$(date +%Y%m%d_%H%M%S) +BACKUP_FILE="$BACKUP_DIR/config_backup_$DATE.tar.gz" + +mkdir -p "$BACKUP_DIR" + +dpkg --get-selections > /root/installed-packages.txt + +tar -czf "$BACKUP_FILE" \ + /etc/ \ + /root/.ssh/ \ + /home/*/.ssh/ \ + /root/installed-packages.txt \ + 2>/dev/null + +find "$BACKUP_DIR" -name "config_backup_*.tar.gz" -mtime +30 -delete + +echo "Backup: $BACKUP_FILE" +ls -lh "$BACKUP_FILE" +``` + +Установи права и запусти первый раз: + +```bash +sudo chmod +x /root/backup-configs.sh +sudo /root/backup-configs.sh +``` +Ожидаемый вывод: +```bash +Backup: /root/backups/config_backup_20260707_145620.tar.gz +-rw-r--r-- 1 root root 660K Jul 7 14:56 /root/backups/config_backup_ДАТА.tar.gz +``` + +Автоматизация через cron (каждое воскресенье в 3:00): + +```bash +sudo crontab -e +``` + +``` +0 3 * * 0 /root/backup-configs.sh >> /var/log/backup-configs.log 2>&1 +``` + +**Важно:** архив лежит на том же диске что и система. Это защита от случайных изменений конфигов, не от отказа диска. Копируй архивы на внешний сервер или S3-совместимое хранилище. + +### Восстановление конфигов + +Восстановить `/etc/` и SSH ключи из архива: + +```bash +sudo tar -xzf /root/backups/config_backup_ДАТА.tar.gz -C / +``` + +Восстановить список пакетов: + +```bash +sudo dpkg --set-selections < /root/installed-packages.txt +``` + +```bash +sudo apt-get dselect-upgrade +``` + +### Финальная проверка +```bash +# Открытые порты +ss -tulnp + +# Статус firewall +sudo ufw status verbose + +# Статус fail2ban +sudo fail2ban-client status sshd + +# Состояние диска +sudo smartctl -H /dev/sda + +# Swap +free -h +``` + +## Что дальше + +Сервер готов к установке приложений. + +- Docker хост - следующая статья серии +- Nginx/Traefik - reverse proxy поверх этой базы +- PostgreSQL/MySQL - базы данных +- Postfix/Dovecot - почтовый сервер + +**Стек этой статьи:** Ubuntu 24.04 LTS (Noble Numbat) · UFW · Fail2ban · OpenSSH · unattended-upgrades · systemd · systemd-resolved · smartmontools + +## Послесловие: пока мы настраивали - они уже ломились + +Пока эта статья писалась и проверялась на реальном сервере, снаружи шла своя работа. Проверяем: + +```bash +sudo fail2ban-client status sshd +``` + +``` +Status for the jail: sshd +|- Filter +| |- Currently failed: 4 +| |- Total failed: 22863 +| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd +`- Actions + |- Currently banned: 3 + |- Total banned: 18 + `- Banned IP list: 167.99.72.161 104.236.83.40 47.77.182.54 +``` + +22 863 неудачных попытки. 18 забаненных IP. 3 в бане прямо сейчас. + +Сколько времени сервер вообще стоит в интернете: + +```bash +uptime -p +``` + +``` +up 4 days, 3 hours, 21 minutes +``` + +4 дня. ~235 попыток в час, почти 4 в минуту - непрерывно, круглосуточно. + +Посмотрим на что они надеялись: + +```bash +sudo grep "Invalid user" /var/log/auth.log | grep -oP "Invalid user \K\S+" | sort | uniq -c | sort -rn | head -10 +``` + +``` + 124 ubuntu + 101 user + 91 test + 75 debian + 59 ftpuser + 55 postgres + 50 oracle + 34 git + 34 deploy + 25 deployer +``` + +`ubuntu` - 124 попытки, классика для облачных серверов. `debian` - 75, логично для нашего дистрибутива. `ftpuser` - 59, кто-то ищет забытый FTP из 2005 года. `postgres`, `oracle` - надеялись что база данных торчит наружу с дефолтным пользователем. `git`, `deploy`, `deployer` - охота на CI/CD пайплайны с предсказуемыми именами. + +Все эти попытки получили одинаковый ответ: порт 22 закрыт, нестандартный порт принимает только ключи, после трёх ошибок - бан на час. + +Это не повод расслабиться. Это повод убедиться что всё настроено именно так, как описано выше - потому что 22 863 попытки за 4 дня на одном небольшом сервере это не целевая атака, это обычный фоновый шум интернета. Целевая атака выглядит иначе.