Ubuntu 系统系列 | 第 5 天(重访·第二季):用户与权限管理——从 ACL 到 PAM,企业级权限体系深度解析

第 5/30 天(重访·第二季)

前言

在系列首轮中,我们系统学习了 useraddusermodsudochownchmod 等基础命令。然而,在真实的生产环境中,单靠传统的 Unix 权限模型(ugo+rwx)往往不足以应对复杂的权限需求。文件访问控制列表(ACL)、Linux 安全能力(Capabilities)、可插拔认证模块(PAM)、用户命名空间(User Namespaces) 等高级机制才是企业级权限管理的核心。

本文将从这些进阶主题出发,帮你构建一套完整的、生产可用的 Ubuntu 权限体系。


一、传统权限模型的局限

传统的 rwx 权限模型将用户分为三类:所有者(u)、同组用户(g)、其他用户(o)。乍看之下够用,但实际场景中常遇到以下问题:

场景 传统模型的问题 解决方案
共享目录(如 /data/project)需要给多个不同组的用户不同权限 只能设置一个组,无法细分 ACL
普通用户需执行 ping(需要 CAP_NET_RAW 只能给 SUID,不安全 Capabilities
Web 服务器只需绑定特权端口(<1024) 需要整进程 root,风险高 Capabilities
限制 SSH 登录的用户只能执行特定命令 无原生支持 PAM + SSH 配置文件
容器内需要以非 root 运行但有 root 能力 无法实现 User Namespaces

二、ACL——细粒度权限控制

ACL(Access Control List)允许你为任意用户或用户组设置独立的权限,突破了传统三组分类的限制。

2.1 启用 ACL

Ubuntu 默认在 ext4 文件系统上开启了 ACL 支持。确认方式:

# 检查挂载选项是否包含 acl
tune2fs -l /dev/sda1 | grep "Default mount options" | grep acl
# 或查看当前挂载
mount | grep "acl"

2.2 核心命令

# 查看文件的 ACL
getfacl /etc/passwd

# 为用户 alice 设置 rwx 权限
setfacl -m u:alice:rwx /data/project

# 为组 devops 设置 rx 权限
setfacl -m g:devops:rx /data/project

# 移除特定用户的 ACL
setfacl -x u:alice /data/project

# 递归设置目录 ACL(影响所有子文件)
setfacl -R -m u:alice:rx /data/project

# 设置默认 ACL(新建文件自动继承)
setfacl -d -m u:alice:rx /data/project

2.3 实战:共享开发目录

假设你有一个团队协作目录 /srv/git/repos,需要给不同角色不同权限:

# 创建组
sudo groupadd developers
sudo groupadd reviewers

# 添加用户到组
sudo usermod -aG developers alice
sudo usermod -aG developers bob
sudo usermod -aG reviewers charlie

# 设置目录权限
sudo mkdir -p /srv/git/repos

# 基础权限:所有者和组 root,其他人无权限
sudo chown root:developers /srv/git/repos
sudo chmod 770 /srv/git/repos

# ACL:reviewers 组只读
sudo setfacl -m g:reviewers:rx /srv/git/repos

# 默认 ACL:新文件继承
sudo setfacl -d -m g:developers:rwx /srv/git/repos
sudo setfacl -d -m g:reviewers:rx /srv/git/repos

# 验证
getfacl /srv/git/repos

输出示例:

# file: /srv/git/repos
# owner: root
# group: developers
user::rwx
group::rwx
group:reviewers:r-x
mask::rwx
other::---
default:user::rwx
default:group::rwx
default:group:reviewers:r-x
default:mask::rwx
default:other::---

2.4 ACL 掩码(Mask)

ACL 中的 mask 字段限制了所有命名用户和命名组的最大权限。即使你给了某个用户 rwx,如果 maskr-x,该用户实际只能 r-x

# 查看当前 mask
getfacl /srv/git/repos | grep mask

# mask 会自动调整:当通过 chmod 修改组权限时,mask 会同步
chmod g-w /srv/git/repos   # mask 会变成 r-x

⚠️ 陷阱: 使用 chmod 修改组权限会间接修改 ACL mask,可能导致 ACL 赋予的权限被意外降级。始终优先使用 setfacl 而非 chmod 来管理 ACL 控制的目录。


三、Linux Capabilities——细粒度特权分离

传统 Unix 中,root 拥有所有特权(约 40 种),普通用户几乎无特权。Capabilities 将 root 特权拆分为独立单元,允许非 root 进程拥有所需的最小特权。

3.1 常用 Capability 列表

Capability 作用 对应操作
CAP_NET_RAW 使用 RAW/PACKET socket ping, tcpdump
CAP_NET_BIND_SERVICE 绑定低于 1024 的端口 Nginx 用 80/443
CAP_DAC_OVERRIDE 绕过文件权限检查 类似 root 的 rwx
CAP_SYS_ADMIN 系统管理能力(大而全,慎用) mount, swapon 等
CAP_SYS_PTRACE 调试其他进程 strace, gdb
CAP_SYS_NICE 调整进程优先级 renice

3.2 查看和设置 Capabilities

# 查看进程的 capabilities
getpcaps 1234

# 查看文件的 capabilities(setcap 设置的)
getcap /usr/bin/ping
# 输出:/usr/bin/ping = cap_net_raw+ep

# 设置 capabilities
sudo setcap cap_net_bind_service=+ep /usr/local/bin/myapp

# 移除 capabilities
sudo setcap -r /usr/local/bin/myapp

# 查看全部已设置 capabilities 的文件
sudo getcap -r /usr

3.3 实战:非 root 运行 Nginx 绑定 80 端口

# 给 Nginx 二进制绑定低端口的能力
sudo setcap cap_net_bind_service=+ep /usr/sbin/nginx

# 验证
getcap /usr/sbin/nginx
# 输出:/usr/sbin/nginx = cap_net_bind_service+ep

# 现在可以以普通用户运行 Nginx 绑定 80 端口
sudo -u www-data nginx

3.4 Capabilities 的安全最佳实践

# 1. 使用 `+ep` 表示 Effective + Permitted
#    e = 有效(进程当前拥有该能力)
#    p = 允许(进程可以获取该能力)

# 2. 禁止使用 cap_sys_admin(相当于半个 root)
sudo setcap cap_sys_admin=+ep /usr/bin/myapp  # ❌ 危险!

# 3. 容器场景:最小能力原则
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

⚠️ 核心原则: Capabilities 应遵循最小特权原则(Principle of Least Privilege)。只给进程运行所需的最少 capability,宁缺毋滥。


四、PAM——可插拔认证模块

PAM(Pluggable Authentication Modules)是 Ubuntu 认证系统的核心框架,它允许你灵活配置认证策略,而无需修改应用程序本身。

4.1 PAM 配置文件结构

# 查看 PAM 配置文件
ls -la /etc/pam.d/
# 常见文件:login, sshd, sudo, passwd, su, common-*

# 查看 SSH 的 PAM 配置
cat /etc/pam.d/sshd

4.2 PAM 模块类型

类型 作用 示例
auth 身份认证 密码验证、SSH key
account 账户有效性 账户过期、登录时间限制
password 密码更新 密码强度、复杂度
session 会话管理 登录日志、环境设置

4.3 实战:密码强度策略

强制要求密码长度 ≥12 位、包含大小写+数字+特殊字符:

# 安装密码质量模块
sudo apt install libpam-pwquality

# 配置密码策略
sudo vim /etc/pam.d/common-password

common-password 中找到 pam_pwquality.so 行,修改为:

password requisite pam_pwquality.so retry=3 minlen=12 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 difok=3

参数说明:
retry=3:允许重试 3 次
minlen=12:最小长度 12
dcredit=-1:至少 1 个数字
ucredit=-1:至少 1 个大写字母
ocredit=-1:至少 1 个特殊字符
lcredit=-1:至少 1 个小写字母
difok=3:新密码与旧密码至少 3 个字符不同

4.4 实战:限制 SSH 登录时间

只允许开发人员在工作时间内 SSH 登录:

# 安装 PAM time 模块(默认已安装)
# 修改 /etc/pam.d/sshd,添加:
# account required pam_time.so

# 编辑 /etc/security/time.conf,添加规则:
# 允许 developers 组在 工作日 9:00-18:00 登录
*;*;@developers;Wd0900-1800
# 拒绝其他人在非工作时间登录
*;*;!@developers;Wd1800-0900
# 周末禁止所有人
*;*;*;Wk

4.5 实战:限制 sudo 用户只能执行特定命令

# 编辑 /etc/sudoers(使用 visudo!)
sudo visudo

# 创建专用组
sudo groupadd admins

# 允许 admins 组只执行系统管理命令
%admins ALL=(ALL) /usr/bin/systemctl, /usr/bin/journalctl, /usr/bin/apt

# 禁止特定命令
%admins ALL=(ALL) !/usr/bin/su, !/bin/bash

# 创建只读用户(只能查看日志)
readonly ALL=(ALL) /usr/bin/journalctl, /usr/bin/tail

⚠️ 重要: 始终使用 visudo 编辑 sudoers 文件,它会做语法检查,避免配置错误导致 sudo 完全失效。


五、用户命名空间(User Namespaces)

User Namespaces 是 Linux 容器技术的基石,它允许非 root 用户拥有 root 身份的映射,但仅限于自己的命名空间内。

5.1 映射原理

# 查看当前用户 ID 映射
cat /proc/$$/uid_map
cat /proc/$$/gid_map

# 格式:namespace_id host_id length
# 0 1000 1  →  namespace 中的 uid 0 映射到宿主机的 uid 1000

5.2 实战:非 root 用户运行特权操作

# 使用 unshare 创建新的用户命名空间
unshare -U -m

# 在命名空间内,你是 root(uid 0)
whoami    # root
id        # uid=0(root) gid=0(root)

# 但实际在宿主机上,你仍然是普通用户
# 可以挂载(仅限命名空间内)
mount -t tmpfs tmpfs /tmp/mymount

5.3 容器中的应用

# Docker 默认启用用户命名空间
# 配置 /etc/docker/daemon.json
{
  "userns-remap": "default"
}

# 重启后,容器内 root 映射到宿主机普通用户
sudo systemctl restart docker

# 验证:容器内创建的文件,宿主机上属于 mapped 用户
docker run --rm alpine touch /tmp/test
ls -la /tmp/test   # 非 root 所有

六、进阶 sudo 配置技巧

6.1 免密码 + 时间限制

# 允许 devops 组免密码执行特定命令,但仅限 5 分钟内
%devops ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/docker
Defaults:%devops timestamp_timeout=5

6.2 环境变量安全

# 默认 sudo 会重置环境变量,防止 PATH 劫持
# 查看当前 sudo 环境策略
sudo -V | grep -i "env"

# 安全配置示例
Defaults env_reset
Defaults env_keep += "HTTP_PROXY HTTPS_PROXY"
Defaults secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

6.3 日志审计

所有 sudo 命令都会记录到日志:

# 查看 sudo 日志
sudo journalctl -u sudo -n 50

# 或查看 auth.log
sudo tail -f /var/log/auth.log | grep sudo

七、企业级权限管理最佳实践

7.1 权限审计脚本

#!/bin/bash
# 审计:找出所有 SUID/SGID 文件
echo "=== SUID/SGID 文件 ==="
find / -type f ( -perm -4000 -o -perm -2000 ) -exec ls -la {} ; 2>/dev/null

# 审计:找出所有 ACL 文件
echo "=== 带 ACL 的文件 ==="
find / -type f -exec getfacl -p {} ; 2>/dev/null | grep -B1 "user:.*:rwx"

# 审计:查找空密码用户
echo "=== 空密码用户 ==="
awk -F: '($2 == "" || $2 == "!") {print $1}' /etc/shadow

# 审计:查找 UID 0 的非 root 用户
echo "=== UID 0 的非 root 用户 ==="
awk -F: '($3 == 0 && $1 != "root") {print $1}' /etc/passwd

7.2 权限管理清单

检查项 命令 频率
空密码用户 awk -F: '($2=="")' /etc/shadow 每日
UID 0 非 root awk -F: '($3==0&&$1!="root")' /etc/passwd 每日
SUID 异常 find / -perm -4000 -type f 2>/dev/null 每周
异常 sudoers cat /etc/sudoers 每周
ACL 变更 getfacl -R /srv 2>/dev/null 每周
过期用户 lastlog -b 90 每月

7.3 生产环境权限模型建议

┌─────────────────────────────────────────────────┐
│               权限分层模型                          │
├─────────────────────────────────────────────────┤
│ Level 3: 安全管理员 (Security Admin)             │
│   - 管理 PAM、sudoers、审计策略                   │
│   - 仅 2-3 人拥有                                │
├─────────────────────────────────────────────────┤
│ Level 2: 系统管理员 (System Admin)               │
│   - 管理服务、软件包、用户创建                     │
│   - 通过 sudo 限制可执行命令                      │
├─────────────────────────────────────────────────┤
│ Level 1: 运维人员 (Operator)                     │
│   - 查看日志、重启服务、监控                      │
│   - sudo 只读 + 特定命令                         │
├─────────────────────────────────────────────────┤
│ Level 0: 普通用户 (Regular User)                 │
│   - 无 sudo,受限目录权限                         │
│   - 通过 ACL 控制共享目录                         │
└─────────────────────────────────────────────────┘

总结

今天的进阶内容帮你构建了 Ubuntu 权限管理的完整知识体系:

技术 适用场景 避免场景
ACL 共享目录、多角色协作 简单场景(ugo 够用时)
Capabilities 最小特权、绑定低端口、容器 需要完整 root 特权
PAM 认证策略、密码质量、登录限制 程序级认证(应用自身处理)
User Namespaces 容器安全、非 root 运行特权 需要跨命名空间操作
sudo 进阶 命令授权、日志审计 全量 root 授权

核心原则: 永远分配最小必要权限,定期审计,并记录所有敏感操作。

系列目录

天数 主题 状态
第 1 天 Ubuntu 简介与版本选择
第 2 天 手把手安装 Ubuntu
第 3 天 Ubuntu 桌面环境初探
第 4 天 Ubuntu 终端基础
第 5 天 用户与权限管理
第 6 天 软件包管理
第 7 天 文件与文本操作
第 8 天 系统服务管理
第 9 天 磁盘与文件系统管理
第 10 天 网络配置与管理
第 11 天 进程管理与监控
第 12 天 计划任务与自动化
第 13 天 备份与恢复策略
第 14 天 系统更新与升级管理
第 15 天 SSH 远程管理与安全加固
第 16 天 Web 服务器搭建
第 17 天 数据库服务器部署
第 18 天 Docker 在 Ubuntu 上的安装与容器化管理
第 19 天 文件共享服务
第 20 天 监控与告警系统
第 21 天 邮件服务器基础
第 22 天 系统安全加固
第 23 天 性能调优与内核参数
第 24 天 虚拟化技术
第 25 天 容器编排入门
第 26 天 高可用与负载均衡
第 27 天 Ubuntu 自动部署
第 28 天 故障排查实战
第 29 天 Ubuntu 社区与文档
第 30 天 30 天回顾总结
第 1 天(重访·第二季) Ubuntu 新篇章——2026 年生态全景
第 2 天(重访·第二季) 手把手安装 Ubuntu——2026 年全新体验
第 3 天(重访·第二季) Ubuntu 桌面环境深度探索
第 4 天(重访·第二季) Ubuntu 终端与 Shell 高级技巧
第 5 天(重访·第二季) 用户与权限管理——从 ACL 到 PAM 🟢 今日
第 6 天(重访·第二季) 软件包管理——apt、dpkg、snap 深度对比
第 7 天(重访·第二季) 文件与文本操作——高效文本处理
第 8 天(重访·第二季) 系统服务管理——systemd 进阶
第 9 天(重访·第二季) 磁盘与文件系统——LVM 与存储
第 10 天(重访·第二季) 网络配置——高级网络与安全
第 11 天(重访·第二季) 进程管理与监控——深度监控
第 12 天(重访·第二季) 计划任务——自动化运维体系
第 13 天(重访·第二季) 备份恢复——企业级灾备方案
第 14 天(重访·第二季) 系统更新——生产级更新策略
第 15 天(重访·第二季) SSH 安全——零信任远程访问
第 16 天(重访·第二季) Web 服务器——高性能配置
第 17 天(重访·第二季) 数据库——高可用与调优
第 18 天(重访·第二季) Docker——容器化生产实践
第 19 天(重访·第二季) 文件共享——分布式存储
第 20 天(重访·第二季) 监控告警——全栈可观测性
第 21 天(重访·第二季) 邮件服务器——安全加固
第 22 天(重访·第二季) 安全加固——纵深防御体系
第 23 天(重访·第二季) 性能调优——生产环境基准
第 24 天(重访·第二季) 虚拟化——KVM 生产调优
第 25 天(重访·第二季) 容器编排——K8s 实战
第 26 天(重访·第二季) 高可用——负载均衡架构
第 27 天(重访·第二季) 自动部署——CI/CD 流水线
第 28 天(重访·第二季) 故障排查——深度排障
第 29 天(重访·第二季) 社区与贡献——开源实践
第 30 天(重访·第二季) 30 天回顾——进阶路线图

下期预告

第 6 天(重访·第二季):软件包管理深度之旅——我们将深入探索 apt 的底层机制、deb 包结构解析、snap 的 sandbox 原理、以及如何构建自己的 APT 仓库和软件包。从 apt install 背后的魔法到企业级软件分发策略,一网打尽。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容