Reputation: 93613
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.)
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?
Caveats and Conditions:
It cannot be a general IP block. 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.). Access to routers is problematic. Access to Apache config is a pain.
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. 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.
Upvotes: 9
Views: 4618
Reputation: 93613
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:
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. But Firefox fails silently with a blank page -- no messages of any kind.
<?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>";
?>
Upvotes: 2
Reputation: 48887
I would recommend doing this via a custom socket via CLI as messing with the apache process could be messy:
#!/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.
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.
Upvotes: 1
Reputation: 39014
I believe you need to close the low-level socket fairly abruptly. You won't be able to do it from 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. At best your efforts are likely to generate a HTTP 500 error which is not what you're after.
Upvotes: 1