From dbf040c27f562683c2901eaf4c3e6633edfc91de Mon Sep 17 00:00:00 2001 From: lwch Date: Mon, 18 Oct 2021 15:37:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0vnc=20connect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/client/connect.go | 22 +++ code/client/global/conf.go | 21 +-- code/client/main.go | 2 + code/client/pool/send_conn.go | 12 ++ code/client/tunnel/vnc/assets.go | 221 +++++++++++++++++++++++++++++ code/client/tunnel/vnc/h_new.go | 56 ++++++++ code/client/tunnel/vnc/h_render.go | 33 +++++ code/client/tunnel/vnc/link.go | 14 ++ code/client/tunnel/vnc/vnc.go | 23 +++ code/network/connect.pb.go | 159 ++++++++++++++++----- code/network/connect.proto | 5 + conf/tunnel.d/vnc.yaml | 7 +- contrib/build/build | 6 +- contrib/build/build_all.go | 9 ++ 14 files changed, 537 insertions(+), 53 deletions(-) create mode 100644 code/client/tunnel/vnc/assets.go create mode 100644 code/client/tunnel/vnc/h_new.go create mode 100644 code/client/tunnel/vnc/h_render.go diff --git a/code/client/connect.go b/code/client/connect.go index 3afab30..1a5d7da 100644 --- a/code/client/connect.go +++ b/code/client/connect.go @@ -7,6 +7,7 @@ import ( "natpass/code/client/tunnel" "natpass/code/client/tunnel/reverse" "natpass/code/client/tunnel/shell" + "natpass/code/client/tunnel/vnc" "natpass/code/network" "net" "strconv" @@ -67,3 +68,24 @@ func shellCreate(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) { conn.SendConnectOK(msg.GetFrom(), msg.GetFromIdx(), msg.GetLinkId()) lk.Forward() } + +func vncCreate(mgr *tunnel.Mgr, conn *pool.Conn, msg *network.Msg) { + create := msg.GetCreq() + v := vnc.New(global.Tunnel{ + Name: create.GetName(), + Target: msg.GetFrom(), + Type: "vnc", + Fps: create.GetCvnc().GetFps(), + }) + mgr.Add(v) + lk := vnc.NewLink(v, msg.GetLinkId(), msg.GetFrom(), conn) + lk.SetTargetIdx(msg.GetFromIdx()) + err := lk.Fork() + if err != nil { + logging.Error("create shell failed: %v", err) + conn.SendConnectError(msg.GetFrom(), msg.GetFromIdx(), msg.GetLinkId(), err.Error()) + return + } + conn.SendConnectOK(msg.GetFrom(), msg.GetFromIdx(), msg.GetLinkId()) + lk.Forward() +} diff --git a/code/client/global/conf.go b/code/client/global/conf.go index 0a5d0a6..01309ab 100644 --- a/code/client/global/conf.go +++ b/code/client/global/conf.go @@ -11,15 +11,18 @@ import ( // Tunnel tunnel config type Tunnel struct { - Name string `yaml:"name"` - Target string `yaml:"target"` - Type string `yaml:"type"` - LocalAddr string `yaml:"local_addr"` - LocalPort uint16 `yaml:"local_port"` - RemoteAddr string `yaml:"remote_addr"` - RemotePort uint16 `yaml:"remote_port"` - Exec string `yaml:"exec"` - Env []string `yaml:"env"` + Name string `yaml:"name"` + Target string `yaml:"target"` + Type string `yaml:"type"` + LocalAddr string `yaml:"local_addr"` + LocalPort uint16 `yaml:"local_port"` + RemoteAddr string `yaml:"remote_addr"` + RemotePort uint16 `yaml:"remote_port"` + // shell + Exec string `yaml:"exec"` + Env []string `yaml:"env"` + // vnc + Fps uint32 `yaml:"fps"` } // Configure client configure diff --git a/code/client/main.go b/code/client/main.go index f943926..19679df 100644 --- a/code/client/main.go +++ b/code/client/main.go @@ -96,6 +96,8 @@ func (a *app) run() { connect(mgr, conn, msg) case network.ConnectRequest_shell: shellCreate(mgr, conn, msg) + case network.ConnectRequest_vnc: + vncCreate(mgr, conn, msg) } default: linkID = msg.GetLinkId() diff --git a/code/client/pool/send_conn.go b/code/client/pool/send_conn.go index d92162a..e14df1f 100644 --- a/code/client/pool/send_conn.go +++ b/code/client/pool/send_conn.go @@ -42,6 +42,18 @@ func (conn *Conn) SendConnectReq(id string, cfg global.Tunnel) { }, }, } + case "vnc": + msg.Payload = &network.Msg_Creq{ + Creq: &network.ConnectRequest{ + Name: cfg.Name, + XType: network.ConnectRequest_vnc, + Payload: &network.ConnectRequest_Cvnc{ + Cvnc: &network.ConnectVnc{ + Fps: cfg.Fps, + }, + }, + }, + } } select { case conn.write <- &msg: diff --git a/code/client/tunnel/vnc/assets.go b/code/client/tunnel/vnc/assets.go new file mode 100644 index 0000000..e538511 --- /dev/null +++ b/code/client/tunnel/vnc/assets.go @@ -0,0 +1,221 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + + //Package vnc generated by go-bindata.// sources: +package vnc + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/code/client/tunnel/vnc/h_new.go b/code/client/tunnel/vnc/h_new.go new file mode 100644 index 0000000..8745140 --- /dev/null +++ b/code/client/tunnel/vnc/h_new.go @@ -0,0 +1,56 @@ +package vnc + +import ( + "fmt" + "natpass/code/client/pool" + "natpass/code/network" + "net/http" + "time" + + "github.com/lwch/logging" + "github.com/lwch/runtime" +) + +// New new vnc +func (v *VNC) New(pool *pool.Pool, w http.ResponseWriter, r *http.Request) { + id, err := runtime.UUID(16, "0123456789abcdef") + if err != nil { + logging.Error("failed to generate link_id for vnc: %s, err=%v", + v.Name, err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + conn := pool.Get(id) + conn.SendConnectReq(id, v.cfg) + link := NewLink(v, id, v.cfg.Target, conn) + v.Lock() + v.links[id] = link + v.Unlock() + ch := conn.ChanRead(id) + timeout := time.After(conn.ReadTimeout) + for { + var msg *network.Msg + select { + case msg = <-ch: + case <-timeout: + logging.Error("create vnc %s on tunnel %s failed, timtout", link.id, link.parent.Name) + http.Error(w, "timeout", http.StatusBadGateway) + return + } + if msg.GetXType() != network.Msg_connect_rep { + conn.Reset(id, msg) + time.Sleep(conn.ReadTimeout / 10) + continue + } + rep := msg.GetCrep() + if !rep.GetOk() { + logging.Error("create vnc %s on tunnel %s failed, err=%s", + link.id, link.parent.Name, rep.GetMsg()) + http.Error(w, rep.GetMsg(), http.StatusBadGateway) + return + } + break + } + logging.Info("new vnc: name=%s, id=%s", v.Name, id) + fmt.Fprint(w, id) +} diff --git a/code/client/tunnel/vnc/h_render.go b/code/client/tunnel/vnc/h_render.go new file mode 100644 index 0000000..53e56cb --- /dev/null +++ b/code/client/tunnel/vnc/h_render.go @@ -0,0 +1,33 @@ +package vnc + +import ( + "bytes" + "html/template" + "io" + "mime" + "net/http" + "path/filepath" + "strings" +) + +// Render render asset file +func (v *VNC) Render(w http.ResponseWriter, r *http.Request) { + dir := strings.TrimPrefix(r.URL.Path, "/") + data, err := Asset(dir) + if err == nil { + ctype := mime.TypeByExtension(filepath.Ext(dir)) + if ctype == "" { + ctype = http.DetectContentType(data) + } + w.Header().Set("Content-Type", ctype) + io.Copy(w, bytes.NewReader(data)) + return + } + data, _ = Asset("index.html") + tpl, err := template.New("all").Parse(string(data)) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + tpl.Execute(w, v) +} diff --git a/code/client/tunnel/vnc/link.go b/code/client/tunnel/vnc/link.go index 93facc4..2a39af0 100644 --- a/code/client/tunnel/vnc/link.go +++ b/code/client/tunnel/vnc/link.go @@ -47,3 +47,17 @@ func (link *Link) GetBytes() (uint64, uint64) { func (link *Link) GetPackets() (uint64, uint64) { return link.recvPacket, link.sendPacket } + +// SetTargetIdx set link remote index +func (link *Link) SetTargetIdx(idx uint32) { + link.targetIdx = idx +} + +// Fork fork worker process +func (link *Link) Fork() error { + return nil +} + +// Forward forward data +func (link *Link) Forward() { +} diff --git a/code/client/tunnel/vnc/vnc.go b/code/client/tunnel/vnc/vnc.go index 1ca0c5d..32b33b9 100644 --- a/code/client/tunnel/vnc/vnc.go +++ b/code/client/tunnel/vnc/vnc.go @@ -1,10 +1,15 @@ package vnc import ( + "fmt" "natpass/code/client/global" "natpass/code/client/pool" "natpass/code/client/tunnel" + "net/http" "sync" + + "github.com/lwch/logging" + "github.com/lwch/runtime" ) // VNC vnc handler @@ -62,4 +67,22 @@ func (v *VNC) GetPort() uint16 { // Handle handle shell func (v *VNC) Handle(pl *pool.Pool) { + defer func() { + if err := recover(); err != nil { + logging.Error("close shell tunnel: %s, err=%v", v.Name, err) + } + }() + pf := func(cb func(*pool.Pool, http.ResponseWriter, *http.Request)) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cb(pl, w, r) + } + } + mux := http.NewServeMux() + mux.HandleFunc("/new", pf(v.New)) + mux.HandleFunc("/", v.Render) + svr := &http.Server{ + Addr: fmt.Sprintf("%s:%d", v.cfg.LocalAddr, v.cfg.LocalPort), + Handler: mux, + } + runtime.Assert(svr.ListenAndServe()) } diff --git a/code/network/connect.pb.go b/code/network/connect.pb.go index d8f4ce8..dce3646 100644 --- a/code/network/connect.pb.go +++ b/code/network/connect.pb.go @@ -69,7 +69,7 @@ func (x ConnectRequestType) Number() protoreflect.EnumNumber { // Deprecated: Use ConnectRequestType.Descriptor instead. func (ConnectRequestType) EnumDescriptor() ([]byte, []int) { - return file_connect_proto_rawDescGZIP(), []int{2, 0} + return file_connect_proto_rawDescGZIP(), []int{3, 0} } type ConnectAddr struct { @@ -182,6 +182,53 @@ func (x *ConnectShell) GetEnv() []string { return nil } +type ConnectVnc struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Fps uint32 `protobuf:"varint,1,opt,name=fps,proto3" json:"fps,omitempty"` +} + +func (x *ConnectVnc) Reset() { + *x = ConnectVnc{} + if protoimpl.UnsafeEnabled { + mi := &file_connect_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConnectVnc) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConnectVnc) ProtoMessage() {} + +func (x *ConnectVnc) ProtoReflect() protoreflect.Message { + mi := &file_connect_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConnectVnc.ProtoReflect.Descriptor instead. +func (*ConnectVnc) Descriptor() ([]byte, []int) { + return file_connect_proto_rawDescGZIP(), []int{2} +} + +func (x *ConnectVnc) GetFps() uint32 { + if x != nil { + return x.Fps + } + return 0 +} + type ConnectRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -192,13 +239,14 @@ type ConnectRequest struct { // Types that are assignable to Payload: // *ConnectRequest_Caddr // *ConnectRequest_Cshell + // *ConnectRequest_Cvnc Payload isConnectRequest_Payload `protobuf_oneof:"payload"` } func (x *ConnectRequest) Reset() { *x = ConnectRequest{} if protoimpl.UnsafeEnabled { - mi := &file_connect_proto_msgTypes[2] + mi := &file_connect_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -211,7 +259,7 @@ func (x *ConnectRequest) String() string { func (*ConnectRequest) ProtoMessage() {} func (x *ConnectRequest) ProtoReflect() protoreflect.Message { - mi := &file_connect_proto_msgTypes[2] + mi := &file_connect_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -224,7 +272,7 @@ func (x *ConnectRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectRequest.ProtoReflect.Descriptor instead. func (*ConnectRequest) Descriptor() ([]byte, []int) { - return file_connect_proto_rawDescGZIP(), []int{2} + return file_connect_proto_rawDescGZIP(), []int{3} } func (x *ConnectRequest) GetName() string { @@ -262,6 +310,13 @@ func (x *ConnectRequest) GetCshell() *ConnectShell { return nil } +func (x *ConnectRequest) GetCvnc() *ConnectVnc { + if x, ok := x.GetPayload().(*ConnectRequest_Cvnc); ok { + return x.Cvnc + } + return nil +} + type isConnectRequest_Payload interface { isConnectRequest_Payload() } @@ -274,10 +329,16 @@ type ConnectRequest_Cshell struct { Cshell *ConnectShell `protobuf:"bytes,11,opt,name=cshell,proto3,oneof"` } +type ConnectRequest_Cvnc struct { + Cvnc *ConnectVnc `protobuf:"bytes,12,opt,name=cvnc,proto3,oneof"` +} + func (*ConnectRequest_Caddr) isConnectRequest_Payload() {} func (*ConnectRequest_Cshell) isConnectRequest_Payload() {} +func (*ConnectRequest_Cvnc) isConnectRequest_Payload() {} + type ConnectResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -290,7 +351,7 @@ type ConnectResponse struct { func (x *ConnectResponse) Reset() { *x = ConnectResponse{} if protoimpl.UnsafeEnabled { - mi := &file_connect_proto_msgTypes[3] + mi := &file_connect_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -303,7 +364,7 @@ func (x *ConnectResponse) String() string { func (*ConnectResponse) ProtoMessage() {} func (x *ConnectResponse) ProtoReflect() protoreflect.Message { - mi := &file_connect_proto_msgTypes[3] + mi := &file_connect_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -316,7 +377,7 @@ func (x *ConnectResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectResponse.ProtoReflect.Descriptor instead. func (*ConnectResponse) Descriptor() ([]byte, []int) { - return file_connect_proto_rawDescGZIP(), []int{3} + return file_connect_proto_rawDescGZIP(), []int{4} } func (x *ConnectResponse) GetOk() bool { @@ -344,27 +405,32 @@ var file_connect_proto_rawDesc = []byte{ 0x22, 0x35, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x78, 0x65, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x22, 0xf3, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x32, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, - 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x63, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, 0x64, - 0x64, 0x72, 0x12, 0x30, 0x0a, 0x06, 0x63, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x73, - 0x68, 0x65, 0x6c, 0x6c, 0x22, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, - 0x74, 0x63, 0x70, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x75, 0x64, 0x70, 0x10, 0x01, 0x12, 0x09, - 0x0a, 0x05, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x6e, 0x63, - 0x10, 0x03, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x34, 0x0a, - 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, - 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6d, 0x73, 0x67, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x3b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x22, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x5f, 0x76, 0x6e, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x70, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x03, 0x66, 0x70, 0x73, 0x22, 0x9f, 0x02, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x32, 0x0a, 0x05, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1d, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x63, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x48, 0x00, 0x52, 0x05, 0x63, 0x61, + 0x64, 0x64, 0x72, 0x12, 0x30, 0x0a, 0x06, 0x63, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, + 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x2a, 0x0a, 0x04, 0x63, 0x76, 0x6e, 0x63, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x76, 0x6e, 0x63, 0x48, 0x00, 0x52, 0x04, 0x63, 0x76, 0x6e, + 0x63, 0x22, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x74, 0x63, 0x70, + 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x75, 0x64, 0x70, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x73, + 0x68, 0x65, 0x6c, 0x6c, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x76, 0x6e, 0x63, 0x10, 0x03, 0x42, + 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x34, 0x0a, 0x10, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x10, + 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, + 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x3b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -380,23 +446,25 @@ func file_connect_proto_rawDescGZIP() []byte { } var file_connect_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_connect_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_connect_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_connect_proto_goTypes = []interface{}{ (ConnectRequestType)(0), // 0: network.connect_request.type (*ConnectAddr)(nil), // 1: network.connect_addr (*ConnectShell)(nil), // 2: network.connect_shell - (*ConnectRequest)(nil), // 3: network.connect_request - (*ConnectResponse)(nil), // 4: network.connect_response + (*ConnectVnc)(nil), // 3: network.connect_vnc + (*ConnectRequest)(nil), // 4: network.connect_request + (*ConnectResponse)(nil), // 5: network.connect_response } var file_connect_proto_depIdxs = []int32{ 0, // 0: network.connect_request._type:type_name -> network.connect_request.type 1, // 1: network.connect_request.caddr:type_name -> network.connect_addr 2, // 2: network.connect_request.cshell:type_name -> network.connect_shell - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 3, // 3: network.connect_request.cvnc:type_name -> network.connect_vnc + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_connect_proto_init() } @@ -430,7 +498,7 @@ func file_connect_proto_init() { } } file_connect_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectRequest); i { + switch v := v.(*ConnectVnc); i { case 0: return &v.state case 1: @@ -442,6 +510,18 @@ func file_connect_proto_init() { } } file_connect_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConnectRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_connect_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConnectResponse); i { case 0: return &v.state @@ -454,9 +534,10 @@ func file_connect_proto_init() { } } } - file_connect_proto_msgTypes[2].OneofWrappers = []interface{}{ + file_connect_proto_msgTypes[3].OneofWrappers = []interface{}{ (*ConnectRequest_Caddr)(nil), (*ConnectRequest_Cshell)(nil), + (*ConnectRequest_Cvnc)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -464,7 +545,7 @@ func file_connect_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_connect_proto_rawDesc, NumEnums: 1, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/code/network/connect.proto b/code/network/connect.proto index 84d5cbf..3bd90de 100644 --- a/code/network/connect.proto +++ b/code/network/connect.proto @@ -13,6 +13,10 @@ message connect_shell { repeated string env = 2; } +message connect_vnc { + uint32 fps = 1; +} + message connect_request { enum type { tcp = 0; @@ -25,6 +29,7 @@ message connect_request { oneof payload { connect_addr caddr = 10; connect_shell cshell = 11; + connect_vnc cvnc = 12; } } diff --git a/conf/tunnel.d/vnc.yaml b/conf/tunnel.d/vnc.yaml index b6b79ed..3ab7bf1 100644 --- a/conf/tunnel.d/vnc.yaml +++ b/conf/tunnel.d/vnc.yaml @@ -1,5 +1,6 @@ -- name: vnc # 链路名称 +- name: vnc # 链路名称 target: that # 目标客户端ID - type: vnc # web vnc + type: vnc # web vnc local_addr: 0.0.0.0 # 本地监听地址 - local_port: 5900 # 本地监听端口号 \ No newline at end of file + local_port: 5900 # 本地监听端口号 + fps: 10 # 刷新频率 \ No newline at end of file diff --git a/contrib/build/build b/contrib/build/build index 4843eb1..e113b51 100755 --- a/contrib/build/build +++ b/contrib/build/build @@ -13,11 +13,13 @@ LDFLAGS="-X 'main.gitHash=$HASH' go run contrib/bindata/main.go -pkg shell -o code/client/tunnel/shell/assets.go \ -prefix html/shell "$@" html/shell/... +go run contrib/bindata/main.go -pkg vnc -o code/client/tunnel/vnc/assets.go \ + -prefix html/vnc "$@" html/vnc/... go run contrib/bindata/main.go -pkg dashboard -o code/client/dashboard/assets.go \ -prefix html/dashboard "$@" html/dashboard/... CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ -CGO_ENABLED=0 go build -v -ldflags "$LDFLAGS" -o bin/np-svr code/server/*.go -CGO_ENABLED=0 go build -v -ldflags "$LDFLAGS" -o bin/np-cli code/client/*.go +CGO_ENABLED=0 go build -ldflags "$LDFLAGS" -o bin/np-svr code/server/*.go +CGO_ENABLED=0 go build -ldflags "$LDFLAGS" -o bin/np-cli code/client/*.go diff --git a/contrib/build/build_all.go b/contrib/build/build_all.go index 8b963e5..d4ee747 100644 --- a/contrib/build/build_all.go +++ b/contrib/build/build_all.go @@ -113,6 +113,15 @@ func bindata() { cmd.Stderr = os.Stderr runtime.Assert(cmd.Run()) + cmd = exec.Command("go", "run", "contrib/bindata/main.go", + "-pkg", "vnc", + "-o", "code/client/tunnel/vnc/assets.go", + "-prefix", "html/vnc", + "html/vnc/...") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + runtime.Assert(cmd.Run()) + cmd = exec.Command("go", "run", "contrib/bindata/main.go", "-pkg", "dashboard", "-o", "code/client/dashboard/assets.go",