today I came a across a pretty strange behaviour of an php based application of mine.
In a certain part of the system there's an UI making use of AJAX-calls to fill list
boxes with content from the backend.
Now, the AJAX listener performs a security check on all incoming requests, making sure
that only valid client IPs get responses. The valid IP are stored in the backend too.
To get the client's IP I used plain old
$_SERVER['REMOTE_ADDR']
which works out for most of the clients. Today I ran into an installation where
remote_addr contained the IP of an network adapter which was'nt that one which performed
the actual communication for my application.
Googling around agve me Roshan's Blog entry on the topuic:
function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP'])) //check ip from share internet
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))//check ip is pass from prxy
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}
Sadly the problem persists.
Did anybody ever stumble into this sort of problem (actually I don't think that I discovered a completly new issue ^^) and has an idea for me how to fix this?
EDIT:
I'm on
PHP Version 5.2.9-1
Apache/2.2.9 (Win32)
The communication is done via a regular LAN card. Now the actuall client has several
devices more. VMNet adapters and such.
I'm wondering how a client configuration can 'disturb' a web server that much...
TIA
K
Unfortunately, you have to take all IP information with a grain of salt.
IP addresses are gathered during the request by taking the packet and request information into account. Sadly, this information can easily be spoofed or even be incorrect (based on a large number of network probabilities) and should not be used for anything more than vanity purposes.
Related
I need to use the Google Places API through PHP in a Wordpress site hosted on Flywheel.
It seems the option I need to use is the IP addresses (web servers, cron jobs, etc.).
My problem is that flywheel has a dynamic IP address system and after a couple of days the API stops working since the IP has changed.
I' trying to see if I can authenticate the site using something else but I have not been able to find it.
I've looked at googleapis/google-api-php-client but the Places API is not part of the APIs the package can connect.
Do you know how If there is any other way to whitelist a site for a web server with a dynamic IP?
It's not necessary to use the API key restriction. You don't need to restrict it by an IP address. It's an optional feature per key.
I'll try to give you at least an option/suggestion because I'm not sure how you intent to use the Google Place API but you can basically create 2 separate keys:
One public API key for browser based calls (show map, suggestions, etc..). In this case I would use HTTP referrer for as restriction and add your websites where this key is running.
One private API key for server based calls (server2server, queue, cronjobs, etc..). Since you have a floating IP you would need to know the full range. In this case I would not "additionally" restrict it by the IP address and only use the secret.
Another suggestions in case your really really want to restrict this additionally:
Ask flywheel if they can give you a dedicated IP address. A quick google lookup showed some forums which indicate that they support it. Attention: I'm sure they will charge you for this additional money.
Move your cronjobs, queues, ... away from flywheel and host it somewhere, where you have control of the IP address. (e.g. AWS EC3 t3.nano with an elastic ip address - costs you ~$5/month)
Hope this helps and gives you some impressions about your options. Let me know if this answers your question or if you need and further information.
Using the simple php curl function for Facebook user-account control, I pull out the site and do the detection according to the incoming data.
But because I have multiple queries, Facebook blocks and php codes are disabled. How can I show each browser function as if it was entered from a different computer by modifying the browser ip-user agent (if there is a proxy) before running it?
Thank you.
Your trying to ask that your ip is blocked to get data through API so that you are trying to fetch data from different ip[proxy]. If this is your concern then try to find why your ip has blocked and get whitelist your ip from FB!!!!!
First, access canhazip.com or jsonip.com from the server to make sure it has the public IP you think.
Second, make sure that IP address is in "Server IP Whitelist" for the app's Settings > Advanced section in the Developer console (https://developers.facebook.com/apps/[APP ID]/settings/advanced/).
I'm migrating our system to the Google App Engine.
When our PDF generator needs a external resource (for example a picture) it does an internal HTTP request (where the request IP is different from the user IP). It then also starts an different session, so I cannot see if the user is logged.
In order to give the right permissions, I need to check if the request comes from a server IP.
In the previous code I checked this trough the following code:
if($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']) {
return true;
}
But since $_SERVER['SERVER_ADDR'] is not available, this cannot be used.
In the new code I check this trough the following code:
$allowed_ips = array(
'127.0.0.1',
'8.35.201.100'
);
if(in_array($_SERVER['REMOTE_ADDR'], $allowed_ips)) { return true; }
The problem is; I do not know which IP addresses Google App Engine uses to do a internal request.
I have found the IP address 8.35.201.100 as a server address, but are there more IP addresses or maybe ranges.
The Task Queues Google App Engine issues requests from the IP address 0.1.0.2 (https://developers.google.com/appengine/docs/php/taskqueue/overview-push#Task_Execution). Is this the same at the internal request.
Greets, Hendrik
I don't think AppEngine discloses IP addresses. AppEngine is a dynamic environment with instances spinning up and spinning down, there would be requests from different IPs as things change.
When you make HTTP requests from AppEngine, it does set a few header fields to mark that the request was from AppEngine. I think the AppId is included. Anyway here is the documentation on that.
https://developers.google.com/appengine/docs/php/urlfetch/#Request_Headers
From a security standpoint, anyone can just write fake HTTP headers. So I wouldn't rely on that as a means of authentication.
I'm trying to run a SOAP method on another domain which must be received from a whitelisted IP Address, but the WSDL seems to somehow think the request is coming from the client and not the server. The call collects information from a form, uses AJAX to post to a PHP function, which formats the fields into the API-friendly format, which is then sent via PHP SoapClient.
I thought the best way to do this was to investigate the headers being sent with the SoapClient, but the headers don't list any IP address (Host, Connection, User-Agent, Content-Type, SOAPAction, and Content-Length).
First, I read the documentation of the SOAP endpoint. It doesn't apparently specify any specific parameter to be passed, which wouldn't make sense anyway because I'd just be able to fake an IP address. Then, I read the documentation for PHP SoapClient. Interestingly I couldn't find quite where the IP addresses were set, but I did find a comment which mentions using 'stream_context', but had no luck with that either.
I am also logging every request, including $_SERVER['SERVER_ADDR'] and $_SERVER['REMOTE_ADDR'], which are both reporting IP addresses as expected; technical support on their end tell me that they are receiving requests from the 'REMOTE_ADDR' value.
I tried sending a bare-bones request and expected to get a different error besides the IP address, but I keep getting IP address problems.
Is there any way I can be more sure that I am sending the SOAP request with the proper (server) IP?
Okay, I figured it out - at least for my own situation. The comment in the PHP manual that you read was correct (assuming we're talking about the same one), however, I needed to include the port on my IP address as well. So the code that I ended up using was:
$options = array('socket' => array('bindto' => 'xxx.xxx.xx.xxx:0'));
$context = stream_context_create($options);
$client = new SoapClient($url,
array('trace' => 1, 'exception' => 0, 'stream_context' => $context));
See, before, I had no included ":0" I had merely included the IP address. So don't forget that!
This is a tough one, because the question does not really draw a clear picture on what systems are actually involved and where and what kind of IP whitelisting is in use.
When using SOAP, the primary source of information about the service is included in the WSDL resource. It is supposed to be obtained via a HTTP request, and it might trigger additional HTTP request if the XML of the primary resource has xi:include elements. All these requests originate from the system that acts as the SOAP client. You cannot choose which IP address to use here (unless you have a very exotic setup of having TWO interfaces that BOTH have a valid route to the target system, and choosing the right IP is the task of the application - I wouldn't think this is the case here, and I stop thinking about it - you'd need to configure a stream context for this, set the "bindto" option, and pass it into the SoapClient).
Inside the WSDL, the URL of the real SOAP server is contained. Note that the server itself might be on a completely different domain than the WSDL description, although such a setup would also be unusual. You can override that location by passing an option array to the SoapClient with an entry "location" => "http://different.domain.example/path/to/service". This would not change the loading of WSDL ressources, but all requests for the SOAP service would go to that different base URL.
The call collects information from a form, uses AJAX to post to a PHP function, which formats the fields into the API-friendly format, which is then sent via PHP SoapClient.
There are plenty of clients and servers mentioned here. AJAX is mentioned, which makes me believe a browser is involved. This is system 1, acting as a client. A request gets sent to some PHP. This target is system 2, acting as a server here. It transforms it and, acting as a client, sends the SOAP request to system 3, which is acting as another server.
So where is the whitelist? If it is on system 3, it must list the IP that is used by system 2. Note that every networked computer has more than one IP address: At least the one from that network device, plus 127.0.0.1. With IPv6, there are even multiple addresses per each device. Using $_SERVER['SERVER_ADDR'] does not really make sense here - and additionally, systems that are on the transport way, like transparent proxies, might also influence the IP. You shouldn't use the SERVER_ADDR as the entry for the whitelist. You should really check the network setup on a shell to know which network device is used, and what IP it has. Or ask the server you are about to contact to check which IP they are seeing.
I am also logging every request, including $_SERVER['SERVER_ADDR'] and $_SERVER['REMOTE_ADDR'], which are both reporting IP addresses as expected; technical support on their end tell me that they are receiving requests from the 'REMOTE_ADDR' value.
This is the strange thing. SERVER_ADDR and REMOTE_ADDR on system 2 are set as expected. I read this as REMOTE_ADDR being the IP of system 1, and SERVER_ADDR being that of system 2. But system 3 sees the IP from system 1? What is happening here? I'd really like to have more feedback on this from the original poster, but the question is already half a year old.
And it does not have a proper description of the experienced "IP address problems". How are they seen? Is it a timeout with "connection failed", or is it any proper HTTP rejection with some 4xx status code that triggers a SoapFault? This problem can only really be solved if the description would be better.
I do suspect however, that there might be complicated code involved, and the real SOAP request is in fact sent by the browser/system 1, because the generated XML on system 2 is mirrored back to system 1 and then sent to system 3. It would at least explain why the IP of system 1 is seen on system 3.
Ok, so I found out that it is impossible to get the server IP rather than the client IP. Very unfortunate...
I guess you will have to keep track of credentials by use of login/pass
Had the same problem. You have two solutions. Both require an extra step for calling the web service.
1) Use file_get_contents to acces your page that actually interrogates the WS via php soap. Example:
public function test() {
$result = file_get_contents('http://your.domain.com/pages/php-soap?params=your-params');
header("Content-type: text/xml; charset=utf-8");
echo $homepage;
}
2) Use CURL for the same purpose.
That way, you'll pass the server ip to the webservice. You can also secure your pages, by checking in php-soap (this example) the ip of the caller (the server ip in your case, which is unique).
Quick and dirty.
how to identify remote machine uniquely in proxy server environment, i have used $_SERVER['REMOTE_ADDR'] but all machines in proxy network has same IP Address, is there any way
Don't ever depend on information that is coming from the client. In this case, you're running up against simple networking problems (you can never be sure the client's IP address is correct), in other cases the client may spoof information on purpose.
If you need to uniquely identify your clients, hand them a cookie upon their first visit, that's the best you can do.
Your best bet would be :
$uid = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']);
however, there's no way to know if they changed their user agent or different browser.
You could use some other headers to help, like these ones (ones that come to mind when looking at a dump of $_SERVER) :
HTTP_USER_AGENT
HTTP_ACCEPT
HTTP_ACCEPT_LANGUAGE
HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_CHARSET
Using several informations coming from the client will help differenciate different clients (the more information you use, the more chances you have that at least one of those is different between two clients)...
... But it will not be a perfect solution :-(
Depending on the kind of proxy software and it's configuration, there might be a header called X-Forwarded-For, that you could use :
The X-Forwarded-For (XFF) HTTP header
is a de facto standard for identifying
the originating IP address of a client
connecting to a web server through an
HTTP proxy or load balancer. This is a
non-RFC-standard request header which
was introduced by the Squid caching
proxy server's developers.
But I wouldn't rely on that either : it will probably not always be present (don't think its' required)
Good luck !
I do not think there are other ways to do what you want. This is because the proxy server proxies the clients' requests and acts on their behalf. So, the clients are virtually hidden from the server's point of view. However, I may be wrong.
If you are aware of the proxy server, I think that implies this is some kind of company LAN. Are you in control of the LAN? Perhaps building and installing some ActiveX plugin which sends a machine-unique ID to the server might be the solution.
In general, HTTP proxy servers are not required to send the IP of their client. So every request sent by a proxy looks like it came from the proxy's IP. (Although the wikipedia has some mention of custom headers some proxies send to forward the client's ip.)
It gets even worse when an HTTP proxy is itself using another HTTP proxy - the server getting the request will only get the IP of the last proxy in the chain, and there's no guarantee that the 2nd proxy is even aware that the 1st proxy wasn't a regular client!
There is currently no way of doing this as you don't get information about the MAC address, and even that can be wrong, as if there are 2 network cards like a wired one or wireless one.
The best thing to do is locally to get JavaScript to write and read to local storage and send that saved setting back to your server with an Ajax command. This still isn't perfect as if they clear their cache, the setting is lost.
JKS,
Remote machines do not have unique identifiers. This is impossible.
Usually developers like to track machines when the end-user visits a page with a form like a login for security reasons.
Here is what I do: I store a cookie, a session variable and use the new html5 localStorage to track folks on my sensitive pages. This is really the only way to do this accurately. The nice thing about localStorage (when browsers can do this), the end-user typically has no idea you are storing stuff on their machine and deleting cookies has no effect.
So you might make a database table with tracking details like:
timestamp, ip_address, user_agent
then let's say you are tracking failed login attempts.. I would do this:
if(isset($_SESSION['failed_logins'])) {
$failed_logins = $_SESSION['failed_logins'];
$_SESSION['failed_logins'] = ($failed_logins + 1);
} else {
$_SESSION['failed_logins'] = 1;
}
I would then do the same for with setcookie() and then the localStorage script..
Now I am tracking this person and know how many times they are failing a login..
I would then write this user's data to my failed_login table as described above.
I'm sure this isn't the answer you were looking for, but it really is the best way to track users on your site.