teoretično dela ane*, zdej u praksi pa neb vedu
*za A recorde, pa če je slučajn umes kkšn CNAME
This commit is contained in:
116
main.go
116
main.go
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"dnsthingymagik/cache"
|
||||
"dnsthingymagik/resolver"
|
||||
"fmt"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"log"
|
||||
@@ -15,95 +15,71 @@ func main() {
|
||||
}
|
||||
defer udpServer.Close()
|
||||
|
||||
rc := cache.NewRecordsCache()
|
||||
|
||||
for {
|
||||
buf := make([]byte, 514)
|
||||
n, addr, err := udpServer.ReadFrom(buf)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
go process(addr, buf[:n], rc)
|
||||
|
||||
//go response(udpServer, addr, buf)
|
||||
go process(udpServer, addr, buf[:n])
|
||||
}
|
||||
}
|
||||
|
||||
func process(addr net.Addr, buf []byte, rc *cache.RecordsCache) {
|
||||
var parser dnsmessage.Parser
|
||||
header, err := parser.Start(buf)
|
||||
func process(udp net.PacketConn, addr net.Addr, buf []byte) {
|
||||
msg, err := resolver.PacketParser(buf)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(header)
|
||||
|
||||
msg := dnsmessage.Message{
|
||||
Header: header,
|
||||
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)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
faq[q] = nips[0]
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
question, err := parser.Question()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(question)
|
||||
msg.Questions = append(msg.Questions, question)
|
||||
answers := []dnsmessage.Resource{}
|
||||
for _, q := range msg.Questions {
|
||||
answers = append(answers, dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: q.Name,
|
||||
Type: dnsmessage.TypeA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
TTL: 300, //TODO
|
||||
},
|
||||
Body: &dnsmessage.AResource{
|
||||
A: [4]byte{faq[q][0], faq[q][1], faq[q][2], faq[q][3]},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for {
|
||||
answer, err := parser.Answer()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(answer)
|
||||
msg.Answers = append(msg.Answers, answer)
|
||||
response := dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: msg.Header.ID,
|
||||
Response: true,
|
||||
OpCode: msg.Header.OpCode,
|
||||
Authoritative: false,
|
||||
RecursionDesired: msg.Header.RecursionDesired,
|
||||
RecursionAvailable: true,
|
||||
RCode: dnsmessage.RCodeSuccess,
|
||||
},
|
||||
Questions: msg.Questions,
|
||||
Answers: answers,
|
||||
}
|
||||
|
||||
for {
|
||||
authority, err := parser.Authority()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
fmt.Println(response)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(authority)
|
||||
msg.Authorities = append(msg.Authorities, authority)
|
||||
packed, err := response.Pack()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
for {
|
||||
additional, err := parser.Additional()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(additional)
|
||||
msg.Additionals = append(msg.Additionals, additional)
|
||||
_, err = udp.WriteTo(packed, addr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// MESSAGE IS FULL
|
||||
|
||||
fmt.Println(msg)
|
||||
|
||||
}
|
||||
|
||||
75
resolver/Packeter.go
Normal file
75
resolver/Packeter.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
)
|
||||
|
||||
func PacketParser(buf []byte) (dnsmessage.Message, error) {
|
||||
var parser dnsmessage.Parser
|
||||
header, err := parser.Start(buf)
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
}
|
||||
|
||||
msg := dnsmessage.Message{
|
||||
Header: header,
|
||||
}
|
||||
|
||||
for {
|
||||
question, err := parser.Question()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
}
|
||||
|
||||
fmt.Println(question)
|
||||
msg.Questions = append(msg.Questions, question)
|
||||
}
|
||||
|
||||
for {
|
||||
answer, err := parser.Answer()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
}
|
||||
|
||||
fmt.Println(answer)
|
||||
msg.Answers = append(msg.Answers, answer)
|
||||
}
|
||||
|
||||
for {
|
||||
authority, err := parser.Authority()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
}
|
||||
|
||||
fmt.Println(authority)
|
||||
msg.Authorities = append(msg.Authorities, authority)
|
||||
}
|
||||
|
||||
for {
|
||||
additional, err := parser.Additional()
|
||||
if err == dnsmessage.ErrSectionDone {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
}
|
||||
|
||||
msg.Additionals = append(msg.Additionals, additional)
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
95
resolver/Resolver.go
Normal file
95
resolver/Resolver.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"dnsthingymagik/resolver/query"
|
||||
"fmt"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ProcessDNSResponse(res dnsmessage.Message) ([]net.IP, []dnsmessage.Name, error) {
|
||||
if res.Header.RCode != dnsmessage.RCodeSuccess {
|
||||
return []net.IP{}, []dnsmessage.Name{}, fmt.Errorf("DNS q failed with RCode %d", res.Header.RCode)
|
||||
}
|
||||
|
||||
ips := []net.IP{}
|
||||
nameservers := []dnsmessage.Name{}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
for _, authority := range res.Authorities {
|
||||
if ns, ok := authority.Body.(*dnsmessage.NSResource); ok {
|
||||
nameservers = append(nameservers, ns.NS)
|
||||
}
|
||||
}
|
||||
return ips, nameservers, nil
|
||||
|
||||
}
|
||||
|
||||
func ResolveDN(domainName string, id uint16) ([]net.IP, error) {
|
||||
// TODO CACHE
|
||||
servers := []string{
|
||||
"198.41.0.4",
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(domainName, ".") {
|
||||
domainName = domainName + "."
|
||||
}
|
||||
|
||||
for {
|
||||
for _, server := range servers {
|
||||
q := dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: id,
|
||||
RecursionDesired: true,
|
||||
},
|
||||
Questions: []dnsmessage.Question{
|
||||
{
|
||||
Name: dnsmessage.MustNewName(domainName),
|
||||
Type: dnsmessage.TypeA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
res, err := query.SendQuery(server, q)
|
||||
if err != nil {
|
||||
return []net.IP{}, err
|
||||
}
|
||||
|
||||
ips, nameservers, err := ProcessDNSResponse(res)
|
||||
if err != nil {
|
||||
return []net.IP{}, err
|
||||
}
|
||||
|
||||
if len(ips) > 0 {
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
if len(nameservers) > 0 {
|
||||
newservers := []string{}
|
||||
for _, ns := range nameservers {
|
||||
nsIPs, err := ResolveDN(ns.String(), id)
|
||||
if err != nil {
|
||||
return []net.IP{}, err
|
||||
}
|
||||
|
||||
for _, nsIP := range nsIPs {
|
||||
newservers = append(newservers, nsIP.String())
|
||||
}
|
||||
}
|
||||
servers = newservers
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func sendQuery(server string, query dnsmessage.Message) (dnsmessage.Message, error) {
|
||||
func SendQuery(server string, query dnsmessage.Message) (dnsmessage.Message, error) {
|
||||
conn, err := net.DialTimeout("udp", server+":53", 5*time.Second)
|
||||
if err != nil {
|
||||
return dnsmessage.Message{}, err
|
||||
Reference in New Issue
Block a user