Unverified Commit 04b83c9f authored by 老广's avatar 老广 Committed by GitHub

Merge pull request #48 from jumpserver/dev

Dev
parents 29a0e0d3 56ca009c
...@@ -11,10 +11,16 @@ ...@@ -11,10 +11,16 @@
var scheme = document.location.protocol == "https:" ? "wss" : "ws"; var scheme = document.location.protocol == "https:" ? "wss" : "ws";
var port = document.location.port ? ":" + document.location.port : ""; var port = document.location.port ? ":" + document.location.port : "";
var wsURL = scheme + "://" + document.location.hostname + port + "/socket.io/"; var wsURL = scheme + "://" + document.location.hostname + port + "/socket.io/";
let interval;
dial(wsURL, { dial(wsURL, {
"elfinder": { "elfinder": {
_OnNamespaceConnected: function (nsConn, msg) { _OnNamespaceConnected: function (nsConn, msg) {
console.log("Connect websocket done") interval = setInterval(() => nsConn.emit('ping', ''), 10000);
},
_OnNamespaceDisconnect: function (ns, msg) {
if (interval) {
clearInterval(interval);
}
}, },
data: function (nsConn, msg) { data: function (nsConn, msg) {
var data = msg.unmarshal(); var data = msg.unmarshal();
......
package httpd package httpd
import ( import (
"fmt"
"sync" "sync"
"github.com/jumpserver/koko/pkg/logger" "github.com/jumpserver/koko/pkg/logger"
...@@ -37,14 +36,12 @@ func (c *Clients) DeleteClient(cID string) { ...@@ -37,14 +36,12 @@ func (c *Clients) DeleteClient(cID string) {
} }
func (c *Clients) AddClient(cID string, conn *Client) { func (c *Clients) AddClient(cID string, conn *Client) {
fmt.Println("Add Client id: ", cID)
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
c.container[cID] = conn c.container[cID] = conn
logger.Debug("Now clients count: ", len(c.container)) logger.Debug("Now clients count: ", len(c.container))
} }
type Connections struct { type Connections struct {
container map[string][]string container map[string][]string
mu *sync.RWMutex mu *sync.RWMutex
...@@ -69,7 +66,7 @@ func (c *Connections) GetClients(cID string) (clients []string) { ...@@ -69,7 +66,7 @@ func (c *Connections) GetClients(cID string) (clients []string) {
} }
func (c *Connections) DeleteClients(cID string) { func (c *Connections) DeleteClients(cID string) {
if clientIDs := c.GetClients(cID); clientIDs != nil{ if clientIDs := c.GetClients(cID); clientIDs != nil {
for _, clientID := range clientIDs { for _, clientID := range clientIDs {
clients.DeleteClient(clientID) clients.DeleteClient(clientID)
} }
...@@ -78,4 +75,3 @@ func (c *Connections) DeleteClients(cID string) { ...@@ -78,4 +75,3 @@ func (c *Connections) DeleteClients(cID string) {
defer c.mu.Unlock() defer c.mu.Unlock()
delete(c.container, cID) delete(c.container, cID)
} }
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"net" "net"
"net/http" "net/http"
"path/filepath" "path/filepath"
"time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/kataras/neffos" "github.com/kataras/neffos"
...@@ -15,28 +16,35 @@ import ( ...@@ -15,28 +16,35 @@ import (
var ( var (
httpServer *http.Server httpServer *http.Server
Timeout = time.Duration(60)
) )
var wsEvents = neffos.Namespaces{ var wsEvents = neffos.WithTimeout{
"ssh": neffos.Events{ ReadTimeout: Timeout * time.Second,
neffos.OnNamespaceConnected: OnNamespaceConnected, WriteTimeout: Timeout * time.Second,
neffos.OnNamespaceDisconnect: OnNamespaceDisconnect, Namespaces: neffos.Namespaces{
neffos.OnRoomJoined: func(c *neffos.NSConn, msg neffos.Message) error { "ssh": neffos.Events{
return nil neffos.OnNamespaceConnected: OnNamespaceConnected,
neffos.OnNamespaceDisconnect: OnNamespaceDisconnect,
neffos.OnRoomJoined: func(c *neffos.NSConn, msg neffos.Message) error {
return nil
},
neffos.OnRoomLeft: func(c *neffos.NSConn, msg neffos.Message) error {
return nil
},
"data": OnDataHandler,
"resize": OnResizeHandler,
"host": OnHostHandler,
"logout": OnLogoutHandler,
"token": OnTokenHandler,
"ping": OnPingHandler,
}, },
neffos.OnRoomLeft: func(c *neffos.NSConn, msg neffos.Message) error { "elfinder": neffos.Events{
return nil neffos.OnNamespaceConnected: OnELFinderConnect,
neffos.OnNamespaceDisconnect: OnELFinderDisconnect,
"ping": OnPingHandler,
}, },
"data": OnDataHandler,
"resize": OnResizeHandler,
"host": OnHostHandler,
"logout": OnLogoutHandler,
"token": OnTokenHandler,
},
"elfinder": neffos.Events{
neffos.OnNamespaceConnected: OnELFinderConnect,
neffos.OnNamespaceDisconnect: OnELFinderDisconnect,
}, },
} }
...@@ -47,6 +55,22 @@ func StartHTTPServer() { ...@@ -47,6 +55,22 @@ func StartHTTPServer() {
return neffos.DefaultIDGenerator(w, r) return neffos.DefaultIDGenerator(w, r)
} }
sshWs.OnUpgradeError = func(err error) { sshWs.OnUpgradeError = func(err error) {
if ok := neffos.IsTryingToReconnect(err); ok {
logger.Debug("A client was tried to reconnect")
return
}
logger.Error("ERROR: ", err)
}
sshWs.OnConnect = func(c *neffos.Conn) error {
if c.WasReconnected() {
logger.Debugf("Connection %s reconnected, with tries: %d", c.ID(), c.ReconnectTries)
} else {
logger.Debug("A new ws connection arrive")
}
return nil
}
sshWs.OnDisconnect = func(c *neffos.Conn) {
logger.Debug("Ws connection disconnect")
} }
router := mux.NewRouter() router := mux.NewRouter()
......
...@@ -172,7 +172,7 @@ func (u *UserVolume) UploadChunk(cid int, dirPath, chunkName string, reader io.R ...@@ -172,7 +172,7 @@ func (u *UserVolume) UploadChunk(cid int, dirPath, chunkName string, reader io.R
func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfinder.FileDir, error) { func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfinder.FileDir, error) {
path := filepath.Join(dirPath, filename) path := filepath.Join(dirPath, filename)
logger.Debug("merge chunk path: ",path) logger.Debug("merge chunk path: ", path)
var rest elfinder.FileDir var rest elfinder.FileDir
fd, err := u.UserSftp.Create(path) fd, err := u.UserSftp.Create(path)
if err != nil { if err != nil {
...@@ -249,6 +249,15 @@ func (u *UserVolume) Rename(oldNamePath, newName string) (elfinder.FileDir, erro ...@@ -249,6 +249,15 @@ func (u *UserVolume) Rename(oldNamePath, newName string) (elfinder.FileDir, erro
} }
func (u *UserVolume) Remove(path string) error { func (u *UserVolume) Remove(path string) error {
var res os.FileInfo
var err error
res, err = u.UserSftp.Stat(path)
if err != nil {
return err
}
if res.IsDir() {
return u.UserSftp.RemoveDirectory(path)
}
return u.UserSftp.Remove(path) return u.UserSftp.Remove(path)
} }
......
...@@ -4,31 +4,32 @@ import ( ...@@ -4,31 +4,32 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/jumpserver/koko/pkg/model"
"io" "io"
"net" "net"
"strings" "strings"
"sync" "sync"
"time"
"github.com/gliderlabs/ssh" "github.com/gliderlabs/ssh"
"github.com/kataras/neffos" "github.com/kataras/neffos"
"github.com/satori/go.uuid" "github.com/satori/go.uuid"
"github.com/jumpserver/koko/pkg/logger" "github.com/jumpserver/koko/pkg/logger"
"github.com/jumpserver/koko/pkg/model"
"github.com/jumpserver/koko/pkg/proxy" "github.com/jumpserver/koko/pkg/proxy"
"github.com/jumpserver/koko/pkg/service" "github.com/jumpserver/koko/pkg/service"
) )
func OnPingHandler(c *neffos.NSConn, msg neffos.Message) error {
c.Emit("pong", []byte(""))
return nil
}
// OnConnectHandler 当websocket连接后触发 // OnConnectHandler 当websocket连接后触发
func OnNamespaceConnected(c *neffos.NSConn, msg neffos.Message) error { func OnNamespaceConnected(c *neffos.NSConn, msg neffos.Message) error {
// 首次连接 1.获取当前用户的信息 // 首次连接 1.获取当前用户的信息
cc := c.Conn cc := c.Conn
if cc.WasReconnected() { logger.Debug("Web terminal on connect event trigger")
logger.Debugf("Web terminal redirected, with tries: %d", cc.ID(), cc.ReconnectTries)
} else {
logger.Debug("Web terminal on connect event trigger")
}
request := cc.Socket().Request() request := cc.Socket().Request()
header := request.Header header := request.Header
cookies := strings.Split(header.Get("Cookie"), ";") cookies := strings.Split(header.Get("Cookie"), ";")
...@@ -54,6 +55,12 @@ func OnNamespaceConnected(c *neffos.NSConn, msg neffos.Message) error { ...@@ -54,6 +55,12 @@ func OnNamespaceConnected(c *neffos.NSConn, msg neffos.Message) error {
} }
remoteIP = strings.Split(remoteAddr, ",")[0] remoteIP = strings.Split(remoteAddr, ",")[0]
logger.Infof("Accepted %s connect websocket from %s", user.Username, remoteIP) logger.Infof("Accepted %s connect websocket from %s", user.Username, remoteIP)
go func() {
for {
<-time.After(30 * time.Second)
c.Emit("ping", []byte(""))
}
}()
return nil return nil
} }
...@@ -130,7 +137,7 @@ func OnHostHandler(c *neffos.NSConn, msg neffos.Message) (err error) { ...@@ -130,7 +137,7 @@ func OnHostHandler(c *neffos.NSConn, msg neffos.Message) (err error) {
} }
go func() { go func() {
defer logger.Debug("Web proxy process end") defer logger.Debug("Web proxy process end")
logger.Debug("Start proxy to host") logger.Debug("Web ssh start proxy to host")
proxySrv.Proxy() proxySrv.Proxy()
logoutMsg, _ := json.Marshal(RoomMsg{Room: roomID}) logoutMsg, _ := json.Marshal(RoomMsg{Room: roomID})
// 服务器主动退出 // 服务器主动退出
......
...@@ -141,6 +141,7 @@ func (s *SwitchSession) Bridge(userConn UserConnection, srvConn srvconn.ServerCo ...@@ -141,6 +141,7 @@ func (s *SwitchSession) Bridge(userConn UserConnection, srvConn srvconn.ServerCo
// 检测是否超过最大空闲时间 // 检测是否超过最大空闲时间
case <-time.After(s.MaxIdleTime * time.Minute): case <-time.After(s.MaxIdleTime * time.Minute):
msg := fmt.Sprintf(i18n.T("Connect idle more than %d minutes, disconnect"), s.MaxIdleTime) msg := fmt.Sprintf(i18n.T("Connect idle more than %d minutes, disconnect"), s.MaxIdleTime)
logger.Debugf("Session idle more than %d minutes, disconnect: %s", s.MaxIdleTime, s.ID)
msg = utils.WrapperWarn(msg) msg = utils.WrapperWarn(msg)
utils.IgnoreErrWriteString(userConn, "\n\r"+msg) utils.IgnoreErrWriteString(userConn, "\n\r"+msg)
return return
......
...@@ -172,7 +172,7 @@ func (u *UserSftp) RemoveDirectory(path string) error { ...@@ -172,7 +172,7 @@ func (u *UserSftp) RemoveDirectory(path string) error {
if conn == nil { if conn == nil {
return sftp.ErrSshFxPermissionDenied return sftp.ErrSshFxPermissionDenied
} }
err := conn.client.RemoveDirectory(realPath) err := u.removeDirectoryAll(conn.client, realPath)
filename := realPath filename := realPath
isSucess := false isSucess := false
operate := model.OperateRemoveDir operate := model.OperateRemoveDir
...@@ -183,6 +183,31 @@ func (u *UserSftp) RemoveDirectory(path string) error { ...@@ -183,6 +183,31 @@ func (u *UserSftp) RemoveDirectory(path string) error {
return err return err
} }
func (u *UserSftp) removeDirectoryAll(conn *sftp.Client, path string) error {
var err error
var files []os.FileInfo
files, err = conn.ReadDir(path)
if err != nil {
return err
}
for _, item := range files {
realPath := filepath.Join(path, item.Name())
if item.IsDir() {
err = u.removeDirectoryAll(conn, realPath)
if err != nil {
return err
}
continue
}
err = conn.Remove(realPath)
if err != nil {
return err
}
}
return conn.RemoveDirectory(path)
}
func (u *UserSftp) Remove(path string) error { func (u *UserSftp) Remove(path string) error {
req := u.ParsePath(path) req := u.ParsePath(path)
if req.host == "" { if req.host == "" {
...@@ -496,9 +521,17 @@ func (u *UserSftp) LoopPushFTPLog() { ...@@ -496,9 +521,17 @@ func (u *UserSftp) LoopPushFTPLog() {
dataChan := make(chan *model.FTPLog) dataChan := make(chan *model.FTPLog)
go u.SendFTPLog(dataChan) go u.SendFTPLog(dataChan)
defer close(dataChan) defer close(dataChan)
var timeoutSecond time.Duration
for { for {
switch len(ftpLogList) {
case 0:
timeoutSecond = time.Second * 60
default:
timeoutSecond = time.Second * 1
}
select { select {
case <-time.After(time.Second * 5): case <-time.After(timeoutSecond):
case logData, ok := <-u.LogChan: case logData, ok := <-u.LogChan:
if !ok { if !ok {
return return
...@@ -613,7 +646,7 @@ func NewFakeFile(name string, isDir bool) *FakeFileInfo { ...@@ -613,7 +646,7 @@ func NewFakeFile(name string, isDir bool) *FakeFileInfo {
} }
} }
func NewFakeSymFile(name string) *FakeFileInfo{ func NewFakeSymFile(name string) *FakeFileInfo {
return &FakeFileInfo{ return &FakeFileInfo{
name: name, name: name,
modtime: time.Now().UTC(), modtime: time.Now().UTC(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment