Use varnish to bypass school proxy (rewrite URL to bypass port blocking).
学校的防火墙规则很严格,除了80,443等常用端口外,不允许特殊端口的通信(就连git使用的9418端口也被block过)。
可以我的网站2812端口有monit服务,我常常想从学校的电脑访问 ,看看自己网站的是不是工作正常。为了解决这个问题,我发现可以用Varnish的rewrite 功能。
原理上讲,Varnish收到一个URL request,会调用vcl_recv函数 (可能是callback机制),然后根据header中的URL来分析如何具体处理,比如可以去掉header,对mobile的browser agent用mobile版的web server,还可以用不同的backend服务器,这个就是用这个功能。
先把相应的配置放上来:
default.vcl中先添加一个后台服务器:
backend monit {
.host = "localhost";
.port = "2812";
}
在sub vcl_recv函数中增加对/monit请求的重写(rewrite),就是说每次访问xxx.com/monit自动翻译成xxx.com/, 然后用backend monit(就是上面的localhost:2812服务器)来服务:
if (req.url ~ "^/monit"){
set req.url = regsub(req.url, "^/monit", "/");
set req.url = regsub(req.url, "^//", "/");
set req.backend = monit;
}
通过上面的设置,就可以在学校里,用80端口来访问服务器端2812端口的内容了。
注意,默认monit会使用这样的链接: xxx.com/nginx
这种情况下,varnish不会用backend monit来服务,我们需要手动访问:xxx.com/monit/nginx
现在还没有想到如何解决这种不方便。
后话1:
Varnish是一个非常强大的proxy,用它内置的VCL语言,可以很灵活、高效(Varnish内部把VCL编译成C语言)处理各种类型的HTTP request。比如round-robin式的负载均衡。最常用的两个函数是vcl_recv (表示varnish接收到browser的请求) 和vcl_fetch(表示varnish已经从后台服务器取得数据)。更多的用法可以见:
后话2:
Varnish不会像Apache/Nginx把log写到磁盘。如需要检查log,可以用Varnish自带的varnishlog。
比如下面的:
12 SessionOpen c 76.235.186.40 34862 :80
12 ReqStart c 76.235.186.40 34862 911966818
12 RxRequest c GET
12 RxURL c /monit
12 RxProtocol c HTTP/1.1
12 RxHeader c Host: zhanxw.com
12 RxHeader c User-Agent: Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:8.0) Gecko/20100101 Firefox/8.0
12 RxHeader c Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
12 RxHeader c Accept-Language: en-us,en;q=0.5
12 RxHeader c Accept-Encoding: gzip, deflate
12 RxHeader c Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
12 RxHeader c Connection: keep-alive
12 RxHeader c Cookie: __utma=134065221.936534807.1323323714.1323329816.1323533189.3; __utmz=134065221.1323323714.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=134065221
12 RxHeader c Authorization: Basic YWRtaW46eGlhb3dlaXhpYW95aQ==
12 RxHeader c Cache-Control: max-age=0
12 VCL_call c recv
12 VCL_return c pass
12 VCL_call c hash
12 VCL_return c hash
12 VCL_call c pass
12 VCL_return c pass
14 BackendOpen b monit 127.0.0.1 37258 127.0.0.1 2812
12 Backend c 14 monit monit
14 TxRequest b GET
14 TxURL b
14 TxProtocol b HTTP/1.1
14 TxHeader b Host: zhanxw.com
14 TxHeader b User-Agent: Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:8.0) Gecko/20100101 Firefox/8.0
14 TxHeader b Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
14 TxHeader b Accept-Language: en-us,en;q=0.5
14 TxHeader b Accept-Encoding: gzip, deflate
14 TxHeader b Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
14 TxHeader b Cookie: __utma=134065221.936534807.1323323714.1323329816.1323533189.3; __utmz=134065221.1323323714.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=134065221
14 TxHeader b Authorization: Basic YWRtaW46eGlhb3dlaXhpYW95aQ==
14 TxHeader b X-Forwarded-For: 76.235.186.40
14 TxHeader b X-Varnish: 911966818
14 RxProtocol b HTTP/1.0
14 RxStatus b 400
14 RxResponse b Bad Request
14 RxHeader b Date: Sat, 10 Dec 2011 17:58:50 GMT
14 RxHeader b Server: monit 5.2.1
14 RxHeader b Content-Type: text/html
14 RxHeader b Connection: close
12 TTL c 911966818 RFC 120 1323539930 0 0 0 0
12 VCL_call c fetch
12 VCL_return c pass
12 ObjProtocol c HTTP/1.1
12 ObjStatus c 400
12 ObjResponse c Bad Request
12 ObjHeader c Date: Sat, 10 Dec 2011 17:58:50 GMT
12 ObjHeader c Server: monit 5.2.1
12 ObjHeader c Content-Type: text/html
14 Length b 201
14 BackendClose b monit
12 VCL_call c deliver
12 VCL_return c deliver
12 TxProtocol c HTTP/1.1
12 TxStatus c 400
12 TxResponse c Bad Request
12 TxHeader c Server: monit 5.2.1
12 TxHeader c Content-Type: text/html
12 TxHeader c Content-Length: 201
12 TxHeader c Date: Sat, 10 Dec 2011 17:58:50 GMT
12 TxHeader c X-Varnish: 911966818
12 TxHeader c Age: 0
12 TxHeader c Via: 1.1 varnish
12 TxHeader c Connection: keep-alive
12 Length c 201
12 ReqEnd c 911966818 1323539930.287971973 1323539930.288527966 0.000089884 0.000468969 0.000087023
12 Debug c "herding"
其中最重要的是第3列: b 表示 “backend”,就是varnish和backend端的通信; c 表示 “client”,就是varnish和client端(www browser)之间的通信。
第2列中, VCL_call 表示varnish内部哪个函数被调用,VCL_return则是调用结果是什么。比如:VCL_call retch ,表示VCL配置文件中vcl_fetch函数被调用; VCL_return pass,表示return pass,同样也是VCL配置文件中的语句。