When you execute a command like ufw allow 22/tcp
, UFW doesn't store these rules in plain text files within /etc/ufw
as one might expect. Instead, it uses a more sophisticated storage system that integrates with Ubuntu's networking stack.
UFW persists rules in two primary locations:
1. /lib/ufw/user.rules
2. /lib/ufw/user6.rules (for IPv6 rules)
These files are part of UFW's backend infrastructure and shouldn't be edited manually. They're maintained by the ufw
command-line utility itself.
When you add a rule via the command line, UFW:
- Parses your input command
- Converts it to iptables/nftables syntax
- Stores the rule in its internal format in user.rules
- Applies the rule immediately to the running firewall
Let's examine what happens when you run:
sudo ufw allow 22/tcp
You can verify the rule persistence by checking:
sudo cat /lib/ufw/user.rules | grep "22/tcp"
This should show the rule in UFW's internal format, which might look like:
### tuple ### allow tcp 22 0.0.0.0/0 any 0.0.0.0/0 in
-A ufw-user-input -p tcp --dport 22 -j ACCEPT
1. Never edit these files manually - Always use the ufw
command-line utility
2. Backup your rules with sudo ufw export
3. Rule ordering matters - UFW maintains the order in which rules were added
For advanced users who need to add custom iptables rules, UFW provides:
/etc/ufw/before.rules
/etc/ufw/after.rules
These files allow you to insert rules that execute before or after UFW's main rule processing.
When you execute commands like ufw allow 22/tcp
in Ubuntu, the rules persist across reboots but aren't visibly stored in /etc/ufw
. The actual storage mechanism uses a different approach:
# Example persistent rule:
ufw allow 22/tcp
# This gets stored in a non-obvious location
UFW maintains persistent rules through a combination of files and backend systems:
- Primary storage:
/lib/ufw/user.rules
(for IPv4) and/lib/ufw/user6.rules
(for IPv6) - Backend integration: Rules get translated to iptables/nftables syntax
- Configuration files:
/etc/ufw/ufw.conf
contains the main configuration
To view currently active persistent rules:
sudo cat /lib/ufw/user.rules
# Or for IPv6:
sudo cat /lib/ufw/user6.rules
You'll see entries like:
### tuple ### allow tcp 22 0.0.0.0/0 any 0.0.0.0/0
-A ufw-user-input -p tcp --dport 22 -j ACCEPT
For advanced users who want to edit rules directly:
# 1. Make backup first
sudo cp /lib/ufw/user.rules /lib/ufw/user.rules.bak
# 2. Edit the file
sudo nano /lib/ufw/user.rules
# 3. Reload UFW
sudo ufw reload
For more complex setups, consider these approaches:
# Method 1: Include files
sudo sh -c 'echo "ufw allow 22/tcp" >> /etc/ufw/user.rules'
# Method 2: Use before.rules/after.rules
sudo nano /etc/ufw/before.rules
When rules don't persist as expected:
# Check the logs:
sudo tail -f /var/log/ufw.log
# Verify rule application:
sudo iptables -L | grep ufw
# Check file permissions:
sudo ls -la /lib/ufw/user*