Linux 内核 2.2 引入 Capability(能力集):把 root 的超级权限拆分成几十个独立、最小粒度的权限单元。setcap = set capabilities,作用:给二进制可执行文件绑定指定的权限能力,普通用户运行该程序时只获得分配的能力,不会拿到完整 root,遵循最小权限原则,大幅提升系统安全。这篇文章主要介绍:使用该命令绑定1024以下特权端口,场景:普通用户启动nginx(nginx端口为80/443等),或其他java端口。setcap [选项] <能力表达式> 目标文件 [多个文件]
| | |
| 绑定1024 以下特权端口 (80/443/22) | Nginx/Java/Go 程序普通用户监听 80、443 |
| | |
| | ping、tcpdump、wireshark 抓包 |
| | |
p (Permitted 允许集):进程被允许拥有该能力(前提,必须配置)e (Effective 生效集):能力实际立刻启用生效,没有 e 就算有 p 也无法使用权限i (Inheritable 可继承集):子进程执行 exec 时可以继承这份能力(守护进程、多进程程序使用)
+:追加能力;=:覆盖清空原有能力再写入;-:移除某个能力
=ep:清空原有 cap,赋予 允许 + 生效
+ep:在原有 cap 基础上,追加 允许 + 生效
三、实操命令
3.1、普通用户部署nginx
--在启动时报错,提示启动没有权限[nginx_oper@ceshiji2 ~]$ /home/nginx_oper/nginx-1.30.4/sbin/nginx nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /home/nginx_oper/nginx-1.30.4/conf/nginx.conf:2nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
3.2、给nginx二进制文件绑定特权端口80
--绑定特权端口80,setcap该命令必须使用root用户,如果没有root用户权限,可以使用sudo,不过前提是在/etc/sudoers有给nginx_oper用户配置,否则需要输入nginx_oper密码--切记后面跟的进程必须是绝对路径,不能是软连接或脚本[nginx_oper@ceshiji2 ~]$ sudo setcap cap_net_bind_service=+ep /home/nginx_oper/nginx-1.30.4/sbin/nginx --绑定后使用getcap进行查看,出现如下结果便是正常,getcap不需要root权限[nginx_oper@ceshiji2 ~]$ getcap /home/nginx_oper/nginx-1.30.4/sbin/nginx --输出结果:/home/nginx_oper/nginx-1.30.4/sbin/nginx = cap_net_bind_service+ep
3.3、使用nginx_oper普通用户启动nginx
--启动nginx[nginx_oper@ceshiji2 ~]$ /home/nginx_oper/nginx-1.30.4/sbin/nginx nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /home/nginx_oper/nginx-1.30.4/conf/nginx.conf:2-- 查看进程,可以看见是用nginx_oper普通用户启动[nginx_oper@ceshiji2 ~]$ ps -eo user:15,uid,pid,cmd |grep nginxnginx_oper 1002 8401 nginx: master process /home/nginx_oper/nginx-1.30.4/sbin/nginxnginx_oper 1002 8402 nginx: worker processnginx_oper 1002 8403 nginx: worker process
3.4、取消文件cap能力
--使用-r参数取消nginx二进制文件cap能力[nginx_oper@ceshiji2 ~]$ sudo setcap -r /home/nginx_oper/nginx-1.30.4/sbin/nginx --查看cap能力,无输出就是没有[nginx_oper@ceshiji2 ~]$ getcap /home/nginx_oper/nginx-1.30.4/sbin/nginx
-需要注意普通用户复制时也需要sudosudo cp --preserve=all 原文件 目标文件--复制[nginx_oper@ceshiji2 ~]$ sudo cp --preserve=all /home/nginx_oper/nginx-1.30.4/sbin/nginx ./--查看没有问题[nginx_oper@ceshiji2 ~]$ ls -lth-rwxrwxr-x. 1 nginx_oper nginx_oper 7.4M Jul 31 23:31 nginxdrwxrwxr-x. 11 nginx_oper nginx_oper 151 Jul 31 22:59 nginx-1.30.4drwxrwxr-x. 3 nginx_oper nginx_oper 53 Jul 31 22:32 software[nginx_oper@ceshiji2 ~]$ getcap /home/nginx_oper/nginx/home/nginx_oper/nginx = cap_net_bind_service+ep
--在原有的nginx自启文件中添加一行ExecStartPre=/usr/sbin/setcap 'cap_net_bind_service=+ep' /home/nginx_oper/nginx-1.30.4/sbin/nginx
nginx版本升级或有新增模块,需要重新编译nginx二进制文件,编译后的nginx二进制文件替换原来二进制文件,此时cap能力会失效,从下图即可看出,具体原理在第6大点
若nginx.service 文件配置了CapabilityBoundingSet、mbientCapabilities会限制文件自带cap
如果你写 bash/python 脚本启动 nginx,给脚本 setcap 无效,cap 必须配置在最终执行的 nginx 本体二进制。
1、root 权限调用 setcap 工具:setcap 修改文件扩展属性必须 root 执行,普通用户无权限修改文件 cap 标签。
2、内核写入扩展属性:内核在 nginx 文件的 inode 扩展属性中,写入 security.capability 字段,持久化保存在磁盘文件元数据(ext4/xfs 默认支持 xattr)。
3、写入的规则:只要任何用户执行这个 nginx 二进制文件,进程自动携带 cap_net_bind_service (允许 + 生效) 能力。
--大佬有建议请随时指点,必虚心采纳--