了解 Linux root 帐户及使用 sudo

内容纲要

查看【Linux】专题可浏览更多内容

root 帐户是全能的管理用户,也称为超级用户帐户(superuser account)。

root 帐户的决定性特效是 UID 为 0。有些人会突发奇想一些操作,比如修改该帐户的用户名或者创建其他 UID 为 0 的帐户,这些操作是能做到但是可能会造成安全隐患,另外在于多人使用系统时也会造成他人的困惑,是不推荐的行为。

传统 UNIX 允许超级用户对所有文件和进程执行任何「正当」的操作,如:

  • 创建设备文件;
  • 设置系统时钟;
  • 提高资源使用限额以及进程优先级;
  • 设置系统主机名;
  • 配置网络接口;
  • 打开特权网络端口(编号小于 1024 的端口);
  • 关闭系统

正确管理 root 帐户至关重要,因为不仅在系统管理时需要,同时也是系统安全的关键所在。

root 帐户登陆

大多数系统允许直接以 root 帐户登陆,但这其实是糟糕。首先,使用 root 登陆不会留下任何操作记录,所以当使用 root 操作后如果回想不起来做了什么就够呛了。其次使用 root 登陆当另一个问题是无法记录执行操作当主题是谁,也就是说如果不止一个人以 root 登陆,压根就分不清是谁这什么时候登陆当。

su:替换用户身份

目前访问 root 帐户一种较好的方式是使用 su 命令,如果不带任何参数来调用 su 命令后,会提示用户输入 root 密码然后启动一个 root shell:

su

在使用完毕后使用 exit 命令退出。

su 并不会记录 root 执行过的命令,但回创建一条日志记录是谁在什么时候替换成 root。

su 即「switch user」所以也可以用于替换其他用户身份,在命令后接上用户名即可:

su <用户名>

-l 选项可以进一步简写成连字符 -,使用该选项会加载用户环境并将工作目录更改为该用户的主目录。

# 切换到 root
su -
# 或指定用户
su - <用户名>

也可以使用 su 命令执行单个命令,而不用启动一个全新的交互式Shell:

su -c 'apt upgrade'

采用这种形式,该命令行被传入新 Shell 执行,且注意需要执行的命令需要用英文引号包裹着。

在诊断用户所碰到的问题时,通过启动登陆 shell 有助于重现发生问题的环境。登陆 shell 具体以 shell 的种类而异,如 bash 作为登陆 shell 为例会读取 ~/.bash_profile,而非登陆 shell 则会读取 ~/.bashrc

⚠️ 注意:在某些系统中会明确要求先使用 su 替换到 root 才能再使用 su 切换到其他用户。

su 替换成 root 后切换到其他用户不需要提供密码,所以妥善管理 root 密码是很重要的。

另外在使用 su 时最好养成输入命令完整路径的习惯(如 /bin/su/usr/bin/su),不要依赖 shell 的帮助查找命令,(特别在有风险的系统上)以防那些打着 su 的旗号偷偷安插到 shell 搜索路径企图窃取密码的恶意程序。

sudo:受限版的 su

sudo 意为「super user do」,当非特权用户使用的命令提示权限问题时,在命令前加上 sudo,很容易记住对不对?

目前推荐使用 sudo 作为访问 root 帐户的主要方式,而使用 su 命令切换到超级用户是在 sudo 出现损坏或错误配置时,作为替代解决方案。

可能有的发行版或者云计算服务商提供的系统默认并不带有 sudo,这时候需要自行安装一下,以 Debian 为例:

apt install sudo

sudo 采用命令行作为参数然后以 root(或其他受限用户)身份执行。sudo 会读取配置文件 /etc/sudoers,该文件中列出了被授权使用 sudo 的用户以及被允许在每台主机上运行的命令。如果执行给出的命令,sudo 会提示输入相应用户(而不是 root 帐户)的密码以执行该命令。

第一次执行 sudo 时会看到一份提示:

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.

翻译过来就是:

我们相信你已经接受了当地系统管理员的例行讲座。通常归结为这三点。
1)尊重他人的隐私。
2)输入前三思而后行。
3)权力越大,责任越大。

在第一次成功执行 sudo 命令后的 5 分钟内的 sudo 命令不需要再次输入密码执行。这是一种避免造成安全隐患的超时机制,可自定义配置延长时间。

sudo 保留了一份日志,其中记录了运行过的命令、运行命令的主机、请求执行命令的用户、运行时所在的目录及什么时候运行的。这些信息会由 syslog 记录或写入指定的文件中。

sudo 的优劣

sudo 的优点:

  • 拥有命令日志,因此显著提高了安全审计能力;
  • 用户无需使用不受限制的 root 权限就可以执行特定任务;
  • 可以极少数人甚至没人知道 root 密码;
  • 使用 sudo 要比运行 su 或以 root 身份登陆进入系统要快;
  • 不需要更改 root 密码即可收回特权;
  • 可维护一个所有具有 root 权限用户的规范列表;
  • 降低了把 root shell 暴露给别人的机会。
  • 只用单个文件就可以控制整个网络的访问控制。

sudo 的缺点:

  • sudo 用户的个人帐户所存在的安全隐患等同于 root 帐户的安全隐患,突破了 sudo 用户就相当于突破了 root 帐户的安全防线。
  • sudo 的命令日志机制很容易被一些小花招搞定,例如在许可的程序中使用 shell 转义字符,或执行 sudo shsudo su

配置 sudo

配置 sudo 需使用 visudo 命令进,因为它可以验证文件语法以免配置错误,并且还能让单个版本的文件同时用在不同主机上。

visudo

下面是配置内容:

#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults    env_reset
Defaults    mail_badpass
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

先从最简单的开始

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

井号开头的行为注释内容不起实际作用,所以就上述两行内容而言,主要构成信息如下:
用户/用户组 主机=[(切换到哪些用户或组)] [是否需要输入密码验证] 命令1,命令2,...

进一步说明:

  1. 名为 root 的用户和名为 sudo 的用户组(在组名前加百分号表示用户组)
  2. ALL=(ALL:ALL) 的第一个 ALL 也就是等号前的「ALL」表示主机,可配置成当仅允许本地登录时使用的 localhost 当包括远程登录时使用的 All,或是指定主机名。
  3. 然后是等号后的括号「(ALL:ALL)」,表示的是切换到的用户或用户组,如果省略, 相当于(root:root),表示可以通过 sudo 替换成到 root 身份执行; 如果为 (ALL) 或者 (ALL:ALL), 表示能够替换到 (任意用户:任意用户组)。
  4. 最后的「ALL」表示为是否需要密码及指定的程序,不需要密码则在该段开头使用 NOPASSWD:,允许所有程序为 ALL。否则填程序的绝对路径,多个程序以逗号隔开,排除的程序在路径开头使用感叹号。

也就是说,现在名为 root 的帐户和名为 sudo 用户组的用户可以在任意主机上执行任意受限命令,且需要密码。

2 个小例子

1.配置名为 tom 的用户可以使用目录 /usr/sbin/ 下和目录 /sbin/ 下的程序,除了程序 /usr/sbin/visudo

tom ALL=/usr/sbin/*,/sbin/*,!/usr/sbin/visudo

2.用户名为 jerry 的用户仅在本地主机登录时使用 sudo 命令且不需要输入密码

jerry localhost=(ALL) NOPASSWD: ALL

别名(alias)

# Host alias specification
Host_Alis   SHIELD=hub, sandbox, fridge, slingshot, triskelion, academy

# User alias specification
User_Alis   ADMINS=tom, jerry

# Cmnd alias specification
Cmnd_Alis   DUMP=/usr/sbin/tcpdump

ADMINS      ALL=(ALL:ALL) ALL
tom         SHIELD=(ALL) ALL, !/usr/sbin/visudo
jerry       ALL=NOPASSWD:DUMP

上述示例使用了别名规范,主要是 3 个作用:

  1. 用户别名中的 ADMINS 含有 tom 和 jerry 两个用户名,在下面 ALL=(ALL:ALL) ALL 应用到了别名用户组 ADMINS 上等同于应用到了 tom 和 jerry 两个用户。
  2. 用户 tom 可以在 SHIELD 主机别名中的主机使用除了 /usr/sbin/visudo 以外的命令。
  3. 用户 jerry 可以任意主机上不需要密码执行程序 /usr/sbin/tcpdump

💡 最后,一个很酷的小技巧,在运行命令后才发现需要 sudo 时怎么办呢?再运行一条命令:sudo !!

让非特权用户得以使用 sudo

看完了上面此时让你配置一个名为 tom 的用户,使得它可以使用 sudo 你会怎么做呢?除了在 root ALL=(ALL:ALL) ALL 下增加一条 tom ALL=(ALL:ALL) ALL 还有一个方法是把 tom 用户加入到名为 sudo 的用户组中。

⚠️ 需要注意的是,不是每个发行版的默认配置中赋予权限的用户组都叫 sudo,比如在 CentOS 中就叫做 wheel。
在 CentOS 安装时的创建用户步骤,会提供选项「将此用户作为管理员」,在勾选时就会将用户将入到 wheel 组中。

新建名为 tom 的用户:

adduser tom

Debian 将普通用户 tom 加入到 sudo 用户组:

usermod -aG sudo tom

CentOS 将普通用户 tom 加入到 wheel 用户组:

usermod -aG wheel tom

使用 sudo 切换到 root

sudo -i