Skip to content
Tauri 中文网

隔离模式

隔离模式是一种在前端发送的 Tauri API 消息到达 Tauri Core 之前拦截和修改它们的方法,全部使用 JavaScript。隔离模式注入的安全 JavaScript 代码称为隔离应用。

¥The Isolation pattern is a way to intercept and modify Tauri API messages sent by the frontend before they get to Tauri Core, all with JavaScript. The secure JavaScript code that is injected by the Isolation pattern is referred to as the Isolation application.

为什么

¥Why

隔离模式的目的是为开发者提供一种机制,帮助保护他们的应用免受对 Tauri Core 的不必要或恶意的前端调用。隔离模式的需求源于来自在前端运行的不受信任的内容的威胁,这是具有许多依赖的应用的常见情况。有关应用可能看到的许多威胁源的列表,请参阅 安全性:威胁模型

¥The Isolation pattern’s purpose is to provide a mechanism for developers to help protect their application from unwanted or malicious frontend calls to Tauri Core. The need for the Isolation pattern rose out of threats coming from untrusted content running on the frontend, a common case for applications with many dependencies. See Security: Threat Models for a list of many sources of threats that an application may see.

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

¥The largest threat model described above that the Isolation pattern was designed in mind was Development Threats. Not only do many frontend build-time tools consist of many dozen (or hundreds) of often deeply-nested dependencies, but a complex application may also have a large amount of (also often deeply-nested) dependencies that are bundled into the final output.

何时

¥When

Tauri 强烈建议在可以使用隔离模式时使用它。由于 Isolation 应用会拦截来自前端的所有消息,因此始终可以使用它。

¥Tauri highly recommends using the isolation pattern whenever it can be used. Because the Isolation application intercepts all messages from the frontend, it can always be used.

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

¥Tauri also strongly suggests locking down your application whenever you use external Tauri APIs. As the developer, you can utilize the secure Isolation application to try and verify IPC inputs, to make sure they are within some expected parameters. For example, you may want to check that a call to read or write a file is not trying to access a path outside your application’s expected locations. Another example is making sure that a Tauri API HTTP fetch call is only setting the Origin header to what your application expects it to be.

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

¥That said, it intercepts all messages from the frontend, so it will even work with always-on APIs such as Events. Since some events may cause your own rust code to perform actions, the same sort of validation techniques can be used with them.

如何

¥How

隔离模式就是在前端和 Tauri Core 之间注入一个安全应用来拦截和修改传入的 IPC 消息。它通过使用 <iframe> 的沙盒功能与主前端应用一起安全地运行 JavaScript 来实现这一点。Tauri 在加载页面时强制执行隔离模式,强制所有对 Tauri Core 的 IPC 调用首先通过沙盒隔离应用进行路由。一旦消息准备好传递给 Tauri Core,就会使用浏览器的 SubtleCrypto 实现对其进行加密,然后传递回主前端应用。到达那里后,它会直接传递给 Tauri Core,然后像平常一样解密和读取。

¥The Isolation pattern is all about injecting a secure application in between your frontend and Tauri Core to intercept and modify incoming IPC messages. It does this by using the sandboxing feature of <iframe>s to run the JavaScript securely alongside the main frontend application. Tauri enforces the Isolation pattern while loading the page, forcing all IPC calls to Tauri Core to instead be routed through the sandboxed Isolation application first. Once the message is ready to be passed to Tauri Core, it is encrypted using the browser’s SubtleCrypto implementation and passed back to the main frontend application. Once there, it is directly passed to Tauri Core, where it is then decrypted and read like normal.

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

¥To ensure that someone cannot manually read the keys for a specific version of your application and use that to modify the messages after being encrypted, new keys are generated each time your application is run.

IPC 消息的大致步骤

¥Approximate Steps of an IPC Message

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

¥To make it easier to follow, here’s an ordered list with the approximate steps an IPC message will go through when being sent to Tauri Core with the Isolation pattern:

  1. Tauri 的 IPC 处理程序收到一条消息

    ¥Tauri’s IPC handler receives a message

  2. IPC 处理程序 -> 隔离应用

    ¥IPC handler -> Isolation application

  3. [sandbox] 隔离应用钩子运行并可能修改消息

    ¥[sandbox] Isolation application hook runs and potentially modifies the message

  4. [sandbox] 消息使用运行时生成的密钥通过 AES-GCM 加密

    ¥[sandbox] Message is encrypted with AES-GCM using a runtime-generated key

  5. [encrypted] 隔离应用 -> IPC 处理程序

    ¥[encrypted] Isolation application -> IPC handler

  6. [encrypted] IPC 处理程序 -> Tauri Core

    ¥[encrypted] IPC handler -> Tauri Core

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

¥Note: Arrows (->) indicate message passing.

性能含义

¥Performance Implications

由于确实发生了消息加密,因此与 Brownfield 模式 相比,即使安全隔离应用不执行任何操作,也会产生额外的开销成本。除了性能敏感的应用(它们可能具有一组精心维护的小型依赖,以保持足够的性能)外,大多数应用不应该注意到加密/解密 IPC 消息的运行时成本,因为它们相对较小,并且 AES-GCM 相对较快。如果你不熟悉 AES-GCM,那么在这种情况下,所有相关的内容是它是 SubtleCrypto 中包含的唯一经过身份验证的模式算法,并且你可能每天都在 TLS 中使用它。

¥Because encryption of the message does occur, there are additional overhead costs compared to the Brownfield pattern, even if the secure Isolation application doesn’t do anything. Aside from performance-sensitive applications (who likely have a carefully-maintained and small set of dependencies, to keep the performance adequate), most applications should not notice the runtime costs of encrypting/decrypting the IPC messages, as they are relatively small and AES-GCM is relatively fast. If you are unfamiliar with AES-GCM, all that is relevant in this context is that it’s the only authenticated mode algorithm included in SubtleCrypto and that you probably already use it every day under the hood with TLS.

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

¥There is also a cryptographically secure key generated once each time the Tauri application is started. It is not generally noticeable if the system already has enough entropy to immediately return enough random numbers, which is extremely common for desktop environments. If running in a headless environment to perform some integration testing with WebDriver then you may want to install some sort of entropy-generating service such as haveged if your operating system does not have one included. Linux 5.6 (March 2020) now includes entropy generation using speculative execution.

限制

¥Limitations

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

¥There are a few limitations in the Isolation pattern that arose out of platform inconsistencies. The most significant limitation is due to external files not loading correctly inside sandboxed <iframes> on Windows. Because of this, we have implemented a simple script inlining step during build time that takes the content of scripts relative to the Isolation application and injects them inline. This means that typical bundling or simple including of files like <script src="index.js"></script> still works properly, but newer mechanisms such as ES Modules will not successfully load.

建议

¥Recommendations

由于 Isolation 应用的目的是防止开发威胁,因此我们强烈建议你尽可能保持 Isolation 应用的简单性。你不仅应努力保持依赖最少,还应考虑保持所需的构建步骤最少。这样,你就不必担心在前端应用之上针对隔离应用的供应链攻击。

¥Because the point of the Isolation application is to protect against Development Threats, we highly recommend keeping your Isolation application as simple as possible. Not only should you strive to keep dependencies minimal, but you should also consider keeping required build steps minimal. This would allow you to not need to worry about supply chain attacks against your Isolation application on top of your frontend application.

创建隔离应用

¥Creating the Isolation Application

在此示例中,我们将制作一个小型 hello-world 风格的 Isolation 应用并将其连接到一个虚构的现有 Tauri 应用。它不会对通过它的消息进行验证,只会将内容打印到 WebView 控制台。

¥In this example, we will make a small hello-world style Isolation application and hook it up to an imaginary existing Tauri application. It will do no verification of the messages passing through it, only print the contents to the WebView console.

出于此示例的目的,让我们假设我们与 tauri.conf.json 位于同一目录中。现有的 Tauri 应用将其 distDir 设置为 ../dist

¥For the purposes of this example, let’s imagine we are in the same directory as tauri.conf.json. The existing Tauri application has it’s distDir set to ../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 configuration 以使用隔离模式,并且刚刚从 Brownfield 模式 引导到隔离模式。

¥Now, all we need to do is set up our tauri.conf.json configuration to use the Isolation pattern, and have just bootstrapped to the Isolation pattern from the Brownfield pattern.

配置

¥Configuration

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

¥Let’s assume that our main frontend distDir is set to ../dist. We also output our Isolation application to ../dist-isolation.

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

Tauri 中文网 - 粤ICP备13048890号