Commit ecf43f40 authored by ibuler's avatar ibuler

添加 ssh server interface

parent e1c4dc5e
...@@ -4,7 +4,7 @@ import threading ...@@ -4,7 +4,7 @@ import threading
from .config import Config from .config import Config
from .sshd import SSHServer from .sshd import SSHServer
from .logger import create_logger from .logging import create_logger
__version__ = '0.4.0' __version__ = '0.4.0'
...@@ -55,8 +55,8 @@ class Coco: ...@@ -55,8 +55,8 @@ class Coco:
def run_forever(self): def run_forever(self):
print(time.ctime()) print(time.ctime())
print('Coco version %s, more see https://www.jumpserver.org' % __version__) print('Coco version %s, more see https://www.jumpserver.org' % __version__)
print('Starting ssh server at %(host)s:%(port)s' % {
'host': self.config['BIND_HOST'], 'port': self.config['SSHD_PORT']}) # Todo: move to websocket server
print('Starting websocket server at %(host)s:%(port)s' % { print('Starting websocket server at %(host)s:%(port)s' % {
'host': self.config['BIND_HOST'], 'port': self.config['WS_PORT']}) 'host': self.config['BIND_HOST'], 'port': self.config['WS_PORT']})
print('Quit the server with CONTROL-C.') print('Quit the server with CONTROL-C.')
...@@ -68,7 +68,7 @@ class Coco: ...@@ -68,7 +68,7 @@ class Coco:
self.shutdown() self.shutdown()
def run_sshd(self): def run_sshd(self):
thread = threading.Thread(target=SSHServer.run, args=(self,)) thread = threading.Thread(target=SSHServer(self).run, args=())
def run_ws(self): def run_ws(self):
pass pass
......
#!coding: utf-8
import logging
import paramiko
logger = logging.getLogger(__file__)
class SSHInterface(paramiko.ServerInterface):
"""
使用paramiko提供的接口实现ssh server.
More see paramiko ssh server demo
https://github.com/paramiko/paramiko/blob/master/demos/demo_server.py
"""
def __init__(self, app, *args, *kwargs):
self.app = app
def check_auth_interactive(self, username, submethods):
"""
:param username: the username of the authenticating client
:param submethods: a comma-separated list of methods preferred
by the client (usually empty)
:return: AUTH_FAILED if this auth method isn’t supported;
otherwise an object containing queries for the user
"""
logger.info("Check auth interactive: %s %s" % (username, submethods))
return paramiko.AUTH_FAILED
def check_auth_interactive_response(self, responses):
logger.info("Check auth interactive response: %s " % responses)
pass
def enable_auth_gssapi(self):
return False
def get_allowed_auths(self, username):
# Todo: Check with server settings or self config
return ",".join(["password", "publickkey"])
def check_auth_none(self, username):
return paramiko.AUTH_FAILED
def check_auth_password(self, username, password):
return self.validate_auth(username, password=password)
def check_auth_publickey(self, username, key):
return self.validate_auth(username, key=key)
def validate_auth(self, username, password="", key=""):
# Todo: Implement it
return True
def check_channel_direct_tcpip_request(self, chanid, origin, destination):
logger.info("Check channel direct tcpip request: %d %s %s" %
(chanid, origin, destination))
return 0
def check_channel_env_request(self, channel, name, value):
logger.info("Check channel env request: %s, %s, %s" %
(channel, name, value))
return False
def check_channel_exec_request(self, channel, command):
logger.info("Check channel exec request: %s `%s`" %
(channel, command))
return False
def check_channel_forward_agent_request(self, channel):
logger.info("Check channel forward agent request: %s" % channel)
return False
def check_channel_pty_request(
self, channel, term, width, height,
pixelwidth, pixelheight, modes):
logger.info("Check channel pty request: %s %s %s %s %s %s %s" %
(channel, term, width, height, pixelwidth,pixelheight, modes))
return True
def check_channel_request(self, kind, chanid):
logger.info("Check channel request: %s %d" % (kind, chanid))
return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel):
logger.info("Check channel shell request: %s" % channel)
return True
def check_channel_subsystem_request(self, channel, name):
logger.info("Check channel subsystem request: %s %s" % (channel, name))
return False
def check_channel_window_change_request(
self, channel, width, height, pixelwidth, pixelheight):
# Todo: implement window size change
return True
def check_channel_x11_request(
self, channel, single_connection, auth_protocol, auth_cookie,
screen_number):
logger.info("Check channel x11 request %s %s %s %s %s" %
(channel, single_connection, auth_protocol,
auth_cookie, screen_number))
return False
def check_port_forward_request(self, address, port):
logger.info("Check channel subsystem request: %s %s" % (address, port))
return False
def get_banner(self):
return None, None
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
import select import select
import uuid import uuid
import socket import socket
import logging
import datetime
BUF_SIZE = 1024 BUF_SIZE = 1024
logger = logging.getLogger(__file__)
logger =
class Session: class Session:
...@@ -17,6 +19,8 @@ class Session: ...@@ -17,6 +19,8 @@ class Session:
self.watchers = [] # Only watch session self.watchers = [] # Only watch session
self.sharers = [] # Join to the session, read and write self.sharers = [] # Join to the session, read and write
self.running = True self.running = True
self.date_created = datetime.datetime.now()
self.date_finished = None
def add_watcher(self, watcher): def add_watcher(self, watcher):
""" """
...@@ -25,6 +29,7 @@ class Session: ...@@ -25,6 +29,7 @@ class Session:
:param watcher: A client socket :param watcher: A client socket
:return: :return:
""" """
logger.info("Session % add watcher %s" % (self, watcher))
self.watchers.append(watcher) self.watchers.append(watcher)
def add_sharer(self, sharer): def add_sharer(self, sharer):
...@@ -33,6 +38,7 @@ class Session: ...@@ -33,6 +38,7 @@ class Session:
:param sharer: A client socket :param sharer: A client socket
:return: :return:
""" """
logger.info("Session % add share %s" % (self, sharer))
self.sharers.append(sharer) self.sharers.append(sharer)
def bridge(self): def bridge(self):
...@@ -76,13 +82,21 @@ class Session: ...@@ -76,13 +82,21 @@ class Session:
self.server.resize_pty(width=width, height=height) self.server.resize_pty(width=width, height=height)
def record(self): def record(self):
"""
Record the session to a file. Using it replay in the future
:return:
"""
parent, child = socket.socketpair() parent, child = socket.socketpair()
self.add_watcher(parent) self.add_watcher(parent)
def replay(self):
pass
def close(self): def close(self):
pass pass
def __str__(self):
return self.id
......
#! coding: utf-8 #! coding: utf-8
import logging
import socket
logger = logging.getLogger(__file__)
BACKLOG = 5
class SSHServer: class SSHServer:
def __init__(self, app=None): def __init__(self, app=None):
self.app = app self.app = app
@classmethod def run(self):
def run(cls, app): host = self.app.config["BIND_HOST"]
self = cls(app) port = self.app.config["SSHD_PORT"]
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(BACKLOG)
print('Starting ssh server at %(host)s:%(port)s' %
{"host": host, "port": port})
def shutdown(self): def shutdown(self):
pass 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