#!/usr/bin/env python3 from flask import Flask, send_from_directory, render_template, request, jsonify, redirect, send_file from flask_socketio import SocketIO, Namespace, emit, join_room, leave_room import paramiko import uuid app = Flask(__name__, template_folder='dist') class SSHws(Namespace): def __init__(self, *args, **kwargs): self.clients = dict() super().__init__(*args, **kwargs) def ssh_with_password(self, connection): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("127.0.0.1", 22, "liuzheng", "liuzheng") self.clients[request.sid]["chan"][connection] = ssh.invoke_shell(term='xterm', width=self.clients[request.sid]["cols"], height=self.clients[request.sid]["rows"]) # self.socketio.start_background_task(self.send_data, self.clients[request.sid]["chan"]) # self.chan.settimeout(0.1) self.socketio.start_background_task(self.sent_data, self, self.clients[request.sid]["chan"][connection], self.clients[request.sid]["room"], connection, request.sid) def sent_data(self, s, chan, room, connection, sid): while True: if connection not in s.clients[sid]["chan"].keys(): return try: data = chan.recv(2048).decode('utf-8', 'replace') s.emit(event='data', data={"data": data, "room": connection}, room=room) except RuntimeError: print(room, connection) def send_data(self, s): # Todo: 这里涉及到并发优化 while True: for sid in self.clients: if self.clients[sid]["chan"]: for room, chan in self.clients[sid]["chan"]: try: data = chan.recv(2048).decode('utf-8', 'replace') s.emit(event='data', data={"data": data, "room": room}, room=self.clients[sid]["room"]) except RuntimeError: print(self.clients) def on_connect(self): self.clients[request.sid] = { "cols": int(request.cookies.get('cols', 80)), "rows": int(request.cookies.get('rows', 24)), "room": str(uuid.uuid4()), "chan": dict() } join_room(self.clients[request.sid]["room"]) # self.socketio.start_background_task(self.send_data, self) def on_data(self, message): self.clients[request.sid]["chan"][message["room"]].send(message["data"]) def on_host(self, message): connection = str(uuid.uuid4()) self.emit('room', {'room': connection, 'secret': message['secret']}) self.ssh_with_password(connection) def on_resize(self, message): self.clients[request.sid]["cols"] = message.get('cols', 80) self.clients[request.sid]["rows"] = message.get('rows', 24) for room in self.clients[request.sid]["chan"]: self.clients[request.sid]["chan"][room].resize_pty(width=self.clients[request.sid]["cols"], height=self.clients[request.sid]["rows"], width_pixels=1, height_pixels=1) def on_room(self, sessionid): if sessionid not in self.clients.keys(): self.emit('error', "no such session", room=self.clients[request.sid]["room"]) else: self.emit('room', self.clients[sessionid]["room"], room=self.clients[request.sid]["room"]) def on_join(self, room): self.leave_room(room=self.clients[request.sid]["room"]) join_room(room) def on_token(self, token): self.on_host(token) def on_disconnect(self): print("disconnect") for connection in self.clients[request.sid]["chan"]: self.clients[request.sid]["chan"][connection].close() del self.clients[request.sid]["chan"] pass def on_leave(self): leave_room(self.room) def on_logout(self, connection): print("logout", connection) if connection: self.clients[request.sid]["chan"][connection].close() del self.clients[request.sid]["chan"][connection] @app.route('/luna/') def send_js(path): return send_from_directory('dist', path) @app.route('/') @app.route('/luna/') def index(): return render_template('index.html') @app.route('/api/perms/v1/user/nodes-assets/') def asset_groups_assets(): assets = [ { "id": 0, "name": "ungrouped", "assets": [] }, { "id": 1, "name": "Default long name long name long name", "comment": "Default asset group", "assets_granted": [ { "id": 1, "hostname": "192.168.1.6", "ip": "192.168.2.6", "port": 22, "platform": "Linux", "system_users_granted": [ { "id": 1, "name": "web", "username": "web", "protocol": "ssh", "auth_method": "P", "auto_push": True, "priority": 10 }, { "id": 2, "name": "liuzheng", "username": "liuzheng", "protocol": "ssh", "auth_method": "P", "auto_push": True, "priority": 10 }], }, { "id": 44, "hostname": "192.168.1.6 long name long name long name long name long name", "ip": "192.168.2.6", "port": 22, "platform": "Linux", "system_users_granted": [ { "id": 1, "name": "web", "username": "web", "protocol": "ssh", "auth_method": "P", "auto_push": True, "priority": 1 }, { "id": 2, "name": "liuzheng", "username": "liuzheng", "protocol": "ssh", "auth_method": "P", "auto_push": True, "priority": 10 } ] }, { "id": 4, "hostname": "windows server", "ip": "123.57.183.135", "port": 3389, "platform": "Windows", "system_users_granted": [ { "id": "3", "name": "web", "username": "web", "protocol": "rdp", "auth_method": "P", "auto_push": True, "priority": 10 } ] } ] } ] return jsonify(assets) @app.route('/api/users/v1/profile/') def user_profile(): assets = { "id": "4fc67feb-9efa-4e7b-94b0-b73356a87b2e", "username": "admin", "name": "Administrator", "email": "admin@mycomany.com", "is_active": True, "is_superuser": True, "role": "Administrator", "groups": [ "Default" ], "wechat": "", "phone": 13888888888, "comment": "", "date_expired": "2087-12-16 07:41:35" } return jsonify(assets) @app.route('/api/terminal/v1/sessions/test/replay/') def replay(): return redirect("http://jps.ilz.me/media/2017-12-24/ec87a486-0344-4f12-b27a-620321944f7f.gz") @app.route('/luna/i18n/') def i18n(i18n): return send_file('./i18n/' + i18n) def read_file(filename, charset='utf-8'): with open(filename, 'r') as f: return f.read().decode(charset) if __name__ == '__main__': socketio = SocketIO(app) socketio.on_namespace(SSHws('/ssh')) socketio.run(app)