Proftpd setup on Fedora 19
Wednesday, June 5. 2013
I needed to transfer really big files (10+ GiB) between couple of servers. Since I was not in a hurry I decided to go with FTP. It performs very well when doing large file transfers, see File Transfer Protocol Performance Study for EUMETSAT Meteorological Data Distribution by students of Institute of Mathematics and Computer Science University of Latvia. Only Rsync could do better, and that is when the target is to transfer large number of files instead of small number of large files. In reality all the time it took me to set up the servers, I'd done transferring my files with any protocol. Really, any. But since I'm expecting to need this setup sometimes later, I went ahead with it.
Anyway, I chose to go with FTPd and since my Fedora 19 beta has one in built in repo, I went with Proftpd. Initial problems:
- It didn't work well (read: not even the simplest things you'd expect work) with IPv6, it took me 3 hours to figure this out.
Fix: I used IPv4 addresses instead of FQDNs. Everything started to work. - No anonymous FTP-access
- No anonymous FTP uploads
IPv6-issues
There is plenty of code like this:
pr_log_debug(DEBUG0,
"Unable to handle PASV for IPv6 address '%s', rejecting command",
pr_netaddr_get_ipstr(session.c->local_addr));
pr_response_add_err(R_501, "%s: %s", cmd->argv[0], strerror(xerrno));
So after I found about that, I just stopped using it.
Anonymous FTP-access
FTP isn't a secure protocol. It was once by 80s standards, but in 2013 Internet... well, no. So the best bet is not to use security at all! I'll place my security on the firewall, use anonymous logins and reduce attack surface by shutting the daemon down when I'm not expecting to need it.
Getting the anonymous FTP to work turned out to be semi-tricky. The daemon needs a -DANONYMOUS_FTP in the sysconfig. Also I needed to re-direct the anonymous FTP root directory into a dedicated partition instead of the out-of-the-box /var/ftp. My enforcing SElinux didn't like that. I had appropriate owner and group setup for the directories and files, but it turned out that my mount-directory had weird SElinux type and I decided to go with pretty generic var_t as directory type, then anonymous user was able to log in. The next thing was to make sure that actual FTP-stuff had SElinux type of public_content_t for access to directories and files to work. The final thing was to convince my SElinux to allow using of appropriate TCP-ports for FTPd:
setsebool -P ftpd_connect_all_unreserved=1
After that I had somewhat working anonymous FTP box.
Passive FTP from Windows
I didn't have any fancy software for testing the client side. All I had was a trustworthy ftp.exe on a Windows PowerShell. However, it operated only on active-FTP -mode, which in my opinion is completely obsoleted. It simply does not work at all with proper firewall setup, so I'd better using passive-FTP -mode. Well, then... how to lure the ancient FTP-client to use it? It wasn't obvious or easy, but luckily somebody else had the same problem and solved it. The solution is to use QUOTE-command for passing the FTP-protocol required PASV, like this:
Connected to 192.168.0.1.
220 FTP Server ready.
User (192.168.0.1:(none)): ftp
331 Anonymous login ok, send your complete email address as your password
Password:
230-
*** Welcome to this anonymous ftp server! ***
You are user 1 out of a maximum of 10 authorized anonymous logins.
The current time here is Wed Jun 05 15:25:31 2013.
If you experience any problems here, contact : root@localhost
230 Anonymous login ok, restrictions apply.
ftp> quote pasv
227 Entering Passive Mode (192,168,0,1,236,242).
That made passive mode work ok.
Allowing anonymous uploads
The last bit was trickiest, it was almost impossible to give Proftpd what it wanted. To my surprise it wasn't about directory permissions or SElinux. It was simply about configuration issue with <Limit> acting stupidly. Out-of-the-box, the config file apparently allows anonymous uploads. The problem is that it doesn't work. There is a line like this:
<Directory uploads/*>
But it should be like this:
<Directory /uploads>
I don't know why it must be like that, but after tinkering it for a very long time, that turned to be the key to my success. I also changed a <Limit READ> into <Limit LIST READ> to prevent getting directory listings from uploads-directory.
That concluded my setup. Just opening suitable IP-addressses and TCP-ports 20 and 21 made my files fly.