Network Infrastructure Discovery
1. Overview
Multi-vector infrastructure discovery combining DNS, network layer, and API sources with parallel execution, data correlation, and delta detection.
Figure 1. Infrastructure Discovery Framework
2. Phase 1: DNS Multi-Source Discovery
2.1. 1.1 pfSense DNS → Structured Extract
dsource d000 dev/network
netapi pfsense dns list 2>/dev/null | \
awk 'BEGIN{FS="│"; OFS=","} NR>4 && NF>=5 {
gsub(/^[ \t]+|[ \t]+$/, "", $2)
gsub(/^[ \t]+|[ \t]+$/, "", $4)
if ($2 != "" && $4 != "") print $2, $4
}' > /tmp/pfsense-dns.csv
2.2. 1.2 BIND Zone Transfer → Cross-Validate
dig @10.50.1.90 inside.domusdigitalis.dev AXFR 2>/dev/null | \
awk '/^[a-z].*IN\s+A\s+/ {
sub(/\.inside\.domusdigitalis\.dev\.$/, "", $1)
print $1","$5
}' | sort > /tmp/bind-dns.csv
2.3. 1.3 AD SRV Records → Service Location
for srv in _ldap._tcp _kerberos._tcp _kpasswd._tcp _gc._tcp _kerberos._udp; do
dig +short SRV ${srv}.inside.domusdigitalis.dev 2>/dev/null | \
awk -v srv="$srv" '{printf "%-20s %-6s %-6s %s\n", srv, $3, $4, $1}'
done
2.4. 1.4 DNS Source Correlation (comm)
# Extract hostnames from both sources, sorted
awk -F, '{print $1}' /tmp/pfsense-dns.csv | sort > /tmp/pf-hosts.txt
awk -F, '{print $1}' /tmp/bind-dns.csv | sort > /tmp/bind-hosts.txt
# Set operations
echo "=== In pfSense ONLY (missing from BIND) ==="
comm -23 /tmp/pf-hosts.txt /tmp/bind-hosts.txt
echo ""
echo "=== In BIND ONLY (missing from pfSense) ==="
comm -13 /tmp/pf-hosts.txt /tmp/bind-hosts.txt
echo ""
echo "=== In BOTH (validated) ==="
comm -12 /tmp/pf-hosts.txt /tmp/bind-hosts.txt | wc -l
2.5. 1.5 Reverse DNS with Parallel + Progress
seq 1 254 | xargs -P64 -I{} sh -c '
ip="10.50.1.{}"
ptr=$(dig +short -x $ip @10.50.1.1 2>/dev/null | head -1 | sed "s/\\.$//" )
[ -n "$ptr" ] && printf "%s,%s\n" "$ip" "$ptr"
' 2>/dev/null | sort -t. -k4 -n | tee /tmp/reverse-dns.csv
echo ""
awk -F, 'END{printf "=== %d PTR records found ===\n", NR}' /tmp/reverse-dns.csv
3. Phase 2: Network Layer Discovery
3.1. 2.1 ICMP Sweep with Timing Stats
START=$(date +%s.%N)
seq 1 254 | xargs -P128 -I{} sh -c '
timeout 0.2 ping -c1 -W1 10.50.1.{} &>/dev/null && echo "10.50.1.{}"
' 2>/dev/null | sort -t. -k4 -n | tee /tmp/live-icmp.txt
END=$(date +%s.%N)
echo ""
awk -v start="$START" -v end="$END" 'END{
printf "=== %d hosts in %.2fs (%.0f hosts/sec) ===\n", NR, end-start, NR/(end-start)
}' /tmp/live-icmp.txt
3.2. 2.2 ARP Cache with Vendor Lookup (Process Substitution)
ip neigh show | awk '/lladdr/ && /10\.50\.1\./ {print $1, $5}' | \
while read ip mac; do
oui=$(echo "$mac" | tr -d ':' | cut -c1-6 | tr 'a-f' 'A-F')
printf "%-15s %-18s %s\n" "$ip" "$mac" "$oui"
done | sort -t. -k4 -n
3.3. 2.3 Consolidated Host Discovery (join)
# Merge ICMP + PTR + ARP into single view
join -t',' -a1 -e'-' -o '1.1,2.2' \
<(sort /tmp/live-icmp.txt) \
<(sort -t',' -k1 /tmp/reverse-dns.csv) | \
join -t',' -a1 -e'-' -o '1.1,1.2,2.2' \
- \
<(ip neigh show | awk '/lladdr/ && /10\.50\.1\./ {print $1","$5}' | sort -t',' -k1) | \
column -t -s',' | tee /tmp/host-inventory.txt
4. Phase 3: Port Discovery Matrix
4.1. 3.1 Service Port Matrix (Parallel × Parallel)
HOSTS=$(cat /tmp/live-icmp.txt | head -30)
PORTS="22 80 443 1812 3389 5432 8443 9200"
# Header
printf "%-15s" "HOST"
for p in $PORTS; do printf "%6s" "$p"; done
echo ""
printf "%-15s" "----"
for p in $PORTS; do printf "%6s" "----"; done
echo ""
# Parallel scan with awk pivot
echo "$HOSTS" | xargs -P16 -I{} sh -c '
host="{}"
for port in '"$PORTS"'; do
timeout 0.3 nc -z $host $port 2>/dev/null && echo "$host,$port,1" || echo "$host,$port,0"
done
' 2>/dev/null | \
awk -F',' -v ports="$PORTS" '
BEGIN { n=split(ports, p, " ") }
{ results[$1][$2] = $3 }
END {
for (host in results) {
printf "%-15s", host
for (i=1; i<=n; i++) {
if (results[host][p[i]] == 1) printf "%6s", "✓"
else printf "%6s", "-"
}
print ""
}
}
' | sort -t. -k4 -n
4.2. 3.2 Full Port Scan (Single Host, 65535 Ports)
TARGET="10.50.1.20"
echo "Scanning $TARGET (65535 ports)..."
START=$(date +%s)
seq 1 65535 | xargs -P256 -I{} sh -c "
timeout 0.1 nc -z $TARGET {} 2>/dev/null && echo {}
" 2>/dev/null | sort -n | tee /tmp/open-ports-${TARGET}.txt
END=$(date +%s)
echo ""
awk -v t=$((END-START)) 'END{printf "=== %d open ports in %ds ===\n", NR, t}' /tmp/open-ports-${TARGET}.txt
4.3. 3.3 Service Fingerprint (Banner + SSL CN)
cat /tmp/live-icmp.txt | head -20 | xargs -P8 -I{} sh -c '
host="{}"
# SSH banner
ssh_banner=$(timeout 2 nc -w1 $host 22 2>/dev/null | head -1 | cut -c1-40)
[ -n "$ssh_banner" ] && echo "$host,22,SSH,$ssh_banner"
# HTTPS cert CN
for port in 443 8443; do
cn=$(timeout 3 openssl s_client -connect $host:$port 2>/dev/null </dev/null | \
openssl x509 -noout -subject 2>/dev/null | sed "s/.*CN *= *//" | cut -c1-40)
[ -n "$cn" ] && echo "$host,$port,TLS,$cn"
done
' 2>/dev/null | column -t -s','
5. Phase 4: API-Based Discovery
5.1. 4.1 ISE Infrastructure (jq Deep Dive)
dsource d000 dev/network
# Deployment nodes with roles
netapi ise api-call ers GET '/ers/config/node' 2>/dev/null | \
jq -r '.SearchResult.resources[] | [.name, .id] | @tsv' | \
while read name id; do
netapi ise api-call ers GET "/ers/config/node/$id" 2>/dev/null | \
jq -r --arg name "$name" '.Node | [$name, .gateWay, (.services // [] | join(","))] | @tsv'
done | column -t
5.2. 4.2 ISE Network Devices → Port Correlation
netapi ise api-call ers GET '/ers/config/networkdevice?size=100' 2>/dev/null | \
jq -r '.SearchResult.resources[] | .id' | head -10 | \
while read id; do
netapi ise api-call ers GET "/ers/config/networkdevice/$id" 2>/dev/null | \
jq -r '.NetworkDevice | [.name, .NetworkDeviceIPList[0].ipaddress, .NetworkDeviceGroupList[0]] | @tsv'
done | column -t
5.3. 4.3 k3s Services with LoadBalancer VIPs
ssh k3s-master-01 "kubectl get svc -A -o json" 2>/dev/null | \
jq -r '
.items[] |
select(.status.loadBalancer.ingress) |
[
.metadata.namespace,
.metadata.name,
(.status.loadBalancer.ingress[0].ip // "pending"),
(.spec.ports | map("\(.port)/\(.protocol)") | join(","))
] | @tsv
' | column -t
5.4. 4.4 k3s Pods by Namespace (awk Pivot Table)
ssh k3s-master-01 "kubectl get pods -A -o custom-columns='NS:.metadata.namespace,STATUS:.status.phase' --no-headers" 2>/dev/null | \
awk '
{ count[$1][$2]++ }
END {
printf "%-20s %8s %8s %8s\n", "NAMESPACE", "Running", "Pending", "Failed"
printf "%-20s %8s %8s %8s\n", "----", "----", "----", "----"
for (ns in count) {
printf "%-20s %8d %8d %8d\n", ns, count[ns]["Running"]+0, count[ns]["Pending"]+0, count[ns]["Failed"]+0
}
}
' | sort -k2 -rn
5.5. 4.5 Vault PKI Certificate Inventory
dsource d000 dev/vault
vault list -format=json pki_int/certs 2>/dev/null | \
jq -r '.[]' | head -10 | \
while read serial; do
vault read -format=json "pki_int/cert/$serial" 2>/dev/null | \
jq -r --arg serial "$serial" '
.data | [
$serial[0:16],
(.certificate | split("\n")[0] | sub("-----BEGIN CERTIFICATE-----"; "")),
.expiration_time
] | @tsv
'
done | column -t
5.6. 4.6 WLC Client Distribution
dsource d000 dev/network
netapi wlc run "show wireless client summary" 2>/dev/null | \
awk 'NR>5 && /^[0-9a-f]/ {
ssid = $NF
count[ssid]++
}
END {
printf "%-30s %8s\n", "SSID", "Clients"
printf "%-30s %8s\n", "----", "----"
for (s in count) printf "%-30s %8d\n", s, count[s]
}' | sort -k2 -rn
6. Phase 5: Infrastructure Report Generation
6.1. 5.1 Comprehensive JSON Export
{
echo '{'
echo ' "timestamp": "'$(date -Iseconds)'",'
echo ' "subnet": "10.50.1.0/24",'
# Live hosts array
echo ' "hosts": ['
first=true
cat /tmp/live-icmp.txt | while read ip; do
hostname=$(awk -F',' -v ip="$ip" '$1==ip {print $2; exit}' /tmp/reverse-dns.csv)
mac=$(ip neigh show $ip 2>/dev/null | awk '/lladdr/{print $5}')
ssh=$(timeout 0.2 nc -z $ip 22 2>/dev/null && echo "true" || echo "false")
https=$(timeout 0.2 nc -z $ip 443 2>/dev/null && echo "true" || echo "false")
[ "$first" = "false" ] && echo ','
first=false
printf ' {"ip":"%s","hostname":"%s","mac":"%s","ssh":%s,"https":%s}' \
"$ip" "${hostname:--}" "${mac:--}" "$ssh" "$https"
done
echo ''
echo ' ]'
echo '}'
} | tee /tmp/infra-report-$(date +%Y%m%d).json
6.2. 5.2 CSV with All Vectors
echo "IP,Hostname,MAC,SSH,HTTPS,RADIUS,RDP,ISE,k3s"
cat /tmp/live-icmp.txt | xargs -P16 -I{} sh -c '
ip="{}"
hostname=$(awk -F"," -v ip="$ip" "\$1==ip {print \$2; exit}" /tmp/reverse-dns.csv)
mac=$(ip neigh show $ip 2>/dev/null | awk "/lladdr/{print \$5}")
ssh=$(timeout 0.2 nc -z $ip 22 2>/dev/null && echo "Y" || echo "-")
https=$(timeout 0.2 nc -z $ip 443 2>/dev/null && echo "Y" || echo "-")
radius=$(timeout 0.2 nc -z $ip 1812 2>/dev/null && echo "Y" || echo "-")
rdp=$(timeout 0.2 nc -z $ip 3389 2>/dev/null && echo "Y" || echo "-")
ise=$(timeout 0.2 nc -z $ip 9060 2>/dev/null && echo "Y" || echo "-")
k3s=$(timeout 0.2 nc -z $ip 6443 2>/dev/null && echo "Y" || echo "-")
echo "$ip,${hostname:--},${mac:--},$ssh,$https,$radius,$rdp,$ise,$k3s"
' 2>/dev/null | sort -t. -k4 -n | tee /tmp/infra-inventory.csv
column -t -s',' /tmp/infra-inventory.csv
7. Phase 6: Delta Detection
7.1. 6.1 Baseline Comparison
BASELINE="/tmp/baseline-hosts.txt"
CURRENT="/tmp/live-icmp.txt"
# Create baseline if missing
[ ! -f "$BASELINE" ] && cp "$CURRENT" "$BASELINE" && echo "Baseline created"
# Compare
echo "=== NEW HOSTS (not in baseline) ==="
comm -13 <(sort "$BASELINE") <(sort "$CURRENT")
echo ""
echo "=== MISSING HOSTS (in baseline, not responding) ==="
comm -23 <(sort "$BASELINE") <(sort "$CURRENT")
# Update baseline
cp "$CURRENT" "$BASELINE"
7.2. 6.2 Service Drift Detection (awk State Machine)
STATE_FILE="/tmp/port-state.txt"
HOSTS="10.50.1.20 10.50.1.21 10.50.1.60"
PORTS="22 443 1812 8443"
# Scan current state
for host in $HOSTS; do
for port in $PORTS; do
timeout 0.3 nc -z $host $port 2>/dev/null && state=1 || state=0
echo "$host:$port:$state"
done
done > /tmp/port-state-current.txt
# Compare with previous (if exists)
if [ -f "$STATE_FILE" ]; then
echo "=== PORT STATE CHANGES ==="
diff <(sort "$STATE_FILE") <(sort /tmp/port-state-current.txt) | \
awk '/^[<>]/ {
split($2, a, ":")
dir = ($1 == "<") ? "CLOSED" : "OPENED"
printf "%-15s %-6s %s\n", a[1], a[2], dir
}'
fi
cp /tmp/port-state-current.txt "$STATE_FILE"
8. Phase 7: Automated Discovery Script
8.1. 7.1 Complete Infrastructure Audit
#!/usr/bin/env bash
# Save as: ~/.local/bin/infra-audit
# Usage: infra-audit [--full|--quick]
set -euo pipefail
SUBNET="10.50.1"
OUTDIR="/tmp/infra-audit-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUTDIR"
log() { printf "\033[1;34m[%s]\033[0m %s\n" "$(date +%H:%M:%S)" "$*"; }
log "Phase 1: DNS Discovery"
dsource d000 dev/network >/dev/null 2>&1
netapi pfsense dns list 2>/dev/null | \
awk 'BEGIN{FS="│"} NR>4 && NF>=5 {gsub(/[ \t]+/,"",$2); gsub(/[ \t]+/,"",$4); if($2!="" && $4!="") print $2","$4}' \
> "$OUTDIR/dns.csv"
log " $(wc -l < "$OUTDIR/dns.csv") DNS records"
log "Phase 2: Host Discovery"
seq 1 254 | xargs -P128 -I{} sh -c "timeout 0.2 ping -c1 ${SUBNET}.{} &>/dev/null && echo ${SUBNET}.{}" \
2>/dev/null | sort -t. -k4 -n > "$OUTDIR/live.txt"
log " $(wc -l < "$OUTDIR/live.txt") live hosts"
log "Phase 3: Reverse DNS"
cat "$OUTDIR/live.txt" | xargs -P32 -I{} sh -c '
ptr=$(dig +short -x {} 2>/dev/null | head -1 | sed "s/\\.$//" )
[ -n "$ptr" ] && echo "{},${ptr}"
' > "$OUTDIR/ptr.csv"
log " $(wc -l < "$OUTDIR/ptr.csv") PTR records"
log "Phase 4: Port Scan (critical services)"
PORTS="22 443 1812 3389 8443"
cat "$OUTDIR/live.txt" | xargs -P32 -I{} sh -c '
for p in '"$PORTS"'; do
timeout 0.3 nc -z {} $p 2>/dev/null && echo "{},${p}"
done
' > "$OUTDIR/ports.csv"
log " $(wc -l < "$OUTDIR/ports.csv") open ports"
log "Phase 5: Generate Report"
{
echo "# Infrastructure Audit Report"
echo "# Generated: $(date)"
echo "# Subnet: ${SUBNET}.0/24"
echo ""
echo "## Summary"
echo "- DNS Records: $(wc -l < "$OUTDIR/dns.csv")"
echo "- Live Hosts: $(wc -l < "$OUTDIR/live.txt")"
echo "- PTR Records: $(wc -l < "$OUTDIR/ptr.csv")"
echo "- Open Ports: $(wc -l < "$OUTDIR/ports.csv")"
echo ""
echo "## Host Inventory"
cat "$OUTDIR/live.txt" | while read ip; do
hostname=$(awk -F',' -v ip="$ip" '$1==ip{print $2; exit}' "$OUTDIR/ptr.csv")
ports=$(awk -F',' -v ip="$ip" '$1==ip{printf "%s ", $2}' "$OUTDIR/ports.csv")
printf "%-15s %-40s [%s]\n" "$ip" "${hostname:--}" "${ports:--}"
done
} > "$OUTDIR/report.txt"
log "Complete: $OUTDIR"
ls -la "$OUTDIR"
9. Quick Reference
| Pattern | Command |
|---|---|
Parallel ping (128 workers) |
|
Process substitution join |
|
Set difference (comm) |
|
awk associative arrays |
|
jq deep extraction |
|
Port matrix with pivot |
|
Parallel SSL cert grab |
|
Timed execution |
|