import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
public class DNSLookup
{
public static void main(String args[])
{
String host = "www.google.com";
try
{
InetAddress inetAddress = InetAddress.getByName(host);
// show the Internet Address as name/address
System.out.println(inetAddress.getHostName() + " " + inetAddress.getHostAddress());
// get the default initial Directory Context
InitialDirContext iDirC = new InitialDirContext();
// get the DNS records for inetAddress
Attributes attributes = iDirC.getAttributes("dns://8.8.8.8/www.google.com", new String[] {"A"});
// get an enumeration of the attributes and print them out
NamingEnumeration<?> attributeEnumeration = attributes.getAll();
System.out.println("");
while (attributeEnumeration.hasMore())
{
System.out.println("" + attributeEnumeration.next());
}
attributeEnumeration.close();
}
catch (UnknownHostException exception)
{
System.err.println("ERROR: Cannot access '" + host + "'");
}
catch (NamingException exception)
{
System.err.println("ERROR: No DNS record for '" + host + "'");
exception.printStackTrace();
}
}
}
If I run this code, I get error like below...
www.google.com 74.125.128.103
ERROR: No DNS record for 'www.google.com'
javax.naming.CommunicationException: DNS error [Root exception is java.net.SocketTimeoutException: Receive timed out]; remaining name 'www.google.com'
at com.sun.jndi.dns.DnsClient.query(DnsClient.java:300)
at com.sun.jndi.dns.Resolver.query(Resolver.java:81)
at com.sun.jndi.dns.DnsContext.c_getAttributes(DnsContext.java:430)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:231)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:139)
at com.sun.jndi.toolkit.url.GenericURLDirContext.getAttributes(GenericURLDirContext.java:103)
at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:142)
at DNSLookup.main(DNSLookup.java:24)
Caused by: java.net.SocketTimeoutException: Receive timed out
at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.receive0(DualStackPlainDatagramSocketImpl.java:121)
at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:145)
at java.net.DatagramSocket.receive(DatagramSocket.java:786)
at com.sun.jndi.dns.DnsClient.doUdpQuery(DnsClient.java:411)
at com.sun.jndi.dns.DnsClient.query(DnsClient.java:203)
... 7 more
But if I use "dns:/www.google.com" as query, not "dns://8.8.8.8/www.google.com", it works perfectly without any error.
Error only happens when I try to specify DNS server to use.
"dns://8.8.8.8/www.google.com" -> ERROR
"dns:/www.google.com" -> Work!
http://docs.oracle.com/javase/7/docs/technotes/guides/jndi/jndi-dns.html
In this document, there is exact same usase what I want to use. I cannot understand why this makes problem.
DirContext ictx = new InitialDirContext();
Attributes attrs3 = ictx.getAttributes("dns://server1.example.com/host3.example.com",
new String[] {"MX"});
There is nothing wrong with your code, but I suspect that you're running it from behind a proxy or firewall that blocks outgoing DNS.
When you ask for dns:/www.google.com you're essentially asking your local DHCP-supplied resolver for the IP of www.google.com - just as when typing the address in the browser address line.
However, when using dns://8.8.8.8/www.google.com you're asking to use Google DNS to resolve google.com which requires that your proxy/firewall allows outgoing TCP/UDP port 53 traffic, which is usually not the case in corporate environments...
Cheers,
Related
The intention is to stream the log during runtime on a specific host:port, so that the logs are accessible to users outside the running system, from browser.
As you can see, i have created a simple SocketHandler for java8 logging(java.util.logging), is there something that i have missed?
import java.net.MalformedURLException;
import java.net.URL;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SocketHandler;
import java.util.logging.XMLFormatter;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = Logger.getLogger("concrete.log");
SocketHandler handler = new SocketHandler("HOSTNAME", 19004);
LogRecord logRec = new LogRecord(Level.INFO, "Log recorded");
handler.publish(logRec);
handler.setFormatter(new XMLFormatter());
logger.addHandler(handler);
logger.info("socket handler info message");
}
}
When i run the code, i see the following exception, i have tried checking the system firewall settings on both local(mac/windows) and remote(Linux) and seen that the settings do not block 19004 port
Exception in thread "main" java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
at java.net.Socket.connect(Socket.java:606)
at java.net.Socket.connect(Socket.java:555)
at java.net.Socket.<init>(Socket.java:451)
at java.net.Socket.<init>(Socket.java:228)
at java.util.logging.SocketHandler.connect(SocketHandler.java:167)
at java.util.logging.SocketHandler.<init>(SocketHandler.java:154)
at Main.main(Main.java:16)
UPDATE
As suggested by bosowski
When i create Socket to listen to a specific port, the log messages are getting printed on the console of the host. However, am unable to access hostname:port for the log to be streamed from the browser. Is there anything specific that needs to be performed after this step?
Please let me know
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args)
{
try {
ServerSocket ss = new ServerSocket(19004);
Socket soc = ss.accept();
DataInputStream dis
= new DataInputStream(soc.getInputStream());
String str = (String)dis.readUTF();
System.out.println("message= " + str);
ss.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
SocketHandler does not open up a port to connect to, if that's what you're assuming. It tries to connect to the specified host and port, so you need to have a port that is listening on the host that you are trying to connect to.
https://docs.oracle.com/javase/8/docs/api/java/util/logging/SocketHandler.html#SocketHandler-java.lang.String-int-
<handler-name>.host specifies the target host name to connect to (no default).
<handler-name>.port specifies the target TCP port to use (no default).
If you do indeed have a listening TCP port on the hostname that you're trying to connect to, you can try running sudo nmap -F hostname to check if the port is indeed accessible from your machine.
I have a java program, that connects to a website to retrieve some XML from it. This works fine on my computer, as well as others outside our company. One of our customers is now not able to connect to the website. I figured out, that they are behind a proxy. I have now found which settings I need to use, and in my test program it works (partially).
In the code below, the downloadFile() call works as expected, and the file can be downloaded without problems. The contactHost() fails on our client machines with an UnknownHostException:
java.net.UnknownHostException: No such host is known (api.myserver.de)
at java.base/java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method)
at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:925)
at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1505)
at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:844)
at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1495)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1354)
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1288)
at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:45)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:111)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
Background: Windows 10 machines, our program is shipped with an internal OpenJDK, version "10.0.2" 2018-07-17. The program is started with the following defines -Djdk.http.auth.tunneling.disabledSchemes="" -Djava.net.preferIPv4Stack=true in order to use IP4 only, and to enable BasicAuthentification for the Proxy. With these settings, the file can be downloaded, however the UnknownHostException is still there.
We have also tried to open the used URL in an browser, and this works as excepted, i.e. in the browser the website is opened.
Here is my code for testing:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.URL;
import java.net.URLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
public class LFTProxyTest {
private static String uname = null;
private static String pass = null;
public static void main(String[] args) {
System.setProperty("java.net.useSystemProxies", "true");
// uname = "test"; // whatever that user provides
// pass = "sectret"; // whatever that user provides
Authenticator.setDefault(new ProxyAuth(uname, pass));
contactHost();
downloadFile();
}
private static boolean downloadFile() {
System.out.println("CHECK connection");
int cp = contactHost();
if (cp == 200)
return true;
if (cp == 407)
return false;
else {
try {
System.out.println("Try loading file: ");
URL url = new URL("https://www.google.de");
URLConnection urlConnection = url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
dBuilder.parse(in);
System.out.println(" FILE DOWNLOAD successfull!");
} catch (Exception e) {
System.out.println(" FILE DOWNLOAD failed:");
System.out.println("***EXCEPTION: " + e.getMessage());
return false;
}
}
System.out.println("CHECK done");
return true;
}
private static int contactHost() {
HttpClient client = HttpClientBuilder.create().build();// new DefaultHttpClient();
String catalogURI = "https://api.myserver.de/query";
HttpGet request = new HttpGet(catalogURI);
try {
int ret = 0;
HttpResponse response = client.execute(request);
ret = response.getStatusLine().getStatusCode();
System.out.println("PROXY test: " + ret);
((CloseableHttpClient) client).close();
return ret;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
}
I don't know what do do know, I'm not even sure where the error could be. Any ideas are highly appreciated!
Ok, so after some further digging, I found out that org.apache.http.client.HttpClient is not respecting java.net.useSystemProxies at all, be it set via System or via -D. And it is also ignoring http.proxyHost etc. Solution is to use a ProxySelector like this:
ProxySelector.setDefault(new ProxySelector() {
#Override
public List<Proxy> select(URI uri) {
ArrayList<Proxy> list = new ArrayList<Proxy>();
list.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy1.de", 8000)));
list.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy2.de", 8080)));
return list;
}
#Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
logger.error("Error in ProxySelector, connection Failed: ", ioe);
}
});
I'm getting another exception now, but I might open another thread for this.
UnknownHostException designates a pretty straight forward problem. That the IP address of the remote host you are trying to reach cannot be resolved. So the solution to this is very simple. You should check the input of Socket (or any other method that throws an UnknownHostException), and validate that it is the intended one. If you are not whether you have the correct host name, you can launch a UNIX terminal and use the nslookup command (among others) to see if your DNS server can resolve the host name to an IP address successfully.
If you are on Windows you can use the host command. If that doesn’t work as expected then, you should check if the host name you have is correct and then try to refresh your DNS cache. If that doesn’t work either, try to use a different DNS server, eg Google Public DNS is a very good alternative.
I have written following code for the client of RMI. But getting
java.rmi.ConnectException: Connection refused to host: localhost; nested
exception is:
java.net.ConnectException: Connection refused: connect
code :
import java.rmi.*;
import java.net.*;
import java.rmi.registry.*;
class client
{
public static void main(String [] ars)
{
Iface serv;
Registry r;
String serveraddr = ars[0];
String serverport = ars[1];
String text = "Hey jude";
System.out.println("Sending" + text);
try{
r = LocateRegistry.getRegistry(
serveraddr,
(new Integer(serverport)).intValue()
);
serv = (Iface) r.lookup("rmi://server");
serv.receive(text);
}
catch(Exception e){
System.out.println(e);
}
}
}
If you're getting that on bind, rebind, or lookup, the Registry isn't running. If you get it doing the remote call, see item A.1 in the RMI FAQ supplied with the Javadoc, and if you're running Linux also check that your /etc/hosts file maps 127.0.0.1 to localhost and your real ip address to your real hostname - this has been a common problem in some Linux distributions.
I met the same problem. It's silly but just that I forgot to start the RMI registry process.
So, you also need to run RMI Registry process
rmiregistry
Before you try to rebind(address, obj) with RMI registry.
I am confused on how the client actually makes the connection to the server if the server is remote(not on the same machine as the client). My code works fine using localhost but i cant figure out how the client actually makes the connection to the server host so that it looks up the rmiregistry. I'm confused on what gets stored in the registry for the server, is it Sample or localhost? This may be dumb but i tried to convert localhost to its ipaddress on the client side and do String url = "//" + server + ":" + 1099 + "/Sample"; where server is the ip from getbyname() but i get a exception: java.rmi.NotBoundException: 127.0.0.1:1099/Sample
That was with the client and server on both machines. I'm just trying to figure out how the two connect remotely but it didn't even work on the same machine using the ip address of localhost.
Client:
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
public class SampleClient {
public static void main(String args[]) {
String url = "//" + "localhost" + ":" + 1099 + "/Sample";
SampleInterface sample = (SampleInterface)Naming.lookup(url);
} catch(Exception e) {
System.out.println("SampleClient exception: " + e);
}
}
}
Server:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
public class SampleServer {
public static void main(String args[]) throws IOException {
// Create and install a security manager
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
try {
String url = "//localhost:" + 1099 + "/Sample";
System.out.println("binding " + url);
Naming.rebind(url, new Sample());
// Naming.rebind("Sample", new Sample());
System.out.println("server " + url + " is running...");
}
catch (Exception e) {
System.out.println("Sample server failed:" + e.getMessage());
}
}
}
The server should bind to a Registry running on 'localhost'.
The client should lookup a Registry at the server host.
It's as simple as that.
I'm confused on what gets stored in the registry for the server, is it Sample or localhost?
Neither. You're confusing three different things:
The hostname, in this case 'localhost'.
The bind-name, in this case 'Sample'.
The object which is bound, which is the remote stub.
I have written following code for the client of RMI. But getting
java.rmi.ConnectException: Connection refused to host: localhost; nested
exception is:
java.net.ConnectException: Connection refused: connect
code :
import java.rmi.*;
import java.net.*;
import java.rmi.registry.*;
class client
{
public static void main(String [] ars)
{
Iface serv;
Registry r;
String serveraddr = ars[0];
String serverport = ars[1];
String text = "Hey jude";
System.out.println("Sending" + text);
try{
r = LocateRegistry.getRegistry(
serveraddr,
(new Integer(serverport)).intValue()
);
serv = (Iface) r.lookup("rmi://server");
serv.receive(text);
}
catch(Exception e){
System.out.println(e);
}
}
}
If you're getting that on bind, rebind, or lookup, the Registry isn't running. If you get it doing the remote call, see item A.1 in the RMI FAQ supplied with the Javadoc, and if you're running Linux also check that your /etc/hosts file maps 127.0.0.1 to localhost and your real ip address to your real hostname - this has been a common problem in some Linux distributions.
I met the same problem. It's silly but just that I forgot to start the RMI registry process.
So, you also need to run RMI Registry process
rmiregistry
Before you try to rebind(address, obj) with RMI registry.