From 26f3759936750082271eb5cc7ee0da29c74ede1b Mon Sep 17 00:00:00 2001 From: aceberg <1502200+aceberg@users.noreply.github.com> Date: Wed, 10 Jul 2024 04:24:46 +0700 Subject: [PATCH] Trying goscan --- .version | 2 +- Makefile | 33 +----- go.mod | 1 + go.sum | 14 +++ internal/arp/arpscan.go | 57 +++++++++++ internal/arp/goscan.go | 156 +++++++++++++++++++++++++++++ internal/conf/getconfig.go | 3 + internal/models/models.go | 2 + internal/web/config.go | 22 ++-- internal/web/index.go | 7 ++ internal/web/public/favicon.png | Bin 13194 -> 20627 bytes internal/web/templates/config.html | 61 +---------- internal/web/webgui.go | 3 + 13 files changed, 254 insertions(+), 107 deletions(-) create mode 100644 internal/arp/arpscan.go create mode 100644 internal/arp/goscan.go diff --git a/.version b/.version index bb7777a..53be989 120000 --- a/.version +++ b/.version @@ -1 +1 @@ -internal/web/templates/version \ No newline at end of file +internal/web/public/version \ No newline at end of file diff --git a/Makefile b/Makefile index 365b9b8..7e79d57 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,3 @@ -DUSER=aceberg -DNAME=watchyourlan - -IFACE=enp4s0 -DBPATH=/data/hosts.db -SHOUTRRR_URL=gotify://192.168.2.1:8083/AwQqpAae.rrl5Ob/?title=Unknown host detected&DisableTLS=yes - mod: rm go.mod || true && \ rm go.sum || true && \ @@ -14,7 +7,6 @@ mod: run: cd cmd/WatchYourLAN/ && \ sudo \ - env IFACE=$(IFACE) DBPATH=$(DBPATH) THEME=$(THEME) \ go run . #-c /data/config #-n http://192.168.2.3:8850 fmt: @@ -24,27 +16,4 @@ lint: golangci-lint run golint ./... -check: fmt lint - -go-build: - cd cmd/WatchYourLAN/ && \ - CGO_ENABLED=0 go build -o ../../tmp/WatchYourLAN . - -docker-build: - docker build -t $(DUSER)/$(DNAME) . - -docker-run: - docker rm wyl || true - docker run --name wyl \ - -e "IFACE=$(IFACE)" \ - -e "SHOUTRRR_URL=$(SHOUTRRR_URL)" \ - -e "TZ=Asia/Novosibirsk" \ - --network="host" \ - -v ~/.dockerdata/wyl:/data \ - $(DUSER)/$(DNAME) - -clean: - rm src/$(DNAME) || true - docker rmi -f $(DUSER)/$(DNAME) - -dev: docker-build docker-run \ No newline at end of file +check: fmt lint \ No newline at end of file diff --git a/go.mod b/go.mod index 02e048f..985c59c 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.4 require ( github.com/gin-gonic/gin v1.10.0 + github.com/google/gopacket v1.1.19 github.com/spf13/viper v1.19.0 ) diff --git a/go.sum b/go.sum index 2614f17..dbb03a5 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -104,18 +106,30 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/arp/arpscan.go b/internal/arp/arpscan.go new file mode 100644 index 0000000..ae073bf --- /dev/null +++ b/internal/arp/arpscan.go @@ -0,0 +1,57 @@ +package arp + +import ( + "log" + "os/exec" + "strings" + "time" + + "github.com/aceberg/WatchYourLAN/internal/models" +) + +func scanIface(iface string) string { + cmd, err := exec.Command("arp-scan", "-glNx", "-I", iface).Output() + if err != nil { + return string("") + } + return string(cmd) +} + +func parseOutput(text string) []models.Host { + var foundHosts = []models.Host{} + + perString := strings.Split(text, "\n") + currentTime := time.Now() + + for _, host := range perString { + if host != "" { + var oneHost models.Host + p := strings.Split(host, " ") + oneHost.IP = p[0] + oneHost.Mac = p[1] + oneHost.Hw = p[2] + oneHost.Date = currentTime.Format("2006-01-02 15:04:05") + oneHost.Now = 1 + foundHosts = append(foundHosts, oneHost) + } + } + + return foundHosts +} + +// Scan all interfaces +func Scan(ifaces []string) []models.Host { + var text string + var foundHosts = []models.Host{} + + for _, iface := range ifaces { + text = scanIface(iface) + + log.Println("INFO: scanning interface", iface) + log.Println("INFO: found IPs:", text) + + foundHosts = append(foundHosts, parseOutput(text)...) + } + + return foundHosts +} diff --git a/internal/arp/goscan.go b/internal/arp/goscan.go new file mode 100644 index 0000000..01a464a --- /dev/null +++ b/internal/arp/goscan.go @@ -0,0 +1,156 @@ +package arp + +import ( + "bytes" + "encoding/binary" + "errors" + "log" + "net" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" +) + +// GoScan - scan iface +func GoScan() { + + iface, _ := net.InterfaceByName("enp4s0") + err := scan(iface) + log.Println(err) +} + +func scan(iface *net.Interface) error { + // We just look for IPv4 addresses, so try to find if the interface has one. + var addr *net.IPNet + if addrs, err := iface.Addrs(); err != nil { + return err + } else { + for _, a := range addrs { + if ipnet, ok := a.(*net.IPNet); ok { + if ip4 := ipnet.IP.To4(); ip4 != nil { + addr = &net.IPNet{ + IP: ip4, + Mask: ipnet.Mask[len(ipnet.Mask)-4:], + } + break + } + } + } + } + // Sanity-check that the interface has a good address. + if addr == nil { + return errors.New("no good IP network found") + } else if addr.IP[0] == 127 { + return errors.New("skipping localhost") + } else if addr.Mask[0] != 0xff || addr.Mask[1] != 0xff { + return errors.New("mask means network is too large") + } + log.Printf("Using network range %v for interface %v", addr, iface.Name) + + // Open up a pcap handle for packet reads/writes. + handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever) + if err != nil { + return err + } + defer handle.Close() + + // Start up a goroutine to read in packet data. + stop := make(chan struct{}) + go readARP(handle, iface, stop) + defer close(stop) + // for { + // Write our scan packets out to the handle. + if err := writeARP(handle, iface, addr); err != nil { + log.Printf("error writing packets on %v: %v", iface.Name, err) + return err + } + // We don't know exactly how long it'll take for packets to be + // sent back to us, but 10 seconds should be more than enough + // time ;) + time.Sleep(10 * time.Second) + // } + return err +} + +// readARP watches a handle for incoming ARP responses we might care about, and prints them. +// +// readARP loops until 'stop' is closed. +func readARP(handle *pcap.Handle, iface *net.Interface, stop chan struct{}) { + src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet) + in := src.Packets() + for { + var packet gopacket.Packet + select { + case <-stop: + return + case packet = <-in: + arpLayer := packet.Layer(layers.LayerTypeARP) + if arpLayer == nil { + continue + } + arp := arpLayer.(*layers.ARP) + if arp.Operation != layers.ARPReply || bytes.Equal([]byte(iface.HardwareAddr), arp.SourceHwAddress) { + // This is a packet I sent. + continue + } + // Note: we might get some packets here that aren't responses to ones we've sent, + // if for example someone else sends US an ARP request. Doesn't much matter, though... + // all information is good information :) + log.Printf("IP %v is at %v", net.IP(arp.SourceProtAddress), net.HardwareAddr(arp.SourceHwAddress)) + } + } +} + +// writeARP writes an ARP request for each address on our local network to the +// pcap handle. +func writeARP(handle *pcap.Handle, iface *net.Interface, addr *net.IPNet) error { + // Set up all the layers' fields we can. + eth := layers.Ethernet{ + SrcMAC: iface.HardwareAddr, + DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + EthernetType: layers.EthernetTypeARP, + } + arp := layers.ARP{ + AddrType: layers.LinkTypeEthernet, + Protocol: layers.EthernetTypeIPv4, + HwAddressSize: 6, + ProtAddressSize: 4, + Operation: layers.ARPRequest, + SourceHwAddress: []byte(iface.HardwareAddr), + SourceProtAddress: []byte(addr.IP), + DstHwAddress: []byte{0, 0, 0, 0, 0, 0}, + } + // Set up buffer and options for serialization. + buf := gopacket.NewSerializeBuffer() + opts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + // Send one packet for every address. + for _, ip := range ips(addr) { + arp.DstProtAddress = []byte(ip) + gopacket.SerializeLayers(buf, opts, ð, &arp) + if err := handle.WritePacketData(buf.Bytes()); err != nil { + return err + } + } + return nil +} + +// ips is a simple and not very good method for getting all IPv4 addresses from a +// net.IPNet. It returns all IPs it can over the channel it sends back, closing +// the channel when done. +func ips(n *net.IPNet) (out []net.IP) { + num := binary.BigEndian.Uint32([]byte(n.IP)) + mask := binary.BigEndian.Uint32([]byte(n.Mask)) + network := num & mask + broadcast := network | ^mask + for network++; network < broadcast; network++ { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], network) + out = append(out, net.IP(buf[:])) + } + return +} diff --git a/internal/conf/getconfig.go b/internal/conf/getconfig.go index 462478b..f3b5696 100644 --- a/internal/conf/getconfig.go +++ b/internal/conf/getconfig.go @@ -14,6 +14,7 @@ func Get(path string) (config models.Conf) { viper.SetDefault("PORT", "8840") viper.SetDefault("THEME", "solar") viper.SetDefault("COLOR", "dark") + viper.SetDefault("NODEPATH", "") viper.SetConfigFile(path) viper.SetConfigType("yaml") @@ -26,6 +27,7 @@ func Get(path string) (config models.Conf) { config.Port = viper.Get("PORT").(string) config.Theme = viper.Get("THEME").(string) config.Color = viper.Get("COLOR").(string) + config.NodePath = viper.Get("NODEPATH").(string) return config } @@ -40,6 +42,7 @@ func Write(config models.Conf) { viper.Set("PORT", config.Port) viper.Set("THEME", config.Theme) viper.Set("COLOR", config.Color) + viper.Set("NODEPATH", config.NodePath) err := viper.WriteConfig() check.IfError(err) diff --git a/internal/models/models.go b/internal/models/models.go index f59dcb7..a0f3d7b 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -8,7 +8,9 @@ type Conf struct { Color string DirPath string ConfPath string + DBPath string NodePath string + Ifaces []string } // Host - one host diff --git a/internal/web/config.go b/internal/web/config.go index cb47e05..8675cd6 100644 --- a/internal/web/config.go +++ b/internal/web/config.go @@ -8,7 +8,7 @@ import ( "github.com/gin-gonic/gin" "github.com/aceberg/WatchYourLAN/internal/check" - // "github.com/aceberg/WatchYourLAN/internal/conf" + "github.com/aceberg/WatchYourLAN/internal/conf" "github.com/aceberg/WatchYourLAN/internal/models" ) @@ -30,21 +30,13 @@ func configHandler(c *gin.Context) { func saveConfigHandler(c *gin.Context) { - // appConfig.Host = c.PostForm("host") - // appConfig.Port = c.PostForm("port") - // appConfig.Theme = c.PostForm("theme") - // appConfig.Color = c.PostForm("color") - // tStr := c.PostForm("timeout") - // hStr := c.PostForm("trim") + appConfig.Host = c.PostForm("host") + appConfig.Port = c.PostForm("port") + appConfig.Theme = c.PostForm("theme") + appConfig.Color = c.PostForm("color") + appConfig.NodePath = c.PostForm("node") - // if tStr != "" { - // appConfig.Timeout, _ = strconv.Atoi(tStr) - // } - // if hStr != "" { - // appConfig.HistTrim, _ = strconv.Atoi(hStr) - // } - - // conf.Write(appConfig) + conf.Write(appConfig) slog.Info("writing new config to " + appConfig.ConfPath) diff --git a/internal/web/index.go b/internal/web/index.go index b3f0424..93bdc8b 100644 --- a/internal/web/index.go +++ b/internal/web/index.go @@ -1,10 +1,12 @@ package web import ( + "log" "net/http" "github.com/gin-gonic/gin" + "github.com/aceberg/WatchYourLAN/internal/arp" "github.com/aceberg/WatchYourLAN/internal/models" ) @@ -12,6 +14,11 @@ func indexHandler(c *gin.Context) { var guiData models.GuiData guiData.Config = appConfig + res := arp.Scan(appConfig.Ifaces) + log.Println("ARPSCAN:", res) + + go arp.GoScan() + c.HTML(http.StatusOK, "header.html", guiData) c.HTML(http.StatusOK, "index.html", guiData) } diff --git a/internal/web/public/favicon.png b/internal/web/public/favicon.png index 16dd7e7a14c9566264838fb8a9885fdc611cc52c..2f2d5ca08d8a0e8e93ce1c65924a6f1f44b62522 100644 GIT binary patch literal 20627 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 W{}1PkMllc&grKb*tX^4o-2NZdZ!UTO literal 13194 zcmds-cTiJb*Y6KaPy|#&qzMX&fPi%A2nd8Ky@uYa^xjo0)F54YsG(O0U8P7T^b(5H z&_eI!9)8br=g!=D-}j$8@7$R;6G~3@*=L`9*4lfm?`M5}t1L@$i~1G-03;AOX*B@A z1^>kbh;D#?_PvHr!9Vz}k`N6d@a0Ej{t5hi^PQZoD*%xGzW%|9V7|<00RJ#ey!p4eG~1S!DQi&z3NvVS)b^C zAykz8^F>b?QOJ|u>p|4nFMkseLf%0fZ$r*66vMT74Jq{$ho5tO6?nE5;Y>;O&ZLFO zcFy{(Gmfro;@$5i^i-D1MU9#xu2&BwKI$URG~6}a$IcE`z8B^-q18wF^U{0@<*)DR zf5t1wh(}exYw%5aC-x!w(r@erCsDYTAj%Yyt?Fd;IKiGNpl4Y%x9yDGB-fgvEjZ78;HBh>$Rbxu{0MHT)7Xd_C zSbxLrnQJXoz0|p4g;jVrso{9~PyH{Zj`DT>R z{mVyP*ytXhAkO+9}pjKGd63 zM{uBSQ8AbM(_d$g>Qjq`Jb>d=&j90cuG9LyZqP!|mgZOe*vrx`m`8$>Fz~~0;U2_6 z;5Go5R_9~Zpqm`iT0o-L3Sqpw&q9d8^$Aw)s`c4`0|78)Z}7Z;w(vQ4Z3nzG1o5P9 zSutQ7-bbuW1^}NztA(0Vm-KD~eU`WAl&iMm~*mu~@VuecY%{g|HO z06~syJrirmTEx}2foB7QgTr_L@OLiR_zl8hG6}Ejd59hWNGRf(wd=DF`QW$Y-&Ya@ z9g9?k|C|<}`ehe@1FSxE*hkYf-zEYbSnS&FsieVQ458p>!2Avl00iBB0{$EQx_}6H zZA^h5Y>)Z?4*RK=+8z8`A#VE~b#VUad;yJ=(t<(jF0mbphb-y+2p!f!-naKu7{E^X z5o>-*2ewkZADKl13hijK{W3FlB~(9{K91=!B?E%#tu2qjsUwz~0;|+22Q|RAdr4u; z&f}%shA<*vz&E)!*V3c6^C;B+(h?6LQ(OYR{mL_9${!0VH-zq%JF;)%ZTi^TUZq|Q z9XFMtqm&S;PQTw$0l=WmFwJD6nNKtL4c|J+<|J26MubK7eSM&;B6*UpxaDZds6$T) zn-+(yZYBi)$gZCePrW6a)Ut-4sk8t(lv;F8&mJd(UpsbeU&yfkM)0!bGV<+Ru;-NY zG<9QP?4QQmJlpEY4_^*BYk;?@2zD>DPx0XBOK^dN?1~y4O#bAAhGE!*DHMQh5tRT! zsjIUgqMZ-8z@0FU-2-R^&Ml{jCIKKLMG^mKw_{|sts>5V<9zSqzmK|{Z2QNNs|Qj}5lJ+a zZIhXYYrNQ%mH;G>6kkr>MwRzdxLokzGC=S`mk3Jrsh`Vo7vTaD0)mm*C<&X^buv;C zX`SBIwo$|b`8N~_ZINTHt|d1z8qBfc-hN+kUWz* zDOtC5^J6-sWCDP)w~=PN++x#%_{ZQwnlI1f(5f!g@zpX5mw6CnZEP)(+x7-#T99Af zmQ5_L3II$j3Eeh+e-dxCg+}?&nDM^U7#%;B>ki(5-@GkG|rt_x8= zWOem#R+2&esXKEo^ljD>Zbn5z#uR-Dt!LGRit8 zDFLxB@~+SXini)-iw*oya+FqF7=fKMeu!sl3%xW<-4M%Q?AaQ2(||2@4=M|1=$~64 zXN2X+Ze&9eh95*;&BSvqN}_L$v11TKXF8Ua`+03N2QRF&Q8}~&Wotqc{u0dfWUC3S zPc9TLG(=4o8q-ETH{e2bj*~{~j=B=vE)6KcOS5~;geJWet(F2x`UR9x5tlKL1oyX` zZrC9^Vu8GpP@fQlghFqTVf@(#!?l_0^^5HNoOV}r{~O&qQH~I-AsGZ!nVRb3gb^+f zJ5J}=_`i%R!W>ej6W=5nGreSB&-KbQA_&l2* zB%NHhS*l})By2N92L28PqSZQtqu{nOr;SmKfQ~?kaKFY+hZ+XVn%w@xv}pN4!6E~=y7bA-Ttr6x-i+YHt?m&SNwGD z(yiqfsy}k->?S!D^pI{Y@(%&0FD^cUYqrD%_r1O1*6wz9=c5Iwa*OyUkpYR!hWko`Nc`CB-D^s@CI(Tqg}R!i&Wh4G?0 z?OtN-Yzhj=6Shz`-8FU$E6mVm14BdrmFj`Z=`^~3kR(b(YBag=vZhjNU>VJb^jV+x z8GPJ~TGvKr!@8r`VCC+Xa_N&*l2eu+4^NK@KJE_~=+=tW$Z5}18m!PaYFa%yd?%@i z+ZY8zyQv@HQI2{ZcniU-A~T@<_ft_mI{(hZAGBV`O*N?HF_ zI#|BFTB*@w7rx3n?ZXROn{){CEN9IKybGL8*J6bgn-d>lyc*fne_em;k@>{N z|H(SQf-6Bk)!-{V6mcFhmTr5$$|6|2OM*GzbQLzRu1}-NB_VSMI32IS9G0HZcluY( zPXT%p{5*GTFVF`emJJ`mpbTG$02Ye2fit(tJIDz1!L|c@i919|mMW%<L!YPK8LFny&UFWKW$-!8oK~8kOE?iWf@AaJlKfc~+xm z{c0Kt4?PJKG*$jo4!*j)ONc8W-#eZaFvqTf3?FF1vX2#!1Um4u&f1p9A>R+=IzYsC zqvVj`%-8FC{m9v`hO7BvdE|R$=W|9<{Gj{wC}CxuHMCtYPfb1|x#KCc-OzD|Z1aR? zl#?$Fk*w4oeuQ*EW(7#1EZ)1s1|~WlC0w_8bvft&o;^kJ?V$YBrhqDbLmDc0VYa}# zsXULLp~7pJ;n1oBu34S!%Uq|Kf#%>Uw{Ujp0$nIpMurniP=~L_Mu4W@F7~gEzSU0| z6&{TlW`%{!Bv~K4eVKKnZIsm;AXHkb?O+%P73PVf!vqi88(xjR($&sA4!4zB@ba(O zX-LDA6~XDfx(|XUsS2o7y;&mz!Ssu^fXXxQWufPoVF|cE?n`>6Xw?ZXvdSTg8ofpb zmyJIMta6SWH7*sTI~ZvzU#W>}UM-ajP}Lc&;;)#HB<(j|Y`+%HN@@JH&+ha_Wm?%i z)$^Ot4}drCeGT3S^NJ-&mtV+ByGsH}Lw zBi8|oWd1ysxZ$rVrs%(%qYnaAnBQ_Mks#9Ez41ME;Vp)VO!cuukS>JRNoIU&GSAS7IRGEulO^k`<&S1o(yt-FU|n~Q2FW9VmpE*r}n(aI8i zT4yaS6TFs&TZNX3Vl&CTh}@ZVT2xPEq(|X_Spc3U1wXJ+fyXU6UgueeUZDR&jEk7S z=<*dF_+Qm0t7VTy^EhZcqJHb0PkR=T&P50ylAt_=W27@Ix{zvHXm4)b;2TC4s0EQ`$_9$DR;EIm)zLd0cJzMIyq9)nu<22O^8la>;p{EkU}4@9;PYO6mD)>^G#c}LO}D0fS^@PtCc19ffMmM!|Gfa z(WXD0cT&CF9cNF#j^Ik*)9V{~&=ByQxuG0Ch=FKPAeq>3R&Q!B2OJq}ph!R} zwah0X7gs!OO2q6YU^ql9YBFM%yAV$a>HtjkMi$j8C{J2bY8)bQKYDzO&o%)7sI15i zXrJ8OPul$S6nJ%adTj1h%Wa`YJ!Lx?JfOhw>q=a`F ztqC6?r9SYS*He!RHraC^0e;yFC4txjXd>JMi#2qD4*k0gMsh zB<#;$f!Pqgz=|yx{iZgcJDlkvIH*-+**@G~uLq{TBg)&%x+wLGX8#E{Wi+2tnC0IF zC-lC;n+SGlhjq9>Lcg8;j`ap-)7K04mXdXAx1B`l5oF;AGC88%u(aB3PcTmYO&p;- z_w*?tu&R0@Y4|lh93f<+-l&&w^o{WRA=T0?!8k$%*7#dr_Ij>vf`)0+-|-^;D{K7M zic!{WJl)NkgwE(IB0!>+s>9kizbH7fBBbL?I9pWe5_07E89ykGyZz-adSKv))@%`; z-~81b%zgkl!v88zD8>t_u36#+Q$x|o)q4FKfSu;oTu`OCLukf3Ynv30)ADdLGM5%S z5XNAQ_N;BfpIfDj(EyFX^sl{5oiu{r%N|k+Hf9SZpwYJshgckKtKW75+ig*rxlhse zArLUBsV@rfI|!TQ8nP{~am3?oH=t;Ga-AZNCbCWGmJ|bX0xm|;8f2PaShHHA_c;Ab zO_;cb0%$rt!usf-tbS^M(G0R%{_1dvtijG#xVz?psl`t$@bho>V9;cTs~nbRXSaSj z5C(Au&OxV&`J9Y&l&*8BqJ7G!sPWpIY)>2m_lc+Ju>H131UMOJvx5nQnA(XOGs5kh zJELwgOPm+wDFg+RbhozJ-e`_Bw;WJPXb#-yUkeS@jP_OGL5O$+8UxvD}4+ieKOZ<@aXB3un|F+yvfwH z`xNS7Y-v^(j4r0Sj)ARt zK)K7oiahjf!nly#I_Uh@=(0?;qzD)C7(xKvaoTl4Ux5<-S!Dump3tfL%b8txb3DD0 zt+Y`l1+Q;k49A0sUst)5;-SIK1#yMjhxQQzvUTOKvkFk~KS1nG}{Qx6AG4L=B z7}_O}R8(2}^mR3BHX`(3^R*>$#3L6)qVpo==O zFET|v;v!gb%B5^;;#DjBATcY4%`;fxUEU=Z&UGY1w^;^V>xMm~s3(Uy;y^hWp zZHZU)!G^Wv70xsAMp3zZm7|5{rE&5fE^frQZk$)caWQ4i`D(oHfC9hUlw^WWEYdJ;9WxN>med z98RSUqt;zIy?@5*T9O?iHypT+^T|P z*eAu6xRH9$I!hzqeq{xNrn#|;W;j|jZ6I62N&@;nKA+JEBWj_A{GbP1A#!!r1GD5#t1Lr}L3#hYjA!pPc=L|UJ+1fZt zy;9coXTS*gM8s_E(5?J*YC77be+pH2AQC{>T^sJ^gR0)AW;`3oNDO4GUH*%Ch|~F_ zH`a5e%oIKOm@zdTynV|UvrQV%K6z@rU4|kcltWm46-P%gD|B*cJ<3UbIU2r>VPAf@ zFhv{*8acgV-DM;8|c^l9fFL7xEbREFgSax=jBl$&!~v8x#8o(ugb+N`8zbSm!p%V zvuCMF2k@^LtD^ub^^1IM&gSWY2igjHv2LQG?R+Rfwtk(daS`to5(s7JqH|4HW5X_r z*l-U2kZtXR(@y+$&;s6LFUewM8512KN@gXC>l-fv=er-qf&YgAmg#-LZl?a$(cx)pz2XN zy2HlK;4o$($mkd2`{^kS;H)W^7}hScX)RO1BJZk@+J|v*m%cjfS!ilQ<4pXf1*$Bv zxVbd=PSthy9zepLK~>0z!nv%R8W!2E(%c^F?saw9X$kqJ(H{H4zCgxe11wY6k<7c_ zgEk%m8I0uGia)B;g_~`P4cR8NKdT0ZPRuW&%}N8t5^9;Dat}7WS3Vq3vo#*>tQc(j zdIB+F1 z+}c7zUEd#L-oPU7?GYSWy7loT7?g8ixbM*80#6R60^M8hHkHP;pUUdkbjnG=s1%ST z%sNT0|3u2^vDg&D=N+9;uMWc_u;^_xhZ7-PV!q=2W$4QDlh#|1?w-=4k>PM_0#ss5 zyqrh1xfbHgwI)FKQMsK!gS%99_tb0oJ3zGVI_tWNR3A#+-uPL#TPEDf%|^Y}P`&Q2 zG^9phGrPa>dPB|qVkLBo<6F-uhuGPi=$J;yF@mEy;@e{|6&ckGXy!FvzIv;L)uapw z;#$_E;XLUQ$a18dsBGePhR1p5!Nt|~vvH&1EYhnpD@^$Rdc;Uh-yo8k6!QLB>%H5T zUgULh^NMv=Y)Gy@!i!wiA+2Fg{ci2&+mqn3Zwo&0u@cbNB1UgCXNuN}$yl`TOg4hn zLiWU-oTZHjD5GBocP`E(6&b-{TiW`_I^YuuT*7e>yUp@QhM$)7$s?ulDq7DPiKe7) z?Uda%7U$RE_iIlOl~pt6JSq?NmeO#*fmMOq=%sma-GDrORM~_SVby-l-I}m(V0=ut z-P`r?Dtg22>6-(&S=TY`(LBp|!BeRmwVTR=$pQ*UkwSht!D(bN4n8o)P*Pz3Lyen0 zGQTdS<@R?9RsEJ&);M`%jSDG=r}R*k|HyAy=B~l24^?2#>>_@htG*P2WC*ji0am1` znZ-iG!mHARMcIMr7SM7;Lp-8Q@qvsFDVN8wN{nYKs#OQaaStNI#dVuMU7yW!-TM}!zGl%G z2ZEC@ZIxs9#Cpxk8R2Eb2mlV$4{tU-w&AcB4jw5a>cS!IeCW>=VtK0YbL$_(64`vOMwEpjQpYD|tAA|I}@lD`Is!iP4;EEr#3pE&9ml@XT-!WYsm`Q}@* zV1~NSg$oSa>`1yf`)OX5!kMVCl=`Rb^+4%}?n`eQ0>7NYN?e~L;#;pWo>E`c{a-xo zzgc`_ab{Rzqay@N0HzvJrAfrxo3DzoP1nx@~*mH z7$e!Y9O-Szmjw&Ds322XxsbKmHJN;uKq}Ci$=I83D=&Psf_IdJKBFXvL3|Wt zJd;|^^S8b=d0uC74bpqXQK)#ZqsvST0){xrr1i>espHIFwQBb_bB(%_-*`Kq&7@Y0v}zTXtWr8;mufAb5g4Ce10LcW(yCG{pQE-tSZ9uS|x$pd!=E7Gbl zcHA{tcOK&czzaEL)EPE$NSpccZ}!p$-T`O8t1acK+}d@BrnoBLF%4)4F((d7xupTu zhZi!F!IaY2d&P>W5k7PP3iJC#`>0k_-_;bxhmIh~b=L5NTo*ck0ok{NcH`l6Z6h{H zNH=p6cT;X%^(+(Ua*Kz3QuWa4_km$L^l+vN0^esYAG0J_8n64|G^^VYB3oh0->Yxk((r;?(YDG{>3FrDpKKMH* zGm9qY6a!J{;1e)ij0U~&KVlZ(UJck4hcHA}!`2^Cg(>0!tKy@2|I+cC?=^Re#Q?@n z`3l`N5qx|!y`op!(yvdx-^vNOaijZlAee`~H!0S1FUi%bem1)octOZWvFlAiC=Y5X z@>#WCMFIS4BFwX!JQHxW#V6{mq*7g%EYltq$GK=$at8?7rak~Mb^mjs5dSOd9GUC_ z@V#cBnZ5AKW!h`Do^su*9(yubZMGJadZkYAIs+}7r%}pp`j0d;Z08Qjc$0xESGfS68i7IkfjL6|c9qr+czb*kyK)S6q8t^3542c;)wMQZ_hd&qP!1fgwJS z3Uca*Q;<_@uh@REyU!30fZd<`gQ^FMxInQk+VS8{YIBuU*14f4v771(90vOpPDm4F z6A37`uzboWT|)q6(RPnjD0M(XU_fWBB0>_EaoRyz%?xVi1_{jgxB!a%OB3rCvC87j z-{mm|Vw9&WvULW3RoHI;a~ad1TsN2|#zV>#0lez^;FXomCG+8l3O+sn*UwBOJ9v0z z@R*Z1*Yodh{t~fQB4u;#-JuqS_wWHZ(GF*gN6*>4E?P5P-jC24*f-iXMQht+jPLl= z`6=Ut?)ZZNzlJ5OHnPkfSrjk+h`jZo;ntF*>>n1p z@N(*E_a!AEL)dVYpi;s81-2K+Z2M$twTp~y-iXo;NyiS=j2z3ujBZfPHdC-|PZ?xP z(9XE49-HkZ(qX3cM$^Gb<+uYTQQr+c#W#xF zI!suTxgtW(i7Es{xf!s1rxW7wj8c9_kIJyAF}O^aiJr+OmvV3|Pa3mW!q!x8{Aw+8 zyhS=xOT$*J-{@Qvo>XWUKbsYcCamu1VS@IFE!!K`o`$XYV4pjX#xp^c^&hyL2R=Qr zcNm_}tnroEGHlE}?~d<2SOXP!P+0{>PMm&gmTuZ$7B617{vh`+Syj=Sdnz!5gx&O} z-h$&8n~UdqI&~iA(wG-hL7M+u#p%VRbiXH71^F#h=y%fKL?6^gcZ(9);M`EM7paVd zhx*t!e(mF&F3Cc12~~@S<`xXOOu6Yfra10L4&>3~<){5kmjs~*F&F!imSEHxG-qAS ze_I^=xG#K0{gkuVgwU``gL|20(J|MNt$7{IgB=k6s{^%Pxh0gy zqo+_A>%66{p?6=C4xD|w9bHjR-}9T=3h}*3;8gB*7|JiWZecSi@NarXhZT8|N9I@r zTFj4WMo7YA2y0R<$ctbcjQ4D)+q@jR`o2@zR_|Hcew-4#{0F$PyZTt6RM>3lDC`TC z)jiJ^B}I9j&K5ASyQ0(;9tx6M+sH=>|C^~xK=M#Mi1 zP)|&xAOXJQ8}awp^ZWLh?tPF&9(Oc>fO3TFSD=bqx7Fv2*%7(N=Zp2_rpNTsu`sNL zyf(YZoAM~>$6w4W;dcUX=e@Z6Xlw*8%Q?ZAEjY$cYTr!p>l(ZH&_=wu{rav3-bb;}mL|@jHhKiG-|INYwAP zul1{p!x@Ffv5^mxhtkuxU6-Exzyq%1fCnuPF(e4=AWhUn*8F)Z_O@4FXE-kB->7a_pI#uD-b+>nGjNmYLFE%5Bf=lIV=!yJ=sZ?dtU$>~KV zJ>MU)!U$ZrE*>V?=z~@xeYY?SRw3^x-xx1y*z5u_0 zxGz=x3A996NdL9O4!{+>P`v>@wl~dUn-xjcpMm8jpwDC<9hHgkS?!&c9Bo`zsQ6q7 zCTojfxYOJmT-`xeu3>w=-f?*slCT4(_wBA8B4q--8D!du|A%Rx`M4H)Ot^sfdAuZ} z$ccCC8AzJR@e z$YIe(i4UuceP?Ha%6BZ=zYd%|Ch3L0`-^TKRT;Dl1Z#KPdgPH=-jb|g(}8RBB_t6G zzTEiJo17!fBPt;1_J4PtJq5b+QMYl-jCNqb)&VH~$WLwEe1K5%EvUJ%07|q+mYDE9R&Wf_9deN)mA?(RMT9Z(LsMU^d6b7{N98*&?5)=1L*!ePZfIG_Zv-vrQHCNDwJMlh^XKG-A|q zU(&#~849$$y7Udj5+06ncj1d3OrZJraH*-fCBw*8`Up$(D@;N$ARdVljfC>)R@x+3{(@+68zt5mVp* zcN*&^yiWpFTzS{3eP|eO41Q(@HtLp}Usj*2Es!&VT(gvcNF!za-2CXKE6)fKLhy$U zZV>itH<>sc>QJmvnrG(0e_ckLFJK`xZTFWig$^o2#Fz%meYkoV5c?+x2y)wdvWjT1 zq$daxJvs?naJ>me#V)D_C6QVE_OdTS4E2ilFQAJ3&7YZp#h>C< zQ@we6x*&KKX?15@#Xec(nYyb0bS}AMioY!%_jUS>3z#cp-Y+Tbs&fn^03fVn@edjt z!FojU*M+zsnKT$9p}>`wTDl%J7~zAZkOobA+GHS+ekC&g0aPqL%?xbMg)A2@5evq3 z6N~F^Y1rembXvRl!Lxb1!J^BKFvhxEu*8!VjCALBOp-_?gTN9;DtfK&SiCO>P#|*M z+V4;Pt+r7xmxXGZeU<&TGARyZblm?!5W)V)X5A;CNoQaj#s${eGS`XoA!+s8D~;o&YHzRNFVeOZG2*dqf55H2ST?Fr!st>QvMhfX^$6|tuSTrwx7 zua|;NO_`D9gh9+;_Y{w=23i-$l*jiP03Uyl@xPQ|CHtoN=y~_r7}>2a>xNgMkQac6 zCN;Rx1IRye+$?KYlsY)|pGd$w@_$z)|KIC=#wbpU*yT5{UUh&5G80ny|Xb?^LK z-#_Km>CGE|1$8f;CntlA1*o!V1hiQ9isS9p`6bMH;^zM;@P44<`bN0BngVbMzQ}^d z+kgoXlPyQ*5~q_@YYlEo!c|ShFZuLa+T@^#KeOBaT4Z2iBDRb5&i0fd7dTn?riO=RQXeLd@k)Lh*ioY61v< zk*j9fP%Rs~-C1&>0IKLp_uiDJ{>A?i5W?N!CXmaVLeSC$pv>gg$z|m0RHvMNHzWr* zo5OkZbi)KR{NJ&j$gG={BYQK3-myg-u^Oa9$_D>b`13##Z~(c?>E2)5QA=R0CUmc2 zxmerK;}7$LNr?`y_}+afjE%mwB$5v`_H<{`_!`1@tsw-p?S8pks&(EC$~#T - Timeout (minutes) - - - - Trim History - + Local node-bootstrap url + @@ -58,59 +54,6 @@

-
-
InfluxDB2 config
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Enable -
- {{ if .Config.InfluxEnable }} - - {{ else }} - - {{ end }} -
-
Address
Token
Org
Bucket
Skip TLS verify -
- {{ if .Config.InfluxSkipTLS }} - - {{ else }} - - {{ end }} -
-
-
-
About
diff --git a/internal/web/webgui.go b/internal/web/webgui.go index b287c00..3017000 100644 --- a/internal/web/webgui.go +++ b/internal/web/webgui.go @@ -23,6 +23,9 @@ func Gui(dirPath, nodePath string) { appConfig.ConfPath = confPath appConfig.NodePath = nodePath + // temp + appConfig.Ifaces = append(appConfig.Ifaces, "enp4s0") + slog.Info("config", "path", appConfig.DirPath) address := appConfig.Host + ":" + appConfig.Port