SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

FreeBSD 如何进行安全更新?基础系统与软件包补丁指南

FreeBSD 将基础系统与软件包更新分为两个独立流程。使用 freebsd-update 管理内核与用户空间,通过 pkg audit 检测第三方漏洞。本文详细说明了为何必须同时运行这两个工具,并解析了 FreeBSD 独特的补丁模型与版本检查命令,帮助 Linux 管理员避免因遗漏补丁导致的系统安全风险。

FreeBSD 如何处理安全更新

FreeBSD 使用两个独立的工具处理安全更新,因为 FreeBSD 服务器由两个独立的部分组成。基础系统(即随发行版一同发布的内核和用户空间)通过 freebsd-update 进行补丁更新。在此之上安装的所有内容均为软件包,软件包则通过 pkg 进行补丁更新。如果只运行其中一个而忽略另一个,机器将有一半处于未修补状态,且系统中没有任何提示。

SSD Nodes 不提供 FreeBSD 镜像。我们的方案运行 Linux。发布此文是因为读者群体高度重合:运行我们 Ubuntu 和 Debian 服务器的用户,通常也会在防火墙或其他遗留设备上运行 FreeBSD。这种分离的补丁模型是 Linux 管理员最容易混淆的地方,因此有必要记录下来。下文中的每条命令、公告格式和支持日期均已在 2026 年 8 月与 FreeBSD 安全页面及项目手册页核对。

在执行命令前请注意:FreeBSD 默认不在基础系统中安装 sudo。此处所有操作均需 root 权限。请使用 su -,或先通过软件包安装 sudodoas

基础系统与软件包是两个独立的范畴

在 Ubuntu 上,apt 管理整台机器。内核、opensslnginx 以及您自己的工具均作为 .deb 文件由同一个工具统一分发,并由 apt upgrade 进行整体更新。

FreeBSD 将其一分为二。基础系统作为一个整体进行构建和版本控制:15.1-RELEASE-p3 是一个单一的版本号,涵盖了内核、C 库、sshd 以及位于 /usr/lib 中的 OpenSSL 副本。这些组件均不来自 pkg。其他所有内容均位于 /usr/local 下,以从 ports 树构建的二进制软件包形式存在,并拥有各自的版本号。

因此,一台机器上可以同时存在两份 OpenSSL:位于 /usr/lib 中的基础副本(仅由 freebsd-update 修补),以及位于 /usr/local/lib 中的软件包副本(仅由 pkg 修补)。程序使用哪一个取决于它链接的是哪一个,而通过软件包安装的软件通常链接的是软件包副本。修补其中一个对另一个没有影响。

以下三个命令可用于确认当前状态:

freebsd-version -u
freebsd-version -k
uname -r

freebsd-version -u 用于打印已安装用户态工具的补丁级别。freebsd-version -k 用于打印已安装内核的补丁级别,而 freebsd-version(1) 则明确解释了为何它与 uname 不同:“如果已安装了新内核但系统尚未重启,freebsd-version 将打印新内核的版本和补丁级别”。uname -r 用于打印当前正在运行的内核。此外还有 freebsd-version -r,它同样打印正在运行的内核,但“不受环境变量影响”,这在 UNAME_r 通常被设置为其他值的 jail 环境中非常重要。

安全公告与勘误通知

FreeBSD 安全团队会发布两种不同类型的通知,其含义各不相同。

安全公告 (Security Advisory) 涵盖基础系统中的安全漏洞。其标识符格式如下 FreeBSD-SA-26:55.elf:字母 SA、两位年份、该年度内的递增编号,以及受影响的组件。FreeBSD-SA-26:52.if_wgFreeBSD-SA-26:50.kqueue 均发布于 2026-07-29。完整列表请见 FreeBSD 公告页面

勘误通知 (Errata Notice) 涵盖值得推送到发布分支的正确性或稳定性问题,且不涉及安全影响。其格式与安全公告相同,仅将 EN 替换为 SA:例如 FreeBSD-EN-26:19.zfsFreeBSD-EN-26:18.tzdata。时区数据更新是典型的例子。过期的时区数据不会导致系统被攻击,但在应用修复前,您的时间戳将显示错误。勘误通知列于 FreeBSD 勘误通知页面

这两种通知均由安全官的 PGP (Pretty Good Privacy) 密钥签名,并归档于 security.FreeBSD.org,同时通过 freebsd-update 交付至您的机器。

以下内容是 Linux 管理员容易忽略的部分:这两种通知均不涵盖软件包。 安全页面明确指出:FreeBSD Ports Collection 中的问题“在 FreeBSD VuXML 文档中单独说明”。nginx 软件包中的远程漏洞永远不会获得 SA 编号。如果您仅关注安全公告订阅源,将无法获知此类漏洞。

如何获取 FreeBSD 安全更新通知?

请订阅 freebsd-security-notifications 邮件列表。该列表经过审核且流量较低,会直接发布安全公告和勘误通知。请访问 lists.freebsd.org 进行订阅。

freebsd-announce 同样经过审核,除发布安全公告外还会推送版本发布信息,如果您希望通过单一列表获取所有通知,该列表更为合适。freebsd-security 是讨论列表。虽然阅读该列表很有价值,但它并非获取补丁更新通知的渠道。

以上列表仅提供基础系统的相关新闻。软件包漏洞信息不会通过邮件发送。您需要通过运行命令来查询此类信息。

pkg audit 与其背后的数据库

VuXML(漏洞与暴露标记语言)是 FreeBSD 项目记录 ports 和软件包安全问题的档案。每条记录都指明了受影响的软件包、存在漏洞的版本范围、CVE(通用漏洞与披露)标识符以及简要说明。您可以在 VuXML 索引 中浏览完整列表,并按软件包、CVE 或日期进行排序。

pkg audit 是读取该数据库的工具:

pkg audit -F

-F 会在检查前获取数据库的最新副本。请务必每次都使用该参数。如果不使用 -F,您将仅针对机器上现有的副本进行比对,该副本可能已过期数月,因此显示“无漏洞”的结果没有任何意义。该命令会将每个已安装的软件包版本与所有 VuXML 条目进行比对,打印出每个匹配项及其 CVE 编号和 VuXML 页面链接,最后输出一行统计信息,告知您在多少个已安装的软件包中发现了多少个问题。

pkg-audit(8) 中还有两个值得了解的标志。pkg audit -r 还会“打印出依赖于受漏洞影响软件包的软件包,因此它们也可能存在漏洞”,通过这种方式,您可以了解到某个存在漏洞的库之所以重要,是因为有六个已安装的程序链接了它。pkg audit -R 会以 JSON 或其他机器可读格式打印相同的结果,这正是监控检查所需的输入。

pkg 软件包会在 /usr/local/etc/periodic/security/410.pkg-audit 安装一个周期性脚本。它作为每日安全检查的一部分运行,并将结果通过邮件发送给 root 用户。请在 /etc/periodic.conf 中添加一行配置以确认其已开启:

daily_status_security_pkgaudit_enable="YES"

那封每日邮件是 FreeBSD 最接近 Ubuntu 上 unattended-upgrades 习惯 的功能,而两者的区别正是核心所在:unattended-upgrades 会在您睡眠时自动安装修复程序,而 pkg audit 只会通知您需要修复。pkg audit 仅负责报告。它从不进行补丁安装。 在标准的 FreeBSD 系统中,没有任何程序会在未经您允许的情况下自动安装安全更新。

修复存在漏洞的软件包

pkg update
pkg upgrade

FreeBSD 软件包仓库中没有仅包含安全更新的存储库。Ubuntu 可以仅从 noble-security 拉取更新,而保持其他软件包版本不变。FreeBSD 没有类似的机制,因此修复一个存在漏洞的软件包,意味着必须同时更新仓库中当前提供的该软件包及其所有关联依赖。请将软件包补丁更新视为一次变更操作,而非后台任务。

您所处的仓库分支决定了修复程序到达的速度。默认分支为 quarterly,手册中将其描述为“提供更可预测且稳定的体验”,因为它仅接受非功能性的更新。latest 分支则会获取所有软件的最新版本。因此,当 pkg audit -F 报告某个软件包存在漏洞,而 pkg upgrade 显示无需更新时,说明修复程序尚未发布到您当前的分支,这就是导致困惑的原因所在。

若要将机器切换到 latest 分支,请复制系统自带的仓库配置文件并进行编辑:

mkdir -p /usr/local/etc/pkg/repos
cp /etc/pkg/FreeBSD.conf /usr/local/etc/pkg/repos/FreeBSD.conf

将副本中 url 行的 quarterly 修改为 latest,然后运行 pkg update -f 拉取新的目录信息。请直接复制该文件,不要凭记忆输入仓库名称:/etc/pkg/FreeBSD.conf 内部的名称才是系统实际使用的名称,而 /usr/local/etc/pkg/repos 下的文件仅会覆盖名称完全匹配的仓库。

应用基础系统补丁

freebsd-update fetch
freebsd-update install

fetch 会下载当前发行版的补丁并列出将要更改的文件。若无更新,它会输出 No updates needed to update system to 15.1-RELEASE-p3. 并退出。若有更新,它会在结束时提示您运行安装命令。在运行 freebsd-update install 之前不会应用任何更改,因此随时运行 fetch 都是安全的。

freebsd-update(8) 仅为 ALPHA、BETA、RC 和 RELEASE 版本提供二进制更新,不适用于 PRERELEASE、STABLE 或 CURRENT 版本。如果您跟踪 stable/15,则需要从源码构建,该工具不适用。

建议将下载过程自动化,并保留手动安装。手册中关于 /etc/crontab 的配置行如下:

@daily                                  root    freebsd-update cron

freebsd-update cron 会随机等待 1 到 3600 秒,然后执行与 fetch 相同的下载操作,并在有更新待处理时向 root 发送邮件。设置随机等待是为了避免互联网上所有的 FreeBSD 机器在同一秒内访问更新镜像源。

输出中的两点常引起困惑。src component not installed, skipped 在没有源码树的服务器上是正常现象,并非错误。组件集由 /etc/freebsd-update.conf 文件中的 Components 行控制,可选值包括 srcworldkernel

如果安装过程出现异常,freebsd-update rollback 可以卸载最近安装的补丁。若使用 ZFS 根文件系统,更好的做法是先创建一个引导环境:

bectl create pre-patch
freebsd-update fetch install

如果打补丁后的系统无法启动,可在引导加载程序菜单中选择旧的引导环境,即可恢复到更新前的状态。这种回退机制是 将 ZFS 作为根文件系统 的实际优势之一,且在两个环境产生差异之前,几乎不占用额外的磁盘空间。

我的 FreeBSD 版本是否仍在支持期内?

每个版本都有固定的支持周期,发布在安全页面的分支表中。截至 2026 年 8 月,该表内容如下:

  • releng/15.1,即 15.1-RELEASE,支持至 2027 年 3 月 31 日
  • releng/15.0,即 15.0-RELEASE,支持至 2026 年 9 月 30 日
  • releng/14.4,即 14.4-RELEASE,支持至 2026 年 12 月 31 日
  • stable/15,支持至 2029 年 12 月 31 日
  • stable/14,支持至 2028 年 11 月 30 日

小版本更新的支持周期较短。15.0-RELEASE 将在本文发布约七周后停止支持,因为 15.1 的发布已为其设定了倒计时。稳定分支(stable branches)支持周期长达数年,它们是源代码分支,freebsd-update 不提供这些分支的二进制包。

使用 freebsd-version -u 查看当前版本并与上表对比。freebsd-update 也会发出警告。临近截止日期时,fetch 会输出:

WARNING: FreeBSD 15.0-RELEASE is approaching its End-of-Life date.
It is strongly recommended that you upgrade to a newer
release within the next 2 months.

日期过后,警告将变为 WARNING: FreeBSD 15.0-RELEASE HAS PASSED ITS END-OF-LIFE DATE.。不受支持的版本仍可继续运行,但不再接收安全公告,这意味着后续出现的任何基础系统漏洞都将永久存在于你的系统中。

升级版本需依次执行 freebsd-update -r 15.1-RELEASE upgradefreebsd-update install,随后重启,再次执行 freebsd-update install,接着运行 pkg-static upgrade -f 以针对新库重装所有软件包,最后执行 freebsd-update install。手册指出,根据库版本号是否变更,安装阶段可能只有两个而非三个。请预留维护窗口,并在开始前阅读 FreeBSD 15 服务器设置指南

重启系统,还是重启服务就足够了?

FreeBSD 通过以下对比来回答这个问题:

freebsd-version -k
uname -r

freebsd-version -k 是磁盘上的内核。uname -r 是内存中运行的内核。如果字符串不同,说明已安装新内核但尚未运行,此时必须重启。如果字符串一致,说明补丁未涉及内核,重启没有任何意义。

对于用户态补丁,请重启所有使用该补丁代码的服务。对 /usr/lib 中基础 OpenSSL 的修复,对于三周前启动且仍在地址空间中映射旧库的 sshd 进程无效。磁盘上的文件已更新,但运行中的进程并未更新。

service sshd restart

同样的规则适用于软件包。pkg upgrade 会替换磁盘上的二进制文件,但运行中的进程仍在使用旧文件,因此 service nginx restart 是使修复生效的必要步骤。

基础系统没有类似 Debian 中 needrestart 的机制,因此没有任何提示,也不会维护相关列表。要么手动跟踪哪些服务链接了已修补的库,要么在任何涉及基础库的补丁更新后重启系统。对于配置已纳入版本控制的服务器,重启是常规操作,且远比“自认为已修补但实际并未生效”的风险代价更小。

为运行 jail 的机器打补丁

jail 与宿主机共享内核,因此内核安全公告属于宿主机问题,该机器上的所有 jail 都会受到影响。更新宿主机并重启后,所有 jail 的内核侧更新即告完成。每个 jail 内部的用户态是独立的安装环境,拥有各自的补丁版本,可通过 freebsd-version -j <jail> 在宿主机上查看。jail 内部的软件包也是独立的,可通过 pkg -j <jail> audit -F 在不进入 jail 的情况下进行审计。这种共享内核与独立用户态的架构差异,正是决定 jail 与 Docker 容器对比 的核心结构性区别。

Ubuntu 的翻译

FreeBSD 的每种习惯都有对应项,因此您可以双向迁移操作流程。

  • 基础系统补丁:先执行 freebsd-update fetch,再执行 freebsd-update install。在 Ubuntu 上,使用 apt update && apt upgrade,它会同时更新基础系统及所有其他组件。
  • 第三方软件:FreeBSD 上使用 pkg update && pkg upgrade。在 Ubuntu 上,同样使用 apt
  • 已知漏洞检查:FreeBSD 上使用 pkg audit -F。在 Ubuntu 24.04 上,最接近的命令是 pro security-status,它会显示已安装软件包的安全更新,包括扩展安全维护(Expanded Security Maintenance)内容。
  • 自动安装:Ubuntu 上的 unattended-upgrades 会为您应用安全更新。FreeBSD 没有等效功能,因此 freebsd-update cron 仅负责下载并发送邮件,安装仍需手动完成。
  • 公告订阅源:freebsd-security-notifications 提供 FreeBSD-SA 和 FreeBSD-EN 条目。ubuntu-security-announce 提供 Ubuntu 安全公告。
  • 漏洞数据库:FreeBSD ports 和软件包使用 VuXML。Ubuntu 软件包使用 Ubuntu CVE 追踪器。
  • 重启检查:FreeBSD 上使用 freebsd-version -k 对比 uname -r。Ubuntu 上则检查 /var/run/reboot-required 是否存在。
  • 支持周期:FreeBSD 安全页面上的分支表。Ubuntu 上则是发布计划和 pro security-status

这两个系统的底层流程完全一致:订阅公告源、按计划运行审计,然后决定安装内容及重启时间。FreeBSD 只是要求您明确执行后半部分操作,因为它不会自动为您完成。Linux 与 FreeBSD 作为服务器平台的更广泛对比 涵盖了在两者之间迁移工作负载时其他需要变更的内容。

FAQ

freebsd-update 会同时修补我的软件包吗?

不会。freebsd-update 仅涵盖基础系统,即随发行版一同发布的内核和用户态程序。通过 /usr/local 安装的软件来自软件包,需使用 pkg upgrade 进行修补。请运行 pkg audit -F 查看已安装软件包中是否存在已知漏洞,因为基础系统的安全公告从不提及这些内容,安全邮件列表也不会发布相关通知。

我如何知道 FreeBSD 更新是否需要重启?

比较 freebsd-version -kuname -r 的输出。前者显示磁盘上安装的内核版本,包括刚写入但尚未引导的版本;后者显示当前正在运行的内核版本。字符串不同则意味着需要重启。如果字符串一致,说明补丁仅涉及用户态,此时只需重启受影响的服务即可(例如使用 service sshd restart),因为正在运行的进程会保持旧库的映射,直到进程重启。

安全公告(Security Advisory)和勘误通知(Errata Notice)有什么区别?

安全公告(如 FreeBSD-SA-26:55.elf)用于修复基础系统中的安全漏洞。勘误通知(如 FreeBSD-EN-26:18.tzdata)用于修复不涉及安全问题的正确性或稳定性缺陷,例如过时的时区数据。两者均采用“年份:序号:组件”的格式。两者均由安全官签署并由 freebsd-update 发布,且均不涵盖通过 ports 或软件包安装的软件。

FreeBSD 有类似 unattended-upgrades 的工具吗?

基础系统中没有。freebsd-update cron 仅下载待处理的基础系统补丁并发送邮件给 root 用户,它不会自动安装。pkg 安装的周期性脚本会每天运行 pkg audit 并通过邮件发送结果,它也不会自动升级任何内容。无人值守安装需要您通过 cron 任务自行实现;此外,由于 FreeBSD 软件包升级通常获取最新版本而非仅针对安全问题的反向移植,大多数管理员会选择阅读邮件并手动安装。

我该如何检查我的 FreeBSD 发行版是否仍在支持期内?

运行 freebsd-version -u 查看您的用户态版本,然后将其与 FreeBSD 安全页面上的支持分支表进行对比。小版本发行版的支持周期较短:截至 2026 年 8 月,15.0-RELEASE 的支持于 2026 年 9 月 30 日结束,而 15.1-RELEASE 的支持持续到 2027 年 3 月 31 日。freebsd-update fetch 会在日期临近时发出警告,一旦日期过期,它会打印一行提示,说明该发行版已超过生命周期终止日期(HAS PASSED ITS END-OF-LIFE DATE)。此后,将不再有任何安全公告适用于您的系统。

#freebsd#安全#patching#advisories#pkg