【问题标题】:How can I customize the message shown to a user who reaches a Guru Meditation error when making a request thru my Varnish server?当通过我的 Varnish 服务器发出请求时,如何自定义向遇到 Guru Meditation 错误的用户显示的消息?
【发布时间】:2021-12-23 07:00:47
【问题描述】:

当用户到达 Guru Meditation 错误屏幕时,我正在尝试自定义屏幕上显示的内容,并向我的后端发出错误请求,该后端前面有一个 Varnish 反向代理。我尝试将log.info(client.ip) 放在default.vcl 的不同子例程中,只是在尝试启动清漆服务时遇到编译错误。我正在使用 Linux 虚拟机。

【问题讨论】:

  • 请澄清您的具体问题或提供更多详细信息以准确突出您的需求。正如目前所写的那样,很难准确地说出你在问什么。

标签: varnish varnish-vcl


【解决方案1】:

你当然可以。看看我创建的以下教程:https://www.varnish-software.com/developers/tutorials/vcl-synthetic-output-template-file/

修改合成输出模板

这是您需要扩展常规 vcl_synth 子例程以防您从 VCL 代码调用 return(synth()) 的 VCL 代码,以及您需要扩展 vcl_backend_response 以防后端获取错误的代码:

vcl 4.1;

import std;

sub vcl_synth {
    set resp.http.Content-Type = "text/html; charset=utf-8";
    set resp.http.Retry-After = "5";
    set resp.body = regsuball(std.fileread("/etc/varnish/synth.html"),"<<REASON>>",resp.reason);
    return (deliver);
}

sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    set beresp.http.Retry-After = "5";
    set beresp.body = regsuball(std.fileread("/etc/varnish/synth.html"),"<<REASON>>",beresp.reason);
    return (deliver);
}

如教程中所述,您可以将要显示的 HTML 代码存储在 HTML 中,然后将其加载到 VCL 输出中。

诀窍是在您的 HTML 中放置一个 &lt;&lt;REASON&gt;&gt; 占位符,实际错误消息将被解析到该位置。

向您的 VCL 添加自定义日志记录

如果要添加发送到 VSL 的自定义日志记录,可以使用 std.log() 函数,它是 vmod_std 的一部分。

下面是一些使用此函数的示例 VCL 代码:

vcl 4.1;

import std;

sub vcl_recv {
    std.log("Client IP: " + client.ip);
}

日志将通过您的 VSL 输出中的 VCL_Log 标签显示。

如果要过滤掉VCL_Log标签,可以使用如下命令:

varnishlog -g request -i VCL_Log

这是您可能收到的输出:

*   << Request  >> 32770
-   VCL_Log        Client IP: 127.0.0.1
**  << BeReq    >> 32771

如果您没有过滤 VCL_Log 标记,您会在运行 varnishlog -g request 时看到它出现在 VSL 输出中。

提示:如果您想查看完整的日志事务但仅针对特定 URL,只需运行 varnishlog -g request -q "ReqUrl eq '/'"。这只会显示主页的日志。

更新:在合成输出中显示客户端 IP

下面的 VCL 代码通过连接原因短语将 X-Forwarded-For 标头注入到输出中:

vcl 4.1;

import std;

sub vcl_synth {
    set resp.http.Content-Type = "text/html; charset=utf-8";
    set resp.http.Retry-After = "5";
    set resp.body = regsuball(std.fileread("/etc/varnish/synth.html"),"<<REASON>>",resp.reason + " (" + req.http.X-Forwarded-For + ")");
    return (deliver);
}

sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    set beresp.http.Retry-After = "5";
    set beresp.body = regsuball(std.fileread("/etc/varnish/synth.html"),"<<REASON>>",beresp.reason + " (" + bereq.http.X-Forwarded-For + ")");
    return (deliver);
}

还可以在模板中提供第二个占位符并执行额外的regsuball() 调用。但为了简单起见,X-Forwarded-For 标头只是附加到原因字符串。

【讨论】:

  • 如果客户端和varnish(如Caddy)之间有代理,我如何获取客户端的IP地址?
  • 这完全取决于您使用的 TLS 代理。如果代理发出X-Forwarded-For 标头,Varnish 将使用该值并将其发送到服务器。如果没有,Varnish 将创建一个 X-Forwarded-For 标头并使用代理的 IP 地址作为值。确保 TLS 代理以 X-Forwarded-For 标头的形式传递原始客户端 IP 符合您的最大利益。
  • 确实如此。在这种情况下,我该怎么做?
  • @TekDood 由于您确认您的 TLS 代理发出 X-Forwarded-For 标头,因此您无需执行任何操作。您要查找的值在 X-Forwarded-For 标头中。使用该值。如果您希望将客户端 IP 存储在日志中,请更改您的日志格式并包括 X-Forwarded-For
  • 我希望在错误 Guru 屏幕上显示客户端的 IP。大多数地方我都尝试抓取客户端的 X-Forwarded-For 并将其写入可以在 backend_error 中读取的内容,这会导致编译错误
猜你喜欢
  • 2016-12-11
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
相关资源
最近更新 更多