如何使用 Cloudflare Worker 实施安全标头?

利用 Cloudflare Workers 实施安全 HTTP 标头

本文将详细介绍如何借助 Cloudflare Workers 在 Cloudflare 托管的网站上部署安全 HTTP 响应标头。

通过设置 HTTP 响应标头,可以有效防御诸如 XSS 跨站脚本攻击、点击劫持、MIME 嗅探以及跨站注入等常见网络安全威胁。 这是一种被广泛认可和推荐的安全实践,OWASP 组织也对此给予了肯定。 (OWASP)

过去,我们探讨过如何在 Apache、Nginx 和 IIS 等 Web 服务器上配置标头。 然而,如果您选择 Cloudflare 作为网站的保护和增强方案,那么您可以充分利用 Cloudflare Workers 来灵活操作 HTTP 响应标头。

Cloudflare Workers 是一种无服务器平台,允许您运行 JavaScript、C、C++ 和 Rust 等多种编程语言编写的代码。它在全球超过 200 个 Cloudflare 数据中心进行部署。

部署过程简单且灵活。 您可以根据需要,将标头应用于整个站点,包括子域,或者通过使用正则表达式进行 匹配模式

在本次演示中,我们将使用来自斯科特·赫尔姆的 代码

让我们开始吧! 👨‍💻

  • 首先,登录到您的 Cloudflare 账户并访问 Workers ( 直接链接)

  • 接下来,复制 GitHub 上的 worker.js 代码,并将其粘贴到脚本编辑器中。
const securityHeaders = {
        "Content-Security-Policy": "upgrade-insecure-requests",
        "Strict-Transport-Security": "max-age=1000",
        "X-Xss-Protection": "1; mode=block",
        "X-Frame-Options": "DENY",
        "X-Content-Type-Options": "nosniff",
        "Referrer-Policy": "strict-origin-when-cross-origin"
    },
    sanitiseHeaders = {
        Server: ""
    },
    removeHeaders = [
        "Public-Key-Pins",
        "X-Powered-By",
        "X-AspNet-Version"
    ];

async function addHeaders(req) {
    const response = await fetch(req),
        newHeaders = new Headers(response.headers),
        setHeaders = Object.assign({}, securityHeaders, sanitiseHeaders);

    if (newHeaders.has("Content-Type") && !newHeaders.get("Content-Type").includes("text/html")) {
        return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: newHeaders
        });
    }

    Object.keys(setHeaders).forEach(name => newHeaders.set(name, setHeaders[name]));

    removeHeaders.forEach(name => newHeaders.delete(name));

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

addEventListener("fetch", event => event.respondWith(addHeaders(event.request)));

请先不要急于保存。 您可能需要根据自身的需求调整以下标头。

Content-Security-Policy – 您可以在此处配置您的应用程序策略。

例如,如果您需要在多个 URL 上通过 iFrame 获取内容,您可以使用 frame-ancestors,如下所示:

"Content-Security-Policy" : "frame-ancestors 'self' gf.dev techblik.com.com",
  

以上配置将允许从 gf.dev、techblik.com.com 以及本站 (self) 加载内容。

X-Frame-Options – 如果您需要在同一网站的某些页面上使用 iframe 显示您网站的内容,可以将其更改为 SAMEORIGIN

"X-Frame-Options": "SAMEORIGIN",
  

Server – 您可以在此处清理服务器标头。 随意设置您想要的值。

"Server" : "techblik.com Server",
  

RemoveHeaders – 您是否需要删除某些标头来隐藏版本信息,以降低信息泄露的风险?

您可以在此处完成这些操作。

let removeHeaders = [
	"Public-Key-Pins",
	"X-Powered-By",
	"X-AspNet-Version",
]
  

添加新的标头 – 如果您需要将一些自定义标头传递给应用程序,可以在 securityHeaders 部分添加它们,如下所示:

let securityHeaders = {
	"Content-Security-Policy" : "frame-ancestors 'self' gf.dev techblik.com.com",
	"Strict-Transport-Security" : "max-age=1000",
	"X-Xss-Protection" : "1; mode=block",
	"X-Frame-Options" : "SAMEORIGIN",
	"X-Content-Type-Options" : "nosniff",
	"Referrer-Policy" : "strict-origin-when-cross-origin",
    "Custom-Header"  : "Success",
}
  

在调整完所有所需的标头后,为您的 Worker 命名,然后点击“保存并部署”。

很好! Worker 已经准备就绪。接下来,我们需要将其添加到您想要应用标头的站点。 我将应用到我的测试站点。

  • 返回到 Cloudflare 的主页/仪表板,选择您的站点。
  • 导航至 “Workers” 选项卡 >> 添加路由。
  • 在路由中输入网址;您可以在这里应用正则表达式。
  • 选择新创建的 Worker 并保存。

完成! 几乎在瞬间,您会注意到所有标头已成功应用到该站点。

这是 Chrome Dev Tools 的显示效果。 您还可以通过 HTTP 标头工具来验证标头。

值得注意的是,服务器标头可能没有按预期显示,这可能是由于 Cloudflare 的某些覆盖机制所致。

整个部署过程只需大约 15 分钟,并且无需像 Apache 或 Nginx 那样需要停机或重启。如果您计划将此方法应用于生产站点,我们建议您先在较低的环境中进行测试,或者利用路由功能,在测试页面上应用并验证结果。一旦确认无误,再将其部署到您需要的地方。

非常棒!

感谢 斯科特 提供代码。