5.6 su命令与sudo服务
各位读者在实验环境中很少遇到安全问题,并且为了避免因权限因素导致配置服务失败,从而建议使用root管理员来学习本书,但是在生产环境中还是要对安全多一份敬畏之心,不要用root管理员去做所有事情。因为一旦执行了错误的命令,可能会直接导致系统崩溃,这样一来,不但客户指责、领导批评,没准奖金也会鸡飞蛋打。但转头一想,尽管Linux系统为了安全性考虑,使得许多系统命令和服务只能被root管理员来使用,但是这也让普通用户受到了更多的权限束缚,从而导致无法顺利完成特定的工作任务。
su命令可以解决切换用户身份的需求,使得当前用户在不退出登录的情况下,顺畅地切换到其他用户,比如从root管理员切换至普通用户:
[root@linuxprobe ~]# su - linuxprobe [linuxprobe@linuxprobe ~]$ id uid=1000(linuxprobe) gid=1000(linuxprobe) groups=1000(linuxprobe) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
细心的读者一定会发现,上面的su命令与用户名之间有一个减号(-),这意味着完全切换到新的用户,即把环境变量信息也变更为新用户的相应信息,而不是保留原始的信息。强烈建议在切换用户身份时添加这个减号(-)。
另外,当从root管理员切换到普通用户时是不需要密码验证的,而从普通用户切换成root管理员就需要进行密码验证了;这也是一个必要的安全检查:
[linuxprobe@linuxprobe ~]$ su - root Password: 此处输入管理员密码 [root@linuxprobe ~]#
尽管像上面这样使用su命令后,普通用户可以完全切换到root管理员身份来完成相应工作,但这将暴露root管理员的密码,从而增大了系统密码被黑客获取的几率;这并不是最安全的方案。
刘遄老师接下来将介绍如何使用sudo命令把特定命令的执行权限赋予给指定用户,这样既可保证普通用户能够完成特定的工作,也可以避免泄露root管理员密码。我们要做的就是合理配置sudo服务,以便兼顾系统的安全性和用户的便捷性。
Tips
授权原则:在保证普通用户完成相应工作的前提下,尽可能少地赋予额外的权限。
sudo命令用于给普通用户提供额外的权限,语法格式为:“ sudo [参数] 用户名”。
使用sudo命令可以给普通用户提供额外的权限来完成原本只有root管理员才能完成的任务。可以限制用户执行指定的命令、记录用户执行过的每一条命令、集中的管理用户与权限(/etc/sudoers)以及验证密码后一段时间内免验证的方便措施。常见的sudo命令可用参数如表5-10所示:
表5-10 sudo命令中的可用参数以及作用
参数 | 作用 |
-h | 列出帮助信息 |
-l | 列出当前用户可执行的命令 |
-u 用户名或UID值 | 以指定的用户身份执行命令 |
-k | 清空密码的有效时间,下次执行sudo时需要再次进行密码验证 |
-b | 在后台执行指定的命令 |
-p | 更改询问密码的提示语 |
当然,如果担心直接修改配置文件会出现问题,则可以使用sudo命令提供的visudo命令来配置用户权限。
visudo命令用于编辑配置用户sudo权限文件,语法格式为:“ visudo [参数]”。
这是一条会自动调用vi编辑器来配置/etc/sudoers权限文件的命令,能够解决多个用户同时修改权限而导致的冲突问题,不仅如此,visudo命令还可以对配置文件内的参数进行语法检查,在发现参数错误时进行报错提醒,比用户直接修改文件更友好、安全、方便。
>>> /etc/sudoers: syntax error near line 1 <<< What now? Options are: (e)dit sudoers file again e(x)it without saving changes to sudoers file (Q)uit and save changes to sudoers file (DANGER!)
使用visudo命令配置权限文件时,其操作方法与Vim编辑器中用到的方法完全一致,因此在编写完成后记得在末行模式下保存并退出。配置权限文件时,按照下面的格式将第101行(大约)填写上指定的信息:
谁可以使用 允许使用的主机=(以谁的身份) 可执行命令的列表
谁可以使用:稍后要为那位用户进行命令授权。
允许使用的主机:可以填写ALL代表不限制来源主机,亦可填写如192.168.10.0/24的网段限制来源地址,只有从允许网段登录时才能使用sudo命令。
以谁的身份:可以填写ALL代表系统最高权限,也可以是另外一位用户的名字。
可执行命令的列表:可以填写ALL代表不限制命令的列表,亦可填写如/usr/bin/cat的文件名称来限制命令列表,多个命令文件之间用逗号(,)间隔。
在Linux系统中配置服务文件时,虽然没有硬性规定,但从经验来讲新增的参数位置不建议太靠上,避免服务一些必要的功能没加载完成时,我们填写的新参数不被执行成功。一般会在配置文件中找一下相似的参数,然后在相邻位置进行新的修改,或者选择文件的中下部位置。
[root@linuxprobe ~]# visudo 99 ## Allow root to run any commands anywhere 100 root ALL=(ALL) ALL 101 linuxprobe ALL=(ALL) ALL
在填写完毕后记得要先保存再退出,然后切换至指定的普通用户身份,此时就可以用sudo -l命令查看到所有可执行的命令了(下面的命令中,验证的是该普通用户的密码,而不是root管理员的密码,请读者不要搞混了):
[root@linuxprobe ~]# su - linuxprobe [linuxprobe@linuxprobe ~]$ sudo -l We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. [sudo] password for linuxprobe: 此处输入linuxprobe用户的密码 Matching Defaults entries for linuxprobe on localhost: !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin User linuxprobe may run the following commands on localhost: (ALL) ALL
接下来是见证奇迹的时刻!作为一名普通用户,是肯定不能看到root管理员的家目录(/root)中的文件信息的,但是,只需要在想执行的命令前面加上sudo命令就行了:
[linuxprobe@linuxprobe ~]$ ls /root ls: cannot open directory '/root': Permission denied [linuxprobe@linuxprobe ~]$ sudo ls /root anaconda-ks.cfg Documents initial-setup-ks.cfg Pictures Templates Desktop Downloads Music Public Videos
效果立竿见影!但是考虑到生产环境中不允许某个普通用户拥有整个系统中所有命令的最高执行权(这也不符合前文提到的权限赋予原则,即尽可能少地赋予权限),因此ALL参数就有些不合适了。因此只能赋予普通用户具体的命令以满足工作需求,这也受到了必要的权限约束。如果需要让某个用户只能使用root管理员的身份执行指定的命令,切记一定要给出该命令的绝对路径,否则系统会识别不出来,这时可以先使用whereis命令找出命令所对应的保存路径:
[linuxprobe@linuxprobe ~]$ exit logout [root@linuxprobe ~]# whereis cat cat: /usr/bin/cat /usr/share/man/man1/cat.1.gz /usr/share/man/man1p/cat.1p.gz [root@linuxprobe ~]# whereis reboot reboot: /usr/sbin/reboot /usr/share/man/man2/reboot.2.gz /usr/share/man/man8/reboot.8.gz
然后使用visudo命令继续编辑权限文件,将原先101行所新增的参数作如下修改,多个命令之间用逗号(,)间隔。
[root@linuxprobe ~]# visudo 99 ## Allow root to run any commands anywhere 100 root ALL=(ALL) ALL 101 linuxprobe ALL=(ALL) /usr/bin/cat,/usr/sbin/reboot
在编辑好后依然是先保存再退出。再次切换到指定的普通用户,然后尝试正常查看某个系统文件的内容,此时系统提示没有权限(Permission denied)。再使用sudo命令就能顺利地查看文件内容了:
[root@linuxprobe ~]# su - linuxprobe [linuxprobe@linuxprobe ~]$ cat /etc/shadow cat: /etc/shadow: Permission denied [linuxprobe@linuxprobe ~]$ sudo cat /etc/shadow [sudo] password for linuxprobe: 此处输入linuxprobe用户的密码 root:$6$tTbuw5DkOPYqq.vI$RMk9FCGHoJOq2qAPRURTQm.Qok2nN3yFn/i4f/falVGgGND9XoiYFbrxDn16WWiziaSJ0/cR06U66ipEoGLPJ.::0:99999:7::: bin:*:17784:0:99999:7::: daemon:*:17784:0:99999:7::: adm:*:17784:0:99999:7::: lp:*:17784:0:99999:7::: sync:*:17784:0:99999:7::: shutdown:*:17784:0:99999:7::: halt:*:17784:0:99999:7::: ………………省略部分输出信息……………… [linuxprobe@linuxprobe ~]$ exit logout
大家千万不要以为到这里就结束了,刘遄老师还有更压箱底的宝贝。不知大家是否发觉在每次执行sudo命令后都会要求验证一下密码。虽然这个密码就是当前登录用户的密码,但是每次执行sudo命令都要输入一次密码其实也挺麻烦的,这时可以添加NOPASSWD参数,使得用户下次再执行sudo命令时就不用密码验证啦~
[root@linuxprobe ~]# visudo 99 ## Allow root to run any commands anywhere 100 root ALL=(ALL) ALL 101 linuxprobe ALL=(ALL) NOPASSWD:/usr/bin/cat,/usr/sbin/reboot
这样,当切换到普通用户后再执行命令时,就不用再频繁地验证密码了,我们在日常工作中也就痛快至极了。
[root@linuxprobe ~]# su - linuxprobe [linuxprobe@linuxprobe ~]$ reboot User root is logged in on tty2. Please retry operation after closing inhibitors and logging out other users. Alternatively, ignore inhibitors and users with 'systemctl reboot -i'. [linuxprobe@linuxprobe ~]$ sudo reboot
同学们请细心留意上面的用户身份变换,visudo命令只有root管理员才可以执行,普通用户使用会提示权限不足。