6月 202010
僕のサイトみたいに複数のドメイン(blog.xcir.net/xcir.net/wiki.xcir.net)管理しているけどVarnishサーバは一つの場合
公式サイトの設定例
acl purge {
"localhost";
"192.0.2.14";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
purge("req.url ~ " req.url);
}
}
だと違うドメインでも同じURLであれば消してしまいます。
ドメインを指定して安全にキャッシュをパージするにはどうすればいいでしょうか?
VCL
acl purge {
//パージを許可するホスト一覧
"localhost";
"192.168.1.0"/24;
}
sub vcl_recv {
//PURGEリクエストの場合PURGE処理を行う
if (req.request == "PURGE") {
//アクセスしてきたIPアドレスがpurgeのACLと一致しなかった場合は拒否して405 Not allowed.を返却
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
//HOSTが完全一致かつURLが一致する(正規表現で評価)URLについてパージする
purge("req.http.host == " req.http.host " && req.url ~ "req.url );
//200を Purged.を返却
error 200 "Purged.";
}
}
リクエスト方法
以下のようなリクエストをVarnishサーバに投げます
PURGE /img.jpg HTTP/1.0 Host: blog.xcir.net
正規表現も使えますので
PURGE .* HTTP/1.0 Host: blog.xcir.net
もOKです。すべて消えますが
特に重要なのがACLの設定です。
きちんと許可IPを設定しないとインターネットから自由にパージされちゃいます。
複数のサーバを管理しているとスクリプトが欲しくなるのでPHPのスクリプトも作りました。
スクリプト
class Varnish_HTTP_Purge{
static function purge($varnish,$url,$port=80){
$all=true;
if(!is_array($varnish) && strlen($varnish)>0){
$varnish=array($varnish);
}
if(!is_array($url) && strlen($url)>0){
$url=array($url);
}
$ret=array();
foreach($varnish as $v){
foreach($url as $u){
$ret["$v->$u"]=self::_purge($v,$u,$port);
$all &=$ret["$v->$u"];
}
}
$ret['all']=$all;
return $ret;
}
private static function _purge($varnish,$url,$port=80){
$url=preg_replace('@http://@',,$url);
$p=explode('/',$url,2);
if(count($p)==1){
$p[]=;
}
$p[1]='/'.$p[1];
$socket = fsockopen($varnish, $port, $errno, $errstr);
if (!$socket) {
return false;
}
$reqheader="PURGE {$p[1]} HTTP/1.0\r\n".
"Host:{$p[0]}\r\n".
"\r\n";
fputs($socket, $reqheader);
$body="";
while (!feof($socket)) {
$body .= fgets($socket, 4096);
}
fclose($socket);
if(stristr($body,'HTTP/1.1 200 Purged.')){return true;}
return false;
}
}
使い方
Varnish_HTTP_Purge::purge(リクエストを投げたいVarnishサーバ,パージしたいURL);
Varnish_HTTP_Purge::purge("192.168.1.1","http://blog.xcir.net/test.jpg");
サーバとURLは配列に対応しているので
Varnish_HTTP_Purge::purge(array("192.168.1.1","192.168.1.2"),array("http://blog.xcir.net/test.jpg","http://blog.xcir.net/test.jpg2"));
とすればOKです
結果は配列で返却します。
要求したホスト->URLでキーを作りそれぞれでboolで返却します。
また全体で成功したかどうかはallキーに格納しています。
返却値をvar_dumpするとこんな感じです
array(5) {
["localhost->http://blog.xcir.net/test.jpg"]=>
bool(false)
["localhost->http://blog.xcir.net/test.jpg2"]=>
bool(false)
["192.168.1.123->http://blog.xcir.net/test.jpg"]=>
bool(true)
["192.168.1.123->http://blog.xcir.net/test.jpg2"]=>
bool(true)
["all"]=>
int(0)
}
wikiにもまとめましたこっちには書いてないPerl版は以下をどうぞ
HTTP経由でのパージ(マルチドメイン対応)
Varnishのパージを行うクラス(PHP)
Varnishのパージを行うパッケージ(Perl)
[…] This post was mentioned on Twitter by livedoorcliphot, \いわなちゃん/. \いわなちゃん/ said: マルチドメイン環境でHTTP経由でPurgeを行うVCL設定とスクリプト http://bit.ly/94wBUm #varnish #varnishjp […]