Why iptables -p all Doesn’t Support –dport: Protocol-Specific Port Requirements Explained


2 views

When working with iptables, you might encounter unexpected behavior when trying to combine -p all with port-based rules. The error message clearly indicates that the --dport option isn't recognized when using the all protocol specification:

iptables -A INPUT -p all --dport www -j ACCEPT
iptables v1.4.4: unknown option --dport'
Try iptables -h' or 'iptables --help' for more information.

The fundamental reason this fails lies in how iptables processes rules at the protocol level. Port numbers are protocol-specific concepts that only make sense for certain transport layer protocols (primarily TCP and UDP). The all protocol specifier matches all IP protocols, including those that don't have port numbers (like ICMP, GRE, or OSPF).

When iptables encounters -p all, it doesn't know which protocol's port numbering scheme to use, hence the rejection of --dport.

For services that operate on both TCP and UDP (like DNS), you'll need separate rules:

# For TCP traffic
iptables -A INPUT -p tcp --dport 53 -j ACCEPT

# For UDP traffic  
iptables -A INPUT -p udp --dport 53 -j ACCEPT

If you're dealing with multiple ports, consider using multiport:

iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p udp -m multiport --dports 53,123 -j ACCEPT

For truly protocol-agnostic filtering, you might consider these alternatives:

# Match by IP address only
iptables -A INPUT -s 192.168.1.100 -j ACCEPT

# Match by network interface
iptables -A INPUT -i eth0 -j ACCEPT

Remember that protocol-specific rules are generally more precise and secure when they can be used.

This behavior has been consistent across iptables versions, from the early 1.2.x releases through modern implementations. The design reflects the fundamental networking principle that ports are transport-layer constructs, not IP-layer features.


When working with iptables, it's crucial to understand that destination port specifications (--dport) are protocol-specific. The -p all parameter refers to all possible protocols (TCP, UDP, ICMP, etc.), but port numbers only make sense for connection-oriented protocols like TCP and UDP.

# This fails because ICMP (ping) has no port concept
iptables -A INPUT -p all --dport 22 -j ACCEPT

The iptables implementation specifically checks protocol type before processing port-related matches. When examining the kernel source (particularly in xt_tcpudp.c), you'll find explicit protocol validation:

if (proto != IPPROTO_TCP && proto != IPPROTO_UDP && proto != IPPROTO_UDPLITE)
    return -EINVAL;

For comprehensive port-based filtering, you need separate rules for each transport protocol:

# Correct approach for port 80 (HTTP)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p udp --dport 80 -j ACCEPT

If you genuinely need to match "all protocols" while still filtering ports where applicable:

# Using multiport with protocol specifications
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p udp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT  # Handle non-port protocols separately

While this behavior exists in all iptables versions, newer releases (1.6.0+) provide clearer error messages. The fundamental limitation remains due to network protocol semantics, not iptables implementation.