ftplib and pyftpdlib communication

Asked

Viewed 403 times

3

I have a server (Fedora 29) at home running (as root) an ftp done in python with the ports 5000-5003 and 40000-50000 open, the machine is in DMZ

import logging
import sys

from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
from pyftpdlib.authorizers import UnixAuthorizer
from pyftpdlib.filesystems import UnixFilesystem

def main():
     logger = logging.getLogger()
     ch = logging.StreamHandler(sys.stdout)
     logger.setLevel(logging.DEBUG)
     ch.setLevel(logging.DEBUG)
     formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
     ch.setFormatter(formatter)
     logger.addHandler(ch)

     authorizer = UnixAuthorizer(allowed_users=['marcelo'], require_valid_shell=True, global_perm='elradfmwMT')
     handler = FTPHandler
     handler.authorizer = authorizer
     handler.abstracted_fs = UnixFilesystem
     handler.passive_ports = (40000, 50000)

     handler.log_prefix = '%(username)s@%(remote_ip)s'

     server = FTPServer(('',5001), handler)
     server.serve_forever()

     if __name__ == '__main__':
         main()

At work I am like a machine (Fedora 29) with the doors 5000-5003/tcp and 40000-50000/tcp open and in DMZ running a client ftplib.

from ftplib import FTP

ftp = FTP('')
ftp.connect('*****',5001)
ftp.login(user='****',passwd='*****')
ftp.set_debuglevel(2)
ftp.set_pasv(False)
#ftp.cwd('/home/marcelo')
response = ftp.retrlines('LIST')
print("response: %s",response)


def uploadFile():
  filename = 'arquivo5.txt'
  ftp.storbinary('STOR '+filename, open(filename,'rb'))



def downloadFile():
  filename = 'backup.dmp'
  localfile = open(filename, 'wb')
  ftp.retrbinary('RETR '+filename, localfile.write, 2048)
  localfile.close()

#uploadFile()
#downloadFile()

ftp.quit()

In the client I receive the following reply: ftplib.error_perm: 501 Rejected data Connection to Foreign address 192.168.0.9:47123.

And on the server: pyftpdlib - WARNING - Imprint@... -> 501 Rejected data Connection to Foreign address 192.168.0.9:47123.

Note: astericas are my public ip Obs2: In the browser works perfectly

I believe the problem is the type C address I’m sending to the server but I don’t know how to fix it.

thank you.

  • You tested the connection by running the client and server on the same machine?

1 answer

1


Look at - I can understand where the problem is, but I don’t know how to give you the solution.

In the FTP protocol, and other protocols on TCP (such as HTTP itself), when the first connection is made to the server -the one that is listening on port 5001, the server transfers this connection to another high random port. So the server can hear port 5001 again waiting for new connections. (in the case of your messages port 47123 is the high port - it can vary between different attempts as it is basically drawn).

And what’s going on there, based on your error messages is that by switching the connection to this FTP "data" connection, the server is passing its local IP - 192.168.0.5, not the public IP (which you’ve masked). Unfortunately I don’t know enough TCP to know the correct way the FTP server should use to switch the connection to another port. At first glance I would say that the FTP server is doing right and this is a problem in its network rules: they do not know that when receiving the package containing the FTP data to change the connection to another port have to "translate" the IP from the internal IP to the public IP.

In short, to make it work as it is you will have to understand how it works this change of connection to high port, at the low level of the FTP protocol, and which component should be responsible for translating the internal IP to the public IP there.

Solution 1: Discard server code and use SFTP

The recommendation however it is not let so for some other reasons: when creating an FTP server you are reinventing the wheel, and it is not an easy wheel in particular. The FTP protocol is one of the oldest on the internet, and over 3 or decades was one of the most vulnerable, with good network engineers taking 15, 20 years to finally have FTP servers without security flaw in your code.

The Python library you are using surely already incorporates many of the fixes found at that time, but possibly there are other problems at the higher level of the protocol that would be the responsibility of the server implementer fix. As examples of the two situations - (1) the library has this object "Authorizer" there that already takes the password inside the FTP package and uses direct Posix authentication mechanisms, instead of something "handmade" with a local password. And (2) you turn on the server in the filesystem without checking anything, and without giving a "Starting point" directory: probably (I didn’t read the pyftplib doc) exposes your filesystem whole, including folders /var and /etc for FTP, and all user files (including program codes, conditioning files with secret production keys, all ).

Another thing: even if you make a really safe FTP server, and with all the right network settings: Procolo FTP is insecure by nature, why login credentials traffic on the internet without any encryption. This implies that an attacker who has access to any router, or other point in the route of your data can capture the password.

So - since you are not doing anything very special on the FTP server, it is better to leave an already consolidated server to serve - and, even more, use the protoclo SFTP - that traffic the FTP data through an SSH tunnel and end the encryption problems.

Climbing an SFTP server is a matter of two configuration lines in the Openssh configuration - if you want to limit the only sftp access to the "Passover" user, and keep SSH for other users, you’ll need to set up more things - otherwise that’s it. The client code (if using the FTP protocol correctly) remains exactly the same, but now with access through the SSH tunnel.

In the case of Folder including sftp is already enabled by default in the file /etc/ssh/sshd_config - is just a matter of reading the documentation to set the ports and user restrictions (and, preferably, which part of the filesystem grant access).

another solution, using your server code:

An alternative to SFTP if you really want to customize the access cm an own server is to use SSH then to create an SSH tunnel to connect the client to the server - this will also make the server work well without worrying about IP, and it will solve the problem of open traffic data on the Internet. (even if the client is a Windows machine, the good old "Putty" can open the necessary SSH tunnel)

Whatever your option, I think you’re gonna need it here:

https://www.openssh.com/manual.html

  • Thank you very much for that enlightening reply. I am creating FTP in python because I would integrate it into an automatic remote backup routine, I am aware of the vulnerabilities of FTP so the FTP server would be raised only at the programmed time and shut down when the process was finished. But as you said I’m really reinvented the wheel. I can do otherwise.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.