ssh and smtp server
This commit is contained in:
92
sshserver.py
Normal file
92
sshserver.py
Normal file
@@ -0,0 +1,92 @@
|
||||
import socket
|
||||
import select
|
||||
import threading
|
||||
import paramiko
|
||||
|
||||
class ParamikoConnection(paramiko.ServerInterface):
|
||||
def __init__(self, server):
|
||||
self.event = threading.Event()
|
||||
self.server = server
|
||||
|
||||
def check_channel_request(self, kind, chanid):
|
||||
print("check_channel_request", kind, chanid)
|
||||
if kind == 'session':
|
||||
return paramiko.OPEN_SUCCEEDED
|
||||
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
|
||||
|
||||
def check_auth_password(self, username, password):
|
||||
if self.server.on_ssh_login:
|
||||
return self.server.on_ssh_login(username, password)
|
||||
|
||||
print("check_auth_password", username, password)
|
||||
return paramiko.AUTH_SUCCESSFUL
|
||||
|
||||
class SSHServer:
|
||||
|
||||
def __init__(self, addr='0.0.0.0', port=22):
|
||||
self.server_address = addr
|
||||
self.listen_port = port
|
||||
self.listen_socket = None
|
||||
self.listen_thread = None
|
||||
self.client_sockets = []
|
||||
self.transports = []
|
||||
self.verbose = True
|
||||
self.on_message = None
|
||||
self.is_running = True
|
||||
self.private_key = None
|
||||
|
||||
# hooks
|
||||
self.on_ssh_login = None
|
||||
|
||||
|
||||
def load_private_key_from_file(self, path):
|
||||
with open(path, "r") as f:
|
||||
self.private_key = paramiko.RSAKey.from_private_key(f)
|
||||
|
||||
def start(self):
|
||||
|
||||
if self.private_key is None:
|
||||
self.private_key = paramiko.RSAKey.generate(2048)
|
||||
|
||||
self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.listen_socket.setblocking(False)
|
||||
self.listen_socket.bind((self.server_address, self.listen_port))
|
||||
self.listen_socket.listen()
|
||||
if self.verbose:
|
||||
print(f"SSH server running on: {self.server_address}:{self.listen_port}")
|
||||
try:
|
||||
while self.is_running:
|
||||
try:
|
||||
client_socket, client_address = self.listen_socket.accept()
|
||||
if self.verbose:
|
||||
print("Incoming connection:", client_address)
|
||||
self.client_sockets.append(client_socket)
|
||||
transport = paramiko.Transport(client_socket)
|
||||
transport.add_server_key(self.private_key)
|
||||
paramiko_connection = ParamikoConnection(self)
|
||||
transport.start_server(server=paramiko_connection)
|
||||
self.transports.append(transport)
|
||||
# for client_sock in self.client_sockets:
|
||||
|
||||
except BlockingIOError:
|
||||
pass
|
||||
# handle_client(client_socket, client_address)
|
||||
finally:
|
||||
self.listen_socket.close()
|
||||
|
||||
def start_background(self):
|
||||
self.listen_thread = threading.Thread(target=self.start)
|
||||
self.listen_thread.start()
|
||||
return self.listen_thread
|
||||
|
||||
def close(self):
|
||||
if self.listen_socket:
|
||||
self.listen_socket.close()
|
||||
for sock in self.client_sockets:
|
||||
sock.close()
|
||||
|
||||
def stop(self):
|
||||
self.is_running = False
|
||||
self.close()
|
||||
if self.listen_thread:
|
||||
self.listen_thread.join()
|
||||
Reference in New Issue
Block a user