How to Configure Firewall Rules: A Complete Technical Guide
A firewall rule is a policy entry that instructs a firewall engine to permit, deny, or log network traffic based on defined criteria such as source/destination IP address, port number, transport protocol, and traffic direction. Correctly configured firewall rules form the primary enforcement layer between your infrastructure and the public internet, making them the single most consequential security control on any server or network device.
This guide covers firewall rule architecture, UFW on Linux, firewalld, Windows Defender Firewall, nftables, and the operational practices that separate a hardened environment from a misconfigured one.
What Firewall Rules Actually Control
Every rule in a firewall ruleset is evaluated against five core packet attributes, commonly called the 5-tuple:
- Source IP address β the originating host or subnet (e.g.,
192.168.1.0/24) - Destination IP address β the target host or range
- Source port β the ephemeral port on the initiating side
- Destination port β the service port on the receiving side (e.g.,
443for HTTPS,22for SSH) - Protocol β
TCP,UDP,ICMP, or protocol number
Beyond the 5-tuple, stateful firewalls also track connection state (NEW, ESTABLISHED, RELATED, INVALID), which allows them to permit return traffic for outbound connections without writing explicit inbound rules for every response.
Stateful vs. Stateless Firewalls
| Feature | Stateful | Stateless |
|---|---|---|
| Tracks connection state | Yes | No |
| Allows return traffic automatically | Yes | No β requires explicit rules |
| Performance overhead | Moderate | Very low |
| Typical use case | Host firewalls, NGFWs | Core routers, high-throughput ACLs |
| Spoofing resistance | High | Low |
| Rule complexity | Lower | Higher |
| Example tools | iptables (conntrack), UFW, Windows Defender | AWS NACL, basic ACL on Cisco IOS |
For virtually all server deployments β including VPS Hosting and Dedicated Servers β a stateful host-based firewall is the correct default choice.
Firewall Rule Processing: The Order Problem
One of the most common sources of misconfiguration is misunderstanding rule ordering. Most firewalls evaluate rules top-to-bottom and apply the first matching rule, then stop. This means:
- A broad
ALLOWrule placed above a specificDENYrule will silently override it. - A
DENY ALLat the top of a chain blocks everything, regardless of what follows. - Duplicate or shadowed rules waste processing cycles and create audit confusion.
Best practice: Always place specific rules before general ones. Place explicit DENY rules for known-bad sources near the top, followed by specific ALLOW rules for trusted services, and terminate every chain with a default DENY policy.
Configuring Firewall Rules on Linux with UFW
UFW (Uncomplicated Firewall) is a frontend for iptables and nftables on Debian/Ubuntu-based systems. It abstracts low-level chain syntax into human-readable commands while preserving full control over port, protocol, IP, and interface filtering.
Step 1: Install and Enable UFW
UFW is pre-installed on Ubuntu. Verify its status before enabling:
sudo ufw status verboseIf inactive, enable it:
sudo ufw enableCritical warning: If you are connected via SSH and have not yet allowed port 22, enabling UFW will lock you out. Always allow SSH before enabling the firewall on a remote server.
Step 2: Set Default Policies
Default policies define what happens to traffic that matches no explicit rule. The secure baseline is:
sudo ufw default deny incoming
sudo ufw default allow outgoingThis drops all unsolicited inbound connections while permitting all outbound traffic. If your security policy requires egress filtering (e.g., preventing data exfiltration or C2 callbacks), change the outgoing default:
sudo ufw default deny outgoingThen explicitly allow only the outbound destinations your application needs.
Step 3: Allow Specific Services and Ports
UFW supports service names from /etc/services or explicit port numbers:
# Allow SSH by service name
sudo ufw allow ssh
# Allow HTTP and HTTPS
sudo ufw allow http
sudo ufw allow https
# Allow a custom application port
sudo ufw allow 8080/tcp
# Allow a UDP service (e.g., DNS resolver)
sudo ufw allow 53/udpTo allow a port range (e.g., passive FTP):
sudo ufw allow 49152:65535/tcpStep 4: Restrict Access to Specific Source IPs
Exposing administrative ports to 0.0.0.0/0 is a leading cause of brute-force compromise. Lock SSH to a known management IP:
sudo ufw allow from 203.0.113.50 to any port 22 proto tcpTo allow an entire management subnet:
sudo ufw allow from 10.0.0.0/8 to any port 22 proto tcpStep 5: Deny Traffic from Specific IPs or Subnets
Block a known-malicious IP:
sudo ufw deny from 198.51.100.77Block an entire subnet (e.g., a geographic block or an abusive ASN range):
sudo ufw deny from 198.51.100.0/24Edge case: UFW deny rules send a TCP RST or ICMP port-unreachable response, which confirms the host exists. Use reject to silently drop packets instead:
sudo ufw reject from 198.51.100.0/24Step 6: Inspect Active Rules
sudo ufw status numberedThe numbered flag assigns an index to each rule, which is required for targeted deletion:
[ 1] 22/tcp ALLOW IN 203.0.113.50
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443/tcp ALLOW IN AnywhereFor a full verbose output including default policies and interface bindings:
sudo ufw status verboseStep 7: Delete Rules
Delete by rule number (preferred β avoids ambiguity):
sudo ufw delete 3Delete by rule specification:
sudo ufw delete allow 8080/tcpStep 8: Reload and Persist Rules
UFW rules persist across reboots automatically. After bulk changes, reload without dropping existing connections:
sudo ufw reloadTo fully reset all rules and start from scratch:
sudo ufw resetAdvanced UFW: Application Profiles
UFW supports named application profiles stored in /etc/ufw/applications.d/. This allows you to define multi-port rules under a single name:
sudo ufw app list
sudo ufw allow 'Nginx Full'
sudo ufw app info 'Nginx Full'Creating a custom profile for a Node.js API:
[NodeAPI]
title=Node.js API Server
description=Custom Node.js application
ports=3000,3001/tcpThen apply it:
sudo ufw allow NodeAPIConfiguring Firewall Rules with firewalld (RHEL/CentOS/Fedora)
firewalld uses a zone-based model rather than a flat ruleset. Each network interface is assigned to a zone (e.g., public, internal, dmz), and rules are applied per zone. This is architecturally more flexible for multi-homed servers.
Basic firewalld Operations
# Check status
sudo firewall-cmd --state
# List all active zones and their interfaces
sudo firewall-cmd --get-active-zones
# List rules in the public zone
sudo firewall-cmd --zone=public --list-allAllow and Remove Services
# Allow HTTPS permanently
sudo firewall-cmd --zone=public --add-service=https --permanent
# Allow a custom port
sudo firewall-cmd --zone=public --add-port=8443/tcp --permanent
# Remove a service
sudo firewall-cmd --zone=public --remove-service=http --permanent
# Reload to apply permanent changes
sudo firewall-cmd --reloadRich Rules for IP-Specific Policies
firewalld rich rules provide the granularity of iptables with a more readable syntax:
# Allow SSH only from a specific IP
sudo firewall-cmd --zone=public
--add-rich-rule='rule family="ipv4" source address="203.0.113.50" service name="ssh" accept'
--permanent
# Block all traffic from a subnet
sudo firewall-cmd --zone=public
--add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" drop'
--permanent
sudo firewall-cmd --reloadConfiguring Firewall Rules with nftables
nftables is the modern replacement for iptables, offering a unified framework for IPv4, IPv6, ARP, and bridge filtering with significantly better performance and atomic rule replacement.
Basic nftables Ruleset
# Flush existing ruleset
sudo nft flush ruleset
# Create a basic filtering table
sudo nft add table inet filter
# Add input, forward, and output chains
sudo nft add chain inet filter input { type filter hook input priority 0 ; policy drop ; }
sudo nft add chain inet filter forward { type filter hook forward priority 0 ; policy drop ; }
sudo nft add chain inet filter output { type filter hook output priority 0 ; policy accept ; }
# Allow established and related connections
sudo nft add rule inet filter input ct state established,related accept
# Allow loopback
sudo nft add rule inet filter input iif lo accept
# Allow SSH from a specific IP
sudo nft add rule inet filter input ip saddr 203.0.113.50 tcp dport 22 accept
# Allow HTTP and HTTPS from anywhere
sudo nft add rule inet filter input tcp dport { 80, 443 } acceptTo make the ruleset persistent, save it to the default configuration file:
sudo nft list ruleset > /etc/nftables.conf
sudo systemctl enable nftablesConfiguring Firewall Rules on Windows
Windows Defender Firewall with Advanced Security provides both GUI and command-line (netsh, PowerShell) interfaces for rule management.
Using the GUI
- Open Windows Defender Firewall with Advanced Security via
wf.msc. - Select Inbound Rules or Outbound Rules in the left panel.
- Click New Rule in the right panel.
- Choose the rule type:
- Port β filter by TCP/UDP port number
- Program β filter by executable path
- Predefined β use a built-in Windows service definition
- Custom β full control over all parameters
- Specify the port or program, choose Allow or Block, select applicable profiles (Domain, Private, Public), and name the rule.
Using PowerShell (Recommended for Automation)
# Allow inbound HTTPS
New-NetFirewallRule -DisplayName "Allow HTTPS Inbound" `
-Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
# Allow inbound SSH (Windows OpenSSH)
New-NetFirewallRule -DisplayName "Allow SSH Inbound" `
-Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow `
-RemoteAddress 203.0.113.50
# Block inbound traffic from a specific IP
New-NetFirewallRule -DisplayName "Block Malicious IP" `
-Direction Inbound -RemoteAddress 198.51.100.77 -Action Block
# View all inbound rules
Get-NetFirewallRule -Direction Inbound | Select-Object DisplayName, Enabled, Action
# Remove a rule by name
Remove-NetFirewallRule -DisplayName "Allow HTTPS Inbound"Using netsh (Legacy but Widely Supported)
:: Allow inbound port 443
netsh advfirewall firewall add rule name="Allow HTTPS" protocol=TCP dir=in localport=443 action=allow
:: Block a specific IP
netsh advfirewall firewall add rule name="Block IP" dir=in remoteip=198.51.100.77 action=block
:: Delete a rule
netsh advfirewall firewall delete rule name="Allow HTTPS"Critical Firewall Rule Pitfalls and Edge Cases
The Implicit Permit for ESTABLISHED Traffic
On stateful firewalls, failing to explicitly allow ESTABLISHED and RELATED connections in the input chain will break all outbound-initiated sessions (e.g., apt update, curl, DNS lookups) even when the output chain is set to ACCEPT. This is the most common misconfiguration on raw iptables or nftables setups.
# This rule MUST appear before any DROP rules in the input chain
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTIPv6 Parity
Many administrators configure IPv4 rules meticulously and forget IPv6 entirely. If your server has an IPv6 address and UFW's IPv6 support is not enabled, an attacker can bypass all IPv4 rules by connecting over ::. Verify /etc/default/ufw contains:
IPV6=yesLoopback Interface
Always explicitly allow traffic on the loopback interface (lo). Many local services (databases, message queues, internal APIs) communicate over 127.0.0.1 or ::1. Blocking loopback breaks inter-process communication silently.
sudo ufw allow in on lo
sudo ufw allow out on loRate Limiting to Prevent Brute Force
UFW supports connection rate limiting natively, which is essential for SSH and other authentication services:
sudo ufw limit sshThis allows a maximum of 6 connection attempts per 30 seconds from a single IP before triggering an automatic temporary block β a lightweight alternative to fail2ban for basic deployments.
ICMP and Diagnostic Traffic
Blocking all ICMP is a common but counterproductive practice. It breaks ping, traceroute, MTU path discovery, and some routing protocols. The correct approach is to allow specific ICMP types:
- Type 0 (Echo Reply) and Type 8 (Echo Request) β for
ping - Type 3 (Destination Unreachable) β for path MTU discovery
- Type 11 (Time Exceeded) β for
traceroute
Block Type 17 (Address Mask Request) and Type 18 (Address Mask Reply), which have no legitimate modern use.
Firewall Rules and Hosting Environments
The correct firewall strategy depends heavily on your infrastructure layer.
On Shared Web Hosting, the firewall is managed at the platform level by the provider. Tenants typically configure application-layer access controls rather than kernel-level packet filters.
On a VPS with cPanel, cPanel/WHM includes ConfigServer Security & Firewall (CSF), which wraps iptables with a high-level interface, automatic brute-force detection, and port knocking support. CSF is the standard firewall solution for cPanel environments and should be used in preference to raw UFW on those systems.
On unmanaged VPS Hosting or Dedicated Servers, you have full control over the kernel firewall. This is where UFW, firewalld, and nftables are the appropriate tools. The hardening baseline should include:
- Default-deny inbound policy
- SSH restricted to known management IPs or a VPN gateway
- All non-essential ports closed
- Rate limiting on authentication ports
- Logging enabled for denied traffic
If you are running GPU workloads or ML inference services on GPU Hosting, pay particular attention to the ports exposed by Jupyter notebooks, TensorBoard, and model-serving APIs β these are frequently targeted by cryptomining bots that scan for open high-numbered ports.
Firewall Rule Audit and Maintenance Checklist
Regular rule audits are as important as initial configuration. Rules accumulate over time and become stale, creating unnecessary attack surface.
Audit tasks to perform quarterly:
- Run
sudo ufw status numberedor equivalent and review every rule against current service inventory - Remove rules for decommissioned services, old IP addresses, and temporary exceptions that were never cleaned up
- Verify that default policies are still
deny incoming - Check that IPv6 rules mirror IPv4 rules
- Confirm that logging is enabled and that denied-traffic logs are being ingested by your SIEM or log aggregator
- Test rules with
nmapfrom an external host to verify the attack surface matches your intent
# Scan your own server from an external host to verify exposed ports
nmap -sS -sV -p 1-65535 --open YOUR_SERVER_IP- Validate that
ESTABLISHED/RELATEDrules are present and correctly ordered - Review rate-limiting rules and adjust thresholds based on observed traffic patterns
Decision Matrix: Choosing the Right Firewall Tool
| Scenario | Recommended Tool | Rationale |
|---|---|---|
| Ubuntu/Debian server, simple ruleset | UFW | Human-readable syntax, persistent by default |
| RHEL/CentOS/Fedora server | firewalld | Native integration, zone model suits multi-NIC setups |
| High-performance or complex filtering | nftables | Atomic updates, single framework for IPv4/IPv6/ARP |
| Legacy RHEL/CentOS 6 | iptables | Only option on older kernels |
| Windows Server | Windows Defender + PowerShell | Native, GPO-manageable, scriptable |
| cPanel VPS | CSF (ConfigServer Firewall) | Purpose-built for cPanel, includes LFD daemon |
| Cloud VM (AWS/GCP/Azure) | Cloud security groups + host firewall | Defense in depth; cloud SGs are stateful and free |
Practical Key Takeaways
- Set default-deny inbound before writing any allow rules. This ensures that any rule you forget to write results in a blocked connection, not an open one.
- Never expose SSH to
0.0.0.0/0on a production server. Restrict it to a management IP, a VPN subnet, or use port knocking. - Write allow rules as specific as possible. Prefer
from 203.0.113.50 to any port 22 proto tcpoverallow 22. - Mirror IPv4 rules in IPv6. A firewall that only filters IPv4 is half a firewall.
- Enable connection-rate limiting on all authentication ports as a baseline brute-force mitigation.
- Log denied traffic. Silent drops without logging make incident response nearly impossible.
- Audit rules on a schedule. Stale rules are a liability, not a safety net.
- Test from outside. Use
nmapor an external port scanner after every significant rule change to confirm the effective attack surface. - Use
ufw reloadinstead ofufw disable && ufw enableto avoid dropping active connections during rule updates. - On
nftablesandiptables, always place theESTABLISHED/RELATEDaccept rule at the top of the input chain to avoid breaking outbound-initiated sessions.
Frequently Asked Questions
What is the difference between a firewall rule and a security group in cloud environments?
A security group (AWS, GCP, Azure) is a stateful, cloud-managed packet filter applied at the hypervisor level before traffic reaches your VM. A host-based firewall rule (UFW, firewalld) runs inside the OS kernel. Both should be used simultaneously for defense in depth β the cloud security group as the outer perimeter and the host firewall as the inner enforcement layer.
Why does UFW show a rule as active but traffic is still blocked?
The most common cause is rule ordering. A DENY rule earlier in the chain is matching before your ALLOW rule. Run sudo ufw status numbered and check the order. Also verify that IPv6 rules exist if the client is connecting over IPv6, and confirm the correct interface is targeted if the server is multi-homed.
Should I block ICMP entirely for security?
No. Blocking all ICMP breaks path MTU discovery, which causes TCP sessions to hang on networks with non-standard MTUs. It also breaks traceroute and makes network diagnostics significantly harder. Block only the ICMP types with no legitimate operational use (types 17 and 18). Allow echo request/reply, destination unreachable, and time exceeded.
What happens to active SSH connections when I reload UFW?
sudo ufw reload reloads the ruleset without flushing existing conntrack state entries. Active SSH sessions remain connected because the kernel's connection tracking table still holds their ESTABLISHED state. Only sudo ufw disable followed by sudo ufw enable would flush state and potentially drop active connections.
How do I prevent firewall rules from being lost after a system reboot?
UFW persists rules automatically across reboots via /etc/ufw/ configuration files. For firewalld, use the --permanent flag on every rule and run sudo firewall-cmd --reload. For raw nftables, save the ruleset with sudo nft list ruleset > /etc/nftables.conf and ensure the nftables systemd service is enabled. For iptables, use iptables-save > /etc/iptables/rules.v4 and install the iptables-persistent package.
on All Hosting Services