Firewalld provides dynamic firewall management with support for IPv4, IPv6, and Ethernet bridges. Unlike static firewall systems that require service restarts after rule changes, Firewalld allows you to modify rules on the fly without disrupting active connections. This makes it particularly useful for managing web servers, protecting SSH access, configuring NAT gateways, and controlling network traffic on multi-interface systems. By the end of this guide, you will have Firewalld installed and running on Debian, with the knowledge to configure zones, manage services, and troubleshoot common issues.
This installation uses Debian’s default repositories and works identically across Debian 13 (Trixie), Debian 12 (Bookworm), and Debian 11 (Bullseye). Package versions vary by release (2.x on Debian 13, 1.x on Debian 12, 0.9.x on Debian 11), but all commands and zone configurations function the same way.
Install Firewalld on Debian
Update the Package Index
Before installing any new software, first refresh your package database to ensure you get the latest available version:
sudo apt update
As a result, APT retrieves the current package information from all configured repositories, ensuring the installation pulls the most recent firewalld version.
Install the Firewalld Package
With the package index updated, you can now install Firewalld using the APT package manager:
sudo apt install firewalld -y
The -y flag automatically confirms the installation prompt, which is useful for scripted deployments but means you won’t see the package list before installation proceeds.
Verify the Installation
After installation completes, verify that Firewalld installed correctly by checking its version:
firewall-cmd --version
Expected output:
2.3.1
Once you see a version number, Firewalld is installed and accessible from your terminal. Your output may show a different version depending on your Debian release.
Enable and Start Firewalld
If you are connected via SSH, ensure SSH access is permitted before enabling the firewall. By default, Firewalld’s public zone allows SSH, but if you change zones or modify rules, you risk losing remote access. Consider adding
sudo firewall-cmd --add-service=ssh --permanentbefore enabling if you are unsure.
Next, start Firewalld and configure it to launch automatically at boot:
sudo systemctl enable --now firewalld
The --now flag combines enable and start into a single command. Verify the service is running:
sudo systemctl status firewalld
Expected output:
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/lib/systemd/system/firewalld.service; enabled; preset: enabled)
Active: active (running) since Sat 2025-12-14 12:00:00 UTC; 5s ago
Docs: man:firewalld(1)
Main PID: 1234 (firewalld)
Tasks: 2 (limit: 4647)
Memory: 28.5M
CPU: 432ms
CGroup: /system.slice/firewalld.service
└─1234 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid
The active (running) status confirms that Firewalld is operational and protecting your system.
Understanding Firewalld Zones
Firewalld organizes network traffic rules into zones, which represent different levels of trust for network connections. In particular, each zone contains a predefined set of rules that control which services and ports are accessible. When a network interface connects, Firewalld applies the rules from the zone assigned to that interface.
Common Predefined Zones
Firewalld includes several predefined zones, each designed for specific network environments:
| Zone | Trust Level | Use Case |
|---|---|---|
| drop | None | Drops all incoming packets silently; outgoing connections allowed |
| block | None | Rejects incoming packets with ICMP response; outgoing allowed |
| public | Low | Public networks like cafes or airports (default zone) |
| external | Low | Systems acting as NAT gateways or routers |
| dmz | Low | Servers in a demilitarized zone with limited access |
| work | Medium | Office environments with partially trusted devices |
| home | High | Home networks where most devices are trusted |
| internal | High | Internal network segments behind a gateway |
| trusted | Full | Accepts all incoming connections (use with caution) |
In most cases, the public zone provides appropriate defaults for Debian servers exposed to the internet, blocking all incoming connections except those explicitly permitted.
View Active Zones and Interfaces
To see which zones are currently active and which network interfaces belong to each zone, run:
sudo firewall-cmd --get-active-zones
Expected output:
public interfaces: eth0 enp0s3
In this example, the public zone is active with the eth0 and enp0s3 interfaces assigned to it. Your interface names will vary depending on your system configuration.
Check the Default Zone
The default zone applies to any interface not explicitly assigned to another zone. To view the current default:
sudo firewall-cmd --get-default-zone
Expected output:
public
Manage Firewalld Services and Ports
Firewalld uses predefined services (like ssh, http, https) to simplify rule management. As a result, you can allow or deny traffic by service name instead of remembering port numbers. This section covers the essential commands for managing network access.
List Services in a Zone
To see which services are currently permitted in a specific zone:
sudo firewall-cmd --zone=public --list-services
Expected output:
dhcpv6-client ssh
By default, the public zone allows both DHCP client traffic and SSH connections.
Add a Service to a Zone
To allow a service through the firewall, use the --add-service option. For example, to permit HTTP traffic:
sudo firewall-cmd --zone=public --add-service=http --permanent
The --permanent flag saves the rule to the persistent configuration, ensuring it survives reboots. However, permanent changes don’t take effect immediately. To apply them, reload the configuration:
sudo firewall-cmd --reload
Alternatively, add the rule without --permanent to apply it immediately (but lose it on reboot), then add the permanent version separately:
sudo firewall-cmd --zone=public --add-service=http
sudo firewall-cmd --zone=public --add-service=http --permanent
Remove a Service from a Zone
To remove a previously added service:
sudo firewall-cmd --zone=public --remove-service=http --permanent
sudo firewall-cmd --reload
Add a Specific Port
For applications that don’t have predefined service definitions, you can open specific ports directly. For example, to allow TCP connections on port 8080:
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
Then verify the port was added:
sudo firewall-cmd --zone=public --list-ports
Expected output:
8080/tcp
Change the Default Zone
To change the default zone for new interfaces:
sudo firewall-cmd --set-default-zone=home
Replace home with your desired zone name. Unlike service changes, this takes effect immediately and persists across reboots.
Advanced Firewalld Configuration
Beyond basic service management, Firewalld supports advanced features like custom services, zone creation, IP masquerading, and port forwarding. These capabilities are essential for configuring NAT gateways, load balancers, and complex network topologies.
Create a Custom Service
If you run an application on a non-standard port that isn’t covered by predefined services, you can define your own. First, create the service:
sudo firewall-cmd --permanent --new-service=myapp
Next, configure the service with a description and port:
sudo firewall-cmd --permanent --service=myapp --set-short="My Custom Application"
sudo firewall-cmd --permanent --service=myapp --add-port=9000/tcp
Once the service is defined, reload Firewalld and add it to a zone:
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --add-service=myapp --permanent
sudo firewall-cmd --reload
Create a Custom Zone
Similarly, for complex network environments you may need zones beyond the predefined options:
sudo firewall-cmd --permanent --new-zone=customzone
sudo firewall-cmd --reload
Then assign interfaces and services to your custom zone as needed.
Enable IP Masquerading
Masquerading (NAT) allows systems behind a gateway to access external networks using the gateway’s IP address. This is essential for routing traffic from private networks:
sudo firewall-cmd --zone=public --add-masquerade --permanent
sudo firewall-cmd --reload
Afterward, verify masquerading is enabled:
sudo firewall-cmd --zone=public --query-masquerade
Expected output:
yes
Configure Port Forwarding
Port forwarding redirects incoming traffic from one port to another. For example, to forward external port 8080 to internal port 80:
sudo firewall-cmd --zone=public --add-forward-port=port=8080:proto=tcp:toport=80 --permanent
sudo firewall-cmd --reload
As shown above, this configuration accepts connections on port 8080 and forwards them to port 80 on the same host. To forward to a different host, add :toaddr=192.168.1.100 to the command.
Create Rich Rules for Granular Control
Rich rules provide fine-grained control over traffic that predefined services and ports cannot express. They allow you to specify source addresses, destination ports, protocols, and actions in a single rule. This is particularly useful for restricting access to specific IP addresses or networks.
For instance, to allow SSH access only from a specific IP address:
sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent
sudo firewall-cmd --reload
Alternatively, to block all traffic from a specific subnet:
sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" reject' --permanent
sudo firewall-cmd --reload
Additionally, you can view all active rich rules for a zone:
sudo firewall-cmd --zone=public --list-rich-rules
To remove a rich rule, use the same syntax with --remove-rich-rule instead of --add-rich-rule. Rich rules are evaluated in order, so more specific rules should be added before general ones when order matters.
Troubleshoot Firewalld Issues
When firewall rules don’t behave as expected, systematic troubleshooting helps identify the root cause. Firewalld provides several diagnostic tools to help you investigate and resolve issues.
Check Service Status
If Firewalld commands fail or rules aren’t applying, first verify the service is running:
sudo systemctl status firewalld
Look for Active: active (running) in the output. If the service shows failed or inactive, check the logs for errors.
Review Firewalld Logs
Firewalld logs events to the system journal. To view recent log entries:
sudo journalctl -u firewalld --no-pager -n 50
The -n 50 flag limits output to the last 50 lines. Look for error messages, configuration warnings, or failed rule applications.
Reload the Configuration
If Firewalld becomes unresponsive or rules aren’t taking effect, reload the configuration:
sudo firewall-cmd --reload
Expected output:
success
As a result, this command re-reads the permanent configuration and applies it without restarting the service. However, runtime-only changes (those made without --permanent) will be lost.
Restart the Firewalld Service
For more persistent issues, restart the entire service:
sudo systemctl restart firewalld
Because a restart fully reinitializes Firewalld from its permanent configuration, this approach can resolve issues caused by corrupted runtime state.
Rules Not Persisting After Reboot
If your firewall rules disappear after a reboot, the rules were likely added without the --permanent flag. To make rules persistent, always include --permanent:
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload
Furthermore, you can check the permanent configuration separately from the runtime configuration:
sudo firewall-cmd --zone=public --list-services --permanent
Interface Not in Expected Zone
If traffic isn’t being filtered as expected, verify the interface is assigned to the correct zone:
sudo firewall-cmd --get-active-zones
To move an interface to a different zone:
sudo firewall-cmd --zone=work --change-interface=eth0 --permanent
sudo firewall-cmd --reload
Verify Configuration Files
Firewalld stores its configuration in /etc/firewalld/. If you suspect configuration corruption, you can examine the files directly:
ls -la /etc/firewalld/zones/
In particular, zone-specific configurations are stored as XML files. The main configuration file is:
cat /etc/firewalld/firewalld.conf
View All Active Rules at Once
When troubleshooting, it helps to see everything Firewalld is currently applying. The --list-all flag displays all services, ports, rich rules, and settings for the default zone:
sudo firewall-cmd --list-all
Expected output:
public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Consequently, this output provides a complete snapshot of the active zone configuration. To view rules for a specific zone, add --zone=zonename to the command. For a comprehensive view of all zones with their configurations, use sudo firewall-cmd --list-all-zones.
Remove Firewalld from Debian
If you need to remove Firewalld, whether to switch to a different firewall solution like UFW or nftables, follow these steps. First, stop and disable the service:
sudo systemctl stop firewalld
sudo systemctl disable firewalld
Next, remove the firewalld package and its configuration:
sudo apt remove --purge firewalld -y
Then remove any orphaned dependencies that were installed with Firewalld. This step cleans up supporting packages like nftables, python3-firewall, iptables, and polkitd that are no longer needed:
sudo apt autoremove -y
Finally, refresh the package cache and verify the removal was successful:
sudo apt update
apt-cache policy firewalld
Expected output:
firewalld:
Installed: (none)
Candidate: 2.3.1-1
Version table:
2.3.1-1 500
500 http://deb.debian.org/debian trixie/main amd64 Packages
Running apt update before the verification ensures you see accurate removal status rather than stale cached information. Your version numbers will vary depending on your Debian release.
The Installed: (none) line confirms that Firewalld has been removed from your system.
After removing Firewalld, your system will have no active firewall. If you need continued protection, consider installing UFW on Debian as a simpler alternative, or configure nftables directly for finer control. Install your replacement firewall before removing Firewalld to avoid leaving the system unprotected.
Conclusion
You now have Firewalld installed and configured on Debian, with the ability to manage zones, control service access, and troubleshoot common issues. The zone-based approach simplifies network security by applying consistent rules across different network environments, while the --permanent flag ensures your configuration survives reboots. For advanced configurations beyond what this guide covers, the official Firewalld documentation provides comprehensive reference material. To complement your firewall configuration, our guide on enabling SSH on Debian covers secure remote access setup that works well with Firewalld’s default public zone rules.