dotlinux blog

How to Open Port for a Specific IP Address in Firewalld

When managing a Linux server, securing access to services is non-negotiable. Instead of opening a port to the entire internet (a major security risk), you can restrict access to only trusted IP addresses using Firewalld—the default firewall management tool for RHEL, Fedora, Rocky Linux, AlmaLinux, and other modern Linux distributions.

This guide will walk you through the process of allowing a specific IP address (or subnet) to access a designated port using Firewalld’s rich rules, which offer granular control over firewall policies. We’ll cover everything from prerequisites to troubleshooting, ensuring you can implement this security measure confidently.

Last Updated: 2026-04

Table of Contents#

  1. Prerequisites
  2. Understanding Firewalld Basics
  3. Step-by-Step Guide: Open Port for a Specific IP 3.1 Check Firewalld Status 3.2 Identify the Target Zone 3.3 Add a Temporary Rich Rule 3.4 Verify the Temporary Rule 3.5 Make the Rule Permanent 3.6 Verify Permanent Rules
  4. Managing Firewalld Rules 4.1 Remove a Rule 4.2 Allow a Subnet Instead of Single IP 4.3 Allow UDP Ports 4.4 Use Service Names Instead of Port Numbers
  5. Troubleshooting Common Issues
  6. Advanced Tips
  7. Conclusion
  8. References

Prerequisites#

Before you begin, ensure you have:

  • A Linux system with Firewalld installed (most modern RHEL-based distros include it by default).
  • Root or sudo privileges to execute firewall commands.
  • The specific IPv4/IPv6 address (or subnet) of the machine that needs access to the port.
  • The port number and protocol (TCP/UDP) of the service you want to expose (e.g., SSH uses TCP port 22, DNS uses UDP port 53).

Understanding Firewalld Basics#

Firewalld operates using two key concepts:

  1. Zones: Predefined rule sets that apply to network interfaces. Common zones include:
    • public: For untrusted public networks (default zone for most systems).
    • internal: For trusted internal networks.
    • trusted: Allows all incoming traffic (use sparingly).
  2. Rich Rules: Flexible, human-readable rules that let you create granular policies (e.g., allow a specific IP to access a specific port). Unlike basic port opening commands, rich rules target traffic from specific sources, making them ideal for our task.

Step-by-Step Guide: Open Port for a Specific IP#

Let’s walk through the process of allowing a trusted IP (e.g., 192.168.1.100) to access TCP port 22 (SSH) on your server.

3.1 Check Firewalld Status#

First, confirm Firewalld is running and enabled to start on boot:

# Check current status
sudo systemctl status firewalld
 
# Start Firewalld if it’s not running
sudo systemctl start firewalld
 
# Enable Firewalld to start automatically at boot
sudo systemctl enable firewalld

3.2 Identify the Target Zone#

Rules are applied to zones, so you need to know which zone your server’s network interface uses. To list active zones:

sudo firewall-cmd --get-active-zones

This will output something like:

public
  interfaces: eth0

In this example, the default zone is public.

3.3 Add a Temporary Rich Rule#

Temporary rules are applied immediately but will be lost if Firewalld restarts or the server reboots. Use this to test your rule first:

sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept'

Let’s break down each part of the rule:

  • family="ipv4": Target IPv4 traffic (use "ipv6" for IPv6 addresses).
  • source address="192.168.1.100": Allow traffic from this specific IP.
  • port protocol="tcp" port="22": Allow access to TCP port 22.
  • accept: Permit the traffic that matches the rule.

3.4 Verify the Temporary Rule#

Confirm the rule was added successfully:

sudo firewall-cmd --zone=public --list-rich-rules

You should see your rule listed in the output.

3.5 Make the Rule Permanent#

To ensure the rule persists across reboots, either: Option 1: Convert temporary rules to permanent:

sudo firewall-cmd --runtime-to-permanent

Option 2: Add the rule as permanent directly (recommended for new rules):

sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept' --permanent

Then reload Firewalld to apply the permanent changes:

sudo firewall-cmd --reload

3.6 Verify Permanent Rules#

Check that the permanent rule is saved:

sudo firewall-cmd --zone=public --list-rich-rules --permanent

Managing Firewalld Rules#

4.1 Remove a Rule#

To remove a temporary rule:

sudo firewall-cmd --zone=public --remove-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept'

To remove a permanent rule:

sudo firewall-cmd --zone=public --remove-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept' --permanent
sudo firewall-cmd --reload

4.2 Allow a Subnet Instead of Single IP#

If you want to allow an entire subnet (e.g., 192.168.1.0/24) to access a port, modify the source address to include the subnet mask:

sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="80" accept' --permanent
sudo firewall-cmd --reload

4.3 Allow UDP Ports#

To allow access to a UDP port (e.g., DNS on port 53), change the port protocol to udp:

sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="udp" port="53" accept' --permanent
sudo firewall-cmd --reload

4.4 Use Service Names Instead of Port Numbers#

For well-known services, you can use firewalld service names instead of raw port numbers. This is more readable and automatically handles the correct protocol:

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

To list available services: firewall-cmd --get-services.


Troubleshooting Common Issues#

If your rule isn’t working, check these common problems:

  1. Incorrect Zone: Ensure you applied the rule to the zone your server’s interface uses (check with firewall-cmd --get-active-zones).
  2. IP Address Typos: Double-check the source IP address in your rule.
  3. Protocol Mismatch: Use tcp for services like SSH, HTTP, or HTTPS; udp for DNS, DHCP, or streaming services.
  4. Rule Not Permanent: If the rule disappears after a reboot, you forgot to add the --permanent flag or run --runtime-to-permanent.
  5. Firewall Blocking Elsewhere: Ensure no other firewalls (e.g., cloud provider firewalls like AWS Security Groups) are blocking the traffic.
  6. Conflicting Rules: Check for conflicting rules with firewall-cmd --zone=<zone> --list-all. A broader rule may override your rich rule.
  7. nftables Backend Issues: If using firewalld 2.0+ with the nftables backend, ensure no leftover iptables rules are interfering. Check with nft list ruleset.

To test if the port is accessible from the trusted IP, use nc (netcat) or curl:

# From the trusted IP machine
nc -zv your-server-ip 22

Or for HTTP/HTTPS services:

curl -I http://your-server-ip:80

Advanced Tips#

  1. Log Allowed Connections: Add logging to your rule to track access attempts from the trusted IP:

    sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" log prefix="SSH_Access" level="info" accept' --permanent
    sudo firewall-cmd --reload

    Logs will be stored in /var/log/messages or /var/log/syslog.

  2. Deny All Other Access to the Port: To ensure only your trusted IP can access the port, deny all other traffic to that port (add this rule after your accept rule):

    sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port protocol="tcp" port="22" reject' --permanent
    sudo firewall-cmd --reload

    Warning: Only do this if you’re sure you won’t lock yourself out of the server.

  3. Use Custom Zones: For better organization, create a custom zone for trusted IPs and apply rules to it:

    sudo firewall-cmd --new-zone=trusted-ips --permanent
    sudo firewall-cmd --reload
    sudo firewall-cmd --zone=trusted-ips --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept' --permanent

    Then assign your server's interface to this zone if needed.

  4. Control Rule Execution Order with Priorities: Rich rules support a priority field (range: -32768 to 32767) that controls their execution order. Lower values are evaluated first, and negative priorities run before other firewalld primitives:

    sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" priority="100" accept' --permanent
    sudo firewall-cmd --reload
  5. Check Your Firewalld Version: Knowing your version helps determine which features are available (e.g., nftables backend, zone priorities):

    sudo firewall-cmd --version

    Firewalld 2.0+ (2023) uses nftables as the default backend and supports zone priorities.


Conclusion#

Opening a port for a specific IP address using Firewalld is a critical security practice that reduces your server’s attack surface by restricting access to trusted sources only. By leveraging rich rules, you can create granular policies tailored to your needs.

Remember to always test your rules before making them permanent, and verify that the traffic flows as expected. Check your firewalld version with firewall-cmd --version to confirm which features are available on your system. For more complex scenarios, refer to Firewalld’s official documentation.


References#