Files
dns-resolver/main.go
T

90 lines
1.9 KiB
Go

package main
import (
"fmt"
"github.com/andwati/dns-resolver/internal/dns"
"github.com/andwati/dns-resolver/internal/network"
"log"
)
func main() {
domain := "dns.google.com"
rootServer := "198.41.0.4:53"
ip, err := resolve(domain, rootServer)
if err != nil {
log.Fatalf("Failed to resolve %s: %v", domain, err)
}
fmt.Printf("Resolved %s to IP: %s\n", domain, ip)
}
func resolve(domain, nameServer string) (string, error) {
for {
fmt.Printf("Querying %s for %s\n", nameServer, domain)
header := dns.DNSHeader{
ID: dns.GenerateRandomID(),
Flags: 0,
QDCount: 1,
}
question := dns.DNSQuestion{
QName: domain,
QType: dns.QTypeA,
QClass: dns.QClassIN,
}
message := dns.DNSMessage{
Header: header,
Question: question,
}
query := message.Serialize()
response, err := network.SendDNSQuery(query, nameServer)
if err != nil {
return "", fmt.Errorf("failed to send query: %w", err)
}
answers, authorities, additionals, err := dns.ParseFullResponse(response)
if err != nil {
return "", fmt.Errorf("failed to parse response: %w", err)
}
for _, answer := range answers {
if answer.Type == dns.QTypeA {
return answer.Data, nil
}
if answer.Type == dns.QTypeCNAME {
domain = answer.Data
}
}
var nextNameServer string
for _, additional := range additionals {
if additional.Type == dns.QTypeA {
nextNameServer = additional.Data
break
}
}
if nextNameServer == "" && len(authorities) > 0 {
for _, authority := range authorities {
if authority.Type == dns.QTypeNS {
ns := authority.Data
nextNameServer, err = resolve(ns, "198.41.0.4:53") // Use root server for NS IP
if err == nil {
break
}
}
}
}
if nextNameServer == "" {
return "", fmt.Errorf("could not find next name server")
}
nameServer = nextNameServer + ":53"
}
}