refactoring rpc package.

This commit is contained in:
greg stone
2023-02-23 09:19:32 +00:00
parent 4a52818c0c
commit 5610b7a11d
12 changed files with 397 additions and 245 deletions

View File

@@ -20,16 +20,10 @@ var (
)
var (
key string
listeners []string
seeds []string
connectors []string
rpc_enable bool
rpc_listen_port uint16
rpc_key string
rpc_whitelist_peer []string
rpc_whitelist_ip []string
rpc_unix_path string
key string
listeners []string
seeds []string
connectors []string
)
func init() {
@@ -39,23 +33,12 @@ func init() {
seedCmd.PersistentFlags().StringSliceVarP(&seeds, "seed", "s", []string{}, "adds an additional seed connection (e.g /dns4/seed0.indra.org/tcp/8337/p2p/<pub_key>)")
seedCmd.PersistentFlags().StringSliceVarP(&connectors, "connect", "c", []string{}, "connects only to the seed multi-addresses specified")
seedCmd.PersistentFlags().BoolVarP(&rpc_enable, "rpc-enable", "", false, "enables the rpc server")
seedCmd.PersistentFlags().Uint16VarP(&rpc_listen_port, "rpc-listen-port", "", 0, "binds the udp server to port (random if not selected)")
seedCmd.PersistentFlags().StringVarP(&rpc_key, "rpc-key", "", "", "the base58 encoded pre-shared key for accessing the rpc")
seedCmd.PersistentFlags().StringSliceVarP(&rpc_whitelist_peer, "rpc-whitelist-peer", "", []string{}, "adds a peer id to the whitelist for access")
seedCmd.PersistentFlags().StringSliceVarP(&rpc_whitelist_ip, "rpc-whitelist-ip", "", []string{}, "adds a cidr ip range to the whitelist for access (e.g /ip4/127.0.0.1/ipcidr/32)")
seedCmd.PersistentFlags().StringVarP(&rpc_unix_path, "rpc-listen-unix", "", "/tmp/indra.sock", "binds to a unix socket with path (default is /tmp/indra.sock)")
viper.BindPFlag("key", seedCmd.PersistentFlags().Lookup("key"))
viper.BindPFlag("listen", seedCmd.PersistentFlags().Lookup("listen"))
viper.BindPFlag("seed", seedCmd.PersistentFlags().Lookup("seed"))
viper.BindPFlag("connect", seedCmd.PersistentFlags().Lookup("connect"))
viper.BindPFlag("rpc-enable", seedCmd.PersistentFlags().Lookup("rpc-enable"))
viper.BindPFlag("rpc-listen-port", seedCmd.PersistentFlags().Lookup("rpc-listen-port"))
viper.BindPFlag("rpc-key", seedCmd.PersistentFlags().Lookup("rpc-key"))
viper.BindPFlag("rpc-whitelist-peer", seedCmd.PersistentFlags().Lookup("rpc-whitelist-peer"))
viper.BindPFlag("rpc-whitelist-ip", seedCmd.PersistentFlags().Lookup("rpc-whitelist-ip"))
viper.BindPFlag("rpc-listen-unix", seedCmd.PersistentFlags().Lookup("rpc-listen-unix"))
rpc.Configure(seedCmd)
rootCmd.AddCommand(seedCmd)
}

View File

@@ -139,7 +139,7 @@ func GetExampleCommands() (c *Command) {
"OneTimeTLSKey": toggle.New(meta.Data{
Aliases: Tags("OTK"),
Tags: Tags("node", "wallet"),
Label: "One Time TLS Key",
Label: "One Time TLS key",
Description: "generate a new TLS certificate pair at startup, but only write the certificate to disk",
Documentation: lorem,
Default: "false",
@@ -186,7 +186,7 @@ func GetExampleCommands() (c *Command) {
"RPCKey": text.New(meta.Data{
Aliases: Tags("RK"),
Tags: Tags("node", "wallet"),
Label: "RPC Key",
Label: "RPC key",
Description: "location of rpc TLS key",
Documentation: lorem,
Default: "~/.pod/rpc.key",

View File

@@ -73,7 +73,7 @@ func NewClient(config *ClientConfig) (*RPCClient, error) {
deviceConf := "" +
"public_key=" + config.Peer.PublicKey.HexString() + "\n" +
"endpoint=0.0.0.0:18222" + "\n" +
"allowed_ip=" + deviceIP.String() + "/32\n" +
"allowed_ip=" + deviceRPCIP.String() + "/32\n" +
"persistent_keepalive_interval=" + strconv.Itoa(int(config.Peer.KeepAliveInterval)) + "\n"
if err = r.device.IpcSet(deviceConf); check(err) {
@@ -89,7 +89,7 @@ func NewClient(config *ClientConfig) (*RPCClient, error) {
//)
conn, err = grpc.DialContext(context.Background(),
deviceIP.String()+":80",
deviceRPCIP.String()+":80",
grpc.WithBlock(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithContextDialer(func(ctx context.Context, address string) (net.Conn, error) {

106
pkg/rpc/cmd.go Normal file
View File

@@ -0,0 +1,106 @@
package rpc
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
flag_tun_enable = "rpc-tun-enable"
flag_tun_key = "rpc-tun-key"
flag_tun_port = "rpc-tun-port"
flag_tun_whitlist_peer = "rpc-tun-whitelist-peer"
)
var (
rpc_tun_enable bool
rpc_tun_key string
rpc_tun_port uint16
rpc_tun_whitelist_peer []string
)
func Configure(cmd *cobra.Command) {
defineUnixSocket(cmd)
cmd.PersistentFlags().BoolVarP(&rpc_tun_enable, flag_tun_enable, "", false, "enables the rpc server tunnel")
cmd.PersistentFlags().Uint16VarP(&rpc_tun_port, flag_tun_port, "", 0, "binds the udp server to port (random if not selected)")
cmd.PersistentFlags().StringVarP(&rpc_tun_key, flag_tun_key, "", "", "the base58 encoded pre-shared key for accessing the rpc")
cmd.PersistentFlags().StringSliceVarP(&rpc_tun_whitelist_peer, flag_tun_whitlist_peer, "", []string{}, "adds a peer id to the whitelist for access")
viper.BindPFlag(flag_tun_enable, cmd.PersistentFlags().Lookup(flag_tun_enable))
viper.BindPFlag(flag_tun_port, cmd.PersistentFlags().Lookup(flag_tun_port))
viper.BindPFlag(flag_tun_key, cmd.PersistentFlags().Lookup(flag_tun_key))
viper.BindPFlag(flag_tun_whitlist_peer, cmd.PersistentFlags().Lookup(flag_tun_whitlist_peer))
}
func ConfigureWithViper() (err error) {
log.I.Ln("configuring the rpc server")
configureUnixSocket()
configureTunnel()
log.I.Ln("rpc listeners:")
log.I.F("- [/ip4/0.0.0.0/udp/%d", config.listenPort)
log.I.F("/ip4/0.0.0.0/udp/%d", config.listenPort)
log.I.F("/ip6/:::/udp/%d", config.listenPort)
log.I.F("/unix" + unixPath + "]")
return
}
func configureTunnel() {
if !viper.GetBool("rpc-tun-enable") {
return
}
log.I.Ln("enabling rpc tunnel")
configureTunnelKey()
configureTunnelPort()
configurePeerWhitelist()
enableTunnel()
}
var (
tunKey *RPCPrivateKey
)
func configureTunnelKey() {
if viper.GetString("rpc-tun-key") == "" {
log.I.Ln("rpc tunnel key not provided, generating a new one.")
tunKey, _ = NewPrivateKey()
viper.Set("rpc-tun-key", tunKey.Encode())
}
log.I.Ln("rpc public key:")
log.I.Ln("-", config.key.PubKey().Encode())
}
func configureTunnelPort() {
if viper.GetUint16("rpc-tun-port") == NullPort {
log.I.Ln("rpc tunnel port not provided, generating a random one.")
viper.Set("rpc-tun-port", genRandomPort(10000))
}
}
func configurePeerWhitelist() {
for _, peer := range viper.GetStringSlice("rpc-whitelist-peer") {
var pubKey RPCPublicKey
pubKey.Decode(peer)
config.peerWhitelist = append(config.peerWhitelist, pubKey)
}
}

View File

@@ -6,51 +6,60 @@ import (
"time"
)
var (
config = rpcConfig{
key: &nullRPCPrivateKey,
listenPort: NullPort,
peerWhitelist: []RPCPublicKey{},
ipWhitelist: []multiaddr.Multiaddr{},
}
)
type rpcConfig struct {
Key *RPCPrivateKey
ListenPort uint16
Peer_Whitelist []RPCPublicKey
IP_Whitelist []multiaddr.Multiaddr
UnixPath string
key *RPCPrivateKey
listenPort uint16
peerWhitelist []RPCPublicKey
ipWhitelist []multiaddr.Multiaddr
unixPath string
}
func (c *rpcConfig) NewKey() {
func (c *rpcConfig) newKey() {
var err error
if c.Key, err = NewPrivateKey(); check(err) {
if c.key, err = NewPrivateKey(); check(err) {
panic(err)
}
}
func (c *rpcConfig) SetKey(key string) {
c.Key.Decode(key)
func (c *rpcConfig) setKey(key string) {
c.key.Decode(key)
}
func (c *rpcConfig) IsNullKey() bool {
return c.Key.IsZero()
func (c *rpcConfig) isNullKey() bool {
return c.key.IsZero()
}
func (c *rpcConfig) SetPort(port uint16) {
c.ListenPort = port
func (c *rpcConfig) setPort(port uint16) {
c.listenPort = port
}
func (c *rpcConfig) IsNullPort() bool {
return c.ListenPort == NullPort
func (c *rpcConfig) isNullPort() bool {
return c.listenPort == NullPort
}
func (c *rpcConfig) SetRandomPort() uint16 {
func (c *rpcConfig) setRandomPort() uint16 {
rand.Seed(time.Now().Unix())
c.ListenPort = uint16(rand.Intn(45534) + 10000)
c.listenPort = uint16(rand.Intn(45534) + 10000)
return c.ListenPort
return c.listenPort
}
func (c *rpcConfig) SetUnixPath(path string) {
c.UnixPath = path
func (c *rpcConfig) setUnixPath(path string) {
c.unixPath = path
}
func (conf *rpcConfig) IsEnabled() bool {
return !conf.Key.IsZero()
func (conf *rpcConfig) isEnabled() bool {
return !conf.key.IsZero()
}

11
pkg/rpc/log.go Normal file
View File

@@ -0,0 +1,11 @@
package rpc
import (
"git-indra.lan/indra-labs/indra"
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)

View File

@@ -1,146 +0,0 @@
package rpc
import (
"context"
"git-indra.lan/indra-labs/indra"
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
"github.com/multiformats/go-multiaddr"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/tun/netstack"
"google.golang.org/grpc"
"net"
"net/netip"
"os"
"strconv"
)
const NullPort = 0
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
var (
config = rpcConfig{
Key: &nullRPCPrivateKey,
ListenPort: NullPort,
Peer_Whitelist: []RPCPublicKey{},
IP_Whitelist: []multiaddr.Multiaddr{},
}
)
var (
isReady = make(chan bool)
startupErrors = make(chan error)
)
func IsReady() chan bool {
return isReady
}
func CantStart() chan error {
return startupErrors
}
var (
deviceIP netip.Addr = netip.MustParseAddr("192.168.4.28")
devicePort int = 0
deviceMTU int = 1420
)
var (
dev *device.Device
network *netstack.Net
tunnel tun.Device
unixSock net.Listener
tcpSock net.Listener
server *grpc.Server
)
func init() {
server = grpc.NewServer()
}
func Register(r func(srv *grpc.Server)) {
r(server)
}
func Start(ctx context.Context) {
var err error
var config = config
// Initializing the tunnel
if tunnel, network, err = netstack.CreateNetTUN([]netip.Addr{deviceIP}, []netip.Addr{}, deviceMTU); check(err) {
startupErrors <- err
return
}
dev = device.NewDevice(tunnel, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "server "))
dev.SetPrivateKey(config.Key.AsDeviceKey())
dev.IpcSet("listen_port=" + strconv.Itoa(int(config.ListenPort)))
for _, peer_whitelist := range config.Peer_Whitelist {
deviceConf := "" +
"public_key=" + peer_whitelist.HexString() + "\n" +
"allowed_ip=" + DefaultClientIPAddr.String() + "/32\n"
if err = dev.IpcSet(deviceConf); check(err) {
startupErrors <- err
return
}
}
if err = dev.Up(); check(err) {
startupErrors <- err
return
}
if unixSock, err = net.Listen("unix", config.UnixPath); check(err) {
startupErrors <- err
return
}
go server.Serve(unixSock)
if tcpSock, err = network.ListenTCPAddrPort(netip.AddrPortFrom(deviceIP, 80)); check(err) {
startupErrors <- err
return
}
go server.Serve(tcpSock)
isReady <- true
select {
case <-ctx.Done():
Shutdown()
}
}
func Shutdown() {
log.I.Ln("shutting down rpc server")
if unixSock != nil {
unixSock.Close()
os.Remove(config.UnixPath)
}
if tcpSock != nil {
tcpSock.Close()
}
if dev != nil {
dev.Close()
}
server.Stop()
}

56
pkg/rpc/server.go Normal file
View File

@@ -0,0 +1,56 @@
package rpc
import (
"context"
"google.golang.org/grpc"
)
func init() {
server = grpc.NewServer()
}
var (
server *grpc.Server
)
var (
isReady = make(chan bool)
startupErrors = make(chan error)
)
func IsReady() chan bool {
return isReady
}
func CantStart() chan error {
return startupErrors
}
func Register(r func(srv *grpc.Server)) {
r(server)
}
func Start(ctx context.Context) {
var err error
if err = startUnixSocket(); check(err) {
startupErrors <- err
}
isReady <- true
select {
case <-ctx.Done():
Shutdown()
}
}
func Shutdown() {
log.I.Ln("shutting down rpc server")
stopUnixSocket()
server.Stop()
}

77
pkg/rpc/socket_unix.go Normal file
View File

@@ -0,0 +1,77 @@
package rpc
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"net"
)
var (
isUnixSockEnabled bool = false
unixSock net.Listener
)
var (
unixPathFlag = "rpc-unix-listen"
unixPathUsage = "binds to a unix socket with path"
unixPath = "/tmp/indra.sock"
)
func defineUnixSocket(cmd *cobra.Command) {
cmd.PersistentFlags().StringVarP(
&unixPath,
unixPathFlag,
"",
unixPath,
unixPathUsage,
)
viper.BindPFlag(
unixPathFlag,
cmd.PersistentFlags().Lookup(unixPathFlag),
)
}
func configureUnixSocket() {
if viper.GetString(unixPathFlag) == "" {
return
}
log.I.Ln("enabling unix listener:", viper.GetString(unixPath))
isUnixSockEnabled = true
}
func startUnixSocket() (err error) {
if !isUnixSockEnabled {
return
}
if unixSock, err = net.Listen("unix", unixPath); check(err) {
return
}
go server.Serve(unixSock)
return
}
func stopUnixSocket() (err error) {
if !isUnixSockEnabled {
return
}
if err = unixSock.Close(); check(err) {
// continue
}
//if err = os.Remove(unixPath); check(err) {
// // continue
//}
return
}

93
pkg/rpc/tunnel.go Normal file
View File

@@ -0,0 +1,93 @@
package rpc
import (
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/tun/netstack"
"net"
"net/netip"
"strconv"
)
const NullPort = 0
var (
isTunnelEnabled bool = false
)
var (
deviceRPCIP netip.Addr = netip.MustParseAddr("192.168.4.28")
deviceRPCPort uint16 = 80
devicePort int = 0
deviceMTU int = 1420
)
var (
dev *device.Device
network *netstack.Net
tunnel tun.Device
tcpSock net.Listener
)
func enableTunnel() {
isTunnelEnabled = true
}
func startTunnel() (err error) {
if !isTunnelEnabled {
return
}
if tunnel, network, err = netstack.CreateNetTUN([]netip.Addr{deviceRPCIP}, []netip.Addr{}, deviceMTU); check(err) {
startupErrors <- err
return
}
dev = device.NewDevice(tunnel, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "server "))
dev.SetPrivateKey(config.key.AsDeviceKey())
dev.IpcSet("listen_port=" + strconv.Itoa(int(config.listenPort)))
for _, peer_whitelist := range config.peerWhitelist {
deviceConf := "" +
"public_key=" + peer_whitelist.HexString() + "\n" +
"allowed_ip=" + DefaultClientIPAddr.String() + "/32\n"
if err = dev.IpcSet(deviceConf); check(err) {
startupErrors <- err
return
}
}
if err = dev.Up(); check(err) {
startupErrors <- err
return
}
if tcpSock, err = network.ListenTCPAddrPort(netip.AddrPortFrom(deviceRPCIP, deviceRPCPort)); check(err) {
startupErrors <- err
return
}
go server.Serve(tcpSock)
return
}
func stopTunnel() (err error) {
if !isTunnelEnabled {
return
}
if err = tcpSock.Close(); check(err) {
// continue
}
dev.Close()
return
}

13
pkg/rpc/util.go Normal file
View File

@@ -0,0 +1,13 @@
package rpc
import (
"math/rand"
"time"
)
func genRandomPort(offset int) uint16 {
rand.Seed(time.Now().Unix())
return uint16(rand.Intn(65534-offset) + offset)
}

View File

@@ -1,50 +0,0 @@
package rpc
import (
"github.com/multiformats/go-multiaddr"
"github.com/spf13/viper"
"strconv"
)
func ConfigureWithViper() (err error) {
log.I.Ln("initializing the rpc server")
config.SetKey(viper.GetString("rpc-key"))
if config.IsNullKey() {
log.I.Ln("rpc key not provided, generating a new one.")
config.NewKey()
}
log.I.Ln("rpc public key:")
log.I.Ln("-", config.Key.PubKey().Encode())
config.SetUnixPath(viper.GetString("rpc-listen-unix"))
config.SetPort(viper.GetUint16("rpc-listen-port"))
if viper.GetUint16("rpc-listen-port") == NullPort {
viper.Set("rpc-listen-port", config.SetRandomPort())
}
log.I.Ln("rpc listeners:")
log.I.Ln("- [/ip4/0.0.0.0/udp/"+strconv.Itoa(int(config.ListenPort)), "/ip6/:::/udp/"+strconv.Itoa(int(config.ListenPort))+" /unix"+config.UnixPath+"]")
for _, ip := range viper.GetStringSlice("rpc-whitelist-deviceIP") {
config.IP_Whitelist = append(config.IP_Whitelist, multiaddr.StringCast(ip))
}
for _, peer := range viper.GetStringSlice("rpc-whitelist-peer") {
var pubKey RPCPublicKey
pubKey.Decode(peer)
config.Peer_Whitelist = append(config.Peer_Whitelist, pubKey)
}
return
}