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 {
}
.elfinder-cwd-file.ui-selected {
background: #455158;
color: #555;
/*color: #555;*/
color: #ddd;
width: 120px !important;
}
.elfinder-cwd-filename input,
......@@ -1309,10 +1310,10 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical {
padding: 0;
}
.elfinder-cwd table tr:nth-child(odd) {
background-color: transparent;
/*background-color: transparent;*/
}
.elfinder-cwd table tr:nth-child(odd).ui-state-hover {
background-color: #4c5961;
/*background-color: #4c5961;*/
}
#elfinder-elfinder-cwd-thead td {
background: #353b42;
......
......@@ -24,6 +24,7 @@ require (
github.com/leonelquinteros/gotext v1.4.0
github.com/mattn/go-runewidth v0.0.4 // indirect
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/sftp v1.10.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
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/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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.0 h1:DGA1KlA9esU6WcicH+P8PxFZOl15O6GYtab1cIJdOlE=
......
......@@ -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")
return
}
resp, err := service.CheckUserOTP(seed, mfaCode)
resp, err := service.CheckUserOTP(seed, mfaCode, remoteAddr, "T")
if err != nil {
logger.Error("Mfa Auth failed: ", err)
return
......
......@@ -56,10 +56,12 @@ func GetUserByUsername(username string) (user *model.User, err error) {
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{
"seed": seed,
"otp_code": code,
"seed": seed,
"otp_code": code,
"remote_addr": remoteAddr,
"login_type": loginType,
}
_, err = client.Post(UserAuthOTPURL, data, &resp)
if err != nil {
......
......@@ -37,6 +37,8 @@ type SSHClient struct {
ref int
key string
mu *sync.RWMutex
closed chan struct{}
}
func (s *SSHClient) refCount() int {
......@@ -67,9 +69,35 @@ func (s *SSHClient) Close() error {
if s.ref > 1 {
return nil
}
select {
case <-s.closed:
return nil
default:
close(s.closed)
}
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 {
Host string `json:"host"`
Port string `json:"port"`
......@@ -207,7 +235,13 @@ func newClient(asset *model.Asset, systemUser *model.SystemUser, timeout time.Du
if err != nil {
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,
......@@ -265,11 +299,12 @@ func RecycleClient(client *SSHClient) {
clientLock.Unlock()
err := client.Close()
if err != nil {
logger.Info("Failed to close client err: ", err.Error())
}else {
logger.Error("Failed to close client err: ", err.Error())
} else {
logger.Debug("Success to close client")
}
default:
client.decreaseRef()
logger.Debugf("Reuse client %p Current ref: %d", client, client.refCount())
}
}
......@@ -4,6 +4,7 @@ import (
"net"
"github.com/gliderlabs/ssh"
"github.com/pires/go-proxyproto"
"github.com/jumpserver/koko/pkg/auth"
"github.com/jumpserver/koko/pkg/config"
......@@ -36,7 +37,12 @@ func StartServer() {
}
// Set sftp handler
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() {
......
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