firewall top image

The Linux Five Minute Firewall

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;

  • Ubuntu Server 18.04 LTS version. (Note: These instructions also work on the latest version of Debian Bullseye)
  • Iptables/Netfilter (The packet filtering software)
  • iptables-persistent/netfilter-persistent (for managing the firewall state)
  • A collection of bash scripts for creating, activating and flushing the current rules.

    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;

  • 22 ssh
  • 25565 Minecraft Server
  • 8123 Minecraft Dynmap Plugin

    The steps to do this will be as follows;

  • Ensure IPTables is installed and working
  • Copy the main firewall scripts to /etc/network
  • Engage the rules on your server
  • Install netfilter-persistent to control your firewall with an init script
  • Save the rules with netfilter-persistent so that the firewall is active on bootup.

    Step 1

    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               destination 
    
    
    Let's get the rules in place and get iptables filtering incoming traffic before anything else.

    Step 2

    In our scenario we want to create a firewall script that will do the following;

  • Block all incoming requests by default
  • Open and ratelimit port 22 ssh incoming connections (which will act as a sort of tar pit for brute force attacks)
  • Open port 25565 for a Minecraft server
  • Open port 8123 for the Dynmap Minecraft web server plugin

    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-reload
    
    The first script will create, activate and output your rules to your console
    The second script will flush (delete) your rules and output them to your console
    The third script will flush and immediately reload your rules in the firewall script

    Script 1 Firewall

    a) open the /etc/network/firewall file

    cd /etc/network
    sudo nano firewall
    
    Copy 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 -nL
    
    
    Engage the firewall;
    sudo /etc/network/firewall
    Take 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-down
    Copy 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 -nL
    
    Script 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-reload
    Copy the following script into nano with copy/paste and save your changes.
    #!/bin/bash
    /etc/network/firewall-down
    /etc/network/firewall
    
    Reload your firewall script;
    sudo /etc/network/firewall-reload

    Step 3 - Making the Rules Permanent

    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-persistent
    This will install the iptables-persistent and netfilter-persistent applications.
    Say yes to Save current Ipv4 rules

    ipv4 configuration screeshot

    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-persistent
    You 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 save
    Test 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.

    Viewing Your Current Firewall Rules

    To simply view the existing set of active firewall rules use iptables -nL

    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
    

    Closing Comments

    These instructions provided you with a framework for easily installing a secure and robust firewall on your server in minimal time. You can also use this for any server or desktop Linux system.

    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.



    Copyright © 2024 Al Audet