|
|
|
package tunnel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/x509"
|
|
|
|
"encoding/base64"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/gorilla/websocket"
|
|
|
|
"github.com/rancher/k3s/pkg/daemons/config"
|
|
|
|
"github.com/rancher/remotedialer"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ports = map[string]bool{
|
|
|
|
"10250": true,
|
|
|
|
"10010": true,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func Setup(config *config.Node) error {
|
|
|
|
restConfig, err := clientcmd.BuildConfigFromFlags("", config.AgentConfig.KubeConfigNode)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
transportConfig, err := restConfig.TransportConfig()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
wsURL := fmt.Sprintf("wss://%s/v1-k3s/connect", config.ServerAddress)
|
|
|
|
headers := map[string][]string{
|
|
|
|
"X-K3s-NodeName": {config.AgentConfig.NodeName},
|
|
|
|
}
|
|
|
|
ws := &websocket.Dialer{}
|
|
|
|
|
|
|
|
if len(config.CACerts) > 0 {
|
|
|
|
pool := x509.NewCertPool()
|
|
|
|
pool.AppendCertsFromPEM(config.CACerts)
|
|
|
|
ws.TLSClientConfig = &tls.Config{
|
|
|
|
RootCAs: pool,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if transportConfig.Username != "" {
|
|
|
|
auth := transportConfig.Username + ":" + transportConfig.Password
|
|
|
|
auth = base64.StdEncoding.EncodeToString([]byte(auth))
|
|
|
|
headers["Authorization"] = []string{"Basic " + auth}
|
|
|
|
}
|
|
|
|
|
|
|
|
once := sync.Once{}
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
wg.Add(1)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
logrus.Infof("Connecting to %s", wsURL)
|
|
|
|
remotedialer.ClientConnect(wsURL, http.Header(headers), ws, func(proto, address string) bool {
|
|
|
|
host, port, err := net.SplitHostPort(address)
|
|
|
|
return err == nil && proto == "tcp" && ports[port] && host == "127.0.0.1"
|
|
|
|
}, func(_ context.Context) error {
|
|
|
|
once.Do(wg.Done)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
wg.Wait()
|
|
|
|
return nil
|
|
|
|
}
|