Python SFTP: Get Notification when Connection breaks - python

Is it Possible if the Connection to a Server cuts off for some reason that I get a Text or something, so I know that the Error has something to do with the Server?
import paramiko
import time
def connSFTP(ssh_key_filepath,host,user):
#Fehleroptionen 1. Pfad zum SSH-KeyError
#-SSH-Key vorhanden?
#2.Host und/oder Username ist falsch
k = paramiko.RSAKey.from_private_key_file(ssh_key_filepath) #SSH KEY
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect( hostname = host, username = user , pkey = k )
sftp = c.open_sftp()
return sftp
def main():
ssh_key_filepath = '/home/dtv/.ssh/id_rsa'
hostname = 'HostAdress'
username = 'user'
sftp = connSFTP(ssh_key_filepath,hostname,username)
print('Connected')
time.sleep(30)
#sftp.close()
if __name__ == '__main__':
main()
I built in a sleep, so I can kill the procedure for the Connection and Simulate the Connection lost in time.

You should use exception handling with the following:
Raises:
BadHostKeyException – if the server’s host key could not be verified
Raises:
AuthenticationException – if authentication failed
Raises:
SSHException – if there was any other error connecting or establishing an SSH session
Raises:
socket.error – if a socket error occurred while connecting
Paramiko api documentation link: http://docs.paramiko.org/en/1.15/api/client.html#paramiko.client.SSHClient.connect

Related

Python 3.9 SFTP connection

I'm trying to connect to SFTP server that is hosted locally (that's a POC ...). I'm using python 3.9 and the library paramiko.
The code I use is the following :
import paramiko
import sys
def main() -> None:
hostkeys = paramiko.hostkeys.HostKeys("known_hosts.txt")
ip = "127.0.0.1"
username = "my_username"
password = "my_password"
# As per the paramiko doc. The host fingerprint is stored using the ed25519 algorithm
hostFingerprint = hostkeys.lookup(ip)["ssh-ed25519"]
try:
tp = paramiko.Transport(ip, 22)
tp.connect(username=username, password=password, hostkey=hostFingerprint)
# Upload operations happening here...
tp.close()
except Exception as e:
print(e)
finally:
return None
The file known_hsts.txt has been generated via Powershell cmd : ssh-keyscan 127.0.0.1 > C:\Users\my_username\PycharmProjects\POC\known_hosts.txt.
When i run the script i don't understand why hostkeys.keys() == []
When i look at the file known_hosts.txt I see the different keys : ssh-rsa, ssh-ed25519, etc.

How to establish a SSH connection in Python

I am using Python 3.6.6 and i need to establish a SSH connection to a server.
I have the IP and port for the server, and i use my credentials to login, usually through putty. The servers is on Linux/Suse .
I need to get the list of directories in the server folder, and copy the content of one of the files out. I am using paramiko, and i need the connection to be open so i can execute and interact with the server.
I am not sure i am clear enough.
Below is my code
import paramiko
nbytes = 4096
hostname = '123.123.123.123'
port = 22020
username = 'uname'
password = 'pwd'
command = 'vi log'
client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)
stdout_data = []
stderr_data = []
session = client.open_channel(kind='session')
session.exec_command(command)
while True:
if session.recv_ready():
stdout_data.append(session.recv(nbytes))
if session.recv_stderr_ready():
stderr_data.append(session.recv_stderr(nbytes))
if session.exit_status_ready():
break
print ("rec status: ", session.recv_ready())
print ("exit status: ", session.recv_exit_status())
print ("".join(stdout_data))
print ("".join(stderr_data))
session.close()
client.close()

Paramiko check login timeout of SSH Server

I want to see how long it takes my ssh server to close the connection if the user does not login.
What i have so far
self.sshobj = paramiko.SSHClient()
self.sshobj.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.sshobj.connect("192.168.0.1", port=22, username="test", password="test")
self.channel = self.sshobj.invoke_shell()
But the problem is that i don't want to login , which sshobj.connect does, i want to be in the login screen.
And i want to check how long it takes for the server to close the connection.
Is there any way to do this via paramiko ?
You do not necessarily need paramiko to check the LoginGraceTime but since you're specifically asking for it:
Note: banner_timeout is just a timeout for the peer ssh banner response.
Note: timeout is actually a socket read timeout, none is no timeout. Use this to set a hard-timeout for your check.
self.sshobj = paramiko.SSHClient()
self.sshobj.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.sshobj.connect("192.168.0.1", port=22, look_for_keys=False, timeout=None, banner_timeout=5)
except paramiko.ssh_exception.SSHException, se:
# paramiko raises SSHException('No authentication methods available',) since we did not specify any auth methods. socket stays open.
pass
ts_start = time.time()
try:
self.channel = self.sshobj.invoke_shell()
except EOFError, e:
# EOFError is raised when peer terminates session.
pass
print time.time()-ts_start
You can even get rid of the first try_catch for No authentication methods available by overriding self.sshobj._auth with an NOP. Below are some changes to the first variant:
def noauth(username, password, pkey, key_filenames, allow_agent,
look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host): pass
...
sshobj._auth = noauth
sshobj.connect("192.168.0.1", port=22, look_for_keys=False, timeout=None, banner_timeout=5)
...
But, as initially mentioned, you do not even need paramiko to test this timeout since the LoginGraceTime triggers like a server-side socket read timeout once banners are exchanged. Therefore you just need to establish a TCP connection, send a fake ssh banner and wait until the remote side disconnects:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.0.1", 22))
s.sendall("SSH-2.0-MyPythonSSHProbingClient")
s.settimeout(5*60) # hard-limit
print s.recv(500) # remote banner
ts_start = time.time()
if not s.recv(100):
# exits when remote site closes connection, or raises socket.timeout when hard-limit is hit.
print time.time()-ts_start
else:
raise Exception("whoop, something's gone wrong")
The non-paramiko variant is even more accurate.

connect to third server using script

I can do ssh from one server to another using this:
# ssh root#1.2.4.148
The following code is doing the same in pythonic way:
import paraminko
#paramiko.util.log_to_file('ssh.log') # sets up logging
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('1.2.4.148')
stdin, stdout, stderr = client.exec_command('ls -l')
But if I need to connect to third server from the second server, I can do this:
# ssh -t root#1.2.4.148 ssh root#1.2.4.149
How is this done in python?
My current server (250) has password less keys saved with 148 server for easy access. But connection to 149 from 148 will need password if that matters.
This python function will connect to middle_server first and then to last_server. It will execute the command "mycommand" on last_server and return it's output.
def myconnect():
middle_server='1.2.3.4'
middle_port=3232
middle_user='shantanu'
middle_key_filename='/root/.ssh/id_rsa.pub'
last_server='6.7.8.9'
last_port=1224
last_user='root'
last_password='xxxxx'
mycommand='pwd'
import paramiko
proxy_client = paramiko.SSHClient()
proxy_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy_client.connect(middle_server, port=middle_port, username=middle_user, key_filename=middle_key_filename)
transport = proxy_client.get_transport()
dest_addr = (last_server, last_port)
local_addr = ('127.0.0.1', 1234)
channel = transport.open_channel("direct-tcpip", dest_addr, local_addr)
remote_client = paramiko.SSHClient()
remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
remote_client.connect('localhost', port=last_port, username=last_user, password=last_password, sock=channel)
(sshin1, sshout1, ssherr1) = remote_client.exec_command(mycommand)
print sshout1.read()
except:
print "error"
return 0

fabric without fabfile - run and sudo gives error, but not local

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)

Categories