Hi I am using following code in a python script (not running fab from command line), at line A when I change local to run or sudo, it gives me error like:
No hosts found. Please specify (single) host string for connection:
Code is:
env.host = "XXXX"
env.user = "XXX"
def execute():
local('uname -a') ### A : changing this gives error ###
execute()
My objective is to ssh into a single host machine.
According to the fabric docs, if you are calling tasks from the python script - you should use fabric.tasks.execute:
from fabric.tasks import execute
from fabric.api import *
env.user = "XXX"
def execute_task():
sudo('uname -a')
execute(execute_task, host="XXX")
Hope that helps.
Why not use paramiko:
import sys
import traceback
import paramiko
paramiko.util.log_to_file('session.log')
username = 'someuser'
port = 22
hostname = 'foo.bar.com'
try:
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy)
client.connect(hostname, port, username, password)
chan = client.invoke_shell()
print repr(client.get_transport())
print '*** Here we go!'
print
interactive.interactive_shell(chan)
chan.close()
client.close()
except Exception, e:
print '*** Caught exception: %s: %s' % (e.__class__, e)
traceback.print_exc()
try:
client.close()
except:
pass
sys.exit(1)
Related
error message in terminalhelp I am trying to create an ssh server in python according to the book blackhat python, when I run this code I get "FileNotFoundError: [Errno 2] No such file or directory: '/home/burp/blackhatpy/.test_rsa.key'"
do I need to create the file .test_rsa.key? Help!! am a beginner and new to python, the image is what error i get When i try to run the server
import os
import paramiko
import socket
import sys
import threading
CWD = os.path.dirname(os.path.realpath(__file__))
HOSTKEY = paramiko.RSAKey(filename=os.path.join(CWD, '.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 == 'tim') and (password == 'sekret'):
return paramiko.AUTH_SUCCESSFUL
if __name__ == '__main__':
server = '137.184.226.245'
ssh_port = 2222
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)
else:
print(f'[+] Got a connection! from {addr}')
bhSession = paramiko.Transport(client)
bhSession.add_server_key(HOSTKEY)
server = Server()
bhSession.start_server(server=server)
chan = bhSession.accept(20)
if chan is None:
print('*** No channel.')
sys.exit(1)
print('[+] Authenticated!')
print(chan.recv(1024).decode())
chan.send('Welcome to bh_ssh')
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()
In the book you refer to, where it presents the code that you've included here, it tells you where to get the SSH key file that should be used to run that code. It says:
For this example, we’re using the SSH key included in the Paramiko demo files.
That file can be found here:
https://github.com/paramiko/paramiko/blob/main/demos/test_rsa.key
The code you provide refers to a file with the name ".test_rsa.key". In the copy of the book that I have, the leading period (.) is not there. I only mention this in case you wonder why the file name in your version of the code is slightly different than that of the file I mention above.
You are missing the file test_rsa.key
On Ubuntu you can use the following command to download on the path you specified "/home/burp/blackhatpy/.test_rsa.key":
wget https://raw.githubusercontent.com/paramiko/paramiko/main/demos/test_rsa.key -O /home/burp/blackhatpy/.test_rsa.key
So I built a program that prints out the login logs of my ubuntu server using tail -f.
The program uses Paramiko to connect via ssh and runs the command to tail the logs.
The program works but it prints out the motd from the server which is unnecessary.
I've tried splicing using itertools.
Tried using next().
Still doesn't work.
Here's my code:
import yaml, paramiko, getpass, traceback, time, itertools
from paramiko_expect import SSHClientInteraction
with open("config.yaml", "r") as yamlfile:
cfg = yaml.load(yamlfile, Loader=yaml.FullLoader)
def main():
command = "sudo tail -f /var/log/auth.log"
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
server_pw = getpass.getpass("Enter the password for your account %s on %s:" % (cfg['ssh_config']['username'], cfg['ssh_config']['host']))
sudo_pw = getpass.getpass("Enter the sudo password for %s on %s: " % (cfg['ssh_config']['username'], cfg['ssh_config']['host']))
ssh.connect(hostname = cfg['ssh_config']['host'], username = cfg['ssh_config']['username'], port = cfg['ssh_config']['port'], password = server_pw)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send(command)
interact.send(sudo_pw + "\n")
with open(interact.tail(line_prefix=cfg['ssh_config']['servername']+': ')) as tail:
for line in itertools.islice(tail, 17, None):
print(line)
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
except Exception:
traceback.print_exc()
finally:
try:
ssh.close()
except:
pass
if __name__ == '__main__':
main()
You get MOTD because you are opening an interactive shell session. I do not think you need that, quite on the contrary.
Use SSHClient.exec_command instead:
stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)
stdin.write(sudo_pw + "\n")
stdin.flush()
for line in iter(stdout.readline, ""):
print(line, end="")
Related questions:
Get output from a Paramiko SSH exec_command continuously
Pass input/variables to command/script over SSH using Python Paramiko
What is the difference between exec_command and send with invoke_shell() on Paramiko?
Obligatory warning: Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".
Testing sending commands to IoT devices that drops the user into a python script instead of a bash shell.
i.e. in /etc/passwd - admin:x:1000:0:admin:/home/admin:/home/admin/IoT.py
So cant use the normal bash exec_commands to talk to the python script. Basically once it connects it needs the send a command string and receive the output. Below the script reads IP addresses from a text file, whats the correct way to send and receive commands
#!/usr/bin/env python
import paramiko
import sys
def LogonSSH(ipAddress) :
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for line in open(ipAddress, "r").readlines() :
ipAddr = line.strip()
username='admin'
password='admin'
try :
print "[+] Trying %s with username: %s password: %s " % (ipAddr, username, password)
ssh.connect(ipAddr, username=username, password=password)
except paramiko.AuthenticationException:
print "[x] %s - could not log in" % (ipAddr)
continue
stdin, stdout, stderr = ssh.exec_command('help')
stdin.flush()
stdin.write('help\n')
out = stdout.read()
stdin.flush()
print out
ssh.close()
break
if __name__ == "__main__" :
LogonSSH(sys.argv[1])
Below changes might help you. Just make send and recv, recv only takes the last commands output, but you need to consider:
Put some sleep after sending command (just trial and error)
Some tricks on output data, because it has invisible string parts such as (<pre>..</pre>)
Some output data might be too big to handle > 65100 bytes of recv, just check Paramiko Docs for recv method.
#!/usr/bin/env python
import paramiko
import sys
def LogonSSH(ipAddress) :
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for line in open(ipAddress, "r").readlines() :
ipAddr = line.strip()
username='admin'
password='admin'
try:
print "[+] Trying %s with username: %s password: %s " % (ipAddr, username, password)
ssh.connect(ipAddr, port=22, username=uname, password=pin, timeout=240,banner_timeout=250, auth_timeout=500)
my_ssh_shell = ssh.invoke_shell()
except Exception as ex:
print("Some exception occured:" + str(ex))
continue
my_ssh_shell.send(bytes("help" + "\x0D", 'utf-8'))
result_screen = my_ssh_shell.recv(65100).decode('ascii')
print("Your SSH -help- command returns:" + str(result_screen))
my_ssh_shell.close()
break
if __name__ == "__main__" :
LogonSSH(sys.argv[1])
Edit: Just change it to any exception for connection, and also some additional paramters on connection string.
The following code will get the MOTD, but send still not working
my_ssh_shell = ssh.invoke_shell()
my_ssh_shell.settimeout(2)
while True :
data = my_ssh_shell.recv(1024).decode('ascii')
if len(data) < 1 :break
print(data)
return
#### DOESNT SEND HERE OR GET RECEIVE RESULTS#########
# my_ssh_shell.send('help\n')
# while True :
# data = my_ssh_shell.recv(1024).decode('ascii')
# if len(data) < 1 :break
# print(data)
# return
my_ssh_shell.close()
im connecting a linux server with sshclient .And then, im connecting cisco routers via telnet on this server. I'm connecting server and execute telnet command perfectly but in second or third telnet command code get stucked and doesnt throw error.Here is part of my code:
def __init__(self):
self.pre_client=paramiko.SSHClient()
self.pre_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sellf.pre_client.connect("server",username="user",password="password")
self.client=self.pre_client.invoke_shell()
def connect(self,ip):
o=self.client.recv(1024)
print o
self.client.exec_command("telnet %s\n"%(ip))
while True:
o=self.client.recv(1024)
print o
#EXECUTE COMMAND ON ROUTER
self.client.exec_command("exit\n")
if 'exit' in o:
break
Why it get stuck on this command? How can i handle it?
I think I'd need to see more code to find what's wrong. If you don't have a specific reason for needing to use a Paramiko Channel, life will probably be a lot easier for you if you just use a Paramiko Client. This is a rough snippet from an old script of mine:
def ssh_connect(usr, pswds, host):
# Open Connection - auto add policy
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Retry with multiple passwords
for pswd in pswds:
try:
ssh.connect(host, username=usr, password=pswd)
return ssh
except:
pass
else:
print("Could not login to: " + host)
return None
def send_command(conn, command):
try:
stdin, stdout, stderr = conn.exec_command(command)
if stdout:
for str in stdout:
sys.stdout.write("\t%s" % str)
return True
if stderr:
for str in stderr:
sys.stderr.write("\t%s" % str)
return False
else:
print("\n")
return True
except paramiko.ssh_exception.SSHException as e:
print(e.message)
return False
And of course, call them with:
conn = ssh_connect(login, passwords, host)
send_command(conn, command)
I was wondering if there is way to pass the channel object from one program (imported as python module) to be used in another. For example - I have following program that I import into another program using c = Connect(host,user,pwd) and then invoke ssh shell on this.
Connect.py:
#!/usr/bin/python
import paramiko
import logging
import time
class Connect:
def __init__(self,host,user,pwd):
self.host = host
self.user = user
self.pwd = pwd
port = 22
logfile = 'log.txt'
logging.basicConfig(filename=logfile,level=logging.INFO)
try:
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(host,port,username=self.user,password=self.pwd,allow_agent=False,look_for_keys=False)
logging.info('Connected to %r host' % host)
except Exception as e:
logging.info('Exception caught : %r' % str(e))
okay, it was simple ..
chan = c.ssh.invoke_shell()
this does the job. Now I dont need to write the Connect related script in my programs any more.