Iptables vs UFW: Which Linux Firewall Should You Use?
Securing a Linux server means controlling network traffic, and that's where firewalls come in. But Linux gives you choices, and the two main options - iptables and UFW - take completely different approaches to the same job.
Iptables is the low-level tool that's been around forever. It talks directly to the Linux kernel's netfilter framework and gives you complete control over every packet that touches your network interfaces. But with that power comes complexity - iptables commands are dense, cryptic, and easy to mess up.
UFW was created specifically to make firewall management less painful. It wraps iptables in a friendlier interface, letting you accomplish common security tasks without needing to understand kernel networking internals.
This guide walks through both tools, showing you what they're good at, where they fall short, and helping you figure out which one fits your needs.
How iptables works
Iptables connects directly to Linux's netfilter system, which lives in the kernel and makes decisions about every network packet. When a packet arrives, netfilter checks it against your rules and decides whether to accept it, drop it, or do something else with it.
The power of iptables comes from this direct connection. You can write rules that match packets based on source address, destination port, protocol type, packet state, and dozens of other criteria. You can modify packets, redirect them, log them, or count them. If netfilter can do it, iptables can configure it.
But this power has a price. An iptables rule looks like this:
That single line opens SSH access from one IP address. It includes the chain name (INPUT), protocol specification (-p tcp), source address (-s), destination port (--dport), connection state matching (-m conntrack --ctstate), and the action to take (-j ACCEPT). Miss any piece and the rule won't work as expected.
Iptables organizes rules into tables and chains. The most common table is the filter table, which contains three chains: INPUT (for incoming packets), OUTPUT (for outgoing packets), and FORWARD (for packets being routed through the system). Rules get evaluated in order, and the first match wins.
What UFW brings to Linux
UFW started as an Ubuntu project to make firewall management accessible to regular users. The goal was simple: give people a way to secure their systems without needing a networking degree.
Instead of long command strings with multiple flags, UFW uses straightforward English-like syntax:
That accomplishes the same thing as the iptables command above, but you can actually read it and understand what it does. The command structure makes sense - allow traffic from this address to this port.
UFW doesn't replace iptables. It sits on top of it, translating your simple commands into the complex iptables rules that netfilter actually uses. When you enable UFW and add rules, it's writing iptables rules behind the scenes. You can verify this by checking iptables directly after making UFW changes.
The trade-off is that UFW can't do everything iptables can do. It focuses on the common use cases - opening and closing ports, allowing or denying specific addresses, setting up basic NAT. For most servers, that's plenty.
Comparing the two approaches
Looking at these tools side by side shows you what you gain and lose with each approach:
| Aspect | iptables | UFW |
|---|---|---|
| Command complexity | Very complex, many flags | Simple, readable commands |
| Learning time | Weeks to months | Hours to days |
| Default availability | On every Linux system | Ubuntu/Debian by default |
| Rule capabilities | Complete packet control | Common scenarios covered |
| Configuration persistence | Requires save mechanism | Automatic on rule changes |
| Application profiles | None built-in | Includes common apps |
| Rule priority control | Complete control via order | Limited explicit priority |
| IPv6 support | Separate ip6tables command | Handles both automatically |
| NAT configuration | Full control, complex setup | Basic NAT, simpler syntax |
| Logging options | Extensive, granular control | Basic logging levels |
| Integration with kernel | Direct netfilter interface | Abstraction layer |
| Advanced matching | All netfilter modules | Subset of common options |
| Performance overhead | None | Minimal translation layer |
| Documentation depth | Extensive but technical | User-friendly guides |
| Community solutions | Decades of examples | Growing collection |
Writing iptables rules
Creating iptables rules means understanding chains, tables, and how packets flow through the system. Each rule specifies criteria for matching packets and an action to take when packets match.
A basic rule to allow web traffic looks like this:
Breaking this down: -A INPUT appends the rule to the INPUT chain, -p tcp matches TCP protocol packets, --dport 80 specifies destination port 80, and -j ACCEPT jumps to the ACCEPT target (allows the packet through).
To see your current rules:
The -L flag lists rules, -v adds verbose output showing packet counts, and -n displays addresses numerically instead of trying to resolve hostnames.
Blocking an IP address requires specifying the source:
The -j DROP target silently discards matching packets without sending any response.
Connection state tracking adds another layer. This rule allows established connections to continue:
The -m conntrack loads the connection tracking module, and --ctstate specifies which connection states to match. This lets reply packets through without needing separate rules for each service.
Setting a default policy determines what happens to packets that don't match any rule:
The -P flag sets the policy for the INPUT chain to DROP, blocking everything not explicitly allowed. This "deny by default" approach is more secure but requires careful rule configuration.
Now that you've seen iptables' complexity, let's look at how UFW simplifies these same tasks.
Creating rules with UFW
UFW takes firewall management and makes it conversational. Instead of memorizing flags and kernel modules, you describe what you want in plain terms.
Opening a port is straightforward:
That's it. UFW figures out you want both TCP and UDP on port 80, creates the necessary iptables rules, and handles IPv4 and IPv6 automatically.
If you only want TCP:
The syntax remains clear - just add the protocol after a slash.
Restricting access by source address reads naturally:
You can read this command and understand it immediately. Allow connections from the 192.168.1.0/24 network to port 22 on any interface.
UFW includes application profiles for common services. Instead of remembering port numbers, you can reference the application:
Application profiles live in /etc/ufw/applications.d/ and define the ports and protocols each application needs. You can create custom profiles for your own applications.
Checking your firewall status gives you a clear overview:
The output shows you exactly what's allowed and from where, formatted in a way that's easy to scan.
Removing a rule mirrors adding it:
Or you can remove by rule number:
UFW's simpler syntax makes these operations faster once you know what you want to do, but it hides details that sometimes matter.
Handling complex scenarios
Where UFW and iptables really diverge is in handling unusual or advanced configurations.
Iptables lets you match packets on practically anything. Need to block packets with specific TCP flags? You can do that:
This drops packets with suspicious flag combinations that might indicate port scanning.
Want to rate-limit connections to prevent brute force attacks?
These rules track connection attempts and drop new connections from IPs that try more than 4 times in 60 seconds. The recent module maintains a list of source addresses and timestamps.
You can also do packet mangling - modifying packet headers as they pass through:
This sets the Type of Service field to minimize delay for web traffic.
UFW handles common rate limiting with a simpler syntax:
This implements basic rate limiting on SSH connections using the same underlying iptables recent module, but you don't control the specific thresholds.
For more complex scenarios, UFW starts showing its limitations. You can't match on arbitrary packet fields or use many of iptables' advanced modules. When you hit these walls, you have two choices: add custom iptables rules alongside UFW, or switch to managing iptables directly.
With the technical differences clear, let's talk about what this means in practice.
Rule persistence and management
One significant difference between these tools is how they handle saving your configuration.
Iptables rules exist only in memory. When you add a rule, it takes effect immediately, but if you reboot your server, that rule disappears. To make rules persistent, you need to save them:
Then configure your system to restore these rules at boot. Different distributions handle this differently. On Debian and Ubuntu, you can install the iptables-persistent package:
During installation, it asks if you want to save current rules. After that, it automatically restores rules at boot from files in /etc/iptables/.
Making changes to persistent rules requires editing the saved files or using iptables-restore:
UFW handles persistence automatically. Every rule you add gets written to configuration files in /etc/ufw/. When UFW starts at boot, it reads these files and recreates all your rules. You never think about saving or restoring.
This automatic persistence makes UFW more beginner-friendly, but it also means less control over exactly when and how rules get applied.
Rule organization differs too. With iptables, you see every single rule in the order they'll be evaluated:
UFW abstracts this into a simpler view but gives you less visibility into rule order and priority.
Understanding persistence is important, but day-to-day operations matter more.
Working with each tool daily
The way these tools fit into your regular workflow has a huge impact on how reliably you'll use them.
Iptables commands are verbose, so most people create shell scripts or use configuration management tools. A typical deployment might look like:
You run this script to configure your firewall, and it's repeatable and version-controllable. But creating and maintaining the script requires understanding all those iptables flags.
UFW encourages interactive management through simple commands. Most people don't script UFW because the commands are already simple enough to type:
You can script these, but it's less common because the individual commands are so quick to type.
Debugging differs significantly. With iptables, you can watch packets in real-time:
This logs every packet hitting the INPUT chain, helping you see exactly what your firewall is doing.
UFW's logging is simpler:
You get less control over what gets logged and how, but it's easier to set up.
Both tools work fine over SSH, but iptables has one dangerous gotcha: if you set a default DROP policy without first allowing SSH, you lock yourself out immediately. UFW protects against this - when you enable it, it automatically creates rules for any services you're currently connected through.
These workflow differences influence which tool works better for different situations.
Combining both approaches
You're not forced to choose just one tool. Many administrators use UFW for day-to-day management but drop into iptables for specific advanced needs.
UFW stores its generated iptables rules in files you can examine:
You can see exactly what iptables rules UFW created. And you can add custom rules in the before.rules or after.rules files:
These custom rules get applied before UFW's generated rules, giving you iptables-level control where you need it while keeping UFW's simpler interface for everything else.
You can also verify UFW's work by checking iptables directly:
This shows you all the chains UFW created and how traffic flows through them. It's useful for understanding what's actually happening and debugging issues.
The hybrid approach works well but requires understanding both tools. You need to know enough iptables to write custom rules correctly and enough UFW to understand how it organizes its chains.
Final thoughts
Iptables and UFW solve the same problem but are aimed at different kinds of users and different levels of complexity.
If you need fine-grained control, are working in high-security or specialized environments, or want to master how Linux networking really works, iptables is the better fit, even though it takes more time and effort to learn. On the other hand, if you mostly run standard servers, work with teams that have mixed experience, or prefer to focus on applications instead of packet rules, UFW usually gives you everything you need with much less friction.