Commit af0cb201 authored by ibuler's avatar ibuler

Fix some bug

parent 74713b64
...@@ -5,22 +5,26 @@ import threading ...@@ -5,22 +5,26 @@ import threading
import logging import logging
import paramiko import paramiko
import time
from .session import Session from .session import Session
from .models import Server from .models import Server
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
TIMEOUT = 8
class ProxyServer: class ProxyServer:
def __init__(self, app, client, request): def __init__(self, app, client):
self.app = app self.app = app
self.request = request
self.client = client self.client = client
self.request = client.request
self.server = None self.server = None
self.connecting = True
def proxy(self, asset, system_user): def proxy(self, asset, system_user):
self.send_connecting_message()
self.server = self.get_server_conn(asset, system_user) self.server = self.get_server_conn(asset, system_user)
if self.server is None: if self.server is None:
return return
...@@ -46,6 +50,7 @@ class ProxyServer: ...@@ -46,6 +50,7 @@ class ProxyServer:
""" """
def get_server_conn(self, asset, system_user): def get_server_conn(self, asset, system_user):
logger.info("Connect to %s" % asset.hostname)
if not self.validate_permission(asset, system_user): if not self.validate_permission(asset, system_user):
self.client.send(b'No permission') self.client.send(b'No permission')
return None return None
...@@ -57,14 +62,18 @@ class ProxyServer: ...@@ -57,14 +62,18 @@ class ProxyServer:
ssh.connect(asset.ip, port=asset.port, ssh.connect(asset.ip, port=asset.port,
username=system_user.username, username=system_user.username,
password=system_user.password, password=system_user.password,
pkey=system_user.private_key) pkey=system_user.private_key,
timeout=TIMEOUT)
except paramiko.AuthenticationException as e: except paramiko.AuthenticationException as e:
self.client.send("Authentication failed: {}".format(e).encode("utf-8")) self.client.send("[Errno 66] Authentication failed: {}".format(e).encode("utf-8"))
return None return None
except socket.error as e: except socket.error as e:
self.client.send("Connection server error: {}".format(e).encode("utf-8")) self.client.send(" {}".format(e).encode("utf-8"))
return None return None
finally:
self.connecting = False
self.client.send(b'\r\n')
term = self.request.meta.get('term', 'xterm') term = self.request.meta.get('term', 'xterm')
width = self.request.meta.get('width', 80) width = self.request.meta.get('width', 80)
...@@ -85,3 +94,15 @@ class ProxyServer: ...@@ -85,3 +94,15 @@ class ProxyServer:
thread.daemon = True thread.daemon = True
thread.start() thread.start()
def send_connecting_message(self):
def func():
delay = 0.0
self.client.send('Connecting to {} {:.1f}'.format('abc.com', delay).encode('utf-8'))
while self.connecting and delay < TIMEOUT:
self.client.send('\x08\x08\x08{:.1f}'.format(delay).encode('utf-8'))
time.sleep(0.1)
delay += 0.1
thread = threading.Thread(target=func)
thread.daemon = True
thread.start()
#!coding: utf-8 #!coding: utf-8
import logging
import socket import socket
import threading import threading
...@@ -9,13 +10,15 @@ from .forward import ProxyServer ...@@ -9,13 +10,15 @@ from .forward import ProxyServer
from .models import Asset, SystemUser from .models import Asset, SystemUser
from .session import Session from .session import Session
logger = logging.getLogger(__file__)
class InteractiveServer: class InteractiveServer:
def __init__(self, app, request, client): def __init__(self, app, client):
self.app = app self.app = app
self.request = request
self.client = client self.client = client
self.request = client.request
def display_banner(self): def display_banner(self):
self.client.send(char.CLEAR_CHAR) self.client.send(char.CLEAR_CHAR)
...@@ -40,8 +43,7 @@ class InteractiveServer: ...@@ -40,8 +43,7 @@ class InteractiveServer:
""" """
# Todo: 实现自动hostname或IP补全 # Todo: 实现自动hostname或IP补全
input_data = [] input_data = []
parser = TtyIOParser(self.request.meta.get("width", 80), parser = TtyIOParser()
self.request.meta.get("height", 24))
self.client.send(wr(prompt, before=1, after=0)) self.client.send(wr(prompt, before=1, after=0))
while True: while True:
data = self.client.recv(10) data = self.client.recv(10)
...@@ -128,10 +130,10 @@ class InteractiveServer: ...@@ -128,10 +130,10 @@ class InteractiveServer:
def search_and_proxy(self, opt, from_result=False): def search_and_proxy(self, opt, from_result=False):
asset = Asset(id=1, hostname="testserver", ip="192.168.244.164", port=22) asset = Asset(id=1, hostname="testserver", ip="192.168.244.164", port=22)
system_user = SystemUser(id=2, username="root", password="redhat", name="web") system_user = SystemUser(id=2, username="root", password="redhat", name="web")
self.connect(asset, system_user) self.proxy(asset, system_user)
def connect(self, asset, system_user): def proxy(self, asset, system_user):
forwarder = ProxyServer(self.app, self.client, self.request) forwarder = ProxyServer(self.app, self.client)
forwarder.proxy(asset, system_user) forwarder.proxy(asset, system_user)
def replay_session(self, session_id): def replay_session(self, session_id):
...@@ -145,7 +147,8 @@ class InteractiveServer: ...@@ -145,7 +147,8 @@ class InteractiveServer:
try: try:
opt = self.get_choice() opt = self.get_choice()
self.dispatch(opt) self.dispatch(opt)
except socket.error: except socket.error as e:
logger.error("Cocket error %s" % e)
break break
self.close() self.close()
......
...@@ -100,7 +100,7 @@ class SSHInterface(paramiko.ServerInterface): ...@@ -100,7 +100,7 @@ class SSHInterface(paramiko.ServerInterface):
return paramiko.OPEN_SUCCEEDED return paramiko.OPEN_SUCCEEDED
def check_channel_shell_request(self, channel): def check_channel_shell_request(self, channel):
logger.info("Check channel shell request: %s" % channel) logger.info("Check channel shell request: %s" % channel.get_id())
self.event.set() self.event.set()
return True return True
......
...@@ -58,11 +58,12 @@ class SystemUser(Decoder): ...@@ -58,11 +58,12 @@ class SystemUser(Decoder):
class Request: class Request:
def __init__(self, remote_ip=""): def __init__(self, addr):
self.type = "" self.type = ""
self.meta = {} self.meta = {}
self.user = None self.user = None
self.remote_ip = remote_ip self.addr = addr
self.remote_ip = self.addr[0]
self.change_size_event = threading.Event() self.change_size_event = threading.Event()
self.date_start = datetime.datetime.now() self.date_start = datetime.datetime.now()
...@@ -74,13 +75,13 @@ class Client: ...@@ -74,13 +75,13 @@ class Client:
``` ```
client = Client(chan, addr, user) client = Client(chan, addr, user)
``` ```
""" """
def __init__(self, chan, addr, user): def __init__(self, chan, request):
self.chan = chan self.chan = chan
self.addr = addr self.request = request
self.user = user self.user = request.user
self.addr = request.addr
def fileno(self): def fileno(self):
return self.chan.fileno() return self.chan.fileno()
...@@ -119,7 +120,6 @@ class Server: ...@@ -119,7 +120,6 @@ class Server:
self.output = '' self.output = ''
self._in_input_state = True self._in_input_state = True
self._input_initial = False self._input_initial = False
self._in_auto_complete_state = False
self._in_vim_state = False self._in_vim_state = False
def fileno(self): def fileno(self):
...@@ -140,11 +140,6 @@ class Server: ...@@ -140,11 +140,6 @@ class Server:
del self.output_data[:] del self.output_data[:]
self._in_input_state = True self._in_input_state = True
# if b == '\t':
# self._in_auto_complete_state = True
# else:
# self._in_auto_complete_state = False
print("Send: %s" % b) print("Send: %s" % b)
return self.chan.send(b) return self.chan.send(b)
......
...@@ -37,7 +37,7 @@ class Session: ...@@ -37,7 +37,7 @@ class Session:
:param silent: If true not send welcome message :param silent: If true not send welcome message
:return: :return:
""" """
logger.info("Session % add watcher %s" % (self, watcher)) logger.info("Session %s add watcher %s" % (self, watcher))
if not silent: if not silent:
watcher.send("Welcome to watch session {}\r\n".format(self.id).encode("utf-8")) watcher.send("Welcome to watch session {}\r\n".format(self.id).encode("utf-8"))
self.sel.register(watcher, selectors.EVENT_READ) self.sel.register(watcher, selectors.EVENT_READ)
...@@ -165,8 +165,7 @@ class Session: ...@@ -165,8 +165,7 @@ class Session:
def close(self): def close(self):
self.running = False self.running = False
for chan in [self.client, self.server] + self.watchers + self.sharers: self.server.close()
chan.close()
def __str__(self): def __str__(self):
return self.id return self.id
......
...@@ -22,18 +22,9 @@ class SSHServer: ...@@ -22,18 +22,9 @@ class SSHServer:
self.stop_event = threading.Event() self.stop_event = threading.Event()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host_key_path = os.path.join(self.app.root_path, 'keys', 'host_rsa_key') self.host_key_path = os.path.join(self.app.root_path, 'keys', 'host_rsa_key')
self.host_key = self.get_host_key()
def listen(self): @property
host = self.app.config["BIND_HOST"] def host_key(self):
port = self.app.config["SSHD_PORT"]
print('Starting ssh server at %(host)s:%(port)s' %
{"host": host, "port": port})
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((host, port))
self.sock.listen(BACKLOG)
def get_host_key(self):
if not os.path.isfile(self.host_key_path): if not os.path.isfile(self.host_key_path):
self.gen_host_key() self.gen_host_key()
return paramiko.RSAKey(filename=self.host_key_path) return paramiko.RSAKey(filename=self.host_key_path)
...@@ -44,7 +35,13 @@ class SSHServer: ...@@ -44,7 +35,13 @@ class SSHServer:
f.write(ssh_key) f.write(ssh_key)
def run(self): def run(self):
self.listen() host = self.app.config["BIND_HOST"]
port = self.app.config["SSHD_PORT"]
print('Starting ssh server at %(host)s:%(port)s' %
{"host": host, "port": port})
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((host, port))
self.sock.listen(BACKLOG)
while not self.stop_event.is_set(): while not self.stop_event.is_set():
try: try:
sock, addr = self.sock.accept() sock, addr = self.sock.accept()
...@@ -63,7 +60,7 @@ class SSHServer: ...@@ -63,7 +60,7 @@ class SSHServer:
logger.warning("Failed load moduli -- gex will be unsupported") logger.warning("Failed load moduli -- gex will be unsupported")
transport.add_server_key(self.host_key) transport.add_server_key(self.host_key)
request = Request() request = Request(addr)
server = SSHInterface(self.app, request) server = SSHInterface(self.app, request)
try: try:
transport.start_server(server=server) transport.start_server(server=server)
...@@ -72,6 +69,7 @@ class SSHServer: ...@@ -72,6 +69,7 @@ class SSHServer:
sys.exit(1) sys.exit(1)
except EOFError: except EOFError:
logger.warning("EOF Error") logger.warning("EOF Error")
sys.exit(1)
chan = transport.accept(10) chan = transport.accept(10)
if chan is None: if chan is None:
...@@ -83,19 +81,20 @@ class SSHServer: ...@@ -83,19 +81,20 @@ class SSHServer:
logger.warning("Client not request a valid request") logger.warning("Client not request a valid request")
sys.exit(2) sys.exit(2)
client = Client(chan, addr, request.user) client = Client(chan, request)
self.app.add_client(client) self.app.add_client(client)
self.dispatch(request, client) self.dispatch(client)
def dispatch(self, request, client): def dispatch(self, client):
if request.type == 'pty': request_type = client.request.type
InteractiveServer(self.app, request, client).activate() if request_type == 'pty':
elif request.type == 'exec': InteractiveServer(self.app, client).activate()
elif request_type == 'exec':
pass pass
elif request.type == 'subsystem': elif request_type == 'subsystem':
pass pass
else: else:
client.send("Not support request type: %s" % request.type) client.send("Not support request type: %s" % request_type)
def shutdown(self): def shutdown(self):
self.stop_event.set() self.stop_event.set()
...@@ -20,8 +20,10 @@ class BaseWehSocketHandler: ...@@ -20,8 +20,10 @@ class BaseWehSocketHandler:
def prepare(self): def prepare(self):
self.app = self.settings["app"] self.app = self.settings["app"]
child, parent = socket.socketpair() child, parent = socket.socketpair()
addr = (self.request.remote_ip, 0) request = Request((self.request.remote_ip, 0))
self.client = Client(parent, addr, self.current_user) request.user = self.current_user
self.request.__dict__.update(request.__dict__)
self.client = Client(parent, self.request)
self.proxy = WSProxy(self, child) self.proxy = WSProxy(self, child)
self.app.clients.append(self.client) self.app.clients.append(self.client)
...@@ -35,9 +37,7 @@ class BaseWehSocketHandler: ...@@ -35,9 +37,7 @@ class BaseWehSocketHandler:
class InteractiveWehSocketHandler(BaseWehSocketHandler, tornado.websocket.WebSocketHandler): class InteractiveWehSocketHandler(BaseWehSocketHandler, tornado.websocket.WebSocketHandler):
@tornado.web.authenticated @tornado.web.authenticated
def open(self): def open(self):
request = Request(self.request.remote_ip) InteractiveServer(self.app, self.client).activate_async()
self.request.__dict__.update(request.__dict__)
InteractiveServer(self.app, self.request, self.client).activate_async()
def on_message(self, message): def on_message(self, message):
try: try:
......
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