When managing enterprise networks, we often need to find hostnames containing specific patterns (like employee names in hostnames). Standard DNS tools don't directly support wildcard searches in the way we might expect from SQL or file system operations.
The DNS protocol itself doesn't support wildcard queries in the middle of hostnames. DNS wildcards (*) only work at the leftmost label (e.g., *.example.com). This is a fundamental protocol limitation, not just a tool restriction.
Here are practical solutions to achieve similar results:
1. Zone Transfers (If Possible)
If you have access to zone transfers, you can dump and grep:
dig axfr localdomain.com | grep -i "miller"
Note: Zone transfers are typically restricted for security reasons.
2. Using Reverse DNS
For smaller networks, scan the IP range and check PTR records:
for ip in {1..254}; do
host 10.10.10.$ip | grep -i "miller"
done
3. LDAP Integration
Since hostnames contain usernames, querying LDAP might be more efficient:
ldapsearch -x -H ldap://dc.localdomain.com -b "dc=localdomain,dc=com" "(&(sn=miller)(objectClass=user))" dn
4. PowerShell Alternative (Windows Networks)
For Active Directory environments:
Get-ADComputer -Filter "Name -like '*miller*'" -Properties IPv4Address |
Select-Object Name,IPv4Address
Here's a Python example using tkinter that combines DNS and LDAP:
import tkinter as tk
from tkinter import ttk
import subprocess
import ldap
def search_hostnames():
last_name = entry.get()
# LDAP search
l = ldap.initialize('ldap://dc.localdomain.com')
l.simple_bind_s()
results = l.search_s('dc=localdomain,dc=com', ldap.SCOPE_SUBTREE,
f'(sn={last_name})', ['sAMAccountName'])
# DNS verification
hosts = []
for dn, entry in results:
username = entry['sAMAccountName'][0].decode()
try:
output = subprocess.check_output(['nslookup', f'sf-{username}.localdomain.com'],
stderr=subprocess.STDOUT)
hosts.append(f'sf-{username}.localdomain.com')
except subprocess.CalledProcessError:
continue
# Update dropdown
combo['values'] = hosts
root = tk.Tk()
tk.Label(root, text="Last Name:").pack()
entry = tk.Entry(root)
entry.pack()
tk.Button(root, text="Search", command=search_hostnames).pack()
combo = ttk.Combobox(root)
combo.pack()
root.mainloop()
For large networks, these approaches can be slow. Consider:
- Caching results
- Implementing a background worker
- Using dedicated network inventory tools
Be cautious with:
- Exposing internal hostnames through GUIs
- Rate limiting to prevent DNS flooding
- Credential handling in scripts
When managing enterprise networks, helpdesk teams frequently need to locate devices by partial hostname patterns (e.g., finding all machines containing "miller" in their FQDNs). Standard DNS tools like nslookup
and dig
don't natively support wildcard searches in the middle of hostnames (*miller*
pattern). Here's how to implement this functionality using built-in macOS tools.
Since DNS doesn't support mid-string wildcards, consider these workarounds:
# Method 1: Leveraging DNS zone transfers (if allowed)
dig axfr localdomain.com | grep miller
# Method 2: Using LDAP (when hostnames are in directory services)
ldapsearch -x -H ldap://dc.localdomain.com -b "dc=localdomain,dc=com" "(cn=*miller*)" dn ipHostNumber
For environments without zone transfer access, here's a script that emulates wildcard search by enumerating forward and reverse DNS records:
#!/bin/bash
# DNS Wildcard Search Tool
search_term=$1
dns_suffix=".localdomain.com"
# Get all PTR records in subnet
for ip in $(seq 1 254); do
host 10.10.10.$ip | grep "$search_term" | awk '{print $1,$5}'
done | grep -i "$search_term" | sort -u
# Alternative: Check pre-populated host list
grep -i "$search_term" /var/cache/dns/hosts.all
For a more user-friendly approach with pulldown selection:
import subprocess
import tkinter as tk
from tkinter import ttk
def dns_search():
results = []
raw_output = subprocess.check_output(
["dig", "+noall", "+answer", "axfr", "localdomain.com"],
text=True
)
for line in raw_output.splitlines():
if search_var.get().lower() in line.lower():
results.append(line.split()[0])
dropdown['values'] = results
root = tk.Tk()
search_var = tk.StringVar()
ttk.Entry(root, textvariable=search_var).pack()
ttk.Button(root, text="Search", command=dns_search).pack()
dropdown = ttk.Combobox(root)
dropdown.pack()
root.mainloop()
For large networks, these methods can be slow. Consider:
- Maintaining a local hosts cache updated hourly
- Using PowerShell for Windows-integrated environments
- Implementing a Redis cache for frequent queries