InetAddress.getCanonicalHostName()返回IP而不是主机名 [英] InetAddress.getCanonicalHostName() returns IP instead of Hostname

查看:1490
本文介绍了InetAddress.getCanonicalHostName()返回IP而不是主机名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在堆栈溢出中寻找如何在Java中进行IP查找,但答案与我已经在做的事情相匹配,并且无法解决我的问题。



这是我的代码:

  public void printHostname(String ip){
System.out.println(InetAddresses.forString(ip) .getCanonicalHostName());
}

InetAddresses 只是一个来自番石榴库的实用程序类,以获取一个 InetAdress



问题:该代码按照预期的一些IP



一个工作示例



例如,对于IP 157.55.39.29,输出是:

  msnbot-157-55-39-29.search.msn.com 

根据Linux c> host 命令,这个结果似乎是正确的:

 >主机157.55.39.29 
29.39.55.157.in-addr.arpa域名指针msnbot-157-55-39-29.search.msn.com。



不工作的例子



对于IP 123.125.71.75,主机命令返回:

 >主机123.125.71.75 
75.71.125.123.in-addr.arpa域名指针baiduspider-123-125-71-75.crawl.baidu.com。

但我的Java代码的输出是:

  123.125.71.75 

而预期输出应为

  baiduspider-123-125-71-75.crawl.baidu.com 



注意:通过 getAllByName0 解析的ip地址与通过 nslookup 相同,即:

  nslookup baiduspider-123-125-71-75.crawl.baidu.com 
服务器:192.168.2.1
地址:192.168.2.1# 53

非授权答案:
名称:baiduspider-123-125-71-75.crawl.baidu.com
地址:62.157.140.133
名称: baiduspider-123-125-71-75.crawl.baidu.com
地址:80.156.86.78

解决方案将使用 dnsjava 库。



dnsjava示例:



String addr = Address.getHostName(InetAddress.getByName(123.125.71.75));
正如预期的那样输出 baiduspider-123- 125-71-75.crawl.baidu.com



免责声明:由于我是Java开发人员,不是一个安全专家,我并不完全了解使用欺骗性IP地址的安全隐患。


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.

这篇关于InetAddress.getCanonicalHostName()返回IP而不是主机名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆