44 "fmt"
55 "os"
66 "path/filepath"
7+ "strings"
78
89 "github.com/anonvector/slipgate/internal/actions"
910 "github.com/anonvector/slipgate/internal/certs"
@@ -70,6 +71,8 @@ func handleTunnelAdd(ctx *actions.Context) error {
7071 backends = []string {config .BackendSOCKS , config .BackendSSH }
7172 }
7273
74+ var failed , succeeded []string
75+ var sharedKeyDir string
7376 for _ , b := range backends {
7477 tunnelTag := tag
7578 tunnelDomain := domain
@@ -93,15 +96,31 @@ func handleTunnelAdd(ctx *actions.Context) error {
9396 }
9497 }
9598
96- if err := addSingleTunnel (ctx , cfg , transport_ , b , tunnelTag , tunnelDomain ); err != nil {
99+ if err := addSingleTunnel (ctx , cfg , transport_ , b , tunnelTag , tunnelDomain , sharedKeyDir ); err != nil {
97100 out .Warning (fmt .Sprintf ("Failed to add %s: %v" , tunnelTag , err ))
101+ failed = append (failed , tunnelTag )
102+ } else {
103+ succeeded = append (succeeded , tunnelTag )
104+ if sharedKeyDir == "" {
105+ sharedKeyDir = config .TunnelDir (tunnelTag )
106+ }
98107 }
99108 }
100109
110+ // Final summary
111+ out .Print ("" )
112+ if len (failed ) == 0 {
113+ out .Success (fmt .Sprintf ("All %d tunnel(s) added successfully" , len (succeeded )))
114+ } else if len (succeeded ) == 0 {
115+ return actions .NewError (actions .TunnelAdd , fmt .Sprintf ("all %d tunnel(s) failed to add" , len (failed )), nil )
116+ } else {
117+ out .Warning (fmt .Sprintf ("%d succeeded, %d failed" , len (succeeded ), len (failed )))
118+ }
119+
101120 return nil
102121}
103122
104- func addSingleTunnel (ctx * actions.Context , cfg * config.Config , transport_ , backend , tag , domain string ) error {
123+ func addSingleTunnel (ctx * actions.Context , cfg * config.Config , transport_ , backend , tag , domain , sharedKeyDir string ) error {
105124 out := ctx .Output
106125
107126 tunnel := config.TunnelConfig {
@@ -147,6 +166,19 @@ func addSingleTunnel(ctx *actions.Context, cfg *config.Config, transport_, backe
147166 case privKeyHex != "" :
148167 out .Info ("Importing private key and deriving public key..." )
149168 pubKey , err = keys .ImportDNSTTKeys (privKeyHex , privKeyPath , pubKeyPath )
169+ case sharedKeyDir != "" :
170+ out .Info ("Reusing shared keypair..." )
171+ if err := copyFile (filepath .Join (sharedKeyDir , "server.key" ), privKeyPath ); err != nil {
172+ return actions .NewError (actions .TunnelAdd , "failed to copy shared private key" , err )
173+ }
174+ if err := copyFile (filepath .Join (sharedKeyDir , "server.pub" ), pubKeyPath ); err != nil {
175+ return actions .NewError (actions .TunnelAdd , "failed to copy shared public key" , err )
176+ }
177+ pubBytes , err := os .ReadFile (pubKeyPath )
178+ if err != nil {
179+ return actions .NewError (actions .TunnelAdd , "failed to read shared public key" , err )
180+ }
181+ pubKey = strings .TrimSpace (string (pubBytes ))
150182 default :
151183 out .Info ("Generating Curve25519 keypair..." )
152184 pubKey , err = keys .GenerateDNSTTKeys (privKeyPath , pubKeyPath )
@@ -191,6 +223,19 @@ func addSingleTunnel(ctx *actions.Context, cfg *config.Config, transport_, backe
191223 case privKeyHex != "" :
192224 out .Info ("Importing private key and deriving public key..." )
193225 pubKey , err = keys .ImportDNSTTKeys (privKeyHex , privKeyPath , pubKeyPath )
226+ case sharedKeyDir != "" :
227+ out .Info ("Reusing shared keypair..." )
228+ if err := copyFile (filepath .Join (sharedKeyDir , "server.key" ), privKeyPath ); err != nil {
229+ return actions .NewError (actions .TunnelAdd , "failed to copy shared private key" , err )
230+ }
231+ if err := copyFile (filepath .Join (sharedKeyDir , "server.pub" ), pubKeyPath ); err != nil {
232+ return actions .NewError (actions .TunnelAdd , "failed to copy shared public key" , err )
233+ }
234+ pubBytes , err := os .ReadFile (pubKeyPath )
235+ if err != nil {
236+ return actions .NewError (actions .TunnelAdd , "failed to read shared public key" , err )
237+ }
238+ pubKey = strings .TrimSpace (string (pubBytes ))
194239 default :
195240 out .Info ("Generating Curve25519 keypair..." )
196241 pubKey , err = keys .GenerateDNSTTKeys (privKeyPath , pubKeyPath )
0 commit comments