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。
- 网络劫持(Service Mesh):给 Istio 的 Init Container 单独授予
三、 基础权限模型(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/passwdx变为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(例如容器内是rootUID 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 策略来拦截容器对底层敏感目录的写操作。
- SELinux(RedHat / CentOS 系):基于安全上下文标签(Labeling)与类型强制(TE),排障时常结合
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(文件描述符打满) 的底层控制点。
- PAM 的
4. 文件隐藏属性(chattr / lsattr)
- 维度差异:与常规的
chmod/chown处于完全不同的维度。常规权限(rwx)限制的是“谁能读写”,而chattr设置的属性直接作用于文件系统的 Inode 层面,是强制性的系统级底层锁——即便你是root用户,在显式解除该属性之前也无法绕过它的限制(排查“为什么我是 root 却删不掉文件”的标准答案)。 - 核心高频属性:
+i(Immutable,不可变):文件不可被删除、改名、修改或建立硬链接(常用于锁定关键系统配置)。+a(Append Only,仅限追加):文件只能追加内容,不能修改或删除已有内容(常用于生产环境审计日志防篡改)。