فهرست منبع

:seedling: Add CLI options

Signed-off-by: mudler <[email protected]>
mudler 2 سال پیش
والد
کامیت
4258ab524b
3فایلهای تغییر یافته به همراه99 افزوده شده و 6 حذف شده
  1. 78 0
      cmd/util.go
  2. 11 0
      pkg/config/config.go
  3. 10 6
      pkg/node/connection.go

+ 78 - 0
cmd/util.go

@@ -15,7 +15,10 @@ package cmd
 
 import (
 	"encoding/json"
+	"fmt"
 	"os"
+	"path/filepath"
+	"strings"
 
 	"os/signal"
 	"runtime"
@@ -23,6 +26,8 @@ import (
 	"time"
 
 	"github.com/ipfs/go-log"
+	"github.com/libp2p/go-libp2p-core/peer"
+	"github.com/libp2p/go-libp2p/core/crypto"
 	rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
 	"github.com/mudler/edgevpn/internal"
 	"github.com/mudler/edgevpn/pkg/config"
@@ -300,6 +305,22 @@ var CommonFlags []cli.Flag = []cli.Flag{
 		Usage:  "Enable peerguard. (Experimental)",
 		EnvVar: "PEERGUARD",
 	},
+	&cli.BoolFlag{
+		Name:   "privkey-cache",
+		Usage:  "Enable privkey caching. (Experimental)",
+		EnvVar: "EDGEVPNPRIVKEYCACHE",
+	},
+	&cli.StringFlag{
+		Name:   "privkey-cache-dir",
+		Usage:  "Specify a directory used to store the generated privkey",
+		EnvVar: "EDGEVPNPRIVKEYCACHEDIR",
+		Value:  stateDir(),
+	},
+	&cli.StringSliceFlag{
+		Name:   "static-peertable",
+		Usage:  "List of static peers to use (in `ip:peerid` format)",
+		EnvVar: "EDGEVPNSTATICPEERTABLE",
+	},
 	&cli.BoolFlag{
 		Name:   "peergate",
 		Usage:  "Enable peergating. (Experimental)",
@@ -329,6 +350,17 @@ var CommonFlags []cli.Flag = []cli.Flag{
 	},
 }
 
+func stateDir() string {
+	baseDir := ".edgevpn"
+	home, _ := os.UserHomeDir()
+	if home != "" {
+		return filepath.Join(home, baseDir)
+	}
+
+	dir, _ := os.Getwd()
+	return filepath.Join(dir, baseDir)
+}
+
 func displayStart(ll *logger.Logger) {
 	ll.Info(Copyright)
 
@@ -433,6 +465,52 @@ func cliToOpts(c *cli.Context) ([]node.Option, []vpn.Option, *logger.Logger) {
 	}
 	llger := logger.New(lvl)
 
+	checkErr := func(e error) {
+		if err != nil {
+			llger.Fatal(err.Error())
+		}
+	}
+
+	// Check if we have any privkey identity cached already
+	if c.Bool("privkey-cache") {
+		keyFile := filepath.Join(c.String("privkey-cache-dir"), "privkey")
+		dat, err := os.ReadFile(keyFile)
+		if err == nil && len(dat) > 0 {
+			llger.Info("Reading key from", keyFile)
+
+			nc.Privkey = dat
+		} else {
+			// generate, write
+			llger.Info("Generating private key and saving it locally for later use in", keyFile)
+
+			privkey, err := node.GenPrivKey(0)
+			checkErr(err)
+
+			r, err := crypto.MarshalPrivateKey(privkey)
+			checkErr(err)
+
+			err = os.MkdirAll(c.String("privkey-cache-dir"), 0600)
+			checkErr(err)
+
+			err = os.WriteFile(keyFile, r, 0600)
+			checkErr(err)
+
+			nc.Privkey = r
+		}
+	}
+
+	for _, pt := range c.StringSlice("static-peertable") {
+		dat := strings.Split(pt, ":")
+		if len(dat) != 2 {
+			checkErr(fmt.Errorf("wrong format for peertable entries. Want a list of ip/peerid separated by `:`. e.g. 10.1.0.1:... "))
+		}
+		if nc.Connection.PeerTable == nil {
+			nc.Connection.PeerTable = make(map[string]peer.ID)
+		}
+
+		nc.Connection.PeerTable[dat[0]] = peer.ID(dat[1])
+	}
+
 	nodeOpts, vpnOpts, err := nc.ToOpts(llger)
 	if err != nil {
 		llger.Fatal(err.Error())

+ 11 - 0
pkg/config/config.go

@@ -61,6 +61,7 @@ type Config struct {
 	Discovery                                  Discovery
 	Ledger                                     Ledger
 	Limit                                      ResourceLimit
+	Privkey                                    []byte
 	// PeerGuard (experimental)
 	// enable peerguardian and add specific auth options
 	PeerGuard PeerGuard
@@ -113,6 +114,8 @@ type Connection struct {
 	StaticRelays               []string
 	OnlyStaticRelays           bool
 
+	PeerTable map[string]peer.ID
+
 	Mplex          bool
 	MaxConnections int
 }
@@ -213,6 +216,14 @@ func (c Config) ToOpts(l *logger.Logger) ([]node.Option, []vpn.Option, error) {
 		node.FromYaml(mDNS, dhtE, config, d, m),
 	}
 
+	for ip, peer := range c.Connection.PeerTable {
+		opts = append(opts, node.WithStaticPeer(ip, peer))
+	}
+
+	if len(c.Privkey) > 0 {
+		opts = append(opts, node.WithPrivKey(c.Privkey))
+	}
+
 	vpnOpts := []vpn.Option{
 		vpn.WithConcurrency(c.Concurrency),
 		vpn.WithInterfaceAddress(address),

+ 10 - 6
pkg/node/connection.go

@@ -53,15 +53,19 @@ func (e *Node) BlockSubnet(cidr string) error {
 	return e.ConnectionGater().BlockSubnet(n)
 }
 
-func (e *Node) genHost(ctx context.Context) (host.Host, error) {
+func GenPrivKey(seed int64) (crypto.PrivKey, error) {
 	var r io.Reader
-	var prvKey crypto.PrivKey
-
-	if e.seed == 0 {
+	if seed == 0 {
 		r = rand.Reader
 	} else {
-		r = mrand.New(mrand.NewSource(e.seed))
+		r = mrand.New(mrand.NewSource(seed))
 	}
+	prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 4096, r)
+	return prvKey, err
+}
+
+func (e *Node) genHost(ctx context.Context) (host.Host, error) {
+	var prvKey crypto.PrivKey
 
 	opts := e.config.Options
 
@@ -91,7 +95,7 @@ func (e *Node) genHost(ctx context.Context) (host.Host, error) {
 	if len(e.config.PrivateKey) > 0 {
 		prvKey, err = crypto.UnmarshalPrivateKey(e.config.PrivateKey)
 	} else {
-		prvKey, _, err = crypto.GenerateKeyPairWithReader(crypto.Ed25519, 4096, r)
+		prvKey, err = GenPrivKey(e.seed)
 	}
 
 	if err != nil {