DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Linux Firewalld Setup

To secure our Nautilus infrastructure in Stratos Datacenter, we have decided to install and configure firewalld on one of the app servers named App Server 1. We have Apache and Nginx services running on these apps. Nginx is running as a reverse proxy server for Apache. We might have more robust firewall settings in the future, but for now we have decided to go with the given requirements listed below:

a. Allow all incoming connections on Nginx port, i.e 80.

b. Block all incoming connections on Apache port, i.e 8085.

c. All rules must be permanent.

d. Zone should be public.

e. If Apache or Nginx services aren't running already, please make sure to start them.


Understanding Firewalld

What is Firewalld

Firewalld is a firewall management tool that provides a dynamically managed firewall with support for network zones. It acts as a frontend for nftables or iptables and offers a simpler way to manage firewall rules compared to directly manipulating iptables.

Key Concepts

Firewalld uses zones to define trust levels for network connections. Each zone has its own set of rules. The public zone is the default zone and is used for public-facing services. Rich rules allow for more granular control over traffic, including dropping specific ports.

Zones Overview

Zone Description
public Public-facing services, default zone
trusted All network connections accepted
home Home network, more permissive
work Work network, moderate restrictions
drop All incoming connections dropped
block Incoming connections rejected

Prerequisites

Before beginning, ensure the following prerequisites are met. A Linux server with root or sudo access is required. The server should have Apache and Nginx installed. Basic command-line knowledge is necessary. Understanding of network ports and protocols is helpful.

Server Details for This Tutorial

Detail Value
Server App Server 1 (stapp01)
User tony
Password Ir0nM@n
Nginx Port 80
Apache Port 8085
Zone public

Step 1: Connect to the Server

Access the target server using SSH with the appropriate credentials.

ssh tony@stapp01
Password: Ir0nM@n
Enter fullscreen mode Exit fullscreen mode

Switch to root to perform administrative tasks.

sudo su -
Password: Ir0nM@n
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Firewalld

Install the firewalld package using the system package manager.

yum install -y firewalld
Enter fullscreen mode Exit fullscreen mode

The installation includes firewalld and its dependencies, including ipset, nftables, and python3-firewall.


Step 3: Start and Enable Firewalld

Start the firewalld service and enable it to start automatically on boot.

systemctl start firewalld
systemctl enable firewalld
Enter fullscreen mode Exit fullscreen mode

The enable command creates a symlink for the service to start on boot.


Step 4: Set the Default Zone

Configure the default zone to public as required.

firewall-cmd --set-default-zone=public
Enter fullscreen mode Exit fullscreen mode

Verify the default zone has been set correctly.

firewall-cmd --get-default-zone
Enter fullscreen mode Exit fullscreen mode

Step 5: Allow Nginx Port (80)

Add a permanent rule to allow incoming traffic on port 80 for Nginx.

firewall-cmd --zone=public --add-port=80/tcp --permanent
Enter fullscreen mode Exit fullscreen mode

The permanent flag ensures the rule persists across reboots.


Step 6: Block Apache Port (8085)

Remove any existing rule for port 8085 and add a rich rule to block it.

firewall-cmd --zone=public --remove-port=8085/tcp --permanent
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="8085" protocol="tcp" drop' --permanent
Enter fullscreen mode Exit fullscreen mode

The rich rule uses the drop action to silently discard packets on port 8085.


Step 7: Reload Firewall

Apply all the permanent rules by reloading the firewall.

firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Step 8: Configure and Start Services

Port Conflict Resolution

By default, both Apache and Nginx listen on port 80, causing a conflict. Since Nginx acts as a reverse proxy, Apache should listen on port 8085 while Nginx listens on port 80.

Configure Apache to listen on port 8085.

sed -i 's/^Listen 80/Listen 8085/' /etc/httpd/conf/httpd.conf
Enter fullscreen mode Exit fullscreen mode

Start Apache

systemctl start httpd
systemctl enable httpd
Enter fullscreen mode Exit fullscreen mode

Start Nginx

systemctl start nginx
systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

Verify Both Services

systemctl status httpd
systemctl status nginx
systemctl is-active httpd
systemctl is-active nginx
Enter fullscreen mode Exit fullscreen mode

Step 9: Complete Verification

Verify the firewall configuration and service status.

firewall-cmd --zone=public --list-all
firewall-cmd --zone=public --list-ports
firewall-cmd --zone=public --list-rich-rules
ss -tlnp | grep -E ":80|:8085"
Enter fullscreen mode Exit fullscreen mode

Understanding the Configuration

Firewall Rules Summary

Rule Port Action Permanent
Nginx 80/tcp Allow Yes
Apache 8085/tcp Block Yes
Zone public Default Yes

Rich Rule Breakdown

rule family="ipv4" port port="8085" protocol="tcp" drop
Enter fullscreen mode Exit fullscreen mode

The rich rule specifies IPv4 traffic on port 8085 using TCP protocol. The drop action silently discards packets without notifying the sender.

Service Ports

Service Default Port Configured Port
Nginx 80 80
Apache 80 8085

Alternative Methods

Using firewall-cmd with Different Syntax

firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" port port="8085" protocol="tcp" drop'
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Using Direct Rules

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 8085 -j DROP
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Using Services Instead of Ports

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Troubleshooting Common Issues

Firewalld Not Found

When the firewalld command is not found, install the package using the system package manager.

yum install -y firewalld
Enter fullscreen mode Exit fullscreen mode

Failed to Start Firewalld

Check the service logs for errors.

journalctl -u firewalld -n 50
systemctl restart firewalld
Enter fullscreen mode Exit fullscreen mode

Port Not Blocked

Verify the rich rule has been applied and reload the firewall.

firewall-cmd --zone=public --list-rich-rules
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Nginx Fails to Start

The most common cause is a port conflict with Apache. Check which service is using port 80.

ss -tlnp | grep :80
Enter fullscreen mode Exit fullscreen mode

If Apache is using port 80, stop Apache, reconfigure it to use port 8085, and start Nginx.

systemctl stop httpd
sed -i 's/^Listen 80/Listen 8085/' /etc/httpd/conf/httpd.conf
systemctl start httpd
systemctl start nginx
Enter fullscreen mode Exit fullscreen mode

Rules Not Permanent

Ensure the permanent flag is used with every firewall-cmd command that modifies rules.

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Verification Commands

# Check firewall status
systemctl status firewalld

# Check default zone
firewall-cmd --get-default-zone

# Check open ports
firewall-cmd --zone=public --list-ports

# Check rich rules
firewall-cmd --zone=public --list-rich-rules

# Check complete configuration
firewall-cmd --zone=public --list-all

# Check services status
systemctl is-active httpd
systemctl is-active nginx

# Check listening ports
ss -tlnp | grep -E ":80|:8085"

# Test connectivity
curl -I http://localhost:80
curl -I http://localhost:8085
Enter fullscreen mode Exit fullscreen mode

Expected Output

Firewall Configuration

public
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 80/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" port port="8085" protocol="tcp" drop
Enter fullscreen mode Exit fullscreen mode

Service Status

httpd: active
nginx: active
Enter fullscreen mode Exit fullscreen mode

Listening Ports

LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=34219,fd=6))
LISTEN 0 511 0.0.0.0:8085 0.0.0.0:* users:(("httpd",pid=8699,fd=4))
Enter fullscreen mode Exit fullscreen mode

Best Practices

Use Permanent Rules

Always use the permanent flag when adding rules to ensure they survive reboots.

firewall-cmd --zone=public --add-port=80/tcp --permanent
Enter fullscreen mode Exit fullscreen mode

Reload After Changes

Always reload the firewall after making permanent changes.

firewall-cmd --reload
Enter fullscreen mode Exit fullscreen mode

Document Rules

Maintain documentation of all firewall rules for audit purposes.

Test Before Production

Test firewall rules in a staging environment before applying to production.

Monitor Logs

Regularly check firewall logs for blocked traffic.

journalctl -u firewalld
tail -f /var/log/firewalld
Enter fullscreen mode Exit fullscreen mode

Automation Script

#!/bin/bash

echo "Firewall Configuration Script"
echo "=============================="

# Install firewalld
yum install -y firewalld

# Start and enable
systemctl start firewalld
systemctl enable firewalld

# Set zone
firewall-cmd --set-default-zone=public

# Allow port 80
firewall-cmd --zone=public --add-port=80/tcp --permanent

# Block port 8085
firewall-cmd --zone=public --remove-port=8085/tcp --permanent
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="8085" protocol="tcp" drop' --permanent

# Reload
firewall-cmd --reload

# Configure Apache port
sed -i 's/^Listen 80/Listen 8085/' /etc/httpd/conf/httpd.conf

# Start services
systemctl start httpd
systemctl enable httpd
systemctl start nginx
systemctl enable nginx

# Verify
echo "Verification:"
firewall-cmd --zone=public --list-all
systemctl is-active httpd
systemctl is-active nginx
Enter fullscreen mode Exit fullscreen mode

Conclusion

What Has Been Accomplished

Firewalld has been successfully installed and configured on App Server 1. Port 80 has been allowed for Nginx traffic, and port 8085 has been blocked for Apache using a rich rule. The zone has been set to public, and all rules have been made permanent. Both Apache and Nginx services are running with Apache on port 8085 and Nginx on port 80.

Key Takeaways

Firewalld provides a dynamic and flexible way to manage firewall rules. The public zone is the default and is suitable for public-facing services. Rich rules allow granular control over traffic. The permanent flag ensures rules persist across reboots. Port conflicts between services must be resolved by configuring services to use different ports.

Complete Solution Summary

# Firewall Rules
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --remove-port=8085/tcp --permanent
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="8085" protocol="tcp" drop' --permanent
firewall-cmd --reload

# Service Configuration
sed -i 's/^Listen 80/Listen 8085/' /etc/httpd/conf/httpd.conf
systemctl start httpd
systemctl enable httpd
systemctl start nginx
systemctl enable nginx

# Verification
firewall-cmd --zone=public --list-all
systemctl is-active httpd
systemctl is-active nginx
Enter fullscreen mode Exit fullscreen mode

Top comments (0)