Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
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
coco
Commits
9ad2eae8
Commit
9ad2eae8
authored
Oct 22, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加监控记录
parent
ba26608a
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
62 additions
and
16 deletions
+62
-16
app.py
coco/app.py
+1
-0
forward.py
coco/forward.py
+9
-4
models.py
coco/models.py
+2
-2
session.py
coco/session.py
+46
-10
conf_example.py
conf_example.py
+3
-0
manage.py
manage.py
+1
-0
No files found.
coco/app.py
View file @
9ad2eae8
...
...
@@ -29,6 +29,7 @@ class Coco:
'SECRET_KEY'
:
None
,
'LOG_LEVEL'
:
'INFO'
,
'LOG_DIR'
:
os
.
path
.
join
(
BASE_DIR
,
'logs'
),
'SESSION_DIR'
:
os
.
path
.
join
(
BASE_DIR
,
'sessions'
),
'ASSET_SORT_BY'
:
'hostname'
,
# hostname, ip
'SSH_PASSWORD_AUTH'
:
True
,
'SSH_PUBLIC_KEY_AUTH'
:
True
,
...
...
coco/forward.py
View file @
9ad2eae8
...
...
@@ -2,6 +2,7 @@
import
socket
import
threading
import
logging
import
paramiko
...
...
@@ -10,6 +11,9 @@ from .models import Server
from
.exception
import
PermissionFailed
logger
=
logging
.
getLogger
(
__file__
)
class
ProxyServer
:
def
__init__
(
self
,
app
,
client
,
request
):
self
.
app
=
app
...
...
@@ -21,12 +25,13 @@ class ProxyServer:
try
:
self
.
server
=
self
.
get_server_conn
(
asset
,
system_user
)
except
PermissionFailed
:
self
.
client
.
send
(
"No permission"
)
self
.
client
.
send
(
b
"No permission"
)
return
session
=
Session
(
self
.
client
,
self
.
server
)
self
.
app
.
sessions
.
append
(
session
)
self
.
watch_win_size_change_async
()
session
.
record_async
()
session
.
bridge
()
self
.
app
.
sessions
.
remove
(
session
)
...
...
@@ -57,11 +62,11 @@ class ProxyServer:
password
=
system_user
.
password
,
pkey
=
system_user
.
private_key
)
except
paramiko
.
AuthenticationException
as
e
:
self
.
client
.
send
(
"Authentication failed:
%
s"
%
e
)
self
.
client
.
send
(
b
"Authentication failed:
%
s"
%
e
)
return
except
socket
.
error
as
e
:
self
.
client
.
send
(
"Connection server error:
%
s"
%
e
)
self
.
client
.
send
(
b
"Connection server error:
%
s"
%
e
)
return
term
=
self
.
request
.
meta
.
get
(
'term'
,
'xterm'
)
...
...
@@ -75,7 +80,7 @@ class ProxyServer:
self
.
request
.
change_size_event
.
clear
()
width
=
self
.
request
.
meta
.
get
(
'width'
,
80
)
height
=
self
.
request
.
meta
.
get
(
'height'
,
24
)
print
(
"Change win size:
%
s -
%
s"
%
(
width
,
height
))
logger
.
debug
(
"Change win size:
%
s -
%
s"
%
(
width
,
height
))
self
.
server
.
chan
.
resize_pty
(
width
=
width
,
height
=
height
)
def
watch_win_size_change_async
(
self
):
...
...
coco/models.py
View file @
9ad2eae8
...
...
@@ -126,8 +126,8 @@ class Server:
return
getattr
(
self
.
chan
,
item
)
def
__str__
(
self
):
return
"<
%
s@
%
s:
%
s>"
%
\
(
self
.
system_user
.
username
,
self
.
asset
.
hostname
,
self
.
asset
.
port
)
return
"<
%
s@
%
s:
%
s>"
%
(
self
.
system_user
.
username
,
self
.
asset
.
hostname
,
self
.
asset
.
port
)
class
WSProxy
:
...
...
coco/session.py
View file @
9ad2eae8
#!coding: utf-8
import
select
import
os
import
threading
import
uuid
import
socket
import
logging
import
datetime
import
time
import
selectors
...
...
@@ -14,10 +16,11 @@ logger = logging.getLogger(__file__)
class
Session
:
def
__init__
(
self
,
client
,
server
):
def
__init__
(
self
,
client
,
server
,
record_dir
=
"/tmp"
):
self
.
id
=
str
(
uuid
.
uuid4
())
self
.
client
=
client
# Master of the session, it's a client sock
self
.
server
=
server
# Server channel
self
.
record_dir
=
record_dir
# Dir to save session record
self
.
watchers
=
[]
# Only watch session
self
.
sharers
=
[]
# Join to the session, read and write
self
.
running
=
True
...
...
@@ -25,38 +28,43 @@ class Session:
self
.
date_finished
=
None
self
.
sel
=
selectors
.
DefaultSelector
()
def
add_watcher
(
self
,
watcher
):
def
add_watcher
(
self
,
watcher
,
silent
=
False
):
"""
Add a watcher, and will be transport server side msg to it.
:param watcher: A client socket
:param silent: If true not send welcome message
:return:
"""
logger
.
info
(
"Session
%
add watcher
%
s"
%
(
self
,
watcher
))
watcher
.
send
(
"Welcome to join session
%
s
\r\n
"
%
self
.
id
)
if
not
silent
:
watcher
.
send
(
"Welcome to watch session {}
\r\n
"
.
format
(
self
.
id
)
.
encode
(
"utf-8"
))
self
.
sel
.
register
(
watcher
,
selectors
.
EVENT_READ
)
self
.
watchers
.
append
(
watcher
)
def
remove_watcher
(
self
,
watcher
):
logger
.
info
(
"Session
%
s remove watcher
%
s"
%
(
self
,
watcher
))
watcher
.
send
(
"Leave session
%
s at
%
s"
%
(
self
.
id
,
datetime
.
datetime
.
now
()))
self
.
sel
.
unregister
(
watcher
)
self
.
watchers
.
remove
(
watcher
)
def
add_sharer
(
self
,
sharer
):
def
add_sharer
(
self
,
sharer
,
silent
=
False
):
"""
Add a sharer, it can read and write to server
:param sharer: A client socket
:param silent: If true not send welcome message
:return:
"""
logger
.
info
(
"Session
%
s add share
%
s"
%
(
self
.
id
,
sharer
))
sharer
.
send
(
"Welcome to join session
%
s
\r\n
"
%
self
.
id
)
if
not
silent
:
sharer
.
send
(
"Welcome to join session {}
\r\n
"
.
format
(
self
.
id
)
.
encode
(
"utf-8"
))
self
.
sel
.
register
(
sharer
,
selectors
.
EVENT_READ
)
self
.
sharers
.
append
(
sharer
)
def
remove_sharer
(
self
,
sharer
):
logger
.
info
(
"Session
%
s remove sharer
%
s"
%
(
self
.
id
,
sharer
))
sharer
.
send
(
"Leave session
%
s at
%
s"
%
(
self
.
id
,
datetime
.
datetime
.
now
()))
sharer
.
send
(
"Leave session {} at {}"
.
format
(
self
.
id
,
datetime
.
datetime
.
now
())
.
encode
(
"utf-8"
))
self
.
sel
.
unregister
(
sharer
)
self
.
sharers
.
remove
(
sharer
)
...
...
@@ -105,14 +113,42 @@ class Session:
"""
parent
,
child
=
socket
.
socketpair
()
self
.
add_watcher
(
parent
)
with
open
(
os
.
path
.
join
(
self
.
record_dir
,
self
.
id
+
".rec"
),
'wb'
)
as
screenf
,
\
open
(
os
.
path
.
join
(
self
.
record_dir
,
self
.
id
+
".time"
),
"w"
)
as
timef
:
screenf
.
write
(
"Script started on {}
\n
"
.
format
(
time
.
asctime
())
.
encode
(
"utf-8"
))
while
self
.
running
:
start_t
=
time
.
time
()
data
=
child
.
recv
(
BUF_SIZE
)
end_t
=
time
.
time
()
size
=
len
(
data
)
if
size
==
0
:
break
timef
.
write
(
"
%.4
f
%
s
\n
"
%
(
end_t
-
start_t
,
size
))
screenf
.
write
(
data
)
print
(
"Pass
%.4
f, print
%
d"
%
(
end_t
-
start_t
,
size
))
print
(
"Data: {}"
.
format
(
data
.
decode
(
'utf-8'
)))
screenf
.
write
(
"Script done on {}
\n
"
.
format
(
time
.
asctime
())
.
encode
(
"utf-8"
))
def
record_async
(
self
):
thread
=
threading
.
Thread
(
target
=
self
.
record
)
thread
.
daemon
=
True
thread
.
start
()
def
replay
(
self
):
"""
Replay the session
:return:
"""
pass
def
replay_down
(
self
):
pass
def
close
(
self
):
self
.
running
=
False
self
.
server
.
close
()
return
for
chan
in
[
self
.
client
,
self
.
server
]
+
self
.
watchers
+
self
.
sharers
:
chan
.
close
()
def
__str__
(
self
):
return
self
.
id
...
...
conf_example.py
View file @
9ad2eae8
...
...
@@ -36,6 +36,9 @@ APP_NAME = "coco"
# 日志存放的目录
# LOG_DIR = os.path.join(BASE_DIR, 'logs')
# Session录像存放目录
# SESSION_DIR = os.path.join(BASE_DIR, 'sessions')
# 资产显示排序方式, ['ip', 'hostname']
# ASSET_LIST_SORT_BY = 'ip'
...
...
manage.py
View file @
9ad2eae8
...
...
@@ -15,6 +15,7 @@ except ImportError:
try
:
os
.
mkdir
(
"logs"
)
os
.
mkdir
(
"keys"
)
os
.
mkdir
(
"sessions"
)
except
:
pass
...
...
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