Tuesday, May 25, 2010

PHP fopen() Tricks

The fopen() function in PHP allows one to read a remote file, or a web page. I recently added a feature in the logmon module to read and parse a remote syslog event definition page by its URL in the Cisco web space, such as this one documenting Cisco NX-OS events.

Here are two tricks that I have learned implementing the above feature. In my case, the server on which my code is run is on a subnet not NATted from the internal network to the outside, which means that I can not directly access an external website. There are two ways to work around this issue:
  1. Use an IP address that is NATted or accessible from the outside;
  2. Go through a proxy server.

Multi-Homed Server


Re-addressing a server may be a bit more involved especially in networking where IP addresses do get directly used a lot. However, a server may have more than one IP addresses. So if we add an IP address that is NATted or public, we can go back to work. To use a different IP address on the server for fopen(), one needs to use the forth parameter to fopen(): the $context.

Here is a little snippet of PHP code specifying source interface for fopen():

$srcip = '192.168.20.30'; // Assuming this is a NATted IP address
$context = stream_context_create
(
array
(
'socket' => array
(
'bindto' => $srcip,
)
)
);
($fn = fopen($url, "r", false, $context)) || die("Can not open '$url'\n\n");

while (!feof($fn)) {
echo fgetss($fn);
}

Proxy


Another way out of this problem is to use a proxy server that is accessible from the internal network. We do have a few of those deployed. To use one of them, we only need to make a simple change in how the $context is created in the example above:

$context = stream_context_create
(
array
(
'http' => array
(
'proxy' => 'tcp://192.168.10.10:80' // The proxy server address and port
),
)
);

3 comments:

  1. Thanks for this information. I am having an issue though..

    I have an IP bound to eth0:26 which works fine.

    The code I'm using is:

    $srcip = 'myip';
    $context = stream_context_create(array( 'socket' => array ( 'bindto' => $srcip )));

    $handle = fopen($url, 'r', false, $context);

    but requests are still going out my main IP bound to eth0.

    Any thoughts on this?

    Thanks

    ReplyDelete
  2. $srcip = '192.168.20.30:8000'; // Assuming this is a NATted IP address
    $context = stream_context_create
    (
    array
    (
    'socket' => array
    (
    'bindto' => $srcip,
    )
    )
    );
    ($fn = fopen($url, "r", false, $context)) || die("Can not open '$url'\n\n");

    while (!feof($fn)) {
    echo fgetss($fn);
    }

    ReplyDelete
  3. Hi,

    It works fine to download the files but if I want to use username and password that how can I use that ??
    Your help will be appreciated.
    Thanks in advance. :)

    ReplyDelete