ICMP Filter
ICMP๐
The filter allows (allow), blocks (block), or rate-limits (ratelimit) ICMPv4 (ip4)
and ICMPv6 (ip6) packets based on the ICMP type and L3 protocol.
The filter does not validate the ICMP type field in received packets; therefore,
it is recommended to use a whitelist policy and drop all ICMP packets with unspecified types.
If a rule applies a rate limit, the specified maximum number of packets and bytes per second is permitted.
Default policy: ICMP packets whose types are not matched by any explicit rule are processed according to the default action defined in the defaults section for the corresponding L3 protocol:
allowin black list modeblockin white list mode
If no action is specified in the defaults section, allow is used as the default action.
The default action may also be a named rate limit.
Note that allow rules have no effect when the default action is allow, and
block rules have no effect when the default action is block.
Refer to the IANA registries for valid ICMP type values:
Configuration format:
icmp <l3-protocol> : <action> {<list of types>}
An example for the filter rules configuration:
ratelimit=my_ratelimit bps=40000 pps=2000;
...
icmp ip6 : allow {10, 12}
icmp ip4 : ratelimit=my_ratelimit {10}
Use the defaults section to apply an action to all ICMP traffic for a specific L3 protocol:
defaults {
...
icmp ip6: block;
...
}
For each L3 protocol (ip4 or ip6), only one explicit ICMP rule can be defined in addition to the default rule.
Each ICMP type specified in a ratelimit rule has its own rate-limit bucket.
In contrast, all ICMP types in the defaults section share a single rate-limit bucket.
ICMPv4๐
ICMPv4 (Internet Control Message Protocol for IPv4) is a protocol that helps devices communicate important information about the network.
It is mainly used for:
- Checking if a host is reachable (Ping)
- Reporting errors when a packet cannot be delivered
- Informing when the packet lifetime (TTL) expires
- Diagnosing network problems
Even though ICMPv4 is very useful for troubleshooting, it can also be misused for attacks. Because of this, it is often a good idea to limit or even completely disable unnecessary ICMP traffic:
# Rate limit for ICMP
ratelimit=icmp_rl pps=10 bps=1000;
# Allow only these types
icmp ip4 : ratelimit=icmp_rl { 0, 3, 8, 11, 12 };
| Type | Description |
|---|---|
| 0 | Echo Reply |
| 3 | Destination Unreachable |
| 8 | Echo Request (ping request) |
| 11 | Time Exceeded (packet lifetime expired) |
| 12 | Parameter Problem (problem with IP header) |
ICMPv6๐
ICMPv6 is the IPv6 version of ICMP. It is more important than ICMPv4 because it replaces several old IPv4 protocols (like ARP) and performs many critical functions.
Without allowing the necessary ICMPv6 packet types, your IPv6 network will not work properly โ devices will not be able to find each other, configure addresses, or exchange data.
It is recommended to allow only the most essential types and apply a rate limit to protect against attacks:
# Rate limit for ICMPv6
ratelimit=icmp_rl pps=10 bps=1000;
# Allow only necessary types for IPv6
icmp ip6 : ratelimit=icmp_rl { 1, 2, 3, 4, 128, 129, 133, 134, 135, 136, 137, 143 };
| Type | Description |
|---|---|
| 1 | Destination Unreachable |
| 2 | Packet Too Big |
| 3 | Time Exceeded |
| 4 | Parameter Problem |
| 128 | Echo Request (ping) |
| 129 | Echo Reply (ping response) |
| 133 | Router Solicitation |
| 134 | Router Advertisement |
| 135 | Neighbor Solicitation (replaces ARP) |
| 136 | Neighbor Advertisement |
| 137 | Redirect |
| 143 | Multicast Listener Discovery |
ICMP + SRC Filter๐
The combination of SRC IPv6 filter and ICMP can behave in a non-obvious way. If you enable the src filter for IPv6, it will also block ICMPv6 packets. This happens because ICMPv6 is tightly integrated into the IPv6 stack. In contrast, IPv4 uses the ARP protocol for some technical operations. ARP is always allowed by XDP because it is a completely separate protocol and there are practically no ARP-based DDoS attacks in practice.
xfw {
defaults { icmp ip6: block; }
icmp ip6: allow { 0, 1, 2, 3, 4, 128, 129, 133, 134, 135, 136, 137, 143 }
ratelimit=test pps=0 bps=0;
src ip6.tcp: ratelimit=test {
[fd00:20::1]
}
}
At first glance, the rule above may look like it allows ICMPv6 traffic while blocking the specific SRC IPv6 address [fd00:20::1]. However, because ICMPv6 is an integral part of the IPv6 stack, the SRC filter applies to it as well. As a result, ICMPv6 packets are blocked first โ even if you explicitly allowed them in the ICMPv6 rule.
This often leads to broken IPv6 connectivity. For example, Neighbor Discovery (which replaces ARP in IPv6) stops working, so TCP traffic cannot pass properly.
Example: if you send 10 TCP packets over IPv6, you might see that 3 packets were blocked โ and none of them are actually TCP packets. All blocked packets are ICMPv6 (usually Neighbor Discovery packets).