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
with127.0.0.1
in the source code resolves the problem , andConnectionRefused
(expected) is raised instead ofNoRouteToHostException
- Disabling Firewalld, Disabling SELinux etc.
Questions
- 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 ?
- 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