Block ICMP Traffic in Linux using iptables

CompTIABeginner
Practice Now

Introduction

In this lab, you will learn how to use iptables, a powerful command-line firewall utility in Linux, to block incoming ICMP traffic. You will configure a firewall rule to drop packets from the ICMP protocol, which is commonly used by the ping command to test network connectivity. This is a fundamental skill for securing a Linux system by controlling network access at the protocol level.

You will begin by performing a preliminary network scan with nmap to assess the system's open ports. Then, you will establish a baseline by using ping to verify that ICMP traffic is initially allowed. The core of the lab involves creating and applying a specific iptables rule to drop all incoming ICMP packets. Finally, you will verify that the rule is active and test its effectiveness by attempting to ping your machine again, confirming that the requests are now successfully blocked.

Scan for Open TCP and UDP Ports with nmap

In this step, you will learn how to use the nmap tool to scan your own system for open network ports. Network ports are the endpoints of communication in an operating system. When a program wants to receive information from the network, it "listens" on a specific port. Scanning for open ports is a fundamental first step in assessing the security of a machine, as each open port represents a potential entry point for an attacker.

First, you need to install nmap, as it is not included in the base environment. It's good practice to update your package list before installing new software.

Run the following command to update the package list:

sudo apt-get update

Now, install nmap by running:

sudo apt-get install -y nmap

You should see output indicating that nmap and its dependencies are being installed.

Next, you need to find your machine's IP address to tell nmap what to scan. You can find this using the ip command.

ip addr show

Look for an entry like eth0 or ens33. Your IP address will be listed next to inet. It will look something like 172.16.50.13/24.

How to identify your IP address from the output:

  1. Look for the interface that has state UP (usually eth0)
  2. Find the line that starts with inet (not inet6)
  3. Take only the IP address part before the / (e.g., if you see inet 172.16.50.13/24, your IP address is 172.16.50.13)
  4. Ignore the loopback interface (lo) with IP 127.0.0.1

For the rest of this lab, we will use <your_IP_address> as a placeholder for your actual IP address.

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:04:c3:1d brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 172.16.50.13/24 metric 100 brd 172.16.50.255 scope global dynamic eth0
       valid_lft 1892159940sec preferred_lft 1892159940sec
    inet6 fe80::216:3eff:fe04:c31d/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:1d:45:49:f8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

Now you are ready to perform your first scan. Let's start by scanning for open TCP (Transmission Control Protocol) ports. TCP is a connection-oriented protocol that is used for many common services like SSH (port 22) and HTTP (port 80). The -sT option in nmap performs a TCP connect scan.

Important: Replace <your_IP_address> with the actual IP you found from the previous step. For example, if your IP is 172.16.50.13, the command would be nmap -sT 172.16.50.13.

Replace <your_IP_address> with the IP you found and run the command:

nmap -sT <your_IP_address>

The output will list the ports that are in the "open" state. Your system will likely have the SSH port (22) open by default, and may have additional services running on other ports.

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-01 14:08 CST
Nmap scan report for iZrj93qpoj98oqswu96cqfZ (172.16.50.13)
Host is up (0.00013s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp
3001/tcp open  nessus

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

Next, let's scan for UDP (User Datagram Protocol) ports. UDP is a connectionless protocol used for services like DNS (port 53) and DHCP (port 67/68). UDP scans can be slower and less reliable than TCP scans. Using sudo provides better results for UDP scans. The -sU option tells nmap to perform a UDP scan.

Remember: Replace <your_IP_address> with your actual IP address from the previous step.

Replace <your_IP_address> with your IP and run the command:

sudo nmap -sU <your_IP_address>

The output might show ports as open|filtered. This means nmap cannot determine if the port is open or if a firewall is blocking the scan. This is a common result for UDP scans.

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-01 14:09 CST
Nmap scan report for iZrj93qpoj98oqswu96cqfZ (172.16.50.13)
Host is up (0.0000060s latency).
Not shown: 998 closed ports
PORT     STATE         SERVICE
68/udp   open|filtered dhcpc
5353/udp open|filtered zeroconf

Nmap done: 1 IP address (1 host up) scanned in 1.29 seconds

By completing these scans, you have successfully identified the services listening for network connections on your machine.

Verify Initial Network Connectivity with ping

In this step, you will use the ping command to verify that your system is responsive to network requests before implementing any firewall rules. The ping command sends ICMP (Internet Control Message Protocol) "echo request" packets to a target host. If the host is reachable and configured to respond, it will send back an "echo reply" packet. This is a fundamental way to test basic network connectivity.

Before we create a firewall rule to block this type of traffic, we must first confirm that the traffic is currently being allowed. This ensures that when we test our rule later, we can be certain that the rule is the cause of the block, not some other pre-existing network issue.

We will ping the "loopback" address, 127.0.0.1. This special IP address always points to your own machine, allowing you to test the local network stack without needing an external connection or even knowing your machine's assigned IP address.

To send just four packets and then stop, we will use the -c 4 option. This is important because, without it, ping would run continuously until you manually stop it with Ctrl+C.

Open your terminal and run the following command:

ping -c 4 127.0.0.1

You should see output showing that four packets were sent and four were received, indicating that your system is correctly responding to ICMP requests.

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.053 ms

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3070ms
rtt min/avg/max/mdev = 0.045/0.051/0.055/0.003 ms

The 0% packet loss line confirms that the connection is working perfectly. Now that you've established a baseline, you are ready to configure a firewall rule to block this exact type of communication.

Create an iptables Rule to Drop ICMP Packets

In this step, you will configure a simple firewall rule using iptables, the standard command-line utility for managing network packet filtering rules in the Linux kernel. We will create a rule to block the ICMP traffic that you previously tested with the ping command.

iptables works with a system of tables, chains, and rules.

  • Tables: These are collections of chains for a specific purpose. The most commonly used table is filter, which is the default and is used for packet filtering.
  • Chains: These are lists of rules that are checked in order. For incoming traffic, the INPUT chain is used.
  • Rules: A rule specifies criteria for a packet (like its protocol or source address) and a target (what to do with the packet, e.g., ACCEPT or DROP).

First, let's examine the current set of rules. Since iptables modifies kernel settings, you must use sudo. The -L option lists the rules in the default filter table.

sudo iptables -L

You will see the three default chains: INPUT, FORWARD, and OUTPUT. In this environment, you may notice that Docker has already created some rules in the FORWARD chain and added custom chains for container networking. The INPUT and OUTPUT chains are still using the default ACCEPT policy for regular traffic.

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-USER  all  --  anywhere             anywhere
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (1 references)
target     prot opt source               destination

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-USER (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Now, let's add a rule to block incoming ICMP packets. We will append (-A) a new rule to the INPUT chain.

The command is constructed as follows:

  • sudo iptables: The command to manage the firewall.
  • -A INPUT: Append a rule to the INPUT chain.
  • -p icmp: This rule applies to packets using the icmp protocol.
  • -j DROP: If a packet matches, jump to the DROP target, which silently discards the packet without sending a response.

Run the following command to create the rule:

sudo iptables -A INPUT -p icmp -j DROP

This command will not produce any output if successful. You have now instructed the kernel firewall to drop all incoming ICMP packets from any source.

Verify the Firewall Rule and Test the Block

In this final step, you will confirm that your new firewall rule has been successfully added and then test its effect by attempting to ping your system again. This process of verification is critical in network administration to ensure that security policies are implemented correctly.

First, let's view the list of rules again to see your new addition. By running the same command as before, you can see the current state of the firewall.

sudo iptables -L

You should now see your new rule listed under the INPUT chain. The output clearly shows that packets matching the icmp protocol will be sent to the DROP target.

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       icmp --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Now that you've confirmed the rule is in place, let's test it. Run the same ping command you used in Step 2.

ping -c 4 127.0.0.1

This time, you will see no replies. The command will seem to hang for a few seconds and then exit. The output will show 100% packet loss. This is the expected behavior because the kernel's firewall is now silently dropping the incoming ICMP packets, just as you instructed.

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3055ms

You have successfully blocked ICMP traffic! The rules you create with iptables are not persistent and will be cleared upon a system reboot. However, it's good practice to know how to remove a rule manually. You can do this using the -D (delete) flag, specifying the exact same rule you added.

Let's remove the rule to restore connectivity.

sudo iptables -D INPUT -p icmp -j DROP

To confirm the rule is gone and connectivity is restored, run ping one last time.

ping -c 2 127.0.0.1

The ping should now succeed, confirming that you have successfully removed the firewall rule.

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.058 ms

--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1024ms
rtt min/avg/max/mdev = 0.048/0.053/0.058/0.005 ms

Summary

In this lab, you learned how to perform initial network reconnaissance on a Linux system. You started by installing the nmap tool to scan for open TCP and UDP ports after identifying the machine's IP address. Following this, you established a baseline for network connectivity by using the ping command, which confirmed that the system was successfully receiving and responding to ICMP traffic.

The core of the lab involved using the iptables firewall utility to manipulate network traffic. You constructed and applied a specific rule to the INPUT chain to DROP all incoming ICMP packets, effectively blocking tools like ping. To complete the process, you verified that the new rule was active by listing the current iptables ruleset and then tested the block by attempting to ping the machine again, confirming that the requests now timed out as expected.