Search code examples
pythonsftpparamikoeoferrorproftpd

Uploading large files to proftpd through paramiko times out


I've set up a SFTP server using proftpd on my local machine. It works fine, except that it times out when uploading files larger than approximately 30000 characters.

Uploading from the command line through proftpd works without any problems, and using paramiko to upload to a different SFTP server also works. This leads me to think there is a bug specifically in the interaction between paramiko and proftpd.

I've made a small script to illustrate the problem:

import paramiko

transport = paramiko.Transport(('localhost', 2220)) # my proftpd SFTP port
transport.connect(username='x', password='x')
client = paramiko.SFTPClient.from_transport(transport)
with open('testimage.jpg') as f: # 35241 characters
    content = f.read()
with client.open('testimage.jpg', 'w') as f:
    f.write(content)

My SFTP-specific proftpd configuration:

<IfModule mod_sftp.c>
    <VirtualHost 0.0.0.0>
        Include            /etc/proftpd/conf.d
        SFTPEngine         on
        SFTPLog            /var/log/proftpd/sftp.log
        Port               2220
        SFTPHostKey        /etc/ssh/ssh_host_rsa_key
        SFTPHostKey        /etc/ssh/ssh_host_dsa_key
        SFTPAuthMethods    password
        SFTPCompression    delayed
        MaxLoginAttempts   3
    </VirtualHost>
</IfModule>

After 10 minutes, the program exits and spits out this error:

Traceback (most recent call last):
  File "ftptest.py", line 9, in <module>
    f.write(content)
  File "/Library/Python/2.7/site-packages/paramiko/file.py", line 330, in write
    self._write_all(data)
  File "/Library/Python/2.7/site-packages/paramiko/file.py", line 447, in _write_all
    count = self._write(data)
  File "/Library/Python/2.7/site-packages/paramiko/sftp_file.py", line 176, in _write
    self._reqs.append(self.sftp._async_request(type(None), CMD_WRITE, self.handle, long(self._realpos), data[:chunk]))
  File "/Library/Python/2.7/site-packages/paramiko/sftp_client.py", line 668, in _async_request
    self._send_packet(t, msg)
  File "/Library/Python/2.7/site-packages/paramiko/sftp.py", line 170, in _send_packet
    self._write_all(out)
  File "/Library/Python/2.7/site-packages/paramiko/sftp.py", line 135, in _write_all
    raise EOFError()
EOFError

Using paramiko 1.15 and proftpd 1.3.5


Solution

  • The default window size of 4 GB was too big for paramiko, causing data transfer to stall.

    The issue was resolved by adding this to the proftpd SFTP configuration:
    SFTPClientMatch ".*" channelWindowSize 3999MB