1424 lines
32 KiB
Markdown
1424 lines
32 KiB
Markdown
---
|
||
title: "Безопасный production-сервер на Debian 12: пошаговая настройка"
|
||
date: 2026-03-07
|
||
draft: false
|
||
description: "Пошаговое руководство по защите Debian 12 с нуля: настройка SSH, ufw, Fail2ban, sysctl, автообновлений и мониторинга. Базовая безопасность production-сервера за один час."
|
||
tags: ["debian", "linux", "security", "безопасность", "ssh", "ufw", "fail2ban", "sysctl", "linux-admin"]
|
||
categories:
|
||
- Linux
|
||
- Безопасность
|
||
---
|
||
|
||
Поставил чистый Debian 12 и думаешь сразу накатывать приложения? Не торопись. Сейчас потратишь час на базовую настройку безопасности - сэкономишь недели на разгребание последствий взлома.
|
||
|
||
{{< lead >}}Эта статья - универсальная база для любого production-сервера. Не важно, будешь ты крутить почту, веб или базу данных - эти настройки нужны всем.{{< /lead >}}
|
||
|
||
## Что будем делать
|
||
|
||
Превратим голый Debian в сервер, который:
|
||
- Не пустит первого попавшегося ботнет
|
||
- Автоматически обновляет критичные патчи
|
||
- Не упадет от fork-бомбы
|
||
- Защищен от базовых сетевых атак
|
||
- Имеет бэкапы конфигов для восстановления
|
||
- Логирует подозрительную активность
|
||
|
||
Без фанатизма и паранойи. Только то, что реально защищает.
|
||
|
||
## Исходные данные
|
||
|
||
**Что есть:**
|
||
- Чистый Debian 12 (Bookworm)
|
||
- Root-доступ по SSH
|
||
- Статический IP-адрес
|
||
|
||
**Что НЕ рассматриваю:**
|
||
- Docker/Podman контейнеры (это отдельная тема)
|
||
- Кластерные конфигурации
|
||
- Специфичные настройки приложений
|
||
|
||
## Обновление системы
|
||
|
||
Первым делом - обновить все до актуального состояния.
|
||
|
||
```bash
|
||
apt update
|
||
apt upgrade -y
|
||
apt dist-upgrade -y
|
||
```
|
||
|
||
**Что делают команды:**
|
||
- `apt update` - обновить списки пакетов
|
||
- `apt upgrade` - обновить установленные пакеты
|
||
- `apt dist-upgrade` - обновить с разрешением зависимостей (может удалить/добавить пакеты)
|
||
|
||
Если спросит про перезагрузку сервисов - соглашайся.
|
||
|
||
Проверь, нужна ли перезагрузка:
|
||
|
||
```bash
|
||
[ -f /var/run/reboot-required ] && echo "Reboot needed" || echo "No reboot needed"
|
||
```
|
||
|
||
Если нужна - перезагружаемся:
|
||
|
||
```bash
|
||
reboot
|
||
```
|
||
|
||
### Базовые утилиты
|
||
|
||
Поставь то, что понадобится для работы и отладки:
|
||
|
||
```bash
|
||
apt install -y \
|
||
sudo \
|
||
curl \
|
||
wget \
|
||
git \
|
||
htop \
|
||
iotop \
|
||
iftop \
|
||
net-tools \
|
||
dnsutils \
|
||
telnet \
|
||
tcpdump \
|
||
screen \
|
||
tmux \
|
||
rsync \
|
||
unzip \
|
||
ca-certificates \
|
||
gnupg2 \
|
||
lsb-release
|
||
```
|
||
|
||
**Что установили:**
|
||
- Мониторинг: `htop`, `iotop`, `iftop`
|
||
- Сеть: `net-tools`, `dnsutils`, `telnet`, `tcpdump`
|
||
- Сессии: `screen`, `tmux`
|
||
- Утилиты: `curl`, `wget`, `git`, `rsync`, `unzip`
|
||
|
||
## Настройка системы
|
||
|
||
### Hostname
|
||
|
||
Установи правильное имя сервера:
|
||
|
||
```bash
|
||
hostnamectl set-hostname srv01.example.ru
|
||
```
|
||
|
||
Замени `srv01.example.ru` на свое.
|
||
|
||
Запусти новую ssh сессию и проверь:
|
||
|
||
```bash
|
||
hostname -f
|
||
```
|
||
|
||
Должно вернуть полное имя (FQDN).
|
||
|
||
### Файл /etc/hosts
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
nano /etc/hosts
|
||
```
|
||
|
||
Приведи к виду:
|
||
|
||
```
|
||
127.0.0.1 localhost
|
||
твой-IP srv01.example.ru srv01
|
||
|
||
# IPv6
|
||
::1 localhost ip6-localhost ip6-loopback
|
||
ff02::1 ip6-allnodes
|
||
ff02::2 ip6-allrouters
|
||
```
|
||
|
||
**Замени:**
|
||
- `твой-IP` - на реальный IP сервера
|
||
- `srv01.example.ru` - на свое имя
|
||
|
||
### Timezone
|
||
|
||
Установи правильную временную зону:
|
||
|
||
```bash
|
||
timedatectl set-timezone Europe/Moscow
|
||
```
|
||
|
||
Посмотри доступные зоны:
|
||
|
||
```bash
|
||
timedatectl list-timezones | grep Moscow
|
||
```
|
||
|
||
Проверь текущее время:
|
||
|
||
```bash
|
||
timedatectl
|
||
```
|
||
|
||
Должно показать правильный timezone и время.
|
||
|
||
### Локаль
|
||
|
||
Проверь текущую локаль:
|
||
|
||
```bash
|
||
locale
|
||
```
|
||
|
||
Если видишь ошибки или не UTF-8 - настрой:
|
||
|
||
```bash
|
||
apt install -y locales
|
||
dpkg-reconfigure locales
|
||
```
|
||
|
||
Выбери:
|
||
- `en_US.UTF-8`
|
||
- `ru_RU.UTF-8` (если нужна кириллица)
|
||
|
||
По умолчанию поставь `en_US.UTF-8`.
|
||
|
||
Проверь:
|
||
|
||
```bash
|
||
locale
|
||
```
|
||
|
||
Должно быть `LANG=en_US.UTF-8`.
|
||
|
||
## SSH hardening
|
||
|
||
SSH - главный вход на сервер. Если его взломают - все остальное не имеет смысла.
|
||
|
||
### Создание пользователя (не root)
|
||
|
||
Работать от root - плохая идея. Создай обычного пользователя:
|
||
|
||
```bash
|
||
adduser admin
|
||
```
|
||
|
||
Введи пароль (временный, потом отключим).
|
||
|
||
Добавь в sudo:
|
||
|
||
```bash
|
||
usermod -aG sudo admin
|
||
```
|
||
|
||
Проверь:
|
||
|
||
```bash
|
||
groups admin
|
||
```
|
||
|
||
Должно быть: `admin : admin sudo`
|
||
|
||
### SSH ключи
|
||
|
||
На **своей рабочей машине** (возможно это Windows) сгенерируй ключ:
|
||
|
||
```bash
|
||
ssh-keygen -t ed25519 -C "admin@srv01"
|
||
```
|
||
|
||
или так
|
||
|
||
```pwsh
|
||
cd c:\users\$env:username
|
||
ssh-keygen
|
||
```
|
||
|
||
Если спросит путь - жми Enter (по умолчанию `~/.ssh/id_ed25519`).
|
||
|
||
Если спросит passphrase - на твое усмотрение (дополнительная защита ключа).
|
||
|
||
Скопируй публичный ключ на сервер:
|
||
|
||
{{< tabs >}}
|
||
{{< tab label="Windows" >}}
|
||
```pwsh
|
||
type $env:userprofile\.ssh\id_ed25519.pub | ssh admin@твой-IP "if [ ! -d ~/.ssh ]; then mkdir -m 700 ~/.ssh; fi; if [ ! -f ~/.ssh/authorized_keys ]; then touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; fi; cat >> ~/.ssh/authorized_keys"
|
||
```
|
||
Команда проверяет наличие `~/.ssh/authorized_keys` и если ее нет - создает с нужными правами.
|
||
{{< /tab >}}
|
||
{{< tab label="Linux" md=false >}}
|
||
```bash
|
||
ssh-copy-id admin@твой-IP
|
||
```
|
||
{{< /tab >}}
|
||
{{< /tabs >}}
|
||
|
||
|
||
Введи пароль пользователя `admin`.
|
||
|
||
Проверь вход по ключу:
|
||
|
||
```bash
|
||
ssh admin@твой-IP
|
||
```
|
||
|
||
Не должен спрашивать пароль (только passphrase ключа, если установил).
|
||
|
||
Если работает - отлично. Теперь настроим сервер.
|
||
|
||
### Настройка sshd
|
||
|
||
Залогинься на сервер под `admin`:
|
||
|
||
```bash
|
||
ssh admin@твой-IP
|
||
```
|
||
|
||
Открой конфиг SSH:
|
||
|
||
```bash
|
||
sudo nano /etc/ssh/sshd_config
|
||
```
|
||
|
||
Найди и измени (или добавь):
|
||
|
||
```
|
||
# Базовые настройки
|
||
Port 2222
|
||
PermitRootLogin no
|
||
PasswordAuthentication no
|
||
PubkeyAuthentication yes
|
||
AuthorizedKeysFile .ssh/authorized_keys
|
||
|
||
# Ограничения
|
||
MaxAuthTries 3
|
||
MaxSessions 2
|
||
LoginGraceTime 30
|
||
|
||
# Отключаем лишнее
|
||
PermitEmptyPasswords no
|
||
ChallengeResponseAuthentication no
|
||
UsePAM yes
|
||
X11Forwarding no
|
||
PrintMotd no
|
||
AcceptEnv LANG LC_*
|
||
|
||
# Таймауты
|
||
ClientAliveInterval 300
|
||
ClientAliveCountMax 2
|
||
|
||
# Только IPv4 (если не используешь IPv6)
|
||
AddressFamily inet
|
||
```
|
||
|
||
**Что настроили:**
|
||
|
||
**Port 2222:**
|
||
- Нестандартный порт вместо 22
|
||
- Отсекает 90% ботов
|
||
- `ВАЖНО:` Запомни новый порт!
|
||
|
||
**PermitRootLogin no:**
|
||
- Запрет входа под root
|
||
- Обязательно использовать обычного пользователя + sudo
|
||
|
||
**PasswordAuthentication no:**
|
||
- Отключаем пароли
|
||
- Только SSH-ключи
|
||
|
||
**MaxAuthTries 3:**
|
||
- Максимум 3 попытки входа
|
||
|
||
**LoginGraceTime 30:**
|
||
- 30 секунд на авторизацию
|
||
|
||
**ClientAliveInterval 300:**
|
||
- Пинговать клиента каждые 5 минут
|
||
- Отключать неактивные сессии
|
||
|
||
Проверь конфиг:
|
||
|
||
```bash
|
||
sudo sshd -t
|
||
```
|
||
|
||
Если ошибок нет - ничего не выводит.
|
||
|
||
{{< alert cardColor="#e63946" iconColor="#ffffff" >}}
|
||
**КРИТИЧЕСКИ ВАЖНО:** Перед перезапуском SSH открой **вторую сессию** и не закрывай её:
|
||
{{< /alert >}}
|
||
|
||
```bash
|
||
ssh admin@твой-IP
|
||
```
|
||
|
||
Это страховка. Если что-то пойдет не так - сможешь исправить через вторую сессию.
|
||
|
||
Перезапусти SSH в первой сессии:
|
||
|
||
```bash
|
||
sudo systemctl restart sshd
|
||
```
|
||
|
||
Во второй сессии проверь новое подключение:
|
||
|
||
```bash
|
||
ssh -p 2222 admin@твой-IP
|
||
```
|
||
|
||
Если работает - отлично. Можешь закрыть старые сессии.
|
||
|
||
Если не работает - исправляй через вторую (старую) сессию.
|
||
|
||
### SSH banner
|
||
|
||
Добавь предупреждение при входе.
|
||
|
||
Создай файл:
|
||
|
||
```bash
|
||
sudo nano /etc/ssh/banner
|
||
```
|
||
|
||
Запиши:
|
||
|
||
```
|
||
###############################################################################
|
||
# ВНИМАНИЕ! #
|
||
# #
|
||
# Доступ к этой системе разрешен только авторизованным пользователям. #
|
||
# Все действия логируются и могут быть использованы в качестве #
|
||
# доказательств при расследовании инцидентов. #
|
||
# #
|
||
# Несанкционированный доступ преследуется по закону. #
|
||
# #
|
||
###############################################################################
|
||
```
|
||
|
||
Добавь в `/etc/ssh/sshd_config`:
|
||
|
||
```
|
||
Banner /etc/ssh/banner
|
||
```
|
||
|
||
Перезапусти SSH:
|
||
|
||
```bash
|
||
sudo systemctl restart sshd
|
||
```
|
||
|
||
При следующем входе увидишь баннер.
|
||
|
||
## Firewall (ufw)
|
||
|
||
Firewall - первая линия защиты от сетевых атак.
|
||
|
||
### Установка ufw
|
||
|
||
```bash
|
||
sudo apt install -y ufw
|
||
```
|
||
|
||
### Базовые правила
|
||
|
||
{{< alert >}}**ВАЖНО:** Сначала настроим правила, потом включим. Иначе можешь заблокировать себя.{{< /alert >}}
|
||
|
||
Политика по умолчанию - блокировать все входящее:
|
||
|
||
```bash
|
||
sudo ufw default deny incoming
|
||
sudo ufw default allow outgoing
|
||
```
|
||
|
||
Разрешаем SSH на новом порту:
|
||
|
||
```bash
|
||
sudo ufw allow 2222/tcp comment 'SSH'
|
||
```
|
||
|
||
**Замени 2222** на свой порт из `sshd_config`.
|
||
|
||
**Не открывай порты, которые не нужны!** Добавишь потом по мере необходимости.
|
||
|
||
### Rate limiting для SSH
|
||
|
||
Защита от брутфорса на уровне firewall:
|
||
|
||
```bash
|
||
sudo ufw limit 2222/tcp
|
||
```
|
||
|
||
Это ограничит количество подключений (максимум 6 попыток за 30 секунд).
|
||
|
||
### Включаем firewall
|
||
|
||
Проверь правила:
|
||
|
||
```bash
|
||
sudo ufw show added
|
||
```
|
||
|
||
Должно быть что-то вроде:
|
||
|
||
```
|
||
ufw allow 2222/tcp
|
||
```
|
||
|
||
Включаем:
|
||
|
||
```bash
|
||
sudo ufw enable
|
||
```
|
||
|
||
Спросит: `Command may disrupt existing ssh connections. Proceed with operation (y|n)?`
|
||
|
||
т.е. `Выполнение команды может прервать существующие SSH-соединения. Продолжить операцию? (y|n)`
|
||
|
||
Жми `y`.
|
||
|
||
Проверь статус:
|
||
|
||
```bash
|
||
sudo ufw status verbose
|
||
```
|
||
|
||
Должно быть:
|
||
|
||
```
|
||
Status: active
|
||
Logging: on (low)
|
||
Default: deny (incoming), allow (outgoing), disabled (routed)
|
||
|
||
To Action From
|
||
-- ------ ----
|
||
2222/tcp LIMIT Anywhere
|
||
```
|
||
|
||
Включи автозапуск:
|
||
|
||
```bash
|
||
sudo systemctl enable ufw
|
||
```
|
||
|
||
## Fail2ban
|
||
|
||
Firewall блокирует порты, Fail2ban блокирует IP-адреса с подозрительной активностью.
|
||
|
||
### Установка
|
||
|
||
```bash
|
||
sudo apt install -y fail2ban
|
||
```
|
||
|
||
### Базовая настройка
|
||
|
||
Создай конфиг:
|
||
|
||
```bash
|
||
sudo nano /etc/fail2ban/jail.local
|
||
```
|
||
|
||
Внеси:
|
||
|
||
```ini
|
||
[DEFAULT]
|
||
# Время бана (10 минут)
|
||
bantime = 600
|
||
|
||
# Окно наблюдения (10 минут)
|
||
findtime = 600
|
||
|
||
# Количество попыток
|
||
maxretry = 5
|
||
|
||
# Игнорируемые IP (свои сети)
|
||
ignoreip = 127.0.0.1/8 ::1
|
||
|
||
# Действие при бане
|
||
banaction = ufw
|
||
action = %(action_mwl)s
|
||
|
||
[sshd]
|
||
enabled = true
|
||
port = 2222
|
||
logpath = /var/log/auth.log
|
||
maxretry = 3
|
||
```
|
||
|
||
**Что настроили:**
|
||
|
||
**DEFAULT:**
|
||
- `bantime = 600` - бан на 10 минут
|
||
- `findtime = 600` - смотрим на последние 10 минут
|
||
- `maxretry = 5` - максимум 5 попыток
|
||
- `ignoreip` - список IP, которые не баним (добавь свои)
|
||
- `banaction = ufw` - блокировать через ufw
|
||
- `action = %(action_mwl)s` - бан + письмо (если настроена почта)
|
||
|
||
**sshd:**
|
||
- Защита SSH
|
||
- Порт 2222 (твой порт)
|
||
- Максимум 3 попытки (строже чем default)
|
||
|
||
### Запуск
|
||
|
||
```bash
|
||
sudo systemctl enable fail2ban
|
||
sudo systemctl start fail2ban
|
||
sudo systemctl status fail2ban
|
||
```
|
||
|
||
Должен быть `active (running)`.
|
||
|
||
### Проверка
|
||
|
||
Посмотри статус тюрем:
|
||
|
||
```bash
|
||
sudo fail2ban-client status
|
||
```
|
||
|
||
Должно быть:
|
||
|
||
```
|
||
Status
|
||
|- Number of jail: 1
|
||
`- Jail list: sshd
|
||
```
|
||
|
||
Статус конкретной тюрьмы:
|
||
|
||
```bash
|
||
sudo fail2ban-client status sshd
|
||
```
|
||
|
||
Покажет:
|
||
- Количество забаненных IP
|
||
- Список IP
|
||
|
||
### Тест
|
||
|
||
С другого IP попробуй подключиться с неправильным паролем 3 раза подряд:
|
||
|
||
```bash
|
||
ssh fake@твой-IP -p 2222
|
||
```
|
||
|
||
После 3-й попытки IP должен быть забанен.
|
||
|
||
Проверь:
|
||
|
||
```bash
|
||
sudo fail2ban-client status sshd
|
||
```
|
||
|
||
Должен появиться IP в `Banned IP list`.
|
||
|
||
Разбань (для теста):
|
||
|
||
```bash
|
||
sudo fail2ban-client set sshd unbanip IP-адрес
|
||
```
|
||
|
||
## Kernel hardening (sysctl)
|
||
|
||
Настроим ядро для защиты от сетевых атак.
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
sudo nano /etc/sysctl.d/99-hardening.conf
|
||
```
|
||
|
||
Внеси:
|
||
|
||
```ini
|
||
# IP Forwarding (отключаем если не роутер)
|
||
net.ipv4.ip_forward = 0
|
||
net.ipv6.conf.all.forwarding = 0
|
||
|
||
# Защита от IP spoofing
|
||
net.ipv4.conf.all.rp_filter = 1
|
||
net.ipv4.conf.default.rp_filter = 1
|
||
|
||
# Игнорировать ICMP redirects
|
||
net.ipv4.conf.all.accept_redirects = 0
|
||
net.ipv4.conf.default.accept_redirects = 0
|
||
net.ipv4.conf.all.secure_redirects = 0
|
||
net.ipv4.conf.default.secure_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
|
||
|
||
# Игнорировать ICMP broadcast
|
||
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
||
|
||
# Игнорировать bogus ICMP errors
|
||
net.ipv4.icmp_ignore_bogus_error_responses = 1
|
||
|
||
# Логировать подозрительные пакеты
|
||
net.ipv4.conf.all.log_martians = 1
|
||
net.ipv4.conf.default.log_martians = 1
|
||
|
||
# Защита от SYN flood
|
||
net.ipv4.tcp_syncookies = 1
|
||
net.ipv4.tcp_max_syn_backlog = 2048
|
||
net.ipv4.tcp_synack_retries = 2
|
||
net.ipv4.tcp_syn_retries = 5
|
||
|
||
# Отключить source routing
|
||
net.ipv4.conf.all.accept_source_route = 0
|
||
net.ipv4.conf.default.accept_source_route = 0
|
||
net.ipv6.conf.all.accept_source_route = 0
|
||
net.ipv6.conf.default.accept_source_route = 0
|
||
|
||
# Оптимизация TCP
|
||
net.ipv4.tcp_fin_timeout = 15
|
||
net.ipv4.tcp_keepalive_time = 300
|
||
net.ipv4.tcp_keepalive_probes = 5
|
||
net.ipv4.tcp_keepalive_intvl = 15
|
||
|
||
# Увеличить диапазон портов
|
||
net.ipv4.ip_local_port_range = 1024 65535
|
||
|
||
# Защита от TIME_WAIT
|
||
net.ipv4.tcp_rfc1337 = 1
|
||
|
||
# Увеличить буферы
|
||
net.core.rmem_max = 16777216
|
||
net.core.wmem_max = 16777216
|
||
net.ipv4.tcp_rmem = 4096 87380 16777216
|
||
net.ipv4.tcp_wmem = 4096 65536 16777216
|
||
|
||
# Файловая система
|
||
fs.file-max = 65535
|
||
fs.inotify.max_user_watches = 524288
|
||
```
|
||
|
||
**Что настроили:**
|
||
|
||
**Защита от spoofing:**
|
||
- Reverse path filtering
|
||
- Проверка source routing
|
||
|
||
**Защита от ICMP атак:**
|
||
- Игнорируем redirects
|
||
- Игнорируем broadcast ping
|
||
|
||
**Защита от SYN flood:**
|
||
- SYN cookies
|
||
- Ограничение backlog
|
||
|
||
**Оптимизация TCP:**
|
||
- Таймауты соединений
|
||
- Размеры буферов
|
||
- Диапазон портов
|
||
|
||
Применяем:
|
||
|
||
```bash
|
||
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
|
||
```
|
||
|
||
Проверяем:
|
||
|
||
```bash
|
||
sudo sysctl net.ipv4.tcp_syncookies
|
||
```
|
||
|
||
Должно вернуть: `net.ipv4.tcp_syncookies = 1`
|
||
|
||
## Swap
|
||
|
||
Если RAM мало (меньше 4GB) - настрой swap.
|
||
|
||
### Проверка наличия swap
|
||
|
||
```bash
|
||
free -h
|
||
```
|
||
|
||
Если в строке `Swap` везде нули - нет swap.
|
||
|
||
Также проверь:
|
||
|
||
```bash
|
||
swapon --show
|
||
```
|
||
|
||
Если пусто - нет swap.
|
||
|
||
### Создание swap-файла
|
||
|
||
Создаем файл на 2GB:
|
||
|
||
```bash
|
||
sudo fallocate -l 2G /swapfile
|
||
```
|
||
|
||
Если `fallocate` не работает:
|
||
|
||
```bash
|
||
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
|
||
```
|
||
|
||
Права:
|
||
|
||
```bash
|
||
sudo chmod 600 /swapfile
|
||
```
|
||
|
||
Форматируем:
|
||
|
||
```bash
|
||
sudo mkswap /swapfile
|
||
```
|
||
|
||
Включаем:
|
||
|
||
```bash
|
||
sudo swapon /swapfile
|
||
```
|
||
|
||
Проверяем:
|
||
|
||
```bash
|
||
free -h
|
||
```
|
||
|
||
Должен появиться swap.
|
||
|
||
Делаем постоянным (добавляем в fstab):
|
||
|
||
```bash
|
||
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
||
```
|
||
|
||
### Настройка swappiness
|
||
|
||
`Swappiness` - насколько активно использовать swap.
|
||
|
||
Проверь текущее значение:
|
||
|
||
```bash
|
||
cat /proc/sys/vm/swappiness
|
||
```
|
||
|
||
По умолчанию: 60 (агрессивно).
|
||
|
||
Для серверов лучше 10:
|
||
|
||
```bash
|
||
sudo nano /etc/sysctl.d/99-swappiness.conf
|
||
```
|
||
|
||
Запиши:
|
||
|
||
```
|
||
vm.swappiness = 10
|
||
```
|
||
|
||
Применяем:
|
||
|
||
```bash
|
||
sudo sysctl -p /etc/sysctl.d/99-swappiness.conf
|
||
```
|
||
|
||
Проверяем:
|
||
|
||
```bash
|
||
cat /proc/sys/vm/swappiness
|
||
```
|
||
|
||
Должно быть: 10
|
||
|
||
## Ограничение ресурсов
|
||
|
||
Защита от fork-бомб и исчерпания дескрипторов.
|
||
|
||
`fork-бомба` - это программа (вредоносная или написанная по ошибке), которая бесконечно создаёт собственные копии через системный вызов `fork()`, пока ресурсы системы полностью не иссякнут.
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
sudo nano /etc/security/limits.conf
|
||
```
|
||
|
||
Добавь в конец:
|
||
|
||
```
|
||
# Ограничения для обычных пользователей
|
||
* soft nofile 65535
|
||
* hard nofile 65535
|
||
* soft nproc 32768
|
||
* hard nproc 32768
|
||
|
||
# Ограничения для root
|
||
root soft nofile 65535
|
||
root hard nofile 65535
|
||
root soft nproc 32768
|
||
root hard nproc 32768
|
||
```
|
||
|
||
**Что настроили:**
|
||
|
||
**nofile:**
|
||
- Максимум открытых файлов/сокетов
|
||
- 65535 достаточно для большинства случаев
|
||
|
||
**nproc:**
|
||
- Максимум процессов пользователя
|
||
- 32768 защитит от fork-бомбы
|
||
|
||
Также настрой PAM:
|
||
|
||
```bash
|
||
sudo nano /etc/pam.d/common-session
|
||
```
|
||
|
||
Добавь в конец:
|
||
|
||
```
|
||
session required pam_limits.so
|
||
```
|
||
|
||
Перелогинься и проверь:
|
||
|
||
```bash
|
||
ulimit -n
|
||
ulimit -u
|
||
```
|
||
|
||
Должно быть:
|
||
- `ulimit -n` → 65535
|
||
- `ulimit -u` → 32768
|
||
|
||
## Автообновления безопасности
|
||
|
||
Критичные патчи должны ставиться автоматически.
|
||
|
||
### Установка
|
||
|
||
```bash
|
||
sudo apt install -y unattended-upgrades apt-listchanges
|
||
```
|
||
|
||
### Настройка
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
|
||
```
|
||
|
||
Найди и раскомментируй/измени:
|
||
|
||
```
|
||
Unattended-Upgrade::Origins-Pattern {
|
||
// Только security-обновления:
|
||
"origin=Debian,codename=${distro_codename},label=Debian-Security";
|
||
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
|
||
};
|
||
|
||
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
|
||
Unattended-Upgrade::MinimalSteps "true";
|
||
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
|
||
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
||
Unattended-Upgrade::Automatic-Reboot "false";
|
||
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
|
||
```
|
||
|
||
**Что настроили:**
|
||
|
||
**Allowed-Origins:**
|
||
- Только обновления безопасности
|
||
- Не обновляем все подряд
|
||
|
||
**AutoFixInterruptedDpkg:**
|
||
- Автоматически чинить прерванные установки
|
||
|
||
**Remove-Unused-Kernel-Packages:**
|
||
- Удалять старые ядра
|
||
|
||
**Remove-Unused-Dependencies:**
|
||
- Удалять неиспользуемые зависимости
|
||
|
||
**Automatic-Reboot:**
|
||
- `false` - не перезагружаться автоматически
|
||
- Если хочешь автоперезагрузку → `true` (в 3 ночи)
|
||
|
||
Включаем:
|
||
|
||
```bash
|
||
sudo dpkg-reconfigure -plow unattended-upgrades
|
||
```
|
||
|
||
Выбери `Yes`.
|
||
|
||
Проверь статус:
|
||
|
||
```bash
|
||
sudo systemctl status unattended-upgrades
|
||
```
|
||
|
||
Должен быть `active`.
|
||
|
||
Проверь логи (через некоторое время):
|
||
|
||
```bash
|
||
cat /var/log/unattended-upgrades/unattended-upgrades.log
|
||
```
|
||
|
||
## Отключение ненужных сервисов
|
||
|
||
Меньше сервисов - меньше поверхность атаки. Арендованные VPS обычно используют специальные версии операционных систем - в них и так все по-минимуму. В остальных случаях:
|
||
|
||
### Список запущенных сервисов
|
||
|
||
```bash
|
||
systemctl list-units --type=service --state=running
|
||
```
|
||
|
||
### Что можно отключить
|
||
|
||
**Bluetooth (на сервере не нужен):**
|
||
|
||
```bash
|
||
sudo systemctl stop bluetooth.service
|
||
sudo systemctl disable bluetooth.service
|
||
sudo systemctl mask bluetooth.service
|
||
```
|
||
|
||
**ModemManager (если нет модема):**
|
||
|
||
```bash
|
||
sudo systemctl stop ModemManager.service
|
||
sudo systemctl disable ModemManager.service
|
||
```
|
||
|
||
**Avahi (mDNS, обычно не нужен):**
|
||
|
||
```bash
|
||
sudo systemctl stop avahi-daemon.service
|
||
sudo systemctl disable avahi-daemon.service
|
||
```
|
||
|
||
**Cups (печать, на сервере не нужна):**
|
||
|
||
```bash
|
||
sudo systemctl stop cups.service
|
||
sudo systemctl disable cups.service
|
||
```
|
||
|
||
**ВАЖНО:** Не отключай:
|
||
- `sshd` - без него не зайдешь
|
||
- `systemd-*` - системные сервисы
|
||
- `cron` - для задач по расписанию
|
||
- `rsyslog` - логирование
|
||
|
||
Проверь, что отключилось:
|
||
|
||
```bash
|
||
systemctl list-units --type=service --state=running
|
||
```
|
||
|
||
## Логирование
|
||
|
||
### Настройка rsyslog
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
sudo nano /etc/rsyslog.conf
|
||
```
|
||
|
||
Убедись, что есть:
|
||
|
||
```
|
||
# Логи аутентификации
|
||
auth,authpriv.* /var/log/auth.log
|
||
|
||
# Системные логи
|
||
*.*;auth,authpriv.none -/var/log/syslog
|
||
|
||
# Cron
|
||
cron.* /var/log/cron.log
|
||
|
||
# Ядро
|
||
kern.* -/var/log/kern.log
|
||
|
||
# Почта (если будет)
|
||
mail.* -/var/log/mail.log
|
||
mail.err /var/log/mail.err
|
||
```
|
||
|
||
Перезапусти:
|
||
|
||
```bash
|
||
sudo systemctl restart rsyslog
|
||
```
|
||
|
||
### Ротация логов
|
||
|
||
Открой:
|
||
|
||
```bash
|
||
sudo nano /etc/logrotate.conf
|
||
```
|
||
|
||
Убедись, что есть:
|
||
|
||
```
|
||
# Ротация раз в неделю
|
||
weekly
|
||
|
||
# Хранить 4 недели
|
||
rotate 4
|
||
|
||
# Создавать новые файлы
|
||
create
|
||
|
||
# Сжимать старые
|
||
compress
|
||
```
|
||
|
||
Настрой индивидуальную ротацию:
|
||
|
||
```bash
|
||
sudo nano /etc/logrotate.d/rsyslog
|
||
```
|
||
|
||
```
|
||
/var/log/syslog
|
||
/var/log/mail.log
|
||
/var/log/mail.err
|
||
/var/log/auth.log
|
||
{
|
||
rotate 7
|
||
daily
|
||
missingok
|
||
notifempty
|
||
compress
|
||
delaycompress
|
||
sharedscripts
|
||
postrotate
|
||
/usr/lib/rsyslog/rsyslog-rotate
|
||
endscript
|
||
}
|
||
```
|
||
|
||
**Что настроили:**
|
||
- Ротация каждый день
|
||
- Хранить 7 дней
|
||
- Сжимать старые логи
|
||
|
||
Проверь ротацию вручную:
|
||
|
||
```bash
|
||
sudo logrotate -f /etc/logrotate.conf
|
||
```
|
||
|
||
## Автоматическая очистка
|
||
|
||
### Старые ядра
|
||
|
||
Debian накапливает старые версии ядер. Очистка:
|
||
|
||
```bash
|
||
sudo apt autoremove --purge -y
|
||
```
|
||
|
||
Автоматизируем в unattended-upgrades (уже настроили выше):
|
||
|
||
```
|
||
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
|
||
```
|
||
|
||
### Кэш пакетов
|
||
|
||
Очистка вручную:
|
||
|
||
```bash
|
||
sudo apt clean
|
||
sudo apt autoclean
|
||
```
|
||
|
||
Автоматизация:
|
||
|
||
```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";
|
||
```
|
||
|
||
**Что настроили:**
|
||
- Обновлять списки пакетов ежедневно
|
||
- Скачивать обновления
|
||
- Очищать кэш раз в неделю
|
||
- Ставить обновления безопасности
|
||
|
||
### Journald
|
||
|
||
Ограничиваем размер логов systemd:
|
||
|
||
```bash
|
||
sudo nano /etc/systemd/journald.conf
|
||
```
|
||
|
||
Раскомментируй/измени:
|
||
|
||
```
|
||
SystemMaxUse=500M
|
||
SystemMaxFileSize=100M
|
||
MaxRetentionSec=1month
|
||
```
|
||
|
||
Перезапусти:
|
||
|
||
```bash
|
||
sudo systemctl restart systemd-journald
|
||
```
|
||
|
||
Проверь размер:
|
||
|
||
```bash
|
||
sudo journalctl --disk-usage
|
||
```
|
||
|
||
Должно быть в пределах 500M.
|
||
|
||
## Базовый бэкап
|
||
|
||
### Что бэкапить
|
||
|
||
**Критично:**
|
||
- `/etc/` - все конфиги системы
|
||
- `/root/.ssh/` - SSH ключи root
|
||
- `/home/*/. ssh/` - SSH ключи пользователей
|
||
- Список установленных пакетов
|
||
|
||
**Важно (если есть):**
|
||
- `/var/www/` - веб-сайты
|
||
- `/var/spool/mail/` - почта
|
||
- Базы данных
|
||
|
||
### Скрипт бэкапа конфигов
|
||
|
||
Создай:
|
||
|
||
```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
|
||
|
||
# Удаляем бэкапы старше 30 дней
|
||
find $BACKUP_DIR -name "config_backup_*.tar.gz" -mtime +30 -delete
|
||
|
||
echo "Backup created: $BACKUP_FILE"
|
||
ls -lh $BACKUP_FILE
|
||
```
|
||
|
||
Права на выполнение:
|
||
|
||
```bash
|
||
sudo chmod +x /root/backup-configs.sh
|
||
```
|
||
|
||
Запусти:
|
||
|
||
```bash
|
||
sudo /root/backup-configs.sh
|
||
```
|
||
|
||
Проверь:
|
||
|
||
```bash
|
||
ls -lh /root/backups/
|
||
```
|
||
|
||
### Автоматизация бэкапа
|
||
|
||
Добавь в cron (раз в неделю):
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
Добавь:
|
||
|
||
```
|
||
0 3 * * 0 /root/backup-configs.sh >> /var/log/backup-configs.log 2>&1
|
||
```
|
||
|
||
Это запустит скрипт каждое воскресенье в 3 ночи.
|
||
|
||
### Восстановление
|
||
|
||
Если нужно восстановить конфиги:
|
||
|
||
```bash
|
||
sudo tar -xzf /root/backups/config_backup_ДАТА.tar.gz -C /
|
||
```
|
||
|
||
Если нужно восстановить пакеты:
|
||
|
||
```bash
|
||
sudo dpkg --set-selections < /root/installed-packages.txt
|
||
sudo apt-get dselect-upgrade
|
||
```
|
||
|
||
## Мониторинг
|
||
|
||
### Проверка диска
|
||
|
||
Установи smartmontools:
|
||
|
||
```bash
|
||
sudo apt install -y smartmontools
|
||
```
|
||
|
||
Проверь диск:
|
||
|
||
```bash
|
||
sudo smartctl -H /dev/sda
|
||
```
|
||
|
||
Должно вернуть: `SMART Health Status: OK`
|
||
|
||
Если `FAILED` - диск умирает.
|
||
|
||
Посмотри детали:
|
||
|
||
```bash
|
||
sudo smartctl -a /dev/sda
|
||
```
|
||
|
||
### Алерты на критичные события
|
||
|
||
> [!TIP] Для работы почтовых уведомлений должен быть настроен MTA (например Postfix).
|
||
|
||
|
||
Создай скрипт проверки:
|
||
|
||
```bash
|
||
sudo nano /root/health-check.sh
|
||
```
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
|
||
ALERT_EMAIL="admin@example.ru"
|
||
HOSTNAME=$(hostname)
|
||
|
||
# Проверка места на диске
|
||
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||
if [ $DISK_USAGE -gt 90 ]; then
|
||
echo "ALERT: Disk usage is ${DISK_USAGE}% on $HOSTNAME" | mail -s "Disk Alert" $ALERT_EMAIL
|
||
fi
|
||
|
||
# Проверка RAM
|
||
MEM_USAGE=$(free | awk 'NR==2 {printf "%.0f", $3/$2*100}')
|
||
if [ $MEM_USAGE -gt 90 ]; then
|
||
echo "ALERT: Memory usage is ${MEM_USAGE}% on $HOSTNAME" | mail -s "Memory Alert" $ALERT_EMAIL
|
||
fi
|
||
|
||
# Проверка swap
|
||
SWAP_USAGE=$(free | awk 'NR==3 {if ($2 > 0) printf "%.0f", $3/$2*100; else print 0}')
|
||
if [ $SWAP_USAGE -gt 80 ]; then
|
||
echo "ALERT: Swap usage is ${SWAP_USAGE}% on $HOSTNAME" | mail -s "Swap Alert" $ALERT_EMAIL
|
||
fi
|
||
|
||
# Проверка load average
|
||
LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
|
||
CORES=$(nproc)
|
||
LOAD_INT=$(echo $LOAD | awk '{printf "%.0f", $1}')
|
||
if [ $LOAD_INT -gt $((CORES * 2)) ]; then
|
||
echo "ALERT: Load average is $LOAD on $HOSTNAME ($CORES cores)" | mail -s "Load Alert" $ALERT_EMAIL
|
||
fi
|
||
```
|
||
{{< alert >}}
|
||
**ВАЖНО:** Замени `admin@example.ru` на свой email.
|
||
{{< /alert >}}
|
||
Права:
|
||
|
||
```bash
|
||
sudo chmod +x /root/health-check.sh
|
||
```
|
||
|
||
Добавь в cron (каждые 15 минут):
|
||
|
||
```bash
|
||
sudo crontab -e
|
||
```
|
||
|
||
Если отправка почты настроена:
|
||
|
||
```
|
||
*/15 * * * * /root/health-check.sh
|
||
```
|
||
|
||
Если отправки почты нет - можешь логировать:
|
||
|
||
```
|
||
*/15 * * * * /root/health-check.sh >> /var/log/health-check.log 2>&1
|
||
```
|
||
|
||
### Тестирование
|
||
|
||
Проверь с внешнего IP:
|
||
|
||
```bash
|
||
# Проверка SSH
|
||
ssh -p 2222 admin@твой-IP
|
||
|
||
# Сканирование портов (с другого сервера)
|
||
nmap -p 1-65535 твой-IP
|
||
|
||
# Проверка firewall
|
||
telnet твой-IP 22 # Должен быть недоступен
|
||
telnet твой-IP 2222 # Должен быть доступен
|
||
```
|
||
|
||
## Что дальше
|
||
|
||
Сервер готов к установке приложений. Теперь можешь:
|
||
- Ставить веб-сервер (Nginx/Apache)
|
||
- Разворачивать почтовый сервер (Postfix/Dovecot)
|
||
- Устанавливать базы данных (PostgreSQL/MySQL)
|
||
- Крутить любые сервисы
|
||
|
||
Все специфичные настройки делаются поверх этой базы.
|
||
|
||
> [!TIP]+ **Главное:**
|
||
> Не забывай регулярно проверять логи и обновлять систему. Безопасность - это процесс, а не состояние. |