Первый сервер на Linux: как настроить SSH и файрвол, не потеряв доступ
SSH-соединение может умереть на пяти разных уровнях: от закрытого порта до неверных прав на домашний каталог. Если вы не знаете, на каком именно — вы не чините, а гадаете. https://seberd.ru/38867
Когда вы разворачиваете виртуальную машину — будь то локальный гипервизор вроде Proxmox, KVM, ESXi или облачный VPS — на старте вы получаете доступ только к консоли. Это виртуальный монитор и клавиатура, подключённые напрямую к гостевой операционной системе, минуя её сетевой стек. Сетевой порт SSH может быть закрыт, демон не запущен, а файрвол настроен по принципу «разрешить всё» или, наоборот, заблокировать сеть из-за кривого шаблона образа.
Задача первоначальной настройки — заменить хаос открытых портов явным списком разрешений, не потеряв при этом единственный канал управления. И здесь кроется главная инженерная проблема: вы настраиваете сетевой доступ, ещё не настроив канал, который сами же собираетесь перестраивать.
Почему теряют доступ к свежему серверу и как этого избежать
Представим типичный случай: администратор подключается по SSH, отключает вход по паролю, меняет порт или вносит правило в файрвол, которое блокирует 22-й порт. Сессия, через которую он это делал, обрывается. Он пытается зайти снова — соединение не устанавливается. Сервер работает, но дверь заперта изнутри.
Причина почти всегда в том, что изменение применилось, а запасного входа не было. Демон SSH (sshd) при перезапуске перечитывает конфигурацию. Если в файле опечатка, указан неверный путь к ключам или отключена аутентификация по паролю до того, как был добавлен ключ, новый вход становится невозможным. Старая сессия при этом может быть разорвана политикой перезапуска или таймаутом.
Единственное правило, которое предотвращает этот сценарий: никогда не закрывать текущую сессию, пока не проверена новая. Перед тем как перезапускать SSH или менять правила файрвола, откройте второе окно терминала и подключитесь к серверу. Если после применения изменений вторая сессия продолжает отвечать — вы в безопасности. Если нет — вы всё ещё внутри системы и можете откатить изменения.
Эта граница важна для одиночного сервера, где SSH — единственный канал управления. В инфраструктуре с бастион-хостами, менеджерами сессий вроде Teleport или консолью облачного провайдера доступ восстанавливается централизованно, и цена опечатки заметно ниже. Но пока у вас только один VPS и один терминал, второе окно — это ваша страховка.
Типовые ошибки при обновлении пакетами, из-за которых команды ломаются
Прежде чем менять настройки, систему нужно обновить. И здесь новички часто спотыкаются о синтаксис командной строки. В логах новичков встречаются команды вида sudo aptupdate $$ aptupgrade -a. Разберём, почему они не работают.
Первая ошибка — слитное написание. Команда называется apt, а update и upgrade — это её аргументы. Правильно: apt update, а не aptupdate.
Вторая ошибка — использование $$ вместо &&. В bash && выполняет следующую команду только если предыдущая завершилась успешно. А $$ — это специальный параметр, который подставляет идентификатор текущего процесса (PID). Оболочка превращает команду в бессмысленный набор аргументов.
Третья ошибка — забытый sudo во второй части цепочки. Команда sudo apt update && apt upgrade -y выполнит обновление списков с правами администратора, но попытка установки обновлений запустится от имени обычного пользователя. Результат предсказуем:
Error: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
Правильная связка выглядит так:
sudo apt update && sudo apt upgrade -y
Здесь sudo стоит перед каждой командой. Если вы хотите выполнить команды последовательно независимо от результата, можно использовать точку с запятой ;, но для обновлений лучше подходит && — он не даст устанавливать пакеты, если список не обновился.
Проверка успешного выполнения проста: вы видите сообщение об обновлении списков пакетов и процесс установки без ошибок Permission denied или Command not found. После этого можно переходить к настройке доступа.
Настройка SSH: от генерации ключей до безопасного отключения паролей
Аутентификация по паролю — первое, что отключают на публичном сервере. Боты начинают подбирать пароли в течение минут после появления IP-адреса в сети. Переход на SSH-ключи убирает эту проблему: подобрать приватный ключ перебором невозможно.
Откуда брать данные для подключения
Перед генерацией ключей нужно понять, под каким именем и по какому адресу вы будете подключаться. Эти данные не выдумываются, а берутся из консоли сервера или панели управления.
В консоли гипервизора выполните:
whoami
Команда покажет имя пользователя, под которым вы вошли. На свежей ВМ это часто root. Если вы создавали отдельного пользователя при установке, будет его имя.
Далее узнайте IP-адрес:
ip a
В выводе найдите сетевой интерфейс (обычно eth0, ens3 или enp0s3) и строку, начинающуюся с inet. Число после inet — это IP-адрес машины. Если сервер в облаке, адрес и имя пользователя обычно указаны в панели управления после создания инстанса.
Эти два значения — имя пользователя и IP — подставляются в команду подключения. Всё остальное, что вы видите в примерах вроде admin@myserver, — это заполнители.
Как подключиться с Windows к Linux
В Windows 10 и 11 встроен клиент OpenSSH. Откройте PowerShell или командную строку и выполните:
ssh -V
Если команда вывела версию клиента — всё готово. Если система пишет, что команда не найдена, установите компонент: Параметры → Приложения → Дополнительные компоненты → Клиент OpenSSH. После установки перезапустите терминал.
Подключение выглядит так:
ssh имя_пользователя@IP_адрес
Например, если whoami показал root, а ip a показал 192.168.1.50:
ssh root@192.168.1.50
При первом подключении клиент спросит, доверяете ли вы отпечатку ключа сервера. Введите yes и пароль пользователя.
Альтернатива — PuTTY, графический клиент. Но для современных ключей Ed25519 встроенный OpenSSH проще: он понимает их сразу, тогда как старые версии PuTTY требуют конвертации через PuTTYgen. Дальше в статье все команды предполагают встроенный клиент Windows или терминал Linux/macOS — синтаксис одинаковый.
Генерация пары ключей
Ключи создаются на вашем локальном компьютере, а не на сервере. Современный стандарт — алгоритм Ed25519. Это схема цифровой подписи на эллиптических кривых, которая работает быстрее и безопаснее старых RSA-ключей сопоставимой длины.
ssh-keygen -t ed25519 -C "мой-ноутбук"
После запуска система задаст три вопроса.
Первый вопрос: Enter file in which to save the key. Это путь, где будет сохранён приватный ключ. По умолчанию используется ~/.ssh/id_ed25519 (на Windows — C:\Users\имя\.ssh\id_ed25519). Если файл уже существует, появится вопрос Overwrite (y/n)?.
Если вы ответите y, старый ключ будет перезаписан, и если он был добавлен на другие серверы, доступ по нему пропадёт. Если у вас уже есть рабочий ключ, ответьте n и укажите другое имя файла.
Второй вопрос: Enter passphrase. Это кодовая фраза, которая шифрует приватный ключ на вашем компьютере. Если вы её установите, при каждом подключении система будет спрашивать эту фразу — либо до тех пор, пока вы не добавите ключ в ssh-agent. Если passphrase не установить (просто нажать Enter), ключ будет лежать на диске в открытом виде. Компромисс здесь между безопасностью и удобством: если злоумышленник скопирует файл ключа без passphrase, он сможет сразу им воспользоваться. С passphrase ему понадобится ещё и кодовая фраза.
Третий вопрос — повтор passphrase. Это просто подтверждение, что вы не опечатались.
Флаг -C задаёт комментарий — произвольную текстовую метку, которая добавляется в конец публичного ключа. На вход она не влияет: это не логин и не адрес, а просто подпись для человека. Когда в authorized_keys накопится несколько ключей от разных машин, по такой метке легко понять, какой ключ от какого устройства. Пишите то, что узнаете сами: имя ноутбука, «ключ от рабочего ПК», свой email. Если метка не нужна, флаг можно опустить — ключ будет работать одинаково.
Команда создаст два файла в каталоге ~/.ssh (на Windows это C:\Users\имя\.ssh\): приватный ключ id_ed25519 и публичный id_ed25519.pub. Приватный ключ никогда не должен покидать вашу машину.
Перенос публичного ключа на сервер
Поскольку SSH-доступ по сети у вас ещё не настроен, утилита ssh-copy-id не сработает — она сама требует рабочего SSH. Публичный ключ придётся перенести вручную через консоль гипервизора.
Откройте файл .pub в любом текстовом редакторе на своём компьютере и скопируйте его содержимое — это одна длинная строка, начинающаяся с ssh-ed25519. Затем в консоли сервера выполните:
mkdir -p ~/.ssh chmod 700 ~/.ssh nano ~/.ssh/authorized_keys
Вставьте скопированную строку в файл, сохраните (Ctrl+O, Enter, Ctrl+X) и закройте права:
chmod 600 ~/.ssh/authorized_keys
Почему права так важны? Демон SSH параноидален по соображениям безопасности. Если файл authorized_keys или каталог .ssh доступны на запись другим пользователям, sshd проигнорирует ключ. Это защита от сценария, когда злоумышленник с доступом на запись может подменить список разрешённых ключей.
Проверка входа и правило двух терминалов
Теперь откройте новое окно PowerShell или терминала на своём компьютере и попробуйте зайти:
ssh имя_пользователя@IP_адрес
Если система не спрашивает пароль, а сразу пускает — ключ работает. Не закрывайте это окно и не выходите из сессии в консоли гипервизора. Это правило двух терминалов: пока вы настраиваете доступ, у вас всегда должен быть открыт запасной вход. Если после изменения конфига SSH перестанет пускать, вы вернётесь в консоль и откатите изменения, не потеряв сервер.
Отключение паролей в конфиге демона
Только после успешного входа по ключу во втором окне можно менять конфиг демона:
nano /etc/ssh/sshd_config
Найдите и измените параметры:
PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes
Запрет прямого входа для root (PermitRootLogin no) означает, что даже при утечке ключа злоумышленнику потребуется знать пароль от sudo вашего обычного пользователя, чтобы получить полный контроль. Отключение PasswordAuthentication закрывает дверь для подбора паролей.
Перед перезапуском службы обязательно проверьте синтаксис конфига:
sshd -t
Если команда ничего не выводит — ошибок нет. Если выводит — не перезапускайте демон, иначе вы потеряете доступ. Флаг -t заставляет демон прочитать конфиг и выйти без применения изменений. Если хотите увидеть, какие настройки реально применятся с учётом всех Include-файлов, используйте sshd -T (заглавная буква) — он выведет дамп эффективной конфигурации.
Применяем изменения:
systemctl restart ssh
Перейдите во второе окно терминала и выполните любую команду. Если сессия отвечает — настройка завершена. Вы отключили пароли, но ключ уже в замке.
Файрвол: iptables, nftables, ufw и поиск застрявшего пакета
Межсетевой экран фильтрует пакеты на уровне ядра Linux. Подсистема ядра, которая этим занимается, называется Netfilter. А iptables, nftables и ufw — это инструменты управления ею.
UFW (Uncomplicated Firewall) создан для быстрого закрытия портов без запоминания синтаксиса (ufw allow OpenSSH, ufw enable). Он хорош для базовой защиты. Но если вам нужно управлять порядком правил, вставлять их в определённую позицию или диагностировать, почему конкретный пакет не проходит, придётся спуститься на уровень ниже — к iptables или nftables.
В Netfilter правила обрабатываются последовательно до первого совпадения (first match wins). Если пакет соответствует правилу, применяется действие, и дальнейшие правила не проверяются. Порядок критичен.
В легаси-интерфейсе iptables добавление правила в конец цепочки INPUT делается флагом -A (append):
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Если выше в цепочке уже стоит правило DROP, которое блокирует весь трафик, ваше разрешающее правило в конце не сработает. Пакет умрёт раньше. Представим типичный случай потери доступа: администратор добавляет разрешения в конец, не глядя на существующий запрет сверху. Для вставки правила в начало цепочки или на конкретную позицию используйте флаг -I (insert):
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
Это вставит правило на позицию 1. Чтобы посмотреть правила со счётчиками и номерами строк:
iptables -L INPUT -v -n --line-numbers
Флаг -v показывает, сколько пакетов и байтов прошло через каждое правило. Если счётчик на правиле DROP растёт при попытке подключения — пакет блокируется именно там. Удаление правила по номеру строки:
iptables -D INPUT 1
Современный интерфейс nftables работает иначе. Каждое правило имеет уникальный идентификатор — handle. Это избавляет от необходимости пересчитывать номера строк при изменении списка.
Просмотр всего набора правил с хендлами:
nft -a list ruleset
Вывод покажет структуру таблиц и цепочек:
table inet filter { chain input { type filter hook input priority 0; policy drop; tcp dport 22 accept # handle 5 ip saddr 192.168.1.0/24 accept # handle 7 } }
Вставка правила перед правилом с handle 5:
nft insert rule inet filter input position 5 tcp dport 22 accept
Удаление правила по handle:
nft delete rule inet filter input handle 5
Отдельной команды «поменять местами» (swap) ни в iptables, ни в nftables не существует. Перестановка правил — это всегда двухшаговая операция: удалить одно и вставить другое на нужную позицию.
Как найти, что именно не работает, если счётчики не дают полной картины? Используйте трассировку пакетов. В современных дистрибутивах, где iptables является обёрткой iptables-nft, можно включить трассировку через утилиту xtables-monitor:
xtables-monitor --trace
Для нативного nftables:
nft monitor trace
Ядро начнёт слать в userspace netlink-события, показывая точный путь пакета по каждой цепочке и правилу в реальном времени. Вы увидите, где именно пакет был принят или отброшен. Это мощнее счётчиков, потому что показывает маршрут конкретного пакета, а не накопленную статистику.
При отладке также помните о разнице между DROP и REJECT. DROP заставляет ядро просто выбросить пакет — клиент будет висеть до таймаута TCP-соединения. REJECT отправляет обратно ICMP-сообщение об ошибке или TCP RST-пакет, и клиент мгновенно получает отказ. Временная замена DROP на REJECT экономит часы ожидания при поиске недоступного сервиса.
Все правила, которые вы только что ввели в iptables или nftables, живут исключительно в оперативной памяти ядра. После первой же перезагрузки сервера вы получите абсолютно чистый сетевой стек и потеряете всю защиту. Для iptables нужно установить пакет iptables-persistent (в некоторых дистрибутивах netfilter-persistent). Во время установки он спросит, сохранить ли текущие правила, и запишет их в /etc/iptables/rules.v4. В дальнейшем сохранение делается командой netfilter-persistent save. Для nftables подход декларативный: вы выгружаете текущий рабочий набор правил в конфигурационный файл и включаете сервис.
nft list ruleset > /etc/nftables.conf systemctl enable --now nftables
Отладка SSH-подключения: на каком из пяти уровней обрывается связь
Когда настройки применены, но войти не получается, нужна карта каскадных отказов. SSH-соединение проходит несколько этапов, и на каждом из них может произойти сбой с разными симптомами.
Первый уровень — сеть и порт. Доходит ли вообще трафик до сервера? Проверьте порт утилитой nc (netcat):
nc -zv server_ip 22
Если получаете Connection refused — порт закрыт. Либо демон SSH не запущен, либо файрвол отвечает отказом (REJECT). Если команда висит и выдаёт таймаут — пакет молча отбрасывается (DROP) файрволом.
Второй уровень — ключ хоста (Host Key). Если соединение устанавливается, но вы видите WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!, это значит, что ключ сервера не совпадает с записью в вашем локальном файле ~/.ssh/known_hosts. Такое бывает, если сервер переустановили. Решение — удалить старую запись:
ssh-keygen -R server_ip
Третий уровень — аутентификация. Ошибка Permission denied (publickey) означает, что сервер не принял ваш ключ. Для диагностики используйте режим подробного вывода:
ssh -vvv user@server_ip
Ищите в логе строки Offering public key и Authentications that can continue. Если сервер не принимает ключ, проверьте права на сервере: 700 на каталог ~/.ssh, 600 на файл authorized_keys. Демон SSH также проверяет, что домашний каталог пользователя не доступен на запись другим пользователям. Если права на /home/user стоят 777, sshd может отказать во входе из соображений безопасности.
Казалось бы, если ключ верный и порт открыт, что ещё нужно? Но SSH проверяет не только криптографию, но и контекст.
Четвёртый уровень — оболочка и окружение. Иногда вход проходит, но сессия сразу закрывается. Это может быть проблема с оболочкой, указанной в /etc/passwd, или ошибка в файлах инициализации .bashrc. Попробуйте запросить выполнение одиночной команды:
ssh user@server_ip 'echo ok'
Если команда выполняется, но интерактивная сессия не открывается — проблема в настройках профиля пользователя.
Пятый уровень — ограничения на стороне PAM или TCP Wrappers. В некоторых дистрибутивах доступ может блокироваться файлами /etc/hosts.allow и /etc/hosts.deny или политиками PAM (Pluggable Authentication Modules), которые ограничивают вход по времени, IP-адресу или группе пользователей, даже если сам SSH-демон настроен верно.
Пять уровней — пять разных инструментов диагностики, и каждый шаг сужает круг поиска.
Мы привыкли воспринимать настройку сервера как возведение крепости: сначала ставим стены файрвола, потом меняем замки SSH, а консоль гипервизора держим в уме как аварийный люк на случай осады. Но в реальности сетевой стек Linux — это не архитектура, а бюрократия. Ядро не «защищает» систему, оно просто педантично сверяет каждый байт с реестром разрешений, который вы ему выдали. И как только вы начинаете видеть в правилах nftables и конфигах sshd не физические барьеры, а пункты должностной инструкции для подсистемы Netfilter, страх случайно заблокировать самому себе доступ исчезает. Вы больше не воюете с машиной, вы просто учите её оформлять пропуска.
Есть одна деталь, которую мы прошли по касательной, хотя она стоит в самом начале любого SSH-подключения. Когда клиент впервые видит ключ сервера, он показывает отпечаток — строку вида SHA256:BogAZskI77YIkz+9UGqSLHO0vT/XPsWfslzkBcq75hU — и спрашивает, доверяете ли вы этому хосту. Вы вводите yes. Этот отпечаток несёт 256 бит энтропии, но решение о доверии принимаете вы одним битом: да или нет, без сверки с каким-либо внешним источником. Модель называется TOFU — Trust On First Use, «доверяй при первом использовании».
Вся последующая защита соединения — от подмены хоста, от перехвата сессии, от повторного подключения к другой машине с тем же IP — держится на одном мгновении, когда вы решили, что цифры на экране выглядят правдоподобно. Ни один из пяти уровней диагностики, разобранных выше, не закрывает компрометацию в эту секунду. И это не дефект протокола. Альтернатива — централизованный реестр доверенных ключей, как в TLS с цепочкой сертификатов, — требует инфраструктуры удостоверяющего центра, которой у одиночного сервера нет. SSH выбрал простоту входа ценой одной точки доверия, которую вы создали, набрав yes в терминале.






























