# 使用者身份切换

身份变化可能有以下几个原因:

  • 使用一般账户:系统平时操作的好习惯

    为了安全,一般都会建议尽量以一般身份使用者来操作 Linux 的日常工作。等到需要设置系统环境时,才切换成 root 来管理系统,相对比较安全,避免误操作一些严重的指令,例如 rm -rf /

  • 用较低权限启动系统服务

    比如:apache 软件,创建一个 apache 用户来启动它,就算该软件被攻破了,至少不至于损坏整个系统;

  • 软件本身的限制

    在远古时代的 telnet 程序中,默认是不允许使用 root 身份登录的,若发现是 UID=0 的登录直接拒绝登录;此外 ssh 也可以设置拒绝 root 登录的

由于上述考虑,没有系统设定等的特殊需求下,都是使用的一般账户登录,如果有则可以变换身份,主要有两种方式:

  • su:以 su - 指令直接将身份变成 root

    该指令需要 root 密码,输入验证成功后才可以切换成 root 身份

  • sudo:以 sudo 指令 执行指令串

    由于 sudo 需要实现设置,且 sudo 需要输入用户自己的密码,因此多人共同管理同一部主机时, sudo 要比 su 好,至少 root 密码不会流传出去

# su

最简单的身份切换指令,可以进行任何身份的切换

su [-lm] [-c 指令] [username]
1

选项与参数:

  • -:单纯使用 su - 表示使用 login-shell 的变量文件读取方式来登录系统,若使用者名称没有加上去,则代表切换为 root 身份
  • -l:与 - 类似,单后面需要加要切换的使用者账户,也是 login-shell 的方式
  • m:与 -p 是一样的,表示:使用目前的环境设置,而不读取新使用者的配置文件
  • -c:仅进行一次指令,所以 -c 后面可以加上指令

前面讲解过 login-shell 是啥,这里有没有加上 - 的指令涉及到了 login-shell 与 non-login shell 的变量读取方式,下面以例子说明

# 范例 1: 假设现在身份是 mrcode , 想要使用 non-login shell 的方式变成 root
[mrcode@study ~]$ su			# 注意提示字符是 mrcode 身份
Password: 
[root@study mrcode]# id	
# id 识别的确是 root 身份
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

# 查看环境变量中
[root@study mrcode]# env | grep 'mrcode'
HOSTNAME=study.centos.mrcode
USER=mrcode			# 当前用户还是 mrcode
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mrcode/.local/bin:/home/mrcode/bin		# 这个影响最大,只找了 /home/mrcode
MAIL=/var/spool/mail/mrcode		# 信箱也是
PWD=/home/mrcode				# 也并非是 root 的家的目录
LOGNAME=mrcode
XDG_DATA_DIRS=/home/mrcode/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
# 虽然 UID 已经具有 root 的身份,但是还有一堆变量是原本 mrcode 的身份,所以还是有很多数据无法直接利用

# 离开当前的 su 环境
[root@study mrcode]# exit
exit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

所以单纯的使用 su 切换成 root 方式,。读取的变量设定方式为 non-login shell 的方式,这种方式很多原本的变量不会被改变,尤其是很重要的 PATH 变量,由于没有改变为 root 环境,因此很多 root 管惯用的指令就只能使用绝对路径来执行。所以执行切换身份时,务必使用以下范例

# 范例 2:使用 login shell 的方式切换为 root 的身份并观察变量
[mrcode@study ~]$ su -
Password: 					# 输入 root 密码登录
Last login: Tue Feb 25 10:47:26 CST 2020 on pts/1
[root@study ~]# env | grep root
USER=root
MAIL=/var/spool/mail/root
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
XAUTHORITY=/root/.xauthL0s7Pj
# 可以看到环境变量都变成 root 的了
[root@study ~]# env | grep mrcode
HOSTNAME=study.centos.mrcode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

同样可以使用 exit 指令离开 root 身份,如果只是想使用 root 执行一次命令,就恢复原本的身份可以使用 -c 选项

# 范例 3:mrcode 要执行  hread -n 3 /etc/shadow 一次,已知 root 密码
[mrcode@study ~]$ head -n 3  /etc/shadow
head: cannot open '/etc/shadow' for reading: Permission denied
[mrcode@study ~]$ su - -c "head -n 3 /etc/shadow"
Password: 				# 输入 root 密码
root:$6$eC75oi.rU.wJPhgN$C.C.qFXTvmJ64qFnez88TdcsHuuQAqtAYrukgBYBspgSZbCgzvJuv4OVJ9gaEfA2/.T7e68AZW7RoZt6ubeHD0::0:99999:7:::
bin:*:17834:0:99999:7:::
daemon:*:17834:0:99999:7:::
[mrcode@study ~]$ 				# 注意看这里的身份还是 mrcode

1
2
3
4
5
6
7
8
9
10

那么怎么切换为其他账户呢?

# 范例 4:原本是 mrcode 使用者,想要变换身份为 mrcode1

[mrcode@study ~]$ su -l mrcode1
Password: 				# 输入 mrcode1 的密码
Last login: Mon Feb 24 17:35:35 CST 2020 from 192.168.4.170 on pts/2
[mrcode1@study ~]$ su -			
密码:				# 输入 root 的密码,切换到 root
上一次登录:二 225 10:58:09 CST 2020pts/1 上
[root@study ~]# id sshd			# 查看这个账户,发现有该账户
uid=74(sshd) gid=74(sshd)=74(sshd)
[root@study ~]# su -l sshd			
This account is currently not available.  # 提示无法切换到 sshd
[root@study ~]# finger sshd		# 查看他的信息如下
Login: sshd           			Name: Privilege-separated SSH
Directory: /var/empty/sshd          	Shell: /sbin/nologin		# 这里的 nologin 问题
Last login 二 225 11:00 (CST) on pts/1
No mail.
No Plan.
[root@study ~]# exit
登出		# 离开第 2 次的 su
[mrcode1@study ~]$ exit
登出		# 离开第 1 次的 su
[mrcode@study ~]$ 		# 这里又回到了最初的 mrcode  身份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 小结用法

  • 若要完整的切换到新使用者的环境,比如要使用 su - username 或 su -l username,才会连同 PATH、USER、MAIL 等变量都转成新用户的环境
  • 如果仅想要执行一次 root 的指令,可以利用 su -c "指令串" 的方式来处理
  • 使用 root 切换称为任何使用者时,并不需要输入新用户的密码

# sudo

相对于 su 需要了解切换用户的密码(常常是 root 的密码),而 sudo 的执行仅需要自己的密码,还可以设置不需要密码就可以执行 sudo;由于 sudo 可以让你以其他用户的身份执行指令,(通常是利用 root 身份执行命令),所以并非所有人都能够执行 sudo,而是需要规范到 /etc/sudoers内的用户才能够执行 sudo 指令

TIP

一般用户能够具有 sudo 的使用权,是经过管理员审核通过后,也就是受信任的账户,否则一般用户默认是不能操作 sudo 的

# sudo 的指令用法

由于系统默认仅有 root 可以执行 sudo,因此下面的范例先使用 root 来执行。等谈到 visudo 时,再已一般使用者来讨论其他 sudo 的用法

TIP

最初情况下是只有 root 能执行 sudo 的,但是在安装 CentOs 时,创建了一个用户,这个用户也具有 sudo 的权限

sudo [-b][-u 新使用者账户]

选项与参数:
	-b:将后续的指令放到背景中让系统自动执行,而不与目前的 shell 产生影响
	-u:后面可以接要切换的使用者账户,若没此项,则表示切换到 root 身份
1
2
3
4
5
# 范例 1:想要以 sshd 的身份在 /tmp 下创建一个名为 myssh 的文件
[root@study ~]# sudo -u sshd touch /tmp/mysshd
您在 /var/spool/mail/root 中有新邮件
[root@study ~]# ll /tmp/mysshd 
-rw-r--r--. 1 sshd sshd 0 225 13:04 /tmp/mysshd
# 可以看到是由 ssh 创建的

# 范例 2:以 mrcode1 的身份创建 ~Vbird1/www 并在其中创建 index.html 文件
[root@study ~]# sudo -u mrcode1 sh -c "mkdir ~mrcode1/www; cd ~mrcode1/www; echo 'This is index.html'  > index.html"
[root@study ~]# ll -a ~mrcode1/www/
总用量 4
drwxr-xr-x. 2 mrcode1 mrcode1  24 225 13:15 .
drwx------. 7 mrcode1 mrcode1 201 225 13:15 ..
-rw-r--r--. 1 mrcode1 mrcode1  19 225 13:15 index.html
# 注意上面 那个 sh -c ""  这一串不是 sudo 的参数,是指令;sh --help 可以看到 sh -c "指令串",是利用 sh 执行命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

范例 2 使用 sh -c 来执行多重指令。

为什么 sudo 预设仅有 root 能使用?是因为 sudo 的执行流程如下:

  1. 当用户执行 sudo 时,系统与 /etc/sudoers 文件中搜索该使用者是否有执行 sudo 的权限
  2. 若使用者具有可执行 sudo 的权限后,便让使用者「输入用户自己的密码」来确认
  3. 若密码输入成功,变开始进行 sudo 后续接的指令(root 执行 sudo 时不需要密码)
  4. 若要切换的身份与执行者身份相同,也不需要输入密码

所以是否能使用 sudo ,必须要看 /etc/sudoers 中是否有配置,这种文件都有自己的规范,所以提供了一个 visudo 指令来帮助管理该文件

# visudo 与 /etc/sudoers

使用 visudo 来修改,在结束离开时,会校验 /etc/sudoers 的语法,来避免修改错误的语法导致 sudo 无法使用

一般来说,visduo 的设置方式有几种简单的方法,下面介绍几个简单的例子来说明

# 单一用户使用 sudo

单一用户可进行 root 所有指令,与 sudoers 文件语法:

# 让 mrcode1 账户可以使用 root 的任何指令,基本上有两种方式:
# 1. 直接修改 /etc/sudoers
[root@study ~]# visudo 
:set nu			# 显示行号
    100 root    ALL=(ALL)       ALL
    101 mrcode1 ALL=(ALL)       ALL			# 在 100 行后,添加 mrcode1 的数据
# 然后保存离开
1
2
3
4
5
6
7

其实 visudo 利用 vi 将文件打开修改。

使用者账户	登陆者的来源主机名=(可切换的身份)	可下达的指令
root    	ALL=(ALL)       				ALL
1
2

各字段含义如下:

  1. 使用者账户:系统中那个账户可以使用 sudo 指令
  2. 登陆者的来源主机名:就是信任哪一台网络主机可以联机,这个值可以指定客户端计算机。默认的 ALL 是允许任何一台网络主机
  3. 可切换的身份:这个账户可以切换成什么身份来下达后续的指令。默认 root 可以切换成任何人
  4. 可下达的指令:可用该身份下达什么指令?这个指令请务必使用绝对路径,预设 root 可以切换任何身份且下达任何指令

All 是特殊的关键词,代表任何身份、主机、指令

# 进行测试
[mrcode1@study ~]$ tail -n 1 /etc/shadow		# 这里是 mrcode1 登录的
# 提示权限不足
tail: cannot open '/etc/shadow' for reading: Permission denied

# 使用 sudo 来执行
[mrcode1@study ~]$ sudo tail -n 1 /etc/shadow

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 mrcode1: 				# 然后输入 mrcode1 自己的密码,就可以执行了
pro3:$6$oku6c8Az$GUOVL1SkmFnSnVHvUCKnToNv8l7094dQ17/GOw/R5mdxqiE0THtkFaO4GpzFMxJy30rZbpWgQcNSpMqHN8KWT/:18316:0:99999:7:::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

利用 wheel 群组以及免密码的功能处理 visudo

# wheel 群组使用 sudo

之前曾建立过 pro1、pro2、pro3 让这 3 个用户也可以使用 sudo,但是通过群组的方式来支持

# 1. 使用 visudo 设置 whell 群组
visudo

     99 ## Allow root to run any commands anywhere
    100 root    ALL=(ALL)       ALL
    101 mrcode1 ALL=(ALL)       ALL
    102 
    103 ## Allows members of the 'sys' group to run networking, software,
    104 ## service management apps and more.
    105 # %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS
    106 
    107 ## Allows people in group wheel to run all commands
    108 %wheel  ALL=(ALL)       ALL
    
# 在最左边增加 % 表示是一个群组,注意在编辑的时候,当时笔者吧 $wheel 这一行写在 上面 root 后面,报错就报错说有语法错误,不知道是否也有识别,需要写到这个 Allows people in group wheel to run all commands 这一行下面呢?
# 注意: whell 这个配置默认已经配置过了,并且该组也已经存在了。应该是系统初始化就有的

# 2. 将 pro1 添加进 wheel 群组
[root@study ~]# usermod -a -G wheel pro1

# 3. 切换到 pro1 、pro2 并执行 sudo 命令查看
[root@study ~]# su -l pro1
[pro1@study ~]$ sudo tail -n 1 /etc/shadow

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 pro1: 
pro3:$6$oku6c8Az$GUOVL1SkmFnSnVHvUCKnToNv8l7094dQ17/GOw/R5mdxqiE0THtkFaO4GpzFMxJy30rZbpWgQcNSpMqHN8KWT/:18316:0:99999:7:::

# 切换到 pro2 
[root@study ~]# su -l pro2
[pro2@study ~]$ export LANG=C
[pro2@study ~]$ sudo tail -n 1 /etc/shadow

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 pro2: 
pro2 is not in the sudoers file.  This incident will be reported.
# 提示 pro2 不在 sudoers 文件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

那么这里对群组进行了支持,pro2 和 pro3 也要支持 sudo 的话,直接使用 usermod 将他们添加到 wheel 组中即可

前面说安装系统创建的用户,直接设置为了管理员的话,也是可以使用 sudo 指令的,这个操作就是将那个账户添加到了 wheel 组了

[mrcode@study ~]$ id mrcode 
uid=1000(mrcode) gid=1000(mrcode) groups=1000(mrcode),100(users)
[mrcode@study ~]$ id pro1
uid=1505(pro1) gid=1508(pro1) groups=1508(pro1),10(wheel),1507(projecta)

[mrcode@study ~]$ sudo cat /etc/shadow
[sudo] password for mrcode: 
mrcode is not in the sudoers file.  This incident will be reported.

# 我们这里看到,这里的账户并没有加入 wheel 这个组,实际执行 sudo 的话,也会提示不支持;
# 这就说明当时我并没有选择添加为管理员

1
2
3
4
5
6
7
8
9
10
11
12

从 Centos 7 开始, %wheel 这行默认存在,并且也有这个组

# 免密使用 sudo

既然管理员都信任这些用户了,是否可以提供:不需要密码就可以使用 sudo 呢?

[root@study ~]# visudo 
## Allows people in group wheel to run all commands
# %wheel        ALL=(ALL)       ALL


## Same thing without a password
%wheel  ALL=(ALL)       NOPASSWD: ALL
1
2
3
4
5
6
7

找到上述地方,在第三个字段,将 NOPASSWD 哪一行放开,把上面原始的注释掉。也就是在可下达的指令前使用 NOPASSWD: 来标识不需要密码

# 有限制的指令操作

上面的配置可以让使用者利用 root 身份进行任何事情,如果要配置只能够允许进行一部分事情的话,比如 myuser1 只能帮 root 修改其他用户的密码,可以如下做

[root@study ~]# visudo 
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
mrcode1 ALL=(ALL)       ALL
myuser1 ALL=(ALL)       /usr/bin/passwd		# 使用绝对路径,来给定使用的指令


# 再使用 myuser1 来测试是否成功
[myuser1@study ~]$ sudo cat /etc/shadow
[sudo] password for myuser1: 
Sorry, user myuser1 is not allowed to execute '/bin/cat /etc/shadow' as root on study.centos.mrcode.
# 可以看到不支持 /bin/cat 指令

# 再使用 sudo passwd ,发现可以执行
[myuser1@study ~]$ sudo passwd myuser3
Changing password for user myuser3.
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
passwd: all authentication tokens updated successfully.
# 上面修改了 myuser3 的密码

# 这里不加参数,发现可以直接修改 root 的密码,这样就不行了
[myuser1@study ~]$ sudo passwd
Changing password for user root.
New password: 

# 还可以限制指令的参数
myuser1 ALL=(ALL)       !/usr/bin/passwd, !/usr/bin/passwd root, /usr/bin/passwd [A-Za-z]*
# 不可执行的指令添加上了感叹号 !
# 上面直接执行 passwd 和 passwd root 都不允许,后面一个用正则规定了参数,必须使用字母开头的参数

# 测试,就会提示不被允许执行
[myuser1@study ~]$ sudo passwd
Sorry, user myuser1 is not allowed to execute '/bin/passwd' as root on study.centos.mrcode.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 通过别名建立 visudo

比如我有 15 个用户加入刚刚的管理员,那么是否都需要将上述限制命令的代码复制 15 行配置到 visudo 中呢?

可以通过 visudo 的别名功能,可以是:指令别名、账户别名、主机别名等。这里仅介绍账户别名

# 假设 pro1、pro2、pro3 与 myuser1、myuser2 要加入上述的密码管理员的 sudo 列表中
# 那么可以创建一个账户别名为 ADMPW,然后配置该账户别名

## User Aliases
## These aren't often necessary, as you can use regular groups
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
## rather than USERALIAS
# User_Alias ADMINS = jsmith, mikem
User_Alias ADMPW = pro1, pro2, pro3, myuser1, myuser2

## Command Aliases
## These are groups of related commands...
Cmnd_Alias ADMPWCOM = !/usr/bin/passwd, !/usr/bin/passwd root, /usr/bin/passwd [A-Za-z]*

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
mrcode1 ALL=(ALL)       ALL
myuser1 ALL=(ALL)       !/usr/bin/passwd, !/usr/bin/passwd root, /usr/bin/passwd [A-Za-z]*
ADMPW   ALL=(ALL)       ADMPWCOM
# 上面定义了 User_Alias 用户别名 和 Cmnd_Alias 命令别名
# 并在之前配置用户的地方使用上了这两个别名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

别名建议使用大写;后续对用户的维护直接修改别名中的即可

# sudo 的时间间隔问题

如果使用同一个账户在极短时间内重复操作 sudo 来运行指令的话,在第二次执行 sudo 时,并不需要输入自己的密码!也可以正常运行

这是因为有一个机制,sudo 两次操作间隔超过 5 分钟,那么就需要重新输入一次密码。这个机制也是为了安全,比如你输入密码执行过一次 sudo,这个时候去厕所了,超过了 5 分钟还没有回来,防止别人动你的电脑执行 sudo

# sudo 搭配 su 的使用方式

有时候需要大量执行很多 root 的工作,一直使用 sudo 就很麻烦,可以通过下面的方式结合 su,并且还使用用户自己的密码来变成 root

visudo
User_Alias ADMINS = pro1, pro2, pro3, myuser1
ADMINS  ALL=(root)      /bin/su -

# 创建一个 ADMINS 的用户别名,再限制该用户只能切换到 root,并且只能执行 su -
# 注意使用是:用 sudo 命令来执行 su
[pro2@study ~]$ sudo su -
[sudo] password for pro2: 
Last login: Tue Feb 25 15:09:19 CST 2020 on pts/1
[root@study ~]# 		# 看这里的提示,变成了 root

1
2
3
4
5
6
7
8
9
10
11

这个方式是这样的:

  1. 限制了可切换为 root,那么这些用户只能切换到 root
  2. 并且这些用户只能通过 sudo 执行 su - 的操作
  3. sudo 需要输入用户自己的密码,通过之后相当于是 root 身份了,用 root 身份执行 su - 切换到 root 身份,就不需要 root 密码了(root 使用 su 不需要密码)

通过中方式也能授权管理员账户。