一、声明
本文为学习笔记,转载请标明原文链接、作者、参考博文链接。
二、前言
在使用服务器运行程序时,为了保证安全性,要禁止使用root账户运行程序。
linux非root用户是禁止注册1024以下端口的。
当想使用普通用户注册1024以下端口的时候,比如http程序需要注册80端口,则可以进行一些配置来实现。
三、目前有两种方式:
- 设置suid
- setcap
1. 设置suid
1.1 suid简介
特殊权限-SUID,SGID,SBIT:
1.1.1 SUID:Set UID,只对二进制程序有效。
设置此权限的二进制程序,当有运行者对此程序有执行权限的时候,在运行程序的期间,会拥有此程序拥有者的权限。
示例:/usr/bin/passwd 拥有者权限为-rwsr-xr-x,拥有者为root。
现在有用户test对/usr/bin/passwd有执行权限,当test运行passwd的期间,则test此用户拥有/usr/bin/passwd程序拥有者root的权限。
1.1.2 SGID:SGID,针对文件和目录都有效。
针对文件:
对二进制程序有用。当有运行者对此程序有执行权限时,运行者在运行的过程中会拥有该程序群组的权限。
针对目录:
使用者在此目录下具有读写执行权限时,创建的文件或目录,所属群组为此目录的所属群组。
1.1.3 SBIT:Sticky Bit,只针对目录有限。
设置此权限后,使用者对此目录具有w,x的权限时,在此目录下创建的文件或者目录,只有创建者和root才可以删除。
示例:目前有目录test,权限为-rwxr-xr-t时。现在有A、B两个用户,A创建了A1文件,B创建了B1文件。则A1文件只能由A和root用户删除。B1文件只能有B和root用户删除。
2. 设置suid
以nginx程序为例
chmod u+x /usr/local/nginx/sbin/nginx
四、setcap
1. setcap简介
Capabilities是Linux内核2.2版本以后新增加的概念与机制。
Capabilities主要用来分割root用户的特权,将root用户的特权分割为不同的能力,每一种能力对应一项特权操作。
在Capilities中,只有进程和可执行文件才具有能力。
每个进程拥有三组能力集,分别称为cap_effective, cap_inheritable, cap_permitted(分别简记为:pE,pI,pP)。
- cap_permitted表示进程所拥有的最大能力集;
- cap_effective表示进程当前可用的能力集,可以看做是cap_permitted的一个子集;
- cap_inheitable则表示进程可以传递给其子进程的能力集。
系统根据进程的cap_effective能力集进行访问控制,cap_effective为cap_permitted的子集,进程可以通过取消cap_effective中的某些能力来放弃进程的一些特权。
可执行文件也拥有三组能力集,对应于进程的三组能力集。分别称为cap_effective, cap_allowed 和 cap_forced(分别简记为fE,fI,fP)。
- cap_allowed表示程序运行时可从原进程的cap_inheritable中集成的能力集
- cap_forced表示运行文件时必须拥有才能完成其服务的能力集
- cap_effective则表示文件开始运行时可以使用的能力。
2. Capabilities的29种能力:
- capability 名称 描述
- CAPAUDITCONTROL 启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则
- CAPAUDITREAD 允许通过 multicast netlink 套接字读取审计日志
- CAPAUDITWRITE 将记录写入内核审计日志
- CAPBLOCKSUSPEND 使用可以阻止系统挂起的特性
- CAP_CHOWN 修改文件所有者的权限
- CAPDACOVERRIDE 忽略文件的 DAC 访问限制
- CAP_FOWNER 忽略文件属主 ID 必须和进程用户 ID 相匹配的限制
- CAP_FSETID 允许设置文件的 setuid 位
- CAPIPCLOCK 允许锁定共享内存片段
- CAPIPCOWNER 忽略 IPC 所有权检查
- CAP_KILL 允许对不属于自己的进程发送信号
- CAP_LEASE 允许修改文件锁的 FL_LEASE 标志
- CAPLINUXIMMUTABLE 允许修改文件的 IMMUTABLE 和 APPEND 属性标志
- CAPMACADMIN 允许 MAC 配置或状态更改
- CAPMACOVERRIDE 忽略文件的 DAC 访问限制
- CAP_MKNOD 允许使用 mknod() 系统调用
- CAPNETADMIN 允许执行网络管理任务
- CAPNETBIND_SERVICE 允许绑定到小于 1024 的端口
- CAPNETBROADCAST 允许网络广播和多播访问
- CAPNETRAW 允许使用原始套接字
- CAP_SETGID 允许改变进程的 GID
- CAP_SETFCAP 允许为文件设置任意的 capabilities
- CAP_SETPCAP 参考 capabilities man page
- CAP_SETUID 允许改变进程的 UID
- CAPSYSADMIN 允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等
- CAPSYSBOOT 允许重新启动系统
- CAPSYSCHROOT 允许使用 chroot() 系统调用
- CAPSYSMODULE 允许插入和删除内核模块
- CAPSYSNICE 允许提升优先级及设置其他进程的优先级
- CAPSYSPACCT 允许执行进程的 BSD 式审计
- CAPSYSPTRACE 允许跟踪任何进程
- CAPSYSRAWIO 允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备
- CAPSYSRESOURCE 忽略资源限制
- CAPSYSTIME 允许改变系统时钟
- CAPSYSTTY_CONFIG 允许配置 TTY 设备
- CAP_SYSLOG 允许使用 syslog() 系统调用
- CAPWAKEALARM 允许触发一些能唤醒系统的东西(比如 CLOCKBOOTTIMEALARM 计时器)
3. 使用setcap配置
以nginx程序为例,假设nginx路径为/usr/local/nginx/sbin/nginx。
setcap cap_net_bind_service=+eip /usr/local/nginx/sbin/nginx
五、java设置了Capabilities无法使用问题
为了安全需求,需要将应用程序的运行用户修改为非root用户时,非root用户启动程序使用1024以下的端口需要设置Capabilities。
给java赋值了Capabilities以后,使用普通用户运行java命令。出现如下报错java : error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory错误。
这是由于当一个可执行文件提升了权限后,运行时加载程序(rtld)— ld.so,它不会与不受信任路径中的库链接。Linux 会为使用了 setcap 或 suid 的程序禁用掉 LD_LIBRARY_PATH。所以就出现了 java 程序加载不到 libjli.so 的情况了,这是 JDK 的一个 bug。
1. 解决方式:
在/etc/ld.so.con.d下面创建java.conf文件,并将java的jli目录绝对路径写入里面。
echo '/usr/java/jdk1.8.0_261-amd64/lib/amd64/jli' > /etc/ld.so.conf.d/java.conf
cat /etc/ld.so.conf.d/java.conf
六、参考博客
setcap详解
Linux之特殊权限(SUID/SGID/SBIT)
java libjli.so_解决setcap导致Java加载libjli.so 失败问题
man.org-capabilities.7
Linux Capabilities 入门教程:概念篇