0

I have a PHP script that runs from our server's non-publicly-accessible directory as a cron task. The script sends cURL POSTs to a publicly-accessible URL.

I set up the receiving URL with a .htaccess file that denies access from any IP address other than the ones I allowed. I ran a PHP script that emailed me the output of a file_get_contents("http://www.whatismyipaddress.com"); to get my server's origin IP address (it's a dedicated server so I don't expect it to change). That's the IP I allowed in the .htaccess file.

But when I ran the script through an SSH prompt, all of the POSTs returned 403 Forbidden errors. When I commented out the .htaccess protections, the POSTs succeeded.

Then I looked at my log files and it turned out the POSTs were coming from a different IP than what was reported by my file_get_contents(). It was easy enough to add that IP to the .htaccess file, which fixed the problem.

But I'm confused as to why there are two different origin IP addresses. Can anyone shed some light on the subject?

Mike Willis
  • 1,493
  • 15
  • 30

1 Answers1

1

First of all, that's a weird way to find out your server's IP address. Tried these?

PHP how to get local IP of system

Second: Do you know if the server is behind a firewall/NAT or something else that redirects traffic? It could be that outgoing traffic from your server via the webserver is allowed, but traffic when called from the command line (different PHP process) goes another route through a proxy so that you end up with 2 different IP addresses in your destination server.

Edit: Clarified something

Edit2: Try this:

On your publicly accessible server, set up a script i.php with the following content:

<?php die($_SERVER['REMOTE_ADDR']); ?>

Then, on your private server that runs cron, make a script like that:

<?php echo file_get_contents("http://publicserver.com/i.php"); ?>

Run it from your browser. Then run it from the shell via SSH. Then, via SSH, execute the following command:

curl http://publicserver.com/i.php

Compare output. Is it all the same?

Community
  • 1
  • 1
ntaso
  • 614
  • 6
  • 12
  • Not sure about the firewall/NAT, but I assume something like that is possible. I didn't know about other methods to get the origin IP, those sound good too. Also not sure about different IPs for the script when run as a cron vs when run through the command prompt. I did all my testing through the command prompt after I saw that the cron was failing. I had both the file_get_contents() and cURL in the script, and (as it turned out) they disagreed with each other. So that could be correct but I don't think it's the reason for the different IP's I saw. – Mike Willis Feb 20 '14 at 14:30
  • Updated my answer, try it please. – ntaso Feb 20 '14 at 14:36
  • Also, it looks like most of the methods in the question you linked are for getting an internal network IP, this is different than the server's origin IP address. – Mike Willis Feb 20 '14 at 14:37
  • ok now we're getting somewhere! When running i.php from the browser, I get (as expected) my own computer's IP. When running through a PHP script through the command prompt, I get the address I found in my log files. When running the cURL through command prompt, I get that address too. So actually file_get_contents() and cURL agree with each other. Then I updated the script to do a file_get_contents() of whatismyipaddress.com, as well as my test script. The whatismyipaddress.com returns the different IP. Looks like traffic to an external address gets a different origin IP than internal! – Mike Willis Feb 20 '14 at 14:45
  • Yeah, seems like some outgoing traffic is routed through a proxy. `$_SERVER['SERVER_ADDR']` should get the own server's IP address. However, this might not be the same that is recorded by your public server. Depends on the private server's configuration and network environment. In your htaccess-file, you could add that address from $_SERVER as well as the one that you got from running the script from the shell. – ntaso Feb 20 '14 at 14:49
  • Just a hint: Another way to make this whole thing secure is, if you give the public script some token. Check if $_GET['token'] == 'mysecret'. If wrong, then don't do anything. If correct, execute the rest. Then, in your private server script, you send the same token along with the request, e. g. `file_get_contents('http://publicserver.com/myscript.php?token=mysecret');`. This way, someone can only execute the public script if he provides the correct token and you don't have to do this whole IP stuff at all. – ntaso Feb 20 '14 at 14:52
  • Yea I do that a lot too, in this case the receiving page is compiled and I don't have access to it, so I'm using the slightly annoying IP restrictions. Thanks for the help with figuring this out! – Mike Willis Feb 20 '14 at 14:56