mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
206 lines
7.8 KiB
Python
206 lines
7.8 KiB
Python
#coding: utf-8
|
|
# +-------------------------------------------------------------------
|
|
# | 宝塔Linux面板
|
|
# +-------------------------------------------------------------------
|
|
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
|
# +-------------------------------------------------------------------
|
|
# | Author: 黄文良 <287962566@qq.com>
|
|
# +-------------------------------------------------------------------
|
|
try:
|
|
import paramiko
|
|
except: pass
|
|
import json
|
|
import time
|
|
import os
|
|
import sys
|
|
import socket
|
|
import threading
|
|
|
|
sys.path.insert(0, '/www/server/panel/class/')
|
|
import public
|
|
from io import BytesIO, StringIO
|
|
from BTPanel import session
|
|
|
|
class ssh_terminal:
|
|
__log_type = 'aaPanel terminal'
|
|
_coll_user = None
|
|
_host = None
|
|
_web_socket = None
|
|
_ssh_info = None
|
|
_ssh_socket = None
|
|
_en_key = '4BbA7076e19H'
|
|
_thread = None
|
|
_my_terms = {}
|
|
_room = "ssh_data"
|
|
_send_last = False
|
|
_send_last_time = 0
|
|
_connect_time = 0
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
def connect(self, ssh_info=None):
|
|
if ssh_info: self._ssh_info = ssh_info
|
|
if not self._host: self._host = self._ssh_info['host']
|
|
# print('----------连接时的ssh_info--------------')
|
|
if self._ssh_info['host'] in self._my_terms:
|
|
if time.time() - self._my_terms[self._host].last_time < 86400:
|
|
return True
|
|
try:
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 262144)
|
|
sock.connect((self._ssh_info['host'], int(self._ssh_info['port'])))
|
|
except Exception as e:
|
|
self._web_socket.send("\rServer connection failed!\r")
|
|
return False
|
|
# 使用Transport连接
|
|
p1 = paramiko.Transport(sock)
|
|
p1.start_client()
|
|
if not 'pkey' in self._ssh_info: self._ssh_info['pkey'] = None
|
|
if not 'c_type' in self._ssh_info: self._ssh_info['c_type'] = None
|
|
try:
|
|
# 如果有pkey时则使用RSA私钥登录
|
|
if self._ssh_info['pkey'] and self._ssh_info['c_type']:
|
|
# print('------使用私钥登陆---------')
|
|
# 将RSA私钥转换为io对象,然后生成rsa_key对象
|
|
p_file = StringIO(self._ssh_info['pkey'])
|
|
pkey = paramiko.RSAKey.from_private_key(p_file)
|
|
p1.auth_publickey(username=self._ssh_info['username'].strip(), key=pkey)
|
|
else:
|
|
# print('-----------使用密码登陆-----------')
|
|
p1.auth_password(username=self._ssh_info['username'].strip(), password=self._ssh_info['password'])
|
|
except Exception as e:
|
|
self._web_socket.send("\rWrong user name or password!\r")
|
|
p1.close()
|
|
return False
|
|
|
|
self._my_terms[self._host] = public.dict_obj()
|
|
self._my_terms[self._host].last_time = time.time()
|
|
self._my_terms[self._host].connect_time = time.time()
|
|
# 打开会话
|
|
self._my_terms[self._host].tty = p1.open_session()
|
|
# 获取终端对象
|
|
self._my_terms[self._host].tty.get_pty(term='xterm', width=100, height=34)
|
|
self._my_terms[self._host].tty.invoke_shell()
|
|
# 记录登陆记录
|
|
#public.M('ssh_records').add('coll_user,ssh_user,host,cmd,addtime', (self._coll_user, self._ssh_info['username'], self._ssh_info['host'], 'login', int(time.time())))
|
|
#print("登录成功")
|
|
self._my_terms[self._host].last_send = []
|
|
self._send_last = True
|
|
self._connect_time = time.time()
|
|
return True
|
|
|
|
def resize(self, data):
|
|
try:
|
|
data = json.loads(data)
|
|
self._my_terms[self._host].tty.resize_pty(width=data['width'], height=data['height'], width_pixels=data['width_px'], height_pixels=data['height_px'])
|
|
return True
|
|
except:
|
|
print(public.get_error_info())
|
|
return False
|
|
|
|
def send(self):
|
|
try:
|
|
while not self._web_socket.closed:
|
|
c_data = self._web_socket.receive()
|
|
if not c_data: continue
|
|
if len(c_data) > 10:
|
|
if c_data.find('new_terminal') != -1:
|
|
if not self._host in self._my_terms:
|
|
self.connect()
|
|
else:
|
|
if time.time() - self._connect_time > 3:
|
|
self.last_send()
|
|
continue
|
|
if c_data.find("reset_connect") != -1:
|
|
if not self._host in self._my_terms: self.connect()
|
|
continue
|
|
|
|
if self._host in self._my_terms:
|
|
self._my_terms[self._host].last_time = time.time()
|
|
self._my_terms[self._host].tty.send(c_data)
|
|
else:
|
|
return
|
|
except:
|
|
print(public.get_error_info())
|
|
|
|
def recv(self):
|
|
try:
|
|
n = 0
|
|
while not self._web_socket.closed:
|
|
self.not_send()
|
|
#if n == 0: self.last_send()
|
|
data = self._my_terms[self._host].tty.recv(1024)
|
|
self.not_send()
|
|
if not data:
|
|
self.close()
|
|
self._web_socket.send('The connection has been disconnected and pressing Enter will attempt to reconnect!')
|
|
return
|
|
try:
|
|
result = data.decode()
|
|
except:
|
|
result = str(data)
|
|
if not result: continue
|
|
if self._web_socket.closed:
|
|
self._my_terms[self._host].not_send = result
|
|
return
|
|
self.set_last_send(result)
|
|
if not n: n = 1
|
|
self._web_socket.send(result)
|
|
except:
|
|
print(public.get_error_info())
|
|
|
|
def set_last_send(self,result):
|
|
last_size = 1024
|
|
if not 'last_send' in self._my_terms[self._host]:
|
|
self._my_terms[self._host].last_send = []
|
|
|
|
self._my_terms[self._host].last_send.append(result)
|
|
last_len = len(self._my_terms[self._host].last_send)
|
|
if last_len > last_size:
|
|
self._my_terms[self._host].last_send = self._my_terms[self._host].last_send[last_len-last_size:]
|
|
|
|
def not_send(self):
|
|
if 'not_send' in self._my_terms[self._host]:
|
|
if self._my_terms[self._host].not_send:
|
|
self._web_socket.send(self._my_terms[self._host].not_send)
|
|
self._my_terms[self._host].not_send = ""
|
|
|
|
def last_send(self):
|
|
if time.time()- self._send_last_time < 3: return False
|
|
self._send_last_time = time.time()
|
|
time.sleep(0.3)
|
|
if not self._host in self._my_terms: return False
|
|
if 'last_send' in self._my_terms[self._host]:
|
|
for d in self._my_terms[self._host].last_send:
|
|
self._web_socket.send(d)
|
|
|
|
def close(self):
|
|
try:
|
|
self._my_terms[self._host].tty.close()
|
|
except:pass
|
|
if self._host in self._my_terms:
|
|
del self._my_terms[self._host]
|
|
self._thread = None
|
|
|
|
def run(self,web_socket, ssh_info=None):
|
|
self._web_socket = web_socket
|
|
if 'id' in ssh_info:
|
|
self._ssh_info = self.get_server_ssh_info(ssh_info)
|
|
else:
|
|
self._ssh_info = ssh_info
|
|
if not self._ssh_info:
|
|
return
|
|
result = self.connect()
|
|
time.sleep(0.1)
|
|
if result:
|
|
sendt = threading.Thread(target=self.send)
|
|
recvt = threading.Thread(target=self.recv)
|
|
sendt.start()
|
|
recvt.start()
|
|
sendt.join()
|
|
recvt.join()
|
|
if time.time() - self._my_terms[self._host].last_time > 86400: self.close()
|
|
self._web_socket = None
|