How do I find out the ISP provider of a person viewing a PHP page?
Is it possible to use PHP to track or reveal it?
If I use something like the following:
gethostbyaddr($_SERVER['REMOTE_ADDR']);
it returns my IP address, not my host name or ISP.
This seems to be what you're looking for, it will attempt to return the full hostname if possible:
http://us3.php.net/gethostbyaddr
EDIT: This method no longer works since the website it hits now blocks automatic queries (and previously this method violated the website's terms of use). There are several other good [legal!] answers below (including my alternative this this one.)
You can get all those things from the following PHP codings.,
<?php
$ip=$_SERVER['REMOTE_ADDR'];
$url=file_get_contents("http://whatismyipaddress.com/ip/$ip");
preg_match_all('/<th>(.*?)<\/th><td>(.*?)<\/td>/s',$url,$output,PREG_SET_ORDER);
$isp=$output[1][2];
$city=$output[9][2];
$state=$output[8][2];
$zipcode=$output[12][2];
$country=$output[7][2];
?>
<body>
<table align="center">
<tr><td>ISP :</td><td><?php echo $isp;?></td></tr>
<tr><td>City :</td><td><?php echo $city;?></td></tr>
<tr><td>State :</td><td><?php echo $state;?></td></tr>
<tr><td>Zipcode :</td><td><?php echo $zipcode;?></td></tr>
<tr><td>Country :</td><td><?php echo $country;?></td></tr>
</table>
</body>
There is nothing in the HTTP headers to indicate which ISP a user is coming from, so the answer is no, there is no PHP builtin function which will tell you this. You'd have to use some sort of service or library which maps IPs to networks/ISPs.
Why not use ARIN's REST API.
<?php
// get IP Address
$ip=$_SERVER['REMOTE_ADDR'];
// create a new cURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, 'http://whois.arin.net/rest/ip/' . $ip);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
// execute
$returnValue = curl_exec($ch);
// close cURL resource, and free up system resources
curl_close($ch);
$result = json_decode($returnValue);
echo <<<END
<pre>
Handle: {$result->net->handle->{'$'}}
Ref: {$result->net->ref->{'$'}}
Name: {$result->net->name->{'$'}}
echo "OrgRef: {$result->net->orgRef->{'#name'}}";
</pre>
END;
// eof
https://www.arin.net/resources/whoisrws/whois_api.html
Sometimes fields change, so this is the improvement of the above post.
<body>
<table align="center">
<?
$ip=$_SERVER['REMOTE_ADDR'];
$url=file_get_contents("http://whatismyipaddress.com/ip/$ip");
preg_match_all('/<th>(.*?)<\/th><td>(.*?)<\/td>/s',$url,$output,PREG_SET_ORDER);
for ($q=0; $q < 25; $q++) {
if ($output[$q][1]) {
if (!stripos($output[$q][2],"Blacklist")) {
echo "<tr><td>".$output[$q][1]."</td><td>".$output[$q][2]."</td></tr>";
}
}
}
?>
</table>
</body>
You can obtain this information from ipinfo.io or similar services.
<?php
/**
* Get ip info from ipinfo.io
*
* There are other services like this, for example
* http://extreme-ip-lookup.com/json/106.192.146.13
* http://ip-api.com/json/113.14.168.85
*
* source: https://stackoverflow.com/a/54721918/3057377
*/
function getIpInfo($ip = '') {
$ipinfo = file_get_contents("https://ipinfo.io/" . $ip);
$ipinfo_json = json_decode($ipinfo, true);
return $ipinfo_json;
}
function displayIpInfo($ipinfo_json) {
var_dump($ipinfo_json);
echo <<<END
<pre>
ip : {$ipinfo_json['ip']}
city : {$ipinfo_json['city']}
region : {$ipinfo_json['region']}
country : {$ipinfo_json['country']}
loc : {$ipinfo_json['loc']}
postal : {$ipinfo_json['postal']}
org : {$ipinfo_json['org']}
</pre>
END;
}
function main() {
echo("<h1>Server IP information</h1>");
$ipinfo_json = getIpInfo();
displayIpInfo($ipinfo_json);
echo("<h1>Visitor IP information</h1>");
$visitor_ip = $_SERVER['REMOTE_ADDR'];
$ipinfo_json = getIpInfo($visitor_ip);
displayIpInfo($ipinfo_json);
}
main();
?>
GeoIP will help you with this: http://www.maxmind.com/app/locate_my_ip
There is a php library for accessing geoip data: http://www.maxmind.com/app/php
Attention though, you need to put the geoip db on your machine in order to make it work, all instructions are there :)
You can't rely on either the IP address or the host name to know the ISP someone is using.
In fact he may not use an ISP at all, or he might be logged in through a VPN connection to his place of employment, from there using another VPN or remote desktop to a hosting service halfway around the world, and connect to you from that.
The ip address you'd get would be the one from either that last remote machine or from some firewall that machine is sitting behind which might be somewhere else again.
I've attempted to correct Ram Kumar's answer but whenever I would edit their post I would be temporarily banned and my changes were ignored. (As to why, I don't know, It was my first and only edit that I've ever made on this website.)
Since his post, his code does not work anymore due to website changes and the Administrator implementing basic bot checks (checking the headers):
<?php
$IP = $_SERVER['REMOTE_ADDR'];
$User_Agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0';
$Accept = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$Accept_Language = 'en-US,en;q=0.5';
$Referer = 'http://whatismyipaddress.com/';
$Connection = 'keep-alive';
$HTML = file_get_contents("http://whatismyipaddress.com/ip/$IP", false, stream_context_create(array('http' => array('method' => 'GET', 'header' => "User-Agent: $User_Agent\r\nAccept: $Accept\r\nAccept-Language: $Accept_Language\r\nReferer: $Referer\r\nConnection: $Connection\r\n\r\n"))));
preg_match_all('/<th>(.*?)<\/th><td>(.*?)<\/td>/s', $HTML, $Matches, PREG_SET_ORDER);
$ISP = $Matches[3][2];
$City = $Matches[11][2];
$State = $Matches[10][2];
$ZIP = $Matches[15][2];
$Country = $Matches[9][2];
?>
<body>
<table align="center">
<tr><td>ISP :</td><td><?php echo $ISP;?></td></tr>
<tr><td>City :</td><td><?php echo $City;?></td></tr>
<tr><td>State :</td><td><?php echo $State;?></td></tr>
<tr><td>Zipcode :</td><td><?php echo $ZIP;?></td></tr>
<tr><td>Country :</td><td><?php echo $Country;?></td></tr>
</table>
</body>
Note that just supplying a user-agent would probably suffice and the additional headers are most likely not required, I just added them to make the request look more authentic.
If all these answers are not useful then you can try API way.
1.http://extreme-ip-lookup.com/json/[IP ADDRESS HERE]
EXAMPLE: http://extreme-ip-lookup.com/json/106.192.146.13
2.http://ip-api.com/json/[IP ADDRESS HERE]
EXAMPLE: http://ip-api.com/json/113.14.168.85
once it works for you don't forget to convert JSON into PHP.
I think you need to use some third party service (Possibly a web service) to lookup the IP and find the service provider.
go to http://whatismyip.com
this will give you your internet address. Plug that address into the database at http://arin.net/whois
<?php
$isp = geoip_isp_by_name('www.example.com');
if ($isp) {
echo 'This host IP is from ISP: ' . $isp;
}
?>
(PECL geoip >= 1.0.2)
geoip_isp_by_name — Get the Internet Service Provider (ISP) name
http://php.net/manual/ru/function.geoip-isp-by-name.php
A quick alternative. (This website allows up to 50 calls per minute.)
$json=file_get_contents("https://extreme-ip-lookup.com/json/$ip");
extract(json_decode($json,true));
echo "ISP: $isp ($city, $region, $country)<br>";
API details at the bottom of the page.
This is the proper way to find a isp from site or ip.
<?php
$isp = geoip_isp_by_name('www.example.com');
if ($isp) {
echo 'This host IP is from ISP: ' . $isp;
}
?>
Related
Introduction
I have written following PHP code to find location based on IP address. But this code works properly at client side and does not work on server. What may be the problem?
Code
echo $ip = $_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("http://ipinfo.io/{$ip}/json"));
echo "<br>".$details->country;
echo "<br>".$details->region;
echo "<br>".$details->city;
echo "<br>".$details->loc;
echo "<br>".$details->postal;
echo "<br>".$details->org;
Problem
This code only shows ip address (executed first line only) and not showing any other details of location.
Not seeing your error message, I'm going to go ahead and assume file_get_contents has been blocked.
CURL the url, much more reliable.
<?php
echo $ip = $_SERVER['REMOTE_ADDR'];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => "http://ipinfo.io/{$ip}/json"
));
$details = json_decode(curl_exec($curl));
curl_close($curl);
echo "<br>".$details->ip;
echo "<br>".$details->country;
echo "<br>".$details->region;
echo "<br>".$details->city;
echo "<br>".$details->loc;
echo "<br>".$details->postal;
echo "<br>".$details->org;
Your server's IP address can be found as follows:
echo $_SERVER['SERVER_ADDR'];
$_SERVER['REMOTE_ADDR']; gives you client or requesting browser/machine's IP address.
-- Please scroll down to where I marked the PHP --
To explain in better detail.
I made a Leaflet map and in that map I want to load my own location.
Here's my code for that in Javascript, but this is out of question like #Pocketsand and I already discussed. So then scroll down to the PHP code and see if you can get the IP address through the browser.
$part_content = "<div id=\"mapid\"></div>";
//.setView([".$longitude.", ".$latitude."], ".$zoom_factor.");
$part_content .= "<script>
var map = L.map('mapid').fitWorld();
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(map);
function onLocationFound(e) {
var radius = e.accuracy / 2;
L.marker(e.latlng).addTo(map)
.bindPopup(\"You are within \" + radius + \" meters from this point\").openPopup();
L.circle(e.latlng, radius).addTo(map);
}
function onLocationError(e) {
alert(e.message);
}
map.on('locationfound', onLocationFound);
map.on('locationerror', onLocationError);
map.locate({setView: true, maxZoom: 16});
</script>";
It's the same code as in this maps source code.
When I go to Firefox, it partly works and on someone else's computer it works fine, when on my computer I get the error from the image I showed you.
So I can't locate on my computer to my own location, as in google maps it works perfectly and my extensions also don't seem to block that part.
PHP:
Basically this:
$ip = !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
Gives me a random IP, because of HTTP_X_FORWARDED_FOR and REMOTE_ADDR gives me the correct IP, but not when I use this from a different IP address then the local one... thats why I check if the proxy is not empty.
This is the full php code for the tracker:
$ip = !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
$url = "http://freegeoip.net/json/$ip";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$data = curl_exec($ch);
curl_close($ch);
if ($data) {
$location = json_decode($data);
$longitude = $location->longitude;
$latitude = $location->latitude;
$longitude = str_replace(",", ".", $longitude);
$latitude = str_replace(",", ".", $latitude);
}
My current problem is:
$ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
Which gets the correct IP address, but it almost seems like it gets the IP hosts location. Which is not my intention, I intend to get the clients location through the IP address, which currently isn't working.
I tried and tried, but couldn't seem to figure this out and hope you guys know more about this.
Thanks in advance!
I am guessing you didn't visit the URL in the error message? It's a Chrome security thing, try running off a local webserver or getting a https certificate on your remote server.
The Chrome Security team and I propose that, for new and particularly
powerful web platform features, browser vendors tend to prefer to make
the the feature available only to secure origins by default.
[...]
Definitions:
“Secure origins” are origins that match at least one of the following
(scheme, host, port) patterns:
(https, *, *)
(wss, *, *)
(*, localhost, ) (, 127/8, *)
(*, ::1/128, *)
(file, *, —)
(chrome-extension, *, —)
This list may be incomplete, and may need to be changed.
Source: https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features
To get a client public ip address, in PHP 5.3 or greater use:
<?php
$ip = getenv('HTTP_CLIENT_IP')?:
getenv('HTTP_X_FORWARDED_FOR')?:
getenv('HTTP_X_FORWARDED')?:
getenv('HTTP_FORWARDED_FOR')?:
getenv('HTTP_FORWARDED')?:
getenv('REMOTE_ADDR');
?>
And if that is not working, use an external provider like https://geolocation-db.com
A JSON-P callback example:
<?php
$jsonp = file_get_contents('https://geolocation-db.com/jsonp');
$data = jsonp_decode($jsonp);
print $data->IPv4 . '<br>';
print $data->country_code . '<br>';
print $data->country_name . '<br>';
print $data->state . '<br>';
print $data->city . '<br>';
print $data->postal . '<br>';
print $data->latitude . '<br>';
print $data->longitude . '<br>';
// Strip callback function name and parenthesis
function jsonp_decode($jsonp) {
if($jsonp[0] !== '[' && $jsonp[0] !== '{') {
$jsonp = substr($jsonp, strpos($jsonp, '('));
}
return json_decode(trim($jsonp,'();'));
}
?>
And a JSON example:
<?php
$json = file_get_contents('https://geolocation-db.com/json');
$data = json_decode($json);
print $data->country_code . '<br>';
print $data->country_name . '<br>';
print $data->state . '<br>';
print $data->city . '<br>';
print $data->postal . '<br>';
print $data->latitude . '<br>';
print $data->longitude . '<br>';
print $data->IPv4 . '<br>';
?>
Instead of going with a PHP function I did a leaflet function instead, which tracks the user through the browser.
Using the library: leaflet.locate
Where then I could use the:
// create control and add to map
var lc = L.control.locate().addTo(map);
// request location update and set location
lc.start();
But this isn't the answer to the PHP part of my code, even though this leaflet function also works for now.
Sadly the PHP part can't find the exact address through the IP if the server is at another place, but the leaflet way of doing it through the browser does work. Hope you guys find use in these answers.
I have a simple script to check if a server is online or offline, however this script doesn't seem to work on the servers I want.
This is the script:
$value = mysql_result($result,$i,"servername");
$value2 = mysql_result($result,$i,"serveraddress");
$value3 = mysql_result($result,$i,"portnumber");
$value4 = mysql_result($result,$i,"description");
$id = mysql_result($result,$i,"id");
ob_start();
if (!$socket = #fsockopen($value2, $value3, $errno, $errstr, 1))
{
echo " <font color='red'><CENTRE><strong>OFFLINE</strong></CENTRE></font>";
}
else
{
echo " <font color='green'><CENTRE><strong>ONLINE</strong></CENTRE></font>";
fclose($socket);
}
$status = ob_get_contents();
ob_end_clean();
?>
The problem is if I say use a Google address and port 80 it will show Google's online, if I use an external IP address and a port like 7000 or so it won't show if the server is online, despite it being online. I'm not sure why this is, I'm thinking its possibly because no data is being sent through the port at the time showing it's closed.
Can someone shed some light on this please and maybe rectify the situation.
So in keeping with my last question, I'm working on scraping the friends feed from Twitter. I followed a tutorial to get this script written, pretty much step by step, so I'm not really sure what is wrong with it, and I'm not seeing any error messages. I've never really used cURL before save from the shell, and I'm extremely new to PHP so please bear with me.
<html>
<head>
<title>Twitcap</title>
</head>
<body>
<?php
function twitcap()
{
// Set your username and password
$user = 'osoleve';
$pass = '****';
// Set site in handler for cURL to download
$ch = curl_init("https://twitter.com/statuses/friends_timeline.xml");
// Set cURL's option
curl_setopt($ch,CURLOPT_HEADER,1); // We want to see the header
curl_setopt($ch,CURLOPT_TIMEOUT,30); // Set timeout to 30s
curl_setopt($ch,CURLOPT_USERPWD,$user.':'.$pass); // Set uname/pass
curl_setopt($ch,CURLOPT_RETURNTRANSER,1); // Do not send to screen
// For debugging purposes, comment when finished
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
// Execute the cURL command
$result = curl_exec($ch);
// Remove the header
// We only want everything after <?
$data = strstr($result, '<?');
// Return the data
$xml = new SimpleXMLElement($data);
return $xml;
}
$xml = twitcap();
echo $xml->status[0]->text;
?>
</body>
</html>
Wouldn't you actually need everything after "?>" ?
$data = strstr($result,'?>');
Also, are you using a free web host? I once had an issue where my hosting provider blocked access to Twitter due to people spamming it.
note that if you use strstr the returend string will actually include the needle-string. so you have to strip of the first 2 chars from the string
i would rather recommend a combination of the function substr and strpos!
anways, i think simplexml should be able to handle this header meaning i think this step is not necessary!
furthermore if i open the url i don't see the like header! and if strstr doesnt find the string it returns false, so you dont have any data in your current script
instead of $data = strstr($result, '<?'); try this:
if(strpos('?>',$data) !== false) {
$data = strstr($result, '?>');
} else {
$data = $result;
}
I'm going to block all bots except the big search engines. One of my blocking methods will be to check for "language": Accept-Language: If it has no Accept-Language the bot's IP address will be blocked until 2037. Googlebot does not have Accept-Language, I want to verify it with DNS lookup
<?php
gethostbyaddr($_SERVER['REMOTE_ADDR']);
?>
Is it ok to use gethostbyaddr, can someone pass my "gethostbyaddr protection"?
function detectSearchBot($ip, $agent, &$hostname)
{
$hostname = $ip;
// check HTTP_USER_AGENT what not to touch gethostbyaddr in vain
if (preg_match('/(?:google|yandex)bot/iu', $agent)) {
// success - return host, fail - return ip or false
$hostname = gethostbyaddr($ip);
// https://support.google.com/webmasters/answer/80553
if ($hostname !== false && $hostname != $ip) {
// detect google and yandex search bots
if (preg_match('/\.((?:google(?:bot)?|yandex)\.(?:com|ru))$/iu', $hostname)) {
// success - return ip, fail - return hostname
$ip = gethostbyname($hostname);
if ($ip != $hostname) {
return true;
}
}
}
}
return false;
}
In my project, I use this function to identify Google and Yandex search bots.
The result of the detectSearchBot function is caching.
The algorithm is based on Google’s recommendation - https://support.google.com/webmasters/answer/80553
In addition to Cristian's answer:
function is_valid_google_ip($ip) {
$hostname = gethostbyaddr($ip); //"crawl-66-249-66-1.googlebot.com"
return preg_match('/\.googlebot|google\.com$/i', $hostname);
}
function is_valid_google_request($ip=null,$agent=null){
if(is_null($ip)){
$ip=$_SERVER['REMOTE_ADDR'];
}
if(is_null($agent)){
$agent=$_SERVER['HTTP_USER_AGENT'];
}
$is_valid_request=false;
if (strpos($agent, 'Google')!==false && is_valid_google_ip($ip)){
$is_valid_request=true;
}
return $is_valid_request;
}
Note
Sometimes when using $_SERVER['HTTP_X_FORWARDED_FOR'] OR $_SERVER['REMOTE_ADDR'] more than 1 IP address is returned, for example '155.240.132.261, 196.250.25.120'. When this string is passed as an argument for gethostbyaddr() PHP gives the following error:
Warning: Address is not a valid IPv4 or IPv6 address in...
To work around this I use the following code to extract the first IP address from the string and discard the rest. (If you wish to use the other IPs they will be in the other elements of the $ips array).
if (strstr($remoteIP, ', ')) {
$ips = explode(', ', $remoteIP);
$remoteIP = $ips[0];
}
https://www.php.net/manual/en/function.gethostbyaddr.php
The recommended way by Google is to do a reverse dns lookup (gethostbyaddr) in order to get the associated host name AND then resolve that name to an IP (gethostbyname) and compare it to the remote_addr (because reverse lookups can be faked, too).
But beware, end lokups take time and can severely slow down your webpage (maybe check for user agent first).
Google also publishes a machine readable file containing the IP addresses of their crawlers, see the link below.
See:
https://developers.google.com/search/docs/advanced/crawling/verifying-googlebot
https://webmasters.googleblog.com/2006/09/how-to-verify-googlebot.html
//The function
function is_google() {
return strpos($_SERVER['HTTP_USER_AGENT'],"Googlebot");
}
How to verify Googlebot.
If you have a site that has thousands of pages then going for reverse DNS will be costly, So I think the best method is to hard code ips list. (Php code example)
function googleBotIPsList(){
return "ips"; //hard coded IPs here.
}
Also you can make another function which gets the latest ips. Now upto you how frequently you call this function.
function getLatestGoogleBotIPsList(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,"https://developers.google.com/static/search/apis/ipranges/googlebot.json");
$result=curl_exec($ch);
curl_close($ch);
$result = (json_decode($result, true));
$ips='';
for($i=0;$i<count($result['prefixes']);$i++) {
$ips .= ($result['prefixes'][$i]['ipv6Prefix'] ? $result['prefixes'][$i]['ipv6Prefix'] : $result['prefixes'][$i]['ipv4Prefix']).',';
}
return rtrim($ips,',');
}
Then use strpos to check from the hardcoded list
if(strpos(googleBotIPsList(),zen_get_ip_address()) !==false){
// Insert into your table etc.
}