Commit 9ad2eae8 authored by ibuler's avatar ibuler

添加监控记录

parent ba26608a
......@@ -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,
......
......@@ -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):
......
......@@ -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:
......
#!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("%.4f %s\n" % (end_t-start_t, size))
screenf.write(data)
print("Pass %.4f, 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
......
......@@ -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'
......
......@@ -15,6 +15,7 @@ except ImportError:
try:
os.mkdir("logs")
os.mkdir("keys")
os.mkdir("sessions")
except:
pass
......
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