I'm trying to whip up some PHP that will open a TCP socket connection to a specified port on a specified host. That's all I'm doing is opening the connection, then closing it. I'm essentially just sniffing ports so I don't need to send or receive any data. I know of two ways to do this:
- fsockopen()
- socket_create(), socket_connect()
But as with all things in life, things get hung up in the details. There are two very important 'features' that I need.
First, I need to be able to bind this outgoing connection to alternate IP that my server has. This website is running on it's own unique IP, and this IP is not the server's default IP. So I'd like all outgoing connections from this site to also use this unique IP. As it turns out, you can bind to an IP using socket_bind() with the socket_create() function. It works nice and easy.
Second, I need to set a connection timeout. Not a read/write timeout, because I'm not actually reading or writing anything. I'm just opening the connection, and then closing it. So I need a way to apply a timeout to that process. As it turns out, fsockopen() supports connection timeouts by default, just stick an int as the 5th argument when calling the function. Nice and easy.
But the problem is that (as far as I've been able to learn), you can't bind to an IP with fsockopen() and you can't set a connection timeout with socket_create()/socket_connect(). Here is the code I have. I tried both techniques, but each one has it's corresponding flaw as mentioned above. using socket_create(), i've even tried setting the default_socket_timeout ini value using ini_set() but nothing seems to have any effect.
I've also read somewhere that I could possibly make socket_connect() connect using a non blocking connection. Which would not hold up the script while the connection is attempted. This why, I could simply give up waiting for a result after my $timeout. The problem is, other than casual mentions, I haven't been able to find any documentation or sample code of how you'd actually DO this. I don't know if it would even work.
So here is my original code, using fsockopen(). It has a connection timeout and it works great, except that the connections are coming from the wrong IP address because I haven't found any way to bind these connections to another IP address.
$sock = @fsockopen($ip,$port,$errno,$errstr,$timeout);
if ($sock)
{
// Open
fclose($sock);
return 1;
}
else
{
if ($errno === 60)
{
// Timeout
return 2;
}
else
{
// Closed
return 3;
}
}
Here was my second try using socket_create() and socket_connect(). These connections are bound to the proper IP address, but there is no way to set a connection timeout. This means that if the port is blocked by a firewall, my PHP script will keep running for about 45 seconds until it gives up. In this code, I even tried setting the read and write timeouts to see if that would work, but it does not. Nor does setting the default_socket_timeout value.
ini_set("default_socket_timeout",$timeout);
$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($sock,OPERATING_IP);
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array("sec" => $timeout, "usec" => 0));
$sock_status = @socket_connect($sock,$ip,$port);
if ( $sock_status )
{
// Open
socket_close($sock);
return 1;
}
else
{
$sock_error = socket_last_error($sock);
if ($sock_error === 61)
{
// Closed
return 3;
}
else
{
// Timeout
return 2;
}
}
Anyway, this is my dilemma. I'm sure there must be some way to make this work, but it seems like PHP socket functions just aren't used that much, and because of that, they don't have nearly as much documentation and sample code across the internet.
[edited by: phranque at 11:35 pm (utc) on Dec 26, 2013]
[edit reason] syntax=php [/edit]