My DNS contains two records for ServerA:
- an A record with its IPv4 address: 10.25.46.130
- an AAAA record with its IPv6 address: fda8:6c3:ce53:a890::55
I am not able to get my SimpleClient.java program (source at the end of this post) on a Windows server to list the IPv6 address of ServerA using InetAddress.getAllByName(), even when configuring the JVM with -Djava.net.preferIPv6Addresses=true.
The same test running on an IPv6 enabled Linux server is successful.
Configuration details:
- Windows: Server 2019 Standard (10.0.17763)
- Java: OpenJDK 11.0.5+
The output of ipconfig on the Windows server shows that IPv6 seems enabled:
> ipconfig
Windows IP Configuration
Ethernet adapter Ethernet: Connection-specific DNS Suffix . : IPv4 Address. . . . . . . . . . . : 10.25.0.214 Subnet Mask . . . . . . . . . . . : X.X.X.X Default Gateway . . . . . . . . . : X.X.X.X
Ethernet adapter Ethernet 2: Connection-specific DNS Suffix . : fr.company.com IPv6 Address. . . . . . . . . . . : fda8:6c3:ce53:a890::3 Link-local IPv6 Address . . . . . : X.X.X.X::X Default Gateway . . . . . . . . . : X.X.X.X::XThe nslookup output from the Windows server is the expected one:
> nslookup ServerA
Server: dns.fr.company.com
Address: X.X.X.X
Non-authoritative answer:
Name: ServerA.fr.company.com
Addresses: fda8:6c3:ce53:a890::55 10.25.46.130I am able to successfully run ping -6 ServerA from the Windows server:
> ping -6 ServerA
Pinging ServerA.fr.company.com [fda8:6c3:ce53:a890::55] with 32 bytes of data:
Reply from fda8:6c3:ce53:a890::55: time<1ms
Reply from fda8:6c3:ce53:a890::55: time<1msBelow is the expected output running from an IPv6 enabled Linux server:
# IPv4 (default)
$ java SimpleClient.java ServerA 12345
preferIPv6Addresses: null
InetAddress.getByName()
ServerA/10.25.46.130
InetAddress.getAllByName()
ServerA/10.25.46.130
ServerA/fda8:6c3:ce53:a890:0:0:0:55
# IPv6
$ java -Djava.net.preferIPv6Addresses=true SimpleClient.java ServerA 12345
preferIPv6Addresses: true
InetAddress.getByName()
ServerA/fda8:6c3:ce53:a890:0:0:0:55
InetAddress.getAllByName()
ServerA/fda8:6c3:ce53:a890:0:0:0:55
ServerA/10.25.46.130The same test failing on the Windows server:
# IPv4 (default)
> java SimpleClient.java ServerA 12345
preferIPv6Addresses: null
InetAddress.getByName()
ServerA/10.25.46.130
InetAddress.getAllByName()
ServerA/10.25.46.130
# IPv6
> java -Djava.net.preferIPv6Addresses=true SimpleClient.java ServerA 12345
preferIPv6Addresses: true
InetAddress.getByName()
ServerA/10.25.46.130
InetAddress.getAllByName()
ServerA/10.25.46.130On the Windows server, the call to InetAddress.getAllByName() is only returning a single IPv4 address and not both an IPv4 and IPv6 address like as expected on the Linux IPv6 enabled server.
I can reproduce the same behavior on a Linux server with IPv6 disabled (grub and kernel settings):
# IPv4 (default)
$ java SimpleClient.java ServerA 12345
preferIPv6Addresses: null
InetAddress.getByName()
ServerA/10.25.46.130
InetAddress.getAllByName()
ServerA/10.25.46.130
# IPv6
$ java -Djava.net.preferIPv6Addresses=true SimpleClient.java ServerA 12345
preferIPv6Addresses: true
InetAddress.getByName()
ServerA/10.25.46.130
InetAddress.getAllByName()
ServerA/10.25.46.130From these tests, I conclude that something is wrong somewhere on the IPv6 configuration of the Windows server but I don't know what.
Some notes and stuff I tried:
- Manually adding the IPv6 address of ServerA in C:\Windows\System32\drivers\etc\hosts results in the program to list the IPv6 address, but only this one.
- I did not find a
DisabledComponentskey in the registy for the pathComputer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
Below is the code for SampleClient.java:
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.InetAddress;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.IOException;
public class SimpleClient { public static void main(String[] args) { if (args.length < 2) return; String hostname = args[0]; System.out.println("preferIPv6Addresses: " + System.getProperty("java.net.preferIPv6Addresses")); try { System.out.println("InetAddress.getByName()"); System.out.println(InetAddress.getByName(hostname)); InetAddress[] addresses = InetAddress.getAllByName(hostname); System.out.println("InetAddress.getAllByName()"); for (InetAddress address : addresses) { System.out.println(address); } } catch (UnknownHostException ex) { System.out.println("Server not found: " + ex.getMessage()); } int port = Integer.parseInt(args[1]); try (Socket socket = new Socket(hostname, port)) { InputStream input = socket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); System.out.println(reader.readLine()); } catch (UnknownHostException ex) { System.out.println("Server not found: " + ex.getMessage()); } catch (IOException ex) { System.out.println("I/O error: " + ex.getMessage()); } }
}Can somebody hint at something that might be wrong on the Windows server configuration?
Thank you.
EDIT1:
As mentioned in the comments, I also reproduced the issue with Python using socket.getaddrinfo():
- Windows server (no AF_INET6)
>>> socket.getaddrinfo("serverA", 12345)
[(<AddressFamily.AF_INET: 2>, 0, 0, '', ('10.25.46.130', 12345))]- Linux server (both AF_INET6 and AF_INET)
>>> socket.getaddrinfo("serverA", 12345)
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('10.25.46.130', 12345)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('10.25.46.130', 12345)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_RAW: 3>, 0, '', ('10.25.46.130', 12345)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('fda8:6c3:ce53:a890::55', 12345, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('fda8:6c3:ce53:a890::55', 12345, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_RAW: 3>, 0, '', ('fda8:6c3:ce53:a890::55', 12345, 0, 0))] 6 1 Answer
The answer came from @user1686 in the comments, pointing out that IPv4 and IPv6 were separated on different interfaces.
It seems that our IT provisioned the Windows server with two interfaces, one dedicated for each IP stack:
- Ethernet (IPv4)
- Ethernet4 (IPv6)
I disabled all extra interfaces on the Windows server and kept only the “Ethernet” one:
I manually re-configured the IPv6 stack on “Ethernet” by copy pasting the settings and properties from “Ethernet 4”:
The resulting ipconfig shows a single interface with both IPv4 and IPv6:
> ipconfig
Windows IP Configuration
Ethernet adapter Ethernet: Connection-specific DNS Suffix . : IPv6 Address. . . . . . . . . . . : fda8:6c3:ce53:a890::3 Link-local IPv6 Address . . . . . : fe80::8d10:5083:9a0:9ab8%16 IPv4 Address. . . . . . . . . . . : 10.25.0.214 Subnet Mask . . . . . . . . . . . : Z.Z.Z.Z Default Gateway . . . . . . . . . : Y:Y:Y:Y::T X.X.X.XAfter this reconfiguration, the test is behaving correctly and lists both the IPv4 and IPv6 addresses for serverA:
# IPv4
> C:\jdk11.0.8\bin\java SimpleClient.java serverA 12345
preferIPv6Addresses: null
InetAddress.getByName()
serverA/10.25.46.130
InetAddress.getAllByName()
serverA/10.25.46.130
serverA/fda8:6c3:ce53:a890:0:0:0:55
# IPv6
> C:\jdk11.0.8\bin\java -Djava.net.preferIPv6Addresses=true SimpleClient.java serverA 12345
preferIPv6Addresses: true
InetAddress.getByName()
serverA/fda8:6c3:ce53:a890:0:0:0:55
InetAddress.getAllByName()
serverA/fda8:6c3:ce53:a890:0:0:0:55
serverA/10.25.46.130So it definitely seems that trying to segregate IP stacks on different interfaces is not a good idea.