在生产环境中,直接使用 root 账户执行日常操作是一种高风险行为,因为它缺乏审计和限制。sudo 机制让系统管理员可以将特定的 root 权限“借给”普通用户,同时严格限制能执行的命令,并记录所有操作日志。正确配置 sudo 的核心是用好 /etc/sudoers 文件,并始终遵循权限最小化原则。
1. 不要直接编辑 /etc/sudoers,使用 visudo
/etc/sudoers 是 sudo 的主配置文件,语法错误可能导致 sudo 完全无法工作,甚至让你无法提升权限修复问题。因此,必须使用 visudo 命令来编辑。visudo 会在保存时检查语法,如果有错误就拒绝写入,避免系统被锁死。
sudo visudo
visudo 默认使用 vi 编辑器。如果你想使用其他编辑器(如 nano),可以设置环境变量:
sudo EDITOR=nano visudo
除了主配置文件,现代发行版通常支持通过 /etc/sudoers.d/ 目录下放置独立文件的方式追加配置。使用 visudo 时,也可以在 /etc/sudoers 中用 @includedir /etc/sudoers.d 引入这些文件。这种方式便于用配置管理工具(Ansible、Puppet 等)单独分发特定用户的权限规则,而不影响主配置。
2. sudoers 规则语法
一条典型的 sudo 规则格式为:
用户 登录主机=(运行身份) 命令列表
- 用户:可以是用户名、
%组名(组前加%)、ALL(所有用户)。 - 登录主机:通常写
ALL或具体主机名,多数场景直接用ALL即可。 - 运行身份:括号中的用户,通常是
(root)或(ALL),表示以哪个用户的身份执行命令。(ALL)允许以任何用户执行。 - 命令列表:允许执行的命令绝对路径,用逗号分隔,支持通配符。
示例一:让用户 alice 在本地执行所有 root 权限的命令
alice ALL=(ALL) ALL
含义:alice 在任何主机上,可以以任何用户(包括 root)的身份执行任何命令。相当于完全的 sudo 权限。
示例二:授予组 webadmin 管理 Web 服务和查看系统状态的有限权限
%webadmin ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx, /usr/bin/less /var/log/nginx/*
这行规则严格限制了只能重启和查看 nginx 服务,以及查看 nginx 日志文件。注意命令必须是绝对路径,可通过 which systemctl 查出。
示例三:无需密码执行特定命令
operator ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp
NOPASSWD 让用户在执行该命令时不需要输入密码。常用于脚本自动化,但要谨慎使用,因为任何获得该用户权限的人都可以无密码执行此特权命令。
3. 权限最小化原则
这是安全配置的第一定律:给用户只授予他们完成工作所必需的最少权限,不多不少。 sudo 的灵活性正好可以用来落实这一点。
具体做法:
- 按需分配,不要直接给全权:即使用户是运维人员,也避免轻易给
ALL=(ALL) ALL,而是分拆为具体命令。 - 命令路径要精确:尽可能用完整路径并指定参数。例如
/usr/bin/systemctl stop myapp,而不要写通配/usr/bin/systemctl *,因为后者允许 stop/start/restart 所有服务。 - 善用通配符但控制范围:
/usr/bin/cat /var/log/app/.log比cat安全得多。 - 分离职责:不同角色的用户通过不同的 sudo 规则获得不同权限。例如数据库管理员只能
sudo -u postgres ...,网络管理员只能重启特定网络服务,日志审计员只能阅读日志文件但不能修改。 - 定期审核:使用
sudo -l -U username命令可以列出某个用户当前获得的所有 sudo 权限,管理员应定期检查是否有冗余或膨胀的权限。
4. 验证和调试
- 查询某用户拥有的 sudo 权限:
sudo -l -U alice
- 以其他用户身份执行特定命令:
sudo -u postgres whoami # 返回 postgres
- 测试规则时开启详细日志:
sudo -v
如果配置错误,sudo 会给出提示,如“用户没有在 sudoers 文件中”或“命令不可执行”。
5. 一个真实场景的最小权限配置
假设有一个应用 myapp,由用户 deploy 管理部署和重启,但不应接触系统其他服务。在 /etc/sudoers.d/deploy 中加入:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl stop myapp, /usr/bin/systemctl start myapp, /usr/bin/systemctl restart myapp
这样 deploy 就可以在部署脚本中直接使用 sudo systemctl restart myapp,而完全无法操作数据库、修改网络配置或以 root 身份执行其他命令。权限明确、可审计,且符合最小化原则。
sudo 配置看似简单,但它是 Linux 安全的第一道闸门。通过精心设计的 sudoers 规则,你可以在不牺牲便利性的前提下,显著降低误操作和恶意提权的风险。