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 […]