PHP在连接关闭后重定向、Iptables和数据


PHP Redirect, Iptables, and data after connection closed

这是一个奇怪的问题。我们最近在我们的代码中发现了一个3个月前的bug,我们在print_r之后发布了一个302重定向头。因此,浏览器将接收该字符串,而不会重定向到下一页。

这个print_r已经在生产环境中存在了很长一段时间,没有人提到它,这让我们相信这是生产和开发中的配置差异。最新的更改是对IPtables的更改,当我们恢复更改时,似乎解决了问题。

奇怪的是,我们不能重现这个问题来启发我们自己。这给我带来了一个问题,IPtables甚至可以影响302重定向吗?更不用说,关心数据是否在标头之前发送?从我的研究来看,没有,但我想先联系那些无所不知的人。

几天前更改IPtables的人(我们恢复并以某种方式解决了这个问题)说这些是违规条目:

ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED

第一个条目是它原来的样子,第二个条目是他把它修改成破坏网站的样子。回到第一个条目"修复了它"。首先,我知道,超级安全…这是一个本地开发盒。

我试着卷曲url(这是现在工作,因为我们不能打破它),看看我能看到什么,我注意到这个问题的第二部分。Curl在print_r进入之前注册* Closing connection #0,当它进入时,它在我的提示符下进入:

< HTTP/1.1 302 Found
< Date: Thu, 18 Apr 2013 16:14:55 GMT
< Server: Apache/2.2.3 (Red Hat)
< X-Powered-By: PHP/5.3.3
< location: app.php?cart_item_id=1234567
< X-UA-Compatible: IE=Edge
< Content-Length: 17
< Connection: close
< Content-Type: text/html; charset=UTF-8
<
* Closing connection #0
<pre>before</pre>[user@localhost ~]$

所以…是的。任何想法吗?我的意思是,现在一切都好了,我只是想知道为什么……

Bass:好的,但是当我旋转yahoo.com时,我得到这个:

[user@localhost~]$ curl yahoo.com -v
* About to connect() to yahoo.com port 80 (#0)
*   Trying 206.190.36.45...
* connected
* Connected to yahoo.com (206.190.36.45) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-redhat-linux-gnu) libcurl/7.24.0 NSS/3.13.5.0 zlib/1.2.5 libidn/1.18 libssh2/1.2.2
> Host: yahoo.com
> Accept: */*
>
< HTTP/1.1 301 Redirect
< Date: Fri, 19 Apr 2013 13:28:10 GMT
< Connection: close
< Server: YTS/1.20.13
< Cache-Control: no-store
< Content-Type: text/html
< Content-Language: en
< Location: http://www.yahoo.com/
< Content-Length: 211
<
<HEAD><TITLE>Redirect</TITLE></HEAD>
<BODY BGCOLOR="white" FGCOLOR="black">
<FONT FACE="Helvetica,Arial"><B>
 "<em>http://www.yahoo.com/</em>".<p></B></FONT>
<!-- default "Redirect" response (301) -->
</BODY>
* Closing connection #0
[user@localhost~]$

我得到* Closing connection #0后,所有的内容。有什么区别呢?

对于iptables规则,在该规则之后还有其他允许,端口80等。所以我猜....钻……我不知道…

正如Bass所说,头将在print_r之前发送。此外,iptables不会做"深度包检查",所以它不能看到你的消息的内容。

两行的不同之处在于第一行允许所有数据包从任何ip到任何ip,而第二行只允许已经建立的连接的数据包

如果没有规则允许数据包建立新连接。任何数据包都不会在允许建立连接的规则下流动。

参见http://php.net/manual/en/function.print-r.php除非将返回参数设置为true,否则print-r的结果将被缓冲。所以print_r不触发发送HTTP头。然后读取http://php.net/manual/en/function.header.php: HTTP状态标头行将始终是第一个发送到客户端的,而不管实际的header()调用是否是第一个。除非HTTP头已经发送,否则状态可能随时被调用header()用新的状态行覆盖。