我有一个 varnish 配置文件,如下所示:
backend web1 { .host = "1.2.3.1" ; ... }
backend web2 { .host = "1.2.3.2" ; ... }
backend web3 { .host = "1.2.3.3" ; ... }
backend web4 { .host = "1.2.3.4" ; ... }
director default_director round-robin {
{ .backend = web1; }
{ .backend = web2; }
{ .backend = web3; }
{ .backend = web4; }
}
include "blacklist.vcl";
sub vcl_recv
{
if (client.ip ~ blacklist ) {
error 403 "You're blacklisted";
}
..
}
显然,黑名单条目包含我不想访问我的服务器的网站。
不幸的是,我的黑名单文件很大,并且每天/每周都变得越来越大:
$ wc -l varnish/blacklist.vcl
6664 varnish/blacklist.vcl
我已经从阻止 /32s 切换到阻止 /24s 以缩短列表,但我仍然发现无法在不到 5 秒的时间内重新启动 varnish。
我还能做什么来加载黑名单?我知道我可以使用 iptables,但对于如此大的条目来说,这也很慢 - 因为当有任何更改时我必须将它们全部清除并重新加载它们。
答案1
如果您只想解决重新启动 Varnish 所需的时间,这可能不是您想要的 - 但对于重新加载配置,我有以下解决方案给您;
Varnish 配置会转换为 C 源代码,并在加载时进行编译。因此,加载配置所需的时间包括编译时间。这很可能就是导致您等待时间过长的原因。
您可以使用 varnishadmin 加载新配置,如下所示:
# varnishadm
vcl.load my_alias_2013-04-13 /etc/varnish/config.vcl
vcl.use my_alias_2013-04-13
如果 VCL 存在语法错误,上述操作还将产生非常有用的调试信息。它不会清除缓存,也不会中断服务。vcl.use 基本上会加载构建的 .so 文件并更改内存中的某些指针 - 这使得在运行时非常容易执行此操作,而无需重新启动整个服务。
答案2
Varnish 在这方面尤其糟糕,它生成的执行此操作的 C 代码实际上是线性搜索——就像向 iptables 添加单独的规则一样糟糕。
但是你能使用 iptables 并使其速度更快。
使用ipset相反。IPSets 是 ips 的快速哈希查找,它可以非常快速地在大量地址中查找 ip。
使用以下命令创建一个 ipset:
ipset create myset hash:ip
这将生成您放置地址的集合。
接下来,将您的 IP 添加到集合中。
ipset add myset 1.1.1.1
ipset add myset 1.1.1.2
ipset add myset 1.1.1.3
ipset add myset 1.1.1.4
...
最后,向IPtables添加一条规则,使用该集合进行匹配。
iptables -N VARNISH_BL
iptables -I VARNISH_BL -m set --match-set myset src -j REJECT
iptables -I INPUT -m tcp -p tcp --dport 80 -m conntrack --ctstate NEW -j VARNISH_BL
iptables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
您可以转储该集合以便稍后重新初始化(例如在重新启动后),并将ipset save myset
其打印到标准输出。当然,您也可以随时使用 向该集合添加更多 IP ipset add
。
另外,您可能实际上希望 IP 黑名单自动过期。ipset
也可以通过为在创建时添加到集合中的任何 IP 指定默认超时来做到这一点:ipset create myset hash:net timeout 86400
默认情况下,一组中最多允许 65535 个主机,但请查看手册页,您可以使用参数创建更大的集合maxelem
。