SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-13

sudo-rs в Ubuntu 26.04: что меняется в файлах sudoers

В Ubuntu 26.04 по умолчанию используется sudo-rs вместо C-версии sudo. Узнайте, почему перестают работать правила с wildcard и как правильно переписать конфигурацию sudoers.

Изменения sudo-rs в Ubuntu

В Ubuntu 26.04 LTS по умолчанию используется sudo-rs вместо оригинального sudo, поэтому команда sudo на свежеустановленном сервере запускает реализацию на языке Rust, а не исходную программу на C. Большинство файлов sudoers продолжают работать без изменений. Исключение составляют правила, содержащие подстановочные знаки (wildcards) в аргументах команд, так как sudo-rs не выполняет сопоставление glob-шаблонов с текстом аргументов.

Первой этот переход совершила Ubuntu 25.10, а в Ubuntu 26.04 LTS он был сохранён. Ubuntu 24.04 LTS это изменение не затрагивает, так как в ней по-прежнему используется оригинальный sudo, если вы не установите sudo-rs вручную. Этот вопрос становится актуальным в момент обновления с Ubuntu 24.04 до 26.04 или при развертывании нового сервера на более новой версии дистрибутива. Если вы также используете промежуточные выпуски, в статье чем отличаются LTS и промежуточные выпуски Ubuntu на сервере объясняется, на каких машинах подобные изменения появляются в первую очередь.

Проверка используемой версии sudo на сервере

Не пытайтесь определить версию по номеру релиза. Запросите информацию у самой системы.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Доверяйте sudo --version на своей машине больше, чем любым таблицам версий в интернете, включая эту страницу. update-alternatives --config sudo — это вторая часть ответа: команда выводит список всех установленных провайдеров /usr/bin/sudo и отмечает выбранный. Наличие установленного пакета не означает, что он выбран в качестве основного, поэтому проверяйте именно выбор, а не список пакетов.

Обе реализации упакованы в дистрибутив на время переходного периода. Версия на Rust — это sudo-rs, в 26.04 по состоянию на август 2026 года она имеет версию 0.2.13. Оригинальная версия, поддерживаемая Todd C. Miller, упакована как sudo.ws, а её программы имеют суффикс .ws: sudo.ws и visudo.ws.

Почему Ubuntu перешла на sudo-rs

sudo работает с установленным битом setuid root. Любой пользователь системы может запустить его, и программа получит полные привилегии, поэтому любая ошибка работы с памятью в ней становится вектором для локального повышения привилегий до root. CVE-2021-3156 была именно такой уязвимостью: переполнение буфера в куче, доступное любому локальному пользователю, которое присутствовало в выпущенном коде около десяти лет. Rust предотвращает этот класс ошибок на этапе компиляции, что и является основным аргументом в пользу переписывания программы.

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

Безопасность работы с памятью устраняет один класс ошибок. Это не делает программу полностью защищенной от багов, и sudo-rs уже получал исправления безопасности с момента перехода на него в качестве стандартного решения. Обновляйте его так же, как и любое другое ПО.

Какие правила sudoers продолжают работать

Файл остается тем же самым. sudo-rs считывает /etc/sudoers и дополнительные файлы в /etc/sudoers.d/, при этом поддерживаются стандартные конструкции, которые использует администратор сервера:

  • deploy ALL=(ALL:ALL) ALL, а также групповые формы, такие как %sudo ALL=(ALL:ALL) ALL
  • теги NOPASSWD: и PASSWD:
  • User_Alias, Runas_Alias, Host_Alias и Cmnd_Alias
  • команда с точным списком аргументов, например /usr/bin/systemctl restart app-api
  • команда, за которой следует "", что разрешает выполнение команды только без каких-либо аргументов
  • команда, за которой следует * в качестве последнего аргумента, что разрешает любые последующие аргументы
  • путь к директории, заканчивающийся на /, что разрешает любую команду в этой директории
  • ! для исключения команды из списка
  • полезное подмножество Defaults, включая secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw и use_pty

Две настройки по умолчанию ведут себя иначе, что часто сбивает пользователей с толку. env_reset невозможно отключить в sudo-rs: эта функция всегда включена. use_pty включена по умолчанию, поэтому команда выполняется в собственном псевдотерминале.

Почему ваше правило sudoers с подстановочными знаками перестало работать

Подстановочные знаки по-прежнему разрешены в одном месте: в имени файла команды. Правило %ops ALL = /sbin/fsck* по-прежнему разрешает sudo fsck и sudo fsck_exfat, поскольку * является частью пути, который сопоставляется с файловой системой.

В списке аргументов sudo-rs принимает только две специальные формы, и ни одна из них не является шаблоном. "" означает отсутствие аргументов. Завершающий * означает любые последующие аргументы. Любой другой аргумент сравнивается как буквальный текст. Поэтому %ops ALL = /sbin/service ntp * работает корректно, так как ntp является буквальным текстом, а * стоит в конце. Однако правило, подобное этому, не предоставляет того, на что вы рассчитывали:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* — это шаблон внутри аргумента. sudo-rs не раскрывает его, поэтому правило не распространяется на systemctl restart app-api, и sudo отклоняет выполнение команды. Две команды позволяют узнать правду о любом правиле на вашем сервере: sudo -l -U deploy, запущенная от имени root, выводит список того, что эта учетная запись может выполнять на самом деле, а sudo visudo -c сообщает, корректно ли синтаксически разбирается файл. Запускайте их до того, как начнете вносить случайные изменения.

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

В оригинальном sudo аргументы, которые вы вводите, объединяются в одну строку и сопоставляются со строкой аргументов правила с помощью glob-шаблона. Glob-шаблон соответствует пробельным символам. Это именно тот момент, который почти все упускают из виду.

Документация sudo-rs дает наиболее наглядное объяснение. Правило /bin/rm *.txt также разрешает sudo rm -rf /home .txt, потому что один * поглощает -rf /home , и объединенная строка все равно заканчивается на .txt. Правило читается как «только текстовые файлы». На деле оно означает «любые аргументы, если строка заканчивается на .txt».

То же самое относится к примеру с systemctl. Поскольку аргументы сравниваются как одна объединенная строка, завершающий шаблон также соответствует всему, что вы добавите после него, поэтому restart app-* охватывает restart app-api плюс любые дополнительные аргументы, которые добавит вызывающий. Шаблон внутри аргумента раскрывает аргументы вокруг него, а именно в аргументах и заключается сила команды. sudo-rs отвергает такую конструкцию, вместо того чтобы пытаться сделать ее безопасной, поскольку безопасной общей формы для нее не существует.

Замените подстановочный знак явным списком команд

Большинство правил с подстановочными знаками существуют только потому, что кто-то не захотел вводить четыре строки. Введите эти четыре строки.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Укажите верный путь. Правило, ссылающееся на /bin/systemctl в системе, где исполняемый файл находится в /usr/bin/systemctl, никогда не сработает, а ошибка будет выглядеть так же, как проблема с правами доступа. Проверьте путь с помощью command -v systemctl и вставьте результат выполнения команды.

Разместите правило в отдельном файле конфигурации, а не в /etc/sudoers, чтобы обновление пакета не привело к конфликту с вашими изменениями:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Назовите файл без точки и без тильды в конце. Стандартный sudo игнорирует файлы в sudoers.d, если в их именах есть точка, поэтому 90-deploy.conf — это классический пример нерабочего правила, которое не выдает ошибок, а соблюдение соглашения не требует усилий.

Используйте обертку, принадлежащую root, если список становится слишком длинным

Если список разрешенных команд слишком велик, вынесите логику принятия решений из sudoers в небольшую программу, владельцем которой является root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

В файле sudoers при этом указывается только одна команда:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

Использование * в конце здесь допустимо, так как решение о том, что разрешено, принимает скрипт, а не sudo. Это верно только до тех пор, пока владельцем скрипта является root, а права на запись отсутствуют у всех остальных. Если deploy может записывать данные в файл, то deploy может заменить его содержимое и запустить что угодно от имени root, что опаснее, чем удаленное вами правило с подстановочным знаком. Проверьте права доступа с помощью ls -l. Если вывод команды вам неясен, изучение строки прав доступа drwxr-xr-x займет у вас пять минут. Это же правило распространяется на каталог: /usr/local/sbin также не должен быть доступен для записи этой учетной записи, так как возможность записи в каталог позволяет полностью заменить файл.

Предоставьте задаче собственную учетную запись вместо правила sudo

Часто правильнее задаться вопросом, почему команде вообще требуются права root. Сервис, работающий от имени собственного пользователя, может управляться этим пользователем, и необходимость в строках sudoers отпадает. Для системных юнитов systemd делегирует это решение polkit, поэтому в правиле можно указать конкретный юнит и конкретного оператора:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Сохраните это как /etc/polkit-1/rules.d/50-app-api.rules, и deploy сможет выполнять systemctl restart app-api без использования sudo. Протестируйте правило в том же контексте, в котором оно будет использоваться: правило, работающее в вашей SSH-сессии, стоит проверить через cron, прежде чем полагаться на него. В любом случае, учетная запись, выполняющая работу, должна существовать только для этой задачи; это тот же принцип, что лежит в основе учетных записей с минимальными привилегиями на VPS.

Что еще не реализовано в sudo-rs

sudo -E не реализован. Используйте Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" для именования необходимых переменных и помните, что env_reset всегда включен, поэтому все, что не сохранено, будет очищено.

Централизованное хранилище sudoers в LDAP отсутствует. sudoers.ldap и cvtsudoers не реализованы, а пакет sudo-ldap был удален в версии 26.04. Аутентификация LDAP через PAM или SSSD по-прежнему работает. За пределами области действия остается только часть, отвечающая за политику в каталоге.

INTERCEPT, который пытался предотвратить выход в оболочку (shell escape) из разрешенной команды, не реализован. Он в любом случае не защищал от целеустремленного пользователя. Если правило позволяет кому-либо запустить редактор или интерпретатор от имени root, он получает права root, и никакая опция sudo это не изменит.

Запись сеансов не реализована, поэтому отсутствуют журналы ввода-вывода и sudoreplay. Логирование осуществляется только в syslog, и нет опции logfile для перенаправления логов в другое место, поэтому сообщения sudo попадают туда, куда ваша система уже отправляет данные syslog.

Стоит ли возвращаться на sudo.ws?

Вы можете это сделать, и в цикле 26.04 оригинальный пакет остается доступным именно по этой причине.

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Копируйте точные пути из вывода --config, а не с этой страницы, так как именно этот список принимает ваша система. Возврат на sudo-rs в дальнейшем означает установку альтернативы на путь к бинарному файлу sudo-rs из того же списка.

Держите открытой вторую SSH-сессию, в которой вы уже авторизованы и которая находится в режиме ожидания, прежде чем менять что-либо, затрагивающее sudo. Ошибка парсинга файла sudoers или альтернатива, указывающая на не установленный бинарный файл, могут лишить вас возможности получить права root на удаленном сервере. Эта привычка должна стать частью всего, что вы делаете в первые десять минут на новом VPS.

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

FAQ

Почему моё правило sudoers с подстановочными знаками перестало работать в Ubuntu 26.04?

Потому что в Ubuntu 26.04 LTS в качестве стандартного sudo выбран sudo-rs, а sudo-rs не поддерживает сопоставление с шаблонами внутри аргументов команды. Он допускает подстановочный знак в имени файла команды, "" для обозначения отсутствия аргументов и одиночный * в качестве последнего аргумента. Правило вида /usr/bin/systemctl restart app-* содержит шаблон в середине аргумента, поэтому оно ничего не разрешает, и в выполнении команды будет отказано. Запустите sudo -l -U deploy от имени root, чтобы увидеть, какие права реально есть у учётной записи, а затем замените правило на точное указание команд или на скрипт-обёртку, принадлежащий root.

Как вернуться к оригинальному sudo в Ubuntu 26.04?

Оригинальный пакет называется sudo.ws. Установите его с помощью sudo apt install sudo.ws, а затем укажите на него через альтернативы командой sudo update-alternatives --set sudo /usr/bin/sudo.ws. Сначала выполните update-alternatives --config sudo, чтобы увидеть точные пути, предлагаемые вашей системой, и держите вторую SSH-сессию открытой во время внесения изменений. Это не вернёт sudo-ldap, который был удалён из 26.04 независимо от выбранной реализации.

Читает ли sudo-rs тот же файл /etc/sudoers?

Да. sudo-rs читает /etc/sudoers и дополнительные файлы в каталоге /etc/sudoers.d/, используя тот же синтаксис для пользователей, групп, псевдонимов, спецификаций выполнения от имени другого пользователя и тега NOPASSWD. Он реализует подмножество языка sudoers, поэтому различия проявляются в виде отсутствующих конструкций, а не в виде конструкций, работающих иначе. Редактируйте файл с помощью sudo visudo, а затем проверяйте его через sudo visudo -c перед тем, как закрыть сессию.

Что заменяет sudo -E в sudo-rs?

sudo -E не реализован, и его использование не рекомендовалось даже в оригинальном sudo, так как передача root-процессу окружения, контролируемого вызывающим пользователем, — это известный способ изменить поведение процесса. Вместо этого укажите нужные переменные в sudoers строкой вида Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". Опция env_reset в sudo-rs всегда включена и не может быть отключена, поэтому все переменные, которые вы не сохранили, будут очищены.

#sudo#sudo-rs#ubuntu#sudoers#permissions