在 nginx 中添加 Content-Security-Policy 后 websocket 连接失败

Posted

技术标签:

【中文标题】在 nginx 中添加 Content-Security-Policy 后 websocket 连接失败【英文标题】:websocket connection fails after adding Content-Security-Policy in nginx 【发布时间】:2021-11-20 14:00:53 【问题描述】:

我想在我的 nginx conf 中添加一个新的标头 Content-Security-Policy 以提高安全性。我已经添加了所有外部资源并且一切正常,除了聊天机器人是 infobip。它使用 wss 协议,由于某种原因我找不到正确的配置方法。

This is the error that I get.

这是我在 nginx.conf 中的头文件

add_header 'Content-Security-Policy' "default-src 'self' 'unsafe-inline' wss: wss://.infobip.com ws://.infobip.com .infobip.com http://www.w3.org https://fonts.googleapis.com https://stackpath.bootstrapcdn.com .youtube.com https://cdn.jsdelivr.net/; img-src 'self' 数据:https://.openstreetmap.org wss://livechat- fr.infobip.com/chat/web/proxy/827/toxgylwd/websocket 总是;connect-src 'self' wss: ws: wss://.infobip.com ws://*.infobip.com .infobip.com https://.doubleclick.net wss://livechat-fr.infobip.com/chat/web/proxy/492/hybzmnjl/websocket 'unsafe-inline' 总是;" ;

我尝试了多种方法来允许 websocket 连接,但似乎都没有。

【问题讨论】:

【参考方案1】:

由于每个 websocket 连接都是由一个常规的 http 请求开始的,你必须为 https://your-websocket-server-domain:port 添加一个 CSP

http 请求会得到一个101: swtiching protocols 的响应,然后这个连接就会变成一个WebSocket 连接。

请注意,我认为根本不需要 ws: 或 wss: csp 指令。

【讨论】:

【参考方案2】:

您有 3 个问题:

    您显示的控制台错误与 CSP 无关。 “403 Forbidden”表示您无权访问相关网址。 “'X-Frame-Options' to 'deny'”表示您尝试嵌入 iframe,但该页面不允许通过 X-Frame-Options: "DENY" HTTP 标头嵌入。

    Nginx add_header 格式错误。它应该看起来像(注意引号 - always 关键字应该放在 CSP 设置之外):

    add_header Content-Security-Policy "default-src 'self'..." always;

    Wrong CSP 的主机源格式。像 .youtube.com 这样的主机源不得包含前导 . 点:youtube.com 将允许从 http(s)://youtube.com*.youtube.com 加载资源将允许来自 youtube.com 子域的资源。

所以你的语法正确的 CSP 应该如下所示:

add_header Content-Security-Policy "\ default-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com\ https://fonts.googleapis.com infobip.com ws://infobip.com wss://infobip.com youtube.com\ https://cdn.jsdelivr.net http://www.w3.org;\ connect-src 'self' infobip.com wss://infobip.com ws://*.infobip.com\ wss://livechat-fr.infobip.com/chat/web/proxy/ https://doubleclick.net;\ img-src 'self' data: https://openstreetmap.org;\" always;

注意:

wss://livechat-fr.infobip.com/chat/web/proxy/492/hybzmnjl/websocket - 不要包含 CSP 的粗体路径部分,因为它每次都会更改。 wss: 之类的方案源涵盖了具有该方案的任何主机源(例如 wss://site.com/websocket)。所以我删除了方案源并离开了主机源。 我删除了一些不受支持的来源,例如connect-src 中的'unsafe-inline'。 Nginx 应该支持反斜杠\ 作为换行符,所以我使用它是因为很难在一行中维护 CSP。检查您的 Nginx 版本是否支持此功能。

注意 2:此 CSP 可以阻止某些来源 - 只需将它们添加到适当的指令中即可。

注意 3: 考虑将源代码从 default-src 指令移至 script-src + style-src + font-src 指令。因为现在你实际上在scrit-src 中允许'unsafe-inline',所以你的CSP 不能防止XSS。未来管理 CSP 也将变得困难,因为源混合在一个指令中。

【讨论】:

谢谢,但不幸的是我仍然遇到同样的错误 - WebSocket 连接到...失败。我还得到:拒绝在框架中显示“livechat-fr.infobip.com”,因为它将“X-Frame-Options”设置为“拒绝”。这就是我始终设置标题 add_header 'X-Frame-Options' "SAMEORIGIN" 的方式; 您在服务器上设置了X-Frame-Options "SAMEORIGIN",但您的服务器不提供livechat-fr.infobip.com 被阻止。这是livechat-fr.infobip.com 发布X-Frame-Options "DENY" 标头以防止嵌入。您可能在您的 infobip.com 帐户中配置错误。 问题已解决。 CSP 指令工作正常。事实证明,公司网络正在阻止来自/到 infobip 的流量,而我没有被告知这一点。再次感谢您的努力,仍然帮助我制定了严格的指令。

以上是关于在 nginx 中添加 Content-Security-Policy 后 websocket 连接失败的主要内容,如果未能解决你的问题,请参考以下文章

Nginx-添加echo模块

nginx日志中添加请求的response日志

尝试在具有代理缓存的 nginx 服务器中添加另一个位置指令

如何在Nginx中添加SSL证书以支持HTTPS协议访问

在 Nginx 的反向代理中为特定静态文件添加缓存?

在 nginx 中添加 Content-Security-Policy 后 websocket 连接失败