SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-09-08

sudo-rs в Ubuntu 26.04: что меняется в sudoers

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

Что меняет sudo-rs в Ubuntu

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

Ubuntu 25.10 первой перешла на этот вариант, а 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, поэтому обе версии могут быть установлены одновременно: /usr/bin/sudo.ws и /usr/bin/visudo.ws, наряду с cvtsudoers.ws и sudoreplay.ws. Проверено по архиву 26.04 в сентябре 2026 года: dpkg -L sudo перечисляет бинарные файлы с суффиксами, а sudo-rs поставляет /usr/bin/sudo-rs рядом с ними.

Почему 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) из правила. Шаблон сопоставляется с пробельными символами. Это тот нюанс, который почти все упускают.

Документация 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
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, а затем укажите на него через систему альтернатив с помощью 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