Files
kubevpn/pkg/handler/ssh.go
2023-10-02 13:44:23 +08:00

110 lines
2.3 KiB
Go

package handler
import (
"context"
"errors"
"fmt"
"golang.org/x/crypto/ssh"
"net"
"net/netip"
"strconv"
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/pkg/core"
"github.com/wencaiwulue/kubevpn/pkg/util"
)
// SSH
// 0) remote server install kubevpn if not found
// 1) start remote kubevpn server
// 2) start local tunnel
// 3) ssh terminal
func SSH(ctx context.Context, config *util.SshConfig) error {
cancel, cancelFunc := context.WithCancel(ctx)
defer cancelFunc()
err := portMap(ctx, config)
if err != nil {
return err
}
go func() {
stdout, stderr, err := util.RemoteRun(config, fmt.Sprintf(`kubevpn serve -L "tcp://:10800" -L "tun://127.0.0.1:8422?net=223.254.0.123/32"`), nil)
if err != nil {
log.Errorf("run error: %v", err)
log.Errorf("run stdout: %v", string(stdout))
log.Errorf("run stderr: %v", string(stderr))
cancelFunc()
}
}()
r := core.Route{
ServeNodes: []string{
fmt.Sprintf("tun:/127.0.0.1:8422?net=%s&route=%s", "223.254.0.124/32", "223.254.0.124/32"),
},
ChainNode: "tcp://172.17.64.35:10800",
Retries: 5,
}
servers, err := Parse(r)
if err != nil {
log.Errorf("parse route error: %v", err)
return err
}
go func() {
log.Error(Run(cancel, servers))
}()
log.Info("tunnel connected")
<-cancel.Done()
return err
}
func portMap(ctx context.Context, conf *util.SshConfig) (err error) {
port := 10800
var remote netip.AddrPort
remote, err = netip.ParseAddrPort(net.JoinHostPort("127.0.0.1", strconv.Itoa(port)))
if err != nil {
return
}
var local netip.AddrPort
local, err = netip.ParseAddrPort(net.JoinHostPort("127.0.0.1", strconv.Itoa(port)))
if err != nil {
return
}
// pre-check network ip connect
var cli *ssh.Client
cli, err = util.DialSshRemote(conf)
if err != nil {
return
} else {
_ = cli.Close()
}
errChan := make(chan error, 1)
readyChan := make(chan struct{}, 1)
go func() {
for {
select {
case <-ctx.Done():
return
default:
}
err := util.Main(ctx, remote, local, conf, readyChan)
if err != nil {
if !errors.Is(err, context.Canceled) {
log.Errorf("ssh forward failed err: %v", err)
}
select {
case errChan <- err:
default:
}
}
}
}()
select {
case <-readyChan:
return
case err = <-errChan:
log.Errorf("ssh proxy err: %v", err)
return
}
}