用户权限与 sudo 提权规范实践

接手一套生产环境时,我最先看的就是账号体系:有多少人知道 root 密码、普通用户被授了什么权。账号体系乱的环境,安全事件只是时间问题。这篇整理一套可落地的用户与提权规范。

一、用户分类与 UID 规划

用户类型 UID 用途
root(管理员) 0 系统管理
普通用户 1000+ 登录操作
虚拟用户 1-999 跑服务用(mysql、nginx 等),不可登录

生产铁律:任何对外服务绝不用 root 跑,每个服务建独立虚拟用户,权限最小化。

用户管理的几个关键文件:

  • /etc/passwd:用户信息(密码位永远是 x,真正的密码在 shadow)
  • /etc/shadow:加密后的密码
  • /etc/group:组信息
  • /etc/skel/:新用户家目录的模板
1
2
3
4
5
6
7
8
# 创建普通用户
useradd ops
# 创建虚拟用户:指定 UID/GID、不建家目录、禁止登录
groupadd -g 888 app
useradd -u 888 -g 888 -M -s /sbin/nologin app

# 删除用户(-r 连文件一起删)
userdel -r ops

二、su 与 su - 的区别(高频踩坑点)

1
2
su ops       # 借用身份,但 PATH/环境变量还是原来的(non-login shell)
su - ops # 完全"变成"这个用户:环境、家目录、PATH 全换(login shell)

经典坑:用 su root(不带横杠)切过去后 echo $PATH 里没有 /usr/sbin/sbin,执行某些命令直接 command not found。原因就是 non-login shell 只读 ~/.bashrc,不读 /etc/profile 系列。

命令 切换后身份 家目录/HOME 环境 要输谁的密码
su / su root root 不变 不加载 root 的 root 密码
su - / su - root root /root 加载 root 的 root 密码
su - mysql mysql /home/mysql 加载 mysql 的 mysql 密码

三、sudo:最小权限提权

sudo 的正解是”把最小必要权限授给该用的人”,而不是把 root 密码交出去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
visudo   # 编辑 /etc/sudoers(自带语法检测,优先用它)

# 授权单个命令
ops ALL=(ALL) /usr/bin/cat

# 授权多个命令(给开发/测试)
ops ALL=(ALL) /usr/bin/cat,/usr/bin/cd

# 全权+取反(运维常用:除了 rm 都行)
ops ALL=(ALL) NOPASSWD: ALL,!/usr/bin/rm

# 使用与查看
sudo -l # 自己有哪些提权命令
sudo cat /var/log/secure # 提权执行

sudo 配置的坑有两类:

  1. 给了 NOPASSWD: ALL 等于裸奔:提权后 rm、chmod 都能干。给 ALL 时一定要配合 ! 取反关键危险命令,或者干脆按命令列表授。
  2. 授权命令写相对路径:sudoers 里命令必须是绝对路径(which cat 先查绝对路径),否则规则永远不生效。

四、安全补充:登录审计

1
2
last      # 登录详细信息(来源 IP、时间、时长)
lastlog # 每个用户最后一次登录时间

五、一次 root 直登整改记录

接手时发现多台服务器 sshd_configPermitRootLogin yes,且 root 用弱密码——意味着任何能猜到密码的人都能直接拿到最高权限。

整改三步:

  1. 关 root 远程直登:PermitRootLogin no,重启 sshd;
  2. 给运维同事建 ops 账号,按职责授 sudo 最小权限(开发只有日志查看权,运维才有管理权);
  3. 推行 sudo 日志留痕:visudo 里加上 Defaults logfile=/var/log/sudo.log

结果:root 密码从”人人皆知”变成”仅紧急情况两人知晓”,日常操作全部走 sudo + 留痕,事后审计有据可查。