The Python Oracle

How to compensate for Paramiko rekey failures?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Cool Puzzler LoFi

--

Chapters
00:00 How To Compensate For Paramiko Rekey Failures?
03:55 Accepted Answer Score 1
05:14 Thank you

--

Full question
https://stackoverflow.com/questions/3181...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #ssh #paramiko

#avk47



ACCEPTED ANSWER

Score 1


I'd still love to hear good answers to #2...

I found the answer to #1 via hacking and slashing: the transport object returned by get_transport includes a packetizer object which can be used to address the need_rekey() method:

$ python
Python 2.7.5 (default, Apr  9 2015, 11:03:32)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import paramiko
>>> ssh = paramiko.SSHClient()
>>> omkey = paramiko.RSAKey.from_private_key_file('./privkey.rsa')
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> ssh.connect('gowenfawr.example.com', username='gowenfawr', pkey=omkey)
>>> transport = ssh.get_transport()
>>> transport.packetizer
<paramiko.packet.Packetizer object at 0x7fb121aa5650>
>>> transport.packetizer.need_rekey()
False
>>>

I updated my "data read" loop to check if transport.packetizer.need_rekey() was set, and if it was, to sleep using time.sleep(1). The following code prints out '.' every 1/80th of the data transfer progress and a 'Z' will be printed out whenever it pauses because a rekey has been requested:

track = 0
hash = int(size/80)
while True:
    r, w, x = select.select([chan], [], [])
    if chan in r:
        data = chan.recv(1024)
        if len(data) == 0:
            break
        os.write(fp[0], data)
        track = track + len(data)
        if transport.packetizer.need_rekey():
            sys.stdout.write('Z')
            sys.stdout.flush()
            time.sleep(1)
        if track > hash:
            sys.stdout.write('.')
            sys.stdout.flush()
            track = 0
print ''

Which results in this sort of output

$ grabdata.py gowenfawr.example.com
target is gowenfawr.example.com
Found appropriate kernel version
Setting up data transfer
.....Z.....Z.....Z.....Z......Z.....Z.....Z.....Z.....Z......Z.....Z.....Z.....Z.....Z......Z.....Z...
Transfer complete!
$ 

Which tells me that rekeys are happening regularly (good, given the volume of data being transferred here) and I have not been able to reproduce the session abort failure over ~10 runs since the change.