# 16.3.账户安全

在 FreeBSD 中，维护安全账户对于数据机密性、系统完整性和权限隔离至关重要，因为它可以防止未经授权的访问、恶意软件和数据泄露，同时确保合规性并保护组织的声誉。

## 16.3.1. 防止登录

在保护系统时，一个良好的起点是对账户进行审计。禁用不需要登录访问的账户。

> **技巧**
>
> 确保 `root` 用户具有强密码，并且该密码不可共享。

有两种方法可以拒绝账户的登录访问。

第一种方法是锁定账户，以下示例演示了如何锁定 `imani` 账户：

```sh
# pw lock imani
```

第二种方法是通过将 shell 改为 **/usr/sbin/nologin** 来防止登录访问。[nologin(8)](https://man.freebsd.org/cgi/man.cgi?query=nologin\&sektion=8\&format=html) shell 防止系统在用户尝试登录时为其分配 shell。

只有超级用户可以为其他用户更改 shell：

```sh
# chsh -s /usr/sbin/nologin imani
```

## 16.3.2. 密码哈希

密码是技术领域中不得不面对的恶性问题。当必须使用密码时，应确保其复杂性，并使用强大的哈希机制对存储在密码数据库中的版本进行加密。FreeBSD 支持多种算法，包括 SHA256、SHA512 和 Blowfish 哈希算法，详细信息请参见 [crypt(3)](https://man.freebsd.org/cgi/man.cgi?query=crypt\&sektion=3\&format=html)。

默认情况下，SHA512 不应更改为不安全的哈希算法，但可以更改为更安全的 Blowfish 算法。

> **注意**
>
> Blowfish 并非 AES 的一部分，也不符合任何联邦信息处理标准（FIPS）。在某些环境中，可能不允许使用它。

要确定使用哪种哈希算法加密用户的密码，超级用户可以查看 FreeBSD 密码数据库中该用户的哈希。每个哈希都以一个符号开头，表示用于加密密码的哈希机制类型。

如果使用的是 DES，则没有开始符号。对于 MD5，符号为 `$`。对于 SHA256 和 SHA512，符号为 `$6$`。对于 Blowfish，符号为 `$2a$`。在这个示例中，`imani` 的密码使用默认的 SHA512 算法进行哈希，因为哈希以 `$6$` 开头。请注意，存储在密码数据库中的是加密哈希，而不是密码本身：

```sh
# grep imani /etc/master.passwd
```

输出应类似于以下内容：

```ini
imani:$6$pzIjSvCAn.PBYQBA$PXpSeWPx3g5kscj3IMiM7tUEUSPmGexxta.8Lt9TGSi2lNQqYGKszsBPuGME0:1001:1001::0:0:imani:/usr/home/imani:/bin/sh
```

哈希机制是在用户的登录类中设置的。

可以运行以下命令检查当前使用的哈希机制：

```sh
% grep passwd_format /etc/login.conf
```

输出应类似于以下内容：

```sh
:passwd_format=sha512:\
```

例如，要将算法更改为 Blowfish，可以将该行修改为：

```sh
:passwd_format=blf:\
```

然后，必须执行 [cap\_mkdb(1)](https://man.freebsd.org/cgi/man.cgi?query=cap_mkdb\&sektion=1\&format=html) 来升级 login.conf 数据库：

```sh
# cap_mkdb /etc/login.conf
```

请注意，这一更改不会影响任何现有的密码哈希。这意味着所有密码都应通过要求用户运行 `passwd` 来重新哈希，以便更改其密码。

## 16.3.3. 密码策略强制执行

强制实施本地账户的强密码策略是系统安全的基本方面。在 FreeBSD 中，可以使用内置的可插拔身份验证模块（PAM）来实现密码长度、密码强度和密码复杂性的要求。

本节演示了如何使用 [pam\_passwdqc(8)](https://man.freebsd.org/cgi/man.cgi?query=pam_passwdqc\&sektion=8\&format=html) 模块配置最小和最大密码长度以及强制执行混合字符。此模块在用户更改密码时强制执行。

要配置此模块，请以超级用户身份登录并取消注释 **/etc/pam.d/passwd** 中包含 `pam_passwdqc.so` 的行。

然后，编辑该行以匹配密码策略：

```ini
password        requisite       pam_passwdqc.so         min=disabled,disabled,disabled,12,10 similar=deny retry=3 enforce=users
```

有关参数的解释，可以参见 [pam\_passwdqc(8)](https://man.freebsd.org/cgi/man.cgi?query=pam_passwdqc\&sektion=8\&format=html)。

保存此文件后，当用户更改密码时，将看到类似如下的消息：

```sh
% passwd
```

输出应类似于以下内容：

```sh
Changing local password for user
Old Password:

You can now choose the new password.
A valid password should be a mix of upper and lower case letters,
digits and other characters.  You can use a 12 character long
password with characters from at least 3 of these 4 classes, or
a 10 character long password containing characters from all the
classes.  Characters that form a common pattern are discarded by
the check.
Alternatively, if no one else can see your terminal now, you can
pick this as your password: "trait-useful&knob".
Enter new password:
```

如果输入的密码不符合策略，将被拒绝，并出现警告，用户将有机会再次尝试，直到达到配置的重试次数。

如果组织的策略要求密码过期，FreeBSD 支持在用户的登录类中设置 `passwordtime`，该配置位于 **/etc/login.conf** 中。

`default` 登录类包含一个示例：

```sh
#       :passwordtime=90d:\
```

因此，要将此登录类的过期时间设置为 90 天，请删除注释符号 (#)，保存编辑，然后执行以下命令：

```sh
# cap_mkdb /etc/login.conf
```

要为个别用户设置过期时间，可以向 `pw` 命令传递过期日期或过期天数和用户名：

```sh
# pw usermod -p 30-apr-2025 -n user
```

如上所示，过期日期的设置格式为 日、月、年。有关更多信息，请参见 [pw(8)](https://man.freebsd.org/cgi/man.cgi?query=pw\&sektion=8\&format=html)。

## 16.3.4. 使用 sudo 进行共享管理

系统管理员通常需要能够授予用户增强的权限，以便他们能够执行特权任务。让团队成员访问 FreeBSD 系统以执行其特定任务，这为每个管理员带来了独特的挑战。这些团队成员只需要超出普通用户级别的一部分访问权限；然而，他们几乎总是告诉管理层，他们无法在没有超级用户访问权限的情况下执行任务。幸运的是，提供此类访问权限给最终用户是没有必要的，因为已经有工具可以管理这一具体需求。

> **技巧**
>
> 即使是管理员，也应在不需要时限制其权限。

到目前为止，本章已经讨论了如何允许授权用户访问以及如何尽量防止未经授权的访问。另一个问题出现了，待授权用户有权访问系统资源。在许多情况下，一些用户可能需要访问应用程序启动脚本，或者一组管理员需要维护系统。传统上，标准的用户和组、文件权限，甚至是 [su(1)](https://man.freebsd.org/cgi/man.cgi?query=su\&sektion=1\&format=html) 命令用于管理这种访问。而随着应用程序需要更多的访问权限，更多用户需要使用系统资源，一个更好的解决方案应运而生。目前使用最广泛的应用程序是 Sudo。

Sudo 允许管理员配置更严格的访问控制系统命令，并提供一些高级日志记录功能。作为一个工具，它可以从 Ports 安装，路径为 [security/sudo](https://cgit.freebsd.org/ports/tree/security/sudo/)，或使用 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 工具。

执行以下命令来安装它：

```sh
# pkg install sudo
```

安装完成后，安装的 `visudo` 将使用文本编辑器打开配置文件。强烈建议使用 `visudo`，因为它内置了语法检查器，可以在文件保存前验证没有错误。

配置文件由多个小节组成，允许进行广泛的配置。在以下示例中，Web 应用程序维护者用户 `user1` 需要启动、停止和重启名为 *webservice* 的 Web 应用程序。为了授予该用户执行这些任务的权限，在 **/usr/local/etc/sudoers** 文件的末尾添加以下行：

```ini
user1   ALL=(ALL)       /usr/sbin/service webservice *
```

现在，用户可以使用以下命令启动 *webservice*：

```sh
% sudo /usr/sbin/service webservice start
```

虽然这个配置允许单个用户访问 *webservice* 服务；然而，在大多数组织中，通常由一个 Web 团队负责管理该服务。单行配置同样可以为整个组提供访问权限。以下步骤将创建一个 Web 组，将用户添加到该组，并允许该组所有成员管理该服务：

```sh
# pw groupadd -g 6001 -n webteam
```

使用相同的 [pw(8)](https://man.freebsd.org/cgi/man.cgi?query=pw\&sektion=8\&format=html) 命令，将用户添加到 webteam 组：

```sh
# pw groupmod -m user1 -n webteam
```

最后，在 **/usr/local/etc/sudoers** 文件中添加这一行，允许 webteam 组的任何成员管理 *webservice*：

```ini
%webteam   ALL=(ALL)       /usr/sbin/service webservice *
```

与 [su(1)](https://man.freebsd.org/cgi/man.cgi?query=su\&sektion=1\&format=html) 不同，[sudo(8)](https://man.freebsd.org/cgi/man.cgi?query=sudo\&sektion=8\&format=html) 只需要最终用户输入自己的密码。这样可以避免共享密码，这是一种不良的做法。

被允许使用 [sudo(8)](https://man.freebsd.org/cgi/man.cgi?query=sudo\&sektion=8\&format=html) 运行应用程序的用户只需输入自己的密码。这比 [su(1)](https://man.freebsd.org/cgi/man.cgi?query=su\&sektion=1\&format=html) 更加安全，并且提供了更好的控制，因为在 \[su(1)] 中，用户输入 `root` 密码后会获得所有 `root` 权限。

> **技巧**
>
> 大多数组织正在或已经转向双因素认证模型。在这种情况下，用户可能没有密码可供输入。
>
> [sudo(8)](https://man.freebsd.org/cgi/man.cgi?query=sudo\&sektion=8\&format=html) 可以通过使用 `NOPASSWD` 变量配置为允许双因素认证模型。将其添加到上述配置中，将允许所有 *webteam* 组成员管理该服务，而无需密码：
>
> ```ini
> %webteam   ALL=(ALL)       NOPASSWD: /usr/sbin/service webservice *
> ```

## 16.3.5. 使用 Doas 进行共享管理

[doas(1)](https://man.freebsd.org/cgi/man.cgi?query=doas\&sektion=1\&format=html) 是一个从 OpenBSD 移植过来的命令行工具，它作为 Unix-like 系统中广泛使用的 [sudo(8)](https://man.freebsd.org/cgi/man.cgi?query=sudo\&sektion=8\&format=html) 命令的替代品。

使用 doas，用户可以以 root 用户身份执行具有提升权限的命令，同时保持简化且注重安全的方法。与 [sudo(8)](https://man.freebsd.org/cgi/man.cgi?query=sudo\&sektion=8\&format=html) 不同，doas 强调简洁性和极简主义，专注于精简的权限委派，而不会出现复杂的配置选项。

执行以下命令来安装它：

```sh
# pkg install doas
```

安装后，必须配置 **/usr/local/etc/doas.conf** 文件，以便为用户授予执行特定命令或角色的权限。

最简单的配置条目可能如下所示，它允许 `local_user` 在执行 doas 命令时以 `root` 身份运行命令，并且不要求输入密码：

```sh
permit nopass local_user as root
```

安装和配置好 `doas` 工具后，现在可以以提升的权限执行命令，例如：

```sh
doas vi /etc/rc.conf
```

更多配置示例，请参阅 [doas.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=doas.conf\&sektion=5\&format=html)。
