Linux sudo 详解

        用 su 可以切换用户身份,如果每个普通用户都能切换到 root 身份,如果某个用户不小心泄漏了 root 密码,那么系统是非常的不安全的。为了改进这个问题,产生了 sudo 这个命令。

        使用 sudo 执行一个 root 才能执行的命令是可以办到的,但是需要输入密码,这个密码并不是 root 的密码,而是用户自己的密码。默认只有 root 用户能使用 sudo 命令,普通用户想要使用 sudo ,是需要 root 预先设定的。使用 visudo 命令去编辑相关的配置文件 /etc/sudoers 。如果没有 visudo 这个命令,使用 yum 安装:

1
yum install -y sudo

语法

1
sudo [选项] [参数]

选项

        -b:在后台执行指令;
        -h:显示帮助;
        -H:将HOME环境变量设为新身份的HOME环境变量;
        -k:结束密码的有效期限,也就是下次再执行sudo时便需要输入密码;。
        -l:列出目前用户可执行与无法执行的指令;
        -p:改变询问密码的提示符号;
        -s:执行指定的shell;
        -u<用户>:以指定的用户作为新的身份。若不加上此参数,则预设以root作为新的身份;
        -v:延长密码有效期限5分钟;
        -V :显示版本信息。

参数

        指令:需要运行的指令和对应的参数。

配置 sudo

        默认 root 能够 sudo 是因为这个文件中有一行 “root ALL=(ALL) ALL” 在该行下面加入 “test ALL=(ALL) ALL” 就可以让 test 用户拥有了 sudo 的权利。使用 “visudo” 命令编辑 /etc/sudoers 配置文件,其实操作方法和 “vim” 命令使用方法是一样的,按 “i” 进入编辑模式,编辑完成后,按 “Esc” ,再输入 “:wq” 完成保存。

1
2
3
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
test ALL=(ALL) ALL

        此时可以验证一下 test 账户的权限了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost ~]# su test
[test@localhost root]$ ls
ls: 无法打开目录.: 权限不够
[test@localhost root]$ sudo ls
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 test:
123 456 789 anaconda-ks.cfg dirb install.log install.log.syslog test test1 test2 test3

        由于切换到 test 账户后的当前目录依旧是在 /root 下, test 账户没有任何权限,所以 ‘ls’ 的时候提示说权限不够,然而使用 sudo ls 输入 test 账户自身的密码后就有权限了。初次使用 sudo 时会有上面的一大段提示,而后再次使用 sudo 命令则不再提示。
        如果每增加一用户就设置一行,这样太麻烦了。所以可以这样设置。把 “#%wheel ALL=(ALL) ALL” 前面 ‘#’ 去掉,让这一行生效。意思是, wheel 这个组的所有用户都拥有了 sudo 权利。接下来只需要把想让 sudo 权利的所有用户加入到 wheel 这个组中即可:

1
2
## Allows people in group wheel to run all commands
%wheel ALL=(ALL) ALL

        配置文件 /etc/sudoers 包含了诸多配置项,可以使用 man sudoers 来获得帮助信息。

实例

        配置 sudo 必须通过编辑 /etc/sudoers 文件,而且只有超级用户才可以修改它,还必须使用 visudo 编辑。之所以使用 visudo 有两个原因:

  1. 它能后防止一两个用户同时修改它;
  2. 它也能进行有限的语法检查。

        所以,即时只有一个超级用户,也最好用 visudo 来检查一下语法。

        visudo 默认的是在 vi 里打开配置文件,用 vi 来修改文件。可以在编译时修改这个默认项。 visudo 不会擅自保存带有语法错误的配置文件,它会提示出现的问题,并询问该如何处理:

1
>>> sudoers file: syntax error, line 22 <<

        此时有三种选择:

  1. 键入 “e” 是重新编辑
  2. 键入 “x” 是不保存退出
  3. 键入 “Q” 是退出并保存

        如果选择 Q ,那么 sudo 将不回再运行,知道错误被纠正。
        需求是把 Linux 服务器设置成:只允许使用普通账户登录,而普通账户登录后,可以不输入密码就能 sudo 切换到 root 账户。

1
[root@localhost ~]# visudo

        然后在文件的最后面加三行:

1
2
3
User_Alias USER_SU = test, test1, yanyi
Cmnd_Alias SU = /bin/su
USER_SU ALL=(ALL) NOPASSWD: SU

        保存配置文件后,使用 test 、test1 、yanyi 三个账户登录 Linux 后,执行命令 sudo su - 切换到 root 账户,获取 root 账户的所有权利。

1
2
3
4
[root@localhost ~]# su - test
[test@localhost ~]$ sudo su -
[root@localhost ~]# whoami
root

日志与安全

        sudo 为安全考虑得很周到,不仅可以记录日志,还能在有必要时向系统管理员报告。但是, sudo 的日志功能不是自动的,必须由管理员开启。

1
2
touch /var/log/sudo
vi /etc/syslog.conf

        在 syslog.conf 最后面加一行(必须用 tab 分隔开)并保存:

1
local2.debug /var/log/sudo

        重启日志守候进程

1
ps aux | grep syslogd

        把得到的 syslog 进程的 PID (输出的第二列是 PID)填入下面

1
kill -HUP PID

        这样 sudo 就可以写日志了:

1
2
3
4
5
[foobar@localhost ~]$ sudo ls /rootanaconda-ks.cfg
Desktop install.log
install.log.syslog
$cat /var/log/sudoJul 28 22:52:54 localhost sudo: foobar :
TTY=pts/1 ; pwd=/home/foobar ; USER=root ; command=/bin/ls /root

        不过,有个小小的“缺陷”,sudo 记录日志并不是很忠实:

1
2
3
[foobar@localhost ~]$ sudo cat /etc/shadow > /dev/null
cat /var/log/sudo...Jul 28 23:10:24 localhost sudo: foobar : TTY=pts/1 ;
PWD=/home/foobar ; USER=root ; COMMAND=/bin/cat /etc/shadow

        重定向没有被记录在日志里,因为在命令运行之前,shell 把重定向的工作做完了,sudo 根本就没有看到重定向。这样也有个好处,下面的手段不回得逞:

1
[foobar@localhost ~]$ sudo ls /root > /etc/shadowbash: /etc/shadow: 权限不够

        sudo 有自己的方式来保护安全。以 root 的身份执行 sudo -v ,查看 sudo 的设置。因为考虑到安全问题,一部分环境变量并没有传递给 sudo 后面的命令,或者被检查后再传递的,比如:PATH 、HOME 、SHELL 等。当然也可以通过 sudoers 来配置环境变量。

sudo -i 也可以登录到 root

        sudo : 暂时切换到超级用户模式以执行超级用户权限,提示输入密码时该密码为当前用户的密码,而不是超级账户的密码。不过有时间限制,Ubuntu默认为一次时长15分钟。

        su : 切换到某某用户模式,提示输入密码时该密码为切换后账户的密码,用法为“su 账户名称”。如果后面不加账户时系统默认为root账户,密码也为超级账户的密码。没有时间限制。

        sudo -i: 为了频繁的执行某些只有超级用户才能执行的权限,而不用每次输入密码,可以使用该命令。提示输入密码时该密码为当前账户的密码。没有时间限制。执行该命令后提示符变为“#”而不是“$”。想退回普通账户时可以执行“exit”或“logout” 。

        还有几个类似的用法:

        sudo /bin/bash : 这个命令也会切换到root的bash下,但不能完全拥有root的所有环境变量,比如PATH,可以拥有root用户的权限。这个命令和 sudo -s 是等同的。

        sudo -s : 如上

        sudo su : 这个命令,也是登录到了root,但是并没有切换root的环境变量,比如PATH。

        sudo su - : 这个命令,纯粹的切换到root环境下,可以这样理解,先是切换到了root身份,然后又以root身份执行了 su - ,这个时候跟使用root登录没有什么区别。这个结果貌似跟sudo -i 的效果是一样的,但是也有不同,sudo 只是临时拥有了root的权限,而su则是使用root账号登录了linux系统。

        所以,我们再来总结一下:

  1. sudo su - 约等于 sudo -i
  2. sudo -s 完全等于 sudo /bin/bash 约等于 sudo su
  3. sudo 终究被一个”临时权限的帽子”扣住,不能等价于纯粹的登录到系统里。