class AdminGuacamole(WebsocketConsumer): def __init__(self, *args, **kwargs): super(AdminGuacamole, self).__init__(*args, **kwargs) self.client = GuacamoleClient(settings.GUACD_HOST, settings.GUACD_PORT) self.group_name = self.scope['url_route']['kwargs']['group_name'] self.fort_server = ServerAssets.objects.select_related('assets').get( id=self.scope['path'].split('/')[3]) self.guacamole_thread = GuacamoleThread(self) def connect(self): self.accept('guacamole') self.client.handshake( protocol='rdp', hostname=self.fort_server.assets.asset_management_ip, port=self.fort_server.port, password=CryptPwd().decrypt_pwd(self.fort_server.password), username=self.fort_server.username) self.send('0.,{0}.{1};'.format(len(self.group_name), self.group_name)) self.guacamole_thread.setDaemon(True) self.guacamole_thread.start() def disconnect(self, event): self.guacamole_thread.stop() def receive(self, text_data=None, bytes_data=None): with self.guacamole_thread.write_lock: self.client.send(text_data)
class MainNamespace(Namespace): def __init__(self, namespace): super(MainNamespace, self).__init__(namespace) self.remote_ip = None self.remote_protocol = None self.remote_port = None self.username = None self.width = None self.height = None self.password = None self.client = None self.connect_status = False def on_connect(self): current_app.logger.debug('Socket connected.') self.client = GuacamoleClient(GUACD_PATH, GUACD_PORT) def on_disconnect(self): self.client.close() def on_remote(self, data): self.remote_ip = data.get('ip') self.remote_protocol = data.get('protocol') self.remote_port = data.get('port') self.width = data.get('width') self.height = data.get('height') self.username = data.get('username') self.password = data.get('password') if self.username and self.password: self.client.handshake(protocol=self.remote_protocol, hostname=self.remote_ip, port=self.remote_port, width=self.width, height=self.height, username=self.username, password=self.password) else: self.client.handshake(protocol=self.remote_protocol, hostname=self.remote_ip, port=self.remote_port, width=self.width, height=self.height) self.connect_status = True # emit('connect_status', {'status': self.connect_status}, Namespace='/data') while True: instruction = self.client.receive() if instruction: if 'disconnect' in instruction: emit('message', instruction, namespace='/data') self.client.close() # emit('connect_status', {'status': False}, Namespace='/data') break emit('message', instruction, namespace='/data') def on_message(self, message): if self.connect_status: self.client.send(message)
class GuacamoleConsumer(WebsocketConsumer): def __init__(self, *args, **kwargs): super(GuacamoleConsumer, self).__init__(*args, **kwargs) self.client = GuacamoleClient(settings.GUACD_HOST, settings.GUACD_PORT, timeout=5) self.group_name = self.scope['url_route']['kwargs']['group_name'] self.fort_server = ServerAssets.objects.select_related('assets').get( id=self.scope['path'].split('/')[3]) self.fort_user = FortServerUser.objects.get( id=self.scope['path'].split('/')[4]) self.guacamole_thread = GuacamoleThread(self) self.query_list = self.scope['query_string'].decode('utf8').split(',') self.remote_ip = self.query_list[0].strip() self.width = self.query_list[1].strip() self.height = self.query_list[2].strip() self.dpi = self.query_list[3].strip() self.fort = None def connect(self): self.accept('guacamole') host_ip = self.fort_server.assets.asset_management_ip username = self.fort_user.fort_username self.fort = r'{}@{}'.format(username, host_ip) server_protocol = self.fort_user.fort_server.server_protocol if server_protocol == 'vnc': self.client.handshake(protocol=server_protocol, hostname=host_ip, port=self.fort_user.fort_vnc_port, password=self.fort_user.fort_password, width=self.width, height=self.height, dpi=self.dpi) elif server_protocol == 'rdp': self.client.handshake(protocol=server_protocol, hostname=host_ip, port=self.fort_server.port, password=self.fort_user.fort_password, username=username, width=self.width, height=self.height, dpi=self.dpi) self.send('0.,{0}.{1};'.format(len(self.group_name), self.group_name)) self.guacamole_thread.setDaemon(True) self.guacamole_thread.start() def disconnect(self, event): try: self.guacamole_thread.record() finally: self.guacamole_thread.stop() self.client.close() def receive(self, text_data=None, bytes_data=None): with self.guacamole_thread.write_lock: self.client.send(text_data)
class MyGuacamole(WebsocketConsumer): def __init__(self, *args, **kwargs): super(MyGuacamole, self).__init__(*args, **kwargs) self.client = GuacamoleClient(settings.GUACD_HOST, settings.GUACD_PORT, timeout=5) self.group_name = self.scope['url_route']['kwargs']['group_name'] self.guacamole_thread = GuacamoleThread(self) self.query_list = self.scope['query_string'].decode('utf8').split(',') self.remote_ip = self.query_list[0].strip() self.width = self.query_list[1].strip() self.height = self.query_list[2].strip() self.dpi = self.query_list[3].strip() self.ip = None self.port = None self.username = None self.password = None self.record_dir = 'admin_guacamole_records' if self.scope[ 'user'].is_superuser else 'fort_guacamole_records' def connect(self): if self.scope["user"].is_anonymous: self.close(code=1007) else: self.accept('guacamole') self.client.handshake(protocol='rdp', hostname=self.ip, port=self.port, password=self.password, username=self.username, width=self.width, height=self.height, dpi=self.dpi) self.send('0.,{0}.{1};'.format(len(self.group_name), self.group_name)) self.guacamole_thread.setDaemon(True) self.guacamole_thread.start() def disconnect(self, event): try: self.guacamole_thread.record() finally: self.guacamole_thread.stop() self.client.close() def receive(self, text_data=None, bytes_data=None): with self.guacamole_thread.write_lock: self.client.send(text_data)
class GuacamoleApp(WebSocketApplication): def __init__(self, ws): self.client = None self._listener = None super(GuacamoleApp, self).__init__(ws) @classmethod def protocol_name(cls): """ Return our protocol. """ return PROTOCOL_NAME def on_open(self, *args, **kwargs): """ New Web socket connection opened. """ if self.client: # we have a running client?! self.client.close() # @TODO: get guacd host and port! self.client = GuacamoleClient('localhost', 4822) # @TODO: get Remote server connection properties self.client.handshake(protocol=PROTOCOL, hostname=HOST, port=PORT, username=USERNAME, password=PASSWORD, domain=DOMAIN, security=SEC, remote_app=APP) self._start_listener() def on_message(self, message): """ New message received on the websocket. """ # send message to guacd server self.client.send(message) def on_close(self, reason): """ Websocket closed. """ # @todo: consider reconnect from client. (network glitch?!) self._stop_listener() self.client.close() self.client = None def _start_listener(self): if self._listener: self._stop_listener() self._listener = gevent.spawn(self.guacd_listener) self._listener.start() def _stop_listener(self): if self._listener: self._listener.kill() self._listener = None def guacd_listener(self): """ A listener that would handle any messages sent from Guacamole server and push directly to browser client (over websocket). """ while True: instruction = self.client.receive() self.ws.send(instruction)
class Client: def __init__(self, websocker): self.websocker = websocker self.start_time = time.time() self.last_save_time = self.start_time tmp_date1 = time.strftime("%Y-%m-%d", time.localtime(int(self.start_time))) tmp_date2 = time.strftime("%Y%m%d%H%M%S", time.localtime(int(self.start_time))) if not os.path.isdir(os.path.join(settings.RECORD_ROOT, tmp_date1)): os.makedirs(os.path.join(settings.RECORD_ROOT, tmp_date1)) self.res_file = settings.RECORD_DIR + '/' + tmp_date1 + '/' + 'webguacamole_' + \ tmp_date2 + '_' + gen_rand_char(16) + '.txt' self.res = [] self.guacamoleclient = None def connect(self, protocol, hostname, port, username, password, width, height, dpi): try: self.guacamoleclient = GuacamoleClient( settings.GUACD.get('host'), settings.GUACD.get('port'), settings.GUACD.get('timeout'), ) if protocol == 'vnc': # vnc 登陆不需要账号 self.guacamoleclient.handshake( protocol=protocol, hostname=hostname, port=port, password=password, width=width, height=height, dpi=dpi, ) elif protocol == 'rdp': self.guacamoleclient.handshake( protocol=protocol, hostname=hostname, port=port, username=username, password=password, width=width, height=height, dpi=dpi, ) Thread(target=self.websocket_to_django).start() except Exception: self.websocker.close(3001) def django_to_guacd(self, data): try: self.guacamoleclient.send(data) except Exception: self.close() def websocket_to_django(self): try: while True: time.sleep(0.0001) data = self.guacamoleclient.receive() if not data: return if self.websocker.send_flag == 0: self.websocker.send(data) elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": data, }) self.res.append(data) # 指定条结果或者指定秒数就保存一次 if len(self.res) > 2000 or int(time.time() - self.last_save_time) > 60 or \ sys.getsizeof(self.res) > 2097152: tmp = list(self.res) self.res = [] self.last_save_time = time.time() res(self.res_file, tmp, False) except Exception: print(traceback.format_exc()) if self.websocker.send_flag == 0: self.websocker.send('0.;') elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": '0.;', }) finally: self.close() def close(self): self.websocker.close() self.guacamoleclient.close() def shell(self, data): self.django_to_guacd(data)
class GuacamoleWebSocketConsumer(AsyncWebsocketConsumer): client = None task = None read_only = False async def connect(self): """ Initiate the GuacamoleClient and create a connection to it. """ guacd_hostname = os.getenv('GUACD_SERVICE_HOST', 'guacd') guacd_port = int(os.getenv('GUACD_SERVICE_PORT', '4822')) settings = get_xblock_settings() params = urllib.parse.parse_qs(self.scope['query_string'].decode()) stack_name = params.get('stack')[0] stack = await database_sync_to_async(self.get_stack)(stack_name) default_port = 3389 if stack.protocol == 'rdp' else 22 self.read_only = bool(strtobool(params.get('read_only')[0])) self.client = GuacamoleClient(guacd_hostname, guacd_port) self.client.handshake( protocol=stack.protocol, width=params.get('width', [1024])[0], height=params.get('height', [768])[0], hostname=stack.ip, port=params.get('port', [default_port])[0], username=stack.user, password=stack.password, private_key=stack.key, color_scheme=settings.get("terminal_color_scheme"), font_name=settings.get("terminal_font_name"), font_size=settings.get("terminal_font_size"), ) if self.client.connected: # start receiving data from GuacamoleClient loop = asyncio.get_event_loop() self.task = loop.create_task(self.open()) # Accept connection await self.accept(subprotocol='guacamole') else: await self.close() def get_stack(self, stack_name): return Stack.objects.get(name=stack_name) async def disconnect(self, code): """ Close the GuacamoleClient connection on WebSocket disconnect. """ self.task.cancel() await sync_to_async(self.client.close)() async def receive(self, text_data=None, bytes_data=None): """ Handle data received in the WebSocket, send to GuacamoleClient. """ if text_data is not None: # ignore all 'key' and 'mouse' events when set to 'read_only" mode if self.read_only and ('key' in text_data or 'mouse' in text_data): pass else: self.client.send(text_data) async def open(self): """ Receive data from GuacamoleClient and pass it to the WebSocket """ while True: content = await sync_to_async(self.client.receive)() if content: await self.send(text_data=content)
class Client: def __init__(self, websocker): self.websocker = websocker self.start_time = time.time() self.last_save_time = self.start_time tmp_date1 = time.strftime("%Y-%m-%d", time.localtime(int(self.start_time))) tmp_date2 = time.strftime("%Y%m%d%H%M%S", time.localtime(int(self.start_time))) if not os.path.isdir(os.path.join(settings.RECORD_ROOT, tmp_date1)): os.makedirs(os.path.join(settings.RECORD_ROOT, tmp_date1)) self.res_file = settings.RECORD_DIR + '/' + tmp_date1 + '/' + 'webguacamole_' + \ tmp_date2 + '_' + gen_rand_char(16) + '.txt' self.res = [] self.guacamoleclient = None self.file_index = {} self.file_cmd = '' def connect(self, protocol, hostname, port, username, password, width, height, dpi, **kwargs): try: self.guacamoleclient = GuacamoleClient( settings.GUACD.get('host'), settings.GUACD.get('port'), settings.GUACD.get('timeout'), ) if protocol == 'vnc': # vnc 登陆不需要账号 self.guacamoleclient.handshake( protocol=protocol, hostname=hostname, port=port, password=password, width=width, height=height, dpi=dpi, ignore_cert="true", disable_audio="true", client_name="devops", **kwargs, ) elif protocol == 'rdp': self.guacamoleclient.handshake( protocol=protocol, port=port, username=username, password=password, hostname=hostname, width=width, height=height, dpi=dpi, security='tls', # rdp,nla,tls,any ignore_cert="true", disable_audio="true", client_name="devops", **kwargs, ) Thread(target=self.websocket_to_django).start() except Exception: logger.error(traceback.format_exc()) self.websocker.close(3001) def django_to_guacd(self, data): try: self.guacamoleclient.send(data) except Exception: self.close() def websocket_to_django(self): try: while 1: # time.sleep(0.00001) data = self.guacamoleclient.receive() if not data: message = str( base64.b64encode('连接被断开或者协议不支持'.encode('utf-8')), 'utf-8') self.websocker.send('6.toastr,1.2,{0}.{1};'.format( len(message), message)) break save_res = True if data.startswith("4.file,"): tmp = data.split(",") file_index = tmp[1].split(".")[1] file_type = tmp[2].split(".")[1] file_name_tmp = tmp[3].rstrip(";").split(".") del file_name_tmp[0] file_name = '.'.join(file_name_tmp) self.file_index[file_index] = [file_name, file_type] message = str( base64.b64encode( '开始下载文件 - {}'.format(file_name).encode('utf-8')), 'utf-8') self.websocker.send('6.toastr,1.3,{0}.{1};'.format( len(message), message)) save_res = False if self.file_index: if data.startswith("4.blob,"): tmp = data.split(",") index = tmp[1].split(".")[1] if index in self.file_index: # lenx = tmp[2].split(".")[0] # logger.info("file: {} len: {}".format(self.file_index[index][0], lenx)) save_res = False if data.startswith("3.end,"): tmp = data.split(",") index = tmp[1].rstrip(";").split(".")[1] if index in self.file_index: cmd_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(int(time.time()))) self.file_cmd += cmd_time + "\t" + '下载文件 - {}'.format( self.file_index[index][0]) + '\n' message = str( base64.b64encode('文件下载完成 - {}'.format( self.file_index[index][0]).encode( 'utf-8')), 'utf-8') self.websocker.send('6.toastr,1.3,{0}.{1};'.format( len(message), message)) save_res = False del self.file_index[index] if self.websocker.send_flag == 0: self.websocker.send(data) elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": data, }) if save_res: # 不保存下载文件时的数据到录像 self.res.append(data) # 指定条结果或者指定秒数就保存一次 if len(self.res) > 2000 or int(time.time() - self.last_save_time) > 60 or \ sys.getsizeof(self.res) > 2097152: tmp = list(self.res) self.res = [] self.last_save_time = time.time() res(self.res_file, tmp, False) except Exception: if self.websocker.send_flag == 0: self.websocker.send('0.;') elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": '0.;', }) finally: self.close() def close(self): try: self.websocker.close() self.guacamoleclient.close() except Exception: logger.error(traceback.format_exc()) def shell(self, data): self.django_to_guacd(data)
class GuacamoleWebSocketConsumer(AsyncWebsocketConsumer): client = None task = None async def connect(self): """ Initiate the GuacamoleClient and create a connection to it. """ guacd_hostname = web_cfg.guacamole.guacd_host or "localhost" guacd_port = int(web_cfg.guacamole.guacd_port) or 4822 guacd_recording_path = web_cfg.guacamole.guacd_recording_path or "" guest_protocol = web_cfg.guacamole.guest_protocol or "vnc" guest_width = int(web_cfg.guacamole.guest_width) or 1280 guest_height = int(web_cfg.guacamole.guest_height) or 1024 guest_username = web_cfg.guacamole.username or "" guest_password = web_cfg.guacamole.password or "" params = urllib.parse.parse_qs(self.scope["query_string"].decode()) if "rdp" in guest_protocol: guest_host = params.get("guest_ip", "") guest_port = int(web_cfg.guacamole.guest_rdp_port) or 3389 else: guest_host = "localhost" ports = params.get("vncport", ["5900"]) guest_port = int(ports[0]) guacd_recording_name = params.get("recording_name", ["task-recording"])[0] self.client = GuacamoleClient(guacd_hostname, guacd_port) self.client.handshake( protocol=guest_protocol, width=guest_width, height=guest_height, hostname=guest_host, port=guest_port, username=guest_username, password=guest_password, recording_path=guacd_recording_path, recording_name=guacd_recording_name, ) if self.client.connected: # start receiving data from GuacamoleClient loop = asyncio.get_event_loop() self.task = loop.create_task(self.open()) # Accept connection await self.accept(subprotocol="guacamole") else: await self.close() async def disconnect(self, code): """ Close the GuacamoleClient connection on WebSocket disconnect. """ self.task.cancel() await sync_to_async(self.client.close)() async def receive(self, text_data=None, bytes_data=None): """ Handle data received in the WebSocket, send to GuacamoleClient. """ if text_data is not None: logger.debug("To server: %s", text_data) self.client.send(text_data) async def open(self): """ Receive data from GuacamoleClient and pass it to the WebSocket """ while True: content = await sync_to_async(self.client.receive)() if content: logger.debug("From server: %s", content) await self.send(text_data=content)
class Client: def __init__(self, websocker): self.websocker = websocker self.start_time = time.time() self.last_save_time = self.start_time self.res_file = 'webguacamole_' + str(int( self.start_time)) + '_' + gen_rand_char(16) + '.txt' self.res = [] self.guacamoleclient = None def connect(self, protocol, hostname, port, username, password, width, height, dpi): try: self.guacamoleclient = GuacamoleClient( settings.GUACD.get('host'), settings.GUACD.get('port'), settings.GUACD.get('timeout'), ) if protocol == 'vnc': # vnc 登陆不需要账号 self.guacamoleclient.handshake( protocol=protocol, hostname=hostname, port=port, password=password, width=width, height=height, dpi=dpi, ) elif protocol == 'rdp': self.guacamoleclient.handshake( protocol=protocol, hostname=hostname, port=port, username=username, password=password, width=width, height=height, dpi=dpi, ) Thread(target=self.websocket_to_django).start() except Exception: self.websocker.close(3001) def django_to_guacd(self, data): try: self.guacamoleclient.send(data) except Exception: self.close() def websocket_to_django(self): try: while True: time.sleep(0.001) data = self.guacamoleclient.receive() if not data: return if self.websocker.send_flag == 0: self.websocker.send(data) elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": data, }) self.res.append(data) # 指定条结果或者指定秒数就保存一次 if len(self.res) > 1000 or int(time.time() - self.last_save_time) > 50: tmp = list(self.res) self.res = [] self.last_save_time = time.time() # windows无法正常支持celery任务 if platform.system().lower() == 'linux': celery_save_res_asciinema.delay( settings.MEDIA_ROOT + '/' + self.res_file, tmp, False) else: with open(settings.MEDIA_ROOT + '/' + self.res_file, 'a+') as f: for line in tmp: f.write('{}'.format(line)) except Exception: if self.websocker.send_flag == 0: self.websocker.send('0.;') elif self.websocker.send_flag == 1: async_to_sync(self.websocker.channel_layer.group_send)( self.websocker.group, { "type": "group.message", "text": '0.;', }) finally: self.close() def close(self): self.websocker.close() self.guacamoleclient.close() def shell(self, data): self.django_to_guacd(data)