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
7 years ago
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加监控记录
parent
ba26608a
Hide 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
,
...
...
This diff is collapsed.
Click to expand it.
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
):
...
...
This diff is collapsed.
Click to expand it.
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
:
...
...
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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'
...
...
This diff is collapsed.
Click to expand it.
manage.py
View file @
9ad2eae8
...
...
@@ -15,6 +15,7 @@ except ImportError:
try
:
os
.
mkdir
(
"logs"
)
os
.
mkdir
(
"keys"
)
os
.
mkdir
(
"sessions"
)
except
:
pass
...
...
This diff is collapsed.
Click to expand it.
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