The following java code will convert an IP Address to its host.
InetAddress addr = InetAddress.getByName("31.13.78.13");
String host = addr.getHostName();
System.out.println(host);
Here host will be printed as "edge-star-shv-01-sit4.facebook.com". The first portion may be the address of a data center of facebook. I only want the "facebook.com" portion. I could not find any built in method in InetAddress library that can sort this out. I can solve the problem using substring method but this is not a good way because I want a generalized approach. Is there any way where I can get "facebook.com" instead of "edge-star-shv-01-sit4.facebook.com" by taking "31.13.78.13" as input?
You can't!
I run multiple websites on one IP adress. So if you would use a script as you discribe it here, what should it return?
The only thing is to get the hostname of the server with the selected IP, this can contain the website name , as in your case, but it doesn't have to. Imagine a server with hostname "example.com" and IP 1.1.1.1, or whatever, on this machine a website in running with url "stackoverflow.com" then you expect when tracing the IP adress to get "stackoverflow.com" but in fact you would get "example.com"
Related
I found code to fetch host name from IP address. The code is some what like shown below:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class GetHostName{
public static void main(String a[]){
try{
InetAddress host = InetAddress.getByName("74.125.68.94");
System.out.println(host.getHostName());
}
catch(UnknownHostException ex){
ex.printStackTrace();
}
}
}
It shows output like:
sc-in-f94.1e100.net
But when i fired this IP address (74.125.68.94) through the browser it opens up Google website.
So my question is how can i fecth URL like http://www.google.com from an IP address rather than displaying sc-in-f94.1e100.net using java?
You can't do that.
Usually, several domains can be reach on same IP. You can just identify the hostname like you already do. This is the name of the machine, equivalent to the IP, which serves the domain.
Moreover, an IP is just an address of a machine which also can serve any domain because it can be a web server or not.
You are actually doing everything right. The thing is that today many host names can live on the same server. This way you can easily convert the host name to the IP address of the server but when you attempt to do the reverse, you only get the name of the server which is in this case sc-in-f94.1e100.net.
Here is an excerpt from hcidata:
In the early years of the Internet, each sub-domain would have a unique IP address so it was common for a host machine to have only one sub domain name. Nowadays, the common practice is to have many sub-domains with the same IP address. It is also common for the domain name to be converted to the IP address of the host machine that runs the www sub domain.
I hope this will clear things up for you.
I looked for how to do IP lookup in Java on Stack Overflow but the answers match what I am already doing and do not resolve my problem.
Here is my code:
public void printHostname( String ip ) {
System.out.println( InetAddresses.forString( ip ).getCanonicalHostName( ) );
}
InetAddresses is just a utility class from guava library to get a InetAdress.
The problem: This code works as expected with some IP adresses and not with some others.
A working example
For example, for IP 157.55.39.29, the output is:
msnbot-157-55-39-29.search.msn.com
This result seems correct according to Linux host command:
> host 157.55.39.29
29.39.55.157.in-addr.arpa domain name pointer msnbot-157-55-39-29.search.msn.com.
A not working example
For IP 123.125.71.75, the host command returns:
> host 123.125.71.75
75.71.125.123.in-addr.arpa domain name pointer baiduspider-123-125-71-75.crawl.baidu.com.
But the output of my Java code is:
123.125.71.75
whereas the expected output should be
baiduspider-123-125-71-75.crawl.baidu.com
The javadoc of getCanonicalHostName method says:
Returns:
the fully qualified domain name for this IP address, or if the operation is not allowed by the security check, the textual representation of the IP address.
but I’m pretty sure it's not really a problem with a security check... or I don't understand what is wrong.
Have you any suggestion to explain this behaviour? Do you have a workaround?
EDIT #1
When looking for a solution, I tried to step debug the implementation in JDK:
// first lookup the hostname
host = nameService.getHostByAddr(addr.getAddress());
/* check to see if calling code is allowed to know
* the hostname for this IP address, ie, connect to the host
*/
if (check) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkConnect(host, -1);
}
}
/* now get all the IP addresses for this hostname,
* and make sure one of them matches the original IP
* address. We do this to try and prevent spoofing.
*/
InetAddress[] arr = InetAddress.getAllByName0(host, check);
In this code, variable host contains the correct value, but the last statement calling getAllByName0 throws an UnknownHostException which is handled by returning just the requested IP. The exception is thrown by internal method getAddressesFromNameServicewith message:
"java.net.UnknownHostException: baiduspider-123-125-71-75.crawl.baidu.com"
I don't know why.
Can I get the host variable value, bypassing the internal exception?
The problem lies in the fact that the java.net.InetAdress has a certain procedure against ip-spoofing.
It first resolves the name into (an) ip address(es). This works fine.
In your case the result are two IP adresses. InetAdress then checks back if (at least one of) these adresses resolve to the original input name.
If they do not, it just returns the original ip adress. The following picture shows the situation after the check for baiduspider-123-125-71-75.crawl.baidu.com
Note: The ip adresses resolved by getAllByName0 are the same as via nslookup, namely:
nslookup baiduspider-123-125-71-75.crawl.baidu.com
Server: 192.168.2.1
Address: 192.168.2.1#53
Non-authoritative answer:
Name: baiduspider-123-125-71-75.crawl.baidu.com
Address: 62.157.140.133
Name: baiduspider-123-125-71-75.crawl.baidu.com
Address: 80.156.86.78
A solution would be to use the dnsjava library. It skips the spoofing check and therefore works fine.
dnsjava example:
String addr = Address.getHostName(InetAddress.getByName("123.125.71.75"));
outputs just as expected baiduspider-123-125-71-75.crawl.baidu.com
Disclaimer: As i am a Java developer and not a security expert, i am not totally aware of the security implications of using a spoofed ip address.
I did not dig a lot into this so I don't know why it is happening, but some online tools (like this one) that checks the health of DNS servers indicates that they have some issues which may or may not be related.
As #jah said, Java tries to double check to see if the hostname has the ip it said it has. The exception is thrown on the native code while trying to do that. In fact, in my case, trying to verify on the command line, the nslookup fails to get the ip from the name, which indicates some configuration preventing this on the DNS Server (maybe on purpose? I'm no expert in DNS either).
When it works:
$ nslookup msnbot-157-55-39-29.search.msn.com
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
Name: msnbot-157-55-39-29.search.msn.com
Address: 157.55.39.29
When it doesnt work:
$ nslookup baiduspider-123-125-71-75.crawl.baidu.com
Server: 192.168.1.1
Address: 192.168.1.1#53
** server can't find baiduspider-123-125-71-75.crawl.baidu.com: NXDOMAIN
When it works:
$ getent hosts msnbot-157-55-39-29.search.msn.com
157.55.39.29 msnbot-157-55-39-29.search.msn.com
When it doesn't:
$ getent hosts baiduspider-123-125-71-75.crawl.baidu.com
$
As an alternative, you can use a DNS Service Provider for JNDI. The documentation has an example, but I'll leave a working snippet for you to test:
String[] octets = "123.125.71.75".split("\\.");
String host = String.join(".", octets[3], octets[2], octets[1], octets[0], "in-addr.arpa");
Properties props = new Properties();
props.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
DirContext dirContext = new InitialDirContext(props);
Attributes attrs = dirContext.getAttributes(host, new String[] {"PTR"});
System.out.println(attrs.get("PTR").get());
I'm trying to get the device's name using its local IP address on the network. Is this how I'm supposed to do it? ex) Arnold-PC, andoid-nnnnnnnnnn
String name = InetAddress.getByName(ip).getHostName();
System.out.println(name);
The above should give me the host's name... but instead gives me the local IP address. - 192.168.2.101
as per the documentation...
public String getHostName ()
Returns the host name corresponding to this IP address. This may or
may not be a fully-qualified name. If the IP address could not be
resolved, the numeric representation is returned instead
Why is it not able to find the host's name?
I don't know much about computer networking... so please excuse my ignorance. :P
check in the command prompt whether you can able to resolve the ip address using nsloookup
if you can't, then your DNS broken
I would like to quote the few lines from java documentation here
getCanonicalHostName() Gets the fully qualified domain name for this
IP address. Best effort method, meaning we may not be able to return
the FQDN depending on the underlying system configuration.
one more trick is to edit host file to get output (not recommended)
Have a look in this answer too
link
From the docs
If this InetAddress was created with a host name, this host name will be remembered and returned; otherwise, a reverse name lookup will be performed and the result will be returned based on the system configured name lookup service. If a lookup of the name service is required, call getCanonicalHostName.
It seems like plain getHostName() won't look up the name if it can't reach out to a DNS server. The DNS server is what will give a name to the host IP address, just like a phone book. Give getCanonicalHostName() a try.
I have two computers plugged in the same router of a network which I know supports IPv6. Let's call them "PC-A" and "PC-B
I want "PC-A" to figure out "PC-B"s IPv6 address and vice-versa
The first thing I do is
setSystem.setProperty("java.net.preferIPv6Addresses", "true");
If I then say
InetAddress IPAddress = InetAddress.getLocalHost();
I can get my own address which will be in IpV6 format
However, neither of the following two statements gives me "PC-B"s IPv6 address:
Inet6Address IPAddress6 = (Inet6Address)InetAddress.getByName("PC-B");
InetAddress IPAddress = InetAddress.getByName("PC-B");
I also tried to import
import com.lavantech.net.dns.SimpleDNSLookup;
import com.lavantech.net.dns.DNSLookup
The first one I am using as:
SimpleDNSLookup d = new SimpleDNSLookup();
System.out.println(d.getInet6Address("PC-B"));
and the second one as:
DNSLookup dnsLookup = new DNSLookup("PC-B", DNSLookup.QTYPE_AAAA, DNSLookup.QCLASS_IN, 3000, null);
// Get all Address Records.
ResourceRecord[] ansRecords = dnsLookup.getAAAARecords();
System.out.println(ansRecords[0]);
none of which works.
I also tried to use the following
import org.xbill.DNS.*;
int type = Type.AAAA;
Name name = Name.fromString("PC-B");
Lookup lookup = new Lookup(name, type);
lookup.run();
int result = lookup.getResult();
Record[] answers = lookup.getAnswers();
System.out.println(answers[0]);
// (where, for brevity, i am skipping the parts where I check whether result == Lookup.SUCCESSFUL
Note that if I substitute "PC-B" for, say, "ipv6.google.com" I get all the desired results!
Also note that if I just use InetAddress and Type_A wherever applicable in the above approaches, my program returns "PC-B"s IPv4 address without problem.
What am I missing?
Any help is greatly appreciated!
Your question is -unfortunately- a yet unsolved network problem dealing with host discovery on a local subnet (regardless if that subnet has a router or not).
Your desired output is clearly an IPv6 address, but it is unclear what exactly your input is.
Let's focus on PC-B. How exactly do you identify PC-B? It clear that you call it "PC-B", but that name should be configured somewhere before your PC know that that's its name. Where exactly is that configured? Is that the hostname you set on PC-B itself, or is there a domain name server (DNS) where you have given that name? If it is the name in the DNS system, you can indeed query the DNS system for the AAAA record to get the IPv6 address, but you need the fully qualified domain name (FQDN). E.g. "PC-B.yourdomain.com" rather than just "PC-B".
If you know the MAC address of PC-B, you can use the neighbour discovery protocol (NDP) to find out the IP address of PC-B.
There are network protocols that allow PC-A and PC-B to announce their names themselves, once you configured them on the local machines. Such protocols are called "service discovery" protocols, and your options here are (1) multicast DNS (mDNS) and possibly DNS service discovery (DNS-SD) on top of that; or (2) Simple Service Discovery Protocol (SSDP) in UPnP on the other hand. The advantage is that some operating systems already implement this. E.g. if PC-B is a Mac OS X host, all you need to do is query DNS for "pc-b.local" to get the answer. Unfortunately, while implementations of mDNS exist for Linux (Avahi) and Windows (Bonjour), they're not installed by default. A third alternative is to write your own host discovery protocol, and have your hosts run that protocol.
Considerations are which platforms you want to support, if installing third-party software is an option, if the discovery needs to be secure (the above options are not, look into Secure Neighbour Discovery -SEND- if this is a concern), and what input you have in the first place (the hostname "PC-B", or the type of service that runs on PC-B, e.g. _http._tcp for a webserver).
I set up a static IP and did port forwarding on my notebook, and now I have a static IP address, but it's relatively static, every time I re-start the machine, I get another address, and since I have a "static" IP I can now do Paypal IPN messaging. But how can I get this static IP from my Java program ? One way I can think of is to visit : http://portforward.com/ and on that page it tells me what my external IP is, so I can extract it with Java code, is there any other way that I can do in my Java code to get this info ?
The best solution is probably dynamic DNS. Essentially, you run a program on your computer (or router) that notifies a DNS server when your IP changes. Then, you can just tell PayPal the domain name.
There is a public service you can call with your script to retrieve your external IP address. Bear in mind they have changed the link location once. If you control your own server, you should probably write your own PHP script to simply return the address of the caller to the script.
http://www.whatismyip.com/faq/automation.asp - follow the developers link they provide
import java.net.*;
import java.io.*;
URL myExternalIP = new URL("PUT THE LINK HERE");
BufferedReader in = new BufferedReader(new InputStreamReader(
myExternalIP.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
Your own server script is a simple one-liner. Create a file called whatismyip.php and here's the content.
<? echo $_SERVER['REMOTE_ADDR']?>
I see three ways of doing this:
As you discovered, querying an external server what IP you're apparently connecting from. This is simple but you require such a service to be available and, usually, that no transparent proxy messes with your results.
IGD, a sub-protocol of UPnP can give you the result very easily if your port forwarding devices supports it (many do). Google "IGD JAVA" for libraries and samples.
Register for a dynamic DNS service and then lookup your own DNS name.
You can use the NetworkInterface class:
Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces();
while(ifcs.hasMoreElements()){
NetworkInterface ifc = ifcs.nextElement();
System.out.println("Adresses of: "+ifc.getDisplayName());
Enumeration<InetAddress> adresses = ifc.getInetAddresses();
while(adresses.hasMoreElements()){
System.out.println(adresses.nextElement().getHostAddress());
}
}
This snippet will show you all of the interfaces and the IPs bound to them. You will need to look through the list to find the appropriate interface (see also NetworkInterface.getByName(String name)) And then look at the addresses for that interface. Once you have found the appropriate InetAdress you can use that to get the string or byte representation.