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)


  One Response to “マルチドメイン環境でHTTP経由でPurgeを行うVCL設定とスクリプト”

  1. […] This post was mentioned on Twitter by livedoorcliphot, \いわなちゃん/. \いわなちゃん/ said: マルチドメイン環境でHTTP経由でPurgeを行うVCL設定とスクリプト http://bit.ly/94wBUm #varnish #varnishjp […]

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください