[英]How do I generate a connection reset programatically?
I'm sure you've seen the " the connection was reset " message displayed when trying to browse web pages. 我确定您在尝试浏览网页时看到“ 连接已重置 ”消息。 (The text is from Firefox, other browsers differ.) (该文本来自Firefox,其他浏览器不同。)
I need to generate that message/error/condition on demand, to test workarounds. 我需要根据需要生成该消息/错误/条件,以测试变通方法。
So, how do I generate that condition programmatically? 那么,我如何以编程方式生成该条件? (
How to generate a TCP
) (
RST
from PHP -- or one of the other web-app languages?
如何从PHP生成TCP
) RST
- 或其他一种Web应用程序语言?
Caveats and Conditions: 警告和条件:
It cannot be a general IP block. 它不能是一般的IP块。 The test client must still be able to see the test server when not triggering the condition. 测试客户端在未触发条件时仍必须能够看到测试服务器。
Ideally, it would be done at the web-application level (Python, PHP, Coldfusion, Javascript, etc.). 理想情况下,它将在Web应用程序级别(Python,PHP,Coldfusion,Javascript等)完成。 Access to routers is problematic. 访问路由器是有问题的。 Access to Apache config is a pain. 访问Apache配置很痛苦。
Ideally, it would be triggered by fetching a specific web-page. 理想情况下,它将通过获取特定的网页来触发。
Bonus if it works on a standard, commercial web host. 如果它适用于标准的商业网络主机,则可获得奖励。
Sending RST
is not enough to cause this condition. 发送RST
不足以导致此情况。 See my partial answer, below. 请参阅下面的部分答案。
I've a solution that works on a local machine, Now need to get it working on a remote host. 我有一个适用于本地计算机的解决方案,现在需要让它在远程主机上运行。
I would recommend doing this via a custom socket via CLI as messing with the apache process could be messy: 我建议通过CLI通过自定义套接字执行此操作,因为搞乱apache进程可能会很乱:
#!/usr/bin/php -q
<?php
set_time_limit (0);
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_bind($sock, '1.1.1.1', 8081) or die('Could not bind to address');
socket_listen($sock);
$client = socket_accept($sock);
sleep(1);
$pid = getmypid();
exec("kill -9 $pid");
?>
This will generate the desired error in Firefox as the connection is closed before read. 这将在Firefox中生成所需的错误,因为在读取之前连接已关闭。
If you feel insanely daring, you could throw this into a web script but I wouldn't even venture trying that unless you own the box and know what you're doing admin wise. 如果你觉得疯狂大胆,你可以把它扔进一个网络脚本,但我甚至不敢冒险尝试,除非你拥有这个盒子,并知道你在做什么管理员明智。
I believe you need to close the low-level socket fairly abruptly. 我相信你需要相当突然地关闭低级套接字。 You won't be able to do it from Javascript. 您将无法通过Javascript执行此操作。 For the other languages you'll generally need to get a handle on the underlying socket object and close() it manually. 对于其他语言,您通常需要获取底层套接字对象的句柄并手动关闭()。
I also doubt you can do this through Apache since it is Apache and not your application holding the socket. 我也怀疑你可以通过Apache做到这一点,因为它是Apache而不是你的应用程序持有套接字。 At best your efforts are likely to generate a HTTP 500 error which is not what you're after. 充其量,您的努力可能会产生HTTP 500错误,这不是您所追求的。
This script worked well enough to test our connection-reset workaround, so it's a partial answer. 这个脚本运行良好,足以测试我们的连接重置解决方法,所以这是一个部分答案。
If someone comes up with the full solution that works on a remote host, I'll gladly mark that as the answer. 如果有人提出在远程主机上运行的完整解决方案,我很乐意将其标记为答案。
The following script works every time when running and tested on the same machine. 每次在同一台机器上运行和测试时,以下脚本都可以运行。 But when running on a remote host, the browser gets the following last 3 packets: 但是当在远程主机上运行时,浏览器会获得以下最后3个数据包:
Source Dest Protocol Info
<server> <client> TCP 8081 > 1835 [RST] Seq=2 Len=0
<server> <client> TCP 8081 > 1835 [RST] Seq=2 Len=0
<server> <client> TCP http > 1834 [ACK] Seq=34 Ack=1 Win=6756 Len=0
As you can see, the RST
flag is set and sent. 如您所见, RST
标志已设置并发送。 But Firefox fails silently with a blank page -- no messages of any kind. 但Firefox无声地用空白页面失败 - 没有任何类型的消息。
<?php
$time_lim = 30;
$listen_port = 8081;
echo
'<h1>Testing generation of a connection reset condition.</h1>
<p><a target="_blank" href="http://' .$_SERVER["HTTP_HOST"]. ':' .$listen_port. '/">
Click here to load page that gets reset. You have ' . $time_lim . ' seconds.</a>
</p>
'
;
flush ();
?>
<?php
//-- Warning! If the script blocks, below, this is not counted against the time limit.
set_time_limit ($time_lim);
$socket = @socket_create_listen ($listen_port);
if (!$socket) {
print "Failed to create socket!\n";
exit;
}
socket_set_nonblock ($socket); //-- Needed, or else script executes until a client interacts with the socket.
while (true) {
//-- Use @ to suppress warnings. Exception handling didn't work.
$client = @socket_accept ($socket);
if ($client)
break;
}
/*--- If l_onoff is non-zero and l_linger is zero, all the unsent data will be
discarded and RST (reset) is sent to the peer in the case of a connection-
oriented socket.
*/
$linger = array ('l_linger' => 0, 'l_onoff' => 1);
socket_set_option ($socket, SOL_SOCKET, SO_LINGER, $linger);
//--- If we just close, the Browser gets the RST flag but fails silently (completely blank).
socket_close ($socket);
echo "<p>Done.</p>";
?>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.