# 七种提升新安装 FreeBSD 安全性的方法

* 原文链接：[Seven Ways to Increase Security in a New FreeBSD Installation](https://freebsdfoundation.org/wp-content/uploads/2021/07/Seven-Ways-to-Increase-Security-in-a-New-FreeBSD-Installation.pdf)
* 作者：**MARIUSZ ZABORSKI**

FreeBSD 可以作为桌面操作系统和服务器操作系统使用。在设置新机器时，选择最安全的配置至关重要。我们的计算机上存储了大量数据，这些数据都需要得到保护。本文介绍了在配置新 FreeBSD 系统时，大家应记住的七项配置优化。

## 1. 全盘加密

在进行全新安装时，决定是否启用硬盘加密非常重要——特别是因为后续添加加密可能会比较困难。磁盘加密的目的是保护存储在系统上的数据。我们在计算机上存储了大量个人和商业数据，大多数时候，我们不希望这些数据被未经授权的人读取。我们的笔记本电脑可能会被盗，如果是这样，就应该假设小偷就可能会访问几乎全部的文档、照片，以及我们通过浏览器登录的所有页面。有些人也可能尝试篡改或读取我们的数据，尤其是在我们远离电脑时。

我们建议加密所有系统——特别是服务器或个人电脑。硬盘加密的成本相对较低，而且它带来的好处非常明显。

在 FreeBSD 中，主要有三种加密存储的方式：

* GBDE
* ZFS 原生加密
* GELI

基于 Geom 的磁盘加密（GBDE）是 FreeBSD 中最早的磁盘加密机制。但目前 GBDE 已被开发者忽视。GBDE 仅支持 AES-CBC 加密算法，使用 128 位密钥长度，并且每次写入时使用不同的密钥，这可能会带来一定的 CPU 开销。它还需要存储每个扇区的密钥，这增加了一些磁盘空间开销。由于出现了其他更高效、更灵活的加密替代方案，GBDE 对开发者和用户来说变得不再那么有吸引力。

OpenZFS 原生磁盘加密是 FreeBSD 中最新的磁盘加密机制，首次出现在 13.0-RELEASE 中。OpenZFS 支持 AES-CCM 和 AES-GCM 加密算法，密钥长度可以是 128 位、192 位和 256 位。在 OpenZFS 的加密中，并非所有数据都会被加密。数据集和快照、池布局或数据集属性等将以未加密的方式存储。通常，这些数据可能不是机密 - 的，但用户应当意识到这一点。另一个 OpenZFS 磁盘加密的问题是，FreeBSD 不能从加密的数据集启动。

如果用户仅希望加密少量数据集并保护系统的某些部分，OpenZFS 原生磁盘加密是一个可靠的选择。OpenZFS 原生加密的一个重要优点是，可以在系统安装后启用。唯一的要求是使用 ZFS，用户可以在此基础上创建新的加密数据集。

GELI 是我们首选的工具。它支持全盘加密，只有 FreeBSD 启动分区不会被加密。并且，GELI 支持多种加密算法，默认使用 AES-XTS 加密算法，密钥长度为 256 位。

如果用户担心其关键系统上的引导加载程序被篡改，可以重新配置 GELI。GELI 可以设置为使用密钥文件和密码短语来加密设备。引导加载程序可以被移到外部存储器设备（如 U 盘），并将密钥文件从硬盘移到该外部存储设备。没有这个存储器设备，任何人都无法启动（因为密钥仅保存在该设备上）。即使有人盗取了存储器设备和计算机，只要他们不知道密码短语，就无法解密设备。记住要备份这个存储器设备——如果丢失，任何人都无法恢复数据。

可以通过 FreeBSD 安装程序轻松配置默认的 GELI 加密：

![](https://github.com/user-attachments/assets/2c4df428-9f8b-49d5-90dd-78bc2de8797c)

GELI 还支持一次性密钥。当系统重启时，加密密钥不会从系统中移除。这意味着存储在交换分区和临时文件系统中的所有数据将会被清除。

操作系统可能会将关键应用程序（例如浏览器）交换到硬盘上，其中可能包含存储在浏览器中的用户机密。如果交换区没有加密，攻击者可能会从磁盘中读取信息。

交换区加密也可以通过 FreeBSD 安装程序轻松启用，因此记得处理这个问题至关重要。相关选项与全盘加密选项一起出现在同一个启动菜单窗口中。

## 2. 使用 ZFS 提升数据完整性

提高 FreeBSD 系统安全性的另一种方式是使用市场上最好的文件系统——ZFS。这也是用户在安装过程中必须考虑的内容，因为更改文件系统可能会有一定挑战。ZFS 拥有众多令人兴奋的特性，但在本节中，我们将重点讨论其中一个：从安全角度来看，ZFS 的数据完整性。

ZFS 使用 Merkle 树。Merkle 树是一种数据结构，其中每个叶子节点都有一个加密哈希值。这意味着 ZFS 对数据及其所有元数据进行层次化校验和。

如果硬盘存在潜在问题，例如损坏的扇区、写/读错误、虚假写入或其他可能破坏数据的情况，ZFS 会发现这些问题。

在不支持数据完整性的文件系统中，当出现这种不一致时，错误的数据可能会返回给应用程序。而在 ZFS 中，返回的将是错误信息，而不是数据。如果我们配置了镜像或 RAIDZ，文件系统会尝试修复问题。

ZFS 支持多种校验和算法，默认使用 SHA-256。用户可以决定是否启用或禁用完整性检查，强烈建议保持启用状态。凭借数据完整性，我们可以确保数据未被篡改。

## 3. ZFS setuid 和 exec 属性

除了数据完整性，我们还可以通过 ZFS 增加一些额外的保护。我们喜欢在不需要 setuid 的数据集上禁用该功能。ZFS 的 setuid 属性控制文件系统中是否执行 setuid 位。当运行 setuid 二进制文件时，它会模拟二进制文件所有者的身份。setuid 非常有用，但同时也非常危险，因此我们建议将其限制，并在大多数数据集上禁用此属性——除了包含系统 `bin/sbin` 目录的数据集。

另一个有吸引力的属性是 exec。此属性能让我们禁用数据集中的程序是否可以被执行。我们喜欢在 `/tmp` 和下载目录禁用它。大多数时候，我们将随机文件移到这些目录或下载文件，我们不希望误执行这些文件。

## 4. 不要使用 root

类 UNIX 操作系统有一个强大的账户——root，它对系统拥有绝对控制权。显然，我们应该限制并审计对该用户的访问。提高安全性的一种方法是为 root 账户设置一个非常复杂、无法猜测的密码，且不与任何人共享。我们应该避免直接登录或使用 su(1) 切换到 root 账户，而是使用像 sudo(8) 这样的应用程序。

sudo(8) 是一个允许你控制作为 root 或系统中任何其他用户运行命令的访问权限的应用程序。系统管理员可以创建一个特权命令列表，用户可以在模拟其他用户身份时执行这些命令。与 su(1) 不同，sudo(8) 不需要 root 或其他用户的密码来运行。当用户想要执行具有提升权限的命令时，它会要求他们输入自己的密码。这限制了系统管理员之间密码的共享。我们可以通过 FreeBSD 的二进制包管理轻松安装 sudo(8)：

```sh
# pkg install sudo
```

通过 sudo(8) 调用的活动会被记录。这为谁做了什么操作提供了一些问责性。这也是为什么我们应避免以不同用户身份启动或登录。

请记住，不要过度复杂化 sudo 配置，保持尽可能简单，绝不允许用户在没有使用 sudo(8) 的情况下访问可以修改的脚本/程序。一个被忽视的 sudo 条目可能成为攻击者的一个易用攻击向量。

系统应配置为使用复杂的 root 密码，并避免让 root 用户远程登录（例如通过 ssh(1)）。当 sudo(8) 在一些关键系统上运行时，用户甚至可以考虑锁定 root 用户：

```sh
sudo pw lock root
```

只要确保在 root 用户必须解锁的情况下，系统有单用户模式或其他恢复方法的启动选项。

通过日常使用 sudo(8)——而不是使用 root shell——用户还可以避免在离开未锁定的计算机时出现问题，因为此时有人可能会利用 root shell 安装恶意软件。sudo(8) 通过在一段时间不活动后要求用户输入密码来缓解这个问题。

## 5. 备份

世界上有两种人——做备份的人和将来会做备份的人。不幸的是，第二类人会通过失去数据的痛苦方式了解到备份的重要性。关于勒索软件和云服务提供商的故事告诉我们，很多人仍然抵触做备份。预防胜于治疗——备份也是如此。用户通常直到为时已晚才明白备份的重要性。如果你从这篇文章中学到的唯一一课——请记得执行备份。

幸运的是，我们在系统上使用了 ZFS，并利用了另一个有趣的特性——快照。快照是某一时刻数据集的副本。它们非常有用，因为我们可以通过 `zfs` 命令提取这些副本，并通过 `zfs receive` 命令导入它们。创建 ZFS 备份的最简单方法是做一个快照并将其导出到文件中：

```sh
# zfs snapshot -r 池名@快照名
# zfs send -R -c 池名@快照名 > 导出名
```

上述命令将会创建池 `池名` 中所有数据集的递归快照，然后将它们导出到 `导出名` 文件中。`-c` 选项表示导出的数据将被压缩。导入时，只需确保系统支持所有使用的压缩算法。现在，备份可以被复制到外部磁盘、加密、发送到云端、任何其他服务器或用户想要保存备份的平台上。还可以通过 SSH 进行简单的远程备份：

```sh
# zfs send -R -c 池名@快照名 | ssh example.com
cat > mybackupfile
```

或者，如果远程服务器支持 ZFS，这也可以自动在远程服务器上导入：

```sh
# zfs send -R -c 池名@快照名 | ssh example.com
zfs receive storage/mybackup
```

因此，数据将在该服务器上可供浏览。可能需要一些额外的配置来启用对 ZFS 特性的访问。用户必须通过 `zfs allow` 或使用 `sudo(8)` 来允许执行 `zfs receive` 命令。发送完整的备份可能会因为所需存储空间和网络带宽的开销而显得有些过多。幸运的是，ZFS 还支持发送增量快照。通过这种方式，ZFS 只会创建包含两个快照之间差异的流。以下命令允许你使用更少的存储和网络资源复制快照：

```sh
# zfs send -c -i name_of_previous_snapshot 池名@快照名 | ssh example.com zfs receive storage/mybackup
```

也可以将这些增量部分导出到文件中。然而，如果 `zfs send` 创建多个小的增量部分，恢复时可能会有些复杂——首先需要导入整个备份，然后再按创建顺序分别导入每个文件。

如果系统使用不同的文件系统，还有一些替代方案。用户可以选择使用像 `dump(8)` 这样的工具来备份 UFS，或者使用 `rsync(1)`，甚至是像 Tarsnap 这样的商业产品。

## 6. 保持系统更新

另一个需要记住的教训是定期升级我们的操作系统。这是每个人都在谈论的一个教训，但不知为何常常被遗忘。

FreeBSD 的安全补丁可以使用以下命令下载和安装：

```sh
# freebsd-update fetch
# freebsd-update install
```

对于 pkg 更新和系统更新：

```sh
# pkg update
# pkg upgrade
```

在使用一些生产工具时，检查它们是否存在已知漏洞也是很明智的，可以使用以下命令：

```sh
# pkg audit
```

由于我们选择的文件系统是 ZFS，因此在进行升级时使用启动环境是一个好方法。这使我们可以在系统出现问题时轻松回滚到先前的版本。

## 7. 安全加固

在安装新的 FreeBSD 实例时，最后一个菜单是关于操作系统加固的。一些选项会对 FreeBSD 进行小幅调整，从而略微提高安全性。我指的是像隐藏进程 UID 和 GID、在系统启动时清空 tmp 目录以及随机化进程标识符等设置。

默认情况下，所有的强化选项都是禁用的。我们建议启用这些选项。

![](https://github.com/user-attachments/assets/7c987922-ba13-403d-8f6b-2f6fd8359f16)

安装后，我们还建议启用 ASLR（地址空间布局随机化），它会在每次运行进程时改变其内存布局，使得应用程序更难被利用。要在 FreeBSD 系统上启用 ASLR（**译者注：14.0 后就默认启用了**），可以运行以下命令：

```sh
# sysctl kern.elf64.aslr.enable=1
# sysctl kern.elf32.aslr.enable=1
```

用户还可以将这些条目添加到文件 `/boot/loader.conf` 中，以便在启动时启用它们。

## 总结

在本文中，我们介绍了七种提高 FreeBSD 系统安全性的方法。使用 ZFS 在 FreeBSD 中非常流行，但减少数据集执行 setuid 和 exec 文件的能力并不常见——而用户可以从中受益。我们希望全盘加密、备份和 sudo(8) 的使用已经成为标准，但总是值得提醒大家使用它们。我们还讨论了 FreeBSD 配置中的一些小调整，这些调整可以随机化或隐藏一些系统信息。

1. 错误的写/读是指硬盘从与系统请求的不同位置写入/读取数据的情况。这可能是由于 CPI/电缆的位翻转，或者硬盘磁头出现问题导致的。
2. 虚假写入是指操作系统认为某些数据已经存储到磁盘上，但由于某种原因，操作并未成功写入磁盘。
3. [勒索软件：如果你成为攻击的受害者，这是你应该首先考虑的事情](https://www.zdnet.com/article/ransomware-this-is-the-first-thing-you-should-think-about-if-you-fall-victim-to-an-attack/)
4. [法国 OVH 火灾](https://www.reuters.com/article/us-france-ovh-fire-idUSKBN2B20NU)

***

**MARIUSZ ZABORSKI** 目前是 4Prime 的安全专家，自 2015 年以来一直是 FreeBSD 的贡献者。他的主要兴趣领域是操作系统安全和低级编程。过去，他曾在 Fudo Security 工作，领导开发 IT 基础设施中最先进的 PAM 解决方案。2018 年，Mariusz 组织了波兰 BSD 用户组。在业余时间，他喜欢在 <https://oshogbo.vexillium.org> 上写博客。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://freebsd-journal-cn.bsdcn.org/20210506-an-quan/security.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
