summaryrefslogtreecommitdiff
path: root/dnssecsocket/dnstrace.go
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2023-12-20 15:12:26 -0600
committerJeff Carr <[email protected]>2023-12-20 15:12:26 -0600
commit379fee6d963fe33b798676fd96955ad1c51a3027 (patch)
tree5f559caa405d0fe895e03c78acfe81184732d191 /dnssecsocket/dnstrace.go
parent382cc8dd171731cc333dd05b7b0b798340162a32 (diff)
rename to go.wit.com/control-panel-dnsv0.2.0
Signed-off-by: Jeff Carr <[email protected]>
Diffstat (limited to 'dnssecsocket/dnstrace.go')
-rw-r--r--dnssecsocket/dnstrace.go168
1 files changed, 168 insertions, 0 deletions
diff --git a/dnssecsocket/dnstrace.go b/dnssecsocket/dnstrace.go
new file mode 100644
index 0000000..d8fca38
--- /dev/null
+++ b/dnssecsocket/dnstrace.go
@@ -0,0 +1,168 @@
+package dnssecsocket
+
+// inspired from github.com/rs/dnstrace/main.go
+
+import "fmt"
+import "net"
+// import "os"
+import "strings"
+import "time"
+
+import "github.com/miekg/dns"
+import "github.com/rs/dnstrace/client"
+
+// import log "github.com/sirupsen/logrus"
+
+// this is cool, but breaks the Windows build
+// import "github.com/wercker/journalhook"
+
+// import "github.com/davecgh/go-spew/spew"
+
+const (
+ cReset = 0
+ cBold = 1
+ cRed = 31
+ cGreen = 32
+ cYellow = 33
+ cBlue = 34
+ cMagenta = 35
+ cCyan = 36
+ cGray = 37
+ cDarkGray = 90
+)
+
+func colorize(s interface{}, color int, enabled bool) string {
+ if !enabled {
+ return fmt.Sprintf("%v", s)
+ }
+ return fmt.Sprintf("\x1b[%dm%v\x1b[0m", color, s)
+}
+
+func Dnstrace(hostname string, qtypestr string) []dns.RR {
+ // color := flag.Bool("color", true, "Enable/disable colors")
+ color := true
+
+ qname := dns.Fqdn(hostname)
+ // qtype := dns.TypeA
+ qtype := dns.StringToType[qtypestr]
+
+ col := func(s interface{}, c int) string {
+ return colorize(s, c, color)
+ }
+
+ m := &dns.Msg{}
+ m.SetQuestion(qname, qtype)
+ // Set DNSSEC opt to better emulate the default queries from a nameserver.
+ o := &dns.OPT{
+ Hdr: dns.RR_Header{
+ Name: ".",
+ Rrtype: dns.TypeOPT,
+ },
+ }
+ o.SetDo()
+ o.SetUDPSize(dns.DefaultMsgSize)
+ m.Extra = append(m.Extra, o)
+
+ c := client.New(1)
+ c.Client.Timeout = 500 * time.Millisecond
+ t := client.Tracer{
+ GotIntermediaryResponse: func(i int, m *dns.Msg, rs client.Responses, rtype client.ResponseType) {
+ fr := rs.Fastest()
+ var r *dns.Msg
+ if fr != nil {
+ r = fr.Msg
+ }
+ qname := m.Question[0].Name
+ qtype := dns.TypeToString[m.Question[0].Qtype]
+ if i > 1 {
+ log(args.VerboseDnssec)
+ }
+ log(args.VerboseDnssec, "%d - query %s %s", i, qtype, qname)
+ if r != nil {
+ log(args.VerboseDnssec, ": %s", strings.Replace(strings.Replace(r.MsgHdr.String(), ";; ", "", -1), "\n", ", ", -1))
+ }
+ log(args.VerboseDnssec)
+ for _, pr := range rs {
+ ln := 0
+ if pr.Msg != nil {
+ ln = pr.Msg.Len()
+ }
+ rtt := float64(pr.RTT) / float64(time.Millisecond)
+ lrtt := "0ms (from cache)"
+ if pr.Server.HasGlue {
+ lrtt = "0ms (from glue)"
+ } else if pr.Server.LookupRTT > 0 {
+ lrtt = fmt.Sprintf("%.2fms", float64(pr.Server.LookupRTT)/float64(time.Millisecond))
+ }
+ log(args.VerboseDnssec, col(" - %d bytes in %.2fms + %s lookup on %s(%s)", cDarkGray), ln, rtt, lrtt, pr.Server.Name, pr.Addr)
+ if pr.Err != nil {
+ err := pr.Err
+ if oerr, ok := err.(*net.OpError); ok {
+ err = oerr.Err
+ }
+ log(args.VerboseDnssec, ": %v", col(err, cRed))
+ }
+ log(args.VerboseDnssec, "\n")
+ }
+
+ switch rtype {
+ case client.ResponseTypeDelegation:
+ var label string
+ for _, rr := range r.Ns {
+ if ns, ok := rr.(*dns.NS); ok {
+ label = ns.Header().Name
+ break
+ }
+ }
+ _, ns := c.DCache.Get(label)
+ for _, s := range ns {
+ var glue string
+ if s.HasGlue {
+ glue = col("glue: "+strings.Join(s.Addrs, ","), cDarkGray)
+ } else {
+ glue = col("no glue", cYellow)
+ }
+ log(args.VerboseDnssec, "%s %d NS %s (%s)\n", label, s.TTL, s.Name, glue)
+ }
+ case client.ResponseTypeCNAME:
+ for _, rr := range r.Answer {
+ log(args.VerboseDnssec, rr)
+ }
+ }
+ },
+ FollowingCNAME: func(domain, target string) {
+ log(args.VerboseDnssec, col("\n~ following CNAME %s -> %s\n", cBlue), domain, target)
+ },
+ }
+ r, rtt, err := c.RecursiveQuery(m, t)
+ if err != nil {
+ log(args.VerboseDnssec, col("*** error: %v\n", cRed), err)
+ return nil
+ }
+
+ log(args.VerboseDnssec)
+ log(args.VerboseDnssec, col(";; Cold best path time: %s\n\n", cGray), rtt)
+ for i, rr := range r.Answer {
+ log(args.VerboseDnssec, "r.Answer =", i, rr, args.VerboseDnssec)
+ }
+ return r.Answer
+ // for _, rr := range r.Answer {
+ // return rr
+ // }
+ // return nil
+}
+
+func ResolveIPv6hostname(hostname string) *net.TCPAddr {
+ dnsRR := Dnstrace(hostname, "AAAA")
+ if (dnsRR == nil) {
+ return nil
+ }
+ aaaa := dns.Field(dnsRR[1], 1)
+ localTCPAddr, _ := net.ResolveTCPAddr("tcp", aaaa)
+ return localTCPAddr
+}
+
+func UseJournalctl() {
+ log(args.VerboseDnssec, "journalhook is disabled because it breaks the Windows build right now")
+ // journalhook.Enable()
+}