【问题标题】:Varnish 6.0lts won't handle secure websockets on a remote proxy?Varnish 6.0lts 无法处理远程代理上的安全 websockets?
【发布时间】:2023-01-09 13:20:06
【问题描述】:

我很难接受这个设置。我有一个 node.js 框在 3000 上提供 HTTP,在 3001 上提供 websockets,在 3002 上提供安全的 websockets。在它前面,我在自己的服务器上有一个远程 Hitch/Varnish 缓存代理,它正在侦听 443/80 并连接第一个服务器通过 3000 作为其默认后端。访问网站 URL https://foo.tld 的用户点击 varnish 代理并看到该网站,网站上的一些 javascript 告诉他们的浏览器连接到 wss://foo.tld:3002 以确保安全网络套接字。

我的问题是让 websockets 透明地传递到后端。在 VCL 我有标准

if (req.http.upgrade ~ "(?i)websocket") {
return (pipe);
}

sub vcl_pipe {
#Declare pipe handler for websockets
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
set bereq.http.connection = req.http.connection;
}
}

在这种情况下这是行不通的。列出我到目前为止没有成功的尝试:

1:在名为“websockets”的 VCL 中创建第二个后端,它是相同的后端 IP,但在端口 3001 或 3002 上,并添加“set req.backend_hint = websockets;”在上面第一个 sn-p 中的管道召唤之前。

2:关闭 HTTPS 并尝试通过纯 HTTP 连接它。

3:修改varnish.service 来尝试让varnish 监听除-a :80 和-a :8443,proxy 之外的端口,在这种情况下varnish 只是拒绝启动。一种尝试是仅使用 HTTP 并尝试在 3001 上运行 varnish 以使 ws:// 在没有 SSL 的情况下工作,但 varnish 拒绝启动。

4:最近我在 VCL 中尝试了以下操作来尝试获取来自 3001 的客户端连接:

if (std.port(server.ip) == 3001) {
set req.backend_hint = websockets;
}

我的目标是让 Varnish box 在 3002 上获取安全的 websocket 流量(wss://)(通过使用普通安全 websocket 连接协议的 443 连接)并将其透明地传递到后端 websocket 服务器,无论 SSL 是否加密连接的腿或不。我之前已经设置了其他像这样的小型服务器,如果 Varnish 和后端服务在同一台机器上或在像 Cloudflare 这样的监管 CDN 后面,让 websockets 工作是微不足道的,所以试图弄清楚这是什么特别令人沮丧远程代理设置需要。我觉得部分解决方案是让 Varnish 或 Hitch(不确定)监听 3002 以接受连接,此时正常的 req.http.upgrade 和管道功能将发挥作用,但软件拒绝合作。

我当前的 hitch.conf:

frontend = "[*]:443"
frontend = "[*]:3001"

backend = "[127.0.0.1]:8443"    # 6086 is the default Varnish PROXY port.
workers = 4                     # number of CPU cores

daemon = on

# We strongly recommend you create a separate non-privileged hitch
# user and group
user = "hitch"
group = "hitch"

# Enable to let clients negotiate HTTP/2 with ALPN. (default off)
# alpn-protos = "h2, http/1.1"

# run Varnish as backend over PROXY; varnishd -a :80 -a localhost:6086,PROXY ..
write-proxy-v2 = on             # Write PROXY header


syslog = on
log-level = 1
# Add pem files to this directory
# pem-dir = "/etc/pki/tls/private"
pem-file = "/redacted/hitch-bundle.pem"

当前默认.vcl:

# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.


backend default {
    .host = "remote.server.ip";
    .port = "8080";
}

backend websockets {
        .host = "remote.server.ip";
        .port = "6081";
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.

    #Allow websockets to pass through the cache (summons pipe handler below)

if (req.http.Upgrade ~ "(?i)websocket") {
        set req.backend_hint = websockets;
        return (pipe);
    } else {
    set req.backend_hint = default;
    }



}

sub vcl_pipe {
    if (req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
    set bereq.http.connection = req.http.connection;
    }
    return (pipe);
}

【问题讨论】:

    标签: ssl caching websocket proxy varnish


    【解决方案1】:

    Varnish Cache 是 Varnish 的开源版本,不支持通过 TLS 的后端连接。

    虽然您可以使用 Hitch 卸载 TLS,但与您的 websocket 服务器的连接不会被加密。

    基本 VCL 示例

    这是一个非常基本的 VCL 示例,其中 web 和 websocket 请求被拆分并发送到单独的后端:

    vcl 4.1;
    
    backend web {
        .port = "3000";
    }
    
    backend ws {
        .port = "3001";
    }
    
    sub vcl_recv {
        if (req.http.Upgrade ~ "(?i)websocket") {
            set req.backend_hint = ws;
            return (pipe);
        } else {
            set req.backend_hint = web;
        }
    }
    
    sub vcl_pipe {
        if (req.http.upgrade) {
            set bereq.http.upgrade = req.http.upgrade;
        }
        return (pipe);
    }
    

    需要更多的投入

    但是,我可能缺少很多上下文。我也没有在后端指定 .host 参数,因此假设所有服务都在本地托管。

    请将完整的 VCL、Hitch 配置和 varnishd 运行时参数添加到您的问题中。这将增加上下文并允许我想出更好的解决方案。

    希奇呢?

    如果您在 Hitch 中终止 TLS,则 HTTPS 和安全 websocket 都将由 Hitch 处理,其中纯文本 HTTP 和 websocket 仍将由 Varnish 直接处理。

    有关 Hitch 教程,请参阅 https://www.varnish-software.com/developers/tutorials/terminate-tls-varnish-hitch,该教程还解释了应如何配置 Varnish。

    我大力提倡在 Varnish 中使用 PROXY 协议。挂钩教程有一个关于此的特定部分:https://www.varnish-software.com/developers/tutorials/terminate-tls-varnish-hitch/#enable-the-proxy-protocol-in-varnish

    自定义端口

    访问该服务的标准端口是 80 用于 HTTP 和不安全的 websockets,443 用于 HTTPS 和安全的 websockets。

    如果你想为 websockets 使用自定义端口,可以在 Hitch 和 Varnish 中配置它们。

    假设您要为您的 websockets 使用主端口 30013002。这意味着您需要 Hitch 中的 2 个前端:

    • 一个用于 443 上的 HTTPs
    • 一个用于3002 上的安全 WS

    有关前端配置的更多信息,请参阅https://www.varnish-software.com/developers/tutorials/terminate-tls-varnish-hitch/#listening-address

    另一方面,清漆需要有 3 个监听地址:

    • 端口 80 (-a http=:80) 上的一个用于 HTTP
    • 一个用于卸载 HTTPS 和安全 WS,PROXY 支持端口 8443 (-a proxy=:8443,PROXY)
    • 一个用于端口3001 (-a ws=:3001) 上的不安全 WS

    下一步

    请使用这些信息,看看这是否有助于找到解决方案。如果没有,请分享您的 VCL 文件、您的 Hitch 配置和 varnishd 运行时。

    【讨论】:

    • 即使按照您的建议,我也无法使最基本的 HTTP/WS 连接正常工作。我完全清空了我的 default.vcl 文件,以确保我正在做的任何其他事情都不会受到干扰。我现在描述的是纯 HTTP/WS,根本没有使用 hitch 或 HTTPS。我只是想让一些东西起作用。 systemctl edit --full varnish 现在可以监听 80 和 ws=:6081(有效)。后端服务器在 3000 上运行 HTTP,在 6081 上运行 WS(通过 IP 访问工作)并且 default.vcl 为 web 和 ws 定义了 2 个后端,其管道与上面给出的示例完全相同。什么都不管用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多