What's the point of the Internet if you can't share files with your friends? Maybe you want to host all those weird zines you picked up or that [Boot to Zork](http://www.codon.org.uk/~mjg59/uefi_zork/) code you downloaded a while ago. But running an unsecured, public FTPs is a [massive security risk](https://info.publicintelligence.net/FBI-PHI-FTP.pdf) so today I'll walk you through the set-up of a "secure" FTP implementation using VSFTPD (on Gentoo, but you could use any Linux in theory) with a rotating password. We will use a set of rotating, easily predictable passwords (this is the way it is implemented on [Raamen.org](https://raamen.org)) just for funsies; note that this is in no way a method of securing your server. For instance, suppose that method for generating these passwords leaks or one of your users tells a few other people who tell more people in-turn. Then your "secure" FTP is (nearly) as bad as an anonymous FTP. Anyway, let's continue with this scheme just for our pleasure. Down to the Basics ------------------ FTP (clarified in [RFC 959](https://tools.ietf.org/html/rfc959)) is a very old protocol for transferring large files between users. It's implemented over the TCP stack (as opposed to the UDP stack) and communicates in plaintext, with optional extensions on top of the protocol allowing for SSL/TLS. On Linux, the most widely-used FTP server is [VSFTPD](https://security.appspot.com/vsftpd.html); it has support for lots of features (many of these we will be taking advantage of) such as virtual users, read-only access, bandwidth throttling, and support for PAM authentication. Therefore you'll need to install VSFTPD before we begin: root # emerge vsftpd ... or use whatever package manager your distribution supports (e.g. `apt`, `yum`, etc. etc.) Next we will need to grab a copy of `pam_pwdfile.so`. This allows VSFTPD to read your rotating password root # git clone https://git.tiwe.de/libpam-pwdfile.git && cd libpam-pwdfile root # make && make install If all goes well then you should have a new file `/lib/security/pam_pwdfile.so` which is the PAM module which we will use to read from the rotating password file. Write a PAM rule for VSFTPD to use by putting the following in `/etc/pam.d/vsftpd`: auth required pam_pwdfile.so debug pwdfile=/etc/vsftpd/login.users account required pam_permit.so This tells PAM to read the file at `/etc/vsftpd/login.users` using the pwdfile module. The general format of this file will be: username:crypt()'d password ... on each line for each username that is allowed to login. Rotating Password Generation ---------------------------- This is pretty cool: the following code will generate our rotating password and place it in the VSFTPD file we specified: #!/bin/bash # Virtual user / password USER=loldongs # Day of the week, lowercase PASS=$(date +"%a" | tr '[:upper:]' '[:lower:]') hash=$(openssl passwd -1 $PASS) echo "$USER:$hash" > /etc/vsftpd/login.users Place this file at `/usr/local/bin/generate-new-ftp-creds`. This will allow users to log in with the username `loldongs` and the password as the (lowercase) day of the week. The idea here is to run this script as root every day via cron, as below: 0 5 * * * /usr/local/bin/generate-new-ftp-creds ... make sure this job is run as root, otherwise you will not be able to write to `/etc/vsftpd/login.users` (permission denied). Finally set up VSFTPD using the below file, making modifications to the configuration where necessary: # Shared directory local_root=/path/to/my/shared/directory # No anonymous users anonymous_enable=NO local_enable=YES chroot_local_user=YES # Port configuration connect_from_port_20=YES pasv_enable=Yes pasv_max_port=10100 pasv_min_port=10090 # Use our PAM module pam_service_name=vsftpd # Really irrelavent but kinda neat dirmessage_enable=YES xferlog_enable=YES listen=YES # Optional TLS configuration ( # listen_ipv6=YES # ssl_enable=YES # ssl_tlsv1=YES # ssl_sslv2=NO # ssl_sslv3=NO # rsa_cert_file=/etc/letsencrypt/live/my-domain/cert.pem # rsa_private_key_file=/etc/letsencrypt/live/my-domain/privkey.pem # force_local_logins_ssl=NO # force_local_data_ssl=NO # allow_anon_ssl=NO ... this will require ports 21, 20 and 10100~10090 forwarded from your router to the server, so do that now too. If you have an SSL cert (e.g. from LetsEncrypt) uncomment the last few lines; they will allow users to connect via either TLS or plaintext; if you would like to force users to use TLS then change `force_local_logins_ssl` and `force_local_data_ssl`. Running the server ------------------ Finally we can start the VSFTPD server by: root # rc-update add vsftpd default root # rc-service vsftpd start ... if you're on a systemd distribution then your command will look different (probably use systemctl). Now the server should be up and running and available on port 21, and you can test your install by FTP'ing in and using the credentials you set up above. In this tutorial the credentials would be: User: loldongs Password: Monday, Tuesday, Wednesday etc. etc. Happy file-sharing!