# 18.5.可用的 MAC 策略

默认的 FreeBSD 内核包含 `options MAC`。这意味着每个与 MAC 框架一起提供的模块都可以通过 `kldload` 作为运行时内核模块加载。在测试模块后，将模块名称添加到 **/boot/loader.conf** 中，以便在引导时加载。对于选择自己编译内核的管理员，每个模块也提供了一个内核选项。

FreeBSD 包含一组可以覆盖大多数安全需求的策略。每个策略在下文中进行了总结。最后三个策略支持整数设置，可以替代三个默认标签。

## 18.5.1. MAC See Other UID 策略

模块名称：**mac\_seeotheruids.ko**

内核配置行：`options MAC_SEEOTHERUIDS`

引导选项：`mac_seeotheruids_load="YES"`

[mac\_seeotheruids(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_seeotheruids\&sektion=4\&format=html) 模块扩展了 `security.bsd.see_other_uids` 和 `security.bsd.see_other_gids` sysctl 可调项。此选项在配置之前不需要设置任何标签，并且可以与其他模块透明地一起工作。

加载该模块后，可以使用以下 `sysctl` 可调项来控制其功能：

* `security.mac.seeotheruids.enabled` 启用该模块并实施默认设置，拒绝用户查看由其他用户拥有的进程和套接字。
* `security.mac.seeotheruids.specificgid_enabled` 允许指定的组免除此策略。要免除特定组，可以使用 `security.mac.seeotheruids.specificgid=XXX sysctl` 可调项，将 *XXX* 替换为要免除的数字组 ID。
* `security.mac.seeotheruids.primarygroup_enabled` 用于免除特定的主组。使用此可调项时，不能设置 `security.mac.seeotheruids.specificgid_enabled`。

## 18.5.2. MAC BSD Extended 策略

模块名称：**mac\_bsdextended.ko**

内核配置行：`options MAC_BSDEXTENDED`

引导选项：`mac_bsdextended_load="YES"`

[mac\_bsdextended(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_bsdextended\&sektion=4\&format=html) 模块强制实施文件系统防火墙。它扩展了标准的文件系统权限模型，允许管理员创建类似防火墙的规则集来保护文件、工具和目录的文件系统层次结构。当尝试访问文件系统对象时，规则列表会依次遍历，直到找到匹配的规则或遍历到末尾。可以使用 `security.mac.bsdextended.firstmatch_enabled` 更改此行为。与 FreeBSD 中的其他防火墙模块类似，可以创建一个包含访问控制规则的文件，并通过 [rc.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=rc.conf\&sektion=5\&format=html) 变量在启动时读取该文件。

规则列表可以使用 [ugidfw(8)](https://man.freebsd.org/cgi/man.cgi?query=ugidfw\&sektion=8\&format=html) 进行输入，语法类似于 [ipfw(8)](https://man.freebsd.org/cgi/man.cgi?query=ipfw\&sektion=8\&format=html)。更多工具可以通过使用 [libugidfw(3)](https://man.freebsd.org/cgi/man.cgi?query=libugidfw\&sektion=3\&format=html) 库中的函数编写。

加载 [mac\_bsdextended(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_bsdextended\&sektion=4\&format=html) 模块后，可以使用以下命令列出当前的规则配置：

```sh
# ugidfw list
0 slots, 0 rules
```

默认情况下，没有定义规则，所有内容都是完全可访问的。要创建一个规则，阻止所有用户的访问，但不影响 `root`：

```sh
# ugidfw add subject not uid root new object not uid root mode n
```

虽然此规则很简单，但它是一个非常糟糕的主意，因为它阻止了所有用户执行任何命令。一个更现实的示例是阻止 `user1` 对 `user2` 的主目录进行所有访问，包括目录列出：

```sh
# ugidfw set 2 subject uid user1 object uid user2 mode n
# ugidfw set 3 subject uid user1 object gid user2 mode n
```

除了 `user1`，还可以使用 `not uid user2` 来强制对所有用户实施相同的访问限制。然而，`root` 用户不受这些规则的影响。

> **注意**
>
> 使用此模块时应极为小心，因为不正确的使用可能会阻止访问文件系统的某些部分。

## 18.5.3. MAC 接口静默策略

模块名称：**mac\_ifoff.ko**

内核配置行：`options MAC_IFOFF`

引导选项：`mac_ifoff_load="YES"`

[mac\_ifoff(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_ifoff\&sektion=4\&format=html) 模块用于实时禁用网络接口，并防止在系统启动期间启用网络接口。它不使用标签，并且不依赖于任何其他 MAC 模块。

该模块的大部分控制是通过以下 `sysctl` 可调项来完成的：

* `security.mac.ifoff.lo_enabled` 启用或禁用所有环回 [lo(4)](https://man.freebsd.org/cgi/man.cgi?query=lo\&sektion=4\&format=html) 接口的流量。
* `security.mac.ifoff.bpfrecv_enabled` 启用或禁用所有 Berkeley 数据包过滤器接口 [bpf(4)](https://man.freebsd.org/cgi/man.cgi?query=bpf\&sektion=4\&format=html) 的流量。
* `security.mac.ifoff.other_enabled` 启用或禁用所有其他接口上的流量。

[mac\_ifoff(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_ifoff\&sektion=4\&format=html) 的一个常见用途是在不允许网络流量通过启动序列的环境中进行网络监控。另一个用法是编写一个脚本，使用如 [security/aide](https://cgit.freebsd.org/ports/tree/security/aide/) 之类的应用程序，自动阻止网络流量，如果它发现受保护目录中的新文件或被更改的文件。

## 18.5.4. MAC 端口访问控制列表策略

模块名称：**mac\_portacl.ko**

内核配置行：`MAC_PORTACL`

引导选项：`mac_portacl_load="YES"`

[mac\_portacl(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_portacl\&sektion=4\&format=html) 模块用于限制本地 TCP 和 UDP 端口的绑定，使得非 `root` 用户能够绑定到指定的特权端口（低于 1024）。

加载该模块后，会在所有套接字上启用 MAC 策略。以下可调项可用：

* `security.mac.portacl.enabled` 启用或禁用整个策略。
* `security.mac.portacl.port_high` 设置 [mac\_portacl(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_portacl\&sektion=4\&format=html) 所保护的最高端口号。
* `security.mac.portacl.suser_exempt` 当设置为非零值时，免除 `root` 用户不受此策略的影响。
* `security.mac.portacl.rules` 指定策略的文本字符串，形式为 `rule[,rule,…]`，规则的数量可以根据需要进行调整，每个规则的形式为 `idtype:id:protocol:port`。`idtype` 可以是 `uid` 或 `gid`，`protocol` 参数可以是 `tcp` 或 `udp`，`port` 参数是允许指定用户或组绑定的端口号。用户 ID、组 ID 和端口参数只能使用数字值。

默认情况下，1024 以下的端口只能由以 `root` 身份运行的特权进程使用。为了允许非特权进程绑定到低于 1024 的端口，可以按如下方式设置以下可调项：

```sh
# sysctl security.mac.portacl.port_high=1023
# sysctl net.inet.ip.portrange.reservedlow=0
# sysctl net.inet.ip.portrange.reservedhigh=0
```

为了防止 `root` 用户受此策略的影响，将 `security.mac.portacl.suser_exempt` 设置为非零值：

```sh
# sysctl security.mac.portacl.suser_exempt=1
```

要允许 `www` 用户（UID 为 80）在不需要 `root` 权限的情况下绑定到端口 80：

```sh
# sysctl security.mac.portacl.rules=uid:80:tcp:80
```

以下示例允许 UID 为 1001 的用户绑定到 TCP 端口 110（POP3）和 995（POP3s）：

```sh
# sysctl security.mac.portacl.rules=uid:1001:tcp:110,uid:1001:tcp:995
```

## 18.5.5. MAC 分区策略

模块名称：**mac\_partition.ko**

内核配置行：`options MAC_PARTITION`

引导选项：`mac_partition_load="YES"`

[mac\_partition(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_partition\&sektion=4\&format=html) 策略根据进程的 MAC 标签将其划分到特定的“分区”中。大部分配置通过 [setpmac(8)](https://man.freebsd.org/cgi/man.cgi?query=setpmac\&sektion=8\&format=html) 完成。此策略有一个可调项：

* `security.mac.partition.enabled` 启用或禁用 MAC 进程分区的执行。

启用此策略时，用户只能看到自己的进程以及自己所在分区内的进程，无法使用超出该分区范围的实用程序。例如，属于 `insecure` 类别的用户将无法访问 `top`，以及许多其他必须生成进程的命令。

以下示例将 `top` 命令添加到 `insecure` 类用户的标签集中。所有由 `insecure` 类用户生成的进程将保持在 `partition/13` 标签中：

```sh
# setpmac partition/13 top
```

此命令显示分区标签和进程列表：

```sh
# ps Zax
```

此命令显示另一个用户的进程分区标签以及该用户当前运行的进程：

```sh
# ps -ZU trhodes
```

> **注意**
>
> 用户可以查看 `root` 标签中的进程，除非加载了 [mac\_seeotheruids(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_seeotheruids\&sektion=4\&format=html) 策略。

## 18.5.6. MAC 多级安全模块

模块名称：**mac\_mls.ko**

内核配置行：`options MAC_MLS`

引导选项：`mac_mls_load="YES"`

[mac\_mls(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_mls\&sektion=4\&format=html) 策略通过执行严格的信息流策略来控制系统中主体与对象之间的访问。

在 MLS 环境中，每个主体或对象的标签中都会设置一个“许可”级别，以及相应的隔离区。由于这些许可级别可以达到数千的数量，配置每个主体或对象可能会变得非常繁琐。为简化管理员的工作，政策中包含了三个标签：`mls/low`、`mls/equal` 和 `mls/high`，它们的定义如下：

* 标有 `mls/low` 的对象具有低的许可级别，并且不允许访问更高许可级别的信息。此标签还防止更高许可级别的对象向较低许可级别的对象写入或传递信息。
* `mls/equal` 应该用于那些应豁免于该政策的对象。
* `mls/high` 是可能的最高许可级别。分配此标签的对象将对系统中的所有其他对象具有支配权；然而，它们不会允许信息泄露到较低级别的对象。

MLS 提供：

* 一个具有非层次类别集的层次安全级别。
* 固定的 `no read up, no write down` 规则。这意味着主体可以读取其自身级别或以下的对象，但不能读取更高的对象。同样，主体可以写入其自身级别或以上的对象，但不能写入较低级别的对象。
* 保密性，或防止不当泄露数据。
* 为处理具有多个敏感级别的数据的系统提供了设计基础，确保机密与保密信息之间不发生信息泄漏。

以下是可用的 `sysctl` 可调项：

* `security.mac.mls.enabled` 用于启用或禁用 MLS 策略。
* `security.mac.mls.ptys_equal` 在创建时将所有 [pty(4)](https://man.freebsd.org/cgi/man.cgi?query=pty\&sektion=4\&format=html) 设备标记为 `mls/equal`。
* `security.mac.mls.revocation_enabled` 在对象的标签更改为较低级别的标签后，撤销对该对象的访问。
* `security.mac.mls.max_compartments` 设置系统上允许的最大隔离级别数。

要操作 MLS 标签，请使用 [setfmac(8)](https://man.freebsd.org/cgi/man.cgi?query=setfmac\&sektion=8\&format=html)。要为对象分配标签：

```sh
# setfmac mls/5 test
```

要获取文件 **test** 的 MLS 标签：

```sh
# getfmac test
```

另一种方法是创建一个主策略文件 **/etc/**，该文件指定 MLS 策略信息，并将该文件传递给 `setfmac`。

使用 MLS 策略模块时，管理员计划控制敏感信息的流动。默认的 `block read up block write down` 将所有信息设置为低级别。所有信息都是可访问的，管理员会逐步增加信息的保密性。

除了三个基本标签选项外，管理员还可以根据需要将用户和组分组，以阻止它们之间的信息流动。可以通过使用描述性词语（如 `Confidential`、`Secret` 和 `Top Secret`）来查看许可级别中的信息。一些管理员会根据项目级别创建不同的组。无论采用何种分类方法，都必须在实施限制性政策之前制定出合理的计划。

MLS 策略模块的一些示例应用场景包括电子商务 Web 服务器、存储关键公司信息的文件服务器以及金融机构环境。

## 18.5.7. MAC Biba 模块

模块名称：**mac\_biba.ko**

内核配置行：`options MAC_BIBA`

引导选项：`mac_biba_load="YES"`

[mac\_biba(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_biba\&sektion=4\&format=html) 模块加载了 MAC Biba 策略。此策略与 MLS 策略类似，唯一不同的是信息流的规则稍微相反。MAC Biba 策略用于防止敏感信息向下流动，而 MLS 策略则防止敏感信息向上流动。

在 Biba 环境中，每个主体或对象都会设置一个“完整性”标签。这些标签由分层的等级和非分层的组件组成。随着等级的升高，其完整性也会提高。

支持的标签有 `biba/low`、`biba/equal` 和 `biba/high`，具体如下：

* `biba/low` 被认为是主体或对象可能拥有的最低完整性。将其设置在对象或主体上会阻止它们写入标记为 `biba/high` 的对象或主体，但不会阻止读取访问。
* `biba/equal` 应该只用于那些被认为豁免于该政策的对象。
* `biba/high` 允许写入低标签的对象，但不允许读取该对象。建议将此标签用于影响整个系统完整性的对象。

Biba 提供：

* 具有一组非层次完整性类别的层次完整性级别。
* 固定规则为 `no write up, no read down`，与 MLS 相反。主体可以写入其自身级别或以下的对象，但不能写入更高的对象。同样，主体可以读取其自身级别或以上的对象，但不能读取较低级别的对象。
* 通过防止数据的不当修改来确保完整性。
* 使用完整性级别，而不是 MLS 敏感性级别。

以下可调项可用于操作 Biba 策略：

* `security.mac.biba.enabled` 用于启用或禁用在目标机器上执行 Biba 策略。
* `security.mac.biba.ptys_equal` 用于禁用 [pty(4)](https://man.freebsd.org/cgi/man.cgi?query=pty\&sektion=4\&format=html) 设备上的 Biba 策略。
* `security.mac.biba.revocation_enabled` 强制在标签变化为主导主体时撤销对对象的访问。

要访问系统对象上的 Biba 策略设置，使用 `setfmac` 和 `getfmac`：

```sh
# setfmac biba/low test
# getfmac test
test: biba/low
```

完整性与敏感性不同，用于保证信息不被不可信方篡改。这包括主体与对象之间传递的信息。它确保用户只能修改或访问他们被明确授权的信息。[mac\_biba(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_biba\&sektion=4\&format=html) 安全策略模块允许管理员配置用户可以查看和调用的文件和程序，同时确保这些程序和文件对该用户是系统信任的。

在初始规划阶段，管理员必须准备好将用户划分为等级、级别和区域。启用此策略模块后，系统将默认设置为高标签，管理员需要配置不同的等级和级别。除了使用许可级别外，一个好的规划方法可以是使用主题。例如，仅允许开发人员修改源代码仓库、源代码编译器和其他开发工具。其他用户可以分组为测试人员、设计人员或最终用户，并仅被允许访问读取权限。

较低完整性的主体无法写入较高完整性的主体，而较高完整性的主体无法列出或读取较低完整性的对象。将标签设置为最低等级可能会使对象无法访问。该安全策略模块的一些应用环境包括受限的 Web 服务器、开发与测试机器以及源代码仓库。较不常见的应用场景包括个人工作站、路由器或网络防火墙。

## 18.5.8. MAC Low-watermark 模块

模块名称：**mac\_lomac.ko**

内核配置行：`options MAC_LOMAC`

引导选项：`mac_lomac_load="YES"`

与 MAC Biba 策略不同，[mac\_lomac(4)](https://man.freebsd.org/cgi/man.cgi?query=mac_lomac\&sektion=4\&format=html) 策略仅在将完整性级别降低后，允许访问较低完整性的对象，以免破坏任何完整性规则。

低水位完整性策略几乎与 Biba 相同，唯一的不同是使用浮动标签来支持通过辅助等级分区对主体进行降级。这个次级分区的形式是 `[auxgrade]`。当为带有辅助等级的策略分配标签时，使用语法 `lomac/10[2]`，其中 `2` 为辅助等级。

该策略依赖于所有系统对象使用完整性标签的普遍标记，允许主体从低完整性对象读取，然后通过 `[auxgrade]` 将标签降级，以防止未来对高完整性对象进行写操作。该策略可能提供更好的兼容性，并且比 Biba 策略需要更少的初始配置。

像 Biba 和 MLS 策略一样，`setfmac` 和 `setpmac` 用于将标签应用于系统对象：

```sh
# setfmac /usr/home/trhodes lomac/high[low]
# getfmac /usr/home/trhodes lomac/high[low]
```

辅助等级 `low` 是 MACLOMAC 策略专有的功能。
