针对 Linux 用户的高端管理,同时还有处理一下重要的 ACL 这玩意儿,针对单一用户、群组所进行的权限设计!
帐号管理是一门大学问,用户可以回想一下之前玩过的 useradd, userdel, usermod 等指令的功能,同时再回想一下之前的权限概念, 就能够知道用户帐号管理的行为有多重要了!这一堂课还会针对同一个文件给予个别帐号或个别群组的权限功能,激活的是所谓的 ACL 的概念! 都是非常重要的管理行为!
在管理权限时,操作者可以借由 id 这个指令查找用户所加入的次要群组支持,借以了解用户对于某个文件的权限。 而主要的文件记录其实是用户的 UID 与 GID。
系统记录用户 UID 与 GID 的文件主要在:
针对 UID 的部份,在 CentOS 7.x 以后,系统管理员、系统帐号与一般帐号的 UID 范围为:
id 范围 | 该 ID 用户特性 |
0 (系统管理员) | 当 UID 是 0 时,代表这个帐号是『系统管理员』! |
1~999 (系统帐号) | 保留给系统使用的 ID,其实除了 0 之外,其他的 UID 权限与特性并没有不一样。缺省 1000
以下的数字让给系统作为保留帐号只是一个习惯。根据系统帐号的由来,通常这类帐号又约略被区分为两种:
|
1000~60000 (可登录帐号) | 给一般用户用的。事实上, Linux 内核支持 32 比特的 UID 记载, 所以目前 linux 内核至少已经可以支持到 4294967295 (2^32-1) 这么大的 UID 号码 |
Linux 的帐号数据记录在 /etc/passwd 当中,这个文件的内容中,以冒号 (:) 为区隔,共有七个字段,每个字段的意义为:
更多的说明可以参考 man 5 passwd 的内容。早期用户加密过的密码记录在 /etc/passwd 第二个字段,但这个文件的权限是任何人均可读取, 因此,有心人士可以查阅到加密过的密码,再以暴力破解法就可能可以获取所有人的密码。因此,密码字段已经移动到另一个文件去, 这就是 /etc/shadow 的由来。 /etc/shadow 以冒号 (:) 分隔成 9 字段,各字段功能为 (详细数据可查找 man 5 shadow):
用户的密码加密机制是可变的,从早期的 md5 到新的 sha512 改善了密码的数据长度,对于暴力破解法来说, 解密的时间会比较长。至于目前系统的加密机制可使用底下的方式查阅:
[root@localhost authselect]# authselect test sssd -s | grep password password requisite pam_pwquality.so local_users_only password sufficient pam_unix.so sha512 shadow nullok use_authtok password sufficient pam_sss.so use_authtok password required pam_deny.so [root@localhost authselect]# cat /etc/login.defs | grep -i encrypt ..... ENCRYPT_METHOD SHA512
用户的初始群组 (原生家庭) 记载在 /etc/passwd 文件的第四个字段,不过该 GID 对应到人类认识的群组名称就得到 /etc/group 当中查找。 这个文件的内容同样使用冒号 (:) 分隔成四个字段,内容为:
这三个文件中心以 /etc/passwd 为主,链接到 /etc/group 与 /etc/shadow 的示意图如下:
从上述数据我们可以知道,Linux 的帐号信息大概都记录在 /etc/passwd, /etc/shadow, /etc/group 当中,那如果我们要新建帐号时, 系统会怎么做呢?先测试建置帐号:
[root@localhost ~]# useradd testuser1 [root@localhost ~]# passwd testuser1 Changing password for user testuser1. New password: Retype new password: passwd: all authentication tokens updated successfully.
让我们观察一下 testuser 这个帐号的相关数据,先看一下用户的 UID 与 GID:
[root@localhost ~]# id testuser1 uid=1008(testuser1) gid=1010(testuser1) groups=1010(testuser1) [root@localhost ~]# grep testuser1 /etc/passwd /etc/group /etc/shadow /etc/passwd:testuser1:x:1008:1010::/home/testuser1:/bin/bash /etc/group:testuser1:x:1010: /etc/shadow:testuser1:$6$t4R4uBMlGGSsvPpH$K/...s.elrZ0/:19478:0:99999:7:::
上述 shadow 的数据可以简易的使用如下的指令来查找:
[root@localhost ~]# LANG=C chage -l testuser1
Last password change : May 01, 2023
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7
一般来说,新建帐号时,系统会搞定底下的事情:
至于新建用户时,上述的动作参考数据其实是参考 /etc/default/useradd 文件而来,该文件内容如下:
[root@localhost ~]# cat /etc/default/useradd # useradd defaults file GROUP=100 <==若为公开群组,使用 GID 100 的群组名称 HOME=/home <==缺省用户家目录位置 INACTIVE=-1 <==密码是否失效,缺省不会失效! EXPIRE= <==帐号是否需要失效 (shadow 第 8 字段) SHELL=/bin/bash <==缺省使用的 shell SKEL=/etc/skel <==缺省用户家目录的参考依据 CREATE_MAIL_SPOOL=yes <==是否要创建用户邮件信箱
除了 /etc/default/useradd 之外,其他像是密码字段的默认值,则写入在 /etc/login.defs 这个文件中,这个文件的内容如下:
[root@localhost ~]# grep -v '#' /etc/login.defs | grep -v '^$' MAIL_DIR /var/spool/mail <==用户缺省邮件信箱放置目录 UMASK 022 <==一般用户设计缺省 umask 是拿掉 w 的 022 HOME_MODE 0700 <==用户家目录创建的权限会是 700 PASS_MAX_DAYS 99999 <==/etc/shadow 内的第 5 栏,多久需变更密码日数 PASS_MIN_DAYS 0 <==/etc/shadow 内的第 4 栏,多久不可重新设置密码日数 PASS_WARN_AGE 7 <==/etc/shadow 内的第 6 栏,过期前会警告的日数 UID_MIN 1000 <==用户最小的 UID,意即小于 1000 的 UID 为系统保留 UID_MAX 60000 <==用户能够用的最大 UID SYS_UID_MIN 201 <==保留给用户自行设置的系统帐号最小值 UID SYS_UID_MAX 999 <==保留给用户自行设置的系统帐号最大值 UID SUB_UID_MIN 100000 SUB_UID_MAX 600100000 SUB_UID_COUNT 65536 GID_MIN 1000 <==用户自订群组的最小 GID,小于 1000 为系统保留 GID_MAX 60000 <==用户自订群组的最大 GID SYS_GID_MIN 201 <==保留给用户自行设置的系统帐号最小值 GID SYS_GID_MAX 999 <==保留给用户自行设置的系统帐号最大值 GID SUB_GID_MIN 100000 SUB_GID_MAX 600100000 SUB_GID_COUNT 65536 ENCRYPT_METHOD SHA512 <==密码加密的机制使用的是 sha512 这一个机制! USERGROUPS_ENAB yes <==使用 userdel 删除时,是否会删除初始群组 CREATE_HOME yes <==在不加 -M 及 -m 时,是否主动创建用户家目录? HMAC_CRYPTO_ALGO SHA512
一般来说,除非有特殊的需求,例如需要创建的是云端集中帐号管理,所以需要修改上述的设置档数据 (/etc/default/useradd, /etc/login.defs),否则尽量使用自订的手动修改用户相关参数,不要随意更动上述的文件内容。
passwd 就含有很多功能!只是, passwd -S 显示的消息比较简略,有时候我们可以通过另外几个程序来了解!
若需要删除帐号,使用 userdel 即可。不过需要加上 -r 的选项较佳!如果忘记加上 -r 的选项时,你应该要这样做:
[root@localhost ~]# userdel testuser1 [root@localhost ~]# ll -d /home/testuser1 /var/spool/mail/testuser1 drwx------. 3 1008 1010 78 May 1 11:06 /home/testuser1 -rw-rw----. 1 1008 mail 0 May 1 11:06 /var/spool/mail/testuser1 [root@localhost ~]# find / -nouser 2> /dev/null /home/testuser1 /home/testuser1/.mozilla /home/testuser1/.mozilla/extensions /home/testuser1/.mozilla/plugins /home/testuser1/.bash_logout /home/testuser1/.bash_profile /home/testuser1/.bashrc /var/spool/mail/testuser1 [root@localhost ~]# rm -rfv /home/testuser1 /var/spool/mail/testuser1
如上所示,系统会有一堆暂存数据需要删除,因此管理员可能需要使用 rm -rf /home/testuser1 /var/spool/mail/testuser1 来删除掉这些没主人的文件。
某些时刻,我们可能需要同时从 /etc 底下的 passwd, shadow, group 抓出同一个帐号的相关信息, 如果我们想要将所有的帐号一个一个的列出,并且慢慢观察时,或使用 shell script 的 for 循环, 会是个有效率的方法喔!for 循环基本语法如下:
for 变量名 in 内容1 内容2 内容3 ... do 运行的脚本 done
变量名称会在 do..done 当中被取用,然后第一次运行循环为『变量名=内容1』,第二次为『变量名=内容2』,以此类推! 依据上面的基本语法,我们可以通过管线命令取出 /etc/passwd 内的第 1 个字段的帐号数据后,丢进循环处理。如下所示:
[root@localhost ~]# mkdir bin; cd bin [root@localhost bin]# vim allid.sh #!/bin/bash # VBird 2023/05/01 users=$( cut -d ':' -f 1 /etc/passwd ) for username in ${users} do echo getent passwd ${username} getent shadow ${username} getent group ${username} echo read -p "press enter to continue." res done [root@localhost bin]# chmod a+x allid.sh [root@localhost bin]# allid.sh root:x:0:0:root:/root:/bin/bash root:$6$XeZr.pMraahNczJu$2XQiaCdvrFu9V....OLUO.4Sq84/::0:99999:7::: root:x:0: press enter to continue.
bash shell script 的循环控制主要是根据 for ... do ... done 来处理,所以也称为 for 循环。上述的脚本中:
用户在新建数据时,缺省的权限会是如何规范?一般来说,依据帐号的差异而会给予这样的设置:
这样的权限设计是考量一般用户可能会有同群组互相操作『同群组共享目录』的可能之故。但其实该缺省权限是可以修改的, 其主要的设置为 umask 所管理。
[student@localhost ~]$ umask 0022 [root@localhost ~]# umask 0022
在这一版本的 RockyLinux 环境中,缺省的 umask 在 root 与一般帐号之间,同样都是 0022!跟以前的版本都不太相同! 这点要特别注意。至于 umask 的意义,最简单的思考方向,umask 为拿掉不想要给予的缺省权限。 而四组分数中,第一个为特殊权限分数,不用理会,后续三个分数即为一般权限设置的三种身份权限。
如果 linuxuser1 在新建目录时,希望同群组的用户可以一同完整操作文件,但是其他人则没有任何权限,该如何处理 umask 呢? 简单的处理流程为:
[root@localhost ~]# su - linuxuser1 [linuxuser1@localhost ~]$ umask 0022 [linuxuser1@localhost ~]$ umask 007 [linuxuser1@localhost ~]$ umask 0007 [linuxuser1@localhost ~]$ mkdir newdir [linuxuser1@localhost ~]$ touch newfile [linuxuser1@localhost ~]$ ll -d new* drwxrwx---. 2 linuxuser1 linuxuser1 6 May 1 11:45 newdir -rw-rw----. 1 linuxuser1 linuxuser1 0 May 1 11:45 newfile
若需要这样的设置永远存在,就写入 ~/.bashrc 当中即可。
解决方案很简单,因为只是修改未来新用户的数据而已,因此只要修订 /etc/skel 即可处理完毕!
[root@localhost ~]# cd /etc/skel [root@localhost skel]# mkdir bin [root@localhost skel]# mkdir .bashrc.d [root@localhost skel]# vim .bashrc.d/vbirdadd HISTSIZE=10000 HISTFILESIZE=10000 alias cp="cp -i" alias mv="mv -i" alias rm="rm -i" [root@localhost skel]# useradd testuser2 [root@localhost skel]# ll -A /home/testuser2 -rw-r--r--. 1 testuser2 testuser2 18 Jan 24 06:42 .bash_logout -rw-r--r--. 1 testuser2 testuser2 141 Jan 24 06:42 .bash_profile -rw-r--r--. 1 testuser2 testuser2 492 Jan 24 06:42 .bashrc drwxr-xr-x. 2 testuser2 testuser2 22 May 1 11:48 .bashrc.d drwxr-xr-x. 2 testuser2 testuser2 6 May 1 11:46 bin drwxr-xr-x. 4 testuser2 testuser2 39 Feb 16 11:43 .mozilla [root@localhost skel]# userdel -r testuser2
建置完毕后我们使用 useradd 创建一个名为 testuser2 的帐号来查看一下是否有问题,若没有问题就可以删除该帐号了!
这五个帐号需求大致有底下的要求:
上述第一点主要是 shell 改成不可交互的 shell 即可,缺省建议使用 /sbin/nologin 较佳。 由于建置帐号的数据太多,因此建议使用 shell script 来处理较佳!
[root@localhost ~]# cd bin [root@localhost bin]# vim mailuser.sh #!/bin/bash # This program will create mail users # VBird 2016/05/03 for user in $(seq 1 5) do username="mailuser${user}" userpass=$(openssl rand -base64 6) useradd -s /sbin/nologin ${username} echo ${userpass} | passwd --stdin ${username} echo "${username} ${userpass}" >> mailuserpw.txt done [root@localhost bin]# sh mailuser.sh [root@localhost bin]# cat mailuserpw.txt mailuser1 M8pk6GEt mailuser2 HznQI88d mailuser3 zKpg4eg/ mailuser4 aakuwjo/ mailuser5 VrJtokaT [root@localhost bin]# grep mailuser /etc/passwd mailuser1:x:1011:1013::/home/mailuser1:/sbin/nologin mailuser2:x:1012:1014::/home/mailuser2:/sbin/nologin mailuser3:x:1013:1015::/home/mailuser3:/sbin/nologin mailuser4:x:1014:1016::/home/mailuser4:/sbin/nologin mailuser5:x:1015:1017::/home/mailuser5:/sbin/nologin
上述即可创建好专门给 mail user 专用的帐号了!而且这些帐号还无法登录系统操作 bash,这样系统较为安全!
由于软件的特殊需求,我们需要创建如下的帐号:
其实不难,只要两个指令即可结束!
[root@localhost ~]# useradd -u 399 -g users sysuser1 [root@localhost ~]# echo rocky9 | passwd --stdin sysuser1 [root@localhost ~]# id sysuser1 uid=399(sysuser1) gid=100(users) groups=100(users)
建议读者们最终一定要自己检查看看是否正确才好!所以上述我们使用了 id 这个指令来查找是否正确!
就是之前谈到文件权限概念时,提到的共享目录功能啰!
问题不难,读者应该会想到,之前处理权限数据时,就曾经玩过『共享目录』的信息,这里即是重新复习一次!
[root@localhost ~]# groupadd project [root@localhost ~]# useradd -G project pro1 [root@localhost ~]# useradd -G project pro2 [root@localhost ~]# useradd -G project pro3 [root@localhost ~]# echo password | passwd --stdin pro1 [root@localhost ~]# echo password | passwd --stdin pro2 [root@localhost ~]# echo password | passwd --stdin pro3 [root@localhost ~]# mkdir /srv/projecta [root@localhost ~]# chgrp project /srv/projecta [root@localhost ~]# chmod 2770 /srv/projecta [root@localhost ~]# ll -d /srv/projecta drwxrws---. 2 root project 6 May 3 21:43 /srv/projecta
最终三个用户都加入 project 这个群组,而这个群组的用户均可在 /srv/projecta 目录里进行任何工作!
由于系统的工作比较复杂,经常有不同的用户会共同管理一部系统,这在社群的实务运作上经常发现。因为管理系统时需要管理员 (root) 的权限, 本章之前读者可以通过 su 来切换用户,但如此一来就得要提供所有的用户 root 的密码,对于系统的运作来说,可能会有些许的问题。 例如某位用户切换成 root 密码后,不小心改了 root 的密码,而且自己也忘记了改回来,则未来大家都不知道如何操作系统了。
相对于 su 需要了解新切换的用户密码 (常常是需要 root 的密码), sudo 的运行则仅需要自己的密码即可!甚至可以设置不需要密码即可运行 sudo ! 由于 sudo 可以让你以其他用户的身份运行指令 (通常是使用 root 的身份来运行指令),因此并非所有人都能够运行 sudo , 而是仅有规范到 /etc/sudoers 内的用户才能够运行 sudo 这个指令。
只有信任用户才能够操作 sudo 这个指令,因此一开始还是需要使用 root 的权限来管理 sudo 的使用权才行。 虽然 sudo 的设置档为 /etc/sudoers,不过建议使用 visudo 来编辑较佳,因为 visudo 可以进行设置档的语法检验功能。
[root@localhost ~]# visudo ## Allow root to run any commands anywhere root ALL=(ALL) ALL 用户帐号 登录者的来源主机=(可切换的身份) 可下达的指令
大约在 100 行附近,读者会看到上面的 root 开头那行。由于仅有 root 这一行,亦即一开始仅有 root 可以运行 sudo 的意思。
除了单一个人的设置之外,在 /etc/sudoers 若有底下这一行,亦代表加入 wheel 群组的用户也能够操作 sudo 之意。
[root@localhost ~]# visudo ## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL # 这一行大概在 107 行前后喔!
上面这个练习过程,你可以发现到,让某个用户加入 wheel 是一个很可怕的决定!你必需要确认该用户不会乱用 sudo, 否则,就不应该让该用户加入 wheel 群组!这个 sudo 也是网络社共管 server 时,经常使用的技巧!可以避免 root 密码流落出去而导致的一些资安问题。
如果 10.1 小节最后的一个练习中, /srv/projecta 需要让 student 这个帐号登录去『查看』数据而已,不能变更现有的权限设置, 此时该如何设计呢?这时就可以考虑 ACL (Access Control List, 访问控制列表) 的使用了!
ACL 是 Access Control List 的缩写,主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限设置。ACL 可以针对单一用户,单一文件或目录来进行 r,w,x 的权限规范,对于需要特殊权限的使用状况非常有帮助。
ACL 主要可以针对几个项目来加以控制:
ACL 必须要配合文件系统的挂载启动才能生效,一般均将 acl 参数写入 /etc/fstab 的第四字段中。不过由于 ACL 几乎为目前 Linux 标准支持的文件系统参数, 因此读者仅须查找内核是否启动 ACL 即可,已无须将 acl 参数写入挂载设置中。
[root@localhost ~]# dmesg | grep -i acl 506:[ 0.802661] systemd[1]: systemd 239 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy) 566:[ 2.494185] SGI XFS with ACLs, security attributes, no debug enabled 582:[ 4.244339] systemd[1]: systemd 239 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy)
除了内核已经有支持之外, systemd 也有支持~XFS 文件系统也缺省支持喔!使用 dmesg 就可以明显的查阅出来。另外, ext4 文件系统家族,在 CentOS 7 以后的版本 (包含 RockyLinux 9),缺省挂载时也会加上 acl 的参数!
ACL 针对单一用户的设置练习中,我们以『让 student 可以读取 /srv/projecta 』为范本来介绍。
[root@localhost ~]# ll -d /srv/projecta drwxrws---. 2 root project 6 May 1 11:53 /srv/projecta [root@localhost ~]# setfacl -m u:student:rx /srv/projecta [root@localhost ~]# ll -d /srv/projecta drwxrws---+ 2 root project 6 May 1 11:53 /srv/projecta [root@localhost ~]# getfacl /srv/projecta getfacl: Removing leading '/' from absolute path names # file: srv/projecta # owner: root # group: project # flags: -s- user::rwx <==缺省的拥有者权限 user:student:r-x <==针对 student 的权限 group::rwx <==缺省的群组权限 mask::rwx <==缺省的 mask 权限 other::---
如上所示,setfacl -m 为设置的指令与选项,而设置的项目则主要有:
至于 getfacl 则是查阅 ACL 设置的指令。输出结果与上述的设置项目类似,只是当帐号或群组名称没有写的时候,代表为文件拥有者的帐号与群组之意。 因此就能够得到上述的结果。
至于 getfacl 输出的结果中,有个 mask 的项目,10.1.4 所述,umask 为拿掉的权限,在 getfacl 当中,mask 则是可给予的权限之意。 缺省 mask 会全部都给予~如果我们将 mask 拿掉只剩下 x 时,会发生的问题如下:
[root@localhost ~]# setfacl -m m::x /srv/projecta [root@localhost ~]# getfacl /srv/projecta # file: srv/projecta # owner: root # group: project # flags: -s- user::rwx user:student:r-x #effective:--x group::rwx #effective:--x mask::--x other::---
由于 mask 的关系,因此 student 这个帐号虽然给予 rx 的权限,但是实际上可以取得的权限则仅有 x 而已 (观察 effective 的输出项目)。 此外,如果要取消掉这个设置值时,可以使用如下的方式处理。
[root@localhost ~]# setfacl -m m::rwx /srv/projecta [root@localhost ~]# getfacl /srv/projecta
亦即重新设置进去即可。那如果使用 pro1 这个帐号实际在 /srv/projecta 操作时,会出现的权限状态情况如下:
[root@localhost ~]# su - pro1 [pro1@localhost ~]$ cd /srv/projecta [pro1@localhost projecta]$ mkdir newdir [pro1@localhost projecta]$ touch newfile [pro1@localhost projecta]$ ll -d new* drwxrwsr-x. 2 pro1 project 6 May 11 20:41 newdir -rw-rw-r--. 1 pro1 project 0 May 11 20:41 newfile
读者们可以发现在 /srv/projecta 目录内的新文件并没有缺省的 ACL 设置值,因此 student 的权限很可能被修改掉而无法保持 rx 的权限设置。此时,我们可以额外指定『缺省的 ACL 权限』信息,如下设置:
[root@localhost ~]# setfacl -m d:u:student:rx /srv/projecta [root@localhost ~]# getfacl /srv/projecta # file: srv/projecta # owner: root # group: project # flags: -s- user::rwx user:student:r-x group::rwx mask::rwx other::--- default:user::rwx default:user:student:r-x default:group::rwx default:mask::rwx default:other::---
若读者发现设置错误,想要将某一条 ACL 的权限设置取消时,例如将 student 的规则取消,则可以使用如下的方式来处理:
[root@localhost ~]# setfacl -x u:student /srv/projecta
取消设置比较单纯,不过要注意取消的情况得要使用 -x 这个选项,而非 -m 的选项。此外,由于取消设置是不需要处理权限的, 因此取消时,仅需要处理『 u:帐号 』或『 g:群组 』这样就好了!那如果要将该文件的所有 ACL 设置都取消时,可以使用底下的方式:
[root@localhost ~]# setfacl -b /srv/projecta [root@localhost ~]# ll -d /srv/projecta/ drwxrws---. 3 root project 35 May 1 12:05 /srv/projecta/
读者可以发现到,权限位置最末位的 + 号不见了,因为已经完整的取消的缘故。
作业硬盘一般操作说明:
作业当中,某些部份可能为简答题~若为简答题时,请将答案写入 /home/student/ans.txt 当中,并写好正确题号,方便老师订正答案。 请注意,文件名写错将无法上传!
请使用 root 的身份进行如下实做的任务。直接在系统上面操作,操作成功即可,上传结果的程序会主动找到你的实做结果。 另外,因为题目是有连续性的,请依照顺序完成题目,尽量不要跳着做。
作业结果传输:请以 root 的身分运行 vbird_book_check_unit 指令上传作业结果。 正常运行完毕的结果应会出现【XXXXXX_aa:bb:cc:dd:ee:ff_unitNN】字样。若需要查阅自己上传数据的时间, 请在操作系统上面使用浏览器查找: http://192.168.251.254 检查相对应的课程文件。 相关流程请参考: vbird_book_check_unit