summaryrefslogtreecommitdiff
path: root/dnssecsocket
diff options
context:
space:
mode:
Diffstat (limited to 'dnssecsocket')
-rw-r--r--dnssecsocket/args.go44
-rw-r--r--dnssecsocket/connection_handler.go131
-rw-r--r--dnssecsocket/dnstrace.go168
-rw-r--r--dnssecsocket/log.go30
4 files changed, 373 insertions, 0 deletions
diff --git a/dnssecsocket/args.go b/dnssecsocket/args.go
new file mode 100644
index 0000000..cbd9fe7
--- /dev/null
+++ b/dnssecsocket/args.go
@@ -0,0 +1,44 @@
+package dnssecsocket
+
+//
+// By using the package "github.com/alexflint/go-arg",
+// these can be configured from the command line
+//
+
+import (
+ // arg "github.com/alexflint/go-arg"
+ // "log"
+ // "os"
+)
+
+type Args struct {
+ VerboseDnssec bool `arg:"--verbose-dnssec" help:"debug dnssec lookups"`
+ Foo string `arg:"env:USER"`
+}
+
+var args struct {
+ Args
+ Verbose bool
+}
+
+func Parse (b bool) {
+ args.Verbose = b
+ args.VerboseDnssec = b
+}
+
+// I attempted to pass the *arg.Parser down
+// to see if I could find the value somewhere but I couldn't find it
+/*
+var conf arg.Config
+
+func Parse (p *arg.Parser) {
+ // conf.Program = "control-panel-dns"
+ // conf.IgnoreEnv = false
+ // arg.NewParser(conf, &args)
+ log.Println("fuckit", p, args.VerboseDnssec)
+ for i, v := range p.SubcommandNames() {
+ log.Println("dnssec.Parse", i, v)
+ }
+ p.Jcarr()
+}
+*/
diff --git a/dnssecsocket/connection_handler.go b/dnssecsocket/connection_handler.go
new file mode 100644
index 0000000..8ccedaa
--- /dev/null
+++ b/dnssecsocket/connection_handler.go
@@ -0,0 +1,131 @@
+// inspired from:
+// https://github.com/mactsouk/opensource.com.git
+// and
+// https://coderwall.com/p/wohavg/creating-a-simple-tcp-server-in-go
+
+package dnssecsocket
+
+import "os"
+import "bufio"
+import "math/rand"
+import "net"
+import "strconv"
+import "strings"
+// import log "github.com/sirupsen/logrus"
+// import "github.com/wercker/journalhook"
+
+import "go.wit.com/shell"
+
+// will try to get this hosts FQDN
+// import "github.com/Showmax/go-fqdn"
+
+import "github.com/miekg/dns"
+
+// import "github.com/davecgh/go-spew/spew"
+
+const MIN = 1
+const MAX = 100
+
+func random() int {
+ return rand.Intn(MAX-MIN) + MIN
+}
+
+func GetRemoteAddr(conn net.TCPConn) string {
+ clientAddr := conn.RemoteAddr().String()
+ parts := strings.Split(clientAddr, "]")
+ ipv6 := parts[0]
+ return ipv6[1:]
+}
+
+//
+// Handle each connection
+// Each client must send it's hostname as the first line
+// Then each hostname is verified with DNSSEC
+//
+func HandleConnection(conn *net.TCPConn) {
+ // Disable journalhook until it builds on Windows
+ // journalhook.Enable()
+
+ // spew.Dump(conn)
+ // ipv6client := GetRemoteAddr(c)
+ ipv6client := conn.RemoteAddr()
+ log(args.VerboseDnssec, "Serving to %s as the IPv6 client", ipv6client)
+
+ // setup this TCP socket as the "standard input"
+ // newStdin, _ := bufio.NewReader(conn.File())
+ newStdin, _ := conn.File()
+ newreader := bufio.NewReader(newStdin)
+
+ log(args.VerboseDnssec, "Waiting for the client to tell me its name")
+ netData, err := newreader.ReadString('\n')
+ if err != nil {
+ log(args.VerboseDnssec, err)
+ return
+ }
+ clientHostname := strings.TrimSpace(netData)
+ log(args.VerboseDnssec, "Recieved client hostname as:", clientHostname)
+
+ dnsRR := Dnstrace(clientHostname, "AAAA")
+ if (dnsRR == nil) {
+ log(args.VerboseDnssec, "dnsRR IS NIL")
+ log(args.VerboseDnssec, "dnsRR IS NIL")
+ log(args.VerboseDnssec, "dnsRR IS NIL")
+ conn.Close()
+ return
+ }
+ ipaddr := dns.Field(dnsRR[1], 1)
+ log(args.VerboseDnssec, "Client claims to be: ", ipaddr)
+ log(args.VerboseDnssec, "Serving to IPv6 client:", ipv6client)
+
+/* TODO: figure out how to fix this check
+ if (ipaddr != ipv6client) {
+ log(args.VerboseDnssec)
+ log(args.VerboseDnssec, "DNSSEC ERROR: client IPv6 does not work")
+ log(args.VerboseDnssec, "DNSSEC ERROR: client IPv6 does not work")
+ log(args.VerboseDnssec, "DNSSEC ERROR: client IPv6 does not work")
+ log(args.VerboseDnssec)
+ conn.Close()
+ return
+ }
+*/
+
+ f, _ := conn.File()
+// shell.SetStdout(f)
+// shell.SpewOn() // turn this on if you want to look at the process exit states
+
+ // send all log() output to systemd journalctl
+// shell.UseJournalctl()
+
+ for {
+ defer shell.SetStdout(os.Stdout)
+ defer conn.Close()
+ netData, err := newreader.ReadString('\n')
+ if err != nil {
+ log(args.VerboseDnssec, err)
+ return
+ }
+
+ temp := strings.TrimSpace(string(netData))
+ if temp == "STOP" {
+ break
+ }
+ log(args.VerboseDnssec, "Recieved: ", temp)
+
+ if (temp == "list") {
+ log(args.VerboseDnssec, "Should run list here")
+ shell.SetStdout(f)
+ shell.Run("/root/bin/list.testing.com")
+ shell.SetStdout(os.Stdout)
+ }
+
+ if (temp == "cpuinfo") {
+ log(args.VerboseDnssec, "Should cat /proc/cpuinfo")
+ shell.SetStdout(f)
+ shell.Run("cat /proc/cpuinfo")
+ shell.SetStdout(os.Stdout)
+ }
+
+ result := strconv.Itoa(random()) + "\n"
+ conn.Write([]byte(string(result)))
+ }
+}
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()
+}
diff --git a/dnssecsocket/log.go b/dnssecsocket/log.go
new file mode 100644
index 0000000..6381899
--- /dev/null
+++ b/dnssecsocket/log.go
@@ -0,0 +1,30 @@
+package dnssecsocket
+
+import (
+ witlog "go.wit.com/gui/log"
+)
+
+// various debugging flags
+var logNow bool = true // useful for active development
+var logError bool = true
+var logWarn bool = false
+var logInfo bool = false
+var logVerbose bool = false
+
+var SPEW witlog.Spewt
+
+// var log interface{}
+
+func log(a ...any) {
+ witlog.Where = "wit/gui"
+ witlog.Log(a...)
+}
+
+func sleep(a ...any) {
+ witlog.Sleep(a...)
+}
+
+func exit(a ...any) {
+ log(logError, "got to log() exit")
+ witlog.Exit(a...)
+}