diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | cloudflare/api.go | 26 | ||||
| -rw-r--r-- | cloudflare/durationSlider.go | 2 | ||||
| -rw-r--r-- | cloudflare/http.go | 49 | ||||
| -rw-r--r-- | cloudflare/mainWindow.go | 3 | ||||
| -rw-r--r-- | cloudflare/oneLiner.go | 42 | ||||
| -rw-r--r-- | cloudflare/rr.go (renamed from cloudflare/cloudflare.go) | 83 | ||||
| -rw-r--r-- | cloudflare/structs.go | 2 | ||||
| -rw-r--r-- | dns-https.go | 62 | ||||
| -rw-r--r-- | dnsLookupStatus.go | 370 | ||||
| -rw-r--r-- | examples/control-panel-cloudflare/Makefile (renamed from examples/cloudflare/Makefile) | 8 | ||||
| -rw-r--r-- | examples/control-panel-cloudflare/argv.go (renamed from examples/cloudflare/argv.go) | 0 | ||||
| -rw-r--r-- | examples/control-panel-cloudflare/config.go (renamed from examples/cloudflare/config.go) | 0 | ||||
| -rw-r--r-- | examples/control-panel-cloudflare/main.go (renamed from examples/cloudflare/main.go) | 16 | ||||
| -rw-r--r-- | go.mod | 39 | ||||
| -rw-r--r-- | go.sum | 88 | ||||
| -rw-r--r-- | gui.go | 114 | ||||
| -rw-r--r-- | hostname.go | 57 | ||||
| -rw-r--r-- | main.go | 27 | ||||
| -rw-r--r-- | net.go | 6 | ||||
| -rw-r--r-- | structs.go | 4 |
22 files changed, 853 insertions, 148 deletions
@@ -4,4 +4,4 @@ control-panel-dns *.swp /plugins/* -examples/cloudflare/cloudflare +examples/control-panel-cloudflare/control-panel-cloudflare @@ -21,6 +21,7 @@ to update the DNS server. Useful links and other external things which might be useful +* [DNS Resource Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types) * [WIT GO projects](http://go.wit.com/) * [GOLANG GUI](https://go.wit.com/gui) * [GO Style Guide](https://google.github.io/styleguide/go/index) diff --git a/cloudflare/api.go b/cloudflare/api.go index 1769f6b..036adc7 100644 --- a/cloudflare/api.go +++ b/cloudflare/api.go @@ -10,11 +10,20 @@ import ( "github.com/davecgh/go-spew/spew" ) +/* + This function should run each time + the user chanegs anything in the GUi + or each time something in general changes + + It returns a RR record which then can be + turned into JSON and sent via http + to cloudflare's API +*/ func DoChange() *RRT { var dnsRow *RRT dnsRow = new(RRT) - log.Println("Look for changes in row", dnsRow.ID) + log.Println("DoChange() START") if (CFdialog.proxyNode.S == "On") { dnsRow.Proxied = true } else { @@ -88,21 +97,6 @@ func SetRow(dnsRow *RRT) { log.Println("http PUT curl =", pretty) CFdialog.curlNode.SetText(pretty) } - - return - log.Println("UPDATE VALUE", CFdialog.NameNode.Name, CFdialog.TypeNode.Name, "to", CFdialog.ValueNode.S) - stuff, result := httpPut(dnsRow) - if (CFdialog.curlNode != nil) { - pretty, _ := FormatJSON(stuff) - log.Println("http PUT curl =", pretty) - CFdialog.curlNode.SetText(pretty) - } - if (CFdialog.resultNode != nil) { - pretty, _ := FormatJSON(result) - log.Println("http PUT result =", pretty) - CFdialog.resultNode.SetText(pretty) - } - // CFdialog.saveNode.Disable() } func GetZonefile(c *ConfigT) *DNSRecords { diff --git a/cloudflare/durationSlider.go b/cloudflare/durationSlider.go index 0d9559b..1ab0e50 100644 --- a/cloudflare/durationSlider.go +++ b/cloudflare/durationSlider.go @@ -9,6 +9,8 @@ import ( "go.wit.com/gui" ) +// TODO: use: https://github.com/robfig/cron/ + // ttl := cloudflare.DurationSlider(g2, "control panel TTL (in tenths of seconds)", 10 * time.Millisecond, 5 * time.Second) // ttl.Set(200 * time.Millisecond) diff --git a/cloudflare/http.go b/cloudflare/http.go index f258f61..1917c8b 100644 --- a/cloudflare/http.go +++ b/cloudflare/http.go @@ -3,7 +3,6 @@ package cloudflare import ( "log" - "fmt" "io/ioutil" "net/http" "bytes" @@ -27,45 +26,43 @@ curl --request POST \ }' */ -func httpPut(dnsRow *RRT) (string, string) { - var url string = cloudflareURL + dnsRow.ZoneID + "/dns_records/" + dnsRow.ID - var authKey string = dnsRow.Auth - var email string = dnsRow.Email - - var tmp string - tmp = makeJSON(dnsRow) - data := []byte(tmp) +func doCurl(method string, rr *RRT) string { + var err error + var req *http.Request - log.Println("http PUT url =", url) - // log.Println("http PUT data =", data) - // spew.Dump(data) - pretty, _ := FormatJSON(string(data)) - log.Println("http PUT data =", pretty) + data := []byte(rr.data) - req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(data)) + if (method == "PUT") { + req, err = http.NewRequest(http.MethodPut, rr.url, bytes.NewBuffer(data)) + } else { + req, err = http.NewRequest(http.MethodPost, rr.url, bytes.NewBuffer(data)) + } // Set headers req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-Auth-Key", authKey) - req.Header.Set("X-Auth-Email", email) + req.Header.Set("X-Auth-Key", rr.Auth) + req.Header.Set("X-Auth-Email", rr.Email) + + log.Println("http PUT url =", rr.url) + log.Println("http PUT Auth =", rr.Auth) + log.Println("http PUT Email =", rr.Email) + log.Println("http PUT data =", rr.data) client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) - return tmp, fmt.Sprintf("blah err =", err) + return "" } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Println(err) - return tmp, fmt.Sprintf("blah err =", err) + return "" } - // log.Println("http PUT body =", body) - // spew.Dump(body) - return tmp, string(body) + return string(body) } func curlPost(dnsRow *RRT) string { @@ -75,10 +72,10 @@ func curlPost(dnsRow *RRT) string { url := dnsRow.url tmp := dnsRow.data - log.Println("curl() START") - log.Println("curl() authkey = ", authKey) - log.Println("curl() email = ", email) - log.Println("curl() url = ", url) + log.Println("curlPost() START") + log.Println("curlPost() authkey = ", authKey) + log.Println("curlPost() email = ", email) + log.Println("curlPost() url = ", url) data := []byte(tmp) req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data)) diff --git a/cloudflare/mainWindow.go b/cloudflare/mainWindow.go index dddb0b7..af5b221 100644 --- a/cloudflare/mainWindow.go +++ b/cloudflare/mainWindow.go @@ -9,7 +9,7 @@ import ( ) // This creates a window -func MakeCloudflareWindow(n *gui.Node) { +func MakeCloudflareWindow(n *gui.Node) *gui.Node { CFdialog.rootGui = n var t *gui.Node @@ -54,6 +54,7 @@ func MakeCloudflareWindow(n *gui.Node) { showCloudflareCredentials(more) makeDebugWindow(CFdialog.mainWindow) + return CFdialog.mainWindow } func makeConfigWindow(n *gui.Node) { diff --git a/cloudflare/oneLiner.go b/cloudflare/oneLiner.go new file mode 100644 index 0000000..5fc7a51 --- /dev/null +++ b/cloudflare/oneLiner.go @@ -0,0 +1,42 @@ +// This is a simple example +package cloudflare + +import ( + "log" + + "go.wit.com/gui" +) + +type OneLiner struct { + p *gui.Node // parent widget + l *gui.Node // label widget + v *gui.Node // value widget + + value string + label string + + Custom func() +} + +func (n *OneLiner) Set(value string) { + log.Println("OneLiner.Set() =", value) + n.v.Set(value) + n.value = value +} + +func NewOneLiner(n *gui.Node, name string) *OneLiner { + d := OneLiner { + p: n, + value: "", + } + + // various timeout settings + d.l = n.NewLabel(name) + d.v = n.NewLabel("") + d.v.Custom = func() { + d.value = d.v.S + log.Println("OneLiner.Custom() user changed value to =", d.value) + } + + return &d +} diff --git a/cloudflare/cloudflare.go b/cloudflare/rr.go index db98c92..05065b2 100644 --- a/cloudflare/cloudflare.go +++ b/cloudflare/rr.go @@ -1,4 +1,9 @@ -// This is a simple example +/* + This will let you edit a single Resource Record within + a DNS zone file. For example: + google-dns.wit.com. 1 IN A 8.8.8.8 +*/ + package cloudflare import ( @@ -110,7 +115,7 @@ func CreateRR(myGui *gui.Node, zone string, zoneID string) { CFdialog.resultNode = group.NewTextbox("result") CFdialog.resultNode.SetText("API response will show here") - CFdialog.saveNode = group.NewButton("Save", func () { + CFdialog.SaveNode = group.NewButton("Save curlPost()", func () { dnsRow := DoChange() result := curlPost(dnsRow) CFdialog.resultNode.SetText(result) @@ -120,63 +125,33 @@ func CreateRR(myGui *gui.Node, zone string, zoneID string) { // CFdialog.resultNode.SetText(result) }) // CFdialog.saveNode.Disable() + group.NewButton("New RR doCurl(PUT)", func () { + rr := DoChange() - group.Pad() - grid.Pad() - grid.Expand() -} + rr.url = "https://api.cloudflare.com/client/v4/zones/" + rr.ZoneID + "/dns_records" -/* -func CreateCurlRR() (string, string) { - // enable the Save/Create Button - if (CFdialog.saveNode != nil) { - CFdialog.saveNode.Enable() - } + result := doCurl("POST", rr) + CFdialog.resultNode.SetText(result) - if (CFdialog.TypeNode != nil) { - CFdialog.Type = CFdialog.TypeNode.S - } - if (CFdialog.NameNode != nil) { - CFdialog.Name = CFdialog.NameNode.S - } - if (CFdialog.proxyNode != nil) { - if (CFdialog.proxyNode.S == "On") { - CFdialog.ProxyS = "true" - } else { - CFdialog.ProxyS = "false" - } - } - if (CFdialog.ValueNode != nil) { - CFdialog.Content = CFdialog.ValueNode.S - } - CFdialog.Ttl = "3600" + pretty, _ := FormatJSON(result) + log.Println(pretty) + }) - var url string = "https://api.cloudflare.com/client/v4/zones/" + CFdialog.ID + "/dns_records" - // https://api.cloudflare.com/client/v4/zones/zone_identifier/dns_records \ - // var authKey string = os.Getenv("CF_API_KEY") - // var email string = os.Getenv("CF_API_EMAIL") + group.NewButton("Update RR doCurl(PUT)", func () { + rr := DoChange() - // make a json record to send on port 80 to cloudflare - var tmp string - tmp = `{"content": "` + CFdialog.Content + `", ` - tmp += `"name": "` + CFdialog.Name + `", ` - tmp += `"type": "` + CFdialog.Type + `", ` - tmp += `"ttl": ` + CFdialog.Ttl + `, ` - tmp += `"proxied": ` + CFdialog.ProxyS + `, ` - tmp += `"comment": "WIT DNS Control Panel"` - tmp += `}` - data := []byte(tmp) + rr.url = "https://api.cloudflare.com/client/v4/zones/" + rr.ZoneID + "/dns_records/" + rr.ID + + result := doCurl("PUT", rr) + CFdialog.resultNode.SetText(result) + + pretty, _ := FormatJSON(result) + log.Println(pretty) + }) + // CFdialog.saveNode.Disable() - log.Println("http PUT url =", url) - // log.Println("http PUT data =", data) - // spew.Dump(data) - pretty, _ := FormatJSON(string(data)) - log.Println("http URL =", url) - log.Println("http PUT data =", pretty) - if (CFdialog.curlNode != nil) { - CFdialog.curlNode.SetText("URL: " + url + "\n" + pretty) - } - return url, tmp + group.Pad() + grid.Pad() + grid.Expand() } -*/ diff --git a/cloudflare/structs.go b/cloudflare/structs.go index f0a23d8..9efef62 100644 --- a/cloudflare/structs.go +++ b/cloudflare/structs.go @@ -50,7 +50,7 @@ type dialogT struct { ttlNode *gui.Node // just set to 1 which means automatic to cloudflare curlNode *gui.Node // shows you what you could run via curl resultNode *gui.Node // what the cloudflare API returned - saveNode *gui.Node // button to send it to cloudflare + SaveNode *gui.Node // button to send it to cloudflare zoneNode *gui.Node // "wit.com" zoneIdNode *gui.Node // cloudflare zone ID diff --git a/dns-https.go b/dns-https.go new file mode 100644 index 0000000..00eec82 --- /dev/null +++ b/dns-https.go @@ -0,0 +1,62 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +// dnsLookupDoH performs a DNS lookup for AAAA records over HTTPS. +func dnsLookupDoH(domain string) ([]string, error) { + var ipv6Addresses []string + + // Construct the URL for a DNS query with Google's DNS-over-HTTPS API + url := fmt.Sprintf("https://dns.google/resolve?name=%s&type=AAAA", domain) + + // Perform the HTTP GET request + resp, err := http.Get(url) + if err != nil { + return nil, fmt.Errorf("error performing DNS-over-HTTPS request: %w", err) + } + defer resp.Body.Close() + + // Read and unmarshal the response body + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("error reading response: %w", err) + } + + var data struct { + Answer []struct { + Data string `json:"data"` + } `json:"Answer"` + } + + if err := json.Unmarshal(body, &data); err != nil { + return nil, fmt.Errorf("error unmarshaling response: %w", err) + } + + // Extract the IPv6 addresses + for _, answer := range data.Answer { + ipv6Addresses = append(ipv6Addresses, answer.Data) + } + + return ipv6Addresses, nil +} + +/* +func main() { + domain := "google.com" + ipv6Addresses, err := dnsLookupDoH(domain) + if err != nil { + fmt.Println("Error:", err) + return + } + + fmt.Printf("IPv6 Addresses for %s:\n", domain) + for _, addr := range ipv6Addresses { + fmt.Println(addr) + } +} +*/ diff --git a/dnsLookupStatus.go b/dnsLookupStatus.go new file mode 100644 index 0000000..e623cae --- /dev/null +++ b/dnsLookupStatus.go @@ -0,0 +1,370 @@ +/* + 'dig' + + This is essentially doing what the command 'dig' does + It performing DNS queries on TCP and UDP + against localhost, cloudflare & google + + IPv4() and IPv6() return true if they are working + + with the 'gui' package, it can also display the results +*/ + +package main + +import ( + "log" + "fmt" + "time" + "strconv" + + "github.com/miekg/dns" + "go.wit.com/gui" + "go.wit.com/control-panel-dns/cloudflare" + "go.wit.com/shell" +) + +type digStatus struct { + ready bool + statusIPv4 string + statusIPv6 string + + parent *gui.Node + window *gui.Node + group *gui.Node + grid *gui.Node + box *gui.Node + + summary *gui.Node + status *cloudflare.OneLiner + statusAAAA *cloudflare.OneLiner + speed *cloudflare.OneLiner + speedActual *cloudflare.OneLiner + + details *gui.Node + dsLocalhost *dnsStatus + dsLocalNetwork *dnsStatus + dsCloudflare *dnsStatus + dsGoogle *dnsStatus + DnsDigUDP *gui.Node + DnsDigTCP *gui.Node +} + +type dnsStatus struct { + title string + server string // The DNS server. Example: "127.0.0.1:53" or "1.1.1.1:53" + hostname string // the hostname to lookup. Example: "www.google.com" or "go.wit.com" + + parent *gui.Node + group *gui.Node + grid *gui.Node + + // DNS setup options + udpA *gui.Node + tcpA *gui.Node + udpAAAA *gui.Node + tcpAAAA *gui.Node + + // show the display + aFail *gui.Node + aSuccess *gui.Node + aaaaFail *gui.Node + aaaaSuccess *gui.Node + + // interger counters + aFailc int + aSuccessc int + aaaaFailc int + aaaaSuccessc int +} + +func NewDigStatusWindow(p *gui.Node) *digStatus { + var ds *digStatus + ds = new(digStatus) + + ds.ready = false + + ds.window = p.NewWindow("DNS Lookup Status") + ds.box = ds.window.NewBox("hBox", true) + + // summary of the current state of things + ds.summary = ds.box.NewGroup("Summary") + + b := ds.summary.NewBox("hBox", true) + ds.status = cloudflare.NewOneLiner(b, "status") + ds.status.Set("unknown") + + b = ds.summary.NewBox("hBox", true) + ds.statusAAAA = cloudflare.NewOneLiner(b, "IPv6 status") + ds.statusAAAA.Set("unknown") + + b = ds.summary.NewBox("hBox", true) + ds.speed = cloudflare.NewOneLiner(b, "speed") + ds.speed.Set("unknown") + + b = ds.summary.NewBox("hBox", true) + ds.speedActual = cloudflare.NewOneLiner(b, "actual") + ds.speedActual.Set("unknown") + + // make the area to store the raw details + ds.details = ds.box.NewGroup("Details") + ds.dsLocalhost = NewDnsStatus(ds.details, "(localhost)", "127.0.0.1:53", "go.wit.com") + ds.dsLocalNetwork = NewDnsStatus(ds.details, "(Local Network)", "172.22.0.1:53", "go.wit.com") + ds.dsCloudflare = NewDnsStatus(ds.details, "(cloudflare)", "1.1.1.1:53", "go.wit.com") + ds.dsGoogle = NewDnsStatus(ds.details, "(google)", "8.8.8.8:53", "go.wit.com") + ds.makeDnsStatusGrid() + + return ds +} + +func (ds *digStatus) Update() { + duration := timeFunction(func () { ds.updateDnsStatus() }) + s := fmt.Sprint(duration) + ds.speedActual.Set(s) + + if (duration > 500 * time.Millisecond ) { + ds.speed.Set("SLOW") + } else if (duration > 100 * time.Millisecond ) { + ds.speed.Set("OK") + } else { + ds.speed.Set("FAST") + } +} + +// Returns true if the status is valid +func (ds *digStatus) Ready() bool { + return ds.ready +} + +// Returns true if IPv4 is working +func (ds *digStatus) IPv4() bool { + if (ds.statusIPv4 == "OK") { + return true + } + if (ds.statusIPv4 == "GOOD") { + return true + } + return false +} + +// Returns true if IPv6 is working +func (ds *digStatus) IPv6() bool { + if (ds.statusIPv6 == "GOOD") { + return true + } + return false +} + +func (ds *digStatus) setIPv4(s string) { + ds.status.Set(s) + ds.statusIPv4 = s +} + +func (ds *digStatus) setIPv6(s string) { + ds.statusAAAA.Set(s) + ds.statusIPv6 = s +} + +func (ds *digStatus) updateDnsStatus() { + var cmd, out string + var ipv4, ipv6 bool + + ipv4, ipv6 = ds.dsLocalhost.Update() + ipv4, ipv6 = ds.dsLocalNetwork.Update() + ipv4, ipv6 = ds.dsCloudflare.Update() + ipv4, ipv6 = ds.dsGoogle.Update() + + if (ipv4) { + log.Println("updateDnsStatus() IPv4 A lookups working") + ds.setIPv4("OK") + } else { + log.Println("updateDnsStatus() IPv4 A lookups not working. No internet?") + ds.setIPv4("No Internet?") + } + if (ipv6) { + log.Println("updateDnsStatus() IPv6 AAAA lookups working") + ds.setIPv4("GOOD") + ds.setIPv6("GOOD") + } else { + log.Println("updateDnsStatus() IPv6 AAAA lookups are not working") + ds.setIPv6("Need VPN") + } + + cmd = "dig +noall +answer www.wit.com A" + out = shell.Run(cmd) + log.Println("makeDnsStatusGrid() dig", out) + ds.DnsDigUDP.SetText(out) + + cmd = "dig +noall +answer www.wit.com AAAA" + out = shell.Run(cmd) + log.Println("makeDnsStatusGrid() dig", out) + ds.DnsDigTCP.SetText(out) + + ds.ready = true +} + +// Makes a DNS Status Grid +func NewDnsStatus(p *gui.Node, title string, server string, hostname string) *dnsStatus { + var ds *dnsStatus + ds = new(dnsStatus) + ds.parent = p + ds.group = p.NewGroup(server + " " + title + " lookup") + ds.grid = ds.group.NewGrid("LookupStatus", 5, 2) + + ds.server = server + ds.hostname = hostname + + ds.grid.NewLabel("") + ds.grid.NewLabel("UDP") + ds.grid.NewLabel("TCP") + ds.grid.NewLabel("Success") + ds.grid.NewLabel("Fail") + + ds.grid.NewLabel("A") + ds.udpA = ds.grid.NewLabel("?") + ds.tcpA = ds.grid.NewLabel("?") + ds.aSuccess = ds.grid.NewLabel("?") + ds.aFail = ds.grid.NewLabel("?") + + ds.grid.NewLabel("AAAA") + ds.udpAAAA = ds.grid.NewLabel("?") + ds.tcpAAAA = ds.grid.NewLabel("?") + ds.aaaaSuccess = ds.grid.NewLabel("?") + ds.aaaaFail = ds.grid.NewLabel("?") + + ds.group.Margin() + ds.grid.Margin() + ds.group.Pad() + ds.grid.Pad() + + return ds +} + +// special thanks to the Element Hotel wifi in Philidelphia that allowed me to +// easily debug this code since the internet connection here blocks port 53 traffic +func (ds *dnsStatus) Update() (bool, bool) { + var results []string + var a bool = false + var aaaa bool = false + + log.Println("dnsStatus.Update() For server", ds.server, "on", ds.hostname) + results, _ = dnsUdpLookup(ds.server, ds.hostname, dns.TypeA) + log.Println("dnsStatus.Update() UDP type A =", results) + + if (len(results) == 0) { + ds.udpA.SetText("BROKEN") + ds.aFailc += 1 + } else { + ds.udpA.SetText("WORKING") + ds.aSuccessc += 1 + a = true + } + + results, _ = dnsTcpLookup(ds.server, ds.hostname, dns.TypeA) + log.Println("dnsStatus.Update() TCP type A =", results) + + if (len(results) == 0) { + ds.tcpA.SetText("BROKEN") + ds.aFailc += 1 + } else { + ds.tcpA.SetText("WORKING") + ds.aSuccessc += 1 + a = true + } + + ds.aFail.SetText(strconv.Itoa(ds.aFailc)) + ds.aSuccess.SetText(strconv.Itoa(ds.aSuccessc)) + + results, _ = dnsUdpLookup(ds.server, ds.hostname, dns.TypeAAAA) + log.Println("dnsStatus.Update() UDP type AAAA =", results) + + if (len(results) == 0) { + ds.udpAAAA.SetText("BROKEN") + ds.aaaaFailc += 1 + ds.aaaaFail.SetText(strconv.Itoa(ds.aaaaFailc)) + } else { + ds.udpAAAA.SetText("WORKING") + ds.aaaaSuccessc += 1 + aaaa = true + } + + results, _ = dnsTcpLookup(ds.server, ds.hostname, dns.TypeAAAA) + log.Println("dnsStatus.Update() UDP type AAAA =", results) + + if (len(results) == 0) { + ds.tcpAAAA.SetText("BROKEN") + ds.aaaaFailc += 1 + ds.aaaaFail.SetText(strconv.Itoa(ds.aaaaFailc)) + } else { + ds.tcpAAAA.SetText("WORKING") + ds.aaaaSuccessc += 1 + aaaa = true + } + + ds.aaaaFail.SetText(strconv.Itoa(ds.aaaaFailc)) + ds.aaaaSuccess.SetText(strconv.Itoa(ds.aaaaSuccessc)) + + return a, aaaa +} + +func (ds *digStatus) makeDnsStatusGrid() { + var cmd, out string + group := ds.details.NewGroup("dig results") + grid := group.NewGrid("LookupStatus", 2, 2) + + cmd = "dig +noall +answer go.wit.com A" + grid.NewLabel(cmd) + ds.DnsDigUDP = grid.NewLabel("?") + out = shell.Run(cmd) + log.Println("makeDnsStatusGrid() dig", out) + ds.DnsDigUDP.SetText(out) + + cmd = "dig +noall +answer go.wit.com AAAA" + grid.NewLabel(cmd) + ds.DnsDigTCP = grid.NewLabel("?") + out = shell.Run(cmd) + log.Println("makeDnsStatusGrid() dig", out) + ds.DnsDigTCP.SetText(out) + + group.Pad() + grid.Pad() +} + +// dnsLookup performs a DNS lookup for the specified record type (e.g., "TXT", "AAAA") for a given domain. +func dnsUdpLookup(server string, domain string, recordType uint16) ([]string, error) { + var records []string + + c := new(dns.Client) + m := new(dns.Msg) + m.SetQuestion(dns.Fqdn(domain), recordType) + r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server + if err != nil { + return nil, err + } + + for _, ans := range r.Answer { + records = append(records, ans.String()) + } + + return records, nil +} + +func dnsTcpLookup(server string, domain string, recordType uint16) ([]string, error) { + var records []string + + c := new(dns.Client) + c.Net = "tcp" // Specify to use TCP for the query + c.Timeout = time.Second * 5 // Set a 5-second timeout + m := new(dns.Msg) + m.SetQuestion(dns.Fqdn(domain), recordType) + r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server + if err != nil { + return nil, err + } + + for _, ans := range r.Answer { + records = append(records, ans.String()) + } + + return records, nil +} diff --git a/examples/cloudflare/Makefile b/examples/control-panel-cloudflare/Makefile index 32f3f55..07d8f77 100644 --- a/examples/cloudflare/Makefile +++ b/examples/control-panel-cloudflare/Makefile @@ -1,10 +1,10 @@ run: build - ./cloudflare + ./control-panel-cloudflare build-release: go get -v -u -x . go build - ./cloudflare + ./control-panel-cloudflare build: GO111MODULE="off" go get -v -x . @@ -18,7 +18,7 @@ log: tail -f /tmp/witgui.* /tmp/guilogfile gocui: build - ./cloudflare -gui gocui >/tmp/witgui.log.stderr 2>&1 + ./control-panel-cloudflare -gui gocui >/tmp/witgui.log.stderr 2>&1 quiet: - ./cloudflare >/tmp/witgui.log.stderr 2>&1 + ./control-panel-cloudflare >/tmp/witgui.log.stderr 2>&1 diff --git a/examples/cloudflare/argv.go b/examples/control-panel-cloudflare/argv.go index 49167cd..49167cd 100644 --- a/examples/cloudflare/argv.go +++ b/examples/control-panel-cloudflare/argv.go diff --git a/examples/cloudflare/config.go b/examples/control-panel-cloudflare/config.go index a65ad25..a65ad25 100644 --- a/examples/cloudflare/config.go +++ b/examples/control-panel-cloudflare/config.go diff --git a/examples/cloudflare/main.go b/examples/control-panel-cloudflare/main.go index 2308478..0661a93 100644 --- a/examples/cloudflare/main.go +++ b/examples/control-panel-cloudflare/main.go @@ -20,19 +20,6 @@ var myGui *gui.Node // var cloudflareURL string = "https://api.cloudflare.com/client/v4/zones/" -/* -var zonedrop *gui.Node -var domainWidget *gui.Node -var masterSave *gui.Node - -var zoneWidget *gui.Node -var authWidget *gui.Node -var emailWidget *gui.Node - -var loadButton *gui.Node -var saveButton *gui.Node -*/ - func main() { // parse the config file readConfig() @@ -41,7 +28,8 @@ func main() { myGui = gui.New().Default() // draw the cloudflare control panel window - cloudflare.MakeCloudflareWindow(myGui) + win := cloudflare.MakeCloudflareWindow(myGui) + win.SetText(title) // This is just a optional goroutine to watch that things are alive gui.Watchdog() @@ -1,3 +1,42 @@ module go.wit.com/control-panel-dns go 1.21.4 + +require ( + github.com/Showmax/go-fqdn v1.0.0 + github.com/alexflint/go-arg v1.4.3 + github.com/creack/pty v1.1.21 + github.com/davecgh/go-spew v1.1.1 + github.com/fsnotify/fsnotify v1.7.0 + github.com/golang/protobuf v1.5.3 + github.com/jsimonetti/rtnetlink v1.4.0 + github.com/miekg/dns v1.1.57 + github.com/rs/dnstrace v1.4.1 + go.wit.com/gui v0.9.2 + go.wit.com/shell v0.0.0-20231220210920-25715e30ee82 + golang.org/x/term v0.15.0 +) + +require ( + github.com/alexflint/go-scalar v1.1.0 // indirect + github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/josharian/native v1.1.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/svent/go-nbreader v0.0.0-20150201200112-7cef48da76dc // indirect + github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef // indirect + github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/tools v0.13.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect +) @@ -0,0 +1,88 @@ +github.com/Showmax/go-fqdn v1.0.0 h1:0rG5IbmVliNT5O19Mfuvna9LL7zlHyRfsSvBPZmF9tM= +github.com/Showmax/go-fqdn v1.0.0/go.mod h1:SfrFBzmDCtCGrnHhoDjuvFnKsWjEQX/Q9ARZvOrJAko= +github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo= +github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA= +github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM= +github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4= +github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= +github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I= +github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/dnstrace v1.4.1 h1:o6W+8hO9kGcdq9FZAVudpCyw6WXeD9XXamXyYiei/Hs= +github.com/rs/dnstrace v1.4.1/go.mod h1:pFQiHK1kt94r2csi+qAxUsJ58r74QbN2q4JCDuFYTeY= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/svent/go-nbreader v0.0.0-20150201200112-7cef48da76dc h1:usYkrH2/es/TT7ETdC/qLAagcJPW3EEYFKqvibSnFbA= +github.com/svent/go-nbreader v0.0.0-20150201200112-7cef48da76dc/go.mod h1:pPzZl0vMkUhyoxUF8PAGG5bDRGo7PY80oO/PMmpLkkc= +github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef h1:7D6Nm4D6f0ci9yttWaKjM1TMAXrH5Su72dojqYGntFY= +github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef/go.mod h1:WLFStEdnJXpjK8kd4qKLwQKX/1vrDzp5BcDyiZJBHJM= +github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117 h1:67A5tweHp3C7osHjrYsy6pQZ00bYkTTttZ7kiOwwHeA= +github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117/go.mod h1:XCsSkdKK4gwBMNrOCZWww0pX6AOt+2gYc5Z6jBRrNVg= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.wit.com/gui v0.9.2 h1:QHMYdwpV6MzKwmFUMGevKUDn2a6GAqHN2Ltx8V3HufI= +go.wit.com/gui v0.9.2/go.mod h1:asRXEYKmdjhtg1yiBi5A8YEY2YG4lWPS0gvNz4NXGDE= +go.wit.com/shell v0.0.0-20231220210920-25715e30ee82 h1:5YVB3Y2PHtH+oE8Y1SzWHIKnJ1SPQa09xNHEw9yxmAI= +go.wit.com/shell v0.0.0-20231220210920-25715e30ee82/go.mod h1:57dOTStlN5aao4EOCZFC+D47rF7In6qDZCjQoobJWcA= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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= @@ -14,8 +14,6 @@ import ( "go.wit.com/gui" "go.wit.com/shell" "go.wit.com/control-panel-dns/cloudflare" - - "github.com/davecgh/go-spew/spew" ) // This setups up the dns control panel window @@ -25,9 +23,13 @@ func setupControlPanelWindow() { debug("artificial sleep of:", me.artificialSleep) sleep(me.artificialSleep) + + // setup the main tab dnsTab("DNS") detailsTab("Details") debugTab("Debug") + + me.digStatus = NewDigStatusWindow(me.window) } func detailsTab(title string) { @@ -59,6 +61,9 @@ func detailsTab(title string) { grid.NewLabel("Current IPv6 =") me.IPv6 = grid.NewLabel("?") + grid.NewLabel("Working Real IPv6 =") + me.workingIPv6 = grid.NewLabel("?") + grid.NewLabel("interfaces =") me.Interfaces = grid.NewCombobox("Interfaces") @@ -122,7 +127,6 @@ func debugTab(title string) { g2.NewButton("os.User()", func () { user, _ := user.Current() - spew.Dump(user) log.Println("os.Getuid =", user.Username, os.Getuid()) if (me.uid != nil) { me.uid.SetText(user.Username + " (" + strconv.Itoa(os.Getuid()) + ")") @@ -132,7 +136,6 @@ func debugTab(title string) { g2.NewButton("dig +trace", func () { o := shell.Run("dig +trace +noadditional DS " + me.hostname + " @8.8.8.8") log.Println(o) - // log.Println(o) }) g2.NewButton("Example_listLink()", func () { @@ -186,30 +189,54 @@ func debugTab(title string) { g2.Pad() } +// will return a AAAA value that needs to be deleted +func deleteAAA() string { + var aaaa []string + aaaa = dhcpAAAA() // your AAAA IP addresses right now + for _, s := range aaaa { + debug(LogNow, "DNS AAAA =", s) + if ( me.ipmap[s] == nil) { + return s + } + } + return "" +} + +// will return a AAAA value that needs to be added +func missingAAAA() string { + var aaaa []string + aaaa = dhcpAAAA() // your AAAA IP addresses right now + for _, s := range aaaa { + debug(LogNow, "missing AAAA =", s) + return s + } + return "" +} + // doesn't actually do any network traffic // it just updates the GUI -func displayDNS() int { +func displayDNS() string { var aaaa []string - aaaa = realAAAA() // your AAAA records right now + aaaa = dhcpAAAA() // your AAAA records right now h := me.hostname var all string - var broken int = 0 + var broken string = "unknown" for _, s := range aaaa { debug(LogNow, "host", h, "DNS AAAA =", s, "ipmap[s] =", me.ipmap[s]) all += s + "\n" if ( me.ipmap[s] == nil) { debug(LogError, "THIS IS THE WRONG AAAA DNS ENTRY: host", h, "DNS AAAA =", s) - broken = 2 + broken = "wrong AAAA entry" } else { - if (broken == 0) { - broken = 1 + if (broken == "unknown") { + broken = "needs update" } } } all = sortLines(all) - if (me.DnsAAAA.S != all) { - debug(LogError, "DnsAAAA.SetText() to:", all) - me.DnsAAAA.SetText(all) + if (me.workingIPv6.S != all) { + debug(LogError, "workingIPv6.SetText() to:", all) + me.workingIPv6.SetText(all) } var a []string @@ -296,6 +323,9 @@ func statusGrid(n *gui.Node) { gridP.NewLabel("DNS Status =") me.DnsStatus = gridP.NewLabel("unknown") + me.statusIPv6 = cloudflare.NewOneLiner(gridP, "IPv6 working") + me.statusIPv6.Set("known") + gridP.NewLabel("hostname =") me.hostnameStatus = gridP.NewLabel("invalid") @@ -315,9 +345,6 @@ func statusGrid(n *gui.Node) { ng := n.NewGroup("TODO:") gridP = ng.NewGrid("nut2", 2, 2) - gridP.NewLabel("IPv6 working =") - gridP.NewLabel("unknown") - gridP.NewLabel("ping.wit.com =") gridP.NewLabel("unknown") @@ -337,26 +364,63 @@ func updateDNS() { if (h == "") { h = "test.wit.com" } + + me.digStatus.Update() + // log.Println("digAAAA()") aaaa = digAAAA(h) debug(LogNow, "digAAAA() =", aaaa) + // log.Println(SPEW, me) if (aaaa == nil) { debug(LogError, "There are no DNS AAAA records for hostname: ", h) + me.DnsAAAA.SetText("(none)") + if (cloudflare.CFdialog.TypeNode != nil) { + cloudflare.CFdialog.TypeNode.SetText("AAAA new") + } + + if (cloudflare.CFdialog.NameNode != nil) { + cloudflare.CFdialog.NameNode.SetText(me.hostname) + } + + d := deleteAAA() + if (d != "") { + if (cloudflare.CFdialog.ValueNode != nil) { + cloudflare.CFdialog.ValueNode.SetText(d) + } + } + m := missingAAAA() + if (m != "") { + if (cloudflare.CFdialog.ValueNode != nil) { + cloudflare.CFdialog.ValueNode.SetText(m) + } + /* + rr := &cloudflare.RRT{ + Type: "AAAA", + Name: me.hostname, + Ttl: "Auto", + Proxied: false, + Content: m, + } + cloudflare.Update(rr) + */ + } } - broken := displayDNS() // update the GUI based on dig results + status := displayDNS() // update the GUI based on dig results + me.DnsStatus.SetText(status) - if (broken == 1) { - me.DnsStatus.SetText("PARTLY WORKING") - } else if (broken == 2) { - me.DnsStatus.SetText("WORKING") - } else { - me.DnsStatus.SetText("BROKEN") - me.fix.Enable() + if me.digStatus.Ready() { + if me.digStatus.IPv6() { + me.statusIPv6.Set("IPv6 WORKING") + } else { + me.statusIPv6.Set("Need VPN") + } } + + // me.fix.Enable() + user, _ := user.Current() - spew.Dump(user) log.Println("os.Getuid =", user.Username, os.Getuid()) if (me.uid != nil) { me.uid.SetText(user.Username + " (" + strconv.Itoa(os.Getuid()) + ")") diff --git a/hostname.go b/hostname.go index a0da280..7b7132a 100644 --- a/hostname.go +++ b/hostname.go @@ -6,17 +6,22 @@ package main import ( + "log" +// "net" + "strings" + "go.wit.com/shell" "go.wit.com/control-panel-dns/cloudflare" - "go.wit.com/control-panel-dns/dnssecsocket" + + "github.com/miekg/dns" ) // will try to get this hosts FQDN import "github.com/Showmax/go-fqdn" // this is the king of dns libraries -import "github.com/miekg/dns" +// import "github.com/miekg/dns" func getHostname() { @@ -98,6 +103,7 @@ func goodHostname(h string) bool { return false } +/* func digAAAA(s string) []string { var aaaa []string // lookup the IP address from DNS @@ -114,5 +120,52 @@ func digAAAA(s string) []string { me.ipv6s[ipaddr] = rr } debug(true, args.VerboseDNS, "aaaa =", aaaa) + log.Println("digAAAA() returned =", aaaa) + log.Println("digAAAA() me.ipv6s =", me.ipv6s) + os.Exit(0) return aaaa } +*/ + +func digAAAA(hostname string) []string { + var blah, ipv6Addresses []string + // domain := hostname + recordType := dns.TypeAAAA // dns.TypeTXT + + // Cloudflare's DNS server + blah, _ = dnsUdpLookup("1.1.1.1:53", hostname, recordType) + log.Println("digAAAA() has BLAH =", blah) + + if (len(blah) == 0) { + log.Println("digAAAA() RUNNING dnsLookupDoH(domain)") + ipv6Addresses, _ = dnsLookupDoH(hostname) + log.Println("digAAAA() has ipv6Addresses =", strings.Join(ipv6Addresses, " ")) + log.Printf("digAAAA() IPv6 Addresses for %s:\n", hostname) + for _, addr := range ipv6Addresses { + log.Println(addr) + } + return ipv6Addresses + } + + // TODO: check digDoH vs blah, if so, then port 53 TCP and/or UDP is broken or blocked + log.Println("digAAAA() has BLAH =", blah) + + return blah +} + +/* +func dnsHttpsLookup(domain string, recordType uint16) ([]string, error) { + domain := "google.com" + dnsLookupDoH(domain string) ([]string, error) { + ipv6Addresses, err := dnsLookupDoH(domain) + if err != nil { + fmt.Println("Error:", err) + return + } + + fmt.Printf("IPv6 Addresses for %s:\n", domain) + for _, addr := range ipv6Addresses { + fmt.Println(addr) + } +} +*/ @@ -59,6 +59,27 @@ func main() { /* Poll for changes to the networking settings */ + +/* https://github.com/robfig/cron/blob/master/cron.go + +// Run the cron scheduler, or no-op if already running. +func (c *Cron) Run() { + c.runningMu.Lock() + if c.running { + c.runningMu.Unlock() + return + } + c.running = true + c.runningMu.Unlock() + c.run() +} + +// run the scheduler.. this is private just due to the need to synchronize +// access to the 'running' state variable. +func (c *Cron) run() { + c.logger.Info("start") +*/ + func checkNetworkChanges() { var lastLocal time.Time = time.Now() var lastDNS time.Time = time.Now() @@ -119,12 +140,12 @@ func DNSloop() { } else if (duration > 100 * time.Millisecond ) { newSpeed = "OK" if (me.fixProc != nil) { - me.fixProc.Disable() + // me.fixProc.Disable() } } else { newSpeed = "FAST" if (me.fixProc != nil) { - me.fixProc.Disable() + // me.fixProc.Disable() } } if (newSpeed != me.DnsSpeedLast) { @@ -156,7 +177,7 @@ func linuxLoop() { } var aaaa []string - aaaa = realAAAA() + aaaa = dhcpAAAA() var all string for _, s := range aaaa { debug(LogNet, "my actual AAAA = ",s) @@ -97,7 +97,11 @@ func checkInterface(i net.Interface) { } } -func realAAAA() []string { +/* + These are the real IP address you have been + given from DHCP +*/ +func dhcpAAAA() []string { var aaaa []string for s, t := range me.ipmap { @@ -57,6 +57,7 @@ type Host struct { NSrr *gui.Node // NS resource records for the domain name DnsAPI *gui.Node // what DNS API to use? DnsAAAA *gui.Node // the actual DNS AAAA results + workingIPv6 *gui.Node // currently working AAAA DnsA *gui.Node // the actual DNS A results (ignore for status since mostly never happens?) DnsStatus *gui.Node // the current state of DNS DnsSpeed *gui.Node // 'FAST', 'OK', 'SLOW', etc @@ -72,6 +73,9 @@ type Host struct { dbOn *gui.Node // button for setting debugging on dbNet *gui.Node // button for setting network debugging on dbProc *gui.Node // button for setting proc debugging on + + digStatus *digStatus + statusIPv6 *cloudflare.OneLiner } type IPtype struct { |
