I’m working on a home server what will be my router, gateway and firewall as well. After the system and daemon installation I have to make the whole system secure. I achieve that with multiple steps, here is a short description how to implement it.

1.) Securing SSH

Later, on the firewall all SSH traffic will be enabled from everywhere. But we have to protect our server, so I made a few changes in the /etc/ssh/sshd_config:

PermitRootLogin no
PermitEmptyPasswords no
AllowGroups ssh-group

The most of the attacks are simple brute force attacks. In the most of the cases, the hackers want to log in with root user. So let’s disable root login.

For the same reason we disable Empty password logins.
Then we should create a group expressly for the SSH, and add the relevant users to it. After that we should limit the SSH access only for this group.

Then to limit the login tries, let’s install fail2ban daemon

apt-get install fail2ban

Then check the config file. It should looks like this:

FILE: /etc/fail2ban/fail2ban.conf

loglevel = 3
logtarget = /var/log/fail2ban.log
socket = /var/run/fail2ban/fail2ban.sock

Modify the /etc/fail2ban/jail.conf file. If a user fail the auth within 3 hours, then he will be blocked out for a month:

bantime  = 2678400
maxretry = 5
findtime = 10800

Then restart the daemon:

service fail2ban restart

And if it’s working correctly, then you will see the fail2ban chain in the end of your iptables:

 # iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
Chain fail2ban-ssh (1 references)
target     prot opt source               destination
DROP       all  --       anywhere
DROP       all  --        anywhere

Additional step:

Set up Google authenticator:

With that we can make 3 way authentication.

apt-get install libpam-google-authenticator

Log in as a user and run “google-authenticator” command to generate the key for this user.

During the key generation type “y” and increase the key availability time.

If the key installed, this will be prompted, together with the scratch keys. Please note these keys to a safe place. In case you loose your phone, or any issue happen, you can use these keys for authentication.

Then open the Google authenticator app on your phone, and type the secret key.
Now you get a constantly changing verification code on your phone.

Last step is to activate the authenticator.

Edit the file /etc/pam.d/sshd:

auth required pam_google_authenticator.so

Add the authenticator to /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes

Finally restart the SSH daemon, and enjoy your new feature.


2. Firewall setup

Strongly recommended to modify the default iptables rules in our system, because it enables everything!

Iptables setup depends on the daemons/services we are running on the server, but I’ve created an example file with some basic services.

Let’s save it to /etc/firewall.rules file:


# Default policies

# Allow connection to/from Loopback interface
 -A INPUT -i lo -p all -j ACCEPT
 -A OUTPUT -o lo -p all -j ACCEPT

# Deny all connections from non-trusted networks, enable only our private IP range
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP
 -A INPUT -s -j DROP

# Allow HTTP and HTTPS connections globally
 -A INPUT -p tcp --dport 80 -j ACCEPT
 -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow all established inbound connections globally

# Allow SSH incoming connections globally
 -A INPUT -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# Allow Samba ports only from the local LAN
 -A INPUT -s -p udp -m udp --dport 137 -j ACCEPT
 -A INPUT -s -p udp -m udp --dport 138 -j ACCEPT
 -A INPUT -s -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT
 -A INPUT -s -m state --state NEW -m tcp -p tcp --dport 445 -j ACCEPT

# Allow minidlna only from the local LAN
 -A INPUT -s -p udp --dport 1900 -j ACCEPT
 -A INPUT -s -p tcp --dport 8200 -j ACCEPT

# Allow ping only from the local LAN
 -A INPUT -s -p icmp -m icmp --icmp-type 8 -j ACCEPT


First, the default rule is deny incoming, but we enable everything to go out. Packet forwarding has denied as well.

Then let’s activate our brand new firewall rules:

iptables-restore < /etc/firewall.rules

Please check if all services are working fine! If yes, then make the firewall permanent:

vi /etc/network/if-pre-up.d/firewall

iptables-restore < /etc/firewall.rules

Save and exit. Test if the firewall is working after a reboot.

iptables -nL


3. Limit user access

We would like to limit the simple user accesses to a few simple commands.
For that I’ll use “rbash” restricted shell. It’s easy to set up:

cd /bin
ln -s bash rbash

Create a directory where you will paste the allowed commands:

mkdir /var/limited-commands
chown root  /var/limited-commands
chmod 755 /var/limited-commands

Link the ping command to this folder:

ln -s /bin/ping  /var/limited-commands
chown root /var/limited-commands/ping
chmod 755 /var/limited-commands/ping

Then add the following line to .profile, and .bashrc of the user:


Finally limit the access to these files:

chown root /home/$User/.profile
chown root /home/$User/.bashrc
chmod 755 /home/$User/.profile
chmod 755 /home/$User/.bashr

As a last step deny/allow the crontab access to this user. Create the /etc/cron.d/cron.allow file and add all users which you would like to allow to access to the cronjob:


For other users won’t be allowed to use the crontab.