利用 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 那样需要停机或重启。如果您计划将此方法应用于生产站点,我们建议您先在较低的环境中进行测试,或者利用路由功能,在测试页面上应用并验证结果。一旦确认无误,再将其部署到您需要的地方。
非常棒!
感谢 斯科特 提供代码。