Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
K
koko
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
koko
Commits
9d0d79f5
Commit
9d0d79f5
authored
May 14, 2019
by
Eric
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/LeeEirc/cocogo
parents
19d3d1be
6607637f
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
332 additions
and
160 deletions
+332
-160
Gopkg.lock
Gopkg.lock
+9
-0
Gopkg.toml
Gopkg.toml
+4
-0
server.go
pkg/auth/server.go
+8
-1
utils.go
pkg/common/utils.go
+35
-1
init.go
pkg/model/init.go
+1
-0
session.go
pkg/model/session.go
+11
-0
parser.go
pkg/proxy/parser.go
+23
-11
recorder.go
pkg/proxy/recorder.go
+111
-81
recorderstorage.go
pkg/proxy/recorderstorage.go
+41
-12
switch.go
pkg/proxy/switch.go
+81
-44
terminal.go
pkg/service/terminal.go
+5
-0
server.go
pkg/sshd/server.go
+3
-10
No files found.
Gopkg.lock
View file @
9d0d79f5
...
@@ -104,6 +104,14 @@
...
@@ -104,6 +104,14 @@
revision = "3ee7d812e62a0804a7d0a324e0249ca2db3476d3"
revision = "3ee7d812e62a0804a7d0a324e0249ca2db3476d3"
version = "v0.0.4"
version = "v0.0.4"
[[projects]]
digest = "1:4a49346ca45376a2bba679ca0e83bec949d780d4e927931317904bad482943ec"
name = "github.com/mattn/go-sqlite3"
packages = ["."]
pruneopts = "UT"
revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75"
version = "v1.10.0"
[[projects]]
[[projects]]
digest = "1:abcdbf03ca6ca13d3697e2186edc1f33863bbdac2b3a44dfa39015e8903f7409"
digest = "1:abcdbf03ca6ca13d3697e2186edc1f33863bbdac2b3a44dfa39015e8903f7409"
name = "github.com/olekukonko/tablewriter"
name = "github.com/olekukonko/tablewriter"
...
@@ -207,6 +215,7 @@
...
@@ -207,6 +215,7 @@
"github.com/jarcoal/httpmock",
"github.com/jarcoal/httpmock",
"github.com/kr/pty",
"github.com/kr/pty",
"github.com/leonelquinteros/gotext",
"github.com/leonelquinteros/gotext",
"github.com/mattn/go-sqlite3",
"github.com/olekukonko/tablewriter",
"github.com/olekukonko/tablewriter",
"github.com/pkg/errors",
"github.com/pkg/errors",
"github.com/pkg/sftp",
"github.com/pkg/sftp",
...
...
Gopkg.toml
View file @
9d0d79f5
...
@@ -74,3 +74,7 @@
...
@@ -74,3 +74,7 @@
[[constraint]]
[[constraint]]
name
=
"gopkg.in/natefinch/lumberjack.v2"
name
=
"gopkg.in/natefinch/lumberjack.v2"
version
=
"2.1.0"
version
=
"2.1.0"
[[constraint]]
name
=
"github.com/mattn/go-sqlite3"
version
=
"1.10.0"
pkg/auth/server.go
View file @
9d0d79f5
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"cocogo/pkg/cctx"
"cocogo/pkg/cctx"
"cocogo/pkg/common"
"cocogo/pkg/common"
"cocogo/pkg/config"
"cocogo/pkg/i18n"
"cocogo/pkg/i18n"
"cocogo/pkg/logger"
"cocogo/pkg/logger"
"cocogo/pkg/service"
"cocogo/pkg/service"
...
@@ -56,10 +57,16 @@ func checkAuth(ctx ssh.Context, password, publicKey string) (res ssh.AuthResult)
...
@@ -56,10 +57,16 @@ func checkAuth(ctx ssh.Context, password, publicKey string) (res ssh.AuthResult)
}
}
func
CheckUserPassword
(
ctx
ssh
.
Context
,
password
string
)
ssh
.
AuthResult
{
func
CheckUserPassword
(
ctx
ssh
.
Context
,
password
string
)
ssh
.
AuthResult
{
if
!
config
.
Conf
.
PasswordAuth
{
return
ssh
.
AuthFailed
}
return
checkAuth
(
ctx
,
password
,
""
)
return
checkAuth
(
ctx
,
password
,
""
)
}
}
func
CheckUserPublicKey
(
ctx
ssh
.
Context
,
key
ssh
.
PublicKey
)
ssh
.
AuthResult
{
func
CheckUserPublicKey
(
ctx
ssh
.
Context
,
key
ssh
.
PublicKey
)
ssh
.
AuthResult
{
if
!
config
.
Conf
.
PublicKeyAuth
{
return
ssh
.
AuthFailed
}
b
:=
key
.
Marshal
()
b
:=
key
.
Marshal
()
publicKey
:=
common
.
Base64Encode
(
string
(
b
))
publicKey
:=
common
.
Base64Encode
(
string
(
b
))
return
checkAuth
(
ctx
,
""
,
publicKey
)
return
checkAuth
(
ctx
,
""
,
publicKey
)
...
@@ -101,6 +108,6 @@ func CheckMFA(ctx ssh.Context, challenger gossh.KeyboardInteractiveChallenge) (r
...
@@ -101,6 +108,6 @@ func CheckMFA(ctx ssh.Context, challenger gossh.KeyboardInteractiveChallenge) (r
return
return
}
}
func
CheckUserNeedMFA
(
ctx
ssh
.
Context
)
(
methods
[]
string
)
{
func
MFAAuthMethods
(
ctx
ssh
.
Context
)
(
methods
[]
string
)
{
return
[]
string
{
"keyboard-interactive"
}
return
[]
string
{
"keyboard-interactive"
}
}
}
pkg/common/utils.go
View file @
9d0d79f5
package
common
package
common
import
"os"
import
(
"compress/gzip"
"io"
"os"
"time"
)
func
FileExists
(
name
string
)
bool
{
func
FileExists
(
name
string
)
bool
{
if
_
,
err
:=
os
.
Stat
(
name
);
err
!=
nil
{
if
_
,
err
:=
os
.
Stat
(
name
);
err
!=
nil
{
...
@@ -10,3 +15,32 @@ func FileExists(name string) bool {
...
@@ -10,3 +15,32 @@ func FileExists(name string) bool {
}
}
return
true
return
true
}
}
func
EnsureDirExist
(
name
string
)
error
{
if
!
FileExists
(
name
)
{
return
os
.
MkdirAll
(
name
,
os
.
ModePerm
)
}
return
nil
}
func
GzipCompressFile
(
srcPath
,
dstPath
string
)
error
{
sf
,
err
:=
os
.
Open
(
srcPath
)
if
err
!=
nil
{
return
err
}
df
,
err
:=
os
.
Create
(
dstPath
)
if
err
!=
nil
{
return
err
}
writer
:=
gzip
.
NewWriter
(
df
)
writer
.
Name
=
dstPath
writer
.
ModTime
=
time
.
Now
()
.
UTC
()
_
,
err
=
io
.
Copy
(
writer
,
sf
)
if
err
!=
nil
{
return
err
}
if
err
:=
writer
.
Close
();
err
!=
nil
{
return
err
}
return
nil
}
pkg/model/init.go
0 → 100644
View file @
9d0d79f5
package
model
pkg/model/session.go
View file @
9d0d79f5
package
model
package
model
type
Command
struct
{
SessionId
string
`json:"session"`
OrgId
string
`json:"org_id"`
Input
string
`json:"input"`
Output
string
`json:"output"`
User
string
`json:"user"`
Server
string
`json:"asset"`
SystemUser
string
`json:"system_user"`
Timestamp
int64
`json:"timestamp"`
}
pkg/proxy/parser.go
View file @
9d0d79f5
...
@@ -2,11 +2,12 @@ package proxy
...
@@ -2,11 +2,12 @@ package proxy
import
(
import
(
"bytes"
"bytes"
"fmt"
"sync"
"cocogo/pkg/logger"
"cocogo/pkg/logger"
"cocogo/pkg/model"
"cocogo/pkg/model"
"cocogo/pkg/utils"
"cocogo/pkg/utils"
"fmt"
"sync"
)
)
var
(
var
(
...
@@ -35,7 +36,7 @@ type Parser struct {
...
@@ -35,7 +36,7 @@ type Parser struct {
srvInputChan
chan
[]
byte
srvInputChan
chan
[]
byte
srvOutputChan
chan
[]
byte
srvOutputChan
chan
[]
byte
cmdCh
chan
*
[
2
]
string
cmdCh
an
chan
[
2
]
string
inputInitial
bool
inputInitial
bool
inputPreState
bool
inputPreState
bool
...
@@ -48,9 +49,9 @@ type Parser struct {
...
@@ -48,9 +49,9 @@ type Parser struct {
output
string
output
string
cmdInputParser
*
CmdParser
cmdInputParser
*
CmdParser
cmdOutputParser
*
CmdParser
cmdOutputParser
*
CmdParser
counter
int
cmdFilterRules
[]
model
.
SystemUserFilterRule
cmdFilterRules
[]
model
.
SystemUserFilterRule
closed
bool
}
}
func
(
p
*
Parser
)
Initial
()
{
func
(
p
*
Parser
)
Initial
()
{
...
@@ -68,22 +69,22 @@ func (p *Parser) Initial() {
...
@@ -68,22 +69,22 @@ func (p *Parser) Initial() {
func
(
p
*
Parser
)
Parse
()
{
func
(
p
*
Parser
)
Parse
()
{
defer
func
()
{
defer
func
()
{
fmt
.
Println
(
"Pars
e done"
)
logger
.
Debug
(
"Parser parse routin
e done"
)
}()
}()
for
{
for
{
select
{
select
{
case
u
b
,
ok
:=
<-
p
.
userInputChan
:
case
b
,
ok
:=
<-
p
.
userInputChan
:
if
!
ok
{
if
!
ok
{
return
return
}
}
b
:=
p
.
ParseUserInput
(
u
b
)
b
=
p
.
ParseUserInput
(
b
)
p
.
userOutputChan
<-
b
p
.
userOutputChan
<-
b
case
s
b
,
ok
:=
<-
p
.
srvInputChan
:
case
b
,
ok
:=
<-
p
.
srvInputChan
:
if
!
ok
{
if
!
ok
{
return
return
}
}
b
:=
p
.
ParseServerOutput
(
s
b
)
b
=
p
.
ParseServerOutput
(
b
)
p
.
srvOutputChan
<-
b
p
.
srvOutputChan
<-
b
}
}
}
}
...
@@ -110,6 +111,7 @@ func (p *Parser) parseInputState(b []byte) []byte {
...
@@ -110,6 +111,7 @@ func (p *Parser) parseInputState(b []byte) []byte {
// 用户又开始输入,并上次不处于输入状态,开始结算上次命令的结果
// 用户又开始输入,并上次不处于输入状态,开始结算上次命令的结果
if
!
p
.
inputPreState
{
if
!
p
.
inputPreState
{
p
.
parseCmdOutput
()
p
.
parseCmdOutput
()
p
.
cmdChan
<-
[
2
]
string
{
p
.
command
,
p
.
output
}
}
}
}
}
return
b
return
b
...
@@ -118,7 +120,6 @@ func (p *Parser) parseInputState(b []byte) []byte {
...
@@ -118,7 +120,6 @@ func (p *Parser) parseInputState(b []byte) []byte {
func
(
p
*
Parser
)
parseCmdInput
()
{
func
(
p
*
Parser
)
parseCmdInput
()
{
data
:=
p
.
cmdBuf
.
Bytes
()
data
:=
p
.
cmdBuf
.
Bytes
()
p
.
command
=
p
.
cmdInputParser
.
Parse
(
data
)
p
.
command
=
p
.
cmdInputParser
.
Parse
(
data
)
fmt
.
Println
(
"parse Command is "
,
p
.
command
)
p
.
cmdBuf
.
Reset
()
p
.
cmdBuf
.
Reset
()
p
.
inputBuf
.
Reset
()
p
.
inputBuf
.
Reset
()
}
}
...
@@ -186,7 +187,6 @@ func (p *Parser) splitCmdStream(b []byte) {
...
@@ -186,7 +187,6 @@ func (p *Parser) splitCmdStream(b []byte) {
if
p
.
zmodemState
!=
""
||
p
.
inVimState
||
!
p
.
inputInitial
{
if
p
.
zmodemState
!=
""
||
p
.
inVimState
||
!
p
.
inputInitial
{
return
return
}
}
fmt
.
Println
(
"Input state: "
,
p
.
inputState
)
if
p
.
inputState
{
if
p
.
inputState
{
p
.
cmdBuf
.
Write
(
b
)
p
.
cmdBuf
.
Write
(
b
)
}
else
{
}
else
{
...
@@ -210,3 +210,15 @@ func (p *Parser) IsCommandForbidden() bool {
...
@@ -210,3 +210,15 @@ func (p *Parser) IsCommandForbidden() bool {
}
}
return
false
return
false
}
}
func
(
p
*
Parser
)
Close
()
{
if
p
.
closed
{
return
}
close
(
p
.
userInputChan
)
close
(
p
.
userOutputChan
)
close
(
p
.
srvInputChan
)
close
(
p
.
srvOutputChan
)
close
(
p
.
cmdChan
)
p
.
closed
=
true
}
pkg/proxy/recorder.go
View file @
9d0d79f5
package
proxy
package
proxy
import
(
import
(
"compress/gzip"
"cocogo/pkg/common"
"context"
"cocogo/pkg/logger"
"encoding/json"
"fmt"
"io"
"os"
"os"
"path/filepath"
"path/filepath"
"strings"
"strings"
"time"
"time"
"cocogo/pkg/config"
"cocogo/pkg/config"
"cocogo/pkg/
logger
"
"cocogo/pkg/
model
"
)
)
var
conf
=
config
.
Conf
type
CommandRecorder
struct
{
type
CommandRecorder
struct
{
Session
*
SwitchSession
Session
*
SwitchSession
storage
CommandStorage
queue
chan
*
model
.
Command
}
}
func
NewCommandRecorder
(
sess
*
SwitchSession
)
(
recorder
*
CommandRecorder
)
{
func
NewCommandRecorder
(
sess
*
SwitchSession
)
(
recorder
*
CommandRecorder
)
{
return
&
CommandRecorder
{
Session
:
sess
}
storage
:=
NewCommandStorage
()
recorder
=
&
CommandRecorder
{
Session
:
sess
,
queue
:
make
(
chan
*
model
.
Command
,
10
),
storage
:
storage
}
go
recorder
.
record
()
return
recorder
}
}
type
Command
struct
{
func
NewReplyRecord
(
sess
*
SwitchSession
)
*
ReplyRecorder
{
SessionId
string
`json:"session"`
storage
:=
NewReplayStorage
()
OrgId
string
`json:"org_id"`
srvStorage
:=
&
ServerReplayStorage
{}
Input
string
`json:"input"`
return
&
ReplyRecorder
{
SessionID
:
sess
.
Id
,
storage
:
storage
,
backOffStorage
:
srvStorage
}
Output
string
`json:"output"`
User
string
`json:"user"`
Server
string
`json:"asset"`
SystemUser
string
`json:"system_user"`
Timestamp
time
.
Time
`json:"timestamp"`
}
}
func
(
c
*
CommandRecorder
)
Record
(
cmd
*
Command
)
{
func
(
c
*
CommandRecorder
)
Record
(
command
[
2
]
string
)
{
data
,
err
:=
json
.
MarshalIndent
(
cmd
,
""
,
" "
)
if
command
[
0
]
==
""
&&
command
[
1
]
==
""
{
if
err
!=
nil
{
return
logger
.
Error
(
"Marshal command error: "
,
err
)
}
}
fmt
.
Printf
(
"Record cmd: %s
\n
"
,
data
)
cmd
:=
&
model
.
Command
{
SessionId
:
c
.
Session
.
Id
,
OrgId
:
c
.
Session
.
Org
,
Input
:
command
[
0
],
Output
:
command
[
1
],
User
:
c
.
Session
.
User
,
Server
:
c
.
Session
.
Server
,
SystemUser
:
c
.
Session
.
SystemUser
,
Timestamp
:
time
.
Now
()
.
Unix
(),
}
c
.
queue
<-
cmd
}
}
var
conf
=
config
.
Conf
func
(
c
*
CommandRecorder
)
Start
()
{
}
func
NewReplyRecord
(
sessionID
string
)
*
ReplyRecorder
{
func
(
c
*
CommandRecorder
)
End
()
{
rootPath
:=
conf
.
RootPath
close
(
c
.
queue
)
currentData
:=
time
.
Now
()
.
UTC
()
.
Format
(
"2006-01-02"
)
}
gzFileName
:=
sessionID
+
".replay.gz"
absFilePath
:=
filepath
.
Join
(
rootPath
,
"data"
,
"replays"
,
currentData
,
sessionID
)
func
(
c
*
CommandRecorder
)
record
()
{
absGzFilePath
:=
filepath
.
Join
(
rootPath
,
"data"
,
"replays"
,
currentData
,
gzFileName
)
cmdList
:=
make
([]
*
model
.
Command
,
0
)
for
{
target
:=
strings
.
Join
([]
string
{
currentData
,
gzFileName
},
"/"
)
select
{
return
&
ReplyRecorder
{
case
p
:=
<-
c
.
queue
:
SessionID
:
sessionID
,
cmdList
=
append
(
cmdList
,
p
)
FileName
:
sessionID
,
if
len
(
cmdList
)
<
5
{
absFilePath
:
absFilePath
,
continue
gzFileName
:
gzFileName
,
}
absGzFilePath
:
absGzFilePath
,
case
<-
time
.
After
(
time
.
Second
*
5
)
:
StartTime
:
time
.
Now
()
.
UTC
(),
if
len
(
cmdList
)
==
0
{
target
:
target
,
continue
}
}
err
:=
c
.
storage
.
BulkSave
(
cmdList
)
if
err
==
nil
{
cmdList
=
cmdList
[
:
0
]
continue
}
if
len
(
cmdList
)
>
10
{
cmdList
=
cmdList
[
1
:
]
}
}
}
}
}
type
ReplyRecorder
struct
{
type
ReplyRecorder
struct
{
SessionID
string
SessionID
string
FileName
string
gzFileName
string
absFilePath
string
absFilePath
string
absGzFilePath
string
absGzFilePath
string
target
string
target
string
WriteF
*
os
.
File
file
*
os
.
File
StartTime
time
.
Time
StartTime
time
.
Time
storage
ReplayStorage
backOffStorage
ReplayStorage
}
}
func
(
r
*
ReplyRecorder
)
Record
(
b
[]
byte
)
{
func
(
r
*
ReplyRecorder
)
Record
(
b
[]
byte
)
{
interval
:=
time
.
Now
()
.
UTC
()
.
Sub
(
r
.
StartTime
)
.
Seconds
()
data
,
_
:=
json
.
Marshal
(
string
(
b
))
_
,
_
=
r
.
WriteF
.
WriteString
(
fmt
.
Sprintf
(
"
\"
%0.6f
\"
:%s,"
,
interval
,
data
))
}
}
func
(
r
*
ReplyRecorder
)
Start
()
{
func
(
r
*
ReplyRecorder
)
Start
()
{
//auth.MakeSureDirExit(r.absFilePath)
rootPath
:=
conf
.
RootPath
//r.WriteF, _ = os.Create(r.absFilePath
)
today
:=
time
.
Now
()
.
UTC
()
.
Format
(
"2006-01-02"
)
//_, _ = r.WriteF.Write([]byte("{"))
gzFileName
:=
r
.
SessionID
+
".replay.gz"
}
replayDir
:=
filepath
.
Join
(
rootPath
,
"data"
,
"replays"
,
today
)
func
(
r
*
ReplyRecorder
)
End
(
ctx
context
.
Context
)
{
r
.
absFilePath
=
filepath
.
Join
(
replayDir
,
r
.
SessionID
)
select
{
r
.
absGzFilePath
=
filepath
.
Join
(
replayDir
,
today
,
gzFileName
)
case
<-
ctx
.
Done
()
:
r
.
target
=
strings
.
Join
([]
string
{
today
,
gzFileName
},
"/"
)
_
,
_
=
r
.
WriteF
.
WriteString
(
`"0":""}`
)
_
=
r
.
WriteF
.
Close
()
}
r
.
uploadReplay
()
}
func
(
r
*
ReplyRecorder
)
uploadReplay
()
{
err
:=
common
.
EnsureDirExist
(
replayDir
)
_
=
GzipCompressFile
(
r
.
absFilePath
,
r
.
absGzFilePath
)
if
err
!=
nil
{
if
store
:=
NewStorageServer
();
store
!=
nil
{
logger
.
Errorf
(
"Create dir %s error: %s
\n
"
,
replayDir
,
err
)
store
.
Upload
(
r
.
absGzFilePath
,
r
.
target
)
return
}
}
_
=
os
.
Remove
(
r
.
absFilePath
)
_
=
os
.
Remove
(
r
.
absGzFilePath
)
}
func
GzipCompressFile
(
srcPath
,
dstPath
string
)
error
{
r
.
file
,
err
=
os
.
Create
(
r
.
absFilePath
)
srcf
,
err
:=
os
.
Open
(
srcPath
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
logger
.
Errorf
(
"Create file %s error: %s
\n
"
,
r
.
absFilePath
,
err
)
}
}
dstf
,
err
:=
os
.
Create
(
dstPath
)
_
,
_
=
r
.
file
.
Write
([]
byte
(
"{"
))
if
err
!=
nil
{
}
return
err
func
(
r
*
ReplyRecorder
)
End
()
{
_
=
r
.
file
.
Close
()
if
!
common
.
FileExists
(
r
.
absFilePath
)
{
return
}
}
zw
:=
gzip
.
NewWriter
(
dstf
)
if
stat
,
err
:=
os
.
Stat
(
r
.
absGzFilePath
);
err
==
nil
&&
stat
.
Size
()
==
0
{
zw
.
Name
=
dstPath
_
=
os
.
Remove
(
r
.
absFilePath
)
zw
.
ModTime
=
time
.
Now
()
.
UTC
()
return
_
,
err
=
io
.
Copy
(
zw
,
srcf
)
if
err
!=
nil
{
return
err
}
}
if
err
:=
zw
.
Close
();
err
!=
nil
{
go
r
.
uploadReplay
()
return
err
if
!
common
.
FileExists
(
r
.
absGzFilePath
)
{
_
=
common
.
GzipCompressFile
(
r
.
absFilePath
,
r
.
absGzFilePath
)
_
=
os
.
Remove
(
r
.
absFilePath
)
}
}
}
return
nil
func
(
r
*
ReplyRecorder
)
uploadReplay
()
{
maxRetry
:=
3
for
i
:=
0
;
i
<=
maxRetry
;
i
++
{
logger
.
Debug
(
"Upload replay file: "
,
r
.
absGzFilePath
)
err
:=
r
.
storage
.
Upload
(
r
.
absGzFilePath
,
r
.
target
)
if
err
==
nil
{
_
=
os
.
Remove
(
r
.
absGzFilePath
)
break
}
// 如果还是失败,使用备用storage再传一次
if
i
==
maxRetry
{
logger
.
Errorf
(
"Using back off storage retry upload"
)
r
.
storage
=
r
.
backOffStorage
r
.
uploadReplay
()
break
}
}
}
}
pkg/proxy/recorderstorage.go
View file @
9d0d79f5
package
proxy
package
proxy
import
(
"cocogo/pkg/config"
"cocogo/pkg/model"
"cocogo/pkg/service"
)
type
ReplayStorage
interface
{
type
ReplayStorage
interface
{
Upload
(
gZipFile
,
target
string
)
Upload
(
gZipFile
,
target
string
)
error
}
type
CommandStorage
interface
{
BulkSave
(
commands
[]
*
model
.
Command
)
error
}
func
NewReplayStorage
()
ReplayStorage
{
cf
:=
config
.
Conf
.
ReplayStorage
tp
,
ok
:=
cf
[
"TYPE"
]
if
!
ok
{
tp
=
"server"
}
switch
tp
{
default
:
return
&
ServerReplayStorage
{}
}
}
func
NewCommandStorage
()
CommandStorage
{
cf
:=
config
.
Conf
.
CommandStorage
tp
,
ok
:=
cf
[
"TYPE"
]
if
!
ok
{
tp
=
"server"
}
switch
tp
{
default
:
return
&
ServerCommandStorage
{}
}
}
}
func
NewStorageServer
()
ReplayStorage
{
type
ServerCommandStorage
struct
{
return
nil
}
}
func
NewJmsStorage
()
ReplayStorage
{
func
(
s
*
ServerCommandStorage
)
BulkSave
(
commands
[]
*
model
.
Command
)
(
err
error
)
{
//appService := auth.GetGlobalService()
return
service
.
PushSessionCommand
(
commands
)
//return &Server{
// StorageType: "jms",
// service: appService,
//}
return
&
Server
{}
}
}
type
Server
struct
{
type
Server
ReplayStorage
struct
{
StorageType
string
StorageType
string
}
}
func
(
s
*
Server
)
Upload
(
gZipFilePath
,
target
string
)
{
func
(
s
*
Server
ReplayStorage
)
Upload
(
gZipFilePath
,
target
string
)
(
err
error
)
{
//sessionID := strings.Split(filepath.Base(gZipFilePath), ".")[0]
//sessionID := strings.Split(filepath.Base(gZipFilePath), ".")[0]
//_ = client.PushSessionReplay(gZipFilePath, sessionID)
//_ = client.PushSessionReplay(gZipFilePath, sessionID)
return
}
}
pkg/proxy/switch.go
View file @
9d0d79f5
package
proxy
package
proxy
import
(
import
(
"cocogo/pkg/model"
"context"
"context"
"time"
"time"
...
@@ -12,14 +11,8 @@ import (
...
@@ -12,14 +11,8 @@ import (
)
)
func
NewSwitchSession
(
userConn
UserConnection
,
serverConn
ServerConnection
)
(
sw
*
SwitchSession
)
{
func
NewSwitchSession
(
userConn
UserConnection
,
serverConn
ServerConnection
)
(
sw
*
SwitchSession
)
{
parser
:=
&
Parser
{
sw
=
&
SwitchSession
{
userConn
:
userConn
,
srvConn
:
serverConn
}
userInputChan
:
make
(
chan
[]
byte
,
1024
),
sw
.
Initial
()
userOutputChan
:
make
(
chan
[]
byte
,
1024
),
srvInputChan
:
make
(
chan
[]
byte
,
1024
),
srvOutputChan
:
make
(
chan
[]
byte
,
1024
),
}
parser
.
Initial
()
sw
=
&
SwitchSession
{
userConn
:
userConn
,
serverConn
:
serverConn
,
parser
:
parser
}
return
sw
return
sw
}
}
...
@@ -37,37 +30,40 @@ type SwitchSession struct {
...
@@ -37,37 +30,40 @@ type SwitchSession struct {
Finished
bool
`json:"is_finished"`
Finished
bool
`json:"is_finished"`
Closed
bool
Closed
bool
srvChan
chan
[]
byte
userChan
chan
[]
byte
cmdFilterRules
[]
model
.
SystemUserFilterRule
cmdRecorder
*
CommandRecorder
cmdRecorder
*
CommandRecorder
replayRecorder
*
Repl
ayStorage
replayRecorder
*
Repl
yRecorder
parser
*
Parser
parser
*
Parser
userConn
UserConnection
cmdRecordChan
chan
[
2
]
string
serverConn
ServerConnection
userConn
UserConnection
userTran
Transport
srvConn
ServerConnection
serverTran
Transport
userChan
Transport
cancelFunc
context
.
CancelFunc
srvChan
Transport
cancelFunc
context
.
CancelFunc
}
}
func
(
s
*
SwitchSession
)
Initial
()
{
func
(
s
*
SwitchSession
)
Initial
()
{
s
.
Id
=
uuid
.
NewV4
()
.
String
()
s
.
Id
=
uuid
.
NewV4
()
.
String
()
s
.
User
=
s
.
userConn
.
User
()
s
.
User
=
s
.
userConn
.
User
()
s
.
Server
=
s
.
s
erver
Conn
.
Name
()
s
.
Server
=
s
.
s
rv
Conn
.
Name
()
s
.
SystemUser
=
s
.
s
erver
Conn
.
User
()
s
.
SystemUser
=
s
.
s
rv
Conn
.
User
()
s
.
LoginFrom
=
s
.
userConn
.
LoginFrom
()
s
.
LoginFrom
=
s
.
userConn
.
LoginFrom
()
s
.
RemoteAddr
=
s
.
userConn
.
RemoteAddr
()
s
.
RemoteAddr
=
s
.
userConn
.
RemoteAddr
()
s
.
DateStart
=
time
.
Now
()
s
.
DateStart
=
time
.
Now
()
}
func
(
s
*
SwitchSession
)
preBridge
()
{
}
s
.
cmdRecordChan
=
make
(
chan
[
2
]
string
,
1024
)
s
.
cmdRecorder
=
NewCommandRecorder
(
s
)
func
(
s
*
SwitchSession
)
postBridge
()
{
s
.
replayRecorder
=
NewReplyRecord
(
s
)
parser
:=
&
Parser
{
userInputChan
:
make
(
chan
[]
byte
,
1024
),
userOutputChan
:
make
(
chan
[]
byte
,
1024
),
srvInputChan
:
make
(
chan
[]
byte
,
1024
),
srvOutputChan
:
make
(
chan
[]
byte
,
1024
),
cmdChan
:
s
.
cmdRecordChan
,
}
parser
.
Initial
()
s
.
parser
=
parser
}
}
func
(
s
*
SwitchSession
)
watchWindowChange
(
ctx
context
.
Context
,
winCh
<-
chan
ssh
.
Window
)
{
func
(
s
*
SwitchSession
)
watchWindowChange
(
ctx
context
.
Context
,
winCh
<-
chan
ssh
.
Window
)
{
...
@@ -82,7 +78,7 @@ func (s *SwitchSession) watchWindowChange(ctx context.Context, winCh <-chan ssh.
...
@@ -82,7 +78,7 @@ func (s *SwitchSession) watchWindowChange(ctx context.Context, winCh <-chan ssh.
if
!
ok
{
if
!
ok
{
return
return
}
}
err
:=
s
.
s
erver
Conn
.
SetWinSize
(
win
.
Height
,
win
.
Width
)
err
:=
s
.
s
rv
Conn
.
SetWinSize
(
win
.
Height
,
win
.
Width
)
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Error
(
"Change server win size err: "
,
err
)
logger
.
Error
(
"Change server win size err: "
,
err
)
return
return
...
@@ -92,63 +88,104 @@ func (s *SwitchSession) watchWindowChange(ctx context.Context, winCh <-chan ssh.
...
@@ -92,63 +88,104 @@ func (s *SwitchSession) watchWindowChange(ctx context.Context, winCh <-chan ssh.
}
}
}
}
func
(
s
*
SwitchSession
)
read
U
serToServer
(
ctx
context
.
Context
)
{
func
(
s
*
SwitchSession
)
read
Par
serToServer
(
ctx
context
.
Context
)
{
defer
func
()
{
defer
func
()
{
logger
.
Debug
(
"Read
u
ser to server end"
)
logger
.
Debug
(
"Read
par
ser to server end"
)
}()
}()
for
{
for
{
select
{
select
{
case
<-
ctx
.
Done
()
:
case
<-
ctx
.
Done
()
:
_
=
s
.
userTran
.
Close
()
return
return
case
p
,
ok
:=
<-
s
.
userTran
.
Chan
()
:
case
p
,
ok
:=
<-
s
.
parser
.
userOutputChan
:
if
!
ok
{
if
!
ok
{
s
.
cancelFunc
()
s
.
cancelFunc
()
}
}
s
.
parser
.
userInputChan
<-
p
_
,
_
=
s
.
srvChan
.
Write
(
p
)
case
p
,
ok
:=
<-
s
.
parser
.
userOutputChan
:
}
}
}
func
(
s
*
SwitchSession
)
readUserToParser
(
ctx
context
.
Context
)
{
defer
func
()
{
logger
.
Debug
(
"Read user to server end"
)
}()
for
{
select
{
case
<-
ctx
.
Done
()
:
_
=
s
.
userChan
.
Close
()
return
case
p
,
ok
:=
<-
s
.
userChan
.
Chan
()
:
if
!
ok
{
if
!
ok
{
s
.
cancelFunc
()
s
.
cancelFunc
()
}
}
_
,
_
=
s
.
serverTran
.
Write
(
p
)
s
.
parser
.
userInputChan
<-
p
}
}
}
}
}
}
func
(
s
*
SwitchSession
)
readServerTo
U
ser
(
ctx
context
.
Context
)
{
func
(
s
*
SwitchSession
)
readServerTo
Par
ser
(
ctx
context
.
Context
)
{
defer
func
()
{
defer
func
()
{
logger
.
Debug
(
"Read server to
u
ser end"
)
logger
.
Debug
(
"Read server to
par
ser end"
)
}()
}()
for
{
for
{
select
{
select
{
case
<-
ctx
.
Done
()
:
case
<-
ctx
.
Done
()
:
_
=
s
.
s
erverTr
an
.
Close
()
_
=
s
.
s
rvCh
an
.
Close
()
return
return
case
p
,
ok
:=
<-
s
.
s
erverTr
an
.
Chan
()
:
case
p
,
ok
:=
<-
s
.
s
rvCh
an
.
Chan
()
:
if
!
ok
{
if
!
ok
{
s
.
cancelFunc
()
s
.
cancelFunc
()
}
}
s
.
parser
.
srvInputChan
<-
p
s
.
parser
.
srvInputChan
<-
p
}
}
}
func
(
s
*
SwitchSession
)
readParserToUser
(
ctx
context
.
Context
)
{
defer
func
()
{
logger
.
Debug
(
"Read parser to user end"
)
}()
for
{
select
{
case
<-
ctx
.
Done
()
:
return
case
p
,
ok
:=
<-
s
.
parser
.
srvOutputChan
:
case
p
,
ok
:=
<-
s
.
parser
.
srvOutputChan
:
if
!
ok
{
if
!
ok
{
s
.
cancelFunc
()
s
.
cancelFunc
()
}
}
_
,
_
=
s
.
userConn
.
Write
(
p
)
s
.
replayRecorder
.
Record
(
p
)
_
,
_
=
s
.
userChan
.
Write
(
p
)
}
}
}
}
}
}
func
(
s
*
SwitchSession
)
recordCmd
()
{
for
cmd
:=
range
s
.
cmdRecordChan
{
s
.
cmdRecorder
.
Record
(
cmd
)
}
}
func
(
s
*
SwitchSession
)
postBridge
()
{
s
.
cmdRecorder
.
End
()
s
.
replayRecorder
.
End
()
s
.
parser
.
Close
()
}
func
(
s
*
SwitchSession
)
Bridge
()
(
err
error
)
{
func
(
s
*
SwitchSession
)
Bridge
()
(
err
error
)
{
winCh
:=
s
.
userConn
.
WinCh
()
winCh
:=
s
.
userConn
.
WinCh
()
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
s
.
cancelFunc
=
cancel
s
.
cancelFunc
=
cancel
s
.
user
Tr
an
=
NewDirectTransport
(
""
,
s
.
userConn
)
s
.
user
Ch
an
=
NewDirectTransport
(
""
,
s
.
userConn
)
s
.
s
erverTran
=
NewDirectTransport
(
""
,
s
.
server
Conn
)
s
.
s
rvChan
=
NewDirectTransport
(
""
,
s
.
srv
Conn
)
go
s
.
parser
.
Parse
()
go
s
.
parser
.
Parse
()
go
s
.
watchWindowChange
(
ctx
,
winCh
)
go
s
.
watchWindowChange
(
ctx
,
winCh
)
go
s
.
readServerToUser
(
ctx
)
go
s
.
readServerToParser
(
ctx
)
s
.
readUserToServer
(
ctx
)
go
s
.
readParserToUser
(
ctx
)
go
s
.
readParserToServer
(
ctx
)
go
s
.
recordCmd
()
defer
s
.
postBridge
()
s
.
readUserToParser
(
ctx
)
logger
.
Debug
(
"Session bridge end"
)
logger
.
Debug
(
"Session bridge end"
)
return
return
}
}
pkg/service/terminal.go
View file @
9d0d79f5
...
@@ -82,3 +82,8 @@ func FinishTask(tid string) bool {
...
@@ -82,3 +82,8 @@ func FinishTask(tid string) bool {
func
PushSessionReplay
(
sessionID
,
gZipFile
string
)
{
func
PushSessionReplay
(
sessionID
,
gZipFile
string
)
{
}
}
func
PushSessionCommand
(
commands
[]
*
model
.
Command
)
(
err
error
)
{
fmt
.
Println
(
"Commands: "
,
commands
)
return
}
pkg/sshd/server.go
View file @
9d0d79f5
...
@@ -25,21 +25,14 @@ func StartServer() {
...
@@ -25,21 +25,14 @@ func StartServer() {
srv
:=
ssh
.
Server
{
srv
:=
ssh
.
Server
{
Addr
:
conf
.
BindHost
+
":"
+
strconv
.
Itoa
(
conf
.
SSHPort
),
Addr
:
conf
.
BindHost
+
":"
+
strconv
.
Itoa
(
conf
.
SSHPort
),
KeyboardInteractiveHandler
:
auth
.
CheckMFA
,
KeyboardInteractiveHandler
:
auth
.
CheckMFA
,
NextAuthMethodsHandler
:
auth
.
CheckUserNeedMFA
,
PasswordHandler
:
auth
.
CheckUserPassword
,
PublicKeyHandler
:
auth
.
CheckUserPublicKey
,
NextAuthMethodsHandler
:
auth
.
MFAAuthMethods
,
HostSigners
:
[]
ssh
.
Signer
{
signer
},
HostSigners
:
[]
ssh
.
Signer
{
signer
},
Handler
:
handler
.
SessionHandler
,
Handler
:
handler
.
SessionHandler
,
SubsystemHandlers
:
map
[
string
]
ssh
.
SubsystemHandler
{},
SubsystemHandlers
:
map
[
string
]
ssh
.
SubsystemHandler
{},
}
}
// Set Auth Handler
// Set Auth Handler
if
conf
.
PasswordAuth
{
srv
.
PasswordHandler
=
auth
.
CheckUserPassword
}
if
conf
.
PublicKeyAuth
{
srv
.
PublicKeyHandler
=
auth
.
CheckUserPublicKey
}
if
!
conf
.
PasswordAuth
&&
!
conf
.
PublicKeyAuth
{
srv
.
PasswordHandler
=
auth
.
CheckUserPassword
}
srv
.
SetSubsystemHandler
(
"sftp"
,
handler
.
SftpHandler
)
srv
.
SetSubsystemHandler
(
"sftp"
,
handler
.
SftpHandler
)
logger
.
Fatal
(
srv
.
ListenAndServe
())
logger
.
Fatal
(
srv
.
ListenAndServe
())
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment