BitVPS
Чек-лист безопасности VPS: первые пятнадцать минут на новом сервере
Чек-лист безопасности

Чек-лист безопасности VPS: первые пятнадцать минут на новом сервере

Новый сервер становится доступен с любого адреса в интернете уже через секунды после загрузки, и первая автоматическая попытка входа обычно приходит раньше, чем вы дочитаете письмо с учётными данными. Звучит тревожно, но по сути таким не является: этот поток атак неизбирателен, стар как мир и полностью останавливается одной строкой конфигурации. По-настоящему дорогая ошибка на такой машине — другая: заблокировать самому себе доступ к серверу, который никто не может разблокировать за вас, потому что провайдер так и не узнал, кто вы, и никогда не хотел этого знать. Этот чек-лист выстраивает восемь важных изменений в порядке, который предотвращает оба сценария: сначала путь отступления, затем дверь, затем стена, а затем то, о чём вы забыли, что оно слушает порт.

Никакого KYC — никогда DMCA игнорируется Без журналов трафика Готов за 60 секунд

Что на самом деле атакует новый сервер — и что на самом деле его отнимает

Направьте свежий IPv4-адрес в интернет — и незапрошенный трафик появится почти сразу. Не потому, что кто-то заметил именно вас: всё адресное пространство сканируется непрерывно, и хост, который отвечает на порту 22, просто присоединяется к уже идущей очереди. За первые сутки типичный новый сервер фиксирует от нескольких сотен до нескольких десятков тысяч попыток SSH-аутентификации, почти все — на root, admin, ubuntu, test и десяток других предсказуемых имён, с паролями из списка, который почти не менялся за десять лет. Это похоже на атаку. На самом деле это больше похоже на погоду.

Это различие важно, потому что именно оно определяет, какие меры заслуживают ваших пятнадцати минут. Подбор паролей в таком объёме не снижается при отключении парольной аутентификации — он исчезает полностью. Не остаётся ни остаточного риска, которым нужно управлять, ни настроек, ни частоты, которую нужно отслеживать. А вот две вещи, которые на самом деле отнимают небольшие серверы у их владельцев, куда менее эффектны: приложение, смотрящее в интернет и работающее на версии с опубликованной, уже многомесячной уязвимостью, и учётные данные, утёкшие где-то в другом месте и всё ещё подходящие здесь. Ни то ни другое не экзотика, и ни то ни другое не имеет никакого отношения к тому, на каком порту слушает SSH.

Есть и третий сценарий отказа, и на хостинге, который никогда не спрашивал, кто вы, он самый распространённый из всех. Вы сами блокируете себе доступ. У массового провайдера это выливается в надоедливый тикет в поддержку: вы отвечаете на несколько вопросов, доказываете, что вы — тот человек, что указан в биллинге, и кто-то сбрасывает вам доступ. Здесь такого пути не существует — не потому, что это осознанный и неохотный выбор политики, а потому, что личность, которую нужно было бы проверить, никогда и не собиралась. Вместо этого есть доступ, привязанный к аккаунту, а не к человеку: аварийная консоль KVM-over-VNC в панели, ежечасные снимки с хранением семь дней и возможность загрузиться с чего-то совсем другого. Этого достаточно. Но достаточно только в том случае, если вы хоть раз воспользовались этим до того, как это понадобилось по-настоящему.

Поэтому чек-лист ниже выстроен по значимости последствий, а не по моде. Сначала — меры, которые полностью устраняют целый класс атак, в конце — те, что просто снижают фоновый шум, а ещё раньше всех остальных — шаг, который ничего не стоит и спасает вечер: убедиться, что вы всё ещё можете попасть внутрь.

Чего боятсяКак это происходит на самом делеЧто это останавливаетЧто не останавливает
SSH-подбор пароляАвтоматические сканирования, тысячи в день, типовые списки имёнPasswordAuthentication no — полностьюНестандартный порт; более длинный пароль
Сервис с известной уязвимостьюСканер сверяет баннер версии спустя недели после выхода патчаАвтоматические обновления безопасности плюс политика перезагрузокФайрвол, если порт всё равно должен быть открыт
Переиспользованные или утёкшие учётные данныеУспешный вход с первой попытки, с адреса, которого вы никогда не виделиАутентификация только по ключу; уникальные учётные данные для каждого сервисаОграничение частоты запросов — одна попытка не похожа на всплеск
Открытый внутренний сервисБаза данных, кэш или эндпоинт метрик, привязанные к wildcard-адресуПривязка к loopback; запрет входящих по умолчанию для обоих семейств адресовПредположение, что сервис приватный, потому что вы никогда на него не ссылались
Потеря собственного доступаВы что-то укрепили, вышли — а изменение оказалось ошибочнымВторая открытая сессия, снимок, проверенная консольУверенность

Проложите путь отступления, прежде чем закрывать дверь

Вот последовательность, которая оставляет людей за бортом, и при этом каждый её шаг сам по себе правилен: отредактировать конфигурацию SSH, перенести порт, отключить вход по паролю, включить файрвол, дать демону перечитать конфигурацию, закрыть терминал. Ошибка не в каком-то отдельном изменении. Она в том, что сессия, в которой вы печатаете команды, была единственным доказательством того, что хоть что-то из этого сработало, — а вы избавились от неё, так и не проверив.

Правило, которое делает весь этот чек-лист безопасным, умещается в одно предложение: держите рабочую сессию открытой и проверяйте каждое изменение из второй. Откройте новый терминал, подключитесь заново, выполните id, повысьте права через sudo. Если это сработало — изменение реально, и первую сессию можно закрывать. Если не сработало — у вас всё ещё есть оболочка, из которой можно всё откатить. Это касается файрвола, sshd, ключа нового пользователя и всего остального, что может отказать вам от двери.

Прежде всего этого настройте внеполосный доступ. В панели BitVPS у каждой строки сервера есть кнопка Консоль, которая открывает сессию KVM-over-VNC к экрану виртуальной машины. Это не оболочка по сети — это именно экран и клавиатура машины, — поэтому она продолжает работать, даже когда sshd не запускается, когда файрвол отбрасывает все входящие пакеты и когда неправильно настроена сеть. Откройте её один раз прямо сейчас, на сервере, который вы ещё не сломали. Убедитесь, что видите приглашение входа. Это займёт тридцать секунд и станет разницей между ошибкой и полноценной аварией.

Сделайте и снимок. На каждом тарифе они ежечасные, с хранением семь дней, и восстанавливаются примерно за тридцать секунд, — это превращает «я вставил не то правило nft» из вечера восстановления в простой откат. А для изменений, в которых вы по-настоящему не уверены, страховка стоит одной строки: systemd-run --on-active=10min /usr/sbin/ufw --force disable ставит таймер, который через десять минут отключит файрвол, если вы его не отмените. Если новые правила работают — вы отменяете таймер. Если они заблокировали вам доступ — машина сама впускает вас обратно, даже если вас нет рядом.

SSH: четыре директивы, которые всё решают, — и файл, который их переопределяет

Создавайте ключ на своей машине, никогда — на сервере: ssh-keygen -t ed25519 -C "laptop-2026". В 2026 году Ed25519 — правильный выбор по умолчанию: короткие ключи, быстрая проверка, никаких параметров, в которых можно ошибиться, и поддержка в любом OpenSSH, собранном за последнее десятилетие. RSA на 4096 битах не является небезопасным — он просто больше и медленнее без какой-либо выгоды. Установите пароль на приватный ключ; ssh-agent позволяет вводить его один раз за сессию, и это единственное, что стоит между украденным ноутбуком и каждым вашим сервером.

Скопируйте публичную половину на сервер с помощью ssh-copy-id и убедитесь, что можете войти по ней, прежде чем что-либо отключать. Права доступа имеют значение, и OpenSSH намеренно строго их проверяет: ~/.ssh с правами 700, authorized_keys с правами 600, оба принадлежат пользователю. Если ключ молча не работает, почти всегда дело в правах доступа, и sshd -e -d, запущенный на переднем плане, сообщит об этом одной строкой.

Дальше практически всю работу делают четыре директивы в /etc/ssh/sshd_config. Всё остальное в этом файле — дело вкуса.

ДирективаУстановите вЧто она делаетЧто сломается, если ошибиться
PasswordAuthenticationnoПолностью убирает пароль как способ входа — весь поток подбора паролей становится не просто медленнее, а невозможнымВы останетесь без доступа, если ваш ключ на самом деле не был установлен. Сначала проверьте — во второй сессии
KbdInteractiveAuthenticationnoЗакрывает вторую дверь в ту же комнату — интерактивный путь PAM всё ещё может принять пароль, даже если первая директива уже установленаЛомает легитимные схемы двухфакторной аутентификации на основе PAM. Оставляйте включённой, только если вы её используете
PermitRootLoginprohibit-passwordRoot всё ещё может войти по ключу (полезно для автоматизации), но никогда — по паролюno строже и вполне подходит — при условии, что ваш sudo-пользователь работает. Сначала проверьте это
PubkeyAuthenticationyesМетод, который вы оставляете. Здесь явное указание лучше значения по умолчаниюНичего, но стоит прописать явно, чтобы будущее редактирование не убрало его незаметно
AllowUsers / AllowGroupsваш пользователь или группаНеобязательно, но это самая ценная необязательная строка — демон отказывает всем остальным учётным записям ещё до аутентификацииОпечатка запрещает доступ всем. Устанавливайте её последней и из второй сессии

А теперь то, на чём попадаются даже опытные администраторы. В Debian 12, Ubuntu 22.04 и во всех более новых версиях /etc/ssh/sshd_config начинается со строки Include /etc/ssh/sshd_config.d/*.conf, а OpenSSH использует первое найденное значение для каждого параметра. Облачные образы кладут в этот каталог свои drop-in-файлы — часто такой, что устанавливает PasswordAuthentication yes, — и поскольку include стоит в самом начале, этот drop-in-файл побеждает строку, которую вы аккуратно отредактировали двумястами строками ниже. Файл утверждает одно, а демон делает другое.

Решение — никогда не доверять файлу. Спросите у самого демона, что он в итоге получил: sshd -T | grep -Ei 'passwordauth|permitrootlogin|kbdinteractive|pubkeyauth' выводит действующую конфигурацию после применения всех include, match-блоков и значений по умолчанию. Одна эта команда стоит больше, чем весь остальной раздел. Дополните её командой sshd -t, которая проверяет синтаксис и завершается с ненулевым кодом при ошибке, и только потом выполните systemctl reload ssh — перечитывание конфигурации не разрывает существующие сессии, так что даже неудачное перечитывание оставит вашу текущую оболочку в живых.

Что касается переноса SSH с порта 22: это уберёт, возможно, 95% объёма ваших логов и ноль процентов риска. Любой сканер, о котором стоит беспокоиться, проверяет все 65,535 портов, а те немногие, что этого не делают, всё равно никогда не прошли бы аутентификацию по одним лишь ключам. Переносите порт, если шум вас раздражает или мешает мониторингу, но не записывайте это в меры безопасности — а если всё же переносите, держите номер порта ниже 1024: такие порты вправе занимать только привилегированные процессы, так что непривилегированный процесс не сможет занять его, если демон вдруг остановится.

Файрвол: запрет входящих по умолчанию и та половина, о которой все забывают

У файрвола на сервере с одной задачей одна работа: сделать множество доступных портов равным множеству портов, для которых вы можете назвать причину. Запретить входящие по умолчанию, разрешить исходящие, разрешить обратно установленные и связанные соединения, а затем открыть те две-три вещи, которые вы действительно запускаете. Если у вас Debian или Ubuntu, ufw — это четыре команды, и этого достаточно; если вы предпочитаете один читаемый файл правил, nftables — современный ответ на уровне ядра и то, во что в итоге пишет сам ufw.

Порядок действий важен ровно в одном месте: разрешите свой порт SSH прежде, чем включать политику. Сначала ufw allow 22/tcp, затем ufw default deny incoming, затем ufw enable. В обратном порядке шаг включения оборвёт ту самую сессию, в которой вы печатаете команды, — это переживаемо, если вы прошли предыдущий раздел и у вас всё ещё есть консоль, а иначе это классический способ рано закончить вечер.

Забытая половина — это IPv6. Каждый сервер здесь получает маршрутизируемый /64, а сервисы по умолчанию привязываются к обоим семействам адресов. Набор правил, написанный только на iptables, управляет исключительно IPv4 и ничего не говорит про IPv6, так что тщательно защищённая файрволом база данных остаётся доступной из всего интернета по другому протоколу. ufw управляет обоими, когда установлено IPV6=yes в /etc/default/ufw (это значение по умолчанию в текущих релизах — проверьте, а не полагайтесь на это), а nftables обходит проблему структурно: набор правил table inet покрывает оба семейства одним набором правил. Если и писать вручную только одну строку конфигурации файрвола — пусть это будет она.

Затем есть Docker, который не столько обходит ваш файрвол, сколько заходит снизу, под ним. Публикация порта через -p 5432:5432 добавляет правила DNAT в таблицу nat, а они проверяются раньше цепочек фильтрации, которыми управляет ufw. В результате контейнер доступен из интернета, пока ufw status показывает порт как закрытый, и из года в год это застаёт врасплох людей, запустивших базу данных в контейнере за политикой, которую они считали запрещающей всё. Вместо этого публикуйте на loopback — -p 127.0.0.1:5432:5432 — либо поместите контейнер во внутреннюю сеть и обращайтесь к нему из другого контейнера по имени.

Во что вы веритеКак обстоит дело на самом делеКак проверить одной командой
«Файрвол запрещает всё, что я не разрешил»Верно только для IPv4, если вы написали правила только для IPv4ip6tables -L -n или nft list ruleset
«База данных не открыта наружу, она в контейнере»Опубликованный порт доступен независимо от политики фильтрацииdocker ps --format '{{.Ports}}'
«На этом порту ничего не слушает»Что-то перезапустилось и заново привязалось к нему уже после того, как вы в последний раз проверялиss -tulpn
«Порт закрыт, это подтвердило моё сканирование»Сканирование с самой машины проверяет loopback, а не интернетСканируйте со второго хоста или со своего ноутбука

Что на самом деле слушает порты — команда, которая кладёт конец догадкам

Одна команда отвечает на самый полезный вопрос об открытости сервера наружу: ss -tulpn. Она перечисляет каждый прослушивающий TCP- и UDP-сокет вместе с процессом, которому он принадлежит, и важен именно столбец локального адреса. 127.0.0.1:5432 означает, что подключиться может только эта машина. 0.0.0.0:5432 означает, что подключиться может любой адрес, способный достучаться до машины, — с единственным ограничением в виде файрвола. [::]:5432 означает то же самое, но по IPv6, и это та строка, которую обычно пробегают взглядом не глядя.

Список постоянных нарушителей всегда один и тот же. Redis, который почти всю свою историю привязывался широко и поставлялся вовсе без аутентификации. PostgreSQL и MySQL — когда конфигурационный файл правили, чтобы принимать соединения «от приложения», а потом приложение переехало. MongoDB и Elasticsearch, которые вдвоём обеспечили добрый десяток лет заголовков об утечках данных именно по этой причине. Memcached, чей UDP-слушатель стал одним из любимых усилителей трафика. Prometheus node_exporter, который с готовностью расскажет о внутреннем устройстве вашего хоста любому, кто спросит. Docker API на порту 2375 — это удалённое выполнение кода, притворяющееся REST-интерфейсом. И сервер для разработки, который кто-то запустил «буквально на минуту» в панели tmux одиннадцать месяцев назад.

Правило простое и не требует размышлений: если сервису не нужен доступ из интернета, привяжите его к loopback. Всё, для чего он лично вам нужен, продолжит работать — ssh -L 5432:127.0.0.1:5432 user@server даёт локальный порт, который туннелируется через соединение, которому вы уже доверяете, а если доступ нужен нескольким машинам, приватный интерфейс WireGuard даёт им диапазон адресов, который никогда не касается публичного интернета. Ни то ни другое ничего не стоит, и оба варианта не защищают сервис, а полностью убирают его из поверхности атаки.

Проверяйте снаружи, а не изнутри. То, что порт помечен как отфильтрованный на самой машине, — это утверждение о вашем собственном стеке loopback; то, что до порта не может достучаться вторая машина, — это уже доказательство. Подключитесь со своего ноутбука или с другого сервера и проверьте порты, которые должны быть открыты, и один, который должен быть закрыт, — тест, который не может провалиться, не является тестом.

СервисТипичное значение по умолчаниюЧто отдаёт открытый наружу экземплярРешение
RedisШирокая привязка, исторически без пароляПолный доступ на чтение и запись, а также известный способ записи файлов от имени пользователя redisПривяжите к loopback; установите requirepass; держите protected-mode включённым
PostgreSQL / MySQLLoopback, пока кто-нибудь это не изменитВесь ваш набор данных, если пароль слабый или переиспользованныйПривяжите к loopback; обращайтесь через SSH или WireGuard
Docker APIВыключен — если только его не включил какой-нибудь туториалВыполнение кода на хосте с правами, эквивалентными rootНикогда не открывайте его наружу; используйте вместо этого SSH-контекст
node_exporter / метрикиВсе интерфейсы, порт 9100Имена хостов, точки монтирования, версии, запущенные процессыПривяжите к loopback; собирайте метрики через приватный интерфейс
Отправка почты, веб-панели администрированияВсе интерфейсы — по необходимостиПоверхность для подбора паролей, которую ключи защитить не могутВот здесь ограничение частоты запросов действительно уместно

Fail2ban и CrowdSec: чего они стоят, когда паролей больше нет

Это пункт, который большинство чек-листов ставят почти в самое начало, а большинство администраторов переоценивают, так что стоит быть точным. При PasswordAuthentication no подбор пароля не может увенчаться успехом — не редко, не с трудом, а никак. Блокировка адреса после пяти неудачных попыток не делает невозможную аутентификацию ещё невозможнее. На уровне SSH fail2ban даёт вам более тихий auth.log, чуть меньше нагрузки на CPU при установке соединений и графики мониторинга, которые проще читать. Это реальные преимущества. Но это эксплуатационная гигиена, а не мера безопасности, и если записать их не в ту графу, в итоге можно получить надёжно защищённый файл логов — и ни разу не пропатченное приложение.

Инструменты такого класса по-настоящему оправдывают себя на любом уровне, где всё ещё есть пароль: форма входа веб-приложения, порт отправки почты, админка Nextcloud или WordPress, сервер IMAP. Их нельзя перевести на аутентификацию по открытому ключу, так что подбор пароля остаётся возможным, и ограничение частоты запросов — это реальная защита. CrowdSec добавляет сверху общую ленту репутации адресов, что по-настоящему полезно на уровне HTTP — вы выигрываете за счёт адресов, чьё плохое поведение уже видели другие, — и почти не имеет значения на уровне SSH, если ключи обязательны.

Стоит назвать два способа выстрелить себе в ногу. Первый — заблокировать самого себя, обычно во время тестирования чего-то в три часа ночи; включите свои собственные диапазоны в ignoreip и помните, что общий адрес или адрес за carrier-grade NAT означает, что, блокируя «атакующего», можно заодно заблокировать пару сотен ни в чём не повинных людей. Второй — инструмент должен быть способен читать логи, которые он фильтрует: на дистрибутивах, которые пишут только в journal systemd, файловый бэкенд по умолчанию молча следит за файлом, в который больше ничего не попадает, а джейл сидит себе, выглядит здоровым и ничего не делает.

Честная рекомендация: ставьте, если шум вас раздражает, настраивайте на уровне приложения, где это действительно важно, и не засчитывайте его дважды. Если нужна та же тишина, но совсем без обслуживания, — директивы MaxStartups и LoginGraceTime в демоне SSH вместе с аутентификацией только по ключу закрывают большую часть этой задачи и никогда не заблокируют вам доступ к собственной машине.

Патчинг: скучная мера, которая предотвращает большинство реальных взломов

Откройте любой разбор инцидента с участием небольшого сервера, смотрящего в интернет, — и картина повторяется: у уязвимости был патч, патч был доступен неделями или месяцами, и никто его не установил. Полезное чтение здесь — каталог активно эксплуатируемых уязвимостей CISA, именно потому, что это не список теоретической опасности — это список того, что прямо сейчас эксплуатируется в реальном мире, и в нём преобладают проблемы с уже опубликованными исправлениями. Поэтому автоматические обновления безопасности — это самые окупаемые пятнадцать секунд на всей этой странице.

В Debian и Ubuntu установите unattended-upgrades, включите его командой dpkg-reconfigure -plow unattended-upgrades и убедитесь, что в /etc/apt/apt.conf.d/50unattended-upgrades выбран именно security-репозиторий. Проверьте, что он в самом деле что-то делает, командой unattended-upgrades --dry-run --debug, которая печатает, какие именно пакеты будут взяты и почему, — справочный материал здесь — страница Debian wiki. В Rocky и Alma ту же работу делает dnf-automatic с apply_updates = yes и включённым таймером. Ограничение только security-репозиторием — осознанный выбор: это конфигурация, которая почти никогда ничего не ломает, а это единственный вид автоматизации, который люди оставляют включённым надолго.

Дальше явно решите вопрос с перезагрузками, потому что именно здесь эта мера обычно даёт слабину. Установка нового пакета ядра не заменяет ядро, которое сейчас работает, а замена разделяемой библиотеки не перезапускает демоны, которые уже отобразили старую копию в память. needrestart в Debian и Ubuntu точно перечисляет, какие сервисы всё ещё держат удалённые библиотеки; обновление ядра требует перезагрузки — без вариантов, а живой патчинг (live-patching) — платная функция, которая не появится на инстансе за $8.50. Либо настройте Unattended-Upgrade::Automatic-Reboot с тихим временем Automatic-Reboot-Time, либо внесите ежемесячную перезагрузку в свой календарь и относитесь к ней как к обслуживанию, а не как к инциденту.

Наконец, знайте, чего автоматические обновления не покрывают, потому что именно в этом пробеле люди и попадаются. Всё, что установлено в обход пакетного менеджера, для него невидимо: бинарник, скачанный из релиза на GitHub, зависимость языковой среды выполнения из pip, npm или cargo, тема или плагин внутри веб-приложения и, прежде всего, образы контейнеров. Хост, который сообщает о нуле ожидающих обновлений, вполне может работать на базовом образе, собранном два года назад, — и ничто на машине вам об этом не скажет. Если вы используете контейнеры, регулярная пересборка и повторное скачивание образов по расписанию — это часть патчинга, а не отдельная задача.

СистемаМеханизмЧто покрываетЧто незаметно упускает
Debian / Ubuntuunattended-upgrades, только security-репозиторийПакеты дистрибутива, применяются каждую ночьРаботающее ядро и отображённые в память библиотеки — до перезагрузки
Rocky / Almadnf-automatic с apply_updates = yesТо же самое, через таймер systemdТот же пробел с перезагрузкой; проверяйте через dnf needs-restarting
КонтейнерыНичего, по умолчаниюНичегоВсё — образ заморожен на момент сборки
Зависимости языковой средыНичего, по умолчаниюНичегоРеальную поверхность атаки вашего приложения

Пользователи, sudo и двери, которые незаметно открываются заново

Создайте обычного пользователя, добавьте его в sudo или wheel, установите туда свой ключ и перестаньте входить как root. Причина не в том, что root с ключом опасен сам по себе, — это однофакторная учётная запись с универсально известным именем и без записи о том, какой именно человек ею пользовался. Именованная учётная запись плюс sudo даёт журнал аудита, позволяет работать нескольким операторам без общих учётных данных и делает вопрос «кто это запустил» в итоге отвечаемым. Однако не выдавайте ей NOPASSWD на всё подряд и не используйте затем эту же учётную запись для веб-сервиса.

Сервисы тоже не должны работать от root, и systemd делает бюджетную версию такой изоляции почти бесплатной. Drop-in-файл, созданный командой systemctl edit <unit> и содержащий NoNewPrivileges=yes, ProtectSystem=strict, ProtectHome=yes и PrivateTmp=yes, запирает скомпрометированный демон в файловой системе, доступной только для чтения, без пути к повышению привилегий, — четыре строки, описанные в документации systemd.exec, которые превращают многие уязвимости приложений из «root на хосте» в «строчку с ошибкой в логе». systemd-analyze security оценивает каждый юнит на машине и подсказывает, какие из них стоят потраченных пяти минут.

Держите authorized_keys в честном состоянии. Один ключ на устройство, у каждого — комментарий с названием устройства, а всё, что вы не можете опознать, — удаляйте. Перечитывайте файл после запуска любого инструмента provisioning, потому что cloud-init, конвейеры сборки образов и панели управления добавляют туда собственные записи, а ключ, который добавили не вы, — это ключ, который вы не можете отозвать. То же касается учётных записей: пользователь по умолчанию, оставшийся от образа, с паролем, который установил скрипт и которым никто с тех пор не пользовался, — это вход, за которым вы не следите.

Самый неочевидный пункт в этом списке — проброс агента. ForwardAgent yes позволяет процессу на удалённом хосте использовать ваш локальный приватный ключ на всё время, пока вы подключены, — именно для этого он и создан, и именно поэтому root на машине, которую вы не полностью контролируете, может одолжить ваш ключ, чтобы добраться до любого другого сервера, который этому ключу доверяет. Используйте вместо этого ProxyJump (ssh -J bastion target): он даёт ту же доступность за счёт туннелирования соединения, а ваш ключ никогда не становится пригодным для использования на промежуточном хосте. Если проброс агента всё же необходим, делайте это для конкретного хоста в ~/.ssh/config, но никогда — глобально.

Резервные копии: мера, которая превращает плохой день в потерянные полдня

Всё, что было выше, снижает вероятность плохого дня. Резервные копии определяют, во сколько этот плохой день обойдётся, а у провайдера, который намеренно не может вас идентифицировать, они важны сильнее, чем обычно: здесь нет пути через поддержку, который восстановит вашу машину из чужой копии, нет процедуры восстановления доступа к аккаунту, которая незаметно выдаст вам восстановление данных, и нет биллинговой записи с привязанным номером телефона. У вас есть ровно то, что вы сами сохранили.

Рабочая схема здесь скучна до неприличия. restic или borg, шифрование на самом сервере — так, чтобы данные были нечитаемы ещё до того, как пересекут сеть, — и отправка на вторую машину, а в идеале и во вторую юрисдикцию, что превращается из отдельного проекта в галочку, когда одна и та же панель предлагает Исландию, Нидерланды, Румынию и Швейцарию. Ежечасные снимки, включённые в каждый тариф, — по-настоящему хороший первый рубеж, и они прекрасно покрывают случай «я час назад сломал конфигурацию». Но они не покрывают файл, который вы удалили пять недель назад, и живут на той же инфраструктуре, что и то, что они защищают. Снимки и резервные копии решают разные задачи — используйте и то, и другое.

Сделайте репозиторий доступным только на дозапись (append-only). Именно эта деталь отличает резервную копию от простой копии: скомпрометированный сервер хранит учётные данные к собственной цели резервного копирования, а всему, что умеет удалять, рано или поздно прикажут удалять. И borg serve --append-only, и rest-server --append-only у restic обеспечивают это на принимающей стороне, так что машина может записывать новые снимки, но не может удалить старые. Чистку (prune) выполняйте откуда-то ещё, по расписанию, с учётными данными, которые сервер никогда не видел.

Две последние вещи, которые обычно пропускают. Пароль от репозитория не должен жить только на той машине, которую он защищает, — запишите его, положите в менеджер паролей где-то ещё, относитесь к нему как к seed-фразе, которой он по сути и является. И восстановите его хотя бы раз. Резервная копия, которую вы ни разу не восстанавливали, — это гипотеза; обычный способ узнать, что правило исключения незаметно пропустило дамп базы данных, — это восстановление, в котором вы не можете позволить себе ошибиться. Разверните инстанс Starter, восстановите резервную копию в него, проверьте данные, уничтожьте инстанс. Это стоит $8.50 и один час, и только так всё остальное на этой странице становится репетицией, а не первой попыткой.

От чего защита сервера вас не убережёт

Она не защитит диск от того, у кого физически оказался этот диск. Каждая мера на этой странице предполагает, что операционная система работает и применяет свои собственные правила; ни одна из них не действует на выключенной машине, чьё хранилище уже сняли образом. Это другая проблема с другим ответом — см. полное шифрование диска, удалённую разблокировку и что реально достаётся при изъятии, — и честный вывод в том, что защита сервера и шифрование обороняются от непересекающихся угроз. Сделав одно, вы не делаете отчасти и другое.

Она не исправит приложение, которое вы запускаете. Сервер может пройти здесь каждую проверку — и всё равно быть потерян из-за устаревшего форума, административного эндпоинта без аутентификации, шаблонизатора, вычисляющего пользовательский ввод, или токена, закоммиченного в публичный репозиторий. Защита хоста сокращает радиус поражения при компрометации приложения — именно для этого и нужна описанная выше изоляция средствами systemd, — но она не аудирует ваш код, и самый распространённый способ потерять небольшой сервер — это всё ещё что-то, что установил сам администратор.

Она не изменит того, кто знает, что вы арендовали эту машину. Идеально защищённый сервер, оплаченный с аккаунта биржи с пройденной верификацией личности и заказанный на личный email, — это идеально защищённый сервер с вашим именем на нём. Уровень безопасности и уровень идентификации независимы друг от друга, и второй решается на этапе оформления заказа, а не в командной оболочке — о том, где на самом деле возникают эти связи, рассказывает материал насколько на самом деле отслеживаем хостинг, оплаченный криптовалютой.

И она ничего не может поделать с анализом трафика. Наблюдатель, способный видеть ваши соединения, узнаёт их форму — тайминги, объём, кто с кем говорит — независимо от того, насколько хорошо настроены конечные точки. Шифрование скрывает содержимое, а не сам факт разговора, и никакая тонкая настройка sshd этого не изменит.

Чек-лист в порядке выполнения

Восемь шагов. Первые четыре — это те самые пятнадцать минут из заголовка, и они устраняют целые категории риска; последние четыре занимают больше времени и как раз отличают сервер, который вы можете защитить, от сервера, который вы просто настроили. В каждой строке указано, как понять, что шаг сработал, потому что непроверенный шаг защиты — это шаг, который вы на самом деле не сделали.

ШагКак понять, что сработало
1Откройте консоль в панели, убедитесь, что видите приглашение входа, сделайте снимокВы увидели приглашение входа на сервере, который ещё не был сломан
2Создайте пользователя не-root, установите свой ключ ed25519, проверьте sudoВо втором терминале вход под этим пользователем и повышение прав проходят успешно
3Отключите парольную и keyboard-interactive аутентификациюsshd -T сообщает passwordauthentication no
4Файрвол с запретом входящих по умолчанию для IPv4 и IPv6nft list ruleset показывает оба семейства адресов; сканирование с другого хоста это подтверждает
5Проверьте прослушивающие сокеты, перепривяжите внутренние сервисы к loopbackss -tulpn не показывает ни одной wildcard-привязки, которую вы не можете объяснить
6Включите автоматические обновления безопасности и политику перезагрузокunattended-upgrades --dry-run --debug выбирает security-репозиторий
7Изолируйте сервисы средствами systemd, приведите в порядок authorized_keysОценки systemd-analyze security улучшаются; у каждого ключа есть имя
8Зашифрованная резервная копия append-only на другой площадке, хотя бы раз восстановленнаяВы восстановили её на одноразовый инстанс, и данные оказались на месте

Ничего из этого не экзотика, и в этом весь смысл. На небольшом сервере важны именно те меры, которые устраняют целый класс проблемы, а не управляют ею: никаких паролей, никаких неожиданных слушателей, никаких непропатченных пакетов, ни одной-единственной копии данных. Всё остальное — дело вкуса, а вкус обходится дёшево, как только четыре несущих изменения внедрены и проверены.

Если вы разворачиваете машину прямо сейчас, а не читаете это заранее, вся последовательность спокойно укладывается в первую же сессию: разверните инстанс, один раз откройте консоль, чтобы убедиться, что она работает, и выполните восемь шагов по порядку ещё до того, как устанавливать хоть что-то ещё. У сервера, защищённого до того, как на нём появился хоть один сервис, нет никакого legacy, с которым приходилось бы разбираться, — это единственное преимущество нового сервера, и длится оно примерно сутки.

Быстрые ответы

Часто задаваемые вопросы

Стоит ли переносить SSH с порта 22?
Это уберёт большую часть шума в логах и ни капли риска. Сканеры, которые имеют значение, проверяют весь диапазон портов, а те, что пробуют только 22-й, всё равно никогда не преодолели бы аутентификацию только по ключу. Переносите порт, если шум вас раздражает или если это утихомирит алерт мониторинга, — только не записывайте это в меры безопасности и не забудьте открыть новый порт в файрволе прежде, чем демон перечитает конфигурацию.
Стоит ли всё ещё ставить fail2ban, если я разрешаю вход по SSH только по ключам?
На уровне SSH он покупает тишину, а не безопасность: при PasswordAuthentication no подбор пароля не может увенчаться успехом, так что ограничение частоты попыток для невозможного входа ничего не меняет. Он оправдывает себя на тех уровнях, где пароль всё ещё существует, — веб-панель администрирования, отправка почты, сервер IMAP. Ставьте его именно там, укажите в ignoreip свои собственные диапазоны, чтобы не заблокировать самого себя, и убедитесь, что он читает лог, в который всё ещё что-то попадает.
Я заблокировал себе доступ к серверу — что реально можно сделать?
Откройте кнопку Консоль в строке сервера в панели. Это сессия KVM-over-VNC прямо к собственному экрану машины, поэтому она работает даже тогда, когда sshd не запускается и когда файрвол отбрасывает каждый пакет, — войдите там и отмените изменение. Если система вообще не загружается, восстановите один из ежечасных снимков (хранение семь дней, примерно тридцать секунд). Чего мы не можем сделать — это подтвердить, что вы — это вы, и сбросить вам доступ: при регистрации не собиралось никакой информации о личности, так что доступ, привязанный к аккаунту, — единственный существующий путь восстановления.
Нужен ли файрвол, если ничего не слушает порты?
Да, потому что «ничего не слушает» — это утверждение про именно эту минуту. Обновление пакета запускает демон, контейнер публикует порт, коллега что-то тестирует и оставляет это работать. Политика запрета по умолчанию превращает каждый такой случай в незначащее событие вместо открытости, о которой вы узнаете уже потом. Это стоит четырёх команд, и это единственная мера на этой странице, которая защищает вас от ваших же будущих изменений.
PermitRootLogin: использовать prohibit-password или no?
prohibit-password — разумное значение по умолчанию: root всё ещё может аутентифицироваться ключом, а значит, автоматизация и аварийный доступ продолжают работать, но никогда — паролем. no строже и корректно, если вы уже проверили, что ваш пользователь с sudo работает, — из второй сессии, и это стоит сделать перед тем, как ставить любое из двух значений. Важная половина в том, что root никогда не должен принимать пароль; принимает ли он ключ — это уже вопрос эксплуатационных предпочтений.
Могут ли автоматические обновления безопасности сломать мой сервер?
Редко, если ограничиться security-репозиторием — этот репозиторий существует именно для того, чтобы поставлять минимальные исправления без изменений поведения, и это та конфигурация, которую люди оставляют включённой годами. Больший риск — обратный: администратор отключает автоматизацию из-за одной неудачной ночи, а потом полгода отстаёт от обновлений. Если вы размещаете что-то хрупкое, включите автоматическую загрузку обновлений с ручным применением — и внесите шаг применения в свой календарь, а не в свои намерения.
Почему мой контейнер Docker доступен, хотя ufw говорит, что порт закрыт?
Потому что публикация порта записывает правила DNAT в таблицу nat, которую ядро проверяет раньше цепочек фильтрации, которыми управляет ufw, — пакет перенаправляется в ваш контейнер ещё до того, как его вообще увидит запрещающая политика. Публикуйте на loopback через -p 127.0.0.1:5432:5432 и обращайтесь к сервису через SSH-туннель, либо поместите контейнер во внутреннюю сеть Docker, чтобы вообще ничего не публиковалось наружу. Проверка ufw status этого никогда не покажет; а вот ss -tulpn и сканирование с другой машины — покажут.
Как часто нужно всё это повторять?
Шаги по настройке — разовые. Периодически нужно проверять три вещи: ss -tulpn — после установки всего, что потенциально может начать слушать порт, authorized_keys — каждый раз, когда устройство меняет владельца, и тест восстановления — примерно раз в полгода. Всё остальное либо автоматическое, либо неизменное. Запись в календаре раз в полгода со словами «слушатели, ключи, восстановление» покрывает всю текущую нагрузку от этой страницы.
Применить

Нагрузки, к которым относится это руководство

Каждая карточка открывает страницу с рекомендациями по размеру и FAQ системного администратора.

Читать дальше

Другие руководства

Сопутствующие материалы, продолжающие там, где это руководство заканчивается.

Разбор по усилению защиты Полное шифрование диска на VPS: LUKS, удалённая разблокировка и что на самом деле остаётся после изъятия

Полное шифрование диска на VPS: LUKS, удалённая разблокировка и что на самом деле остаётся после изъятия

Шифровать диск арендованного сервера стоит, но оно не делает того, что большинству кажется. Где именно проходит граница между выключенной машиной и работающей, как установить зашифрованный root и разблокировать его по SSH, и что на самом деле выдаёт снятый образ диска.

14 мин чтения Читать руководство
Пошаговая инструкция по VPN Свой VPN на VPS: WireGuard за десять минут и та приватность, которую он реально даёт

Свой VPN на VPS: WireGuard за десять минут и та приватность, которую он реально даёт

VPN не прячет вас — он лишь меняет того, кто может за вами наблюдать. Разбираемся, чего стоит такой обмен, когда точка выхода — ваш собственный сервер, приводим пятнадцать строк WireGuard, которые поднимают туннель, и четыре утечки, что незаметно обходят только что построенный туннель.

15 мин чтения Читать руководство
Гид по доставляемости Свой почтовый сервер на VPS: порт 25, PTR и почему письма всё равно попадают в спам

Свой почтовый сервер на VPS: порт 25, PTR и почему письма всё равно попадают в спам

Свой почтовый сервер на VPS настроить просто, с доставляемостью сложнее. Что проверяют получатели, как работают SPF, DKIM и DMARC и когда self-hosting не подходит.

15 мин чтения Читать руководство
Доверие и отслеживаемость Анонимен ли VPS? Насколько отслеживаем хостинг за криптовалюту на самом деле

Анонимен ли VPS? Насколько отслеживаем хостинг за криптовалюту на самом деле

Честная карта того, что no-KYC хостинг может и не может увидеть о вас — платёжный след, IP подключения, контент, который вы размещаете — и три разных вида «анонимности», которые люди путают между собой.

9 мин чтения Читать руководство

Прочитали достаточно? Развернуть за 60 секунд

Без верификации email, без удостоверения, без аккаунта. Выберите тариф, оплатите любой криптовалютой, получите root.