Detect that a VPN is needed
IPv6() returns true if it's working display duration a 'DNS Lookup Status' window actual dig results display status and failure counters count lookup failures and successes add TCP dns lookup logic to test if dns is working at all add DNS over HTTPS cloudflare new & update kind of working holy shit, go.wit.com finally works with git mod tidy working, but cloudflare api stuff is broken AAAA '(none)' logic detection is better cloudflare control panel display the working real AAAA addresses Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
73b0cee933
commit
6fa6d6dfc9
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
func doCurl(method string, rr *RRT) string {
|
||||
var err error
|
||||
var req *http.Request
|
||||
|
||||
var tmp string
|
||||
tmp = makeJSON(dnsRow)
|
||||
data := []byte(tmp)
|
||||
data := []byte(rr.data)
|
||||
|
||||
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)
|
||||
|
||||
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))
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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()
|
||||
|
||||
rr.url = "https://api.cloudflare.com/client/v4/zones/" + rr.ZoneID + "/dns_records"
|
||||
|
||||
result := doCurl("POST", rr)
|
||||
CFdialog.resultNode.SetText(result)
|
||||
|
||||
pretty, _ := FormatJSON(result)
|
||||
log.Println(pretty)
|
||||
})
|
||||
|
||||
group.NewButton("Update RR doCurl(PUT)", func () {
|
||||
rr := DoChange()
|
||||
|
||||
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()
|
||||
|
||||
|
||||
group.Pad()
|
||||
grid.Pad()
|
||||
grid.Expand()
|
||||
}
|
||||
|
||||
/*
|
||||
func CreateCurlRR() (string, string) {
|
||||
// enable the Save/Create Button
|
||||
if (CFdialog.saveNode != nil) {
|
||||
CFdialog.saveNode.Enable()
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
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")
|
||||
|
||||
// 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)
|
||||
|
||||
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
|
||||
}
|
||||
*/
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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()
|
39
go.mod
39
go.mod
|
@ -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=
|
116
gui.go
116
gui.go
|
@ -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)
|
||||
}
|
||||
broken := displayDNS() // update the GUI based on dig results
|
||||
me.DnsAAAA.SetText("(none)")
|
||||
if (cloudflare.CFdialog.TypeNode != nil) {
|
||||
cloudflare.CFdialog.TypeNode.SetText("AAAA new")
|
||||
}
|
||||
|
||||
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 (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)
|
||||
*/
|
||||
}
|
||||
}
|
||||
status := displayDNS() // update the GUI based on dig results
|
||||
me.DnsStatus.SetText(status)
|
||||
|
||||
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()) + ")")
|
||||
|
|
57
hostname.go
57
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)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
27
main.go
27
main.go
|
@ -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)
|
||||
|
|
6
net.go
6
net.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue