feat: monitor peers in logs, README, Status
Signed-off-by: HeshamTB <hishaminv@gmail.com>
This commit is contained in:
parent
4bab068c10
commit
ed0fcb59eb
@ -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 .
|
||||||
|
@ -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
5
const.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package hvpnnode3
|
||||||
|
|
||||||
|
const (
|
||||||
|
CONTENT_JSON = "application/json"
|
||||||
|
)
|
17
handlers.go
17
handlers.go
@ -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
61
monitor.go
Normal 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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user