简体   繁体   English

java:使Apache HttpClient连接到具有特定IP的主机

[英]java: make Apache HttpClient connect to host with specific IP

Some domain names are resolved to several IPs by DNS. DNS将某些域名解析为多个IP。 I need to make http requests to all those IPs (a kind of service healthcheck). 我需要对所有这些IP发出http请求(一种服务运行状况检查)。 I can use 我可以用

InetAddress[] addrs = InetAddress.getAllByName("google.com")

to resolve all IPs which should be checked. 解决所有应检查的IP。 It is not about google, but it is with testing on google that I've found puzzles 这与Google无关,但与在Google上进行的测试有关,我发现了难题

I'm trying to use Apache HttpClient to make request. 我正在尝试使用Apache HttpClient发出请求。 Like this: 像这样:

HttpHead req = new HttpHead(url);
//InetAddress addr = InetAddress.getByAddress("google.com", new byte[] {74, 125, (byte) 131, 101});
InetAddress addr = // one of those we got from InetAddress.getAll...
CloseableHttpResponse resp = cli.execute(new HttpHost(addr, 443, "https"), req);

It seems to work, however I decided to check it constructing the IP manually - see the commented string. 看来可行,但是我决定检查一下它是否手动构建IP-参见注释字符串。 If it is uncommented and used instead of the addr from the dns enumeration, all works fine, returning 200. 如果取消注释并使用它代替dns枚举中的addr ,则一切正常,返回200。

But if I then change IP address to 8, 8, 8, 8 in this line and expect to get connection timeout (as it is address of google's dns which don't listen on 443 port, it is firewalled) - I see 404 instead. 但是,如果我随后在此行中将IP地址更改为8, 8, 8, 8并希望获得连接超时(因为它是不监听443端口的Google dns的地址,则它已被防火墙保护)-我看到的是404 。 Thus I am not sure it uses the specified IP for real connection rather than for verification. 因此,我不确定它是否将指定的IP用于实际连接而不是用于验证。

This makes me think that the approach is wrong and I use this HttpHost incorrectly. 这使我认为该方法是错误的,并且我错误地使用了此HttpHost。

Alternative approach is to use custom DnsResolver set up for given HttpClient , which will feed only specific IPs, and do it in turns. 另一种方法是使用为给定HttpClient设置的自定义DnsResolver ,它将仅提供特定的IP,并DnsResolver执行。 however this looks like ugly and inconvenient hack so I'm searching for "proper" way... 但是,这看起来很丑陋且不方便,所以我正在寻找“正确”的方式...

PS variant with sending requests in plain text to sockets (without any library) will work fine, but most probably solution will need to work with https also which makes this variant difficult. 将纯文本请求发送到套接字(没有任何库)的PS变体可以很好地工作,但很可能解决方案将需要与https一起使用,这也使得此变体很困难。

Your approach to hit a specific IP is correct and works: 您达到特定IP的方法正确且可行:

try {
    HttpClient hc = HttpClientBuilder.create().build();
    HttpGet req = new HttpGet("https://www.google.com");
    HttpResponse res = hc.execute(new HttpHost("8.8.8.8", 443, "https"), req);
    System.out.println(res.getStatusLine());
} catch (Exception e) {
    System.out.println(e.getMessage());
}

Prints: 打印:

Certificate for <8.8.8.8> doesn't match any of the subject alternative names: [*.c.docs.google.com, .....

Apparently the Google's Public DNS server 8.8.8.8 in addition to DNS also listens on port 443: 显然,除DNS之外, Google的Public DNS服务器8.8.8.8还在端口443上进行侦听:

$ openssl s_client -showcerts -connect 8.8.8.8:443 | more
CONNECTED(0000012C)
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.c.docs.google.com
   i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3

Now I can't speak intelligently about the content it is serving, but I can conclude that 8.8.8.8 isn't meant to handle https://www.google.com traffic since neither *.c.docs.google.com nor any of the subject alternative names match www.google.com . 现在,我不能明智地谈论其正在提供的内容,但是我可以得出结论,因为*.c.docs.google.com*.c.docs.google.com都不是,所以8.8.8.8并不是要处理https://www.google.com流量。任何主题备用名称都与www.google.com匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM