A firewall or packet filter is an important security tool for your headless Linux server. This article will give you the framework for easily setting up a firewall on your server that will ensure incoming connections only access allowed ports and completely ignore unwanted requests.
The first time you try this will take more than five minutes. The idea is that once you have done it a couple of times you can quickly spin up a new server and setup a firewall that is reproducible and exactly to your specifications.
The instructions apply to Debian based systems and their derivitaves. In this install I will be using the following;
Your donations keep this site ad free -- Thank You
The Setup
These instructions simulate the creation of a firewall for a brand new Minecraft Server. It's the same process if you're setting it up for web servers, DNS or email servers. The only difference is the ports that you make available to the world.
This firewall setup will filter all incoming requests by default and open the following ports only;
The steps to do this will be as follows;
/etc/network
First thing to do is check that your iptables packet filter is ready to go. It is installed by default on Ubuntu. The following command shows that the default iptables setup is wide open. We are accepting all connections to every port. Thankfully, on a new install most ports except 22(ssh) are closed.
al@sandbox:~$ sudo iptables -nL Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destinationLet's get the rules in place and get iptables filtering incoming traffic before anything else.
In our scenario we want to create a firewall script that will do the following;
Let's create the scripts.
cd /etc/network sudo touch firewall firewall-down firewall-reload
Lock down the permissions so that only root can open and view the files.
sudo chmod 700 firewall firewall-down firewall-reloadThe first script will create, activate and output your rules to your console
Script 1 Firewall
a) open the /etc/network/firewall
file
cd /etc/network sudo nano firewallCopy the following script into nano with copy/paste and save your changes. This is our main firewall script that will activate the rules we wish to enforce.
#!/bin/bash # # iptables example configuration script # Drop ICMP echo-request messages sent to broadcast or multicast addresses echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Drop source routed packets echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route # Enable TCP SYN cookie protection from SYN floods echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Don't accept ICMP redirect messages echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects # Don't send ICMP redirect messages echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects # Enable source address spoofing protection echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter # Log packets with impossible source addresses echo 1 > /proc/sys/net/ipv4/conf/all/log_martians # Flush all chains /sbin/iptables --flush # Allow unlimited traffic on the loopback interface /sbin/iptables -A INPUT -i lo -j ACCEPT /sbin/iptables -A OUTPUT -o lo -j ACCEPT # Set default policies /sbin/iptables --policy INPUT DROP /sbin/iptables --policy OUTPUT DROP /sbin/iptables --policy FORWARD DROP # Previously initiated and accepted exchanges bypass rule checking # Allow unlimited outbound traffic /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT /sbin/iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT #Ratelimit SSH for attack protection /sbin/iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP /sbin/iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set /sbin/iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT # Allow certain ports to be accessible from the outside /sbin/iptables -A INPUT -p tcp --dport 25565 -m state --state NEW -j ACCEPT #Minecraft /sbin/iptables -A INPUT -p tcp --dport 8123 -m state --state NEW -j ACCEPT #Dynmap plugin # Other rules for future use if needed. Uncomment to activate # /sbin/iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT # http # /sbin/iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT # https # UDP packet rule. This is just a random udp packet rule as an example only # /sbin/iptables -A INPUT -p udp --dport 5021 -m state --state NEW -j ACCEPT # Allow pinging of your server /sbin/iptables -A INPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT # Drop all other traffic /sbin/iptables -A INPUT -j DROP # print the activated rules to the console when script is completed /sbin/iptables -nLEngage the firewall;
sudo /etc/network/firewallTake time to go through each line in your firewall script to better understand what it is actually doing. The lines that start with # are commented lines that give you some hints.
Script 2 firewall-down. This script will flush(wipe) the rules you put in place if needed.
b) open /etc/network/firewall-down
file
sudo nano firewall-downCopy the following script into nano with copy/paste and save your changes.
#!/bin/bash /sbin/iptables -F /sbin/iptables -X /sbin/iptables -t nat -F /sbin/iptables -t nat -X /sbin/iptables -t mangle -F /sbin/iptables -t mangle -X # the rules allow us to reconnect by opening up all traffic. /sbin/iptables -P INPUT ACCEPT /sbin/iptables -P FORWARD ACCEPT /sbin/iptables -P OUTPUT ACCEPT # print out all rules to the console after running this file. /sbin/iptables -nLScript 3 firewall-reload. If you want to change your script rules you can modify the firewall script and then run this one. It will flush the rules and reload your changes. It will only do so until the next reboot. We will discuss making the rules permanent in the next section.
c) open /etc/network/firewall-reload
file
sudo nano firewall-reloadCopy the following script into nano with copy/paste and save your changes.
#!/bin/bash /etc/network/firewall-down /etc/network/firewallReload your firewall script;
sudo /etc/network/firewall-reload
We want our firewall to activate when the system boots up, preferably before the network interface is activated. To do this use the netfilter-persistent and iptables-persistent package available in the Ubuntu repositories. It can be installed with apt as follows;
sudo apt install iptables-persistentThis will install the iptables-persistent and netfilter-persistent applications.
Say yes to Save current Ipv6 rules in the next screen as well.
Once complete the netfilter-persistent script will be installed to /etc/init.d
which will allow you to start, stop, flush and save your firewall rules.
To see the options available type the following
sudo /etc/init.d/netfilter-persistentYou will see the following message.
Usage: /etc/init.d/netfilter-persistent {start|restart|reload|force-reload|save|flush}Let's start by saving our rules so that they are engaged when the system boots up.
sudo /etc/init.d/netfilter-persistent saveTest the other options for flushing and reloading with netfilter-persistent. Now everytime you modify your rules in
/etc/network/firewall
and run /etc/network/firewall-reload
, make sure
you save them permanently with netfilter-persistent save
.
al@sandbox:/etc$ sudo iptables -nL Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 4 name: DEFAULT side: source mask: 255.255.255.255 tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:25565 state NEW ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8123 state NEW ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8 state NEW,RELATED,ESTABLISHED DROP all -- 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state NEW,RELATED,ESTABLISHED
Your comments are welcomed, if you see any errors in this guide please feel free to contact me directly. Your feedback is appreciated and I will post any good questions and answers here for others to see.