Varnish 6.0 LTS远程代理无法处理WebSocket问题求助
问题:Varnish代理WebSocket连接失败排查
环境背景
后端Node.js服务器分端口提供服务:
- 3000端口:HTTP服务
- 3001端口:WebSocket服务
- 3002端口:安全WebSocket服务
前端部署独立的Hitch/Varnish缓存代理,监听80/443端口,默认将流量转发至后端3000端口的HTTP服务。目前用户访问https://foo.tld可正常通过Varnish获取内容,但页面JS发起的wss://foo.tld:3002安全WebSocket连接无法正常工作。
已配置的WebSocket透传规则
已在VCL中添加标准WebSocket透传配置:
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; } }
已尝试的无效方案
- 在VCL中新增指向后端3001/3002端口的
websockets后端,在pipe前设置set req.backend_hint = websockets; - 关闭HTTPS,尝试纯HTTP环境下的WebSocket连接
- 修改varnish.service配置让Varnish监听其他端口,但Varnish无法启动
- 在VCL中通过
std.port(server.ip) == 3001判断端口并切换后端
目标是让Varnish通过Hitch在443端口接收wss://流量(或直接监听3002端口),透传至后端WebSocket服务器,无论两端连接是否加密。此前同机部署或Cloudflare CDN下的配置均可正常工作,但远程代理场景下始终无法解决。
环境简化后的问题(更新)
已简化测试环境:
- 后端8080端口提供纯HTTP服务
- 后端6081端口提供WS服务
- 移除Hitch和TLS组件
直接访问后端IP时WebSocket可正常工作,但通过Varnish代理仍无法连接,问题明确出在Varnish配置上。
当前相关配置
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 = "redacted" group = "redacted" # 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"
default.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); }
Varnish的systemd执行参数
ExecStart=/usr/sbin/varnishd \ -a http=:80 \ -a proxy=localhost:8443,PROXY \ -a ws=:6081 \ -p feature=+http2 \ -f /etc/varnish/default.vcl \ -s malloc,256m \ -p pipe_timeout=1800
在纯HTTP和非安全WebSocket的简化环境下,问题仍未解决,恳请协助排查。
内容的提问来源于stack exchange,提问作者8protons
相关产品推荐
相关产品推荐

