From d53cd027aef464196c92946935108406b177a0c9 Mon Sep 17 00:00:00 2001 From: Mathijs van Mourick <14082160+mmourick@users.noreply.github.com> Date: Wed, 6 Mar 2024 09:10:15 +0100 Subject: [PATCH 1/3] feat: properly align displayed results --- cmd/root.go | 5 ++- go.mod | 7 +++- go.sum | 20 ++++++++++- pkg/core/core.go | 86 +++++++++++++++++++++++++--------------------- pkg/model/model.go | 7 ++++ 5 files changed, 82 insertions(+), 43 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 8683560..0aa60e2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -47,6 +47,7 @@ var ( queryTypes = core.FilterQueryTypes(queryTypes, flagStore.UserSpecifiedQueryType) } + var results []model.QueryResult // Send a DNS query for each query type in the queryTypes slice for _, queryType := range queryTypes { msg := core.PrepareDNSQuery(domainName, queryType.Type) @@ -55,9 +56,11 @@ var ( if err != nil { log.Fatal(err) } + results = append(results, model.QueryResult{QueryType: queryType, Records: response.Answer}) - core.DisplayRecords(domainName, queryType, response.Answer) } + // Print the results + core.DisplayRecords(domainName, results) }, } ) diff --git a/go.mod b/go.mod index 58a5223..40ffc87 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,15 @@ require ( github.com/spf13/cobra v1.8.0 ) -require golang.org/x/net v0.20.0 // indirect +require ( + github.com/lunixbochs/vtclean v1.0.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + golang.org/x/net v0.20.0 // indirect +) require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/juju/ansiterm v1.0.0 github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/sirupsen/logrus v1.9.3 diff --git a/go.sum b/go.sum index f67efe3..36b8843 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,20 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/juju/ansiterm v1.0.0 h1:gmMvnZRq7JZJx6jkfSq9/+2LMrVEwGwt7UR6G+lmDEg= +github.com/juju/ansiterm v1.0.0/go.mod h1:PyXUpnI3olx3bsPcHt98FGPX/KCFZ1Fi+hw1XLI6384= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mattn/go-colorable v0.1.10/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -23,14 +35,18 @@ github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyh github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -39,6 +55,8 @@ golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/core/core.go b/pkg/core/core.go index e83a511..21632d8 100644 --- a/pkg/core/core.go +++ b/pkg/core/core.go @@ -3,11 +3,14 @@ package core import ( "fmt" "net" + "os" "runtime" + "strconv" "time" model "github.com/bschaatsbergen/dnsee/pkg/model" "github.com/fatih/color" + "github.com/juju/ansiterm" "github.com/miekg/dns" "github.com/sirupsen/logrus" ) @@ -78,47 +81,50 @@ func SendDNSQuery(client *dns.Client, msg dns.Msg, dnsServerIP, dnsServerPort st return response, timeDuration, nil } -// DisplayRecords displays the DNS records returned by the DNS server. -func DisplayRecords(domainName string, queryType struct { - Type uint16 - Name string -}, answers []dns.RR) { - for _, ans := range answers { - switch queryType.Type { - case dns.TypeA: - if aRecord, ok := ans.(*dns.A); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(aRecord.Hdr.Ttl), aRecord.A) - } - case dns.TypeAAAA: - if aaaaRecord, ok := ans.(*dns.AAAA); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(aaaaRecord.Hdr.Ttl), aaaaRecord.AAAA) - } - case dns.TypeCNAME: - if cnameRecord, ok := ans.(*dns.CNAME); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(cnameRecord.Hdr.Ttl), cnameRecord.Target) - } - case dns.TypeMX: - if mxRecord, ok := ans.(*dns.MX); ok { - fmt.Printf("%s\t%s.\t%s\t%d\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(mxRecord.Hdr.Ttl), mxRecord.Preference, mxRecord.Mx) - } - case dns.TypeTXT: - if txtRecord, ok := ans.(*dns.TXT); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(txtRecord.Hdr.Ttl), txtRecord.Txt[0]) - } - case dns.TypeNS: - if nsRecord, ok := ans.(*dns.NS); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(nsRecord.Hdr.Ttl), nsRecord.Ns) - } - case dns.TypeSOA: - if soaRecord, ok := ans.(*dns.SOA); ok { - fmt.Printf("%s\t%s.\t%s\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(soaRecord.Hdr.Ttl), soaRecord.Ns, soaRecord.Mbox) - } - case dns.TypePTR: - if ptrRecord, ok := ans.(*dns.PTR); ok { - fmt.Printf("%s\t%s.\t%s\t%s\n", color.HiYellowString(queryType.Name), color.HiBlueString(domainName), FormatTTL(ptrRecord.Hdr.Ttl), ptrRecord.Ptr) +func DisplayRecords(domainName string, results []model.QueryResult) { + + w := ansiterm.NewTabWriter(os.Stdout, 8, 8, 1, ' ', 0) + w.SetColorCapable(true) + + for _, result := range results { + for _, record := range result.Records { + switch result.QueryType.Type { + case dns.TypeA: + if aRecord, ok := record.(*dns.A); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(aRecord.Hdr.Ttl)), color.HiWhiteString(aRecord.A.String())) + } + case dns.TypeAAAA: + if aaaaRecord, ok := record.(*dns.AAAA); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(aaaaRecord.Hdr.Ttl)), color.HiWhiteString(aaaaRecord.AAAA.String())) + } + case dns.TypeCNAME: + if cnameRecord, ok := record.(*dns.CNAME); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(cnameRecord.Hdr.Ttl)), color.HiWhiteString(cnameRecord.Target)) + } + case dns.TypeMX: + if mxRecord, ok := record.(*dns.MX); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t%s\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(mxRecord.Hdr.Ttl)), color.HiRedString(strconv.FormatUint(uint64(mxRecord.Preference), 10)), color.HiWhiteString(mxRecord.Mx)) + } + case dns.TypeTXT: + if txtRecord, ok := record.(*dns.TXT); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(txtRecord.Hdr.Ttl)), color.HiWhiteString(txtRecord.Txt[0])) + } + case dns.TypeNS: + if nsRecord, ok := record.(*dns.NS); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(nsRecord.Hdr.Ttl)), color.HiWhiteString(nsRecord.Ns)) + } + case dns.TypeSOA: + if soaRecord, ok := record.(*dns.SOA); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(soaRecord.Hdr.Ttl)), color.HiWhiteString(soaRecord.Ns), color.GreenString(soaRecord.Mbox)) + } + case dns.TypePTR: + if ptrRecord, ok := record.(*dns.PTR); ok { + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(ptrRecord.Hdr.Ttl)), color.HiWhiteString(ptrRecord.Ptr)) + } } } } + w.Flush() // Write table to stdout } func FormatTTL(ttl uint32) string { @@ -129,8 +135,8 @@ func FormatTTL(ttl uint32) string { if hours > 0 { return fmt.Sprintf("%02dh%02dm%02ds", hours, minutes, seconds) } else if minutes > 0 { - return fmt.Sprintf("%02dm%02ds ", minutes, seconds) + return fmt.Sprintf("%02dm%02ds", minutes, seconds) } else { - return fmt.Sprintf("%02ds ", seconds) + return fmt.Sprintf("%02ds", seconds) } } diff --git a/pkg/model/model.go b/pkg/model/model.go index 55dda22..943f515 100644 --- a/pkg/model/model.go +++ b/pkg/model/model.go @@ -1,6 +1,13 @@ package model +import "github.com/miekg/dns" + type QueryType struct { Type uint16 Name string } + +type QueryResult struct { + QueryType QueryType + Records []dns.RR +} From 6c91773b57f13ccd63e0e0d020edec0763f66364 Mon Sep 17 00:00:00 2001 From: Mathijs van Mourick <14082160+mmourick@users.noreply.github.com> Date: Wed, 6 Mar 2024 09:42:41 +0100 Subject: [PATCH 2/3] chore: increase spacing between columns --- pkg/core/core.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/core.go b/pkg/core/core.go index 21632d8..bf37ebb 100644 --- a/pkg/core/core.go +++ b/pkg/core/core.go @@ -83,7 +83,7 @@ func SendDNSQuery(client *dns.Client, msg dns.Msg, dnsServerIP, dnsServerPort st func DisplayRecords(domainName string, results []model.QueryResult) { - w := ansiterm.NewTabWriter(os.Stdout, 8, 8, 1, ' ', 0) + w := ansiterm.NewTabWriter(os.Stdout, 8, 8, 4, ' ', 0) w.SetColorCapable(true) for _, result := range results { From 3325c44a246e2f30a3fecf808e2ae7b4c3776dc9 Mon Sep 17 00:00:00 2001 From: Mathijs van Mourick <14082160+mmourick@users.noreply.github.com> Date: Wed, 6 Mar 2024 09:43:06 +0100 Subject: [PATCH 3/3] feat: concat priority and record for MX records --- pkg/core/core.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/core/core.go b/pkg/core/core.go index bf37ebb..479dabd 100644 --- a/pkg/core/core.go +++ b/pkg/core/core.go @@ -6,6 +6,7 @@ import ( "os" "runtime" "strconv" + "strings" "time" model "github.com/bschaatsbergen/dnsee/pkg/model" @@ -103,7 +104,7 @@ func DisplayRecords(domainName string, results []model.QueryResult) { } case dns.TypeMX: if mxRecord, ok := record.(*dns.MX); ok { - fmt.Fprintf(w, "%s\t%s.\t%s\t%s\t%s\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(mxRecord.Hdr.Ttl)), color.HiRedString(strconv.FormatUint(uint64(mxRecord.Preference), 10)), color.HiWhiteString(mxRecord.Mx)) + fmt.Fprintf(w, "%s\t%s.\t%s\t%s\n", color.HiYellowString(result.QueryType.Name), color.HiBlueString(domainName), color.HiMagentaString(FormatTTL(mxRecord.Hdr.Ttl)), strings.Join([]string{color.HiRedString(strconv.FormatUint(uint64(mxRecord.Preference), 10)), color.HiWhiteString(mxRecord.Mx)}, " ")) } case dns.TypeTXT: if txtRecord, ok := record.(*dns.TXT); ok {