跳转到内容
Tauri

隔离模式

隔离模式是一种拦截和修改前端发送给 Tauri 核心的 Tauri API 消息的方法,所有这些都通过 JavaScript 实现。隔离模式注入的安全 JavaScript 代码被称为隔离应用程序。

为什么

隔离模式的目的是为开发者提供一种机制,帮助保护他们的应用程序免受不必要或恶意的对 Tauri 核心的前端调用。隔离模式的需求源于来自前端运行的不受信任内容的威胁,这是许多依赖项众多的应用程序的常见情况。请参阅安全:威胁模型,了解应用程序可能面临的各种威胁来源。

上述最大的威胁模型是隔离模式设计时考虑的开发威胁。不仅许多前端构建工具由许多(或数百个)通常深度嵌套的依赖项组成,而且复杂的应用程序也可能有大量(通常也是深度嵌套的)依赖项被打包到最终输出中。

何时

Tauri 强烈建议在可以使用隔离模式时使用它。因为隔离应用程序拦截所有来自前端的消息,它总是可以使用。

Tauri 还强烈建议在使用外部 Tauri API 时锁定你的应用程序。作为开发者,你可以利用安全的隔离应用程序来尝试验证 IPC 输入,确保它们在某些预期参数范围内。例如,你可能希望检查对读取或写入文件的调用是否尝试访问应用程序预期位置之外的路径。另一个例子是确保 Tauri API HTTP 获取调用仅将 Origin 标头设置为应用程序预期的值。

也就是说,它拦截所有来自前端的消息,因此它甚至可以与始终启用的 API 如事件一起工作。由于某些事件可能会导致你自己的 Rust 代码执行操作,因此可以使用相同的验证技术。

如何

隔离模式的核心是在前端和 Tauri 核心之间注入一个安全应用程序,以拦截和修改传入的 IPC 消息。它通过使用<iframe>的沙箱功能来安全地运行 JavaScript,与主前端应用程序并行。Tauri 在加载页面时强制执行隔离模式,强制所有对 Tauri 核心的 IPC 调用首先通过沙箱化的隔离应用程序。一旦消息准备好传递给 Tauri 核心,它将使用浏览器的SubtleCrypto实现进行加密,并传递回主前端应用程序。一旦到达那里,它将直接传递给 Tauri 核心,在那里它将被解密并像正常一样读取。

为了确保某人无法手动读取特定版本应用程序的密钥并使用它来修改加密后的消息,每次运行应用程序时都会生成新密钥。

IPC 消息的大致步骤

为了更容易理解,这里有一个有序列表,列出了使用隔离模式将 IPC 消息发送到 Tauri 核心时的大致步骤:

  1. Tauri 的 IPC 处理程序接收到一条消息
  2. IPC 处理程序 -> 隔离应用程序
  3. [沙箱] 隔离应用程序钩子运行并可能修改消息
  4. [沙箱] 消息使用运行时生成的密钥通过 AES-GCM 加密
  5. [加密] 隔离应用程序 -> IPC 处理程序
  6. [加密] IPC 处理程序 -> Tauri 核心

注意:箭头 (->) 表示消息传递。

性能影响

因为消息的加密确实会发生,所以与Brownfield 模式相比,存在额外的开销成本,即使安全的隔离应用程序什么也不做。除了性能敏感的应用程序(它们可能有一个精心维护的小型依赖集,以保持性能充足),大多数应用程序应该不会注意到加密/解密 IPC 消息的运行时成本,因为它们相对较小,且 AES-GCM 相对较快。如果你不熟悉 AES-GCM,在这个上下文中相关的只是它是SubtleCrypto中包含的唯一认证模式算法,你可能每天都在使用它,通过TLS

每次启动 Tauri 应用程序时,还会生成一个加密安全的密钥。如果系统已经有足够的熵立即返回足够的随机数,这通常不会引起注意,桌面环境非常常见。如果在无头环境中运行以使用 WebDriver 进行一些集成测试,那么你可能希望安装某种熵生成服务,如haveged,如果你的操作系统没有包含。Linux 5.6(2020 年 3 月)现在包括使用推测执行的熵生成。

限制

隔离模式中有一些限制是由于平台不一致性引起的。最显著的限制是由于外部文件在 Windows 上的沙箱化<iframe>中无法正确加载。因此,我们在构建时实现了一个简单的脚本内联步骤,该步骤获取与隔离应用程序相关的脚本内容并将其内联注入。这意味着典型的打包或简单包含文件如<script src="index.js"></script>仍然可以正常工作,但较新的机制如 ES 模块将不会成功加载。

建议

因为隔离应用程序的目的是保护开发威胁,我们强烈建议尽可能保持隔离应用程序的简单性。你不仅应该努力保持依赖项的最小化,还应该考虑保持所需的构建步骤最小化。这将使你不必担心对你的隔离应用程序的供应链攻击,以及你的前端应用程序。

创建隔离应用程序

在这个例子中,我们将创建一个小的 hello-world 风格的隔离应用程序,并将其连接到一个假想的现有 Tauri 应用程序。它不会验证通过它的消息,只会将内容打印到 WebView 控制台。

为了这个例子,我们假设我们在tauri.conf.json所在的目录中。现有的 Tauri 应用程序将其distDir设置为../dist

../dist-isolation/index.html

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Isolation Secure Script</title>
</head>
<body>
<script src="index.js"></script>
</body>
</html>

../dist-isolation/index.js

window.__TAURI_ISOLATION_HOOK__ = (payload) => {
// let's not verify or modify anything, just print the content from the hook
console.log('hook', payload);
return payload;
};

现在,我们需要做的就是设置我们的tauri.conf.json配置以使用隔离模式,并从Brownfield 模式引导到隔离模式。

配置

我们假设我们的主前端distDir设置为../dist。我们还输出我们的隔离应用程序到../dist-isolation

{
"build": {
"distDir": "../dist"
},
"app": {
"security": {
"pattern": {
"use": "isolation",
"options": {
"dir": "../dist-isolation"
}
}
}
}
}

© 2024 Tauri中文网

备案号:赣ICP备2020014263号-10