2020-05-27 13:48:31 +00:00
|
|
|
package gui
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os/exec"
|
|
|
|
"sort"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/UnnoTed/wireguird/gui/get"
|
|
|
|
"github.com/dustin/go-humanize"
|
|
|
|
"github.com/gotk3/gotk3/glib"
|
|
|
|
"github.com/gotk3/gotk3/gtk"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/ungerik/go-dry"
|
|
|
|
"gopkg.in/ini.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
var Connected = false
|
|
|
|
|
|
|
|
type Tunnels struct {
|
|
|
|
Interface struct {
|
|
|
|
Status *gtk.Label
|
|
|
|
PublicKey *gtk.Label
|
|
|
|
ListenPort *gtk.Label
|
|
|
|
Addresses *gtk.Label
|
|
|
|
DNS *gtk.Label
|
|
|
|
}
|
|
|
|
|
|
|
|
Peer struct {
|
|
|
|
PublicKey *gtk.Label
|
|
|
|
AllowedIPs *gtk.Label
|
|
|
|
Endpoint *gtk.Label
|
|
|
|
LatestHandshake *gtk.Label
|
|
|
|
Transfer *gtk.Label
|
|
|
|
}
|
|
|
|
|
|
|
|
ButtonChangeState *gtk.Button
|
|
|
|
icons map[string]*gtk.Image
|
|
|
|
ticker *time.Ticker
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Tunnels) Create() error {
|
|
|
|
t.icons = map[string]*gtk.Image{}
|
|
|
|
t.ticker = time.NewTicker(1 * time.Second)
|
|
|
|
|
|
|
|
var configList []string
|
|
|
|
list, err := dry.ListDirFiles("/etc/wireguard/")
|
|
|
|
if err != nil {
|
|
|
|
// showError(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, fileName := range list {
|
|
|
|
if !strings.HasSuffix(fileName, ".conf") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
configList = append(configList, strings.TrimSuffix(fileName, ".conf"))
|
|
|
|
}
|
|
|
|
|
|
|
|
tl, err := get.ListBox("tunnel_list")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Slice(configList, func(a, b int) bool {
|
|
|
|
return configList[a] < configList[b]
|
|
|
|
})
|
|
|
|
|
|
|
|
activeName := t.ActiveDeviceName()
|
|
|
|
|
|
|
|
lasti := len(configList) - 1
|
|
|
|
for i, name := range configList {
|
|
|
|
row, err := gtk.ListBoxRowNew()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
row.SetName(name)
|
|
|
|
row.SetMarginStart(8)
|
|
|
|
row.SetMarginEnd(8)
|
|
|
|
if i == 0 {
|
|
|
|
row.SetMarginTop(8)
|
|
|
|
} else if i == lasti {
|
|
|
|
row.SetMarginBottom(8)
|
|
|
|
}
|
|
|
|
|
|
|
|
// icon, err := gtk.ButtonNew()
|
|
|
|
// icon, err := gtk.ColorButtonNew()
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
var img *gtk.Image
|
|
|
|
|
|
|
|
if activeName == name {
|
2021-02-28 20:47:03 +00:00
|
|
|
green, err := gtk.ImageNewFromFile("/opt/wireguird/Icon/dot-green.png")
|
2020-05-27 13:48:31 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
img = green
|
|
|
|
} else {
|
2021-02-28 20:47:03 +00:00
|
|
|
gray, err := gtk.ImageNewFromFile("/opt/wireguird/Icon/dot-gray.png")
|
2020-05-27 13:48:31 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
img = gray
|
|
|
|
}
|
|
|
|
|
|
|
|
t.icons[name] = img
|
2021-02-28 20:47:03 +00:00
|
|
|
// img, err := gtk.ImageNewFromFile("/opt/wireguird/Icon/dot-gray.png")
|
2020-05-27 13:48:31 +00:00
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
// icon.SetImage(img)
|
|
|
|
|
|
|
|
// dg, err := static.ReadFile("icon/dot-gray.svg")
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pbl, err := gdk.PixbufLoaderNew()
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
// pb, err := pbl.WriteAndReturnPixbuf(dg)
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
// img, err := gtk.ImageNewFromPixbuf(pb)
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
// icon.Image
|
|
|
|
// icon.SetImage(img)
|
|
|
|
|
|
|
|
img.SetVAlign(gtk.ALIGN_CENTER)
|
|
|
|
img.SetHAlign(gtk.ALIGN_START)
|
|
|
|
img.SetSizeRequest(10, 10)
|
|
|
|
// icon.SetMarginBottom(0)
|
|
|
|
// icon.SetMarginTop(0)
|
|
|
|
img.SetVExpand(false)
|
|
|
|
img.SetHExpand(false)
|
|
|
|
|
|
|
|
// sctx, err := icon.GetStyleContext()
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
// sctx.AddClass("circular")
|
|
|
|
|
|
|
|
// if name == activeName {
|
|
|
|
// sctx.AddClass("btn-green")
|
|
|
|
// // rgba := gdk.NewRGBA(102, 204, 153, 1)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
label, err := gtk.LabelNew(name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
label.SetHAlign(gtk.ALIGN_START)
|
|
|
|
// label.SetHExpand(true)
|
|
|
|
|
|
|
|
label.SetMarginStart(8)
|
|
|
|
label.SetMarginEnd(8)
|
|
|
|
label.SetMarginTop(8)
|
|
|
|
label.SetMarginBottom(8)
|
|
|
|
|
|
|
|
box, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 4)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
box.Add(img)
|
|
|
|
box.Add(label)
|
|
|
|
|
|
|
|
row.SetName(name)
|
|
|
|
row.Add(box)
|
|
|
|
row.ShowAll()
|
|
|
|
tl.Insert(row, -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.Status, err = get.Label("label_interface_status")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.PublicKey, err = get.Label("label_interface_public_key")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.ListenPort, err = get.Label("label_interface_listen_port")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.Addresses, err = get.Label("label_interface_addresses")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.DNS, err = get.Label("label_interface_dns_servers")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Peer.PublicKey, err = get.Label("label_peer_public_key")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Peer.AllowedIPs, err = get.Label("label_peer_allowed_ips")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Peer.Endpoint, err = get.Label("label_peer_endpoint")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Peer.LatestHandshake, err = get.Label("label_peer_latest_handshake")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Peer.Transfer, err = get.Label("label_peer_transfer")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.ButtonChangeState, err = get.Button("button_change_state")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.ButtonChangeState.Connect("clicked", func() {
|
|
|
|
err := func() error {
|
|
|
|
list, err := wgc.Devices()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
activeName = t.ActiveDeviceName()
|
|
|
|
for _, d := range list {
|
2021-02-28 20:47:03 +00:00
|
|
|
gray, err := gtk.ImageNewFromFile("/opt/wireguird/Icon/dot-gray.png")
|
2020-05-27 13:48:31 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.icons[d.Name].SetFromPixbuf(gray.GetPixbuf())
|
|
|
|
})
|
|
|
|
|
|
|
|
if err := exec.Command("wg-quick", "down", d.Name).Run(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
indicator.SetIcon("wireguard_off")
|
|
|
|
}
|
|
|
|
|
|
|
|
row := tl.GetSelectedRow()
|
2021-02-28 20:47:03 +00:00
|
|
|
// row not found for config
|
|
|
|
if row == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-27 13:48:31 +00:00
|
|
|
name, err := row.GetName()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// dont connect to the new one
|
|
|
|
if activeName != "" && activeName == name {
|
|
|
|
t.UpdateRow(row)
|
2021-02-28 20:47:03 +00:00
|
|
|
|
|
|
|
glib.IdleAdd(func() {
|
|
|
|
header.SetSubtitle("Not connected!")
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := exec.Command("wg-quick", "up", name).Run(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
glib.IdleAdd(func() {
|
|
|
|
header.SetSubtitle("Connected to " + name)
|
|
|
|
})
|
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
green, err := gtk.ImageNewFromFile("/opt/wireguird/Icon/dot-green.png")
|
2020-05-27 13:48:31 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.icons[name].SetFromPixbuf(green.GetPixbuf())
|
|
|
|
t.UpdateRow(row)
|
|
|
|
indicator.SetIcon("wireguard")
|
|
|
|
})
|
2021-02-28 20:47:03 +00:00
|
|
|
|
|
|
|
if err := wlog("INFO", "Connected to "+name); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-05-27 13:48:31 +00:00
|
|
|
return nil
|
|
|
|
}()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
ShowError(window, err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// boxPeers, err := get.Box("box_peers")
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
tl.Connect("row-activated", func(l *gtk.ListBox, row *gtk.ListBoxRow) {
|
|
|
|
t.UpdateRow(row)
|
|
|
|
})
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
<-t.ticker.C
|
|
|
|
|
|
|
|
if !window.HasToplevelFocus() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
row := tl.GetSelectedRow()
|
2021-02-28 20:47:03 +00:00
|
|
|
if row == nil {
|
|
|
|
t.UnknownLabels()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-05-27 13:48:31 +00:00
|
|
|
name, err := row.GetName()
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("row get name err")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if name != t.ActiveDeviceName() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
d, err := wgc.Device(name)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("wgc get device err")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Interface.PublicKey.SetText(d.PublicKey.String())
|
|
|
|
t.Interface.ListenPort.SetText(strconv.Itoa(d.ListenPort))
|
|
|
|
|
|
|
|
for _, p := range d.Peers {
|
|
|
|
hs := humanize.Time(p.LastHandshakeTime)
|
2021-02-28 20:47:03 +00:00
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.Peer.LatestHandshake.SetText(hs)
|
|
|
|
t.Peer.Transfer.SetText(humanize.Bytes(uint64(p.ReceiveBytes)) + " received, " + humanize.Bytes(uint64(p.TransmitBytes)) + " sent")
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (t *Tunnels) UpdateRow(row *gtk.ListBoxRow) {
|
|
|
|
err := func() error {
|
|
|
|
ds, err := wgc.Devices()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug().Interface("list", ds).Msg("devices")
|
|
|
|
|
|
|
|
id, err := row.GetName()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg, err := ini.Load("/etc/wireguard/" + id + ".conf")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.UnknownLabels()
|
|
|
|
|
|
|
|
peersec := cfg.Section("Peer")
|
|
|
|
insec := cfg.Section("Interface")
|
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.Interface.Addresses.SetText(insec.Key("Address").String())
|
|
|
|
t.Interface.Status.SetText("Inactive")
|
|
|
|
t.Interface.DNS.SetText(insec.Key("DNS").String())
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.ButtonChangeState.SetLabel("Activate")
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.Peer.AllowedIPs.SetText(peersec.Key("AllowedIPs").String())
|
|
|
|
t.Peer.PublicKey.SetText(peersec.Key("PublicKey").String())
|
|
|
|
t.Peer.Endpoint.SetText(peersec.Key("Endpoint").String())
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
|
|
|
|
for _, d := range ds {
|
|
|
|
if d.Name != id {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// i'll do this later
|
|
|
|
// _ = boxPeers
|
|
|
|
// boxPeers.GetChildren().Foreach(func(item interface{}) {
|
|
|
|
// boxPeers.Remove(item.(*gtk.Widget))
|
|
|
|
// })
|
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.Interface.Status.SetText("Active")
|
|
|
|
t.ButtonChangeState.SetLabel("Deactivate")
|
|
|
|
t.Interface.PublicKey.SetText(d.PublicKey.String())
|
|
|
|
t.Interface.ListenPort.SetText(strconv.Itoa(d.ListenPort))
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
|
|
|
|
for _, p := range d.Peers {
|
|
|
|
hs := humanize.Time(p.LastHandshakeTime)
|
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.Peer.LatestHandshake.SetText(hs)
|
|
|
|
t.Peer.Transfer.SetText(humanize.Bytes(uint64(p.ReceiveBytes)) + " received, " + humanize.Bytes(uint64(p.TransmitBytes)) + " sent")
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("row activated")
|
|
|
|
ShowError(window, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Tunnels) UnknownLabels() {
|
2021-02-28 20:47:03 +00:00
|
|
|
glib.IdleAdd(func() {
|
|
|
|
t.ButtonChangeState.SetLabel("unknown")
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.Interface.Addresses.SetText("unknown")
|
|
|
|
t.Interface.Status.SetText("unknown")
|
|
|
|
t.Interface.DNS.SetText("unknown")
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.Peer.AllowedIPs.SetText("unknown")
|
|
|
|
t.Peer.PublicKey.SetText("unknown")
|
|
|
|
t.Peer.Endpoint.SetText("unknown")
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.Interface.Status.SetText("unknown")
|
|
|
|
t.ButtonChangeState.SetLabel("unknown")
|
|
|
|
t.Interface.PublicKey.SetText("unknown")
|
|
|
|
t.Interface.ListenPort.SetText("unknown")
|
|
|
|
t.Peer.LatestHandshake.SetText("unknown")
|
2020-05-27 13:48:31 +00:00
|
|
|
|
2021-02-28 20:47:03 +00:00
|
|
|
t.Peer.Transfer.SetText("unknown")
|
|
|
|
})
|
2020-05-27 13:48:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Tunnels) ActiveDeviceName() string {
|
|
|
|
ds, _ := wgc.Devices()
|
|
|
|
|
|
|
|
for _, d := range ds {
|
|
|
|
return d.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|
2021-02-28 20:47:03 +00:00
|
|
|
|
|
|
|
func wlog(t string, text string) error {
|
|
|
|
wlogs, err := get.ListBox("wireguard_logs")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
l, err := gtk.LabelNew("")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if t == "ERROR" {
|
|
|
|
t = `<span color="#FF0000">` + t + "</span>"
|
|
|
|
}
|
|
|
|
|
|
|
|
l.SetMarkup(`<span color="#008080">[` + time.Now().Format("02/Jan/06 15:04:05 MST") + `]</span>[` + t + `]: ` + text)
|
|
|
|
l.SetHExpand(true)
|
|
|
|
l.SetHAlign(gtk.ALIGN_START)
|
|
|
|
|
|
|
|
glib.IdleAdd(func() {
|
|
|
|
l.Show()
|
|
|
|
wlogs.Add(l)
|
|
|
|
})
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|