Paramiko: Socket is closed when copying file through forwarded port

Created on 10 Apr 2015  路  5Comments  路  Source: paramiko/paramiko

Hi,

I am new to python. I was using forward.py to copy files through the tunnel (I executed the scp manually). The strange thing is that small files are copied without problem (even if a directory contains lots of small files) but in case of larger ones (>40Mb) the tunnel closes. Only part of the file is copied. The scp reports "Packet corrupt".
It works fine if I manually create the tunnel without python.
What can cause this?
Thanks.

python forward.py -r 10.78.150.59:22 150.132.151.147:22
Connecting to ssh host 150.132.151.147:22 ...
Now forwarding port 4000 to 10.78.150.59:22 ...
Connected! Tunnel open ('127.0.0.1', 37263) -> ('150.132.151.147', 22) -> ('10.78.150.59', 22)
Tunnel closed from ('127.0.0.1', 37263)
Connected! Tunnel open ('127.0.0.1', 37322) -> ('150.132.151.147', 22) -> ('10.78.150.59', 22)

Exception happened during processing of request from ('127.0.0.1', 37322)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 649, in init
self.handle()
File "forward.py", line 79, in handle
chan.send(data)
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 698, in send
return self._send(s, m)
File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 1058, in _send
raise socket.error('Socket is closed')
error: Socket is closed

Most helpful comment

There's a bug in forward.py in the Handler.handle() method. After data is received from the sock.recv(1024) call, the data is sent over the channel by calling chan.send(data). However, the return value of the send call is ignored.

The python documentation for socket.send() says, "Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data." In the case where a lot of data is being written to the tunnel faster than it can be sent over the channel, the send buffer/window may fill up, and instead of sending all the data it will only send a portion of it. The return value indicates how much of the data was actually sent. (With the current code, throttling back the file transfer (e.g. sftp with -l option) may avoid the problem).

Similarly on the receiving end, the return value of the call to sock.send(data) needs to be checked as well (this could cause problems downloading). rforward.py also has the same bug. I discovered this while troubleshooting a similar problem in the sshtunnel python library ( https://github.com/pahaz/sshtunnel/issues/115 ). Other developers may be using forward.py as a reference example.

All 5 comments

Also having this issue. I do not see it when I am forwarding to a machine on my wired network, but if I am forwarding to a machine over wifi I do see this issue. using SSH -L I do not see this issue. Then again maybe ssh is doing something to intelligently reconnect. Perhaps the forward.py sample just doesn't demonstrate how to do that?

Having same issue with file 300Mb.
using paramiko.Transport and paramiko.SFTPClient.from_transport

Any workarounds on this, except manual copy ?

I see the same issue, tried scp and sftp both, no dice. Please fix.

There's a bug in forward.py in the Handler.handle() method. After data is received from the sock.recv(1024) call, the data is sent over the channel by calling chan.send(data). However, the return value of the send call is ignored.

The python documentation for socket.send() says, "Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data." In the case where a lot of data is being written to the tunnel faster than it can be sent over the channel, the send buffer/window may fill up, and instead of sending all the data it will only send a portion of it. The return value indicates how much of the data was actually sent. (With the current code, throttling back the file transfer (e.g. sftp with -l option) may avoid the problem).

Similarly on the receiving end, the return value of the call to sock.send(data) needs to be checked as well (this could cause problems downloading). rforward.py also has the same bug. I discovered this while troubleshooting a similar problem in the sshtunnel python library ( https://github.com/pahaz/sshtunnel/issues/115 ). Other developers may be using forward.py as a reference example.

I'm chasing down an Ansible issue which seemingly stems from this exact issue. Large configs sent over paramiko to network devices is leading to dead sockets and long deployment calls.

I would love some attention be put to this issue as it could help out so much in certain Ansible use cases. Thanks all!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

plegrand1 picture plegrand1  路  4Comments

Kkevsterrr picture Kkevsterrr  路  5Comments

thomasd3 picture thomasd3  路  3Comments

aop picture aop  路  6Comments

aliceinwire picture aliceinwire  路  5Comments