package vpn import ( "context" "io" "net/netip" "time" "git.jasinco.work/wgcl/internal/logger" "git.jasinco.work/wgcl/internal/wg" protovpn "git.jasinco.work/wgcl/proto/out" "github.com/gin-gonic/gin" "google.golang.org/protobuf/encoding/protojson" ) var wgctrl *wg.WG var sync_cancel context.CancelFunc func SyncWGStat(ctx context.Context) { for { select { case <-ctx.Done(): return default: wgctrl.SyncStatus() logger.Logger.Info("sync wg status") time.Sleep(5 * time.Second) } } } func StartWG() { var err error baseip4 := netip.AddrFrom4([4]byte{172, 16, 0, 1}) pool := wg.IPPool_Init(baseip4, 26) wgctrl, err = wg.WG_init("wg0", wg.NewKey(), 51823, pool) if err != nil { logger.Logger.Warn(err.Error()) logger.Logger.Fatal("Failed init wgctrl") } ctx, cancel := context.WithCancel(context.Background()) sync_cancel = cancel go SyncWGStat(ctx) } func StopWG() { logger.Logger.Info("Stopping WG") sync_cancel() wgctrl.Deinit() } func GETPeers(c *gin.Context) { resp := wgctrl.GetPeersJson() resp_json, err := protojson.Marshal(resp) if err != nil { c.Status(500) return } c.Data(200, "application/json", resp_json) } func NewPeer(c *gin.Context) { req := &protovpn.PeerReq{} req_json, err := io.ReadAll(c.Request.Body) if err != nil { c.Status(400) return } if protojson.Unmarshal(req_json, req) != nil { c.Status(400) return } wgctrl.WriteTxStart() defer wgctrl.WriteTxEnd() var ip4 *netip.Addr if req.HasIp4() { _ip4, err := netip.ParseAddr(req.GetIp4()) ip4 = &_ip4 if err != nil { c.Status(400) return } } else { _ip4, err := wgctrl.IP4Pool.Next() if err != nil { logger.Logger.Warn("ip pool exhausted") c.Status(500) return } ip4 = &_ip4 } peer := wg.WGPeer_init(req.GetName(), wg.NewKey(), *ip4) wgctrl.AddPeer(peer) wgctrl.IP4Pool.Lease(*ip4) wgctrl.Apply() c.Status(200) } func SearchPeer(c *gin.Context) { if pubkey := c.Query("pubkey"); len(pubkey) > 0 { p, err := wgctrl.SearchPeerPubkey(pubkey) if p == nil { if err != nil { logger.Logger.Warn(err.Error()) } c.Status(400) return } b, err := protojson.Marshal(p.ToPeerStatus()) if err != nil { logger.Logger.Warn(err.Error()) } c.Data(200, "application/json", b) } else { c.Status(400) } } func DeletePeer(c *gin.Context) { if pubkey := c.Query("pubkey"); len(pubkey) > 0 { p, err := wgctrl.SearchPeerPubkey(pubkey) if p == nil { if err != nil { logger.Logger.Warn(err.Error()) } c.Status(400) return } wgctrl.WriteTxStart() defer wgctrl.WriteTxEnd() p.Disable() if err = wgctrl.Apply(); err != nil { logger.Logger.Warn("Can't apply disable peer") } wgctrl.RemovePeer(p) c.Status(200) } else { c.Status(400) } }