dela za google.com ¯\_(ツ)_/¯ ne pa za govekar.net ker so nameserverji drug tld

This commit is contained in:
LovroG05
2025-03-11 11:11:34 +01:00
parent 754ca37f6f
commit 1f97121585
2 changed files with 98 additions and 32 deletions

18
main.go
View File

@@ -34,16 +34,30 @@ func process(udp net.PacketConn, addr net.Addr, buf []byte) {
faq := map[dnsmessage.Question]net.IP{}
for _, q := range msg.Questions {
if q.Type == dnsmessage.TypeA {
nips, err := resolver.ResolveDN(q.Name.String(), msg.Header.ID)
nips, err := resolver.ResolveDN(q.Name.String(), msg.Header.ID, dnsmessage.TypeA)
if err != nil {
log.Println(err)
}
if len(nips) == 0 {
log.Printf("No IP found for %s", q.Name.String())
continue
}
faq[q] = nips[0]
}
}
answers := []dnsmessage.Resource{}
for _, q := range msg.Questions {
ip, found := faq[q]
if !found {
log.Printf("No answer for %s, skipping...", q.Name.String())
continue
}
fmt.Println(ip)
answers = append(answers, dnsmessage.Resource{
Header: dnsmessage.ResourceHeader{
Name: q.Name,
@@ -52,7 +66,7 @@ func process(udp net.PacketConn, addr net.Addr, buf []byte) {
TTL: 300, //TODO
},
Body: &dnsmessage.AResource{
A: [4]byte{faq[q][0], faq[q][1], faq[q][2], faq[q][3]},
A: [4]byte{ip[0], ip[1], ip[2], ip[3]},
},
})
}

View File

@@ -8,54 +8,81 @@ import (
"strings"
)
func ProcessDNSResponse(res dnsmessage.Message) ([]net.IP, []dnsmessage.Name, error) {
func ProcessDNSResponse(res dnsmessage.Message) ([]net.IP, []dnsmessage.Resource, map[string]net.IP, string, error) {
if res.Header.RCode != dnsmessage.RCodeSuccess {
return []net.IP{}, []dnsmessage.Name{}, fmt.Errorf("DNS q failed with RCode %d", res.Header.RCode)
return []net.IP{}, []dnsmessage.Resource{}, make(map[string]net.IP), "", fmt.Errorf("DNS q failed with RCode %d", res.Header.RCode)
}
ips := []net.IP{}
nameservers := []dnsmessage.Name{}
nameservers := []dnsmessage.Resource{}
nsIPMap := make(map[string]net.IP)
var cnameTarget string
for _, ans := range res.Answers {
switch ans.Header.Type {
case dnsmessage.TypeA:
ips = append(ips, ans.Body.(*dnsmessage.AResource).A[:])
case dnsmessage.TypeCNAME:
cname := ans.Body.(*dnsmessage.CNAMEResource).CNAME
nameservers = append(nameservers, cname)
cnameTarget = ans.Body.(*dnsmessage.CNAMEResource).CNAME.String()
}
}
for _, authority := range res.Authorities {
if ns, ok := authority.Body.(*dnsmessage.NSResource); ok {
nameservers = append(nameservers, ns.NS)
if _, ok := authority.Body.(*dnsmessage.NSResource); ok {
nameservers = append(nameservers, authority)
}
if a, ok := authority.Body.(*dnsmessage.AResource); ok {
nsIPMap[authority.Header.Name.String()] = net.IP(a.A[:])
}
}
return ips, nameservers, nil
for _, additional := range res.Additionals {
if additional.Header.Type == dnsmessage.TypeA {
nsName := additional.Header.Name.String()
nsIP := additional.Body.(*dnsmessage.AResource).A[:]
nsIPMap[nsName] = nsIP
}
}
return ips, nameservers, nsIPMap, cnameTarget, nil
}
func ResolveDN(domainName string, id uint16) ([]net.IP, error) {
// TODO CACHE
servers := []string{
"198.41.0.4",
func ResolveDN(domainName string, id uint16, rtype dnsmessage.Type) ([]net.IP, error) {
return resolveRecursive(domainName, id, rtype, 0, map[string]bool{})
}
func resolveRecursive(domainName string, id uint16, rtype dnsmessage.Type, depth int, queriedNS map[string]bool) ([]net.IP, error) {
if depth > 5 {
return nil, fmt.Errorf("maximum recursion depth reached for %s", domainName)
}
servers := []string{"198.41.0.4"} // Root server
if !strings.HasSuffix(domainName, ".") {
domainName = domainName + "."
domainName += "."
}
for {
var nextServers []string
queryFailed := true // Track if all queries fail
for _, server := range servers {
if queriedNS[server] {
continue // Don't re-query same NS
}
queriedNS[server] = true
q := dnsmessage.Message{
Header: dnsmessage.Header{
ID: id,
RecursionDesired: true,
RecursionDesired: false, // Ensure we don't depend on external recursion
},
Questions: []dnsmessage.Question{
{
Name: dnsmessage.MustNewName(domainName),
Type: dnsmessage.TypeA,
Type: rtype,
Class: dnsmessage.ClassINET,
},
},
@@ -63,33 +90,58 @@ func ResolveDN(domainName string, id uint16) ([]net.IP, error) {
res, err := query.SendQuery(server, q)
if err != nil {
return []net.IP{}, err
fmt.Printf("Query to %s failed: %v\n", server, err)
continue // Try next server
}
ips, nameservers, err := ProcessDNSResponse(res)
ips, nameservers, nsIPmap, cnameTarget, err := ProcessDNSResponse(res)
if err != nil {
return []net.IP{}, err
fmt.Printf("Error processing response: %v\n", err)
continue
}
if len(ips) > 0 {
return ips, nil
return ips, nil // Success
}
if len(nameservers) > 0 {
newservers := []string{}
for _, ns := range nameservers {
nsIPs, err := ResolveDN(ns.String(), id)
if err != nil {
return []net.IP{}, err
}
if cnameTarget != "" {
fmt.Printf("Following CNAME: %s → %s\n", domainName, cnameTarget)
return resolveRecursive(cnameTarget, id, rtype, depth+1, queriedNS)
}
for _, nsIP := range nsIPs {
newservers = append(newservers, nsIP.String())
}
for _, ns := range nameservers {
nsDomain := ns.Body.(*dnsmessage.NSResource).NS.String()
// Check for glue records
if nsIP, found := nsIPmap[nsDomain]; found {
fmt.Printf("Using glue record: %s → %s\n", nsDomain, nsIP)
nextServers = append(nextServers, nsIP.String())
continue
}
servers = newservers
// Resolve NS name to IP
fmt.Printf("Resolving NS: %s\n", nsDomain)
nsIPs, err := resolveRecursive(nsDomain, id, dnsmessage.TypeA, depth+1, queriedNS)
if err != nil {
fmt.Printf("Failed to resolve NS %s: %v\n", nsDomain, err)
continue
}
for _, nsIP := range nsIPs {
fmt.Printf("Resolved NS %s → %s\n", nsDomain, nsIP)
nextServers = append(nextServers, nsIP.String())
}
}
if len(nextServers) > 0 {
servers = nextServers
queryFailed = false
break
}
}
if len(nextServers) == 0 || queryFailed {
return nil, fmt.Errorf("failed to resolve %s", domainName)
}
}
}