Files
wehub-resource-sync 19dc5d82a0
Rust / build (push) Failing after 1s
Rust / docker (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:29:44 +08:00

17 KiB
Raw Permalink Blame History

English | 简体中文

安全

RustNet 处理不受信任的网络数据,因此纵深防御至关重要。本文档描述了已实现的安全措施。

目录

Landlock 沙箱(Linux

在 Linux 5.13+ 上,RustNet 使用 Landlock 在初始化后限制自身的 Linux capabilities。这样即使包解析存在漏洞被利用,也能限制损害范围。

受限制的内容

限制项 内核版本 描述
文件系统 5.13+ /proc 可读(用于进程识别)
网络 6.4+ 禁止 TCP bind/connectRustNet 为被动模式)
Linux capabilities 任意 pcap socket 打开后丢弃 CAP_NET_RAW
Linux capabilities 任意 eBPF 程序加载后丢弃 CAP_BPFCAP_PERFMONCAP_SYS_ADMIN
root uid 任意 以 root 启动时(如 sudo rustnet),初始化完成后降权到调用用户(SUDO_UID/SUDO_GID)或 nobody
特权 3.5+ PR_SET_NO_NEW_PRIVS 由 RustNet 自身设置——始终生效,即使使用 --no-sandbox——防止通过 setuid 二进制文件提升特权

工作原理

  1. 初始化阶段RustNet 加载 eBPF 程序、打开包捕获句柄、创建日志文件
  2. 特权锁定:设置 PR_SET_NO_NEW_PRIVS(即使禁用沙箱也会应用)
  3. Linux capabilities 剥离:移除 CAP_NET_RAWCAP_BPFCAP_PERFMONCAP_SYS_ADMIN
  4. root uid 降权:以 root 运行时,通过 setresuid/setresgid 切换到调用 sudo 的用户(或 nobody)。已打开的捕获 socket、eBPF 程序和日志/导出文件继续有效。在没有 Landlock 的内核上,这是主要的隔离手段
  5. Landlock:限制文件系统和网络访问

安全收益

如果攻击者利用 DPI/包解析中的漏洞:

  • 无法读取任意文件(凭据、配置等)
  • 无法写入文件系统(除配置的日志路径外)
  • 无法建立出站 TCP 连接(阻止数据外泄)
  • 无法绑定 TCP 端口(阻止反向 shell)
  • 无法创建新的 raw socketLinux capabilities 已剥离)
  • 无法通过 setuid 二进制文件提升特权(PR_SET_NO_NEW_PRIVS,即使使用 --no-sandbox 也会设置)
  • 不以 root 运行:使用 sudo rustnet 时进程会切换为调用用户,即使在没有 Landlock 的内核上,攻击者也无法获得 root

CLI 选项

--no-sandbox        禁用 Landlock 沙箱、Linux capabilities 剥离和 root uid 降权
                    (仍会设置 PR_SET_NO_NEW_PRIVS
--sandbox-strict    要求完整沙箱强制生效,否则退出
--no-uid-drop       初始化后保持 root 运行,
                    不降权到 SUDO_UID/SUDO_GID(或 nobody

root uid 降权的权衡:降权后,procfs 回退路径的进程归属只能检查目标用户拥有的进程, /var/log/pods 下的 Kubernetes 日志目录也可能不可读。eBPF 快速路径(默认)不受影响。 如果依赖纯 procfs 归属(如未启用 eBPF 的构建)且需要归属其他用户的进程,请使用 --no-uid-drop

优雅降级

  • Kernel < 5.13:跳过沙箱,记录警告
  • Kernel 5.13-6.3:仅文件系统限制
  • Kernel 6.4+:完整的文件系统 + 网络限制
  • Docker:Landlock 可能受限;应用正常运行

Seatbelt 沙箱(macOS

在 macOS 10.5+ 上,RustNet 使用 Seatbeltsandbox_init_with_parameters)在初始化后限制自身能力。这样即使包解析存在漏洞被利用,也能限制损害范围。

受限制的内容

限制项 描述
出站网络 TCP/UDP 出站被阻止;Unix socketMach IPC)允许
文件系统读取 禁止读取用户主目录(/Users/var/root);GeoIP 路径显式允许
文件系统写入 禁止写入所有用户主目录(/Users/var/root
文件系统写入 仅配置的日志、JSON log、PCAP 和 PCAPNG 导出路径可写
进程执行 /usr/sbin/lsof 外,禁止执行所有二进制文件
root uid 以 root 启动时(如 sudo rustnet),初始化完成后降权到调用用户(SUDO_UID/SUDO_GID)或 nobody

工作原理

  1. 初始化阶段RustNet 打开包捕获句柄(BPF/PKTAP)并创建日志文件
  2. 预创建PCAP sidecar 文件(.connections.jsonl)和 PCAPNG 输出文件在沙箱应用前创建,因此其路径已经是有效的允许目标;同时移交给降权目标用户,确保降权后仍可写入
  3. root uid 降权:以 root 运行时,通过 setgid/setuid 切换到调用 sudo 的用户(或 nobody)。已打开的捕获和日志/导出文件描述符继续有效
  4. 沙箱应用:调用 sandbox_init_with_parameters;已打开的文件描述符保持不变,仅限制未来的操作

配置文件策略

RustNet 使用 默认允许 的 SBPL 配置文件配合针对性拒绝。拒绝默认的配置文件需要显式将所有系统库、Mach 端口、区域设置数据、字体和其他 OS 内部组件加入白名单——脆弱且容易出错。默认允许配合针对性拒绝覆盖了主要威胁(凭据窃取、数据外泄、shell 逃逸),同时避免操作风险。具体的拒绝规则阻止对用户主目录下的文件读/写、出站网络连接,以及除 /usr/sbin/lsof 外所有二进制文件的执行。

输出文件支持

--json-log--pcap-export--pcapng-export 路径通过运行时参数(JSON_LOG_PATHPCAP_PATHPCAP_JSONL_PATHPCAPNG_PATH)传递给 SBPL 配置文件。配置文件为每个路径授予显式的 allow file-write* 规则,该规则通过 SBPL 的特异性优先于更宽泛的 /Users 拒绝规则。未使用的参数默认为 /dev/null

三个标志在沙箱内均可正常工作。

安全收益

如果攻击者利用 DPI/包解析中的漏洞:

  • 无法读取 /Users 下的 SSH 密钥、AWS 凭据、浏览器配置文件或其他凭据文件
  • 无法写入 /Users 下的 SSH 密钥、AWS 凭据、浏览器配置文件或其他凭据文件
  • 无法建立出站 TCP/UDP 连接(阻止数据外泄)
  • 无法打开新的 raw network socket
  • 无法执行二进制文件(不能通过 /bin/sh/usr/bin/curl 等逃逸 shell
  • 不以 root 运行:使用 sudo rustnet 时进程会切换为调用用户

CLI 选项

--no-sandbox        禁用 Seatbelt 沙箱和 root uid 降权
--sandbox-strict    要求完整沙箱强制生效,否则退出
--no-uid-drop       初始化后保持 root 运行,
                    不降权到 SUDO_UID/SUDO_GID(或 nobody

root uid 降权的权衡:默认的 PKTAP 归属路径不受影响(进程元数据随已打开的捕获 fd 带内到达),但 lsof 回退路径(PKTAP 不可用时启用,例如显式指定 --interface) 降权后只能看到目标用户的进程。如果依赖 lsof 归属其他用户的进程,请使用 --no-uid-drop

为什么默认使用 BestEffort

sandbox_init_with_parameters 是 macOS 的私有(未公开)API。自 macOS 10.5 以来一直保持稳定,Chromium、Firefox 和 Safari 都使用它进行进程沙箱,但理论上可能在没有通知的情况下发生变化。BestEffort 在 API 行为异常时优雅降级,而不是阻止应用运行。使用 --sandbox-strict 可要求沙箱生效,否则中止。

剪贴板行为

与 Linux Landlock 不同,在 Seatbelt 下剪贴板复制(c 键)正常工作。macOS 剪贴板使用 NSPasteboard,通过 Mach IPC 在 Unix domain socket 上通信——SBPL 配置文件显式允许 (network-outbound (remote unix-socket))

在 Linux 上,剪贴板需要访问 Wayland socket/run/user/UID/wayland-0)或 X11 socket/tmp/.X11-unix/)。Landlock 的拒绝默认模型会阻止这些,因为它们不在写路径的允许列表中,因此当 Landlock 激活时剪贴板不可用。

FreeBSD 沙箱

FreeBSD 当前未启用沙箱。计划使用 cap_enter() 配合 libcasper 实现完整的 Capsicum 沙箱,用于特权进程查找——详见 ROADMAP.md

root uid 降权

在 Capsicum 落地之前,FreeBSD 上的主要隔离手段是 root 降权:以 root 启动时(如 sudo rustnet),BPF 捕获设备打开后,进程通过 setresuid/setresgid 降权到调用用户(SUDO_UID/SUDO_GID)或 nobody。已打开的捕获和日志/导出文件描述符继续有效,预创建的导出文件会移交给目标用户。注意 doas 不设置 SUDO_UID,因此 doas 用户会回退到 nobody

权衡:进程归属使用 sockstat,非 root 用户只能看到目标用户的 socket。如需归属其他用户的进程,请使用 --no-uid-drop

--no-uid-drop       初始化后保持 root 运行,
                    不降权到 SUDO_UID/SUDO_GID(或 nobody

权限剥离与 Job Object 沙箱(Windows

在 Windows 上,RustNet 在初始化后从进程令牌中移除危险特权,并应用 Job Object 阻止子进程创建。

受限制的内容

限制项 描述
特权移除 永久移除 SeDebugPrivilege、SeTakeOwnershipPrivilege、SeBackupPrivilege、SeRestorePrivilege 等危险特权
子进程 Job Object 阻止创建子进程(反向 shell、基于 exec 的数据外泄)

工作原理

  1. 初始化阶段RustNet 打开 Npcap 句柄并创建日志文件
  2. 特权移除AdjustTokenPrivileges 配合 SE_PRIVILEGE_REMOVED 永久从进程令牌中剥离危险特权
  3. Job Object:应用 JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 1 的 Job Object,阻止任何子进程创建

安全收益

如果攻击者利用 DPI/包解析中的漏洞:

  • 无法调试其他进程(SeDebugPrivilege 已移除)
  • 无法取得任意文件的所有权(SeTakeOwnershipPrivilege 已移除)
  • 无法通过 ACL 绕过读取文件(SeBackupPrivilege 已移除)
  • 无法生成子进程(cmd.exe、powershell.exe、curl.exe —— 被 Job Object 阻止)
  • 无法加载内核驱动(SeLoadDriverPrivilege 已移除)

局限性

Windows 沙箱弱于 Linux/macOS/FreeBSD

  • 无文件系统限制 —— Windows 缺少与 Landlock 或 Seatbelt 等效的进程级文件系统沙箱
  • 无网络限制 —— 阻止出站会中断 Npcap 包捕获
  • 特权移除仅影响提升进程已拥有的特权

CLI 选项

--no-sandbox        禁用特权移除和 Job Object
--sandbox-strict    要求完整沙箱强制生效,否则退出

权限需求

RustNet 需要特权访问来捕获网络数据包:

平台 需求
Linux CAP_NET_RAW 这项 Linux capability 或 root
macOS Root 或 BPF 组成员(access_bpf 组)
Windows Administrator(用于 Npcap
FreeBSD Root 或 BPF 设备访问

为什么需要特权

  • Raw socket 访问 —— 在低层拦截网络流量(只读、非混杂模式)
  • BPF 设备访问 —— 将包过滤器加载到内核
  • eBPF 程序 —— 可选的内核探针,用于增强进程追踪(仅限 Linux)

推荐:基于 Linux capabilities 的执行(Linux

与其以 root 运行,不如仅授予所需的 Linux capabilities

# 现代 Linux5.8+):包捕获 + eBPF
sudo setcap 'cap_net_raw,cap_bpf,cap_perfmon+eip' $(which rustnet)

# 仅包捕获(eBPF 会回退到 procfs
sudo setcap cap_net_raw+eip $(which rustnet)

旧版 pre-5.8 内核需要宽泛的 CAP_SYS_ADMIN 才能执行 eBPF 操作。RustNet 的安装包不会自动授予该 capability;除非你明确接受该风险,否则请只授予 CAP_NET_RAW 并使用 procfs 回退。沙箱应用后,CAP_NET_RAW 和 eBPF 加载相关 capabilities 会被丢弃——进程仅保留所需的最小特权。

只读操作

RustNet 仅监控流量,不会:

  • 修改数据包
  • 阻断连接
  • 注入流量
  • 更改路由表
  • 更改防火墙规则

包捕获以非混杂、只读模式打开。

不主动对外通信

RustNet 完全在本地运行:

  • 无遥测或分析
  • 无网络请求(除监控的流量外)
  • 无云服务或远程 API
  • 所有数据保留在你的系统上

日志文件隐私

日志文件可能包含敏感信息:

  • IP 地址和端口
  • 主机名和 SNI 数据
  • 进程名和 PID
  • DNS 查询和响应

最佳实践:

  • 默认禁用日志记录(不使用 --log-level 标志)
  • 保护日志目录权限
  • 实施日志轮转和保留策略
  • 分享前检查日志中的敏感数据

eBPF 安全

使用 eBPF 进行增强型进程检测时(Linux 默认):

  • 现代内核需要额外的 Linux capabilitiesCAP_BPFCAP_PERFMON
  • eBPF 程序在加载前由内核验证
  • 仅限只读操作(不修改数据包)
  • 如果 eBPF 失败,自动回退到 procfs

威胁模型

RustNet 防护的内容:

  • 未经授权的用户无法在没有适当权限的情况下捕获数据包
  • 基于 Linux capabilities 的权限限制了被入侵后的影响范围
  • LandlockLinux)和 SeatbeltmacOS)沙箱限制潜在的漏洞利用

RustNet 不防护的内容:

  • 拥有包捕获权限的用户可以看到所有未加密的流量
  • Root/Administrator 用户可以直接修改 RustNet 或捕获数据包
  • 对机器的物理访问可以捕获数据包
  • 网络级攻击(RustNet 是监控工具,不是安全设备)

以 Root 身份运行时的沙箱

LandlockLinux)和 SeatbeltmacOS)即使在 RustNet 以 root(UID 0)运行时也会强制执行限制。沙箱一旦应用就无法从进程内部撤销——在 Linux 上,RustNet 会在应用任何限制之前直接设置 PR_SET_NO_NEW_PRIVS(Landlock 也需要并会同样设置它),该设置对每个进程不可逆,并且即使使用 --no-sandbox 也会应用。

然而,沙箱不能防护供应链攻击。被入侵的二进制文件可以直接不应用沙箱。Root 也可以:

  • 传递 --no-sandbox 完全跳过沙箱(PR_SET_NO_NEW_PRIVS 除外)
  • 卸载 Landlock LSM 内核模块
  • 在 macOS 上禁用 SIP(控制沙箱强制执行)
  • 使用 ptrace 修改运行中的进程

因此,强烈建议使用细粒度 Linux capabilitiessetcap cap_net_raw=eip)运行,而不是以 root 运行。

供应链安全

RustNet 采取以下措施防护供应链攻击:

  • 依赖锁文件Cargo.lock 已提交到仓库,固定所有传递依赖版本并记录源校验和。这防止静默版本升级。
  • 安全审计cargo deny check 在每次 push 和 pull request 时于 CI 中运行,对照 RustSec Advisory Database 检查依赖,并强制执行许可证、来源和通配符版本策略(deny.toml)。一个每日定时工作流会针对已提交的 Cargo.lock 重新检查安全公告,因此新发布的公告无需 push 即可被发现。
  • CI action 固定:所有 GitHub Actions 均通过 commit SHA(而非标签)固定,防止对上游 action 的标签重写攻击。
  • 保守的依赖策略:新依赖需要说明理由,并审查其维护状态和安全记录(参见 CONTRIBUTING.zh-CN.md)。
  • 构建时完整性Windows Npcap SDK 下载在 build.rs 中对照硬编码的 SHA256 校验和进行验证。
  • 代码签名macOS 发布版本使用 Apple Developer 证书签名并进行公证。
  • 校验和验证:所有打包工作流(Homebrew、Chocolatey、AUR)在发布前计算并双重验证 SHA256 校验和。

局限性

  • cargo install rustnet 从 crates.io 获取最新兼容版本,并使用 Cargo.lock。从源码构建的用户应验证源 tarball 校验和。
  • 构建脚本(build.rs)和 proc-macros 在编译时执行任意代码。虽然所有当前依赖都是久经考验的 crate,但这是 Rust 构建模型的固有风险。

审计与合规

对于生产环境:

  • 审计记录谁以包捕获权限运行 RustNet
  • 网络监控策略和数据保护法规合规
  • 对特权网络访问进行用户访问审查
  • 通过配置管理系统实现自动化 Linux capabilities 管理

报告安全问题

请通过 GitHub Issues 报告安全漏洞,或直接与维护者联系。