Unverified Commit 02264e53 authored by Eric_Lee's avatar Eric_Lee Committed by GitHub

support tcp proxy and ssh keep-alive (#74)

* support tcp proxy (#72)

* fix selected item display bug

* [Update]add ssh keep-alive

* Fix MFA login http response error
parent 8f79e09a
...@@ -1280,7 +1280,8 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical { ...@@ -1280,7 +1280,8 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical {
} }
.elfinder-cwd-file.ui-selected { .elfinder-cwd-file.ui-selected {
background: #455158; background: #455158;
color: #555; /*color: #555;*/
color: #ddd;
width: 120px !important; width: 120px !important;
} }
.elfinder-cwd-filename input, .elfinder-cwd-filename input,
...@@ -1309,10 +1310,10 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical { ...@@ -1309,10 +1310,10 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical {
padding: 0; padding: 0;
} }
.elfinder-cwd table tr:nth-child(odd) { .elfinder-cwd table tr:nth-child(odd) {
background-color: transparent; /*background-color: transparent;*/
} }
.elfinder-cwd table tr:nth-child(odd).ui-state-hover { .elfinder-cwd table tr:nth-child(odd).ui-state-hover {
background-color: #4c5961; /*background-color: #4c5961;*/
} }
#elfinder-elfinder-cwd-thead td { #elfinder-elfinder-cwd-thead td {
background: #353b42; background: #353b42;
......
...@@ -24,6 +24,7 @@ require ( ...@@ -24,6 +24,7 @@ require (
github.com/leonelquinteros/gotext v1.4.0 github.com/leonelquinteros/gotext v1.4.0
github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/olekukonko/tablewriter v0.0.1 github.com/olekukonko/tablewriter v0.0.1
github.com/pires/go-proxyproto v0.0.0-20190615163442-2c19fd512994
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/pkg/sftp v1.10.0 github.com/pkg/sftp v1.10.0
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
......
...@@ -66,6 +66,8 @@ github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7 ...@@ -66,6 +66,8 @@ github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/pires/go-proxyproto v0.0.0-20190615163442-2c19fd512994 h1:3ssKn22MN6oLH+l2iimsBdCliSgELXTBWWR+yooB2lQ=
github.com/pires/go-proxyproto v0.0.0-20190615163442-2c19fd512994/go.mod h1:6/gX3+E/IYGa0wMORlSMla999awQFdbaeQCHjSMKIzY=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.0 h1:DGA1KlA9esU6WcicH+P8PxFZOl15O6GYtab1cIJdOlE= github.com/pkg/sftp v1.10.0 h1:DGA1KlA9esU6WcicH+P8PxFZOl15O6GYtab1cIJdOlE=
......
...@@ -95,7 +95,7 @@ func CheckMFA(ctx ssh.Context, challenger gossh.KeyboardInteractiveChallenge) (r ...@@ -95,7 +95,7 @@ func CheckMFA(ctx ssh.Context, challenger gossh.KeyboardInteractiveChallenge) (r
logger.Error("Mfa Auth failed, may be user password or publickey auth failed") logger.Error("Mfa Auth failed, may be user password or publickey auth failed")
return return
} }
resp, err := service.CheckUserOTP(seed, mfaCode) resp, err := service.CheckUserOTP(seed, mfaCode, remoteAddr, "T")
if err != nil { if err != nil {
logger.Error("Mfa Auth failed: ", err) logger.Error("Mfa Auth failed: ", err)
return return
......
...@@ -56,10 +56,12 @@ func GetUserByUsername(username string) (user *model.User, err error) { ...@@ -56,10 +56,12 @@ func GetUserByUsername(username string) (user *model.User, err error) {
return return
} }
func CheckUserOTP(seed, code string) (resp *AuthResp, err error) { func CheckUserOTP(seed, code, remoteAddr, loginType string) (resp *AuthResp, err error) {
data := map[string]string{ data := map[string]string{
"seed": seed, "seed": seed,
"otp_code": code, "otp_code": code,
"remote_addr": remoteAddr,
"login_type": loginType,
} }
_, err = client.Post(UserAuthOTPURL, data, &resp) _, err = client.Post(UserAuthOTPURL, data, &resp)
if err != nil { if err != nil {
......
...@@ -37,6 +37,8 @@ type SSHClient struct { ...@@ -37,6 +37,8 @@ type SSHClient struct {
ref int ref int
key string key string
mu *sync.RWMutex mu *sync.RWMutex
closed chan struct{}
} }
func (s *SSHClient) refCount() int { func (s *SSHClient) refCount() int {
...@@ -67,9 +69,35 @@ func (s *SSHClient) Close() error { ...@@ -67,9 +69,35 @@ func (s *SSHClient) Close() error {
if s.ref > 1 { if s.ref > 1 {
return nil return nil
} }
select {
case <-s.closed:
return nil
default:
close(s.closed)
}
return s.client.Close() return s.client.Close()
} }
func KeepAlive(c *gossh.Client, closed <-chan struct{}, keepInterval time.Duration) {
t := time.NewTicker(keepInterval * time.Second)
defer t.Stop()
logger.Debugf("SSH client %p keep alive start", c)
defer logger.Debugf("SSH client %p keep alive stop", c)
for {
select {
case <-closed:
return
case <-t.C:
_, _, err := c.SendRequest("keepalive@jumpserver.org", true, nil)
if err != nil {
logger.Error("SSH client %p keep alive err: ", c, err.Error())
return
}
}
}
}
type SSHClientConfig struct { type SSHClientConfig struct {
Host string `json:"host"` Host string `json:"host"`
Port string `json:"port"` Port string `json:"port"`
...@@ -207,7 +235,13 @@ func newClient(asset *model.Asset, systemUser *model.SystemUser, timeout time.Du ...@@ -207,7 +235,13 @@ func newClient(asset *model.Asset, systemUser *model.SystemUser, timeout time.Du
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &SSHClient{client: conn, username: systemUser.Username, mu: new(sync.RWMutex)}, err closed := make(chan struct{})
go KeepAlive(conn, closed, 60)
return &SSHClient{
client: conn,
username: systemUser.Username,
mu: new(sync.RWMutex),
closed: closed,}, nil
} }
func NewClient(user *model.User, asset *model.Asset, systemUser *model.SystemUser, timeout time.Duration, func NewClient(user *model.User, asset *model.Asset, systemUser *model.SystemUser, timeout time.Duration,
...@@ -265,11 +299,12 @@ func RecycleClient(client *SSHClient) { ...@@ -265,11 +299,12 @@ func RecycleClient(client *SSHClient) {
clientLock.Unlock() clientLock.Unlock()
err := client.Close() err := client.Close()
if err != nil { if err != nil {
logger.Info("Failed to close client err: ", err.Error()) logger.Error("Failed to close client err: ", err.Error())
}else { } else {
logger.Debug("Success to close client") logger.Debug("Success to close client")
} }
default: default:
client.decreaseRef() client.decreaseRef()
logger.Debugf("Reuse client %p Current ref: %d", client, client.refCount())
} }
} }
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"net" "net"
"github.com/gliderlabs/ssh" "github.com/gliderlabs/ssh"
"github.com/pires/go-proxyproto"
"github.com/jumpserver/koko/pkg/auth" "github.com/jumpserver/koko/pkg/auth"
"github.com/jumpserver/koko/pkg/config" "github.com/jumpserver/koko/pkg/config"
...@@ -36,7 +37,12 @@ func StartServer() { ...@@ -36,7 +37,12 @@ func StartServer() {
} }
// Set sftp handler // Set sftp handler
sshServer.SetSubsystemHandler("sftp", handler.SftpHandler) sshServer.SetSubsystemHandler("sftp", handler.SftpHandler)
logger.Fatal(sshServer.ListenAndServe()) ln, err := net.Listen("tcp", addr)
if err != nil {
logger.Fatal(err)
}
proxyListener := &proxyproto.Listener{Listener: ln}
logger.Fatal(sshServer.Serve(proxyListener))
} }
func StopServer() { func StopServer() {
......
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