SSH server and client to run remote commands with Paramiko

SSH server and client to run remote commands with Paramiko

Paramiko is a Python library for SSH (Secure Shell) protocol implementation. It allows you to create secure connections to remote servers over SSH, execute commands, transfer files, and manage various aspects of the remote system.

Python
import paramiko


def ssh_command(ip, user, passwd, command):
    client = paramiko.SSHClient()
    # client can also support using key files
    # client.load_host_keys('/home/user/.ssh/known_hosts')
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, username=user, password=passwd)
    ssh_session = client.get_transport().open_session()
    if ssh_session.active:
        ssh_session.exec_command(command)
        print(ssh_session.recv(1024))
    return


ssh_command('192.168.100.131', 'junaid', 'lovesthepython', 'ClientConnected')

Explanation:

  1. Import Paramiko:

    • The script begins by importing the paramiko module.
  2. Function ssh_command:

    • This function takes four parameters: ip (IP address of the remote server), user (SSH username), passwd (SSH password), and command (the command to execute on the remote server).
    • Inside the function, an instance of the SSHClient class is created.
  3. Setting Host Key Policy:

    • The script sets the host key policy to AutoAddPolicy(), which automatically adds the server’s host key to the local known_hosts file. This is insecure and should be avoided in production for security reasons.
  4. Connecting to the Remote Server:

    • The connect method is used to establish an SSH connection to the remote server. It takes the IP address, username, and password as parameters.
  5. Opening an SSH Session:

    • The get_transport().open_session() method is used to open an SSH session.
  6. Executing the Command:

    • If the SSH session is active (if ssh_session.active:), the specified command is executed on the remote server using exec_command.
  7. Receiving and Printing Output:

    • The script receives the output of the executed command (limited to 1024 bytes) using ssh_session.recv(1024). It is then decoded from bytes to a UTF-8 string and printed.
  8. Exception Handling:

    • Any exceptions that occur during the execution of the script are caught, and an error message is printed.
  9. Closing the SSH Connection:

    • Finally, the close method is called to close the SSH connection.
  10. Example Usage:

    • The script concludes with an example usage of the ssh_command function, where it connects to the server with the specified IP, username, password, and executes the command 'ClientConnected'.

SSH client to connect to an SSH server:

Python
import subprocess
import paramiko


def ssh_command(ip, user, passwd, command):
    client = paramiko.SSHClient()
    # client can also support using key files
    # client.load_host_keys('/home/user/.ssh/known_hosts')
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, username=user, password=passwd)
    ssh_session = client.get_transport().open_session()
    if ssh_session.active:
        ssh_session.send(command)
        print(ssh_session.recv(1024))  # read banner

        while True:
            # get the command from the SSH server
            command = ssh_session.recv(1024)
            try:
                cmd_output = subprocess.check_output(command.decode(), shell=True)
                ssh_session.send(cmd_output)
            except Exception as e:
                ssh_session.send(str(e))
    client.close()
    return


ssh_command('192.168.100.122', 'Junaid', 'lovesthepython', 'ClientConnected')

Explanation:

  1. Interactive Shell Functionality:

    • This script extends the previous example by creating an interactive shell over the SSH connection.
  2. Sending and Receiving Commands:

    • The initial command is sent to the server using ssh_session.send(command).
    • The script then enters a main loop where it continuously receives commands from the SSH server using ssh_session.recv(1024).decode().
  3. Executing Commands:

    • Each received command is executed locally on the script’s machine using subprocess.check_output(command, shell=True).
    • The output of the command is sent back to the SSH server using ssh_session.send(cmd_output).
  4. Exception Handling:

    • If an exception occurs during the execution of a command, the exception message is sent back to the SSH server.
  5. Closing the SSH Connection:

    • The finally block ensures that the SSH connection is closed even if an exception occurs.
  6. Example Usage:

    • The script concludes with an example usage of the ssh_command function, connecting to the server with the specified IP, username, password, and initiating the command 'ClientConnected'.

SSH Server

The server listens for incoming connections, authenticates clients based on a hardcoded username and password, and allows the authenticated clients to execute commands on the server.

Python
import socket
import paramiko
import threading
import sys

# using the server host key from the paramiko demo files
host_key = paramiko.RSAKey(filename='test_rsa.key')


class Server(paramiko.ServerInterface):
    def __init__(self):
        self.event = threading.Event()

    def check_channel_request(self, kind, chanid):
        if kind == 'session':
            return paramiko.OPEN_SUCCEEDED
        return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED

    def check_auth_password(self, username, password):
        if username == 'root' and password == 'toor':
            return paramiko.AUTH_SUCCESSFUL
        return paramiko.AUTH_FAILED


server = sys.argv[1]
ssh_port = int(sys.argv[2])

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((server, ssh_port))
    sock.listen(100)
    print("[+] Listening for connection...")
    client, addr = sock.accept()
except Exception as e:
    print("[-] Listen failed: " + str(e))
    sys.exit(1)

print("[+] Got a connection!")

try:
    # noinspection PyTypeChecker
    bhSession = paramiko.Transport(client)
    bhSession.add_server_key(host_key)
    server = Server()
    try:
        bhSession.start_server(server=server)
    except paramiko.SSHException:
        print("[-] SSH negotiation failed.")
    chan = bhSession.accept(20)
    print("[+] Authenticated!")
    print(chan.recv(1024))
    chan.send("Welcome to bh_ssh!")
    while True:
        try:
            command = input("Enter command: ").strip("\n")
            if command != "exit":
                chan.send(command)
                print(chan.recv(1024).decode(errors="ignore") + "\n")
            else:
                chan.send("exit")
                print("Exiting...")
                bhSession.close()
                raise Exception("exit")
        except KeyboardInterrupt:
            bhSession.close()
        except Exception as e:
            print("[-] Caught exception: " + str(e))
            bhSession.close()
finally:
    sys.exit(1)

Explanation:

  1. SSH Server Configuration:

    • The script configures an SSH server using Paramiko.
    • It listens on a specified IP address (server) and port number (ssh_port).
  2. Server Class (paramiko.ServerInterface):

    • The Server class is a custom implementation of paramiko.ServerInterface.
    • It checks channel requests and authentication requests. In this case, it allows only the ‘session’ channel and authenticates a user with the username ‘root’ and password ‘toor’.
  3. Socket Setup and Connection:

    • The script creates a socket, binds it to the specified IP and port, and starts listening for incoming connections.
    • When a connection is received, it accepts the connection.
  4. SSH Session Setup:

    • The script creates a Paramiko Transport object (bhSession) for the accepted connection.
    • It adds the server’s host key (host_key) to the session.
  5. SSH Negotiation:

    • The script starts the SSH server and accepts the connection.
  6. Authenticated Channel Setup:

    • Upon successful authentication, it accepts a channel (chan) and prints an authentication message.
  7. Interactive Command Execution:

    • The script enters a loop allowing the user to input commands.
    • It sends the command to the client and prints the received output.
  8. Exiting the Server:

    • The user can enter ‘exit’ to close the SSH session and exit the server.
Total
3
Shares

Leave a Reply

Previous Post
Building a TCP proxy for accessing network-based software

Building a TCP proxy for accessing network-based software

Next Post
SSH forward and reverse tunneling

SSH forward and reverse tunneling

Related Posts