Files
dnstest/backend/internal/checker/www.go
robertas_stauskas a70f3262e0 Initial commit: DNS Test - DNS health checking tool
Go backend (miekg/dns) + Nuxt 3 frontend (Tailwind CSS v4).

8 check categories, 52 checks total:
- Overview: @ record, WWW, MX with ASN/provider lookup
- Domain Registration: expiry, registrar (RDAP + whois fallback)
- Parent Delegation: NS records, glue, consistency
- Nameservers: 17 checks (reachability, auth, recursion, TCP/UDP, AXFR, etc.)
- SOA: serial consistency, timing values
- Mail (MX): 11 checks (CNAME, PTR, public IPs, consistency)
- Mail Auth: SPF, DKIM, DMARC
- WWW: A record, CNAME

Features:
- SSE streaming (results appear as each category completes)
- SQLite history (modernc.org/sqlite)
- Rate limiting, CORS, request logging
- Dark mode, responsive design
2026-03-20 13:39:57 +02:00

106 lines
2.6 KiB
Go

package checker
import (
"fmt"
"net"
"strings"
"time"
"github.com/intodns/backend/internal/resolver"
"github.com/miekg/dns"
)
// checkWWW runs the 2 WWW checks.
func checkWWW(domain string, r *resolver.Resolver) Category {
cat := Category{Name: "www", Title: "WWW"}
domain = dns.Fqdn(domain)
wwwName := "www." + domain
// 1. www-a-record
cat.Checks = append(cat.Checks, checkWWWARecord(wwwName, r))
// 2. www-cname
cat.Checks = append(cat.Checks, checkWWWCNAME(wwwName, r))
return cat
}
func checkWWWARecord(wwwName string, r *resolver.Resolver) CheckResult {
start := time.Now()
res := CheckResult{ID: "www-a-record", Title: "WWW A Record"}
defer func() { res.DurationMs = measureDuration(start) }()
resp, err := r.Query(wwwName, "8.8.8.8", dns.TypeA)
if err != nil {
res.Status = StatusWarn
res.Message = fmt.Sprintf("Failed to query A record for %s: %v", wwwName, err)
return res
}
var ips []string
for _, rr := range resp.Answer {
if a, ok := rr.(*dns.A); ok {
ips = append(ips, a.A.String())
}
}
if len(ips) == 0 {
res.Status = StatusInfo
res.Message = fmt.Sprintf("No A record found for %s", wwwName)
return res
}
allPublic := true
for _, ipStr := range ips {
ip := net.ParseIP(ipStr)
if isPublicIP(ip) {
res.Details = append(res.Details, fmt.Sprintf("%s -> %s (public)", wwwName, ipStr))
} else {
allPublic = false
res.Details = append(res.Details, fmt.Sprintf("%s -> %s (NOT public)", wwwName, ipStr))
}
}
if allPublic {
res.Status = StatusPass
res.Message = fmt.Sprintf("%s has A record(s) with public IP(s)", wwwName)
} else {
res.Status = StatusWarn
res.Message = fmt.Sprintf("%s has A record(s) but some IPs are not public", wwwName)
}
return res
}
func checkWWWCNAME(wwwName string, r *resolver.Resolver) CheckResult {
start := time.Now()
res := CheckResult{ID: "www-cname", Title: "WWW CNAME"}
defer func() { res.DurationMs = measureDuration(start) }()
resp, err := r.Query(wwwName, "8.8.8.8", dns.TypeCNAME)
if err != nil {
res.Status = StatusInfo
res.Message = fmt.Sprintf("Could not check CNAME for %s", wwwName)
return res
}
var targets []string
for _, rr := range resp.Answer {
if cname, ok := rr.(*dns.CNAME); ok {
targets = append(targets, cname.Target)
}
}
if len(targets) > 0 {
res.Status = StatusInfo
res.Message = fmt.Sprintf("%s is a CNAME to %s", wwwName, strings.Join(targets, ", "))
for _, t := range targets {
res.Details = append(res.Details, fmt.Sprintf("CNAME target: %s", t))
}
} else {
res.Status = StatusInfo
res.Message = fmt.Sprintf("%s is not a CNAME (direct A/AAAA record)", wwwName)
}
return res
}