<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fwolf's Blog &#187; http - Fwolf's Blog</title>
	<atom:link href="http://www.fwolf.com/blog/post/tag/http/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fwolf.com/blog</link>
	<description>随心·随意·随缘·努力～</description>
	<lastBuildDate>Wed, 07 Jul 2010 07:07:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Curl奇怪的403错误</title>
		<link>http://www.fwolf.com/blog/post/444</link>
		<comments>http://www.fwolf.com/blog/post/444#comments</comments>
		<pubDate>Tue, 30 Jun 2009 17:27:33 +0000</pubDate>
		<dc:creator>Fwolf</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[403]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://www.fwolf.com/blog/?p=444</guid>
		<description><![CDATA[自己用的小PHP应用，使用curl抓网页下来处理，为了穿墙方便，使用Privoxy作为代理，便于选择哪些网站使用proxy、哪些不用。但今天却遇到了奇怪的问题，访问google baidu这些网站居然都返回403错误，而访问其他的一些网站没事，如果设置为不使用proxy则都能正常访问。 难道google baidu就不让用proxy连接么？显然不可能，所以打开curl的信息输出（curl_setopt($this-&#62;mSh, CURLOPT_VERBOSE, 1);）看看，得到以下结果： * Trying 127.0.0.1... * connected * Connected to 127.0.0.1 (127.0.0.1) port 8118 (#0) * Establish HTTP proxy tunnel to www.baidu.com:80 &#62; CONNECT www.baidu.com:80 HTTP/1.0 Host: www.baidu.com:80 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) Proxy-Connection: Keep-Alive &#60; HTTP/1.0 403 Connection not allowable &#60; X-Hint: If you read this [...]]]></description>
			<content:encoded><![CDATA[<p>自己用的小PHP应用，使用curl抓网页下来处理，为了穿墙方便，使用Privoxy作为代理，便于选择哪些网站使用proxy、哪些不用。但今天却遇到了奇怪的问题，访问google baidu这些网站居然都返回403错误，而访问其他的一些网站没事，如果设置为不使用proxy则都能正常访问。</p>

<p>难道google baidu就不让用proxy连接么？显然不可能，所以打开curl的信息输出（<code>curl_setopt($this-&gt;mSh, CURLOPT_VERBOSE, 1);</code>）看看，得到以下结果：</p>

<pre><code>*   Trying 127.0.0.1... * connected
* Connected to 127.0.0.1 (127.0.0.1) port 8118 (#0)
* Establish HTTP proxy tunnel to www.baidu.com:80
&gt; CONNECT www.baidu.com:80 HTTP/1.0
Host: www.baidu.com:80
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Proxy-Connection: Keep-Alive

&lt; HTTP/1.0 403 Connection not allowable
&lt; X-Hint: If you read this message interactively, then you know why this happens ,-)
&lt; 
* The requested URL returned error: 403
* Received HTTP code 403 from proxy after CONNECT
* Closing connection #0
... Failed.
</code></pre>

<p>可以看到proxy服务器工作正常，的确是baidu返回了403错误，但原因肯定还在我这边。终于，从网上（<a href="http://curl.haxx.se/mail/archive-2006-04/0054.html">1of2</a>, <a href="http://curl.haxx.se/mail/archive-2006-04/0055.html">2of2</a>）得到了点启发──我使用的是proxytunnel而非proxy。</p>

<p>在代码中，有这么一句：</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mSh</span><span style="color: #339933;">,</span> CURLOPT_HTTPPROXYTUNNEL<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mSh</span><span style="color: #339933;">,</span> CURLOPT_PROXY<span style="color: #339933;">,</span> <span style="color: #000088;">$phost</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>php文档中没有详细说明，不过<code>man curl</code>中有详细解释，两者都是代理，proxytunnel（<code>-p参数</code>）允许其他协议通过http代理传输，而proxy（<code>-x参数</code>）则只能走http协议。所以我猜测，google baidu的服务器和curl的proxytunnel不和，所以返回403。</p>

<p>禁用掉上面2行代码的第一句后，curl访问恢复正常。</p>

<p>比较奇怪的是，几种操作系统下还不一样，一台MAC OSX就要显式的禁用proxytunnel才可以，curl版本：</p>

<pre><code>$ curl --version
curl 7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Protocols: tftp ftp telnet dict ldap http file https ftps 
Features: GSS-Negotiate IPv6 Largefile NTLM SSL libz 
</code></pre>

<p>而另外一台ubuntu则完全不受影响，怎么都能用，curl版本：</p>

<pre><code>$ curl --version
curl 7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.10
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps 
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 
</code></pre>

<p>MT主机上的centos也没事，curl版本：</p>

<pre><code>$ curl --version
curl 7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
Protocols: tftp ftp telnet dict ldap http file https ftps 
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 
</code></pre>

<p>看来不完全是curl版本问题，MAC OSX的确与众不同啊。</p>

<p>还有一个原因也会导致curl返回403错误，如果设置了：</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_NOBODY<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>则需要紧跟着设置：</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_CUSTOMREQUEST<span style="color: #339933;">,</span> <span style="color: #0000ff;">'GET'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>不然会因为http服务器不允许 HEAD 命令而返回403错误。参考：<a href="http://forums.devshed.com/php-development-5/trouble-with-a-curl-request-in-php-445222.html">Trouble with a cURL request in PHP</a>。MAC OSX上curl之所以特殊，也不排除是这种原因吧。</p>

	Tags: <a href="http://www.fwolf.com/blog/post/tag/403" title="403" rel="tag">403</a>, <a href="http://www.fwolf.com/blog/post/tag/curl" title="curl" rel="tag">curl</a>, <a href="http://www.fwolf.com/blog/post/tag/error" title="error" rel="tag">error</a>, <a href="http://www.fwolf.com/blog/post/tag/http" title="http" rel="tag">http</a>, <a href="http://www.fwolf.com/blog/post/tag/php" title="PHP" rel="tag">PHP</a>, <a href="http://www.fwolf.com/blog/post/tag/proxy" title="proxy" rel="tag">proxy</a>, <a href="http://www.fwolf.com/blog/post/tag/tunnel" title="tunnel" rel="tag">tunnel</a><br />

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.fwolf.com/blog/post/411" title="由一个错误学到的一些php安全配置问题 (2008-07-13)">由一个错误学到的一些php安全配置问题</a> (4)</li>
	<li><a href="http://www.fwolf.com/blog/post/391" title="adodb5连接sybase的一个错误 (2008-03-25)">adodb5连接sybase的一个错误</a> (0)</li>
	<li><a href="http://www.fwolf.com/blog/post/300" title="针对$_SERVER['PHP_SELF']的跨站脚本攻击（XSS） (2007-03-18)">针对$_SERVER['PHP_SELF']的跨站脚本攻击（XSS）</a> (3)</li>
	<li><a href="http://www.fwolf.com/blog/post/443" title="配置安全的共享web服务器（抛砖引玉） (2009-06-09)">配置安全的共享web服务器（抛砖引玉）</a> (4)</li>
	<li><a href="http://www.fwolf.com/blog/post/400" title="选择Eclipse PHP Development Tools(PDT)作为PHP开发工具 (2008-05-03)">选择Eclipse PHP Development Tools(PDT)作为PHP开发工具</a> (8)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.fwolf.com/blog/post/444/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HTTP Referer二三事</title>
		<link>http://www.fwolf.com/blog/post/320</link>
		<comments>http://www.fwolf.com/blog/post/320#comments</comments>
		<pubDate>Sat, 05 May 2007 08:35:48 +0000</pubDate>
		<dc:creator>Fwolf</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[privoxy]]></category>
		<category><![CDATA[referrer]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.fwolf.com/blog/post/320</guid>
		<description><![CDATA[什么是HTTP Referer 简言之，HTTP Referer是header的一部分，当浏览器向web服务器发送请求的时候，一般会带上Referer，告诉服务器我是从哪个页面链接过来的，服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里，他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。 Referer其实应该是英文单词Referrer，不过拼错的人太多了，所以编写标准的人也就将错就错了。 我的问题 我刚刚把feed阅读器改变为Gregarius，但他不像我以前用的liferea，访问新浪博客的时候，无法显示其中的图片，提示“此图片仅限于新浪博客用户交流与沟通”，我知道，这就是HTTP Referer导致的。 由于我上网客户端配置的特殊性，首先怀疑是squid的问题，但通过实验排除了，不过同时发现了一个Squid和Tor、Privoxy协同使用的隐私泄露问题，留待以后研究。 Gregarius能处理这个问题么？ 答案是否定的，因为Gregarius只是负责输出html代码，而对图像的访问是有客户端浏览器向服务器请求的。 不过，安装个firefox扩展也许能解决问题，文中推荐的&#8221;Send Referrer&#8221;我没有找到，但发现另外一个可用的：&#8221;RefControl&#8220;，可以根据访问网站的不同，控制使用不同的Referer。 但是我不喜欢用Firefox扩展来解决问题，因为我觉得他效率太低，所以我用更好的方式——Privoxy。 Privoxy真棒 在Privoxy的default.action中添加两行： {+hide-referrer{forge}} .album.sina.com.cn 这样Gregarius中新浪博客的图片就出来了吧？+hide-referrer是Privoxy的一个过滤器，设置访问时对HTTP Referer的处理方式，后面的forge代表用访问地址当作Refere的，还可以换成block，代表取消Referer，或者直接把需要用的Referer网址写在这里。 用Privoxy比用Firefox简单的多，赶紧换吧。 From https to http 我还发现，从一个https页面上的链接访问到一个非加密的http页面的时候，在http页面上是检查不到HTTP Referer的，比如当我点击自己的https页面下面的w3c xhtml验证图标（网址为http://validator.w3.org/check?uri=referer），从来都无法完成校验，提示： No Referer header found! 原来，在http协议的rfc文档中有定义： 15.1.3 Encoding Sensitive Information in URI's ... Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if [...]]]></description>
			<content:encoded><![CDATA[<h3>什么是HTTP Referer</h3>

<p>简言之，HTTP Referer是header的一部分，当浏览器向web服务器发送请求的时候，一般会带上Referer，告诉服务器我是从哪个页面链接过来的，服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里，他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。</p>

<p>Referer其实应该是英文单词Referrer，不过拼错的人太多了，所以编写标准的人也就将错就错了。</p>

<h3>我的问题</h3>

<p>我刚刚把feed阅读器改变为<a href="http://gregarius.net/">Gregarius</a>，但他不像我以前用的liferea，访问新浪博客的时候，无法显示其中的图片，提示“此图片仅限于新浪博客用户交流与沟通”，我知道，这就是HTTP Referer导致的。</p>

<p>由于<a href="294">我上网客户端配置的特殊性</a>，首先怀疑是squid的问题，但通过实验排除了，不过同时发现了一个<a href="http://wiki.noreply.org/noreply/TheOnionRouter/SquidProxy">Squid和Tor、Privoxy协同使用的隐私泄露问题</a>，留待以后研究。</p>

<h3>Gregarius能处理这个问题么？</h3>

<p><a href="http://forums.gregarius.net/comments.php?DiscussionID=448">答案是否定的</a>，因为Gregarius只是负责输出html代码，而对图像的访问是有客户端浏览器向服务器请求的。</p>

<p>不过，安装个firefox扩展也许能解决问题，文中推荐的&#8221;Send Referrer&#8221;我没有找到，但发现另外一个可用的：&#8221;<a href="https://addons.mozilla.org/en-US/firefox/addon/953">RefControl</a>&#8220;，可以根据访问网站的不同，控制使用不同的Referer。</p>

<p>但是我不喜欢用Firefox扩展来解决问题，因为我觉得他效率太低，所以我用更好的方式——Privoxy。</p>

<h3>Privoxy真棒</h3>

<p>在Privoxy的default.action中添加两行：</p>

<pre><code>{+hide-referrer{forge}}
.album.sina.com.cn
</code></pre>

<p>这样Gregarius中新浪博客的图片就出来了吧？<code>+hide-referrer</code>是Privoxy的一个过滤器，设置访问时对HTTP Referer的处理方式，后面的<code>forge</code>代表用访问地址当作Refere的，还可以换成<code>block</code>，代表取消Referer，或者直接把需要用的Referer网址写在这里。</p>

<p>用Privoxy比用Firefox简单的多，赶紧<a href="294">换</a>吧。</p>

<h3>From https to http</h3>

<p>我还发现，从一个https页面上的链接访问到一个非加密的http页面的时候，在http页面上是检查不到HTTP Referer的，比如当我点击自己的https页面下面的w3c xhtml验证图标（网址为<a href="http://validator.w3.org/check?uri=referer">http://validator.w3.org/check?uri=referer</a>），从来都无法完成校验，提示：</p>

<pre><code>No Referer header found!
</code></pre>

<p>原来，在<a href="http://www.ietf.org/rfc/rfc2616.txt">http协议的rfc文档</a>中有定义：</p>

<pre><code>15.1.3 Encoding Sensitive Information in URI's

...

   Clients SHOULD NOT include a Referer header field in a (non-secure)
   HTTP request if the referring page was transferred with a secure
   protocol.
</code></pre>

<p>这样是出于安全的考虑，访问非加密页时，如果来源是加密页，客户端不发送Referer，<a href="http://support.microsoft.com/kb/178066">IE一直都是这样实现的</a>，<a href="http://kb.mozillazine.org/Network.http.sendSecureXSiteReferrer">Firefox浏览器也不例外</a>。但这并不影响从加密页到加密页的访问。</p>

<h3>Firefox中关于Referer的设置</h3>

<p>都在<about:config>里，有两个键值：</about:config></p>

<ul>
<li><p>network.http.sendRefererHeader (default=2)
设置Referer的发送方式，0为完全不发送，1为只在点击链接时发送，在访问页面中的图像什么的时候不发送，2为始终发送。参见<a href="http://cafe.elharo.com/privacy/privacy-tip-3-block-referer-headers-in-firefox/">Privacy Tip #3: Block Referer Headers in Firefox</a></p></li>
<li><p>network.http.sendSecureXSiteReferrer (default=true)
设置从一个加密页访问到另外一个加密页的时候是否发送Referer，true为发送，false为不发送。</p></li>
</ul>

<h3>利用Referer防止图片盗链</h3>

<p>虽然Referer并不可靠，但用来防止图片盗链还是足够的，毕竟不是每个人都会修改客户端的配置。实现一般都是通过apache的配置文件，首先设置允许访问的地址，标记下来：</p>

<pre><code># 只允许来自domain.com的访问，图片可能就放置在domain.com网站的页面上
SetEnvIfNoCase Referer "^http://www.domain.com/" local_ref
# 直接通过地址访问
SetEnvIf Referer "^$" local_ref
</code></pre>

<p>然后再规定被标记了的访问才被允许：</p>

<pre><code>&lt;FilesMatch ".(gif|jpg)"&gt;
Order Allow,Deny
Allow from env=local_ref
&lt;/FilesMatch&gt;
</code></pre>

<p>或者</p>

<pre><code>&lt;Directory /web/images&gt;
   Order Deny,Allow
   Deny from all
   Allow from env=local_ref
&lt;/Directory&gt;
</code></pre>

<p>这方面的文章网上很多，参考：</p>

<ul>
<li><a href="http://leftleg.hzpub.com/read.php?405">Apache 下防止盗链的解决办法</a></li>
<li><a href="http://blog.51766.com/page/zsc?entry=1144852732034">Apache的环境变量设置</a></li>
<li><a href="http://blog.soueasy.net/post/80.htm">配置 Apache 实现禁止图片盗链</a></li>
</ul>

<h3>不要使用Rerferer的地方</h3>

<p>不要把Rerferer用在身份验证或者其他非常重要的检查上，因为Rerferer非常容易在客户端被改变，不管是通过上面介绍的Firefox扩展，或者是Privoxy，甚至是libcurl的调用，所以Rerferer数据非常之不可信。</p>

<p>如果你想限制用户必须从某个入口页面访问的话，与其使用Referer，不如使用session，在入口页面写入session，然后在其他页面检查，如果用户没有访问过入口页面，那么对应的session就不存在，参见<a href="http://www.thescripts.com/forum/thread3090.html">这里的讨论</a>。不过和上面说的一样，也不要过于相信这种方式的“验证”结果。</p>

<p>个人感觉现在Rerferer除了用在防盗链，其他用途最多的就是访问统计，比如统计用户都是从哪里的链接访问过来的等等。</p>

	Tags: <a href="http://www.fwolf.com/blog/post/tag/http" title="http" rel="tag">http</a>, <a href="http://www.fwolf.com/blog/post/tag/privoxy" title="privoxy" rel="tag">privoxy</a>, <a href="http://www.fwolf.com/blog/post/tag/referrer" title="referrer" rel="tag">referrer</a>, <a href="http://www.fwolf.com/blog/post/tag/tips" title="tips" rel="tag">tips</a><br />

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.fwolf.com/blog/post/300" title="针对$_SERVER['PHP_SELF']的跨站脚本攻击（XSS） (2007-03-18)">针对$_SERVER['PHP_SELF']的跨站脚本攻击（XSS）</a> (3)</li>
	<li><a href="http://www.fwolf.com/blog/post/410" title="用ssh打通反向隧道，内网也可对外提供服务 (2008-07-10)">用ssh打通反向隧道，内网也可对外提供服务</a> (2)</li>
	<li><a href="http://www.fwolf.com/blog/post/377" title="你最希望在哪里看到TIPS？ (2008-01-10)">你最希望在哪里看到TIPS？</a> (5)</li>
	<li><a href="http://www.fwolf.com/blog/post/152" title="[Ubuntu]使用点滴 (2006-07-08)">[Ubuntu]使用点滴</a> (7)</li>
	<li><a href="http://www.fwolf.com/blog/post/446" title="[Git]初学者注意事项 (2009-08-04)">[Git]初学者注意事项</a> (0)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.fwolf.com/blog/post/320/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
