Charles Buege, Guru

Setting up a Secured SFTP Server

Security is something that I am very interested in of late. While I have my other IT-based passions (VMware, Linux, Palo Alto firewalls), I realize more and more that to be able to do what you need, you MUST take security into account.

With that said, the other day at the Old Job, I was tasked with looking to replace our FTP site with something more secure. After some discussion, we decided on SFTP instead of FTPS. For those who don’t know the difference, SFTP is using an SSH session to perform a file transfer while FTPS is using the standard FTP protocol, but with a certificate on top of it. Since we didn’t want to purchase another certificate for this site, we decided to go with SFTP for our file transfer medium of choice.

After looking into it, I thought it was going to be nice and easy – setup a Linux box, use secure and complex IDs and passwords, and *POOF!* I’m done. Nope. Not even close. After thinking about it, I realized that with this methodology, I’d be exposing a server to the outside world with easy access to a shell prompt. Bad idea, dummie!! That was literally what I thought to myself. *laughs*

Anyway, I started looking into it and found a way to make the entire thing more secure and not to have to worry about this. Here are the set of steps that I used to create a secure (or so I think) SFTP site. I decided to make port 22 available to the outside world but only allow SFTP connections to that port. I also setup a port only accessible internally for administration of the server.

First off, I setup a clean server with CentOS 7. I use a minimal install of CentOS 7, set a static IP address, set the time zone, and then set the root password and my own ID and password with setting my ID as an ‘administrator’ (get added to the ‘wheel’ group). After that, I’ve got a standard script that I use after setting up the OS that I paste into a putty session to do the base configuration of the server. Here is the most basic one. I’ll post another article where I run through the different scripts I have and any I do what I do.

Switch to the ‘root’ ID before pasting these commands. Type in ‘sudo -s’, enter your ID’s password, and then paste away!

yum install nano wget epel-release -y
yum remove mysql* -y
yum remove mariadb* -y
sed -i 's~^%wheel.*~## %wheel ALL=(ALL) ALL~g' /etc/sudoers
sed -i 's~^# %wheel.*~%wheel ALL=(ALL) NOPASSWD: ALL~g' /etc/sudoers
echo ifconfig \| grep \"inet 10.\" \| awk \'{ print \"IP Address: \" \$2 }\' > /usr/local/bin/get-ip-address
chmod +x /usr/local/bin/get-ip-address
cp /etc/issue /etc/issue-backup
chmod +x /etc/rc.d/rc.local
echo cp /etc/issue-backup /etc/issue >> /etc/rc.d/rc.local
echo /usr/local/bin/get-ip-address \>\> /etc/issue >> /etc/rc.d/rc.local
echo echo \"\" \>\> /etc/issue >> /etc/rc.d/rc.local
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
yum update -y
init 6

After the reboot, I re-connect with putty and continue with the server configuration.

Since this is a server setup, I prefer to do a lot of my work directly from the ‘root’ ID instead of throwing ‘sudo’ in front of each command. So, after reconnecting, I issue the command ‘sudo -s’ to get to the root login.

To reiterate, the only thing that will be able do be done on port 22 will be SFTP. All IDs that I create will be limited to SFTP by the simple expedience of setting their login shell to ‘/sbin/nologin’. Even if they try to connect with putty, as soon as they connect they will be dropped. I will then setup a separate port number with another instance of sshd to allow SSH access to the server. I’ve even gone ahead and assigned a specific group as being the only ones that can connect via SFTP for further, more granular control. I know I could have setup SFTP for the different numbered port, but I choose to do it this way so that external customers who connect to the SFTP server don’t have to worry about specifying the port.

Setup Port 14384

Now, before we lock down port 22 to the settings we want, you want to be sure to leave yourself a door into the system to administer it. I choose the port number of 14384 just for the heck of it – no special meaning, no hidden code – just the first set of five numbers I typed in when deciding the port to use for this.

I start by working from the ‘root’ ID as mentioned previously using the command ‘sudo -s’. With the script above, I’ve changed the ‘wheel’ group to no longer require a password, so no prompt and I’m in as ‘root’.

Once in as root, I create the necessary group that I need for the administration of the server.

groupadd ssh-admin-users

I then open the port in firewalld for port 14384.

firewall-cmd --permanent --zone=public --port=14384/tcp
firewall-cmd --reload

NOTE: Now you may be asking yourself why, if I’m opening port 14384 through the firewall, why won’t that port be opened to the outside world as well. Well, since I am a VERY firm believer in the concept of layers of security, I then have an additional firewall beyond the SFTP server itself. That port, 22, will be the only one that will be opened through the hardware firewall, so port 14384 will only be accessible internally to the network. Back to setting up port 14384……

Next, we will go to the directory of /etc/ssh and make a copy of the sshd_config file.

cp /etc/ssh/sshd_config /etc/ssh/sshd_config_14384

Going into this file with your editor of choice, we will make the following changes:

  1. Change ‘Port’ to 14384 from 22
  2. Append the following line: AllowGroups ssh-admin-users

After saving and exiting the file, we will need to modify another file.

cp /etc/sysconfig/sshd /etc/sysconfig/sshd_14384

Again, pull this file up in an editor and append the following line to the end of the file:

OPTIONS="-f /etc/ssh/sshd_config_14384"

Lastly, we need to setup the service file so that we can have this daemon auto-start with the system boot.

cp /usr/lib/systemd/system/sshd.service /usr/lib/systemd/system/sshd_14384.service

Let’s make a change to this file and do the following:
– Change this line: EnvironmentFile=/etc/sysconfig/sshd
– To this line: EnvironmentFile=/etc/sysconfig/sshd_14384

After this, the service is ready to be enabled and started.

systemctl enable sshd_14384.service
systemctl start sshd_14384

And TA DA!! Port 14384 is ready for you to use.

Wait – it ISN’T ready for use yet? *grins* Yep – you’re right. We did miss one step – we haven’t added anyone to the ‘ssh-admin-users’ group yet so no one can use this port to connect. Go ahead and add anyone you want to use this port to the group and you will be good to go.

usermod -a -G ssh-admin-users [USERNAME]

NOW it’s ready to use!!

Lock Down Port 22

I’ll start by adding a group ‘sftpusers’.

groupadd sftpusers

After that, I’d want to start making modifications to sshd_config, but I want a copy of the original file.

cp /etc/ssh/sshd_config /root/sshd_config.orig

Next, I’m going to start modifying sshd_config. Load up the file in your editor of choice (I tend to use nano – quick, easy, don’t need a lot of the bells and whistles that vi/vim offer).

nano /etc/ssh/sshd_config

From here, I make the following modifications to the file:
– Comment out this line: Subsystem sftp /usr/local/libexec/sftp-server

– Add this line: Subsystem sftp internal-sftp

– Change this line: X11Forwarding yes
– To this line: X11Forwarding no

– Change this line: #PermitRootLogin yes
– To this line: PermitRootLogin no

– Append the following lines:
— AllowGroups sftpusers
— ChrootDirectory %h
— ForceCommand internal-sftp
— AllowTcpForwarding no

I’m not sure of the use of all of these commands. If anyone wants to comment on this post and add any notes as to what different uses are, please feel free. As for what I do know, I’ll add what documentation to these steps as I understand them.

X11Forwarding no – This will prevent the use of trying to use VNC over SSH on this port. I know plenty of people who have done VNC over SSH (I’ve dabbled in it myself), but this just give an added layer of protection.

PermitRootLogin no – I’d think that this is self-explanatory, but just in case it isn’t – it prevents the use of the ‘root’ login over this ssh daemon.

AllowGroups sftpusers – This will require that anyone connecting to this SSH connection as being a member of this group. I believe that the ‘wheel’ group is also auto-permitted in this statement as well, but I will be performing more testing to determine if this is the case or not.

ChrootDirectory %h – This directs you to the home directory (%h) of the user you are logging in as with root-level access to the folder. I’m really not sure why this is required – I’d personally rather just have the user connect to the site with their current credentials and then let them go gang-busters in the home directory, but this appears to be required, so the command is in there.

ForceCommand internal-sftp – This is another command that I am not clear on the need of. Any comments on this, please don’t hesitate to ask.

AllowTcpForwarding no – I understand that this is in addition to the locking down of the X11Forwarding command – to help prevent usage of the port to do anything other than SFTP.

After these changes are in place, restart the ssh daemon.

systemctl restart sshd

User Maintenance

Now that the server is setup, you’ll want to know how to configure each type of user (admin vs SFTP-only access). Here’s the template that I use for each type of user. Simply replace the ‘(username)’ with the actual username. Yes, this wasn’t clear to some people so I had to spell it out. *laughs*

Administrative User:

sudo useradd [USERNAME]
sudo passwd [USERNAME]
sudo usermod -a -G wheel [USERNAME]
sudo usermod -a -G ssh-admin-users [USERNAME]

In case any clarification was needed on these steps, what is happening is that the user is being added, a password is being set, the user is being added to the ‘wheel’ group so they have access to sudo without a password, and finally the user is being added to the ‘ssd-admin-users’ group so they can SSH into the server. Pretty straight forward.

SFTP User:

sudo useradd -g sftpusers -s /sbin/nologin [USERNAME]
sudo passwd [USERNAME]
sudo mkdir /home/[USERNAME]/transfer
sudo chown root:root /home/[USERNAME]
sudo chmod 755 /home/[USERNAME]
sudo chown [USERNAME]:sftpusers /home/[USERNAME]/transfer
sudo chmod 755 /home/[USERNAME]/transfer
sudo rm -rf /home/[USERNAME]/.ba*

Now this user type is a little more confusing, and to be frank I’m not clear on some of it, but it is what was necessary to make my project work.

First off, the user is created and added to the ‘sftpusers’ group right off of the bat. Additionally, their login shell is set to ‘/sbin/nologin’ so that even if they try to SSH into the server with proper credentials, as soon as they connect, they will be dropped. There is no shell for them to connect to, so no SSH access.

After the password is set, a ‘transfer’ directory is created for them in their home directory. I don’t understand why (I haven’t taken the time to learn this yet), but for whatever reason, the SFTP connection requires that ‘root’ owns the home directory of the user. But, since this is the ID I want them to use when logging into the system, I setup the ‘transfer’ directory so they could use that to send and receive files. So, I set the security and ownership of the home directory to ‘root’ and the security and ownership of the ‘transfer’ directory to that of the username. Lastly, I clear out all of the ‘.ba*’ files in the user’s home directory as to not confuse my users.

So, that’s my Secured SFTP server. I welcome anything that anyone has to say about it – recommendations, corrections, or details. Thank you, and have a great day!!

Sir Charles

Image Credit – Digital Blasphemy (

Leave a Reply

Your email address will not be published. Required fields are marked *