用非root身份运行X
大多数人犯下的第一个错误是:一开始就以root身份运行X,无意中一切都变得非常简单——能够直接访问到所有的文件,系统管理任务可以轻松地搞定,能够安装新的软件,等等。
问题在于有许多程序是不应该用root身份运行的。如果你用自己的身份(非root身份)启动文件管理器,然后删除/home,你会丢失自己的所有文件,然后一边寻找备份文件一边不停地抱怨自己。万幸的是所有其他用户的文件都还安然无恙。但是,如果你用root来做同样的事情,马上就会陷入众人的抱怨和诅咒之中。
文件共享程序也同样不应该用root身份运行。如果有人找出了Irc或者Gnutella程序的漏洞,他们最多只能偷窃你自己的文件。但如果你用root来运行这些程序,所有用户的文件将完全暴露在他们的眼前,包括最最重要的/etc/shadow密码文件,以及你同事的私人邮件。这可不是什么好事。
所以,请务必用你自己的帐号来运行X,用本文下面介绍的方法来运行那些必须使用root才能运行的任务。
su和su -
假设有人占据了拨号线路,我们想知道那个家伙到底是谁。tcpdump会显示出线路上的数据包传输情况,我们来试试下面这个命令:
[wstearns@sparrow wstearns] $ tcpdump -i ppp0 -qtn
tcpdump: socket: Operation not permitted
哦,对了。这个shell和所有其他X下的程序一样,都用wstearns运行。你会想我可以从命令行提示看出来,不是吗?:-)
不过,我可不想只为了一个命令从X完全退出。su命令让我们用另外一个用户临时地替代当前用户。如果不指定自己想成为哪一个用户,则su默认我们想成为root。不要吓起哄说什么黑客技术,除非当前用户就是root,否则还是老老实实给su提供目标用户的密码。:-)
[wstearns@sparrow wstearns] $ tcpdump -i ppp0 -qtn
tcpdump: socket: Operation not permitted
[wstearns@sparrow wstearns] $ su - Password: < 输入root的密码 >
[root@sparrow /root]# tcpdump -i ppp0 -qt
User level filter, protocol ALL, datagram packet socket
tcpdump: listening on ppp0
< reflectix.xs4all.nl.29788 > ME.33085: tcp 1448 (DF) [tos 0x10]
> ME.33085 > reflectix.xs4all.nl.29788: tcp 0 (DF)
< reflectix.xs4all.nl.29788 > ME.33085: tcp 1448 (DF) [tos 0x10]
> ME.33085 > reflectix.xs4all.nl.29788: tcp 0 (DF)
< reflectix.xs4all.nl.29788 > ME.33085: tcp 1448 (DF) [tos 0x10]
> ME.33085 > reflectix.xs4all.nl.29788: tcp 0 (DF)
< reflectix.xs4all.nl.29788 > ME.33085: tcp 1448 (DF) [tos 0x10]
7 packets received by filter
[root@sparrow /root]# exit
[wstearns@sparrow wstearns] $
哦,原来是我自己下载文件占用了拨号线路。呵呵。
你或许已经注意到,上面这个例子使用的是su -而不是su。“-”将提供目标用户的环境来替代当前用户的环境。下面这个例子很明确地说明了这一点,不用su -时shell不能在/sbin和/usr/sbin下找到我们要执行的命令:
[wstearns@sparrow wstearns] $ su
Password: < 输入root的密码 >
[root@sparrow wstearns]# tcpdump -i ppp0 -qt
bash: tcpdump: command not found
[root@sparrow wstearns]# exit
[wstearns@sparrow wstearns] $
在这个例子中,我仍旧留在当前的wstearns目录,没有进入root的默认目录。另外,由于/usr/sbin不在我的路径中,我得指定tcpdump的完整路径。这样看来,一般情况下还是使用“su -”更方便一点。
su - -c <命令>
如果你确实只需执行一个命令,下面还有一种更快的方法。-c选项告诉su运行指定的命令然后立即返回到原来的用户:
[wstearns@sparrow wstearns] $ whoami
wstearns
[wstearns@sparrow wstearns] $ su - -c whoami
Password: < 输入root的密码 >
root
[wstearns@sparrow wstearns] $
su的man文档有关于该命令及其命令行选项的更多说明。
sudo
上面的su命令也有缺点,这就是我们必须在每次运行某个命令的时候输入一下密码。更糟糕的是,要输入的密码还是root的密码!
如果要为级别较低的管理员授权,比如授予他们在系统中增加新用户的权限,应该怎么办?你可以让他们使用su,但如果你把root的密码也给了他们,他们马上就是高级管理员了。:-(
sudo不仅解决了这个问题,而且还提供更多的功能。下面我们要在系统上安装一个新的rpm:
[wstearns@sparrow updates-sparrow] $ rpm -Uvh cyrus-sasl-1.5.24-11.i386.rpm
cannot open Packages index using db3 - Permission denied (13)
-- >The rpm database cannot be opened in db3 format.
If you have just upgraded the rpm package you need to convert
your database to db3 format by running "rpm --rebuilddb" as root.
error: cannot open Packages database in /var/lib/rpm
[wstearns@sparrow updates-sparrow] $
rpm说不能打开数据库,所以不能安装新软件。
[wstearns@sparrow updates-sparrow] $ sudo rpm -Uvh cyrus-sasl-1.5.24-11.i386.rpm
Password: < 输入wstearns的密码 >
cyrus-sasl ##################################################
[wstearns@sparrow updates-sparrow] $
这看起来有点象su - -c,是吧?我在sudo命令中指定了要它执行的命令,sudo用root身份来执行这个命令。但这里我只要输入自己的密码,而不是root的密码。从这点来看,sudo是一个比su更有用的工具。
如果我在5分钟之内执行另外一个命令,不再需要输入自己的密码:
[wstearns@sparrow updates-sparrow] $ sudo rpm --erase cyrus-sasl
[wstearns@sparrow updates-sparrow] $
sudo也把所有的命令记录到了/var/log/secure:
Oct 29 22:26:49 sparrow sudo: wstearns : TTY=pts/21 ; PWD=/mnt/redhat ; USER=root ; COMMAND=/bin/rpm -Uvh cyrus-sasl-1.5.24-11.i386.rpm
Oct 29 22:30:03 sparrow sudo: wstearns : TTY=pts/21 ; PWD=/mnt/redhat ; USER=root ; COMMAND=/bin/rpm --erase cyrus-sasl
在普通用户能够使用sudo之前,root必须声明哪些用户可以用root身份执行哪些命令。在下面这个例子中,假定root决定允许我安装新软件、卸下驱动器。root运行visudo命令编辑/etc/sudoers,修改完成后,visudo将检查该文件以保证不存在语法错误。下面是这个/etc/sudoers文件的内容:
# User privilege specification
rootALL=(ALL) ALL wstearns ALL=(root) /bin/rpm,/bin/umount
如果我试图执行其他命令,sudo将拒绝执行命令并在/var/log/secure登记我的这一企图:
[wstearns@sparrow wstearns] $ sudo mcedit test
Sorry, user wstearns is not allowed to execute '/usr/bin/mcedit test' as root on sparrow.
[wstearns@sparrow wstearns] $ su - -c 'tail --lines=1 /var/log/secure'
Password: < 输入root的密码 >
Oct 29 22:46:53 sparrow sudo: wstearns : command not allowed ; TTY=pts/21 ; PWD=/home/wstearns ; USER=root ; COMMAND=/usr/bin/mcedit test
[wstearns@sparrow wstearns] $
授予sudo权限时一定要小心。在上面这个例子中,root授权我安装和删除rpm软件包,此时如果我怀有恶意,就可以用带有特洛伊木马/bin/login的软件包取代系统上的正常软件包,下次root登录时,/bin/login就可以把root使用的密码发送给我。即使只授予某个用户在sudo下运行less的权限,也使得该用户能够从less通过!命令得到root身份的shell。
在授予任何人通过sudo执行某个命令的权限之前,一定要仔细地考虑一下所有滥用该权限的可能。他们能够用自己的文件替换/etc/passwd或/etc/shadow吗?当运行dd、tar、ln和任何文本编辑器的用户是root时,它们都属于这类危险的命令。
和su一样,请参见sudo、visudo、sudoers的man文档了解更多信息。
vlock -a
如果我同时登录了多个终端,现在想要离开一下去倒杯咖啡,却又不想从所有终端注销然后再在几分钟后重新登录,特别当那些终端上运行着程序时更是如此。为此,我可以在某个空闲的终端上运行vlock -a:
[wstearns@sparrow wstearns] $ vlock -a
The entire console display is now completely locked.
You will not be able to switch to another virtual console.
Please enter the password to unlock.
wstearns's Password: < 输入wstearns的密码 >
[wstearns@sparrow wstearns] $
vlock并不使我从系统注销,也不会中止我正在运行的任何程序,它只是不让用户再在该终端上输入任何命令。另外,使用-a选项之后,vlock也禁止用户在输入密码之前切换到其他终端,这就保护了所有其他终端。
注意该操作要在控制台进行,-a选项不能在xterm下使用。请查看man vlock了解更多信息。