Skip to content

Commit

Permalink
feat: add ssh to linux server
Browse files Browse the repository at this point in the history
  • Loading branch information
fengcaiwen authored and wencaiwulue committed Oct 29, 2023
1 parent faf7c5e commit b2458c2
Show file tree
Hide file tree
Showing 33 changed files with 3,047 additions and 377 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ LDFLAGS=--ldflags "\
-X ${BASE}/pkg/config.Image=${IMAGE} \
-X ${BASE}/pkg/config.Version=${VERSION} \
-X ${BASE}/pkg/config.GitCommit=${GIT_COMMIT} \
-X ${BASE}/pkg/config.GitHubOAuthToken=${GitHubOAuthToken} \
-X ${FOLDER}/cmds.BuildTime=${BUILD_TIME} \
-X ${FOLDER}/cmds.Branch=${BRANCH} \
-X ${FOLDER}/cmds.OsArch=${OS_ARCH} \
-X ${FOLDER}/cmds.GitHubOAuthToken=${GitHubOAuthToken} \
"

GO111MODULE=on
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![kubevpn](samples/flat_log.png)
![kubevpn](https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/flat_log.png)

[![GitHub Workflow][1]](https://github.com/KubeNetworks/kubevpn/actions)
[![Go Version][2]](https://github.com/KubeNetworks/kubevpn/blob/master/go.mod)
Expand Down
2 changes: 1 addition & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![kubevpn](samples/flat_log.png)
![kubevpn](https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/flat_log.png)

[![GitHub Workflow][1]](https://github.com/KubeNetworks/kubevpn/actions)
[![Go Version][2]](https://github.com/KubeNetworks/kubevpn/blob/master/go.mod)
Expand Down
1 change: 1 addition & 0 deletions cmd/kubevpn/cmds/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func NewKubeVPNCommand() *cobra.Command {
CmdConfig(factory),
CmdCp(factory),
CmdSSH(factory),
CmdSSHDaemon(factory),
CmdLogs(factory),
CmdReset(factory),
CmdQuit(factory),
Expand Down
35 changes: 24 additions & 11 deletions cmd/kubevpn/cmds/ssh.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package cmds

import (
"io"
"os"

"github.com/spf13/cobra"
"golang.org/x/net/websocket"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"

"github.com/wencaiwulue/kubevpn/pkg/handler"
"github.com/wencaiwulue/kubevpn/pkg/daemon"
"github.com/wencaiwulue/kubevpn/pkg/util"
)

Expand All @@ -18,10 +20,9 @@ import (
func CmdSSH(_ cmdutil.Factory) *cobra.Command {
var sshConf = &util.SshConfig{}
cmd := &cobra.Command{
Use: "ssh",
Hidden: true,
Short: "Ssh to jump server",
Long: `Ssh to jump server`,
Use: "ssh",
Short: "Ssh to jump server",
Long: `Ssh to jump server`,
Example: templates.Examples(i18n.T(`
# Jump to server behind of bastion host or ssh jump host
kubevpn ssh --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
Expand All @@ -32,14 +33,26 @@ func CmdSSH(_ cmdutil.Factory) *cobra.Command {
└──────┘ └──────┘ └──────┘ └──────┘ └────────┘
kubevpn ssh --ssh-alias <alias>
`)),
PreRun: func(*cobra.Command, []string) {
if !util.IsAdmin() {
util.RunWithElevated()
os.Exit(0)
}
PreRunE: func(cmd *cobra.Command, args []string) error {
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
err := handler.SSH(cmd.Context(), sshConf)
config, err := websocket.NewConfig("ws://test/ws", "http://test")
if err != nil {
return err
}
config.Header.Set("ssh-addr", sshConf.Addr)
config.Header.Set("ssh-username", sshConf.User)
config.Header.Set("ssh-password", sshConf.Password)
config.Header.Set("ssh-keyfile", sshConf.Keyfile)
config.Header.Set("ssh-alias", sshConf.ConfigAlias)
client := daemon.GetTCPClient(true)
conn, err := websocket.NewClient(config, client)
if err != nil {
return err
}
go io.Copy(conn, os.Stdin)
_, err = io.Copy(os.Stdout, conn)
return err
},
}
Expand Down
50 changes: 50 additions & 0 deletions cmd/kubevpn/cmds/sshdaemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cmds

import (
"fmt"
"os"

"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"

"github.com/wencaiwulue/kubevpn/pkg/daemon"
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
)

// CmdSSHDaemon
// 设置本地的IP是223.254.0.1/32 ,记得一定是掩码 32位,
// 这样别的路由不会走到这里来
func CmdSSHDaemon(_ cmdutil.Factory) *cobra.Command {
var clientIP string
cmd := &cobra.Command{
Use: "ssh-daemon",
Hidden: true,
Short: "Ssh daemon server",
Long: `Ssh daemon server`,
Example: templates.Examples(i18n.T(`
# SSH daemon server
kubevpn ssh-daemon --client-ip 223.254.0.123/32
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
err := daemon.StartupDaemon(cmd.Context())
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
client, err := daemon.GetClient(true).SshStart(
cmd.Context(),
&rpc.SshStartRequest{
ClientIP: clientIP,
},
)
if err != nil {
return err
}
fmt.Fprint(os.Stdout, client.ServerIP)
return nil
},
}
cmd.Flags().StringVar(&clientIP, "client-ip", "", "Client cidr")
return cmd
}
10 changes: 2 additions & 8 deletions cmd/kubevpn/cmds/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,15 @@ import (
"github.com/wencaiwulue/kubevpn/pkg/upgrade"
)

// GitHubOAuthToken
// --ldflags -X
var (
GitHubOAuthToken = ""
)

func CmdUpgrade(_ cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "upgrade",
Short: "Upgrade KubeVPN version",
Long: `Upgrade KubeVPN version, automatically download latest KubeVPN from GitHub`,
Run: func(cmd *cobra.Command, args []string) {
var client = http.DefaultClient
if GitHubOAuthToken != "" {
client = oauth2.NewClient(cmd.Context(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: GitHubOAuthToken, TokenType: "Bearer"}))
if config.GitHubOAuthToken != "" {
client = oauth2.NewClient(cmd.Context(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: config.GitHubOAuthToken, TokenType: "Bearer"}))
}
err := upgrade.Main(cmd.Context(), config.Version, config.GitCommit, client)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ var (
Version = "latest"
GitCommit = ""

// GitHubOAuthToken --ldflags -X
GitHubOAuthToken = ""

OriginImage = "docker.io/naison/kubevpn:" + Version

DaemonPath string
Expand Down
4 changes: 2 additions & 2 deletions pkg/core/tunhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ func (h tunHandler) printRoute() {
sb.WriteString(fmt.Sprintf("to: %s, route: %s\n", key, strings.Join(s, " ")))
}
})
fmt.Println(sb.String())
fmt.Println(i)
log.Debug(sb.String())
log.Debug(i)
}
}
}
Expand Down
104 changes: 104 additions & 0 deletions pkg/daemon/action/sshdaemon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package action

import (
"context"
"net"
"sync"
"time"

"github.com/containernetworking/cni/pkg/types"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/wait"

"github.com/wencaiwulue/kubevpn/pkg/config"
"github.com/wencaiwulue/kubevpn/pkg/core"
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/pkg/handler"
"github.com/wencaiwulue/kubevpn/pkg/tun"
"github.com/wencaiwulue/kubevpn/pkg/util"
)

var _, bits = config.DockerCIDR.Mask.Size()
var DefaultServerIP = (&net.IPNet{IP: config.DockerRouterIP, Mask: net.CIDRMask(bits, bits)}).String()

var serverIP string
var mux sync.Mutex
var sshCancelFunc context.CancelFunc

func (svr *Server) SshStart(ctx context.Context, req *rpc.SshStartRequest) (*rpc.SshStartResponse, error) {
mux.Lock()
defer mux.Unlock()

clientIP, clientCIDR, err := net.ParseCIDR(req.ClientIP)
if err != nil {
log.Errorf("parse cidr error: %v", err)
return nil, err
}
if serverIP == "" {
r := core.Route{
ServeNodes: []string{
"tun://127.0.0.1:8422?net=" + DefaultServerIP,
"tcp://:10800",
},
Retries: 5,
}
servers, err := handler.Parse(r)
if err != nil {
log.Errorf("parse route error: %v", err)
return nil, err
}
ctx, sshCancelFunc = context.WithCancel(context.Background())
go func() {
err := handler.Run(ctx, servers)
if err != nil {
log.Errorf("run route error: %v", err)
}
}()

ctx2, cancelF := context.WithCancel(ctx)
wait.UntilWithContext(ctx2, func(ctx context.Context) {
ip, _, _ := net.ParseCIDR(DefaultServerIP)
ok, err := util.Ping(ip.String())
if err != nil {
} else if ok {
cancelF()
} else {
// todo
cancelF()
}
}, time.Millisecond*20)
if err != nil {
return nil, err
}
serverIP = DefaultServerIP
}

serverip, _, err := net.ParseCIDR(serverIP)
if err != nil {
return nil, err
}
tunDevice, err := util.GetTunDevice(serverip)
if err != nil {
return nil, err
}
err = tun.AddRoutes(tunDevice.Name, types.Route{
Dst: net.IPNet{
IP: clientIP,
Mask: clientCIDR.Mask,
},
GW: nil,
})
if err != nil {
log.Errorf("add route error: %v", err)
return nil, err
}

return &rpc.SshStartResponse{ServerIP: serverIP}, nil
}

func (svr *Server) SshStop(ctx context.Context, req *rpc.SshStopRequest) (*rpc.SshStopResponse, error) {
if sshCancelFunc != nil {
sshCancelFunc()
}
return &rpc.SshStopResponse{}, nil
}
24 changes: 24 additions & 0 deletions pkg/daemon/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -157,3 +159,25 @@ func runDaemon(ctx context.Context, exe string, isSudo bool) error {

return err
}

func GetHttpClient(isSudo bool) *http.Client {
client := http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
var d net.Dialer
d.Timeout = 30 * time.Second
d.KeepAlive = 30 * time.Second
return d.DialContext(ctx, "unix", GetSockPath(isSudo))
},
},
}
return &client
}

func GetTCPClient(isSudo bool) net.Conn {
conn, err := net.Dial("unix", GetSockPath(isSudo))
if err != nil {
return nil
}
return conn
}
33 changes: 32 additions & 1 deletion pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import (
"net"
"net/http"
"os"
"strings"
"time"

log "github.com/sirupsen/logrus"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"google.golang.org/grpc"
"google.golang.org/grpc/admin"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"

"github.com/wencaiwulue/kubevpn/pkg/daemon/action"
_ "github.com/wencaiwulue/kubevpn/pkg/daemon/handler"
"github.com/wencaiwulue/kubevpn/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/pkg/util"
)
Expand Down Expand Up @@ -64,8 +68,16 @@ func (o *SvrOption) Start(ctx context.Context) error {
// [tun-client] 223.254.0.101 - 127.0.0.1:8422: dial tcp 127.0.0.1:55407: connect: can't assign requested address
http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 100
rpc.RegisterDaemonServer(o.svr, &action.Server{Cancel: o.Stop, IsSudo: o.IsSudo, GetClient: GetClient, LogFile: file})
// startup a http server
// With downgrading-capable gRPC server, which can also handle HTTP.
downgradingServer := &http.Server{}
var h2Server http2.Server
_ = http2.ConfigureServer(downgradingServer, &h2Server)
handler := CreateDowngradingHandler(o.svr, http.HandlerFunc(http.DefaultServeMux.ServeHTTP))
downgradingServer.Handler = h2c.NewHandler(handler, &h2Server)
o.uptime = time.Now().Unix()
return o.svr.Serve(lis)
return downgradingServer.Serve(lis)
//return o.svr.Serve(lis)
}

func (o *SvrOption) Stop() {
Expand All @@ -77,3 +89,22 @@ func (o *SvrOption) Stop() {
path := GetSockPath(o.IsSudo)
_ = os.Remove(path)
}

// CreateDowngradingHandler takes a gRPC server and a plain HTTP handler, and returns an HTTP handler that has the
// capability of handling HTTP requests and gRPC requests that may require downgrading the response to gRPC-Web or gRPC-WebSocket.
//
// if r.ProtoMajor == 2 && strings.HasPrefix(
// r.Header.Get("Content-Type"), "application/grpc") {
// grpcServer.ServeHTTP(w, r)
// } else {
// yourMux.ServeHTTP(w, r)
// }
func CreateDowngradingHandler(grpcServer *grpc.Server, httpHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.ProtoMajor == 2 && strings.HasPrefix(r.Header.Get("Content-Type"), "application/grpc") {
grpcServer.ServeHTTP(w, r)
} else {
httpHandler.ServeHTTP(w, r)
}
})
}
Loading

0 comments on commit b2458c2

Please sign in to comment.