Bali, Indonesia
Insights

Mastering DNS Glue Records: Architecture, Circular Delegation Traps, and an Advanced Multi-TLD Bash Auditor

October 12, 2026
0:00
When configuring custom or vanity nameservers (ns1.yourdomain.com and ns2.yourdomain.com), web hosting administrators and site reliability engineers frequently stumble upon sporadic DNS resolution failures. Browsers throw DNS_PROBE_FINISHED_NXDOMAIN, curl sessions hang on name resolution, and propagation tools report conflicting responses across global nodes. In the vast majority of these incidents, the culprit is not an invalid zone file or firewall blockage on port 53—it is a missing, misconfigured, or dangling DNS Glue Record at the parent Top-Level Domain (TLD) registry. This technical guide dissects the architectural mechanics of DNS delegation, analyzes the packet-level anatomy of circular dependencies, and provides a production-grade Bash auditor that evaluates glue records across any global TLD directly from your command line.
To understand why glue records exist, we must trace how a recursive resolver discovers the IP address of an authoritative nameserver.
TEXT
Root Zone (.)
             │
             ▼ Queries root for .com nameserver
     TLD Registry (.com)
             │
             ▼ Delegates yourdomain.com to ns1.yourdomain.com
 Authoritative Nameserver (ns1.yourdomain.com)
             │
             ▼ Returns A record for yourdomain.com (198.51.100.10)
Imagine you register example.com and specify its authoritative nameservers as:
  • ns1.example.com
  • ns2.example.com
When a client queries https://example.com, the recursive resolver executes the following resolution chain:
  1. The resolver queries the Root DNS servers (.) to find the authoritative servers for .com.
  2. The .com TLD servers (e.g., Verisign's a.gtld-servers.net) respond: "The authoritative nameserver for example.com is ns1.example.com."
  3. The resolver now needs to query ns1.example.com for the IP address of example.com.
  4. But wait: To resolve ns1.example.com, the resolver must first ask the nameserver responsible for example.com!
This creates an infinite circular loop:
You cannot resolve example.com without querying ns1.example.com, but you cannot locate ns1.example.com without resolving example.com.
A Glue Record is simply an A (IPv4) or AAAA (IPv6) address record stored directly in the parent zone (the TLD registry, such as Verisign for .com or PANDI for .id). When the TLD server delegates authority for example.com, it includes this IP address directly inside the ADDITIONAL SECTION of its DNS response packet. This "glues" the nameserver name to its physical IP address, breaking the circular dependency before recursion stalls.
Not all domain configurations require glue records. The requirement depends strictly on whether the nameserver is in-bailiwick:
Configuration TypeExample NameserverGlue Record Required?Rationale
In-Bailiwickns1.example.com for example.comYES (Mandatory)Circular dependency exists; child zone name matches nameserver subdomain.
Out-of-Bailiwickns1.cloudflare.com for example.comNOResolver resolves cloudflare.com independently through .com TLD without circular loop.
Cross-TLD In-Bailiwickns1.example.id for example.comNOResolved through the .id registry independently.
If you run private cPanel, DirectAdmin, or Plesk servers with branded nameservers (ns1.yourbrand.com), you must register glue records through your domain registrar's control panel (often labeled Child Nameservers, Host Records, or Private Nameservers).
Local tools like standard dig example.com or ping query your local recursive resolver, which masks whether glue records exist at the TLD level because the resolver caches answers. To verify actual registry glue, you must query the TLD nameserver directly with recursion disabled (+norecurse):
BASH
# 1. Discover the authoritative TLD nameservers for .com
dig ns com +short

# 2. Query a .com TLD server directly for your child nameserver
dig @a.gtld-servers.net. ns1.candraoctavianr.com +norecurse
When valid glue exists, the TLD server outputs both the delegation in the AUTHORITY SECTION and the glue IP in the ADDITIONAL SECTION:
DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48120
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;ns1.example.com.              IN      A

;; AUTHORITY SECTION:
example.com.           172800  IN      NS      ns1.example.com.
example.com.           172800  IN      NS      ns2.example.com.

;; ADDITIONAL SECTION:
ns1.example.com.       172800  IN      A       103.189.234.15
ns2.example.com.       172800  IN      A       103.189.234.16
Warning: If the ADDITIONAL SECTION is empty or missing, your nameserver lacks a glue record at the registry, leading to sporadic lookup failures across privacy-hardened public resolvers (like Quad9 and Cloudflare 1.1.1.1).

One of the most insidious hosting outages occurs when an organization migrates its nameserver VPS to a new IP address:
  1. The sysadmin updates the A record inside the zone file on the authoritative server:
    DNS
    ns1.example.com.  IN  A  198.51.100.99
  2. The sysadmin forgets to update the Glue Record at the domain registrar (which updates the TLD registry).
  3. The TLD registry continues advertising the old IP 198.51.100.15 in its ADDITIONAL SECTION.
This results in Dangling Glue. Depending on how long recursive resolvers cache glue records versus authoritative answers, 30% to 70% of worldwide users will intermittently fail to resolve the domain until both values are synchronized.
While simple scripts rely on web WHOIS scrapers (which frequently hit rate limits or only work for .com), production infrastructure requires an auditor that inspects actual TLD root servers natively and can fall back to registrar REST APIs. Save the following script as check-glue.sh:
BASH
#!/usr/bin/env bash
# ==============================================================================
# check-glue.sh - Production DNS Glue Record & Delegation Auditor
# Author: Candra Octavian (https://candraoctavianr.com)
# ==============================================================================

set -eo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

print_banner() {
    echo -e "${CYAN}======================================================${NC}"
    echo -e "${CYAN}   DNS Glue Record & Delegation Auditor - v2.1        ${NC}"
    echo -e "${CYAN}======================================================${NC}"
}

usage() {
    echo -e "Usage: $0 <nameserver-fqdn-or-root-domain> [options]"
    echo -e ""
    echo -e "Examples:"
    echo -e "  $0 ns1.google.com"
    echo -e "  $0 candraoctavianr.com --audit-all"
    echo -e "  $0 a.gtld-servers.net --verisign-api"
    exit 1
}

AUDIT_ALL=false
USE_VERISIGN_API=false

TARGET="${1:-}"
shift || true

while [[ $# -gt 0 ]]; do
    case "$1" in
        --audit-all)
            AUDIT_ALL=true
            shift
            ;;
        --verisign-api)
            USE_VERISIGN_API=true
            shift
            ;;
        *)
            echo -e "${RED}Unknown option: $1${NC}"
            usage
            ;;
    esac
done

if [[ -z "$TARGET" ]]; then
    usage
fi

print_banner

# Function to query Verisign REST API for .com / .net
check_verisign_api() {
    local ns="$1"
    local tld="${ns##*.}"
    
    echo -e "${BLUE}[+] Querying Verisign Registry API for: ${YELLOW}${ns}${NC}"
    local endpoint="https://webwhois.verisign.com/webwhois-ui/rest/whois?q=${ns}&tld=${tld}&type=nameserver"
    
    local api_res
    if command -v jq &> /dev/null; then
        api_res=$(curl -s -L "$endpoint" | jq -r '.message // empty' 2>/dev/null || true)
    else
        api_res=$(curl -s -L "$endpoint" | grep -o '"message":".*"' | cut -d'"' -f4 || true)
    fi

    if [[ -n "$api_res" ]]; then
        echo -e "${GREEN}[✔] Registry Response Received:${NC}"
        echo "$api_res" | sed -n \
            -e "/For more information on Whois status codes/q" \
            -e "s/>>>/  /g" \
            -e "s/<<</ /g" \
            -e "s/^   //g" \
            -e "p"
    else
        echo -e "${YELLOW}[!] No direct Verisign record found or non-supported TLD.${NC}"
    fi
}

# Universal Native DNS Query directly to TLD root servers
check_native_tld_glue() {
    local ns="$1"
    # Clean trailing dot
    ns="${ns%.}"

    # Extract top-level domain
    local tld="${ns##*.}"

    echo -e "
${BLUE}[+] Performing Raw DNS TLD Inspection for: ${YELLOW}${ns}${NC}"

    # Find authoritative TLD nameservers
    local tld_servers
    tld_servers=$(dig +short NS "$tld" | head -n 2)

    if [[ -z "$tld_servers" ]]; then
        echo -e "${RED}[✘] Error: Could not determine TLD authoritative nameservers for .${tld}${NC}"
        return 1
    fi

    local selected_tld_server
    selected_tld_server=$(echo "$tld_servers" | head -n 1)
    echo -e "${CYAN}    → Querying Parent TLD Server: ${selected_tld_server} (.${tld})${NC}"

    # Query without recursion to examine ADDITIONAL section
    local raw_output
    raw_output=$(dig @"$selected_tld_server" "$ns" A +norecurse +additional 2>/dev/null)

    # Extract ADDITIONAL SECTION entries
    local glue_ipv4
    glue_ipv4=$(echo "$raw_output" | awk '/;; ADDITIONAL SECTION:/,/^$/' | grep -E '\s+A\s+' | awk '{print $NF}')
    
    local glue_ipv6
    glue_ipv6=$(echo "$raw_output" | awk '/;; ADDITIONAL SECTION:/,/^$/' | grep -E '\s+AAAA\s+' | awk '{print $NF}')

    if [[ -n "$glue_ipv4" || -n "$glue_ipv6" ]]; then
        echo -e "${GREEN}[✔] GLUE RECORD VERIFIED IN PARENT TLD!${NC}"
        [[ -n "$glue_ipv4" ]] && echo -e "    ${GREEN}IPv4 Glue (A):    ${NC}${glue_ipv4}"
        [[ -n "$glue_ipv6" ]] && echo -e "    ${GREEN}IPv6 Glue (AAAA): ${NC}${glue_ipv6}"
    else
        echo -e "${YELLOW}[!] NO GLUE RECORD DETECTED IN TLD ADDITIONAL SECTION.${NC}"
        echo -e "    If ${ns} is an out-of-bailiwick nameserver, this is expected."
        echo -e "    If this is a custom child nameserver, resolution may fail!"
    fi
}

# Audit mode: Automatically discover and check all NS records of a root domain
if [[ "$AUDIT_ALL" == "true" ]]; then
    echo -e "${BLUE}[+] Discovering Authoritative Nameservers for Domain: ${YELLOW}${TARGET}${NC}"
    NS_LIST=$(dig +short NS "$TARGET" | sort -u)

    if [[ -z "$NS_LIST" ]]; then
        echo -e "${RED}[✘] Could not find any NS records for ${TARGET}.${NC}"
        exit 1
    fi

    echo -e "${CYAN}Found Nameservers:${NC}"
    echo "$NS_LIST"
    echo ""

    for ns in $NS_LIST; do
        check_native_tld_glue "$ns"
        if [[ "$USE_VERISIGN_API" == "true" ]]; then
            check_verisign_api "$ns"
        fi
        echo "------------------------------------------------------"
    done
else
    check_native_tld_glue "$TARGET"
    if [[ "$USE_VERISIGN_API" == "true" ]]; then
        check_verisign_api "$TARGET"
    fi
fi

echo -e "
${GREEN}[✔] Audit complete.${NC}"

Make the script executable:
BASH
chmod +x check-glue.sh
BASH
./check-glue.sh a.gtld-servers.net
Sample output:
TEXT
======================================================
   DNS Glue Record & Delegation Auditor - v2.1        
======================================================

[+] Performing Raw DNS TLD Inspection for: a.gtld-servers.net
    → Querying Parent TLD Server: a.gtld-servers.net. (.net)
[✔] GLUE RECORD VERIFIED IN PARENT TLD!
    IPv4 Glue (A):    192.5.6.30
    IPv6 Glue (AAAA): 2001:503:a83e::2:30

[✔] Audit complete.
To audit all delegated nameservers for an entire domain simultaneously, pass --audit-all:
BASH
./check-glue.sh candraoctavianr.com --audit-all
The script automatically queries the root zone, isolates each authoritative host (grant.ns.cloudflare.com, norah.ns.cloudflare.com), queries the parent .com registry, and validates both IPv4 and IPv6 glue delegations.
  1. Always Register Both IPv4 and IPv6 Glue: Many modern mobile networks (especially 5G carriers) operate in IPv6-mostly mode with NAT64. A missing AAAA glue record introduces latency delays of up to 1,500ms while resolvers fail over to IPv4.
  2. Never Change Authoritative IP Without Updating Registrar: When renumbering nameserver hosts, always update registrar child host records at least 48 hours prior to decommissioning old IPs.
  3. Use Multiple TLDs for Resilient Infrastructure: Enterprise architectures avoid hosting all nameservers under the same domain. For example, use ns1.brand.com and ns2.brand.net so an issue with a single TLD registry does not take down your entire network.
  4. Automate Continuous Verification: Incorporate the check-glue.sh script into your CI/CD health checks or Zabbix/Prometheus monitoring scripts to alert on registry discrepancies before clients notice downtime.