Передача сервера подрядчику: чек-лист по доступам и рискам
Рано или поздно на сервер нужно пустить кого-то со стороны — фрилансера для доработки, подрядчика для миграции, стороннюю команду для аудита. Соблазн проще всего сказать «вот пароль от root» велик, но именно так теряют серверы: забытый доступ, лишний cron-скрипт, случайно оставленный публичный порт. Ниже — не юридический, а чисто технический чек-лист: как выдать ровно столько доступа, сколько нужно для задачи, и как аккуратно его забрать, когда работа закончена.
Содержание
- Почему нельзя просто отдать root и общий пароль
- Шаг 1. Отдельный пользователь и sudo только на нужные команды
- Шаг 2. SSH-ключ подрядчика вместо пароля
- Шаг 3. Доступ только к тем ресурсам, которые нужны для задачи
- Шаг 4. Логирование действий подрядчика отдельно от остальных
- Шаг 5. Точный срок доступа и немедленный отзыв по факту завершения
- Шаг 6. Аудит изменений и bastion-хост для критичных систем
Почему нельзя просто отдать root и общий пароль
Общий административный доступ — это доступ без авторства. Если на сервере что-то сломалось после работы подрядчика, а логи пишутся от имени root или от вашей учётки, вы физически не сможете отличить его действия от своих собственных или от действий второго подрядчика, если он тоже был. То же самое с паролем: скопировать его можно куда угодно, отозвать — только сменой пароля для всех, кто им пользовался, включая вас.
Второй риск — масштаб доступа не соответствует масштабу задачи. Подрядчику нужно поправить конфиг nginx для одного сайта, а он получает доступ ко всем базам данных на сервере, ко всем остальным проектам, к сетевым настройкам. Если у подрядчика скомпрометирован ноутбук или он просто ошибся командой, ущерб ограничен не задачей, а всем, до чего в принципе можно дотянуться с root.
Дальше — семь конкретных шагов, которые снимают оба риска, без лишней теории.
Шаг 1. Отдельный пользователь и sudo только на нужные команды
Первое правило: у подрядчика всегда свой linux-пользователь, никогда не общий root и не ваша личная учётка.
useradd -m -s /bin/bash -c "Подрядчик: Иванов, проект X, до 20.09.2026" contractor_ivanov
passwd -l contractor_ivanov
passwd -l блокирует вход по паролю — заходить будем только по ключу (шаг 2). Комментарий в -c — не формальность, через полгода по getent passwd вы должны сразу понять, кто это и зачем.
Если подрядчику всё-таки нужны привилегированные операции (перезапустить сервис, посмотреть системные логи), не выдавайте ALL=(ALL) NOPASSWD: ALL — это ничем не отличается от root. Ограничьте sudoers конкретными командами:
visudo -f /etc/sudoers.d/contractor_ivanov
Содержимое файла:
contractor_ivanov ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp
contractor_ivanov ALL=(root) NOPASSWD: /usr/bin/systemctl status myapp
contractor_ivanov ALL=(root) NOPASSWD: /usr/bin/journalctl -u myapp --no-pager
Обратите внимание — путь к бинарнику указан явно, без wildcard в духе /usr/bin/systemctl *: с wildcard подрядчик может дописать в конец команды что угодно через специфику обработки аргументов и получить произвольное выполнение. visudo не даст сохранить файл с синтаксической ошибкой — это встроенная защита от того, что вы случайно заблокируете себе sudo на всём сервере.
Если задача вообще не требует прав root — например, только работа с файлами конкретного проекта — sudoers-файл просто не нужен, и это лучший вариант.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSШаг 2. SSH-ключ подрядчика вместо пароля
Пароли утекают, пересылаются в мессенджерах, остаются в истории браузера. Ключ подрядчик генерирует сам на своей машине, вам передаётся только публичная часть:
mkdir -p /home/contractor_ivanov/.ssh
chmod 700 /home/contractor_ivanov/.ssh
Вставляете присланный публичный ключ (строка вида ssh-ed25519 AAAA... contractor@laptop) в файл:
echo "ssh-ed25519 AAAA...присланный-ключ contractor@laptop" >> /home/contractor_ivanov/.ssh/authorized_keys
chmod 600 /home/contractor_ivanov/.ssh/authorized_keys
chown -R contractor_ivanov:contractor_ivanov /home/contractor_ivanov/.ssh
Приватная часть ключа никогда не покидает машину подрядчика — вы её просто не видите и не должны видеть. Если у сервера в /etc/ssh/sshd_config ещё разрешён PasswordAuthentication yes — самое время это проверить и по возможности выключить глобально, отдельная статья о том, как это сделать без риска потерять доступ самому, — SSH-ключи вместо пароля на VPS.
Для более тонкого разделения полезен блок Match User в sshd_config — он позволяет для конкретного пользователя запретить проброс портов и X11, даже если для остальных они разрешены:
Match User contractor_ivanov
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
После правки — sshd -t для проверки синтаксиса и только потом systemctl reload sshd, чтобы не оборвать себе же текущую сессию некорректным конфигом.
Шаг 3. Доступ только к тем ресурсам, которые нужны для задачи
Отдельный пользователь без ограничения прав на файлы — половина дела. Если проект лежит в /var/www/project-x, у подрядчика не должно быть возможности читать /var/www/project-y или домашние директории других пользователей.
Базовый вариант — владение и группа:
groupadd project-x
usermod -aG project-x contractor_ivanov
chgrp -R project-x /var/www/project-x
chmod -R 2770 /var/www/project-x
Бит 2 в правах (setgid) следит, чтобы новые файлы, которые создаст подрядчик, автоматически наследовали группу project-x, а не его личную группу — иначе через неделю в проекте появятся файлы, которые никто из команды прочитать не сможет.
Если нужна более точная настройка без переписывания владельца всего дерева каталогов — ACL:
setfacl -R -m u:contractor_ivanov:rwx /var/www/project-x
setfacl -R -d -m u:contractor_ivanov:rwx /var/www/project-x
Второй setfacl с флагом -d задаёт права по умолчанию для новых файлов и подкаталогов.
С базой данных — тот же принцип: не общий root-доступ к MySQL/PostgreSQL, а отдельный пользователь БД с правами ровно на нужную схему:
-- MySQL/MariaDB
CREATE USER 'contractor_ivanov'@'%' IDENTIFIED BY 'сгенерированный-пароль';
GRANT SELECT, INSERT, UPDATE ON project_x.* TO 'contractor_ivanov'@'%';
FLUSH PRIVILEGES;
-- PostgreSQL
CREATE ROLE contractor_ivanov LOGIN PASSWORD 'сгенерированный-пароль';
GRANT CONNECT ON DATABASE project_x TO contractor_ivanov;
GRANT USAGE ON SCHEMA app TO contractor_ivanov;
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA app TO contractor_ivanov;
Если задача не требует DELETE или DROP — их просто не выдают. Это дешевле, чем потом разбираться, кто и зачем удалил таблицу.
Шаг 4. Логирование действий подрядчика отдельно от остальных
Отдельный пользователь даёт готовую точку для аудита — все действия можно фильтровать по UID, не выискивая их среди общих логов. Если на сервере установлен auditd, правило по конкретному пользователю выглядит так:
id contractor_ivanov
# допустим, uid=1010
auditctl -a always,exit -F arch=b64 -S execve -F auid=1010 -k contractor_ivanov
Дальше действия ищутся отдельно от всего остального:
ausearch -k contractor_ivanov
Как разворачивать auditd с нуля и какие типовые правила задавать, разобрано в отдельной статье — настройка auditd на сервере. Если auditd разворачивать ради одного временного доступа избыточно, минимальный вариант — включить логирование ввода-вывода sudo для конкретного пользователя:
Defaults:contractor_ivanov log_input, log_output
Defaults:contractor_ivanov iolog_dir="/var/log/sudo-io/%{user}"
Записи sudo I/O логов можно потом просмотреть командой sudoreplay — по сути, это запись сессии терминала, что именно вводилось и что выводилось в ответ.
Шаг 5. Точный срок доступа и немедленный отзыв по факту завершения
До начала работ стоит договориться не «на пару дней», а о конкретной дате — и сразу выставить её на уровне системы, а не полагаться на то, что кто-то не забудет отозвать доступ вручную:
chage -E $(date -d "+14 days" +%Y-%m-%d) contractor_ivanov
Это автоматически блокирует учётку в указанную дату независимо от того, вспомнили вы о ней или нет. Полезная страховка, но не замена ручному отзыву — как только работы фактически завершены, доступ снимается сразу, не «на всякий случай, вдруг ещё понадобится»:
userdel -r contractor_ivanov
sed -i '/contractor_ivanov/d' /etc/sudoers.d/*
rm -f /etc/sudoers.d/contractor_ivanov
Отдельно проверьте и почистите следы за пределами самой учётки:
crontab -u contractor_ivanov -l
pkill -u contractor_ivanov
Если для доступа к БД заводился отдельный пользователь — не забудьте DROP USER 'contractor_ivanov'@'%';, иначе созданная в шаге 3 учётка БД останется рабочей даже после удаления системного пользователя linux — это разные, никак не связанные между собой сущности.
Шаг 6. Аудит изменений и bastion-хост для критичных систем
Перед тем как закрыть задачу, полезно понять, что именно подрядчик сделал на сервере — не из недоверия, а потому что через месяц эту информацию будет узнать заметно сложнее. Быстрая сверка:
dpkg -l > /root/packages-after.txt
diff /root/packages-before.txt /root/packages-after.txt
Если снимок пакетов «до» не снимали — сравните хотя бы список работающих сервисов и открытых портов на «сейчас» с тем, что должно быть по документации проекта:
systemctl list-units --state=running
ss -tlnp
Удобно держать /etc под git — тогда после ухода подрядчика git diff в этом каталоге сразу покажет, какие конфиги менялись:
cd /etc && git status && git diff
Отдельно стоит проверить authorized_keys во всех домашних директориях — не появился ли там ещё один ключ, который вы не выдавали:
grep -H "ssh-" /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys 2>/dev/null
Если сервер критичный — платёжный шлюз, база с персональными данными, продакшн с большой нагрузкой — прямой доступ подрядчику лучше не давать вообще. Правильнее поставить bastion-хост: отдельную маленькую машину, которая ничего не хостит, а только принимает SSH и логирует каждое подключение, а дальше пробрасывает сессию во внутреннюю сеть:
# ~/.ssh/config у подрядчика
Host project-bastion
HostName bastion.example.com
User contractor_ivanov
Host project-internal
HostName 10.0.0.15
User contractor_ivanov
ProxyJump project-bastion
На самом продакшн-сервере при этом файрвол пропускает SSH только с IP-адреса bastion, а не откуда угодно. Такой bastion не обязательно ставить на тот же сервер, где идут работы — это ровно тот случай, когда имеет смысл поднять отдельную небольшую VPS специально под эту роль, благо стоит она немного. О том, как в принципе выдавать доступ команде без общего root, а не только разовому подрядчику, есть отдельный разбор — как раздать доступ команде без выдачи root.
Параллельно с техническими мерами разумно закрыть и юридическую сторону — договориться с подрядчиком об NDA, отдельно оговорить, что именно он видит и с кем может это обсуждать. Но это тема отдельного разговора с юристом, а не то, что решается на уровне конфигов сервера — здесь же речь именно о технической стороне ограничения доступа.
Если после завершения работ вы вообще пересматриваете, как в компании устроена ротация паролей и ключей после каждого внешнего подрядчика — стоит один раз выстроить процесс, а не повторять его вручную каждый раз, об этом — ротация секретов и ключей на практике.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Подрядчик просит прислать ему пароль от root, потому что «так быстрее». Что делать?
Отказать и предложить прислать публичный SSH-ключ вместо этого — создание отдельного пользователя с ограниченным sudo занимает пять минут и не требует объяснять подрядчику, что и почему вы делаете иначе.
У меня несколько подрядчиков работают одновременно над разными частями сервера. Нужен ли им общий пользователь?
Нет, у каждого — своя учётка и свой набор прав по своему проекту, даже если формально они из одной компании-подрядчика. Иначе аудит действий (шаг 4) теряет смысл: вы не поймёте, кто из двоих что сделал.
Подрядчик работает через VPN или прокси, IP всё время разный — как ограничить доступ по адресу?
Ограничение по IP в файрволе в этом случае не сработает надёжно, поэтому опирайтесь на связку SSH-ключ + отдельный пользователь + sudo на конкретные команды, а не на сетевой периметр. Если нужен предсказуемый IP — попросите подрядчика подключаться через свой статический выход или согласуйте один диапазон адресов заранее.
Что делать, если подрядчик уже получил root ещё до того, как вы прочитали этот чек-лист?
Смените пароли и ключи всех учёток, у которых был или мог быть доступ, проверьте authorized_keys, sudoers и список пользователей на предмет лишнего, затем разверните доступ заново по описанной схеме — с отдельным пользователем и ограниченными правами.
Нужно ли всё это для доступа на пару часов ради одной мелкой правки?
Да, разница в трудозатратах небольшая — создание пользователя и ключа занимает те же пять минут, что и отправка пароля, зато после снимается однозначно и без следов остаточного доступа.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →