TFTP & FTP Server on Centos 7

If you ever needed a TFTP or an anonymous FTP server to transfer files, logs, or crash debugs to and from your network devices it can be a little tricky if you don't have anything setup. There are some free quick programs out there if you are in a pinch for one-time transfers but if you ever wanted to have something in infrastructure that is ready to go for this kind of stuff just follow this tutorial below.

I'm using the latest version of Centos 7 minimal, we need to add some house keeping items first so let's get started! Install NANO ( I like it, don't judge me!):

1yum install nano

Install Firewalld (Seems like Centos 7 1511 does not include it at least the minimal version)

1yum install firewalld

Enable firewalld to startup automatically when Centos boots up:

1systemctl enable firewalld

Start firewalld:

1systemctl start firewalld

This first part of this tutorial will go over installing TFTP followed by installing the FTP. If you want to skip TFTP installation, i.e you only need FTP, select the link: Install FTP Server on Centos

Add the TFTP rule to the Centos Firewall and reload it:

1firewall-cmd --permanent --zone=public --add-service=tftp
2firewall-cmd --reload

Install the TFTP server as well as the TFTP client just in case we want to test TFTP locally:

1yum install xinetd tftp-server tftp

Enable the TFTP program to startup automatically:

1systemctl enable xinetd tftp

Start the TFTP program now:

1systemctl start xinetd tftp

Since we have started the TFTP service let's focus on the configuration file and settings for it. We don't want this TFTP service to run has root, so let's create a system account for TFTP.

1useradd -s /bin/false -r tftp

This command basically creates a system account which cannot be used to access a shell a.k.a "login". Depending on how this system was installed your path may be different if you are expecting to store a lot of files. In this tutorial I'm going to be hosting these files under the /var folder. My full path is /var/FileServerRoot/TFTP The folder FileServerRoot is not created by default so I'll create the folder and put the correct permissions on this folder so that the TFTP system account can get access to it. Create the FileServerRoot Folder as well as a sub folder under it called TFTP:

1mkdir /var/FileServerRoot
2mkdir /var/FileServerRoot/TFTP

Apply ownership for the TFTP system account:

1chown tftp:tftp /var/FileServerRoot/TFTP/

Permissions should already be rwxr-xr-x for this directory. Next open up the configuration file for the TFTP server located at /etc/xinetd.d/tftp and following the example configuration file below:

 1nano /etc/xinetd.d/tftp
 2# default: off
 3# description: The tftp server serves files using the trivial file transfer \
 4#       protocol.  The tftp protocol is often used to boot diskless \
 5#       workstations, download configuration files to network-aware printers, \
 6#       and to start the installation process for some operating systems.
 7service tftp
 8{
 9        socket_type             = dgram
10        protocol                = udp
11        wait                    = yes
12        user                    = root
13        server                  = /usr/sbin/in.tftpd
14        server_args             = -c -s /var/FileServerRoot/TFTP -v -v -v -u tftp -p
15        disable                 = no
16        per_source              = 11
17        cps                     = 100 2
18        flags                   = IPv4
19}

If you are curious of what each server argument means you can take a look here at the man page for TFTP server. Restart both services for the TFTP server:

1systemctl restart xinetd tftp

So after that we have to run more command for SELinux to be happy and the best part is we DON'T turn it off! Right now we are able to download files from the TFTP server but we get a permission denied when we try to upload files. To fix that run this command:

1chcon -t tftpdir\_rw\_t /var/FileServerRoot/TFTP

We now have a functioning TFTP server, all files permissions in this folder should be no more than 664. Although it would work with full permissions TFTP isn't that secure to begin with, now onto installing the FTP server :)

Install FTP Server on Centos 7

Alight let's install the FTP server on Centos and include the FTP client just in case we want to test locally:

1yum install vsftpd ftp

Now let's start looking at the firewall settings, and configuration settings to make this FTP anonymous for both uploads and downloads. Add an FTP rule to firewall and reload it:

1firewall-cmd --permanent --zone=public --add-service=ftp
2firewall-cmd --reload

Enable the vsftpd to startup apon boot:

1systemctl enable vsftpd

Let's create the FTP folder and in this example its going to be under the FileServerRoot we created earlier with TFTP or if you skiped the TFTP installation just create a Root directory first followed by creating the FTP folder.

1mkdir /var/FileServerRoot
2mkdir /var/FileServerRoot/FTP

We have to change permissions on the FTP folder to the following:

1chmod 555 /var/FileServerRoot/FTP\

We are also going to make two more folders under the FTP folder called upload and download to keep things organized:

1mkdir /var/FileServerRoot/FTP/upload
2mkdir /var/FileServerRoot/FTP/download

Change ownership of these folder to the FTP account which is built in:

1chown ftp:ftp /var/FileServerRoot/FTP/upload
2chown ftp:ftp /var/FileServerRoot/FTP/download

Let's make a backup of the configuration file that runs FTP (Just in case)

1cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig

Open up the configuration file with nano at /etc/vsftpq/vsftpd.conf and make the following edits towards the top of the file:

 1# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
 2anonymous_enable=YES
 3#
 4# Uncomment this to allow local users to log in.
 5# When SELinux is enforcing check for SE bool ftp_home_dir
 6local_enable=NO
 7#
 8# Uncomment this to enable any form of FTP write command.
 9write_enable=YES
10#
11# Default umask for local users is 077. You may wish to change this to 022,
12# if your users expect that (022 is used by most other ftpd's)
13local_umask=022
14#
15# Uncomment this to allow the anonymous FTP user to upload files. This only
16# has an effect if the above global write enable is activated. Also, you will
17# obviously need to create a directory writable by the FTP user.
18# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access
19anon_upload_enable=YES
20#

At the end of file put the following:

 1# Point users at the Public directory
 2anon_root=/var/FileServerRoot/FTP/
 3#
 4# Stop prompting for a password on the command line.
 5no_anon_password=YES
 6#
 7# Show the user and group as ftp:ftp, regardless of the owner.
 8hide_ids=YES
 9#
10# Limit the range of ports that can be used for passive FTP
11pasv_min_port=40000
12pasv_max_port=50000

We are almost done we have to make some changes to SELinux before we are good to go. We have to install Policy Core Utils:

1yum install policycoreutils-python

We are now making changes to SELinux to allow anonymous downloads:

1semanage fcontext -a -t public\_content\_t "/var/FileServerRoot/FTP(/.\*)?"

Next command to run:

1restorecon -R -v /var/FileServerRoot/FTP

-Output -

1restorecon reset /var/FileServerRoot/FTP context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:public_content_t:s0
2restorecon reset /var/FileServerRoot/FTP/upload context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:public_content_t:s0
3restorecon reset /var/FileServerRoot/FTP/download context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:public_content_t:s0

Now let's make changes to SELinux to allow anonymous uploads:

1semanage fcontext -a -t public\_content\_rw\_t "/var/FileServerRoot/FTP/upload(/.\*)?"

Next command to run:

1restorecon -R -v /var/FileServerRoot/FTP/upload

-Output -

1restorecon reset /var/FileServerRoot/FTP/upload context unconfined_u:object_r:public_content_t:s0->unconfined_u:object_r:public_content_rw_t:s0

One more command to run:

1semanage boolean -m --on allow\_ftpd\_anon\_write\

That should be it! Let's restart the server to make sure everything comes back online including the TFTP part that we finished earlier.

1shutdown -r now

If you have a TFTP and FTP client go ahead and test it out when the server reboots. If you run into some issues some troubleshooting tips are:

  • Check SELinux, if you are getting file permissions errors when uploading or downloading and permissions look this is likely SELinuix. It it can be a little picky which is why you'll read a lot of people just disable it. You can disable SELinux Temporarily (Turns back on when you reboot) to check if TFTP or FTP works by running
1setenforce 0
  • If you are having problems with anonymous FTP, like downloading or uploading check security context by running:
1ls -Z
  • For FTP to work the context output should like something below:
1[root@localhost ~]# ls -Z /var/FileServerRoot/FTP/
2drwxr-xr-x. ftp ftp unconfined_u:object_r:public_content_t:s0 download
3drwxr-xr-x. ftp ftp unconfined_u:object_r:public_content_rw_t:s0 upload
4[root@localhost ~]#

Keep in mind we just created a system that is open to any TFTP and FTP connection. Reads and writes are anonymous so if there is a need to control what/who can access your server over your network/internet its recommended to in put ACLs in place to block unwanted connections. Otherwise you might be on list like this one, in which the entire IPv4 address space was scanned to find what responds anonymously on TCP port 21. That's all I got for now, as always I hope this information helpful!