DropVPS Team
Writer: Cooper Reagan
How to secure ubuntu 25.04 with firewalld zones and rules

Table of Contents
What you will read?
- 1 Prepare the system and check UFW
- 2 Install and start FirewallD
- 3 Runtime vs permanent changes
- 4 Inspect zones and set the default zone
- 5 Bind interfaces to zones
- 6 Allow essential services safely
- 7 Open custom ports
- 8 Create rich rules (IP-based allow/deny)
- 9 Enable logging for denied packets
- 10 Masquerading (NAT) and port forwarding
- 11 IPv6 considerations
- 12 Panic mode and quick lockdown
- 13 Backup and restore FirewallD configuration
- 14 Test and verify exposure
- 15 Create a custom service definition
Lock down Ubuntu 25.04 with FirewallD’s zone-based policy. Replace UFW, enable persistent rules, and manage services and ports safely without locking yourself out. The steps below cover installation, zones, runtime vs permanent changes, rich rules, NAT and port forwarding, IPv6, logging, backups, and verification on a production-ready server.
Prepare the system and check UFW
Ensure you won’t conflict with UFW. Stop and disable it if active. Use sudo-capable user.
id
sudo ufw status verbose || true
sudo systemctl stop ufw || true
sudo systemctl disable ufw || true
sudo ufw disable || true
Status: inactive
Install and start FirewallD
Add firewalld, enable it on boot, and confirm it is running.
sudo apt update
sudo apt install -y firewalld
sudo systemctl enable --now firewalld
sudo systemctl status --no-pager firewalld
firewall-cmd --state
firewall-cmd --version
running
1.3.x
Runtime vs permanent changes
FirewallD keeps separate runtime and permanent configs. Apply permanent changes and reload to activate them.
# Example: sync runtime to disk, then reload
sudo firewall-cmd --runtime-to-permanent
sudo firewall-cmd --reload
Inspect zones and set the default zone
Zones define trust levels. Public is a safe default for internet-facing hosts.
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --get-zones
firewall-cmd --zone=public --list-all
sudo firewall-cmd --set-default-zone=public
Bind interfaces to zones
Attach network interfaces to the appropriate zone. This controls which rules apply to traffic on that interface.
ip -br a
# Replace eth0 with your interface name
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
sudo firewall-cmd --reload
firewall-cmd --get-active-zones
Allow essential services safely
Allow SSH first to retain access, then add web services.
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-services
ssh http https
Open custom ports
Expose application ports explicitly with protocol and optional ranges.
# Single port
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
# UDP range example
sudo firewall-cmd --permanent --zone=public --add-port=60000-60100/udp
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-ports
Create rich rules (IP-based allow/deny)
Use rich rules for source-based filtering and finer control.
# Allow a trusted host
sudo firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family=ipv4 source address=203.0.113.10 accept'
# Drop a noisy subnet
sudo firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family=ipv4 source address=198.51.100.0/24 drop'
# Block SMTP from everywhere (example)
sudo firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family=ipv4 port port=25 protocol=tcp drop'
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-rich-rules
Enable logging for denied packets
Turn on denied-packet logging and watch recent events for troubleshooting.
sudo firewall-cmd --set-log-denied=all
sudo journalctl -u firewalld -n 50 --no-pager
sudo journalctl -k | grep -i 'DPT=' | tail -n 20
Masquerading (NAT) and port forwarding
Enable NAT for egress when routing traffic, and forward ports to services.
# Enable IPv4 forwarding (runtime and persistent)
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-firewalld-ipforward.conf
sudo sysctl --system
# Turn on masquerade in the egress zone
sudo firewall-cmd --permanent --zone=public --add-masquerade
# Forward external TCP/80 to local TCP/8080
sudo firewall-cmd --permanent --zone=public \
--add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-all
IPv6 considerations
Service/port rules apply to IPv4 and IPv6. Use rich rules with family=ipv6 for v6-specific policies.
# Example: allow IPv6 SSH from a subnet
sudo firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family=ipv6 source address=2001:db8:1234::/48 service name=ssh accept'
sudo firewall-cmd --reload
Panic mode and quick lockdown
Panic mode drops all incoming/outgoing connections immediately. Use only for emergencies.
# Enable, then disable once safe
sudo firewall-cmd --panic-on
sudo firewall-cmd --panic-off
Backup and restore FirewallD configuration
Archive the configuration directory to preserve services, zones, and policies.
sudo tar czf /root/firewalld-backup-$(date +%F).tar.gz /etc/firewalld
# Restore (overwrites current config)
# sudo tar xzf /root/firewalld-backup-YYYY-MM-DD.tar.gz -C /
# sudo firewall-cmd --reload
Test and verify exposure
Confirm open ports locally and from a remote host to validate policies.
ss -tulpen
sudo apt install -y nmap
nmap -p 22,80,443,8080 localhost
# From another host:
# nmap -Pn -p 22,80,443 your.server.ip
Create a custom service definition
Define reusable services with XML and enable them like built-ins.
# Create /etc/firewalld/services/myapp.xml
sudo tee /etc/firewalld/services/myapp.xml >/dev/null <<'XML'
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>MyApp</short>
<description>Custom app on TCP/9000</description>
<port protocol="tcp" port="9000"/>
</service>
XML
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --zone=public --add-service=myapp
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-services
FirewallD on Ubuntu 25.04 provides clear, auditable, and flexible network control using zones, services, ports, rich rules, and NAT. Keep SSH open, apply permanent rules, reload safely, log denies, and back up configs before changes. For more guides, visit dropvps.com