| |

LFCE 75 ๐Ÿง iptables โ€” Rules and Matching

โฑ๏ธ Estimated read: 12 min | |

A rule is a set of match criteria followed by a target. The match criteria determine which packets the rule applies to, and the target determines what happens to a matching packet. The previous chapter covered the tables and chains that organize the rules; this chapter covers the criteria and targets that make each rule specific. A firewall with only a default policy and no rules blocks everything. A firewall with rules that match too broadly or too narrowly does not do what the administrator intended, and the mismatch is often invisible until a service fails.

The match criteria are specified with options: -p for the protocol, -s and -d for the source and destination addresses, -i and -o for the input and output interfaces, and --dport and --sport for the ports. The -m flag loads a match module for more complex criteria, such as connection state, multiple ports, or packet rate. The target is specified with -j and is one of the built-in targetsโ€”ACCEPT, DROP, REJECT, LOGโ€”or a custom chain . The rule is added to a chain with -A or -I, and the chain determines when the rule is evaluated.

Key point: The match criteria are combined with a logical AND. A rule -p tcp --dport 22 -s 192.168.1.0/24 matches a packet only if it is TCP, destined for port 22, and sourced from the 192.168.1.0/24 network. The order of the options does not matter, but the order of the rules in the chain does: the first rule that matches determines the packet’s fate. A rule that is more specific must appear before a rule that is more general, or the general rule catches the packet first .


Why rules require careful matching

The implicit-AND problem.

The options in a rule are combined with AND, not OR. A rule -p tcp -p udp is not a rule that matches both protocols; it is a rule that matches neither, because a packet cannot be both TCP and UDP. To match multiple ports or multiple protocols, the -m multiport or -m multiport module is used, or multiple rules are added. The single-rule form with multiple -p options is a common mistake that produces a rule that never matches .

The interface-direction problem.

The -i option matches the incoming interface, and the -o option matches the outgoing interface. The -i option is valid in the INPUT, FORWARD, and PREROUTING chains. The -o option is valid in the OUTPUT, FORWARD, and POSTROUTING chains. Using -i in the OUTPUT chain or -o in the INPUT chain produces an error, because the interface information is not available at that point in the packet’s journey . The -i lo match in the INPUT chain is the standard way to allow loopback traffic.

The connection-state problem.

A stateless firewall that allows only the SYN packets of outgoing connections drops the replies, because the replies are not SYN packets and do not match the rule. The -m conntrack --ctstate match solves this by tracking the connection state. The ESTABLISHED state matches packets that belong to an existing connection, and the RELATED state matches packets that are related to an existing connection, such as FTP data transfers. The standard rule -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT allows the replies to outgoing connections without opening a new inbound port .


a. The protocol, address, and port matches

The -p option matches the protocol, and the --dport and --sport options match the destination and source ports. The ports are only valid with the tcp or udp protocols.

# Allow SSH from a specific network
sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

# Allow HTTP from anywhere
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Allow DNS queries from a specific server
sudo iptables -A INPUT -p udp --sport 53 -s 192.168.1.1 -j ACCEPT

The -p tcp matches TCP packets, and the --dport 22 matches packets destined for port 22. The -s 192.168.1.0/24 matches packets from the specified network. The --sport 53 matches packets whose source port is 53, which is the response from a DNS server . The order of the options does not affect the match, but the rule is more readable when the protocol comes first.

The -d option matches the destination address, and the -i and -o options match the interfaces.

# Allow traffic on the loopback interface
sudo iptables -A INPUT -i lo -j ACCEPT

# Allow forwarding from eth0 to eth1
sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT

The -i lo matches packets that arrive on the loopback interface. The -i eth0 -o eth1 matches packets that arrive on eth0 and leave on eth1, which is the standard forwarding rule for a router with two interfaces .


b. The connection-state match

The -m conntrack match loads the connection-tracking module, and the --ctstate option matches the connection state. The four common states are NEW, ESTABLISHED, RELATED, and INVALID.

# Allow established and related connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Drop invalid packets
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

The ESTABLISHED state matches packets that belong to an existing connection. The RELATED state matches packets that are related to an existing connection, such as the ICMP error that reports a failed connection. The INVALID state matches packets that do not belong to any known connection, which are often the result of a port scan or a malformed packet . The NEW state matches packets that initiate a new connection, and it is the state that the service-specific rules match.

The connection-state match is what makes a stateful firewall possible. Without it, the firewall would need a rule for every port in both directions, and the rules would not distinguish between an incoming connection and the reply to an outgoing connection.


c. The multiport, iprange, and rate-limit matches

The -m multiport match allows multiple ports in a single rule, and the -m iprange match allows a range of addresses. The -m limit match limits the rate of matching packets, which is useful for logging or for protecting against floods.

# Allow multiple ports in one rule
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT

# Match a range of addresses
sudo iptables -A INPUT -m iprange --src-range 192.168.1.10-192.168.1.20 -j ACCEPT

# Limit the rate of logged packets
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables: "

The -m multiport --dports 80,443,8080 matches any of the three ports in a single rule, which is more efficient than three separate rules. The --dports option accepts a comma-separated list, and the --sports option does the same for source ports . The -m iprange --src-range matches a range of source addresses, which is useful when the addresses are not a single CIDR block. The -m limit --limit 5/min matches at most five packets per minute, and the rest are not matched, which prevents a log flood from filling the disk .


Complete Example Session

# ============================================
# PART 1: FLUSH THE EXISTING RULES
# ============================================
sudo iptables -F

# ============================================
# PART 2: SET THE DEFAULT POLICIES
# ============================================
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# ============================================
# PART 3: ALLOW LOOPBACK
# ============================================
sudo iptables -A INPUT -i lo -j ACCEPT

# ============================================
# PART 4: ALLOW ESTABLISHED AND RELATED
# ============================================
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# ============================================
# PART 5: DROP INVALID PACKETS
# ============================================
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# ============================================
# PART 6: ALLOW SSH FROM THE LOCAL NETWORK
# ============================================
sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

# ============================================
# PART 7: ALLOW MULTIPLE WEB PORTS
# ============================================
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

# ============================================
# PART 8: LIMIT LOGGING
# ============================================
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-drop: "

# ============================================
# PART 9: VERIFY THE RULES
# ============================================
sudo iptables -L INPUT -n -v --line-numbers
# Output shows the rules in order with counters

# ============================================
# PART 10: TEST THE FIREWALL
# ============================================
curl -I http://localhost
# The local connection succeeds because of the loopback rule
# A remote SSH connection from the allowed network succeeds
# A connection from an unallowed network is dropped

The ten parts demonstrate the rule and matching configuration: flushing, setting the policies, allowing loopback, allowing established connections, dropping invalid packets, allowing SSH from the local network, allowing multiple web ports, limiting logging, verifying, and testing. The critical rules are Parts 4 and 5: the established-connection rule allows the replies, and the invalid-packet rule drops the malformed traffic.


Quick Reference

Match Options

OptionPurposeExample
-pProtocol-p tcp
-sSource address-s 192.168.1.0/24
-dDestination address-d 10.0.0.1
-iInput interface-i eth0
-oOutput interface-o eth1
--dportDestination port--dport 22
--sportSource port--sport 53

Match Modules

ModulePurposeExample
-m conntrackConnection state--ctstate ESTABLISHED,RELATED
-m multiportMultiple ports--dports 80,443
-m iprangeAddress range--src-range 192.168.1.10-20
-m limitRate limiting--limit 5/min

Connection States

StateMeaning
NEWInitiates a new connection
ESTABLISHEDBelongs to an existing connection
RELATEDRelated to an existing connection
INVALIDDoes not belong to any known connection

Targets

TargetAction
ACCEPTAllow the packet
DROPSilently discard
REJECTDiscard with an error response
LOGLog and continue
<custom-chain>Jump to a custom chain

Best Practices

โœ… Do This:

# Allow loopback
iptables -A INPUT -i lo -j ACCEPT                              # โœ…

# Allow established and related
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # โœ…

# Use multiport for multiple ports
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT # โœ…

# Limit logging
iptables -A INPUT -m limit --limit 5/min -j LOG                # โœ…

# Put specific rules before general rules
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -j DROP                                       # โœ…

โŒ Don’t Do This:

# Use multiple -p options in one rule
iptables -A INPUT -p tcp -p udp -j ACCEPT    # Matches neither   # โŒ

# Use -i in the OUTPUT chain
iptables -A OUTPUT -i eth0 -j ACCEPT    # Error                 # โŒ

# Forget the established-connection rule
iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # Replies dropped # โŒ

# Put the DROP rule before the specific allows
iptables -A INPUT -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT    # Never reached  # โŒ

# Log without a limit
iptables -A INPUT -j LOG    # Log flood                          # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Rule never matchesMultiple -p options combined with ANDUse -m multiport
Replies droppedNo ESTABLISHED,RELATED ruleAdd the conntrack rule
Interface error-i used in OUTPUT or -o in INPUTUse the correct chain
Rule unreachablePlaced after a general DROPPut specific rules first
Log floodNo -m limitAdd --limit
Multiport syntax errorUsed spaces instead of commas--dports 80,443

Real-World Examples

1. Allow SSH from a network

iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

2. Allow HTTP and HTTPS

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

3. Allow loopback

iptables -A INPUT -i lo -j ACCEPT

4. Allow established

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

5. Drop invalid

iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

6. Log with a limit

iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "drop: "

7. Source port match

iptables -A INPUT -p udp --sport 53 -j ACCEPT

8. Interface match

iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT

9. Address range

iptables -A INPUT -m iprange --src-range 192.168.1.10-192.168.1.20 -j ACCEPT

10. REJECT instead of DROP

iptables -A INPUT -p tcp --dport 23 -j REJECT --reject-with tcp-reset

Visual

The Implicit AND

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE OPTIONS IN A RULE ARE COMBINED WITH AND                 โ”‚
โ”‚                                                              โ”‚
โ”‚  -p tcp --dport 22 -s 192.168.1.0/24                         โ”‚
โ”‚       โ”‚         โ”‚           โ”‚                                โ”‚
โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                โ”‚
โ”‚       A packet matches only if it is:                        โ”‚
โ”‚       โœ“ TCP                                                  โ”‚
โ”‚       โœ“ destined for port 22                                 โ”‚
โ”‚       โœ“ sourced from 192.168.1.0/24                          โ”‚
โ”‚                                                              โ”‚
โ”‚  A packet that matches two of the three does not match.      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Connection State

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CONNECTION TRACKING MAKES A STATEFUL FIREWALL               โ”‚
โ”‚                                                              โ”‚
โ”‚  Outgoing connection:                                        โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ Client โ†’ Server: SYN          (state: NEW)            โ”‚  โ”‚
โ”‚  โ”‚ Server โ†’ Client: SYN-ACK      (state: ESTABLISHED)    โ”‚  โ”‚
โ”‚  โ”‚ Client โ†’ Server: ACK          (state: ESTABLISHED)    โ”‚  โ”‚
โ”‚  โ”‚ Client โ†’ Server: data         (state: ESTABLISHED)    โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  The INPUT chain's ESTABLISHED rule matches the replies,     โ”‚
โ”‚  even though there is no explicit rule for the reply port.   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Rule Order

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SPECIFIC RULES MUST COME BEFORE GENERAL RULES               โ”‚
โ”‚                                                              โ”‚
โ”‚  โœ… Correct:                                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ 1. -i lo -j ACCEPT                                     โ”‚  โ”‚
โ”‚  โ”‚ 2. -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTโ”‚  โ”‚
โ”‚  โ”‚ 3. -p tcp --dport 22 -j ACCEPT                         โ”‚  โ”‚
โ”‚  โ”‚ 4. -j DROP                                             โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  โŒ Incorrect:                                               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ 1. -j DROP                                             โ”‚  โ”‚
โ”‚  โ”‚ 2. -p tcp --dport 22 -j ACCEPT    โ† never reached      โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Protocol match-p tcp
Source match-s <address>
Destination match-d <address>
Input interface-i <interface>
Output interface-o <interface>
Destination port--dport <port>
Source port--sport <port>
Multiple ports-m multiport --dports 80,443
Connection state-m conntrack --ctstate
Rate limiting-m limit --limit 5/min
Accept-j ACCEPT
Drop-j DROP
Reject-j REJECT
Log-j LOG

Key takeaways:

  • The match options are combined with AND. A rule with multiple options matches only the packets that satisfy all of them. Multiple protocols or ports require the -m multiport module or multiple rules .
  • The interface matches are directional. The -i option matches the incoming interface and is valid in the INPUT, FORWARD, and PREROUTING chains. The -o option matches the outgoing interface and is valid in the OUTPUT, FORWARD, and POSTROUTING chains .
  • The connection-state match makes the firewall stateful. The ESTABLISHED,RELATED rule allows the replies to outgoing connections without opening a new inbound port. The INVALID state drops malformed packets .
  • The rule order matters. The first rule that matches determines the packet’s fate. Specific rules must appear before general rules, or the general rule catches the packet first.
  • The -m multiport module allows multiple ports in one rule. The --dports 80,443 option matches either port, which is more efficient than two separate rules .
  • The -m limit module prevents log floods. The --limit 5/min option matches at most five packets per minute, and the rest are not logged. Without the limit, a flood of dropped packets fills the disk.

Remember: A rule is a set of match criteria and a target. The criteria are combined with AND, and the first matching rule wins. The protocol, address, port, interface, and connection-state matches define which packets the rule applies to. The -m multiport, -m conntrack, and -m limit modules extend the criteria for complex cases. The ACCEPT, DROP, and REJECT targets determine what happens to a matching packet. The order of the rules determines which one is reached first. A firewall is only as good as its match criteria and its rule order; a rule that is too broad, too narrow, or in the wrong position does not do what the administrator intended.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!