How to block ping with iptables

Blocking ping with iptables stops remote hosts from receiving ICMP echo replies while normal TCP and UDP services keep following the existing firewall policy. Keep the rule narrow so it matches ICMP echo requests instead of blocking every ICMP message or changing the whole INPUT policy.

The default filter table sends packets addressed to the local host through the INPUT chain. A rule that matches icmp traffic with --icmp-type echo-request and jumps to DROP makes IPv4 ping probes time out, and its packet counter increases when clients send echo requests.

Runtime iptables changes disappear unless the host has a persistence loader, and current Ubuntu systems commonly expose iptables syntax through the nf_tables backend. Use a controlled client for testing, keep a delete command ready for rollback, and add a separate ip6tables rule when the host also answers IPv6 ping.

Steps to block ping with iptables:

  1. Print the active iptables backend before changing rules.
    $ iptables --version
    iptables v1.8.11 (nf_tables)

    (nf_tables) means the command uses the nftables compatibility backend. (legacy) means it uses the older xtables backend.

  2. List the INPUT chain with line numbers and counters.
    $ sudo iptables --list INPUT --line-numbers --numeric --verbose
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination

    INPUT is the right chain for ping packets addressed to the local host. Use FORWARD only when the system is routing packets for another host.

  3. Confirm ping currently reaches the host from a controlled client.
    $ ping -c 2 server.example.com
    PING server.example.com (192.0.2.20) 56(84) bytes of data.
    64 bytes from server.example.com (192.0.2.20): icmp_seq=1 ttl=64 time=0.416 ms
    64 bytes from server.example.com (192.0.2.20): icmp_seq=2 ttl=64 time=0.056 ms
    
    --- server.example.com ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1003ms
    rtt min/avg/max/mdev = 0.056/0.236/0.416/0.180 ms

    Use a client outside the host, VM, or container being protected. A local loopback ping does not prove that inbound network traffic is affected.

  4. Confirm an unrelated service still answers before the firewall change.
    $ curl -sS http://server.example.com:8080/
    icmp block test ok

    Use an existing service that should remain reachable, such as SSH, HTTPS, or a temporary test listener.

  5. Insert the IPv4 ping block rule before broader allow rules.
    $ sudo iptables -I INPUT 1 -p icmp --icmp-type echo-request -j DROP

    Blocking ping can break uptime checks, monitoring probes, and troubleshooting habits that depend on ICMP echo replies. Confirm the monitoring path before saving the rule permanently.

    DROP makes ping time out. Use REJECT only when clients should receive an immediate error response instead of waiting for a timeout.

  6. Check that the exact rule exists.
    $ sudo iptables -C INPUT -p icmp --icmp-type echo-request -j DROP

    No output means the exact rule is present. A nonzero exit means the rule specification did not match the current INPUT chain.

  7. Confirm the rule order and initial counter values.
    $ sudo iptables --list INPUT --line-numbers --numeric --verbose
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination
    1        0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8

    The rule must appear before any earlier rule that accepts the same ICMP echo-request packets.

  8. Test ping from the controlled client again.
    $ ping -c 3 -W 1 server.example.com
    PING server.example.com (192.0.2.20) 56(84) bytes of data.
    
    --- server.example.com ping statistics ---
    3 packets transmitted, 0 received, 100% packet loss, time 2043ms

    A timeout is expected with DROP. If ping still receives replies, check rule order, chain selection, the target address, and whether the client is using IPv6.

  9. Confirm the unrelated service still answers.
    $ curl -sS http://server.example.com:8080/
    icmp block test ok

    If the unrelated service also fails, remove the rule and review the chain for broader drops, interface matches, default policies, or upstream firewall changes.

  10. List the INPUT chain again and confirm the ICMP rule counter increased.
    $ sudo iptables --list INPUT --line-numbers --numeric --verbose
    Chain INPUT (policy ACCEPT 7 packets, 447 bytes)
    num   pkts bytes target     prot opt in     out     source               destination
    1        3   252 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8

    The pkts and bytes counters increase only when packets match this rule. Use ip6tables for a separate IPv6 ping block and counter check.

  11. Add a separate IPv6 ping block when the host answers IPv6 echo requests.
    $ sudo ip6tables -I INPUT 1 -p ipv6-icmp --icmpv6-type echo-request -j DROP

    Test with ping -6 from a controlled IPv6 client. IPv4 iptables output does not prove the IPv6 firewall state.

  12. Keep the rollback commands ready until monitoring and client tests are complete.
    $ sudo iptables -D INPUT -p icmp --icmp-type echo-request -j DROP
    $ sudo ip6tables -D INPUT -p ipv6-icmp --icmpv6-type echo-request -j DROP

    Delete by exact match while the rule shape is known. Deleting by line number is riskier after other rules have been inserted or removed.

  13. Save the tested runtime rules through the host firewall persistence method when the block should survive reboot.
    $ sudo netfilter-persistent save
    run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
    run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save

    Debian and Ubuntu use netfilter-persistent when iptables-persistent is installed. Other firewall managers may replace direct runtime rules during reload, so save or hand off the rule through the manager that owns the host policy.