当前位置:首页>Linux>Linux 权限体系详解:chmod、chown 与 ACL 的进阶玩法

Linux 权限体系详解:chmod、chown 与 ACL 的进阶玩法

  • 2026-08-24 00:22:26
Linux 权限体系详解:chmod、chown 与 ACL 的进阶玩法

Linux 权限体系详解:chmod、chown 与 ACL 的进阶玩法

一、概述

1.1 背景介绍

说实话,Linux 权限这块我踩过不少坑。记得刚入行那会儿,有次为了图省事直接 chmod 777 -R /var/www,结果被老大骂了一顿——"你这是把大门敞开让小偷随便进啊!"

Linux 的权限体系是整个系统安全的基石。从最基础的 rwx 三权分立,到 SUID/SGID 这些"特权通道",再到 ACL 细粒度控制,最后是 SELinux/AppArmor 这种强制访问控制,形成了一套层层递进的安全防护网。

2026 年了,随着容器化和云原生的普及,权限管理变得更加复杂。你不仅要管好宿主机的权限,还得搞清楚容器内的 UID 映射、Rootless 容器这些新玩意儿。这篇文章就把这些年我在生产环境中积累的经验都掏出来,希望能帮你少走弯路。

1.2 技术特点

  • 层次分明:基础权限 → 特殊权限 → ACL → MAC,由简到繁
  • 向后兼容:新特性不影响老系统,平滑升级
  • 灵活可控:从粗粒度到细粒度,满足各种场景需求
  • 审计友好:所有权限变更都可追溯,便于合规审计

1.3 适用场景

  • Web 服务器:Nginx/Apache 的目录权限配置
  • 多用户开发环境:团队协作时的代码目录权限管理
  • 容器化部署:Docker/Kubernetes 中的权限映射
  • 合规审计:满足等保、SOC2 等安全合规要求
  • 数据安全:敏感文件的访问控制

1.4 环境要求

组件
版本要求
说明
操作系统
CentOS 8+/Ubuntu 20.04+/Debian 11+
推荐使用最新 LTS 版本
内核版本
5.4+
支持完整的 ACL 和 capabilities
文件系统
ext4/xfs/btrfs
需支持扩展属性(xattr)
SELinux
3.0+
CentOS/RHEL 默认启用
AppArmor
3.0+
Ubuntu/Debian 默认启用

二、详细步骤

2.1 准备工作

2.1.1 系统检查

# 检查系统版本cat /etc/os-release# 检查内核版本(需要 5.4+ 以获得完整特性支持)uname -r# 检查文件系统类型df -Th# 检查是否支持 ACLgrep -i acl /boot/config-$(uname -r) 2>/dev/null || zcat /proc/config.gz 2>/dev/null | grep -i acl# 检查 SELinux 状态(RHEL 系)getenforce 2>/dev/null || echo"SELinux not installed"# 检查 AppArmor 状态(Debian 系)aa-status 2>/dev/null || echo"AppArmor not installed"

2.1.2 安装必要工具

# RHEL/CentOS 系列sudo dnf install -y acl attr policycoreutils-python-utils setools-console# Debian/Ubuntu 系列sudo apt updatesudo apt install -y acl attr apparmor-utils auditd

2.2 核心配置

2.2.1 基础权限:rwx 三剑客

先来复习一下基础,这块很多人以为自己懂了,其实细节上还是会犯错。

# 权限的数字表示法# r=4, w=2, x=1# 755 = rwxr-xr-x = 所有者全权限,组和其他人只读+执行# 查看文件权限的详细信息ls -la /etc/passwd# -rw-r--r-- 1 root root 2847 Jan 15 10:23 /etc/passwd# │├─┤├─┤├─┤# │ │  │  └── 其他用户权限 (r--)# │ │  └───── 所属组权限 (r--)# │ └──────── 所有者权限 (rw-)# └────────── 文件类型 (-=普通文件, d=目录, l=链接)# 修改权限的两种方式# 方式一:数字法(推荐,精确控制)chmod 644 config.yml      # rw-r--r--chmod 755 script.sh       # rwxr-xr-xchmod 600 .ssh/id_rsa     # rw------- (私钥必须是600!)# 方式二:符号法(适合微调)chmod u+x script.sh       # 给所有者加执行权限chmod g-w config.yml      # 去掉组的写权限chmod o= secret.txt       # 清空其他用户的所有权限chmod a+r public.html     # 所有人加读权限

我踩过的坑:有次部署应用,死活启动不了,查了半天发现是配置文件权限给成了 000。所以现在我养成习惯,部署脚本里一定会加权限检查。

2.2.2 目录权限的特殊之处

目录的权限和文件不太一样,这点很多新手会搞混:

# 目录权限含义:# r - 可以列出目录内容(ls)# w - 可以在目录中创建/删除文件# x - 可以进入目录(cd)和访问目录中的文件# 实验:创建测试目录mkdir -p /tmp/perm_test && cd /tmp/perm_test# 场景1:只有 r 没有 xmkdir test_r && chmod 444 test_recho"hello" > test_r/file.txt 2>/dev/null  # 会失败ls test_r/                                    # 能看到文件名,但看不到详情cat test_r/file.txt                          # 失败,因为没有 x 权限# 场景2:只有 x 没有 rmkdir test_x && chmod 111 test_xecho"hello" > test_x/file.txtls test_x/                                    # 失败,不能列目录cat test_x/file.txt                          # 成功!知道文件名就能访问# 场景3:生产环境常用配置chmod 755 /var/www/html      # Web 目录,所有人可读可进入chmod 750 /app/config        # 配置目录,组内可读,其他人禁止chmod 700 /root/.ssh         # SSH 目录,仅所有者可访问

2.2.3 特殊权限:SUID、SGID、Sticky Bit

这三个特殊权限是很多安全问题的根源,但用好了也是利器:

# SUID (Set User ID) - 数字表示:4xxx# 执行文件时,临时获得文件所有者的权限# 典型例子:passwd 命令需要修改 /etc/shadow,普通用户执行时临时获得 root 权限ls -la /usr/bin/passwd# -rwsr-xr-x 1 root root 68208 Mar 14 2023 /usr/bin/passwd#    ^-- 注意这个 s,表示设置了 SUID# 设置 SUIDchmod u+s /usr/local/bin/myappchmod 4755 /usr/local/bin/myapp# SGID (Set Group ID) - 数字表示:2xxx# 对文件:执行时临时获得文件所属组的权限# 对目录:在该目录下创建的文件自动继承目录的所属组(团队协作神器!)# 团队共享目录配置mkdir -p /data/team_projectchown root:developers /data/team_projectchmod 2775 /data/team_project# 现在 developers 组的成员在这里创建的文件,所属组都是 developers# Sticky Bit - 数字表示:1xxx# 只对目录有效:目录中的文件只能被文件所有者或 root 删除# 典型例子:/tmp 目录ls -ld /tmp# drwxrwxrwt 15 root root 4096 Jan 20 10:00 /tmp#          ^-- 注意这个 t,表示设置了 Sticky Bit# 设置 Sticky Bitchmod +t /data/sharedchmod 1777 /data/shared

安全警告:SUID 是安全审计的重点关注对象。定期检查系统中的 SUID 文件:

# 查找所有 SUID 文件find / -perm -4000 -type f 2>/dev/null# 查找所有 SGID 文件find / -perm -2000 -type f 2>/dev/null# 生产环境建议:建立基线,定期对比find / -perm -4000 -type f 2>/dev/null | sort > /var/log/suid_baseline_$(date +%Y%m%d).txt

2.2.4 文件所有权:chown 和 chgrp

# 修改所有者chown nginx /var/www/html/index.html# 修改所有者和所属组chown nginx:www-data /var/www/html/index.html# 只修改所属组chgrp www-data /var/www/html/index.html# 或者chown :www-data /var/www/html/index.html# 递归修改(谨慎使用!)chown -R nginx:www-data /var/www/html/# 只修改符合条件的文件(更安全的做法)find /var/www/html -type f -exec chown nginx:www-data {} \;find /var/www/html -type d -exec chown nginx:www-data {} \;# 参考符号链接的目标(默认不跟随)chown -h nginx:www-data /var/www/html/link  # 修改链接本身chown nginx:www-data /var/www/html/link     # 修改链接指向的文件

2.2.5 ACL:细粒度权限控制

传统的 rwx 权限有个致命缺陷:只能设置一个所有者和一个所属组。如果你想让用户 A 有读写权限,用户 B 只有读权限,用户 C 完全没权限,传统权限就搞不定了。这时候 ACL 就派上用场了。

# 查看文件的 ACLgetfacl /data/project/config.yml# 输出示例:# file: data/project/config.yml# owner: root# group: developers# user::rw-# user:alice:rw-        # alice 用户有读写权限# user:bob:r--          # bob 用户只有读权限# group::r--# group:ops:rw-         # ops 组有读写权限# mask::rw-# other::---# 设置用户 ACLsetfacl -m u:alice:rw /data/project/config.yml    # 给 alice 读写权限setfacl -m u:bob:r /data/project/config.yml       # 给 bob 只读权限# 设置组 ACLsetfacl -m g:ops:rw /data/project/config.yml      # 给 ops 组读写权限# 删除特定 ACLsetfacl -x u:alice /data/project/config.yml       # 删除 alice 的 ACLsetfacl -x g:ops /data/project/config.yml         # 删除 ops 组的 ACL# 删除所有 ACL(恢复到传统权限)setfacl -b /data/project/config.yml# 递归设置 ACLsetfacl -R -m u:alice:rwX /data/project/          # X 表示仅对目录设置执行权限# 设置默认 ACL(新创建的文件自动继承)setfacl -d -m u:alice:rw /data/project/           # 目录下新文件自动给 alice 读写权限setfacl -d -m g:developers:rwx /data/project/     # 目录下新文件自动给 developers 组全权限

ACL 的 mask 机制:这是个容易被忽略但很重要的概念。mask 定义了 ACL 权限的上限。

# 查看当前 maskgetfacl /data/project/config.yml | grep mask# 设置 mask(限制所有 ACL 的最大权限)setfacl -m m::r /data/project/config.yml# 即使 alice 设置了 rw 权限,实际生效的也只有 r(被 mask 限制)# 注意:chmod 会影响 mask!chmod 640 /data/project/config.yml# 这会把 mask 设置为 r--,可能导致 ACL 权限失效

我的经验:ACL 虽然强大,但也增加了复杂度。我的建议是:

  1. 能用组权限解决的,就不要用 ACL
  2. 用了 ACL 一定要做好文档记录
  3. 定期审计 ACL 配置,避免权限膨胀

2.3 启动和验证

2.3.1 权限配置验证脚本

#!/bin/bash# 文件名:check_permissions.sh# 用途:验证关键目录和文件的权限配置RED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'NC='\033[0m'check_permission() {local path=$1local expected_perm=$2local expected_owner=$3local expected_group=$4if [[ ! -e "$path" ]]; thenecho -e "${RED}[FAIL]${NC}$path does not exist"return 1filocal actual_perm=$(stat -c "%a""$path")local actual_owner=$(stat -c "%U""$path")local actual_group=$(stat -c "%G""$path")local status=0if [[ "$actual_perm" != "$expected_perm" ]]; thenecho -e "${RED}[FAIL]${NC}$path permission: expected $expected_perm, got $actual_perm"        status=1fiif [[ "$actual_owner" != "$expected_owner" ]]; thenecho -e "${RED}[FAIL]${NC}$path owner: expected $expected_owner, got $actual_owner"        status=1fiif [[ "$actual_group" != "$expected_group" ]]; thenecho -e "${YELLOW}[WARN]${NC}$path group: expected $expected_group, got $actual_group"fiif [[ $status -eq 0 ]]; thenecho -e "${GREEN}[OK]${NC}$path"fireturn$status}echo"=== Permission Check Report ==="echo"Date: $(date)"echo""# 检查关键系统文件echo"--- System Files ---"check_permission "/etc/passwd""644""root""root"check_permission "/etc/shadow""640""root""shadow"check_permission "/etc/ssh/sshd_config""600""root""root"# 检查 SSH 目录echo""echo"--- SSH Directory ---"check_permission "$HOME/.ssh""700""$USER""$USER"check_permission "$HOME/.ssh/authorized_keys""600""$USER""$USER" 2>/dev/nullcheck_permission "$HOME/.ssh/id_rsa""600""$USER""$USER" 2>/dev/null# 检查 Web 目录(如果存在)if [[ -d "/var/www/html" ]]; thenecho""echo"--- Web Directory ---"    check_permission "/var/www/html""755""www-data""www-data"fiecho""echo"=== Check Complete ==="

2.3.2 SUID/SGID 审计

#!/bin/bash# 文件名:audit_suid.sh# 用途:审计系统中的 SUID/SGID 文件BASELINE_FILE="/var/log/suid_baseline.txt"CURRENT_FILE="/tmp/suid_current_$(date +%Y%m%d).txt"# 生成当前 SUID 文件列表find / -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null | sort > "$CURRENT_FILE"if [[ -f "$BASELINE_FILE" ]]; thenecho"=== SUID/SGID File Changes ==="echo""# 新增的 SUID 文件    new_files=$(comm -13 "$BASELINE_FILE""$CURRENT_FILE")if [[ -n "$new_files" ]]; thenecho"!!! NEW SUID/SGID FILES DETECTED !!!"echo"$new_files"echo""fi# 删除的 SUID 文件    removed_files=$(comm -23 "$BASELINE_FILE""$CURRENT_FILE")if [[ -n "$removed_files" ]]; thenecho"--- Removed SUID/SGID files ---"echo"$removed_files"echo""fiif [[ -z "$new_files" && -z "$removed_files" ]]; thenecho"No changes detected since last baseline."fielseecho"No baseline file found. Creating baseline..."    cp "$CURRENT_FILE""$BASELINE_FILE"echo"Baseline created at $BASELINE_FILE"echo""echo"Current SUID/SGID files:"    cat "$CURRENT_FILE"fi

三、示例代码和配置

3.1 完整配置示例

3.1.1 SELinux 配置(RHEL/CentOS 系)

SELinux 是强制访问控制(MAC)的实现,比传统权限更加严格。很多人遇到问题就直接 setenforce 0 关掉,这是非常不好的习惯。

# 查看 SELinux 状态getenforce# Enforcing = 强制模式(生产环境推荐)# Permissive = 宽容模式(只记录不阻止,调试用)# Disabled = 禁用sestatus# 查看详细状态# 临时切换模式(重启后失效)sudo setenforce 0  # 切换到 Permissivesudo setenforce 1  # 切换到 Enforcing# 永久修改(需要重启)sudo vim /etc/selinux/config# SELINUX=enforcing# 查看文件的 SELinux 上下文ls -Z /var/www/html/# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html#                       └─────────────────────────────────────────┘#                                    SELinux 上下文# 修改文件的 SELinux 上下文# 临时修改(重新标记后会恢复)chcon -t httpd_sys_content_t /var/www/html/newfile.html# 永久修改(推荐)semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?"restorecon -Rv /data/web/# 查看 SELinux 布尔值getsebool -a | grep httpd# 设置布尔值(允许 httpd 连接网络)setsebool -P httpd_can_network_connect on

SELinux 故障排查:

# 查看 SELinux 拒绝日志sudo ausearch -m avc -ts recent# 使用 audit2why 分析原因sudo ausearch -m avc -ts recent | audit2why# 生成允许规则(谨慎使用!)sudo ausearch -m avc -ts recent | audit2allow -M mypolicysudo semodule -i mypolicy.pp# 实用技巧:临时切换到 Permissive 模式测试sudo setenforce 0# 测试功能是否正常# 如果正常,说明是 SELinux 问题sudo setenforce 1# 然后根据日志修复 SELinux 配置

3.1.2 AppArmor 配置(Ubuntu/Debian 系)

# 查看 AppArmor 状态sudo aa-status# 查看特定程序的配置文件cat /etc/apparmor.d/usr.sbin.nginx# AppArmor 模式# enforce - 强制模式# complain - 投诉模式(只记录不阻止)# disabled - 禁用# 切换到投诉模式(调试用)sudo aa-complain /usr/sbin/nginx# 切换到强制模式sudo aa-enforce /usr/sbin/nginx# 禁用特定配置sudo aa-disable /usr/sbin/nginx# 重新加载配置sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx# 查看日志sudo dmesg | grep apparmorsudo journalctl -k | grep apparmor

自定义 AppArmor 配置示例:

# /etc/apparmor.d/usr.local.bin.myapp#include <tunables/global>/usr/local/bin/myapp {#include <abstractions/base>#include <abstractions/nameservice># 可执行文件  /usr/local/bin/myapp mr,# 配置文件(只读)  /etc/myapp/** r,# 数据目录(读写)  /var/lib/myapp/** rw,# 日志目录  /var/log/myapp/** w,# 临时文件  /tmp/myapp-* rw,# 网络访问  network inet stream,  network inet dgram,# 拒绝其他所有访问  deny /etc/shadow r,  deny /etc/passwd w,}

3.2 实际应用案例

案例一:容器环境权限管理

2026 年了,不懂容器权限基本没法干活。这块坑特别多,我来详细说说。

# Docker 默认以 root 运行,这是个安全隐患docker run -it ubuntu whoami# root# 指定用户运行(推荐)docker run -it --user 1000:1000 ubuntu whoami# 会显示 uid=1000# 在 Dockerfile 中指定用户# Dockerfile 示例cat << 'EOF' > DockerfileFROM ubuntu:22.04# 创建非 root 用户RUN groupadd -r appgroup && useradd -r -g appgroup appuser# 设置工作目录权限WORKDIR /appCOPY --chown=appuser:appgroup . .# 切换到非 root 用户USER appuserCMD ["./myapp"]EOF

UID 映射问题:容器内的 UID 和宿主机是共享的!

# 容器内 UID 1000 = 宿主机 UID 1000# 这可能导致权限问题# 查看容器内进程的实际 UIDdocker run -d --name test nginxps aux | grep nginx# 你会看到宿主机上显示的是 UID,不是用户名# 解决方案:使用 User Namespace(Rootless 容器)# Docker Rootless 模式dockerd-rootless-setuptool.sh install# 验证 Rootless 模式docker info | grep -i rootless

Kubernetes 中的权限控制:

# Pod Security Context 示例apiVersion:v1kind:Podmetadata:name:secure-podspec:securityContext:runAsNonRoot:truerunAsUser:1000runAsGroup:1000fsGroup:1000containers:-name:appimage:myapp:latestsecurityContext:allowPrivilegeEscalation:falsereadOnlyRootFilesystem:truecapabilities:drop:-ALLadd:-NET_BIND_SERVICE# 只添加必要的 capability

案例二:Web 服务器权限配置最佳实践

#!/bin/bash# 文件名:setup_web_permissions.sh# 用途:配置 Nginx Web 服务器的权限WEB_ROOT="/var/www/html"WEB_USER="www-data"WEB_GROUP="www-data"UPLOAD_DIR="${WEB_ROOT}/uploads"# 创建目录结构mkdir -p "${WEB_ROOT}"/{static,uploads,logs}# 设置所有权chown -R ${WEB_USER}:${WEB_GROUP}${WEB_ROOT}# 设置目录权限find ${WEB_ROOT} -type d -exec chmod 755 {} \;# 设置文件权限find ${WEB_ROOT} -type f -exec chmod 644 {} \;# 上传目录特殊处理(需要写权限,但禁止执行)chmod 775 ${UPLOAD_DIR}# 在 Nginx 配置中禁止执行上传目录的脚本# location /uploads/ {#     location ~ \.(php|pl|py|sh)$ { deny all; }# }# 配置文件权限(敏感信息)chmod 640 /etc/nginx/conf.d/*.confchown root:${WEB_GROUP} /etc/nginx/conf.d/*.confecho"Web permissions configured successfully!"

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 最小权限原则

这是安全的黄金法则,说起来简单做起来难。

# 错误示范(千万别这么干!)chmod 777 /var/www/html  # 全开放,等着被黑吧chmod -R 777 /           # 系统直接废了# 正确做法:按需分配# 1. 先确定谁需要访问# 2. 确定需要什么权限(读/写/执行)# 3. 只给必要的权限# 常用权限速查# 644 - 普通文件(所有者读写,其他人只读)# 755 - 可执行文件/目录(所有者全权限,其他人读+执行)# 600 - 敏感文件(仅所有者读写)# 700 - 私有目录(仅所有者访问)# 640 - 配置文件(所有者读写,组内只读)# 750 - 应用目录(所有者全权限,组内读+执行)

4.1.2 安全加固清单

#!/bin/bash# 文件名:security_hardening.sh# 用途:系统权限安全加固echo"=== Starting Security Hardening ==="# 1. 关键系统文件权限chmod 644 /etc/passwdchmod 640 /etc/shadowchmod 644 /etc/groupchmod 640 /etc/gshadowchmod 600 /etc/ssh/sshd_configchmod 700 /root# 2. 限制 cron 访问chmod 600 /etc/crontabchmod 700 /etc/cron.dchmod 700 /etc/cron.dailychmod 700 /etc/cron.hourly# 3. 设置 umask(新文件默认权限)# 在 /etc/profile 或 /etc/bashrc 中设置# umask 027  # 新文件 640,新目录 750# 4. 禁用不必要的 SUID# 根据实际需求决定是否移除# chmod u-s /usr/bin/chage# chmod u-s /usr/bin/gpasswdecho"=== Security Hardening Complete ==="

4.2 注意事项

4.2.1 常见错误

错误现象
原因分析
解决方案
Permission denied
权限不足或 SELinux 阻止
检查 rwx 权限和 SELinux 上下文
Operation not permitted
文件有 immutable 属性
lsattr
 检查,chattr -i 移除
chmod 不生效
文件系统挂载为只读
mount -o remount,rw
ACL 权限失效
mask 限制或 chmod 覆盖
检查 mask 设置

4.2.2 危险操作警告

# 这些命令可能导致系统崩溃,请三思!# 1. 递归修改根目录权限chmod -R 777 /          # 绝对禁止!chown -R user:group /   # 绝对禁止!# 2. 修改关键系统文件chmod 777 /etc/shadow   # 安全漏洞chmod 777 /etc/sudoers  # sudo 会拒绝工作# 3. 移除自己的权限chmod 000 ~/.bashrc     # 可能无法登录

五、故障排查和监控

5.1 故障排查

5.1.1 权限问题诊断流程

# 第一步:检查基础权限ls -la /path/to/filestat /path/to/file# 第二步:检查 ACLgetfacl /path/to/file# 第三步:检查扩展属性lsattr /path/to/file# 第四步:检查 SELinux(RHEL 系)ls -Z /path/to/fileausearch -m avc -ts recent# 第五步:检查 AppArmor(Debian 系)aa-statusdmesg | grep apparmor

5.2 性能监控

5.2.1 权限审计配置

# 使用 auditd 监控权限变更# 安装 auditdsudo apt install auditd  # Debian/Ubuntusudo dnf install audit   # RHEL/CentOS# 添加审计规则sudo auditctl -w /etc/passwd -p wa -k passwd_changessudo auditctl -w /etc/shadow -p wa -k shadow_changessudo auditctl -w /etc/sudoers -p wa -k sudoers_changes# 查看审计日志sudo ausearch -k passwd_changes

5.3 备份与恢复

# 备份文件权限getfacl -R /data > /backup/data_acl_backup.txt# 恢复文件权限setfacl --restore=/backup/data_acl_backup.txt

六、总结

6.1 技术要点回顾

  • 基础权限:rwx 三权分立,数字法和符号法灵活运用
  • 特殊权限:SUID/SGID/Sticky Bit 各有用途,谨慎使用
  • ACL:细粒度控制,注意 mask 机制
  • SELinux/AppArmor:强制访问控制,别轻易关闭
  • 容器权限:UID 映射、Rootless 模式是趋势

6.2 进阶学习方向

  1. Linux Capabilities:比 SUID 更细粒度的特权控制
  2. Seccomp:系统调用过滤,容器安全必备
  3. eBPF 安全:新一代内核级安全监控

6.3 参考资料

  • Linux man pages - chmod/chown
  • Red Hat SELinux Guide
  • Ubuntu AppArmor Wiki
  • Docker Security Best Practices

作者寄语:权限管理看似简单,实则博大精深。记住最小权限原则,养成良好习惯,你的系统会更加安全。有问题欢迎交流!

最新文章

随机文章