The Linux Five Minute Firewall
A practical iptables setup guide for Debian-based servers
Introduction
A firewall or packet filter is an important security tool for your headless Linux server. This guide gives you the framework for setting up a firewall that filters all incoming connections by default and only allows access to the ports you specify.
The first time you follow this guide it 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 with a reproducible firewall that is exactly to your specifications.
These instructions apply to Debian-based systems. This guide uses the following:
- Ubuntu Server 18.04 LTS (also works on Debian Bullseye and later)
- Iptables / Netfilter — the packet filtering software
- iptables-persistent / netfilter-persistent — for managing firewall state across reboots
- A set of bash scripts for creating, activating, and flushing rules
The Setup
These instructions simulate building a firewall for a Minecraft server. The process is identical for web, DNS, or email servers — only the ports change.
This firewall will block all incoming requests by default and open only these ports:
- 22 — SSH
- 25565 — Minecraft server
- 8123 — Minecraft Dynmap plugin
The steps are:
- Verify iptables is installed and working
- Copy the firewall scripts to
/etc/network - Engage the rules on your server
- Install netfilter-persistent to persist rules across reboots
- Save the rules so the firewall activates at boot
Step 1 — Verify iptables
Check that your iptables packet filter is ready. It is installed by default on Ubuntu. The following command shows the default setup is wide open — all connections are accepted on every port. On a fresh install, most ports except 22 (SSH) are closed by default anyway.
Command
sudo iptables -nL
Output
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
Good. Now let’s get rules in place before anything else.
Step 2 — Create the Scripts
Create three empty scripts in /etc/network and lock down their permissions so only root can read them.
Create the files
cd /etc/network sudo touch firewall firewall-down firewall-reload sudo chmod 700 firewall firewall-down firewall-reload
firewall— creates and activates your rulesfirewall-down— flushes (removes) all rulesfirewall-reload— flushes and immediately reloads rules
Script 1 — firewall
Open /etc/network/firewall and paste in the following script. This is the main firewall that activates your rules.
/etc/network/firewall
#!/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. 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 — 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 /sbin/iptables -nL
Engage the firewall and review each line to understand what it does — commented lines give hints.
Activate
sudo /etc/network/firewall
Script 2 — firewall-down
Open /etc/network/firewall-down and paste in the following. This flushes all rules and re-opens all traffic so you can reconnect if needed.
/etc/network/firewall-down
#!/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 # Open up all traffic so you can reconnect /sbin/iptables -P INPUT ACCEPT /sbin/iptables -P FORWARD ACCEPT /sbin/iptables -P OUTPUT ACCEPT # Print rules to the console /sbin/iptables -nL
Script 3 — firewall-reload
Open /etc/network/firewall-reload and paste in the following. Use this after editing the firewall script to flush and reload changes without rebooting.
/etc/network/firewall-reload
#!/bin/bash /etc/network/firewall-down /etc/network/firewall
Reload
sudo /etc/network/firewall-reload
Step 3 — Making Rules Permanent
The firewall rules are lost on reboot until you persist them. Install iptables-persistent to activate the firewall automatically before the network interface comes up.
Install
sudo apt install iptables-persistent
When prompted, say Yes to save current IPv4 rules and Yes to save current IPv6 rules.
The iptables-persistent installer prompting to save current IPv4 rules.
Once installed, netfilter-persistent is available at /etc/init.d/netfilter-persistent. Its available commands are:
Usage
sudo /etc/init.d/netfilter-persistent {start|restart|reload|force-reload|save|flush}
Save the current rules to make them boot-persistent:
Save rules
sudo /etc/init.d/netfilter-persistent save
From now on, after modifying /etc/network/firewall and running firewall-reload, always follow up with netfilter-persistent save to make the changes permanent.
Viewing Your Current Rules
Use iptables -nL at any time to see the active ruleset.
Output with rules active
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
This guide provides a framework for quickly setting up a secure and reproducible iptables firewall on any Debian-based server or desktop. Adapt the open ports to match your own services.
If you spot any errors or have feedback, feel free to contact me directly.