Monday 25 February 2019

Java Socket fails to connect to "0.0.0.0" with NoRouteToHostException instead of ConnectionRefused

Problem

When opening a socket to IP: 0.0.0.0 and Port: 37845 (just a random closed port) with java's socket class , the socket connect fails with a java.net.NoRouteToHostException on Machine 1

Exception in thread "main" java.net.NoRouteToHostException: No route to host (Host unreachable)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:204)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at Test.main(Test.java:26)

I'm using this testcode:

import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

public class Test {

 public static void main(String[] args) throws Exception {

  Socket socket;

  // create a socket with a timeout
  SocketAddress socketAddress = new InetSocketAddress("0.0.0.0", 37845);

  // create a socket
  socket = new Socket();

  // this method will block no more than timeout ms.
  int timeoutInMs = 10 * 1000; // 10 seconds
  socket.connect(socketAddress, timeoutInMs);
  System.err.println("SUCCESS");
 }
}

Expected

What , I'm actually expecting is a java.net.ConnectException : Connection refused (Connection refused) , which is also what I'm getting with another Cent OS machine, let's call it Machine2:

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:350)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:204)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at Test.main(Test.java:26)


Setup

Machine1:

[qa@jenkins-staging ~]$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[qa@jenkins-staging ~]$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
[qa@jenkins-staging ~]$ uname -a
Linux jenkins-staging.fancydomain 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Machine2:

[qa@localhost ~]$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[qa@localhost ~]$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
[qa@localhost ~]$ uname -a
Linux localhost.localdomain 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

So it seems like the only difference is the kernel version.

Additional things i've tried:

  • I tried the "same" code with python , there i always get a ConnectionRefused (on Machine1 + Machine2)

    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("0.0.0.0", 37845))
    
    
  • Pinging 0.0.0.0 on Machine1 works as well and resolves to 127.0.0.1
  • Replacing 0.0.0.0 with 127.0.0.1 in the source code resolves the problem , and ConnectionRefused (expected) is raised instead of NoRouteToHostException
  • Disabling Firewalld, Disabling SELinux etc.

Questions

  1. Is this a java bug ? If so why is it working on Machine2 even though they are using the same jdk and same java version ?
  2. Is this a Linux Kernel Bug ? If so why is it working with Python when i open a socket to 0.0.0.0 but not with java ? I would assume the underlying syscalls are the same.

Clarification

In the example above i used a port which is closed , just for demonstration purposes. The same applies if there is an actual listening port on the machine then it will be ConnectionRefused vs SUCCESS



from Java Socket fails to connect to "0.0.0.0" with NoRouteToHostException instead of ConnectionRefused

No comments:

Post a Comment