Firewalls

A firewall controls network traffic entering, leaving, or passing through a system.

A simple way to think about a firewall is:

A firewall is a rule-based traffic guard.

It checks packets against rules and decides whether to allow, block, reject, forward, or log them.

INTERNET TRAFFIC ---> |--------------------------| ---> INTERNAL NETWORK
   [IP:123.45.67.89]  |                          | [Accepted IP: 123.45.67.89]
   Port 80 HTTP       |    +----------------+    | Port 80 -> Allowed
                      |    |   FIREWALL     |    |
                      |    | Rules Applied: |    |
   [IP: 98.76.54.32]  |    | - Allow HTTP   |    | [Rejected IP: 98.76.54.32]
   Port 22 SSH        |    | - Block SSH    |    | Port 22 -> Blocked
                      |    +----------------+    |
                      |                          |
                      |--------------------------|

Firewalls are used to:

A firewall does not make a vulnerable service safe by itself, but it reduces what can reach that service.

Basic Firewall Concepts

A firewall rule usually answers these questions:

Firewall Rule Component Description
Direction Is the traffic incoming, outgoing, or forwarded?
Protocol Does the rule apply to TCP, UDP, ICMP, or all protocols?
Port Which port(s) are affected (e.g., 22, 80, 443, 8080)?
Source Which IP address or subnet is the traffic coming from?
Destination Which IP address or subnet is the traffic going to?
Action What should happen to matching traffic: allow, drop, reject, log, or forward?

Example:

Allow incoming TCP traffic from anywhere to port 22.

This means SSH is reachable.

Another example:

Deny incoming TCP traffic from anywhere to port 80.

This means HTTP is blocked.

Common Firewall Actions

Firewalls commonly use these actions:

Firewall Target Description
ACCEPT Allow the packet to pass.
DROP Silently discard the packet without notifying the sender.
REJECT Block the packet and send an error response to the sender.
LOG Record information about the packet, then continue processing subsequent rules.
DNAT (Destination NAT) Rewrite the packet's destination IP address and/or port.
SNAT (Source NAT) Rewrite the packet's source IP address.
MASQUERADE Dynamically rewrite the source IP address for NAT, commonly used for internet sharing when the external IP may change.

DROP is quiet. The client may wait until timeout.

REJECT is explicit. The client receives a refusal.

Example difference:

Action Client Behavior
DROP The packet is silently discarded. The client waits and eventually times out.
REJECT The packet is blocked and an error response is sent. The client quickly receives a "connection refused" or "unreachable" message.

Incoming, Outgoing, and Forwarded Traffic

Traffic direction matters.

Traffic Direction Description
Incoming traffic Remote client → this machine
Outgoing traffic This machine → remote server
Forwarded traffic One network → this machine/router → another network

Diagram:

Incoming:
Internet ---> Server

Outgoing:
Server ---> Internet

Forwarded:
LAN Client ---> Linux Router ---> Internet

Most host firewalls focus on incoming traffic.

Routers, gateways, and NAT systems also care heavily about forwarded traffic.

Ports and Protocols

Many services listen on well-known ports.

Port / Protocol Service
22/tcp SSH
53/tcp, 53/udp DNS
80/tcp HTTP
443/tcp HTTPS
25/tcp SMTP
3306/tcp MySQL / MariaDB
5432/tcp PostgreSQL
21/tcp FTP (control connection)

Check listening services with:

sudo ss -tulnp

Example output:

Netid State  Local Address:Port  Peer Address:Port Process
tcp   LISTEN 0.0.0.0:22          0.0.0.0:*         users:(("sshd",pid=1100,fd=3))
tcp   LISTEN 0.0.0.0:80          0.0.0.0:*         users:(("nginx",pid=2200,fd=6))

Interpretation:

Firewall Tools on Linux

Linux has several firewall management tools.

Common ones include:

This note focuses on:

A simple comparison:

Firewall Tool Description
iptables Low-level and powerful firewall framework; commonly found on older Linux systems.
ufw (Uncomplicated Firewall) Simple and beginner-friendly firewall interface; commonly used on Ubuntu.
firewalld Zone-based, dynamic firewall management tool; commonly used on Fedora, RHEL, CentOS, AlmaLinux, and Rocky Linux.

Modern systems often use nftables underneath, even when administrators use higher-level tools such as firewalld or ufw.

Safety Warning for Remote Servers

Firewall mistakes can lock you out of a remote server.

Before changing firewall rules over SSH:

A safe pattern is:

  1. Allow SSH from your trusted IP.
  2. Confirm the rule exists.
  3. Only then enable stricter defaults.
  4. Test with a new SSH session before closing the old one.

On remote servers, a bad firewall command can cause this:

iptables

iptables is a low-level firewall tool for managing packet filtering rules.

It uses tables, chains, and rules.

The most common table for basic filtering is:

filter

The default chains in the filter table are:

Diagram:

Packet entering local machine
        |
        v
INPUT chain
        |
        v
local service, if allowed


Packet leaving local machine
        |
        v
OUTPUT chain
        |
        v
network


Packet passing through machine
        |
        v
FORWARD chain
        |
        v
another network

Viewing iptables Rules

Use:

sudo iptables -L

A more useful version includes numbers and numeric ports:

sudo iptables -L -n -v --line-numbers

Example output:

Chain INPUT (policy ACCEPT)
num  pkts bytes target  prot opt in  out source      destination
1    1200  96K ACCEPT  all  --  *   *   0.0.0.0/0   0.0.0.0/0   ctstate RELATED,ESTABLISHED
2       5  420 DROP    icmp --  *   *   0.0.0.0/0   0.0.0.0/0   icmp echo-request
3     200 18K ACCEPT  tcp  --  *   *   0.0.0.0/0   0.0.0.0/0   tcp dpt:22
4      20 1600 ACCEPT tcp  --  *   *   0.0.0.0/0   0.0.0.0/0   tcp dpt:80

Chain FORWARD (policy DROP)
num  pkts bytes target  prot opt in  out source          destination
1       0    0 ACCEPT  all  --  *   *   192.168.1.0/24  192.168.1.0/24
2       0    0 DROP    all  --  *   *   0.0.0.0/0       0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
num  pkts bytes target  prot opt in  out source      destination

Interpretation:

iptables Rule Order

Rule order matters.

iptables checks rules from top to bottom.

Packet arrives
    |
    v
Rule 1 match? yes -> action
    |
    no
    v
Rule 2 match? yes -> action
    |
    no
    v
Rule 3 match? yes -> action
    |
    no
    v
Default policy

If a broad DROP rule appears before an ACCEPT rule, the later ACCEPT may never be reached.

Example bad order:

The SSH allow rule is useless because traffic was already dropped.

Adding an iptables Rule

Allow incoming HTTP:

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Meaning:

iptables Option Description
-A INPUT Append a rule to the INPUT chain.
-p tcp Match TCP packets.
--dport 80 Match packets with destination port 80.
-j ACCEPT Jump to the ACCEPT target and allow matching packets.

Allow SSH:

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Block ping:

sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

Deleting an iptables Rule

First list with line numbers:

sudo iptables -L INPUT -n -v --line-numbers

Example:

Chain INPUT (policy ACCEPT)
num  target  prot source      destination
1    ACCEPT  tcp  0.0.0.0/0   0.0.0.0/0   tcp dpt:22
2    ACCEPT  tcp  0.0.0.0/0   0.0.0.0/0   tcp dpt:80

Delete rule 2:

sudo iptables -D INPUT 2

Interpretation:

Saving iptables Rules

iptables changes are usually runtime-only unless saved.

On Debian-based systems:

sudo iptables-save | sudo tee /etc/iptables/rules.v4

You may need:

sudo apt install iptables-persistent

On older Red Hat-based systems:

sudo service iptables save

Important:

If rules are not saved, they may disappear after reboot.

ufw

UFW stands for Uncomplicated Firewall.

It provides a simpler interface for common firewall tasks.

It is common on Ubuntu and beginner-friendly systems.

Check status:

sudo ufw status numbered

Example output:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 1000:2000/tcp              ALLOW IN    192.168.1.0/24
[ 5] 22/tcp                     ALLOW IN    Anywhere (v6)
[ 6] 80/tcp                     ALLOW IN    Anywhere (v6)
[ 7] 443/tcp                    ALLOW IN    Anywhere (v6)

Interpretation:

Basic ufw Commands

Allow SSH:

sudo ufw allow ssh

Allow port 22 explicitly:

sudo ufw allow 22/tcp

Allow HTTP:

sudo ufw allow http

Allow HTTPS:

sudo ufw allow https

Deny HTTP:

sudo ufw deny http

Delete a numbered rule:

sudo ufw status numbered
sudo ufw delete 2

Enable UFW:

sudo ufw enable

Disable UFW:

sudo ufw disable

UFW Default Policies

A common safe server policy is:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

Meaning:

On a remote server, allow SSH before enabling UFW.

firewalld

firewalld is a dynamic firewall manager commonly used on Fedora, RHEL, CentOS, AlmaLinux, and Rocky Linux.

It organizes rules into zones.

A zone represents a trust level.

Examples:

Firewalld Zone Description
public For untrusted networks; only explicitly allowed services are accessible.
home For home networks with a moderate level of trust.
work For work networks with trusted devices and services.
internal For internal trusted networks.
trusted All network traffic is allowed.
drop Incoming traffic is silently dropped.
block Incoming traffic is rejected with an error response.

Diagram:

eth0 connected to internet
        |
        v
public zone
        |
        v
allow ssh, http, https


eth1 connected to office LAN
        |
        v
internal zone
        |
        v
allow more trusted services

Runtime vs Permanent Configuration

firewalld has two configurations:

Commands without --permanent usually affect runtime only.

Commands with --permanent save the rule, but the rule usually needs reload before it becomes active.

Common pattern:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

Viewing firewalld Rules

List active zone configuration:

sudo firewall-cmd --list-all

Example output:

public (active)
  target: default
  interfaces: eth0
  services: ssh dhcpv6-client http https
  ports: 8080/tcp 9090/tcp
  masquerade: no
  forward-ports:
  rich rules:
    rule family="ipv4" source address="192.168.0.0/24" accept
    rule family="ipv4" source address="10.0.0.0/8" port port="443" protocol="tcp" accept

Interpretation:

Check zones:

sudo firewall-cmd --get-zones
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones

Adding and Removing firewalld Rules

Allow SSH permanently:

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

Allow a custom port:

sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload

Remove HTTP:

sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload

List again:

sudo firewall-cmd --list-all

firewalld Zones and Interfaces

Move an interface to the internal zone:

sudo firewall-cmd --permanent --zone=internal --change-interface=eth1
sudo firewall-cmd --reload
sudo firewall-cmd --zone=internal --list-all

Create a custom zone:

sudo firewall-cmd --permanent --new-zone=web-admin
sudo firewall-cmd --permanent --zone=web-admin --add-service=https
sudo firewall-cmd --permanent --zone=web-admin --add-source=192.168.50.0/24
sudo firewall-cmd --reload

Interpretation:

firewalld Rich Rules

Rich rules allow more specific matching.

Allow HTTPS only from 10.0.0.0/8:

sudo firewall-cmd --permanent \
  --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" service name="https" accept'

sudo firewall-cmd --reload

List rich rules:

sudo firewall-cmd --list-rich-rules

Example output:

rule family="ipv4" source address="10.0.0.0/8" service name="https" accept

Interpretation:

Only clients from 10.0.0.0/8 match this HTTPS allow rule.

Choosing Between iptables, ufw, and firewalld

Use ufw:

Use firewalld:

Use iptables:

Rule of thumb:

Scenario 1: Allow SSH but Block HTTP with UFW

Allow remote administration through SSH while blocking web traffic on HTTP port 80.

Simulate

Check current status:

sudo ufw status numbered

Allow SSH:

sudo ufw allow 22/tcp

Deny HTTP:

sudo ufw deny 80/tcp

Enable UFW if not already enabled:

sudo ufw enable

Check

sudo ufw status numbered

Example output:

Status: active

     To        Action      From
     --        ------      ----
[ 1] 22/tcp    ALLOW IN    Anywhere
[ 2] 80/tcp    DENY IN     Anywhere

Test

From another machine:

ssh user@SERVER_IP
curl -I http://SERVER_IP

Example SSH result:

user@SERVER_IP's password:

Example HTTP result:

curl: (7) Failed to connect to SERVER_IP port 80: Connection refused

or:

curl: (28) Connection timed out

Interpretation:

Scenario 2: Deny Incoming by Default and Allow Outgoing

Create a secure default host firewall posture.

Simulate

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

Check

sudo ufw status verbose

Example output:

Status: active
Logging: on
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere

Interpretation:

Scenario 3: Block ICMP Echo Requests

Prevent the system from replying to ping requests.

iptables Simulation

sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

Check

sudo iptables -L INPUT -n -v --line-numbers

Example output:

num  pkts bytes target prot opt source      destination
1       3   252 DROP   icmp --  0.0.0.0/0   0.0.0.0/0   icmp echo-request

Test

From another host:

ping SERVER_IP

Example output:

PING SERVER_IP 56(84) bytes of data.
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2

Interpretation:

Remove the Rule

List line numbers:

sudo iptables -L INPUT --line-numbers

Delete the matching rule number:

sudo iptables -D INPUT 1

Scenario 4: Allow HTTP Only from One IP Address

Restrict access to a web service so only one trusted client can connect.

UFW Simulation

Allow HTTP from one IP:

sudo ufw allow from 192.168.1.50 to any port 80 proto tcp

Deny other HTTP traffic:

sudo ufw deny 80/tcp

Check

sudo ufw status numbered

Example output:

Status: active

     To        Action      From
     --        ------      ----
[ 1] 80/tcp    ALLOW IN    192.168.1.50
[ 2] 80/tcp    DENY IN     Anywhere

Test

From allowed host:

curl -I http://SERVER_IP

Example output:

HTTP/1.1 200 OK

From blocked host:

curl -I http://SERVER_IP

Example output:

curl: (28) Failed to connect: Connection timed out

Interpretation:

Scenario 5: Safely Change Firewall Rules on a Remote Server

Avoid locking yourself out while changing firewall rules over SSH.

Safe Pattern with UFW

First, find your client IP from the server side:

echo "$SSH_CLIENT"

Example output:

203.0.113.25 53244 22

Allow SSH from your IP:

sudo ufw allow from 203.0.113.25 to any port 22 proto tcp

Allow fallback SSH generally if needed:

sudo ufw allow 22/tcp

Then set defaults:

sudo ufw default deny incoming
sudo ufw default allow outgoing

Enable:

sudo ufw enable

Open a new terminal and test a second SSH connection before closing the first.

Optional Rollback Timer

Before risky changes, schedule a rollback:

echo "sudo ufw disable" | at now + 5 minutes

If the firewall works, cancel the job:

atq
atrm JOB_ID

Interpretation:

Scenario 6: Allow SSH Only from Trusted IPs

Reduce SSH attack surface by allowing only known source addresses.

UFW Simulation

Allow trusted IP:

sudo ufw allow from 203.0.113.25 to any port 22 proto tcp

Deny other SSH:

sudo ufw deny 22/tcp

Check

sudo ufw status numbered

Example output:

Status: active

     To        Action      From
     --        ------      ----
[ 1] 22/tcp    ALLOW IN    203.0.113.25
[ 2] 22/tcp    DENY IN     Anywhere

Interpretation:

Important Warning

Scenario 7: Rate-Limit Incoming Connections

Limit repeated connection attempts to reduce brute-force or abuse.

UFW SSH Rate Limit

UFW has a simple built-in rate limit:

sudo ufw limit ssh

Check:

sudo ufw status numbered

Example output:

Status: active

     To        Action      From
     --        ------      ----
[ 1] 22/tcp    LIMIT IN    Anywhere

Interpretation:

iptables Example

Limit new TCP connections to port 8080:

sudo iptables -A INPUT -p tcp --dport 8080 -m conntrack --ctstate NEW \
  -m limit --limit 100/minute --limit-burst 20 -j ACCEPT

sudo iptables -A INPUT -p tcp --dport 8080 -j DROP

Check:

sudo iptables -L INPUT -n -v --line-numbers

Example output:

num  pkts bytes target prot source      destination
1    1000  60K ACCEPT tcp  0.0.0.0/0   0.0.0.0/0 tcp dpt:8080 ctstate NEW limit: avg 100/min burst 20
2     200  12K DROP   tcp  0.0.0.0/0   0.0.0.0/0 tcp dpt:8080

Interpretation:

Scenario 8: Log Dropped Packets

Record blocked packets for investigation.

iptables Simulation

Add a logging rule before a drop rule:

sudo iptables -A INPUT -m limit --limit 10/min --limit-burst 5 \
  -j LOG --log-prefix "iptables denied: " --log-level 4

sudo iptables -A INPUT -j DROP

Check Logs

On many systems:

sudo journalctl -k | grep "iptables denied"

or:

sudo dmesg | grep "iptables denied"

Example log:

kernel: iptables denied: IN=eth0 OUT= MAC=... SRC=198.51.100.20 DST=203.0.113.10 LEN=60 PROTO=TCP SPT=51512 DPT=23

Interpretation:

Important Warning

Scenario 9: Forward Port 8080 to Port 80

Redirect traffic arriving on port 8080 to a service listening on port 80.

Local Redirect with iptables

This redirects local incoming TCP port 8080 to port 80:

sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80

If testing from the same host, also use OUTPUT redirect:

sudo iptables -t nat -A OUTPUT -p tcp -o lo --dport 8080 -j REDIRECT --to-port 80

Check NAT Rules

sudo iptables -t nat -L -n -v --line-numbers

Example output:

Chain PREROUTING (policy ACCEPT)
num  pkts bytes target   prot source      destination
1      10   600 REDIRECT tcp  0.0.0.0/0   0.0.0.0/0 tcp dpt:8080 redir ports 80

Test

Run a web server on port 80, then from another host:

curl -I http://SERVER_IP:8080

Example output:

HTTP/1.1 200 OK

Interpretation:

Scenario 10: Block Outgoing Traffic to a Specific IP

Prevent the server from connecting to a known unwanted destination.

UFW Simulation

Block outgoing traffic to a specific IP:

sudo ufw deny out to 203.0.113.200

Check

sudo ufw status numbered

Example output:

Status: active

     To              Action      From
     --              ------      ----
[ 1] 203.0.113.200   DENY OUT    Anywhere

Test

curl http://203.0.113.200

Example output:

curl: (7) Failed to connect to 203.0.113.200 port 80

Interpretation:

Note About Domains

Firewalls usually filter IP addresses, ports, protocols, and interfaces.

Blocking domains is more complicated because domain names can resolve to changing IP addresses.

For domain-based blocking, consider:

Scenario 11: firewalld Public Zone with HTTP and HTTPS

Allow web traffic using firewalld.

Simulate

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Check

sudo firewall-cmd --list-all

Example output:

public (active)
  services: ssh http https
  ports:

Interpretation:

Check listening services:

sudo ss -tulnp | grep -E ':80|:443'

Scenario 12: firewalld Custom Port

Allow a custom TCP port, such as 8443.

Simulate

sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload

Check

sudo firewall-cmd --list-ports

Example output:

8443/tcp

Interpretation:

Scenario 13: firewalld Runtime vs Permanent Rule

Understand why a rule may disappear after reload.

Add Runtime Rule Only

sudo firewall-cmd --add-port=9090/tcp

Check:

sudo firewall-cmd --list-ports

Example:

9090/tcp

Reload:

sudo firewall-cmd --reload

Check again:

sudo firewall-cmd --list-ports

Example:

No output.

Interpretation:

Permanent Fix

sudo firewall-cmd --permanent --add-port=9090/tcp
sudo firewall-cmd --reload

Scenario 14: Diagnose “Service Is Running but Not Reachable”

Use firewall tools to separate service problems from firewall problems.

Symptom

A web service should be reachable, but clients cannot connect.

Step 1: Check Service

sudo systemctl status nginx

Example:

Active: active (running)

Step 2: Check Listening Port

sudo ss -tulnp | grep ':80'

Example:

tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=2200,fd=6))

Interpretation:

Step 3: Check Firewall

UFW:

sudo ufw status numbered

firewalld:

sudo firewall-cmd --list-all

iptables:

sudo iptables -L INPUT -n -v --line-numbers

Example Firewall Output

Status: active

To        Action      From
--        ------      ----
22/tcp    ALLOW IN    Anywhere
80/tcp    DENY IN     Anywhere

Interpretation:

Fix with UFW

sudo ufw allow 80/tcp

Scenario 15: Diagnose “Firewall Rule Exists but Still Cannot Connect”

Understand that firewall rules are only one part of connectivity.

Checklist

  1. Is the service running?
  2. Is the service listening on the expected port?
  3. Is it listening on the correct address?
  4. Does the firewall allow the traffic?
  5. Is the cloud firewall/security group open?
  6. Is the client using the correct IP and port?
  7. Is routing correct?
  8. Is SELinux blocking the service?

Commands:

sudo systemctl status SERVICE
sudo ss -tulnp
ip addr
ip route
sudo ufw status numbered
sudo firewall-cmd --list-all
sudo iptables -L -n -v

Example issue:

Check:

sudo ss -tulnp | grep ':80'

Output:

tcp LISTEN 0 511 127.0.0.1:80 0.0.0.0:* users:(("nginx",pid=2200,fd=6))

Interpretation:

Common Firewall Troubleshooting Workflow

When a connection fails:

  1. Identify source IP, destination IP, protocol, and port.
  2. Check whether the service is listening.
  3. Check local firewall rules.
  4. Check cloud or upstream firewall rules.
  5. Test from the client.
  6. Check logs and packet counters.
  7. Confirm rule order.
  8. Confirm persistence after reboot or reload.

Step 1: Identify the Traffic

Example:

Field Value
Client IP 192.168.1.50
Server IP 192.168.1.10
Protocol TCP
Port 443
Direction Incoming

This prevents vague troubleshooting.

Step 2: Check Service Listening

sudo ss -tulnp | grep ':443'

If there is no listener, the firewall is not the only issue.

Step 3: Check Firewall Rules

UFW:

sudo ufw status numbered

firewalld:

sudo firewall-cmd --list-all

iptables:

sudo iptables -L INPUT -n -v --line-numbers

Step 4: Check Packet Counters

iptables counters can show whether traffic is matching rules.

sudo iptables -L INPUT -n -v --line-numbers

Example:

num  pkts bytes target prot source      destination
1       0     0 ACCEPT tcp  0.0.0.0/0   0.0.0.0/0 tcp dpt:443
2     150  9K DROP   all  0.0.0.0/0   0.0.0.0/0

Interpretation:

Step 5: Test from Client

Use:

curl -I http://SERVER_IP
nc -vz SERVER_IP 22
nc -vz SERVER_IP 443

Example:

Connection to SERVER_IP 22 port [tcp/ssh] succeeded!

Interpretation:

Useful Command Summary

Check listening services:

sudo ss -tulnp

iptables:

sudo iptables -L -n -v --line-numbers
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -D INPUT RULE_NUMBER
sudo iptables-save

UFW:

sudo ufw status numbered
sudo ufw status verbose
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw deny 80/tcp
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw delete RULE_NUMBER

firewalld:

sudo firewall-cmd --list-all
sudo firewall-cmd --get-zones
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-rich-rules

Testing:

curl -I http://SERVER_IP
nc -vz SERVER_IP PORT
ping SERVER_IP
traceroute SERVER_IP

Logs:

sudo journalctl -k
sudo dmesg
sudo journalctl -u firewalld
sudo tail -f /var/log/ufw.log

Safe Lab Cleanup

If you added temporary iptables rules, list them first:

sudo iptables -L INPUT -n -v --line-numbers

Delete only the test rules by number:

sudo iptables -D INPUT RULE_NUMBER

For UFW, list and delete numbered rules:

sudo ufw status numbered
sudo ufw delete RULE_NUMBER

For firewalld test ports:

sudo firewall-cmd --permanent --remove-port=8443/tcp
sudo firewall-cmd --permanent --remove-port=9090/tcp
sudo firewall-cmd --reload

If you created a custom firewalld zone:

sudo firewall-cmd --permanent --delete-zone=web-admin
sudo firewall-cmd --reload

Practical Challenges

  1. Configure the firewall to allow SSH on port 22 but block HTTP on port 80. Test both from another machine.
  2. Set the default policy to deny incoming traffic and allow outgoing traffic. Explain why SSH must be allowed before enabling this policy remotely.
  3. Block ICMP echo requests and confirm that another host cannot ping the machine. Then remove the rule and test again.
  4. Allow HTTP only from a specific IP address. Test from the allowed IP and from a blocked IP.
  5. Create a safe rollback plan before changing firewall rules on a remote server.
  6. Restrict SSH to a trusted source IP. Explain the risk if your source IP changes.
  7. Rate-limit SSH or another TCP service and explain what kind of abuse this helps reduce.
  8. Add logging for dropped packets with rate limiting. Review logs and interpret one dropped packet entry.
  9. Forward local port 8080 to port 80 and verify that traffic to 8080 reaches the web service.
  10. Block outgoing traffic to a specific IP address and test the result with curl or nc.
  11. With firewalld, add a runtime-only port rule, reload firewalld, and observe that the rule disappears.
  12. With firewalld, create a permanent custom port rule and verify it survives reload.
  13. Diagnose a service that is running but unreachable. Check the service, listening port, firewall rules, and client test output.
  14. Compare the same rule implemented with iptables, ufw, and firewalld.
  15. Write a short firewall troubleshooting report including source IP, destination IP, protocol, port, rule checked, test command, output, and interpretation.