.htaccess/virtualhost动态阻止列表+错误文档



我目前有一个多站点虚拟主机,我已经设置了一些通用的错误文档,每个域都可以重置这些文档。我也有一个黑名单重写,但我试图设置一个自定义错误条件,如果一个IP被阻止,然后显示一个自定义的错误页面。

<Virtualhost *:80>
ServerName catchall.host
ServerAlias *
VirtualDocumentRoot /var/www/hosts/%0
Alias /cloud-cgi /var/www/cloud-cgi
SetEnv DIRECT_ACCESS no
HttpProtocolOptions Unsafe
RewriteEngine On
RewriteMap access txt:/var/www/blacklist.txt
RewriteCond ${access:%{REMOTE_ADDR}} deny [NC]
RewriteRule ^ "/cloud-cgi/error_handler.php" [R=404,L]
RemoteIPHeader CF-Connecting-IP
CustomLog /var/www/catchall_access.log combined
ErrorLog /var/www/catchall_error.log
</Virtualhost>

/var/www//var/www/hosts/中,有一个htaccess设置ErrorDocuments

ErrorDocument 400 /cloud-cgi/error_handler.php
ErrorDocument 401 /cloud-cgi/error_handler.php
ErrorDocument 403 /cloud-cgi/error_handler.php
ErrorDocument 404 /cloud-cgi/error_handler.php
ErrorDocument 500 /cloud-cgi/error_handler.php

在vhost中,您可以看到黑名单,如果满足RewriteCond,则会尝试使用HTTP代码404将浏览器重定向到/cloud-cgi/error_handler.php

出于某种原因,当我尝试这样做时,我得到的不是自定义的ErrorDocument,而是默认的Apache。如何触发其中一个HTTP错误,并重定向到ErrorDocument。如果我可以设置一个带有值的环境变量,这样处理程序就可以设置一条自定义消息,那也太好了。我也尝试过从vhost定义中设置错误文档,但没有成功。

我是不是错过了什么?

RewriteRule ^ "/cloud-cgi/error_handler.php" [R=404,L]

尝试使用HTTP代码404 将浏览器重定向到/cloud-cgi/error_handler.php

当您指定R标志在3xx范围之外的HTTP状态代码时,替换字符串将被忽略(不会发生替换)。在这种情况下,最好简单地包括一个连字符(-)作为替换字符串,以明确表示不打算进行替换。

当您指定R=404时,Apache会触发404响应(通过内部子请求),并根据定义调用自定义404ErrorDocument

但是,定义的错误文档本身需要是可访问的。在您发布的指令中,当用户IP地址在黑名单上时,对/cloud-cgi/error_handler.php的请求本身也会触发404响应,因此无法显示自定义错误文档。Apache回到Apache默认值(抱怨自定义错误文档触发了404甚至500响应,这取决于您在哪里使用这些指令)。

要使其可访问,您可以:

包括特定异常

在规则中包含一个异常,以排除对特定错误文档的请求。例如:

RewriteRule !^/cloud-cgi/error_handler.php - [R=404]

(指定非3xx响应代码时不需要L标志;它是隐含的。)

包括一般异常

或者,更一般地说,当错误响应已经被触发时,防止触发规则。这可以通过检查REDIRECT_STATUS环境变量来实现,该变量在触发错误文档后设置为HTTP响应代码。例如:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ - [R=404]

在上面的内容中,我们只是简单地检查REDIRECT_STATUSenv var是否为空。(附加:此技术在LiteSpeed服务器上不起作用,因为REDIRECT_STATUSenv var在请求到错误状态期间不会更新。)

允许公众访问错误文档

但也可能有其他指令也需要触发错误文档。。。

或者,使用mod_authz_core来允许公共访问。例如:

<Files error_handler.php>
Require all granted
</Files>

在错误状态下阻止进一步的重写处理

或者,当设置了REDIRECT_STATUS时,创建早期异常并阻止进一步的重写处理(在当前上下文中)。但是,这取决于您有哪些其他指令,现在指令的顺序很重要。例如,在vHost config:中的现有规则之前

RewriteCond %{ENV:REDIRECT_STATUS} !^$
RewriteRule ^ - [END]

内部重写

或者,您可以在内部将请求重写为自定义错误文档。但是您现在必须在PHP脚本中设置404响应代码(理想情况下,您无论如何都需要这样做,以防直接请求错误文档——不太可能但并非不可能):

RewriteRule ^ /cloud-cgi/error_handler.php [L]

一些可以由每个域重置的通用错误文档

这里的问题是,如果每个域都重置了它们,那么上面包含的特定异常将不再有效。您可以为所有错误文档创建一个特定的子目录,只需允许对该目录进行不受限制的访问。

如果我可以设置一个带有值的环境变量,这样处理程序就可以设置一条自定义消息,那也太好了。

您可以在同一个RewriteRule指令中设置env-var。例如:

RewriteRule ^ - [E=MYVAR:Message,R=404]

上面将环境变量MYVAR设置为值Message。如果消息文本包含空格,则用双引号将整个flags参数括起来。(尽管我会将您的具体错误文本留给error_handler.php,并在此处设置一个短代码或标志。)

RewriteRule ^ - "[E=MYVAR:Custom message with spaces,R=404]"

正如anubhava所说。。。尝试将RewriteRule ^ "/cloud-cgi/error_handler.php" [R=404,L]更改为RewriteRule ^ - [R=404,L]

重写规则使得错误处理程序文件看起来不存在。因此,因为apache无法访问错误处理程序文件,所以它显示了默认的错误处理程序。您还应该在默认错误页面中看到一条通知,上面写着类似的内容。此外,在尝试使用ErrorDocument处理请求时遇到了404 Not Found错误

最新更新