feat: monitor peers in logs, README, Status

Signed-off-by: HeshamTB <hishaminv@gmail.com>
This commit is contained in:
HeshamTB 2024-03-19 02:56:52 +03:00
parent 4bab068c10
commit ed0fcb59eb
5 changed files with 79 additions and 11 deletions

View File

@ -1,5 +1,8 @@
# hvpn-node3 # hvpn-node3
hvpn is a basic HTTP API service that manages wireguard VPN. Can be part of part of
a larger system of services. The program itself does not route and manage the
VPN traffic; but the underlying host and kernel wiregaurd driver. hvpn only
exposes the state and allows changes to be applied.
## Build ## Build
```bash ```bash
cd cmd/hvpn-node && go build . cd cmd/hvpn-node && go build .

View File

@ -55,6 +55,8 @@ func main() {
func run(ctx *cli.Context) { func run(ctx *cli.Context) {
slog.Debug("Starting run()") slog.Debug("Starting run()")
hvpnnode3.StartMonitor(wgLink, *slog.Default())
apiMux := http.NewServeMux() apiMux := http.NewServeMux()
apiMux.HandleFunc("GET /node", hvpnnode3.HandleGetNodeInfo(wgLink)) apiMux.HandleFunc("GET /node", hvpnnode3.HandleGetNodeInfo(wgLink))
apiMux.HandleFunc("GET /peer/{pubkey}", hvpnnode3.HandleGetPeer(wgLink)) apiMux.HandleFunc("GET /peer/{pubkey}", hvpnnode3.HandleGetPeer(wgLink))

5
const.go Normal file
View File

@ -0,0 +1,5 @@
package hvpnnode3
const (
CONTENT_JSON = "application/json"
)

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"net/http" "net/http"
"net/url"
"github.com/felixge/httpsnoop" "github.com/felixge/httpsnoop"
"github.com/google/uuid" "github.com/google/uuid"
@ -119,15 +120,8 @@ func HandlePostPeer(wgLink *WGLink) http.HandlerFunc {
} }
if exists { if exists {
debugf("Peer %s already exists", reqID, peerRequest.PublicKey) debugf("Peer %s already exists", reqID, peerRequest.PublicKey)
w.WriteHeader(http.StatusFound) w.Header().Add("Location", fmt.Sprintf("/peer/%s", url.QueryEscape(peerRequest.PublicKey)))
peer, err := wgLink.GetPeer(peerRequest.PublicKey) w.WriteHeader(http.StatusConflict)
if err != nil {
slog.Error(err.Error())
return
}
json.NewEncoder(w).Encode(
proto.WgPeerToPeer(*peer),
)
return return
} }
@ -140,7 +134,9 @@ func HandlePostPeer(wgLink *WGLink) http.HandlerFunc {
) )
return return
} }
debugf("Allocated IP: %s", reqID, peer.AllowedIPs[0].IP.String()) infof("Allocated IP: %s", reqID, peer.AllowedIPs[0].IP.String())
infof("Peer %s added", reqID, peerRequest.PublicKey)
w.Header().Set("Content-Type", CONTENT_JSON)
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode( json.NewEncoder(w).Encode(
proto.WgPeerToPeer(*peer), proto.WgPeerToPeer(*peer),
@ -174,6 +170,7 @@ func HandleDeletePeer(wg *WGLink) http.HandlerFunc {
) )
slog.Error(err.Error()) slog.Error(err.Error())
} }
w.WriteHeader(http.StatusNoContent)
} }
} }

61
monitor.go Normal file
View File

@ -0,0 +1,61 @@
package hvpnnode3
import (
"fmt"
"log/slog"
"strings"
"time"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
var log slog.Logger
func StartMonitor(wg *WGLink, log slog.Logger) {
go monitor(wg, log)
}
func monitor(wg *WGLink, log slog.Logger) {
log.Info("[WGMonitor] Starting")
for {
time.Sleep(time.Second * 5)
peers, err := wg.GetAllPeers()
if err != nil {
log.Error("[WGMonitor] " + err.Error())
continue
}
activepeers, err := getActivePeers(peers)
if err != nil {
log.Error("[WGMonitor] " + err.Error())
continue
}
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("Peers: %d ", len(peers)))
sb.WriteString(fmt.Sprintf("Active peers: %d ", len(activepeers)))
var totalRx int64
var totalTx int64
for _, peer := range activepeers {
totalRx += peer.ReceiveBytes
totalTx += peer.TransmitBytes
}
sb.WriteString(fmt.Sprintf("TX: %d RX: %d", totalTx, totalRx))
log.Info("[WGMonitor] " + sb.String())
}
}
func getActivePeers(peers []wgtypes.Peer) ([]wgtypes.Peer, error) {
active := make([]wgtypes.Peer, 0)
for _, peer := range peers {
if peer.LastHandshakeTime.IsZero() {
continue
} else if time.Now().UTC().Sub(peer.LastHandshakeTime.UTC()) < time.Duration(4 * time.Minute) {
active = append(active, peer)
}
}
return active, nil
}