Skip to content

Instantly share code, notes, and snippets.

@rajkrrsingh
Last active September 4, 2022 23:54
Show Gist options
  • Save rajkrrsingh/b4cd654739425acabdd8c3086e00e6a1 to your computer and use it in GitHub Desktop.
Save rajkrrsingh/b4cd654739425acabdd8c3086e00e6a1 to your computer and use it in GitHub Desktop.
how the java dns resolution work

lets take a sample code to demonste what happen when java tries to resolve the ip for the give hostname.


import java.net.InetAddress;
import java.net.UnknownHostException;

public class DNSClient {
    public static void main(String[] args) {
        InetAddress address = null;
        try {
            address = InetAddress.getByName(args[0]);
            System.out.println("host address: "+address.getHostAddress());
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }

    }
}

InetAddress.getByName(args[0]), on high level it first do Lookup hostname in JVM cache (positive & negative cache configurable by property networkaddress.cache.ttl and networkaddress.cache.negative.ttl), if the address was found in cache it will returned from here otherwise it tries to do lookupAllHostAddr from the default nameservice. from now onward it invoke the native methods Inet6AddressImpl#lookupAllHostAddr or Inet4AddressImpl#lookupAllHostAddr (can be configured. (to use only specific ip protocol by java flag java.net.preferIPv4Stack=true). if application not interested in IPv6 look ups then please consider changing this flag to preferIPv4Stack to get perf benefits.

Inet6AddressImpl#lookupAllHostAddr relies on native function call getaddrinfo which will ultimately resolve the nameserver and send the dns request over UDP to ns.

To understand internal working of the underlying implementation, lets do strace on it:q!

strace  -f java  DNSClient google.com > strace.out 2>&1

The output is quite big so I am breaking it down to relevent information which I observe into the logs.

// getaddrinfo read the nsswitch.conf and based on the config load libnss_files.so and libnss_dns.so

[pid  8797] open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3

cat /etc/nsswitch.conf | grep host
#hosts:     db files nisplus nis dns
hosts:      files dns

as configured it will first try to read the /etc/host and then fallback to the dns, thats what we saw in the strace logs

[pid  8797] open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 5
[pid  8797] open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 5

find the nsserver and start sendiing the requst to the dns server, in the following log snippet you can see request (to resolve google.com) was sent to 10.0.0.2 and response was recieved.

pid  8797] connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.0.2")}, 16) = 0
[pid  8797] poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
[pid  8797] sendmmsg(5, {{{msg_name(0)=NULL, msg_iov(1)=[{"D\323\1\0\0\1\0\0\0\0\0\0\6google\3com\0\0\1\0\1", 28}], msg_controllen=0, msg_flags=0}, 28}, {{msg_name(0)=NULL, msg_iov(1)=[{"\240\335\1\0\0\1\0\0\0\0\0\0\6google\3com\0\0\34\0\1", 28}], msg_controllen=0, msg_flags=0}, 28}}, 2, MSG_NOSIGNAL) = 2
[pid  8797] poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}])
[pid  8797] ioctl(5, FIONREAD, [44])    = 0
[pid  8797] recvfrom(5, "D\323\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\300\f\0\1"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.0.2")}, [16]) = 44
[pid  8797] poll([{fd=5, events=POLLIN}], 1, 4998) = 1 ([{fd=5, revents=POLLIN}])
[pid  8797] ioctl(5, FIONREAD, [56])    = 0
[pid  8797] mprotect(0x7f53dc0df000, 65536, PROT_READ|PROT_WRITE) = 0
[pid  8797] recvfrom(5, "\240\335\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\300\f\0\34"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.0.2")}, [16]) = 56
[pid  8797] close(5) 


// output

[pid  8797] write(1, "host address: 142.250.190.142", 29host address: 142.250.190.142) = 29

TCP Dump to quickly verify the DNS lookup call.

for quickly capture and review the tcpdump we can try something similar to the following

 

tcpdump -w /tmp/dns.pcap -i eth0 port not 22 &

 

tcpdump -n -t -r /tmp/dns.pcap port 53 <- check for the obvious problem here, if any, otherwise you should see a beautiful :) DNS lookup request and response.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment