WIP: Rewrite package with napi-go #18
257
addon/addon.go
257
addon/addon.go
@@ -1,257 +0,0 @@
|
||||
package addon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/abhisekp/napi-go"
|
||||
napiEntry "github.com/abhisekp/napi-go/entry"
|
||||
"github.com/abhisekp/napi-go/js"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// napiEntry.Export("constant", func(env napi.Env, info napi.CallbackInfo) napi.Value { return nil })
|
||||
// deleteInterface(name: string): Promise<void>;
|
||||
// napiEntry.Export("deleteInterface", GetInterface)
|
||||
napiEntry.Export("getConfig", GetInterface)
|
||||
napiEntry.Export("setConfig", SetInterface)
|
||||
}
|
||||
|
||||
type PkgInfo struct {
|
||||
DriveVersion string `json:"driveVersion"`
|
||||
}
|
||||
|
||||
type Peer struct {
|
||||
PresharedKey string
|
||||
KeepInterval int
|
||||
Endpoint string
|
||||
AllowedIPs []net.IPNet
|
||||
|
||||
RemoveMe bool
|
||||
RxByte int
|
||||
TxByte int
|
||||
LastHandshake time.Time
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
PortListen int
|
||||
Fwmark int
|
||||
ReplacePeers bool
|
||||
Address []netip.Addr
|
||||
Peers map[string]*Peer
|
||||
}
|
||||
|
||||
func mustBigInt(env napi.Env, v int) napi.Value {
|
||||
b, _ := napi.CreateBigIntInt64(env, int64(v))
|
||||
return b
|
||||
}
|
||||
|
||||
func processArgs(env napi.Env, info napi.CallbackInfo) ([]js.Value, error) {
|
||||
cbInfo, st := napi.GetCbInfo(env, info)
|
||||
if st != napi.StatusOK {
|
||||
return nil, napi.StatusError(st)
|
||||
}
|
||||
jsEnv := js.AsEnv(env)
|
||||
args := make([]js.Value, len(cbInfo.Args))
|
||||
for i, cbArg := range cbInfo.Args {
|
||||
args[i] = js.Value{
|
||||
Env: jsEnv,
|
||||
Value: cbArg,
|
||||
}
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (cfg Config) ToNapi(env napi.Env) napi.Value {
|
||||
obj := map[string]any{}
|
||||
addrs := []string{}
|
||||
peers := map[string]map[string]any{}
|
||||
|
||||
for _, addr := range cfg.Address {
|
||||
addrs = append(addrs, addr.String())
|
||||
}
|
||||
|
||||
for pubKey, peer := range cfg.Peers {
|
||||
peerAddr := []string{}
|
||||
for _, addr := range peer.AllowedIPs {
|
||||
peerAddr = append(peerAddr, addr.String())
|
||||
}
|
||||
|
||||
peers[pubKey] = map[string]any{
|
||||
"presharedKey": peer.PresharedKey,
|
||||
"keepInterval": peer.KeepInterval,
|
||||
"endpoint": peer.Endpoint,
|
||||
"allowdIPs": peerAddr,
|
||||
"lastHandshake": peer.LastHandshake,
|
||||
"rxBytes": mustBigInt(env, peer.RxByte),
|
||||
"txBytes": mustBigInt(env, peer.TxByte),
|
||||
}
|
||||
}
|
||||
|
||||
obj["privateKey"] = cfg.PrivateKey
|
||||
obj["publicKey"] = cfg.PrivateKey
|
||||
obj["portListen"] = cfg.PortListen
|
||||
obj["fwmark"] = cfg.Fwmark
|
||||
obj["fwmark"] = cfg.Fwmark
|
||||
obj["address"] = addrs
|
||||
obj["peers"] = peers
|
||||
|
||||
return js.AsEnv(env).ValueOf(obj).Value
|
||||
}
|
||||
|
||||
func mustNapi[T any](v T, _ napi.Status) T {
|
||||
return v
|
||||
}
|
||||
|
||||
func (cfg *Config) FromNapi(env napi.Env, info napi.CallbackInfo) error {
|
||||
args, err := processArgs(env, info)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(args) == 0 {
|
||||
return errors.New("return config to Wireguard interface")
|
||||
}
|
||||
configValue := args[0].Value
|
||||
if !mustNapi(napi.HasNamedProperty(env, configValue, "name")) {
|
||||
return fmt.Errorf("set wireguard interface name!")
|
||||
} else if !mustNapi(napi.HasNamedProperty(env, configValue, "privateKey")) {
|
||||
return fmt.Errorf("require privateKey to wireguard interface")
|
||||
}
|
||||
|
||||
cfg.Name = mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetNamedProperty(env, configValue, "name"))))
|
||||
cfg.PrivateKey = mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetNamedProperty(env, configValue, "privateKey"))))
|
||||
if mustNapi(napi.HasNamedProperty(env, configValue, "publicKey")) {
|
||||
cfg.PublicKey = mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetNamedProperty(env, configValue, "publicKey"))))
|
||||
}
|
||||
if mustNapi(napi.HasNamedProperty(env, configValue, "portListen")) {
|
||||
cfg.PortListen = int(mustNapi(napi.GetValueInt32(env, mustNapi(napi.GetNamedProperty(env, configValue, "portListen")))))
|
||||
}
|
||||
if mustNapi(napi.HasNamedProperty(env, configValue, "fwmark")) {
|
||||
cfg.Fwmark = int(mustNapi(napi.GetValueInt64(env, mustNapi(napi.GetNamedProperty(env, configValue, "fwmark")))))
|
||||
}
|
||||
if mustNapi(napi.HasNamedProperty(env, configValue, "replacePeers")) {
|
||||
cfg.ReplacePeers = mustNapi(napi.GetValueBool(env, mustNapi(napi.GetNamedProperty(env, configValue, "replacePeers"))))
|
||||
}
|
||||
|
||||
if mustNapi(napi.IsArray(env, mustNapi(napi.GetNamedProperty(env, configValue, "address")))) {
|
||||
arrayValue := mustNapi(napi.GetNamedProperty(env, configValue, "address"))
|
||||
sliceSize := mustNapi(napi.GetArrayLength(env, arrayValue))
|
||||
cfg.Address = make([]netip.Addr, sliceSize)
|
||||
for index := range sliceSize {
|
||||
addrStr := mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetElement(env, arrayValue, index))))
|
||||
if cfg.Address[index], err = netip.ParseAddr(addrStr); err != nil {
|
||||
return fmt.Errorf("%s: %s", addrStr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mustNapi(napi.HasNamedProperty(env, configValue, "peers")) {
|
||||
cfg.Peers = map[string]*Peer{}
|
||||
|
||||
peers := mustNapi(napi.GetNamedProperty(env, configValue, "peers"))
|
||||
keys := mustNapi(napi.GetPropertyNames(env, peers))
|
||||
keysSize := mustNapi(napi.GetArrayLength(env, keys))
|
||||
for index := range keysSize {
|
||||
publicKey := mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetElement(env, keys, index))))
|
||||
peerObj := mustNapi(napi.GetNamedProperty(env, peers, publicKey))
|
||||
|
||||
if mustNapi(napi.HasNamedProperty(env, peerObj, "removeMe")) && mustNapi(napi.GetValueBool(env, mustNapi(napi.GetNamedProperty(env, peers, "removeMe")))) {
|
||||
cfg.Peers[publicKey] = &Peer{RemoveMe: true}
|
||||
} else {
|
||||
peerInfo := &Peer{}
|
||||
cfg.Peers[publicKey] = peerInfo
|
||||
|
||||
if mustNapi(napi.HasNamedProperty(env, peerObj, "presharedKey")) {
|
||||
peerInfo.PresharedKey = mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetNamedProperty(env, peerObj, "presharedKey"))))
|
||||
}
|
||||
if mustNapi(napi.HasNamedProperty(env, peerObj, "keepInterval")) {
|
||||
peerInfo.KeepInterval = int(mustNapi(napi.GetValueInt32(env, mustNapi(napi.GetNamedProperty(env, peerObj, "keepInterval")))))
|
||||
}
|
||||
if mustNapi(napi.HasNamedProperty(env, peerObj, "endpoint")) {
|
||||
peerInfo.Endpoint = mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetNamedProperty(env, peerObj, "endpoint"))))
|
||||
}
|
||||
if mustNapi(napi.IsArray(env, mustNapi(napi.GetNamedProperty(env, peerObj, "allowedIPs")))) {
|
||||
ips := mustNapi(napi.GetNamedProperty(env, peerObj, "allowedIPs"))
|
||||
ipsSize := mustNapi(napi.GetArrayLength(env, ips))
|
||||
peerInfo.AllowedIPs = make([]net.IPNet, ipsSize)
|
||||
for index := range ipsSize {
|
||||
addr := mustNapi(napi.GetValueStringUtf8(env, mustNapi(napi.GetElement(env, ips, index))))
|
||||
if _, ip, err := net.ParseCIDR(addr); err == nil {
|
||||
peerInfo.AllowedIPs[index] = *ip
|
||||
} else {
|
||||
ipAddr, err := netip.ParseAddr(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ipAddr.Is4() {
|
||||
peerInfo.AllowedIPs[index] = net.IPNet{IP: net.ParseIP(addr), Mask: net.CIDRMask(31, 32)}
|
||||
} else {
|
||||
peerInfo.AllowedIPs[index] = net.IPNet{IP: net.ParseIP(addr), Mask: net.CIDRMask(64, 128)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func pointValue[T any](v T) *T { return &v }
|
||||
|
||||
func (cfg Config) WgConfig() (wgtypes.Config, error) {
|
||||
config := wgtypes.Config{
|
||||
ListenPort: pointValue(cfg.PortListen),
|
||||
FirewallMark: pointValue(cfg.Fwmark),
|
||||
ReplacePeers: cfg.ReplacePeers,
|
||||
Peers: []wgtypes.PeerConfig{},
|
||||
}
|
||||
pk, err := wgtypes.ParseKey(cfg.PrivateKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
config.PrivateKey = pointValue(pk)
|
||||
|
||||
for peerKey, peerInfo := range cfg.Peers {
|
||||
pb, err := wgtypes.ParseKey(peerKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
|
||||
if peerInfo.RemoveMe {
|
||||
config.Peers = append(config.Peers, wgtypes.PeerConfig{
|
||||
PublicKey: pb,
|
||||
Remove: true,
|
||||
})
|
||||
} else {
|
||||
peer := wgtypes.PeerConfig{PublicKey: pb, AllowedIPs: peerInfo.AllowedIPs}
|
||||
if peerInfo.PresharedKey != "" {
|
||||
pr, err := wgtypes.ParseKey(peerInfo.PresharedKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
peer.PresharedKey = pointValue(pr)
|
||||
}
|
||||
|
||||
if peerInfo.Endpoint != "" {
|
||||
if peer.Endpoint, err = net.ResolveUDPAddr("udp", peerInfo.Endpoint); err != nil {
|
||||
return config, err
|
||||
}
|
||||
}
|
||||
|
||||
peer.PersistentKeepaliveInterval = pointValue(time.Duration(peerInfo.KeepInterval))
|
||||
|
||||
// Append to config
|
||||
config.Peers = append(config.Peers, peer)
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
126
addon/linux.go
126
addon/linux.go
@@ -1,126 +0,0 @@
|
||||
//go:build linux
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/abhisekp/napi-go"
|
||||
"github.com/abhisekp/napi-go/js"
|
||||
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
// args: [Name: string]
|
||||
func GetInterface(env napi.Env, info napi.CallbackInfo) napi.Value {
|
||||
args, err := processArgs(env, info)
|
||||
if err != nil {
|
||||
napi.Throw(env, js.AsEnv(env).ValueOf(err.Error()).Value)
|
||||
return nil
|
||||
}
|
||||
|
||||
promise, _ := napi.CreatePromise(env)
|
||||
asyncResourceName, _ := napi.CreateStringUtf8(env, "addon/GetInterface")
|
||||
devInfo := &Config{}
|
||||
|
||||
var worker napi.AsyncWork
|
||||
worker, _ = napi.CreateAsyncWork(env, nil, asyncResourceName,
|
||||
func(env napi.Env) {
|
||||
if len(args) == 0 {
|
||||
err = errors.New("Set interface name")
|
||||
return
|
||||
}
|
||||
|
||||
// Interface name
|
||||
interfaceName, _ := napi.GetValueStringUtf8(args[0].Env.Env, args[0].Value)
|
||||
|
||||
// Get client to wireguard
|
||||
var client *wgctrl.Client
|
||||
if client, err = wgctrl.New(); err != nil {
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Get config
|
||||
var dev *wgtypes.Device
|
||||
if dev, err = client.Device(interfaceName); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
devInfo.PublicKey = dev.PublicKey.String()
|
||||
devInfo.PrivateKey = dev.PrivateKey.String()
|
||||
devInfo.PortListen = dev.ListenPort
|
||||
devInfo.Fwmark = dev.FirewallMark
|
||||
devInfo.Peers = map[string]*Peer{}
|
||||
for _, peer := range dev.Peers {
|
||||
devInfo.Peers[peer.PublicKey.String()] = &Peer{
|
||||
PresharedKey: peer.PresharedKey.String(),
|
||||
LastHandshake: peer.LastHandshakeTime,
|
||||
KeepInterval: int(peer.PersistentKeepaliveInterval.Seconds()),
|
||||
TxByte: int(peer.TransmitBytes),
|
||||
RxByte: int(peer.ReceiveBytes),
|
||||
AllowedIPs: peer.AllowedIPs,
|
||||
}
|
||||
if peer.Endpoint != nil {
|
||||
devInfo.Peers[peer.PublicKey.String()].Endpoint = peer.Endpoint.String()
|
||||
}
|
||||
}
|
||||
},
|
||||
func(env napi.Env, status napi.Status) {
|
||||
defer napi.DeleteAsyncWork(env, worker)
|
||||
if status == napi.StatusCancelled {
|
||||
return
|
||||
} else if err != nil {
|
||||
v, _ := napi.CreateError(env, nil, js.AsEnv(env).ValueOf(err.Error()).Value)
|
||||
napi.RejectDeferred(env, promise.Deferred, v)
|
||||
return
|
||||
}
|
||||
napi.ResolveDeferred(env, promise.Deferred, devInfo.ToNapi(env))
|
||||
},
|
||||
)
|
||||
napi.QueueAsyncWork(env, worker)
|
||||
return promise.Value
|
||||
}
|
||||
|
||||
func SetInterface(env napi.Env, info napi.CallbackInfo) napi.Value {
|
||||
devInfo := &Config{}
|
||||
err := devInfo.FromNapi(env, info)
|
||||
|
||||
result, _ := napi.CreatePromise(env)
|
||||
asyncResourceName, _ := napi.CreateStringUtf8(env, "addon/SetInterface")
|
||||
|
||||
var asyncWork napi.AsyncWork
|
||||
asyncWork, _ = napi.CreateAsyncWork(env, nil, asyncResourceName,
|
||||
func(env napi.Env) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get client to wireguard
|
||||
var client *wgctrl.Client
|
||||
if client, err = wgctrl.New(); err != nil {
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
var devConfig wgtypes.Config
|
||||
if devConfig, err = devInfo.WgConfig(); err == nil {
|
||||
err = client.ConfigureDevice(devInfo.Name, devConfig)
|
||||
}
|
||||
},
|
||||
func(env napi.Env, status napi.Status) {
|
||||
defer napi.DeleteAsyncWork(env, asyncWork)
|
||||
if status == napi.StatusCancelled {
|
||||
return
|
||||
} else if err != nil {
|
||||
v, _ := napi.CreateError(env, nil, js.AsEnv(env).ValueOf(err.Error()).Value)
|
||||
napi.RejectDeferred(env, result.Deferred, v)
|
||||
return
|
||||
}
|
||||
napi.ResolveDeferred(env, result.Deferred, devInfo.ToNapi(env))
|
||||
napi.ResolveDeferred(env, result.Deferred, js.AsEnv(env).Undefined().Value)
|
||||
},
|
||||
)
|
||||
napi.QueueAsyncWork(env, asyncWork)
|
||||
return result.Value
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
//go:build unix && !linux
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
_ "golang.zx2c4.com/wireguard/conn"
|
||||
_ "golang.zx2c4.com/wireguard/device"
|
||||
_ "golang.zx2c4.com/wireguard/tun"
|
||||
)
|
@@ -1,3 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package addon
|
11
go.mod
11
go.mod
@@ -2,10 +2,13 @@ module sirherobrine23.com.br/Wireguard/Wireguard-tools.js
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require github.com/abhisekp/napi-go v0.0.0-20250217102150-a60dbfea2dfd
|
||||
require (
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
||||
sirherobrine23.com.br/Sirherobrine23/napi-go v0.1.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||
@@ -15,9 +18,5 @@ require (
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 // indirect
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 // indirect
|
||||
)
|
||||
|
12
go.sum
12
go.sum
@@ -1,5 +1,3 @@
|
||||
github.com/abhisekp/napi-go v0.0.0-20250217102150-a60dbfea2dfd h1:RsyP1mP+EDsLI+tT1gi3wudUoBzWq5Gl3adrgPLuvIE=
|
||||
github.com/abhisekp/napi-go v0.0.0-20250217102150-a60dbfea2dfd/go.mod h1:fZYo8r5iHqF0JIr6OzTc+aGTcRPjAGnOmsSPleYKXTg=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
@@ -12,18 +10,14 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||
@@ -36,3 +30,5 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdI
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
||||
sirherobrine23.com.br/Sirherobrine23/napi-go v0.1.1 h1:qbAry0o+aR4ZPWqGu1LP2MzcAHL/JcwsOLK64ekLsFM=
|
||||
sirherobrine23.com.br/Sirherobrine23/napi-go v0.1.1/go.mod h1:ou35usxSZyinNvaeRHPlnxglSrmc9Wg9cfJ4mE5/9kA=
|
||||
|
2
main.go
2
main.go
@@ -1,5 +1,5 @@
|
||||
package main
|
||||
|
||||
import _ "sirherobrine23.com.br/Wireguard/Wireguard-tools.js/addon"
|
||||
import _ "sirherobrine23.com.br/Wireguard/Wireguard-tools.js/wg_addon"
|
||||
|
||||
func main() {}
|
||||
|
47
wg_addon/addon.go
Normal file
47
wg_addon/addon.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package wg_addon
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
_ "unsafe"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
_ "sirherobrine23.com.br/Sirherobrine23/napi-go/entry"
|
||||
)
|
||||
|
||||
//go:linkname wg sirherobrine23.com.br/Sirherobrine23/napi-go/entry.Register
|
||||
func wg(env napi.EnvType, export *napi.Object) {
|
||||
getConfig, _ := napi.CreateFunction(env, "getConfig", GetInterface)
|
||||
export.Set("getConfig", getConfig)
|
||||
setConfig, _ := napi.CreateFunction(env, "setConfig", SetInterface)
|
||||
export.Set("setConfig", setConfig)
|
||||
// deleteInterface, _ := napi.CreateFunction(env, "deleteInterface", DeleteInterface)
|
||||
// export.Set("deleteInterface", deleteInterface)
|
||||
}
|
||||
|
||||
// Peer info
|
||||
type Peer struct {
|
||||
PresharedKey string `napi:"presharedKey"`
|
||||
KeepInterval int `napi:"keepInterval"`
|
||||
Endpoint string `napi:"endpoint"`
|
||||
AllowedIPs []net.IPNet `napi:"allowedIPs"`
|
||||
|
||||
RemoveMe bool `napi:"removeMe"`
|
||||
|
||||
RxByte int `napi:"rxBytes"`
|
||||
TxByte int `napi:"txBytes"`
|
||||
LastHandshake time.Time `napi:"lastHandshake"`
|
||||
}
|
||||
|
||||
// Wireguard interface configs
|
||||
type Config struct {
|
||||
Name string `napi:"name"`
|
||||
PrivateKey string `napi:"privateKey"`
|
||||
PublicKey string `napi:"publicKey"`
|
||||
PortListen int `napi:"portListen"`
|
||||
Fwmark int `napi:"fwmark"`
|
||||
ReplacePeers bool `napi:"replacePeers"`
|
||||
Address []netip.Addr `napi:"address"`
|
||||
Peers map[string]*Peer `napi:"peers"`
|
||||
}
|
32
wg_addon/unix.go
Normal file
32
wg_addon/unix.go
Normal file
@@ -0,0 +1,32 @@
|
||||
//go:build unix && !linux
|
||||
|
||||
package wg_addon
|
||||
|
||||
import (
|
||||
_ "golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
)
|
||||
|
||||
// Interface tunnels
|
||||
var Tuns = map[string]*Tun{}
|
||||
|
||||
// Tunnel device
|
||||
type Tun struct {
|
||||
Tun tun.Device
|
||||
Dev *device.Device
|
||||
}
|
||||
|
||||
var GetConfig = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
var SetConfig = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
var DeleteInterface = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
return nil, nil
|
||||
})
|
188
wg_addon/wgctrl.go
Normal file
188
wg_addon/wgctrl.go
Normal file
@@ -0,0 +1,188 @@
|
||||
//go:build linux || windows
|
||||
|
||||
package wg_addon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go"
|
||||
"sirherobrine23.com.br/Sirherobrine23/napi-go/js"
|
||||
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
var SetInterface = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
if len(args) == 0 {
|
||||
return nil, fmt.Errorf("set interface config")
|
||||
}
|
||||
|
||||
var wgDevConfig Config
|
||||
if err := js.ValueFrom(args[0], &wgDevConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
promise, err := napi.CreatePromise(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = napi.CreateAyncWorker(env, context.Background(), func(env napi.EnvType, ctx context.Context) {
|
||||
devInfo, err := wgDevConfig.WgConfig()
|
||||
if err != nil {
|
||||
napiErr, _ := napi.CreateError(env, err.Error())
|
||||
promise.Reject(napiErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Get client to wireguard
|
||||
client, err := wgctrl.New()
|
||||
if err != nil {
|
||||
napiErr, _ := napi.CreateError(env, err.Error())
|
||||
promise.Reject(napiErr)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Set Config
|
||||
if err := client.ConfigureDevice(wgDevConfig.Name, devInfo); err != nil {
|
||||
napiErr, _ := napi.CreateError(env, err.Error())
|
||||
promise.Reject(napiErr)
|
||||
return
|
||||
}
|
||||
|
||||
// Resolve promise
|
||||
und, _ := env.Undefined()
|
||||
promise.Resolve(und)
|
||||
})
|
||||
return promise, err
|
||||
})
|
||||
|
||||
var GetInterface = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
if len(args) == 0 {
|
||||
return nil, fmt.Errorf("set interface name")
|
||||
}
|
||||
interfaceName := napi.ToString(args[0])
|
||||
typeof, err := interfaceName.Type()
|
||||
if !(err == nil || typeof == napi.TypeString) {
|
||||
return nil, fmt.Errorf("set interface name")
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
{
|
||||
interfaceName, _ := interfaceName.Utf8Value()
|
||||
// Get client to wireguard
|
||||
var client *wgctrl.Client
|
||||
if client, err = wgctrl.New(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Get config
|
||||
var dev *wgtypes.Device
|
||||
if dev, err = client.Device(interfaceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.FromWg(dev)
|
||||
}
|
||||
|
||||
return js.ValueOf(env, config)
|
||||
})
|
||||
|
||||
var DeleteInterface = napi.Callback(func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) {
|
||||
if len(args) == 0 {
|
||||
return nil, fmt.Errorf("set interface name")
|
||||
}
|
||||
interfaceName := napi.ToString(args[0])
|
||||
typeof, err := interfaceName.Type()
|
||||
if !(err == nil || typeof == napi.TypeString) {
|
||||
return nil, fmt.Errorf("set interface name")
|
||||
}
|
||||
|
||||
{
|
||||
// interfaceName, _ := interfaceName.Utf8Value()
|
||||
// // Get client to wireguard
|
||||
// var client *wgctrl.Client
|
||||
// if client, err = wgctrl.New(); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// defer client.Close()
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
func pointValue[T any](v T) *T { return &v }
|
||||
|
||||
func (cfg Config) WgConfig() (wgtypes.Config, error) {
|
||||
config := wgtypes.Config{
|
||||
ListenPort: pointValue(cfg.PortListen),
|
||||
FirewallMark: pointValue(cfg.Fwmark),
|
||||
ReplacePeers: cfg.ReplacePeers,
|
||||
Peers: []wgtypes.PeerConfig{},
|
||||
}
|
||||
pk, err := wgtypes.ParseKey(cfg.PrivateKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
config.PrivateKey = pointValue(pk)
|
||||
|
||||
for peerKey, peerInfo := range cfg.Peers {
|
||||
pb, err := wgtypes.ParseKey(peerKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
|
||||
if peerInfo.RemoveMe {
|
||||
config.Peers = append(config.Peers, wgtypes.PeerConfig{
|
||||
PublicKey: pb,
|
||||
Remove: true,
|
||||
})
|
||||
} else {
|
||||
peer := wgtypes.PeerConfig{PublicKey: pb, AllowedIPs: peerInfo.AllowedIPs}
|
||||
if peerInfo.PresharedKey != "" {
|
||||
pr, err := wgtypes.ParseKey(peerInfo.PresharedKey)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
peer.PresharedKey = pointValue(pr)
|
||||
}
|
||||
|
||||
if peerInfo.Endpoint != "" {
|
||||
if peer.Endpoint, err = net.ResolveUDPAddr("udp", peerInfo.Endpoint); err != nil {
|
||||
return config, err
|
||||
}
|
||||
}
|
||||
|
||||
peer.PersistentKeepaliveInterval = pointValue(time.Duration(peerInfo.KeepInterval))
|
||||
|
||||
// Append to config
|
||||
config.Peers = append(config.Peers, peer)
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (cfg *Config) FromWg(dev *wgtypes.Device) {
|
||||
cfg.PublicKey = dev.PublicKey.String()
|
||||
cfg.PrivateKey = dev.PrivateKey.String()
|
||||
cfg.PortListen = dev.ListenPort
|
||||
cfg.Fwmark = dev.FirewallMark
|
||||
cfg.Peers = map[string]*Peer{}
|
||||
for _, peer := range dev.Peers {
|
||||
cfg.Peers[peer.PublicKey.String()] = &Peer{
|
||||
PresharedKey: peer.PresharedKey.String(),
|
||||
LastHandshake: peer.LastHandshakeTime,
|
||||
KeepInterval: int(peer.PersistentKeepaliveInterval.Seconds()),
|
||||
TxByte: int(peer.TransmitBytes),
|
||||
RxByte: int(peer.ReceiveBytes),
|
||||
AllowedIPs: peer.AllowedIPs,
|
||||
}
|
||||
if peer.Endpoint != nil {
|
||||
cfg.Peers[peer.PublicKey.String()].Endpoint = peer.Endpoint.String()
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user