跳至内容
Linux 用户管理与权限控制

Linux 用户管理与权限控制

一、 用户与用户组管理(User & Group)

1. 身份标识与组概念

通过 id 命令可以查看当前用户的 UID、GID 及所属组列表:

bakapiano@DESKTOP-NN9GVHM:/mnt/c/Users/Administrator$ id
uid=1000(bakapiano) gid=1000(bakapiano) groups=1000(bakapiano),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),1001(docker)
  • uid:用户唯一标识 ID。
  • gid(主组 / Primary Group):用户默认归属的主用户组(新建文件时默认继承该组)。
  • groups(附加组 / Supplementary Groups):用户挂载的扩展权限组(如 sudo、docker 组)。

2. 核心配置文件

  • /etc/passwd:存储用户基本信息(用户名、UID、GID、家目录、默认 Shell 等)。
  • /etc/shadow:存储加密后的用户密码哈希及密码过期策略(仅 root 可读)。
  • /etc/group:存储用户组信息及组成员列表。

3. 用户与组在内核中的核心作用

  • 管理文件与硬件:控制对存储数据以及外部硬件设备(在 Linux 中硬件被抽象为文件)的访问权限。
  • 管理进程与资源:控制进程间操作权限(如 kill 他人进程、ptrace 调试、IPC 进程间通信),以及配合管控 CPU 与 Memory 资源。

二、 特权管理:Sudo 与 Capabilities(Cap)

1. sudo 机制

  • 实现原理:/usr/bin/sudo 二进制文件拥有 Setuid 权限位,普通用户执行时会临时变身为 root 身份。
  • 核心价值:按命令粒度进行权限放行与安全审计。通过配置文件(/etc/sudoers)指定允许以 root 执行的命令,支持验证用户自身密码或配置 NOPASSWD 免密执行。

2. Linux Capabilities(权能拆分)

  • 背景:传统 Unix 权限模型中,root 拥有绝对特权(全有或全无),一旦提权风险极高。
  • 机制:将 root 的超级特权拆分为几十项独立的细粒度权能(Capabilities),支持按需发放给普通进程或容器。
  • 典型场景:普通程序需要监听高危特权端口(如 80、443,即小于 1024 的端口),无需使用 root 运行整个程序,只需单独授予 CAP_NET_BIND_SERVICE 权能即可。

3. Capabilities 的容器化实战应用

  • docker run 默认机制:默认剥夺 Linux 40 多项权能中的绝大部分,仅保留约 14 项基础权能(如 CAP_CHOWN、CAP_SETUID、CAP_NET_BIND_SERVICE 等),防止容器内的 root 修改宿主机内核或挂载文件系统。
  • K8s 生产推荐实践(最小权限原则):默认 drop: ["ALL"] + 按需添加(add)。
    • 网络劫持(Service Mesh):给 Istio 的 Init Container 单独授予 CAP_NET_ADMIN 修改 iptables,完成后即销毁,业务容器保持无特权。
    • 在线排障(Profiling):使用 strace、gdb 或 dotnet-trace 时需要 CAP_SYS_PTRACE 权能。
    • 避坑指南:坚决避免在生产环境配置 privileged: true 或滥用接近完整 root 的 CAP_SYS_ADMIN。

三、 基础权限模型(rwx 与 umask)

1. 权限归属与修改限制

  • 三类身份:Owner(所有者)、Group(所属组)、Others(其他人)。
  • 修改权限(chmod):只有 root、文件所有者(File Owner) 或拥有 CAP_FOWNER 权能的进程才能修改文件权限。

2. 基本权限位(rwx)在文件与目录上的本质区别

底层本质:目录在文件系统中本质上也是一个特殊文件,内部保存着 文件名列表(Name List) + Inode 映射表(Inode Map)。

权限位权重对普通文件的作用对目录的作用
r (Read)4读取文件具体内容使用 ls 列出目录内的文件名列表
w (Write)2修改文件内容在目录内新建、删除、重命名文件(修改目录的 Inode 映射表)
x (Execute)1作为可执行程序运行使用 cd 进入目录(访问目录及其子项的最基础通行证)

3. 默认权限掩码(umask)

  • 作用:决定新建文件或目录时的初始扣减权限(常见默认值为 0022)。
  • 计算基准:
    • 新文件基准为 0666:出于安全考虑,默认剥离执行权限(防止新建文件直接可执行),扣减 0022 后为 0644 (rw-r--r--)。
    • 新目录基准为 0777:目录必须有 x 权限才能进入,扣减 0022 后为 0755 (rwxr-xr-x)。

4. 内核安检流水线(匹配原则)

  • 匹配顺序:isRoot? -> isOwner? -> isGroup? -> Others
  • 核心规则(单向瀑布流,命中即止):内核按顺序核验身份,一旦命中第一条符合的身份即刻终止后续判断。
    • 典型案例:若某文件权限为 ---rwxrwx,即使文件所有者(Owner)同时属于该文件的所属组(Group),内核在匹配到 isOwner 时发现权限为 ---,就会直接拒绝访问,不会继续往下匹配 Group 权限。

四、 三个特殊权限位(Setuid / Setgid / Sticky Bit)

1. Setuid(SUID)

  • 机制:程序所有者 {user} 留下一段可执行程序并设置 SUID,任何人在运行该程序时,进程的有效身份都会临时变成程序所有者 {user}(通常为 root)。
  • 现状与示例:因可直接变身 root,现代软件极少使用,仅保留在 sudo、passwd 等系统核心工具中。
    $ ls -l /usr/bin/passwd
    -rwsr-xr-x 1 root root 68248 Jan 10 09:30 /usr/bin/passwd
    (注:所有者执行位由 x 变为 s)

2. Setgid(SGID)

  • 作用于程序:进程执行时临时借用该程序的所属组(Group)身份。
  • 作用于目录(核心场景:管理团队共享目录):只要给共享文件夹加上 Setgid,此后无论谁在该文件夹内新建文件或子目录,新文件的“所属组”都会默认继承父文件夹的所属组(例如自动归属“研发部”组),而非创建者自己的主组。

3. Sticky Bit(粘滞位)

  • 作用(防误删锁):设置在共享目录上(权限末尾显示为 t,如 /tmp 的 rwxrwxrwt)。即使所有人对该目录都有写(w)权限,目录内的文件也仅允许文件所有者、目录所有者或 root 删除,防止他人误删或恶意删除。

五、 ACL(访问控制列表)

1. 核心作用

打破传统 Owner / Group / Others 的“单用户 + 单组”限制,支持给特定某个人或特定某个组单独精准授权(带有 ACL 规则的文件在 ls -l 输出末尾会带有 + 号)。

2. 引入 ACL 后的内核安检流水线

匹配顺序扩展为: isRoot? -> isOwner? -> isNamedUser (ACL 特定用户)? -> isAnyGroup (原所属组 或 ACL 特定组,取并集)? -> Others

3. ACL Mask(最大有效权限掩码)

  • 机制:mask 定义了 ACL 特定用户、ACL 特定组以及文件原所属组所能拥有的最大权限上限(扣除掉超出 mask 的权限),用于统一收紧权限而不破坏原有独立 ACL 条目。

六、 进程权限与内核检查时机

1. 进程的三个 UID 身份

  • 真实用户 ID(Real UID / uid):启动该进程的用户身份(我是谁)。
  • 有效用户 ID(Effective UID / euid):内核进行权限检查时实际依据的身份(我当前拥有谁的权限,受 Setuid 影响)。
  • 保存的设置用户 ID(Saved Set-UID):保存进程提权前的有效身份副本,方便进程在特权身份与普通身份之间按需安全切换。

2. 内核触发权限检查的时机

  • 跨界系统调用触发:只要进程发起跨越自身私有领地的系统调用(如 open、unlink、kill、bind 特权端口、mount 等),即会触发内核权限检查。
  • “开门查证,进屋不管”原则:内核仅在调用 open() 打开文件的瞬间核验文件权限。一旦校验通过并返回文件描述符(FD, File Descriptor),后续进程凭该 FD 进行的 read() / write() 操作将不再重复查验文件权限(即使文件在打开期间被 chmod 000,已持有 FD 的进程仍可继续读写)。

七、 进阶与底层安全隔离(企业生产与云原生补充)

1. Namespaces(命名空间视图隔离)

  • 核心机制:提供视图级别的隔离,让进程看不到其他隔离区的 user、pid、net、mount(文件系统)、ipc、uts 等资源。日常可使用 unshare 命令进行调试与隔离实验。
  • User Namespace(用户隔离核心):
    • 映射机制:将容器内的 uid 和 gid 映射到宿主机对应的普通非特权 uid 和 gid(例如容器内是 root UID 0,在宿主机内核看来只是普通用户 UID 100000),从而防范容器逃逸。
    • 底层实现:通过 /proc/<PID>/uid_map 和 /proc/<PID>/gid_map 这两个文件维护内外身份的映射翻译。
    • 联动 Capabilities:进程在属于自己的 User Namespace 里拥有全量的 Capabilities,可以在自己的命名空间内随意修改配置(如配虚拟网卡),但一旦跨界操作宿主机资源则会立刻被内核拦截。
    • 工程痛点(挂载卷权限拒绝):由于内外 UID 映射错位,常导致宿主机目录挂载到容器时报 Permission Denied,工程上需通过在宿主机 chown 对齐映射后的 UID,或使用现代内核(5.12+)的 Idmapped Mounts 技术解决。

2. MAC(强制访问控制):SELinux / AppArmor

  • 核心本质:超越传统 DAC(rwx),实现对象与资源级别的强制控制,精细管控某个进程具体能否读写哪个文件或路径。策略由系统强制执行,即便进程是 root 身份也同样受限。
  • 主流实现:
    • SELinux(RedHat / CentOS 系):基于安全上下文标签(Labeling)与类型强制(TE),排障时常结合 getenforce、ls -Z 与 /var/log/audit/audit.log。
    • AppArmor(Ubuntu / Debian 系):基于程序绝对路径的配置文件(Profile),Docker 在 Ubuntu 上默认会自动加载 docker-default 的 AppArmor 策略来拦截容器对底层敏感目录的写操作。

3. PAM(可插拔认证模块, Pluggable Authentication Modules)

  • 核心作用:将系统认证逻辑与应用程序解耦,允许企业灵活实现和插拔自己的身份校验与会话管理逻辑(支撑 sshd、su、login 等程序,配置文件位于 /etc/pam.d/,如 /etc/pam.d/sshd)。
  • 高并发调优核心考点(pam_limits.so):
    • PAM 的 session 阶段配合 pam_limits.so 模块去读取 /etc/security/limits.conf,控制 ulimit 资源上限(如 nofile 最大文件打开数、nproc 最大进程数)。
    • 这是后端高并发场景下解决 Too many open files(文件描述符打满) 的底层控制点。

4. 文件隐藏属性(chattr / lsattr)

  • 维度差异:与常规的 chmod / chown 处于完全不同的维度。常规权限(rwx)限制的是“谁能读写”,而 chattr 设置的属性直接作用于文件系统的 Inode 层面,是强制性的系统级底层锁——即便你是 root 用户,在显式解除该属性之前也无法绕过它的限制(排查“为什么我是 root 却删不掉文件”的标准答案)。
  • 核心高频属性:
    • +i(Immutable,不可变):文件不可被删除、改名、修改或建立硬链接(常用于锁定关键系统配置)。
    • +a(Append Only,仅限追加):文件只能追加内容,不能修改或删除已有内容(常用于生产环境审计日志防篡改)。