Using dig as a LLMNR or mDNS CLI Lookup utility

I was looking for a LLMNR commandline lookup utility. Actually, dig can do the job quite fine.

LLMNR usage

LLMNR (Link-Local Multicast Name Resolution), RFC4795, is a Microsoft-centric DNS-based protocol for resolving names using multicast on the local network. It is expected to be used by default for single label names only:

By default, an LLMNR sender SHOULD send LLMNR queries only for single-label names. Stub resolvers supporting both DNS and LLMNR SHOULD avoid sending DNS queries for single-label names, in order to reduce unnecessary DNS queries.

In the Windows world, it is used alongside with other protocols1 such as NBNS/NBT-NS (NetBios/TCP Name Service, RFC1001, RFC1002), WINS and DNS. Apparently, LLMNR is tried before NBNS but it's not really documented AFAIU.

LLMNR is quite similar in spirit to mDNS (multicast DNS, RFC6762). mDNS is originated from Apple Bonjour where it is used with DNS-SD (DNS Service Discovery, RFC6783) and has been available on Linux systemd for a long time through Avahi. It is normally used for domain names in the local domain (eg. foo.local, foo.bar.local, etc.).

On Linux systems, in addition to Avahi, system-resolved supports both LLMNR and mDNS/DNS-SD.

LLMNR lookup with dig

I was looking for a CLI tool for resolving names with LLMNR but could not find any. In fact, dig can be the job well. LLMNR is really DNS with a few changes:

  • queries requests are sent to multicast address 224.0.0.252 or ff02:0:0:0:0:0:1:3 with UDP port 5355;

  • responses are sent to the requester IP address and port using the IP and port the request was sent to;

  • a few flags have a different meaning.

LLMNR header:

1  1  1  1  1  1
0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  | C|TC| T| Z| Z| Z| Z|   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

DNS header:

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

This means we can actually do LLMNR requests with dig. Dor example, we can do a DNS WPAD 😨 request:

dig +noedns -p 5355 @224.0.0.252 wpad

EDNS0 is disabled because the Microsoft LLMNR profile does not support EDNS0:

The Link Local Multicast Name Resolution (LLMNR) Profile [...] does not support Extension Mechanisms for DNS (EDNS0) [RFC2671].

mDNS lookup with dig

Similarly for mDNS, requests are sent to 224.0.0.251 or ff02::fb on UDP port 5353. Full mDNS queries are expected to send queries from this same IP/port tuple (and receive the answer on this same tuple):

A compliant Multicast DNS querier, which implements the rules specified in this document, MUST send its Multicast DNS queries from UDP source port 5353 (the well-known port assigned to mDNS), and MUST listen for Multicast DNS replies sent to UDP destination port 5353 at the mDNS link-local multicast address** (224.0.0.251 and/or its IPv6 equivalent FF02::FB).

This cannot be done with dig: it cannot listen for answers sent to a multicast address.

However, the mDNS protocol allows for a simpler client implementation, One-Shot Multicast DNS Queries:

The most basic kind of Multicast DNS client may simply send standard DNS queries blindly to 224.0.0.251:5353, without necessarily even being aware of what a multicast address is. [...] these queries MUST NOT be sent using UDP source port 5353, since using UDP source port 5353 signals the presence of a fully compliant Multicast DNS querier, as described below.

This means we can use dig as well:

dig -p 5353 @224.0.0.251 example.local

Lookup with resolvectl

Alternatively if systemd-resolved is running, resolvectl can be used:

resolvectl query -p llmnr example
resolvectl query -p mdns example.local

  1. Apparently there is as well PNRP (Peer Name Resolution Protocol) and SNID (Server Network Information Discovery).