iptables extensions turn a bare accept-or-drop rule into one that understands connection state, rate and intent. This builds a small, reviewable ruleset with them, using the installed iptables 1.8.10 command with its nf_tables backend, and checks what is actually active. Allow about 15 minutes on a test host, or longer over SSH where you need a console fallback.
You need the iptables package and a shell with sudo access. Rule changes affect the host immediately, so keep an existing SSH session open, have console access if possible, and substitute your real interface and service values before applying anything. Commands that just print help are ordinary; listing and changing the live ruleset normally need root.
This guide uses the extensions most often needed in a small host firewall:
conntrack. Matches connection state.limit. Controls the average match rate and burst.comment. Records why a rule exists.LOG. Records matching packets while rule traversal continues.REJECT. Ends traversal and sends an error response.Record the program version, then ask each extension for its own options: the module name follows -m, and a target name follows -j.
iptables --version
iptables -m conntrack --help
iptables -m limit --help
iptables -m comment --help
iptables -j LOG --help
iptables -j REJECT --help
On this installation the first command reports iptables v1.8.10 (nf_tables). The help output is the useful compatibility check: it shows, for example, --ctstate, --limit, --limit-burst and --comment. Extension help can vary with the package and kernel, so check it here rather than copying an option from a different host.
Save a readable view of the current filter table. This does not change any rules. The numeric form avoids DNS lookups and makes the output easier to compare later:
sudo iptables -L INPUT -n -v --line-numbers
sudo iptables -S INPUT
You should see the chain policy followed by numbered rules. Record the output somewhere safe before adding one. Do not assume an empty-looking custom chain means the host has no protection: the built-in chain policy and rules in other tables matter too.
A common first rule for a host firewall accepts packets belonging to connections already seen in both directions, plus related traffic such as an associated error or data connection:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
The state names come from the conntrack extension. NEW is for a connection starting now; INVALID means connection tracking cannot associate the packet with a known connection. Rule order matters: iptables evaluates matches in the order written, and a terminating target such as ACCEPT stops traversal there.
Check the rule is present before continuing:
sudo iptables -C INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -S INPUT
A successful -C check produces no output and exits with status zero. It is safe to repeat this check, but repeating -A would create a duplicate rule.
Replace the example port with a service you deliberately expose. This permits new TCP connections to HTTPS on every interface, then records the reason in the rule itself:
sudo iptables -A INPUT -p tcp --dport 443 \
-m conntrack --ctstate NEW \
-m comment --comment "allow public HTTPS" \
-j ACCEPT
The comment extension accepts a comment up to 256 characters according to the installed manpage. Keep it short enough to explain the owner or purpose, not a second policy document. Verify the exact rule:
sudo iptables -C INPUT -p tcp --dport 443 \
-m conntrack --ctstate NEW \
-m comment --comment "allow public HTTPS" \
-j ACCEPT
Logging every dropped packet can fill your logs and burn CPU. The limit match uses an average rate and a burst; on this installation the defaults shown by help are 3 per hour and a burst of 5, but specify values explicitly so the rule explains itself:
sudo iptables -A INPUT -m conntrack --ctstate INVALID \
-m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "iptables invalid: " --log-level 4
LOG is non-terminating, so a packet still continues to the following rules. The prefix helps you find these records in the system log. The numeric level is accepted by the target help; the precise destination depends on the host's logging configuration. Inspect counters first, then generate only controlled test traffic if you know how the host logs kernel messages:
sudo iptables -L INPUT -n -v --line-numbers
Do not put a broad logging rule ahead of an intended accept rule unless you want the accepted traffic logged too. If the log rate is still too high, tighten it or remove the rule with the exact delete command below.
DROP silently discards a packet. REJECT sends an error response and is valid in the built-in INPUT, FORWARD and OUTPUT chains, among other restrictions documented for the target. For a final default policy, a silent drop is often less revealing:
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
For a specific service or network where a quick refusal is preferable, use a narrow reject rule and choose its response type from iptables -j REJECT --help.
Warning: do not indiscriminately reject INVALID packets. The installed manpage warns that a delayed packet can be classified as invalid after a healthy retransmission has already moved the connection along, and an error response could damage that connection.
Before deleting anything, list line numbers and copy the exact rule. Matching deletion is less fragile than guessing a number, but it has to match the rule as installed:
sudo iptables -D INPUT -p tcp --dport 443 \
-m conntrack --ctstate NEW \
-m comment --comment "allow public HTTPS" \
-j ACCEPT
sudo iptables -D INPUT -m conntrack --ctstate INVALID \
-m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "iptables invalid: " --log-level 4
To remove the established-traffic rule, use the same specification with -D. If a change has locked you out, use the console or an existing privileged session to delete the new rule.
Destructive action: avoid iptables -F as a recovery shortcut. Flushing a chain removes all of its rules at once, and can expose services or remove access controls you did not put there yourself.
iptables --version and each required extension's help output were checked on this host.INVALID traffic is not broadly rejected.iptables -C or a numbered listing confirms the intended rules are in place.-D commands and a console path for recovery.