dotlinux guide

Setting Up Linux Firewalls: A Step-by-Step Guide for Admins

In today’s interconnected world, securing Linux servers is paramount. A firewall acts as the first line of defense, controlling incoming and outgoing network traffic based on predefined rules. Linux systems offer robust, built-in firewall tools that integrate with the kernel’s netfilter framework, providing granular control over network access. Whether you’re managing a small VPS or a large enterprise infrastructure, understanding how to configure Linux firewalls is critical for mitigating threats like unauthorized access, data breaches, and malware. This guide demystifies Linux firewall concepts and provides step-by-step instructions for setting up firewalls using three popular tools: ufw (Uncomplicated Firewall), firewalld, and iptables. We’ll cover fundamental concepts, common use cases, and best practices to help you secure your systems efficiently.

Table of Contents

1. Fundamentals of Linux Firewalls

1.1 What is a Firewall?

A firewall is a network security device that monitors and filters incoming/outgoing traffic based on predefined security rules. Its primary goal is to allow legitimate traffic while blocking malicious or unauthorized activity. On Linux, firewalls are implemented at the kernel level (via netfilter) and managed via user-space tools.

1.2 Linux Firewall Tools: iptables, ufw, and firewalld

Linux offers multiple firewall management tools, each with its use case:

  • iptables: A low-level, command-line tool that directly interacts with the netfilter kernel framework. It’s powerful but complex, requiring manual rule management.
  • ufw (Uncomplicated Firewall): A frontend for iptables designed for simplicity. Ideal for beginners and small-scale systems (e.g., Ubuntu, Debian).
  • firewalld: A dynamic firewall manager with support for zones and services. Common in enterprise environments (e.g., RHEL, CentOS, Fedora) and supports runtime rule changes without restarting.

1.3 How Linux Firewalls Work: Netfilter, Chains, and Policies

At the core of Linux firewalls is netfilter—a kernel subsystem that hooks into network stack layers to filter packets. User-space tools like iptables or firewalld configure netfilter rules.

Key concepts:

  • Chains: Predefined sequences of rules (e.g., INPUT for incoming traffic, OUTPUT for outgoing, FORWARD for routed traffic).
  • Rules: Conditions that packets must match (e.g., port, IP, protocol) and actions (targets) like ACCEPT, DROP, or REJECT.
  • Policies: Default action for a chain when no rules match (e.g., DROP all incoming traffic by default).

2. Step-by-Step Setup with ufw (Uncomplicated Firewall)

2.1 Installing ufw

ufw is preinstalled on Ubuntu/Debian. For other distros:

# Debian/Ubuntu
sudo apt update && sudo apt install ufw -y

# Fedora/RHEL (if not preinstalled)
sudo dnf install ufw -y

2.2 Basic ufw Configuration

  1. Check status (initially inactive):

    sudo ufw status verbose
  2. Set default policies (deny incoming, allow outgoing):

    sudo ufw default deny incoming   # Block all unsolicited incoming traffic
    sudo ufw default allow outgoing  # Allow all outgoing traffic
  3. Allow essential services (e.g., SSH, HTTP):

    sudo ufw allow 22/tcp   # SSH (TCP port 22)
    sudo ufw allow 80/tcp   # HTTP (TCP port 80)
    sudo ufw allow 443/tcp  # HTTPS (TCP port 443)
  4. Enable ufw (starts on boot):

    sudo ufw enable
  5. Verify rules:

    sudo ufw status numbered  # List rules with numbers (for deletion)

2.3 Advanced ufw Rules

  • Allow traffic from a specific IP:

    sudo ufw allow from 192.168.1.100 to any port 22/tcp  # Allow SSH from 192.168.1.100
  • Deny a port/protocol:

    sudo ufw deny 3306/tcp  # Block MySQL port 3306
  • Delete a rule (use rule number from status numbered):

    sudo ufw delete 2  # Delete the 2nd rule
  • Rate-limiting (block repeated SSH attempts):

    sudo ufw limit 22/tcp  # Allow 6 connections/30s per IP (prevents brute-force)

3. Step-by-Step Setup with firewalld

3.1 Installing and Enabling firewalld

Preinstalled on RHEL/CentOS/Fedora. For Debian/Ubuntu:

sudo apt install firewalld -y
sudo systemctl enable --now firewalld  # Start and enable on boot

3.2 Basic firewalld Configuration

  1. Check status:

    sudo firewall-cmd --state          # Should return "running"
    sudo firewall-cmd --list-all       # List active rules and zones
  2. Set default zone (e.g., public for untrusted networks):

    sudo firewall-cmd --set-default-zone=public
  3. Allow services (uses predefined service files in /usr/lib/firewalld/services/):

    # Allow HTTP/HTTPS permanently (--permanent saves across reboots)
    sudo firewall-cmd --add-service=http --permanent
    sudo firewall-cmd --add-service=https --permanent
    
    # Allow SSH (already enabled in most default zones)
    sudo firewall-cmd --add-service=ssh --permanent
  4. Reload to apply changes:

    sudo firewall-cmd --reload  # Applies permanent rules without restarting

3.3 Advanced firewalld Rules

  • Allow a custom port:

    sudo firewall-cmd --add-port=8080/tcp --permanent  # Allow TCP port 8080
  • Limit SSH to a specific IP:

    sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent
  • Enable logging (denied packets):

    sudo firewall-cmd --set-log-denied=all --permanent
    sudo firewall-cmd --reload
  • List all services/ports:

    sudo firewall-cmd --list-services  # List allowed services
    sudo firewall-cmd --list-ports     # List allowed ports

4. Step-by-Step Setup with iptables

4.1 Understanding iptables Basics

iptables directly configures netfilter and uses tables (e.g., filter, nat) and chains. The filter table (default) handles packet filtering with chains: INPUT, OUTPUT, FORWARD.

4.2 Basic iptables Rules

  1. Check existing rules (may be empty by default):

    sudo iptables -L -v --line-numbers  # -L: list, -v: verbose, --line-numbers: rule numbers
  2. Set default policies (deny incoming, allow outgoing):

    sudo iptables -P INPUT DROP       # Drop all incoming traffic by default
    sudo iptables -P OUTPUT ACCEPT    # Allow all outgoing traffic
    sudo iptables -P FORWARD DROP     # Block forwarded traffic (if not a router)
  3. Allow loopback traffic (critical for system processes):

    sudo iptables -A INPUT -i lo -j ACCEPT  # Allow traffic on loopback interface (lo)
  4. Allow established/related connections (e.g., HTTP responses):

    sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
  5. Allow SSH, HTTP, HTTPS:

    sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT    # SSH
    sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # HTTP
    sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT   # HTTPS

4.3 Saving and Restoring iptables Rules

iptables rules are temporary (lost on reboot). Save them:

  • Debian/Ubuntu:

    sudo apt install iptables-persistent -y  # Installs persistence tool
    sudo netfilter-persistent save           # Saves rules to /etc/iptables/rules.v4
  • RHEL/CentOS/Fedora:

    sudo iptables-save > /etc/sysconfig/iptables  # Save to file
    sudo systemctl enable --now iptables          # Restore on boot (RHEL 7 and earlier)
    # For RHEL 8+/Fedora, use `firewalld` instead or `iptables-services` package.
  • Restore rules manually:

    sudo iptables-restore < /etc/iptables/rules.v4

5. Common Firewall Practices

5.1 Allowing Essential Services (SSH, HTTP/HTTPS)

Always prioritize allowing critical services like SSH (remote management) and HTTP/HTTPS (web servers). Use specific ports/protocols (e.g., 22/tcp for SSH) instead of broad rules.

5.2 Blocking Unused Ports

Default-deny incoming policies ensure unused ports (e.g., 3306/MySQL, 21/FTP) are blocked unless explicitly allowed. Audit open ports with:

sudo ss -tuln  # List listening TCP/UDP ports

5.3 Limiting SSH Brute-Force Attacks

  • With ufw: Use sudo ufw limit 22/tcp.
  • With iptables: Use the recent module to block repeated attempts:
    sudo iptables -A INPUT -p tcp --dport 22 -m recent --name ssh_brute --rcheck --seconds 60 --hitcount 5 -j DROP
    sudo iptables -A INPUT -p tcp --dport 22 -m recent --name ssh_brute --set -j ACCEPT
    (Blocks IPs with 5+ SSH attempts in 60 seconds.)

5.4 Logging Firewall Events

Logging helps debug and detect attacks.

  • ufw:

    sudo ufw logging on  # Enable logging (low/medium/high)
  • firewalld:

    sudo firewall-cmd --set-log-denied=all --permanent && sudo firewall-cmd --reload
  • iptables:

    sudo iptables -A INPUT -j LOG --log-prefix "DENIED_INPUT: " --log-level 4  # Log denied input

    Logs are stored in /var/log/kern.log (Debian/Ubuntu) or /var/log/messages (RHEL/CentOS).

6. Best Practices for Linux Firewalls

  1. Least Privilege: Only allow traffic required for your use case (e.g., block port 22 unless SSH is needed).
  2. Audit Rules Regularly: Use ufw status, firewall-cmd --list-all, or iptables -L to review rules.
  3. Test Rules Before Deployment: Use a staging environment to avoid locking yourself out (e.g., test SSH rules with a secondary terminal).
  4. Backup Rules: Save rules to a file (e.g., iptables-save > backup.rules) to restore after failures.
  5. Document Changes: Track rule modifications for compliance and troubleshooting.
  6. Use Centralized Management: For large fleets, use tools like Ansible, Puppet, or firewalld’s firewall-cmd --runtime-to-permanent for consistency.
  7. Update Firewall Software: Keep ufw, firewalld, or iptables updated to patch vulnerabilities.

7. Conclusion

Linux firewalls are critical for securing servers and networks. Whether you choose ufw (simplicity), firewalld (enterprise dynamic management), or iptables (low-level control), the core principles remain: default-deny policies, least privilege, and regular auditing. By following this guide and best practices, you can build a robust defense against unauthorized access and cyber threats.

8. References