If you run a game server, a web application or a Discord bot, the moment you expose the machine to the internet it starts getting scanned. An iptables firewall lets you decide exactly which traffic gets in and out by driving the packet-filtering layer (Netfilter) built into the Linux kernel: you open only the ports you need and silently refuse everything else. In this guide we'll build a secure rule set from scratch, write port rules and filter the most common attacks, step by step.
How iptables works: chains and tables
iptables organizes rules into tables and chains. For everyday firewalling, the filter table and three chains are all you need:
- INPUT — packets arriving at the server (this is where our protection lives).
- OUTPUT — packets leaving the server.
- FORWARD — packets routed through the server to another destination (router/Docker scenarios).
Each packet walks the chain top to bottom; the target of the first matching rule wins: ACCEPT (allow), DROP (silently discard) or REJECT (refuse and return an error). If nothing matches, the chain's default policy applies. The core principle of a solid firewall: set the policy to DROP, then open only what you explicitly allow.
Don't lock yourself out: order matters
The most common mistake is setting the policy to DROP before adding the SSH rule, killing your remote session. So write the allow rules first, tighten the policy last. Also free up loopback and existing connections right at the top:
# Let already-established connections continue
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Never block loopback (127.0.0.1) traffic
iptables -A INPUT -i lo -j ACCEPT
# Drop malformed / invalid packets
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
That first rule is critical: thanks to the conntrack module, reply packets for connections the server started or that are already established pass automatically, so you don't need separate rules on the OUTPUT side.
Port rules: open only what you need
Now let's add port rules per service. A typical setup: SSH (22), HTTP (80), HTTPS (443) and a game server port. -p sets the protocol, --dport the destination port:
# SSH (add this first, then lock down!)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Web
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Example game server (e.g. Metin2 TCP 13000)
iptables -A INPUT -p tcp --dport 13000 -j ACCEPT
To open multiple ports in a single line, use the multiport module:
iptables -A INPUT -p tcp -m multiport --dport 80,443,13000 -j ACCEPT
Opening a port only to a specific IP (for instance SSH only from your static IP) is far safer:
iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT
Once all allow rules are written, tighten the default policies:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
Filtering basic attacks
An exposed server constantly faces port scans, brute-force and spoofed-packet attempts. A few targeted rules drop or slow down most of them.
Slowing SSH brute-force: with the recent module, temporarily block any IP making more than 4 new SSH connections in 60 seconds:
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --name SSH -j DROP
Port scans / invalid flags: TCP packets with no flags (NULL) or nonsensical flag combinations usually come from a scanning tool:
# NULL packets
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# XMAS scan
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
# New connections that aren't SYN
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
Rate-limiting ICMP (ping): rather than disabling ping entirely, limiting requests per second keeps diagnostics usable while stopping floods:
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 1/second -j ACCEPT
Remember: iptables alone won't stop a real DDoS (a saturated link is beyond the kernel), but it seriously reduces application-layer scanning and noise.
Making rules persistent
iptables rules live in memory and are lost on reboot. On Debian/Ubuntu the iptables-persistent package saves them and restores them at boot:
sudo apt install iptables-persistent
sudo netfilter-persistent save # /etc/iptables/rules.v4
You can also save and restore manually:
iptables-save > /etc/iptables/rules.v4
iptables-restore < /etc/iptables/rules.v4
To view rules with line numbers and delete them:
iptables -L INPUT -n -v --line-numbers
iptables -D INPUT 3 # delete rule number 3
A note on nftables and UFW
On modern distributions the iptables command is usually redirected to nftables under the hood (iptables-nft). The command syntax stays the same, so everything in this guide works. For new projects, learning nft directly makes sense, but countless existing docs and scripts are still iptables-based. If you want a simpler interface, UFW (Uncomplicated Firewall) wraps iptables: one-liners like ufw allow 443/tcp do the same job. To actually understand what's happening, though, basic iptables knowledge is invaluable.
Frequently Asked Questions
Should I use DROP or REJECT?
DROP discards the packet silently; the sender can't tell whether the port is open, closed or firewalled, which slows scanners down. REJECT returns a "connection refused" message, giving faster feedback. On an internet-facing INPUT chain, DROP is usually preferred; on an internal network REJECT is more convenient for quick errors.
Why does rule order matter so much?
Because iptables stops at the first matching rule. If you put a broad DROP at the top, the ACCEPT rules below it never run. Always put narrow/specific allows first and general denials/the policy last.
Do I need separate rules for IPv6?
Yes. iptables only manages IPv4; IPv6 traffic is configured separately with ip6tables. If your server has IPv6, leaving it unfiltered is a big hole, so write matching ip6tables rules with the same logic.
Want your server configured securely and robustly? If you need help with firewalling, hardening and deployment for a game server, VPS or web infrastructure, get in touch with me.