Setting up an FTP server on a CentOS 7 system

You can install the vsftpd package to provide FTP server service on a CentOS 7 system by logging into the root account and issuing the command yum install vsftpd. You can then start the service with service vsftpd start and verify that it is running and the system is listening for FTP connections with netstat -a | grep "ftp" | grep "LISTEN".

# service vsftpd start
Redirecting to /bin/systemctl start  vsftpd.service
# netstat -a | grep "ftp" | grep "LISTEN"
tcp6       0      0 [::]:ftp                [::]:*                  LISTEN

But, before you start the software or before you allow outside access to the FTP server through the firewall, you might want to edit the configuration file for the FTP server software, which can be found at /etc/vsftpd/vsftpd.conf. Note: I recommend making a backup copy should you have problems after modifying settings and wish to go back to the original settings.

E.g., FTP server software can allow anonymous logins, so that someone connecting via FTP does not need to provide a userid and password for a user account on the system. In the configuration file you will see the following:

# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=YES

If you don't want to allow anonymous logins, change the "Yes" to "No". If you allow anonymous logins, the person logging in anonymously will be restricted to /var/ftp where there is a pub directory that he or she can access. By default, write access is disallowed, so the person can only retrieve files, but not upload them.

Local accounts on the system can be used to login; if you don't want to allow that, e.g., you only want to allow anonymous logins, change the "Yes" in the section below to "No":

# Uncomment this to allow local users to log in.
# When SELinux is enforcing check for SE bool ftp_home_dir
local_enable=YES

If you want to give anonymous users the privilege of uploading files to the server, remove the "#" from the beginning of the #anon_upload_enable=YES line.

# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access
#anon_upload_enable=YES

Make sure the global write enable is activated by looking for the lines below. Ensure there is no "#" before write_enable=YES and that the value is "YES" rather than "NO".

# Uncomment this to enable any form of FTP write command.
write_enable=YES

Also remove the "#" from the beginning of the line below, if you wish to allow anonymous users the capability to create subdirectories within the directory where you've granted them write access.

#anon_mkdir_write_enable=YES

So, to allow anonymous users write access and the ability to create subdirectories, all of the following should be set to "YES". By default, all are set, but the last two.

anonymous_enable=YES
write_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES

If you are using SELinux, see the comment above regarding allow_ftpd_full_access.

You will also need to allow write access to whatever directory you wish anonymous users to be able to place uploaded files. Suppose I want to create a directory within /var/ftp/pub specifically for uploaded files and that is the only directory where I want to grant anonymous users write access. I could use the following commands:

# mkdir /var/ftp/pub/uploads
# chown ftp /var/ftp/pub/uploads

I changed the owner of the /var/ftp/pub/uploads directory I created to ftp since that is the account under which the FTP service runs, so by changing the owner, I am granting write access to the directory for anonymous users.

When you install vsftpd, an FTP account is created, which you can see by checking the etc/passwd file.

# grep ftp /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

When the the /var/ftp directory and /var/ftp/pub directory beneath it are created, they are owned by root and only root has write access. Others have only read access and execute/search access, which allows them to see the files in a directory.

# ls -ld /var/ftp
drwxr-xr-x. 3 root root 16 Jun 27 21:41 /var/ftp
# ls -ld /var/ftp/pub
drwxr-xr-x. 2 root root 21 Jun 28 16:26 /var/ftp/pub

By changing ownership of the uploads directory to the ftp account with the chown command in the step above, someone logging in anonymously will now be able to upload files to that directory.

$ ls -ld /var/ftp/pub/uploads
drwxr-xr-x. 2 ftp root 6 Jun 30 21:48 /var/ftp/pub/uploads

You could remove read access, if you didn't wish to allow an anonymous user to see the files others have uploaded. Write access would also allow an anonymous user to delete files in the uploads directory, so you could block the ability to see file names by removing read access with chmod u-r /var/ftp/pub/uploads.

# chmod u-r /var/ftp/pub/uploads
# ls -ld /var/ftp/pub/uploads
d-wxr-xr-x. 2 ftp root 30 Jun 30 22:40 /var/ftp/pub/uploads

Anonymous users could then upload files to the directory, but dir and ls commands they might issue from their FTP clients would not result in any of the files in the directory being shown, though they could see files in the /var/ftp/pub directory above the uploads directory. In addition to not being able to see files in the uploads directory, they won't be able to delete them either with delete * or even by specifying a known file name, such as the filename for a file that they have uploaded.

By default, the files uploaded to the directory will have the permissions shown below:

# ls -l /var/ftp/pub/uploads
total 8
-rw-------. 1 ftp ftp 3230 Jun 30 22:40 example.png
-rw-------. 1 ftp ftp 3308 Jun 30 23:15 urls.txt

Take a look at the other settings in the vsftpd.conf file and customize the configuration to match your preferences, if you don't want all of the default settings.

If you made changes to the configuration file after you started the FTP service, restart it with systemctl restart vsftpd to have the modifications you made take effect. You can also use the command to start the FTP service, if you haven't yet started it.

# systemctl restart vsftpd
#

That starts the FTP server software, but doesn't configure the system to start it automatically when the system reboots as you can see by issuing the systemctl list-unit-files command.

CentOS 7 System Engineer Complete Course
CentOS 7 System Engineer
Complete Course
1x1 px

# systemctl list-unit-files | grep vsftpd
vsftpd.service                              disabled
vsftpd@.service                             disabled
vsftpd.target                               disabled

You can also check the status of the service with systemctl status vsftpd

# systemctl status vsftpd
vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; disabled)
   Active: active (running) since Sat 2015-06-27 22:22:32 EDT; 3min 9s ago
  Process: 7567 ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf (code=exited, status=0/SUCCESS)
 Main PID: 7568 (vsftpd)
   CGroup: /system.slice/vsftpd.service
           +-7568 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf

Jun 27 22:22:32 localhost.localdomain systemd[1]: Started Vsftpd ftp daemon.

The above output shows that the service is running, but is disabled, so it will not start again automatically if the system is rebooted. You can get it to start automatically at boot time with systemctl enable vsftpd.

# systemctl enable vsftpd
ln -s '/usr/lib/systemd/system/vsftpd.service' '/etc/systemd/system/multi-user.target.wants/vsftpd.service'
# systemctl list-unit-files | grep vsftpd
vsfptd.service                              enabled
vsfptd@.service                             disabled
vsfptd.target                               disabled
# systemctl status vsftpd
vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; enabled)
   Active: active (running) since Sat 2015-06-27 22:22:32 EDT; 8min ago
 Main PID: 7568 (vsftpd)
   CGroup: /system.slice/vsftpd.service
           +-7568 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf

Jun 27 22:22:32 localhost.localdomain systemd[1]: Started Vsftpd ftp daemon.

If you issue the service vsftpd status command after the systemctl enable vsftpd cammand and see that the status that appears after "Active:" is "inactive (dead)", then issue the service vsftpd start command to start it. You would see that status if you hadn't yet initiated the service with a systemctl restart vsftpd or prior systemctl start vsftpd command.

# systemctl enable vsftpd
Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.
# service vsftpd status
Redirecting to /bin/systemctl status  vsftpd.service
● vsftpd.service - Vsftpd ftp daemon
   Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
# service vsftpd start
Redirecting to /bin/systemctl start  vsftpd.service
# systemctl list-unit-files | grep vsftpd
vsftpd.service                              enabled 
vsftpd@.service                             disabled
vsftpd.target                               disabled
#

You also need to configure the firewall software on the system to allow FTP connections from external systems. The default firewall software for CentOS 7 is no longer iptables, but is firewalld, which can be configured from a shell prompt with firewall-cmd. You can determine if firewalld is running using the command firewall-cmd --list-services; if it isn't running you will see the message below:

# firewall-cmd --list-services
FirewallD is not running

You can use firewall-cmd --permanent --add-service=ftp to allow inbound connectivity to the default FTP port of TCP port 21. When you want a permanent rule, you need to restart the firewall software after adding the rule with firewall-cmd --reload. You can verify the service is allowed with firewall-cmd --list-services.

# firewall-cmd --add-service=ftp --permanent
success
# firewall-cmd --reload
success
# firewall-cmd --list-services
dhcpv6-client ftp http pop3s smtp ssh

If you only wanted to create a temporary rule allowing FTP that will disappear if the firewall software is restarted or you reboot the system, you could omit the --permanent.

# firewall-cmd --add-service=ftp
success

Bear in mind that FTP uses two ports, ports 20 and 21 on the server, unless it is put in "passive" mode. An FTP client connects to the FTP server on TCP port 21 on the server for command and control. That is the port used to login to the FTP server. But data is passed back from the server is response to commands such as ls, dir, etc. from port 20 on the server to a port on the client specified by the client. E.g., if the client connected to port 21 on the server with a source port of 30000, it will tell the server to send data back from port 20 on the server to port 30001 on the client side. If there is a firewall at the client side or the system on which the FTP client is running is using host-based software, that connectivity will not work unless there is a firewall rule on the client side as well. If there is a firewall or router with firewall capabilities in front of the host running the FTP client software and the FTP client system is also running host-based firewall software, an appropriate firewall rule will need to be set in both. And if the router in front of the host is performing network address translation (NAT), such as most home routers do, then port forwaring may need to be set for the FTP connectivity to work.

There is a solution for this problem where firewall rules are only needed at the server end. The solution is "passive FTP" (see Active FTP vs. Passive FTP), a Definitive Explanation. But not all FTP clients support passive FTP, The command line FTP client included with the Microsoft Windows operating system does not support passive FTP. You may see some sites stating it does, because you can issue commands, such as "quote pasv" or "literal pasv" in the Windows FTP client, but though they get sent to the server, the Windows FTP client does not actually switch to passive mode, so such commands are effectively useless to address the problem. For Microsoft Windows systems, if you use an FTP client, such as WinSCP, which also supports SFTP, it will work automatically, so you don't need to worry about that issue at the client end. So, if someone using a Microsoft Windows system says he can't connect to the FTP server, make sure he isn't using the Microsoft Windows FTP client.

If you wish to test whether the system is or verify it is not accessible from a host out on the Internet, you can use the Online FTP tester site. It allows you to specify the login port (the default value is 21), and a username (the default value is anonymous), password (for an anonymous login the convention is to provide your email address, though you can put in anything), and the protocol with the choices being "Explicit FTP over TLS" or "Implicit FTP over TLS" for FTPS transfers, or "Plain FTP (insecure)", where the username, password, and any commands and data are transferred in plaintext format, i.e, in unencrypted form.