# System Security, Firewalls, and iptables/nftables

> Chapter 12 of the Courseiva LPI-LPIC2 curriculum — https://courseiva.com/learn/lpi-lpic2/system-security-and-firewalls

**Official objective:** 202.4 — System Security

## Introduction

How do you stop unauthorised people and malicious software from breaking into your Linux server over the internet? This problem is what the LPIC-2 exam objective 202.4, System Security, addresses by teaching you how to configure a firewall, which acts as a gatekeeper between your server and the internet, using tools like `iptables` and its modern replacement `nftables`.

## The Concert Entry and Bouncer Analogy

Securing a server against unwanted network traffic first requires knowing who is trying to get in, and that leads to the need for a system that can make split-second decisions based on rules you set. Imagine your Linux server is a private concert venue you are hosting for a band and their fans. The venue has a single front door (the network interface). When someone arrives, they knock with a request, like "I am here to see the band" (a data packet arriving). You, as the organiser, have hired a bouncer (the firewall application, like `iptables` or `nftables`) to manage the door. You give the bouncer a strict list of rules printed on a clipboard (the firewall rule set). The first rule might say, "If anyone says they are selling something, do not let them in" (block advertising or malicious packets). Another rule might say, "If anyone claims to be a VIP member with a backstage pass, let them through to a specific area" (allow secure shell (SSH) connections from a specific IP address).

The bouncer does not think about the rules; he just checks each person against the list in order. If a person matches a rule that says "Let them in," they enter. If they match a rule that says "Turn them away," they are stopped. If no rule matches, the final rule on the clipboard says "Turn everyone else away" (the default deny policy). This process of checking data packets against a sequence of rules until a match is found is the core of how `iptables` and `nftables` work. The bouncer keeps a log of suspicious characters (system logs) so you can review who tried to cause trouble later.

## Core explanation

System security on a Linux server is a broad topic, but for the LPIC-2 exam, it focuses heavily on the firewall. A firewall is a piece of software or hardware that controls what network traffic is allowed to enter or leave a computer or network. You can think of it as a filter that examines every piece of data trying to cross a network boundary. The older tool for this job is `iptables`, while the newer, more efficient tool is `nftables`. The LPIC-2 exam covers both, but you need to understand that `nftables` is the successor designed to replace `iptables`.

When data travels across a network, it is broken into small chunks called packets. Each packet has a source IP address (where it came from), a destination IP address (where it is going), and a port number (which service it is trying to access, like port 80 for web traffic or port 22 for secure shell (SSH)). The firewall examines these packet headers and then decides what to do with the packet based on your rules. This decision is called a target. The most common targets are ACCEPT (let the packet through), DROP (ignore the packet as if it never arrived), and REJECT (send a message back saying the connection was refused). The difference between DROP and REJECT is important for security: DROP makes it look like your server does not even exist, while REJECT tells the sender there is a server there, which can be useful but gives away information.

Now, let us look at how `iptables` organises its rules. It uses a system of tables and chains. A table is a collection of related rules. The main tables are the filter table (for basic firewalling, deciding which packets to allow or block), the nat table (for Network Address Translation, which changes IP addresses of packets, often used for routing traffic), and the mangle table (for special modifications to packet headers). Inside each table, there are chains. A chain is a sequence of rules that are checked in order. The default chains in the filter table are INPUT (for packets destined for the server itself), OUTPUT (for packets leaving the server), and FORWARD (for packets passing through the server to another network, like a router). For LPIC-2, you must understand the basic anatomy of an `iptables` command: `iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT`. This command appends (-A) a rule to the INPUT chain that says: if the protocol (-p) is TCP, the destination port (--dport) is 22 (SSH), and the source IP address (-s) is from the network 192.168.1.0/24 (a range of addresses), then jump (-j) to the target ACCEPT.

The newer tool `nftables` simplifies this. Instead of having separate tools for tables and chains, `nftables` uses a single framework. You still have tables and chains, but the command structure is different and more consistent. For example, a simple rule in `nftables` might look like this: `nft add rule inet filter input tcp dport 22 accept`. Here, `inet` is the address family (IPv4 and IPv6 combined), `filter` is the table name, `input` is the chain name, and `tcp dport 22 accept` is the rule. `nftables` also uses a single tool (`nft`) instead of the multiple tools `iptables`, `ip6tables`, `arptables`, and `ebtables` that `iptables` required. This makes `nftables` easier to script and manage. A key difference for the exam is that `nftables` rules are transactional: you can define a whole set of rules and apply them atomically (all at once or not at all), whereas `iptables` applies each rule one by one, which can leave your firewall in an inconsistent state if a rule fails.

Finally, both tools rely on rules being checked in order. This is called a chain. When a packet arrives, the firewall checks it against the first rule in the chain. If the rule matches criteria (like the port and source), the firewall executes the target (like ACCEPT or DROP) and stops checking subsequent rules. If the rule does not match, the firewall moves to the next rule. This process continues until either a rule matches, or the firewall reaches the end of the chain. If no rule matches, the default policy for that chain is applied. Typically, the default policy is set to DROP, meaning anything not explicitly allowed is blocked. This is the most secure setup, known as a whitelist approach. For LPIC-2, you need to know how to add, delete, insert, and list rules in both `iptables` and `nftables`, and how to make these rules persistent (save them so they survive a reboot).

## Real-world context

Consider a small business with a single Linux web server hosting an e-commerce site. The server is connected to the internet and must be accessible to customers. The IT professional managing this server is responsible for ensuring that only legitimate web traffic (port 80 for HTTP and port 443 for HTTPS) can reach the web server, and that no unauthorised access is possible.

The first step the IT professional takes is to check the current firewall rules. On an older system, this might be done with `iptables -L -n -v` (list rules with numeric addresses and packet counts). On a newer system, the command might be `nft list ruleset`. The professional sees that the default policy on the INPUT chain is ACCEPT, meaning all traffic is allowed by default. This is a massive security risk. They immediately change the default policy to DROP using `iptables -P INPUT DROP` or the equivalent in `nftables`.

Next, they need to allow specific traffic. They know they need to let in HTTP (port 80) and HTTPS (port 443) traffic from anywhere. They add rules like: `iptables -A INPUT -p tcp --dport 80 -j ACCEPT` and `iptables -A INPUT -p tcp --dport 443 -j ACCEPT`. They also remember that they need to allow traffic from the server itself (loopback traffic, which is critical for local processes to communicate) and established connections (so that when a customer visits the site, the server can send data back to them; otherwise, the server would block its own outgoing responses). For established connections, they add a state rule: `iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT`.

The IT professional also needs to provide SSH access (port 22) for remote management, but they do not want to leave it open to the whole internet. They decide to only allow SSH from the company's office IP address. They add a rule: `iptables -A INPUT -p tcp --dport 22 -s 203.0.113.0/24 -j ACCEPT`, where `203.0.113.0/24` is the office network range.

To ensure these rules persist after a reboot, they save the rules using `iptables-save > /etc/iptables/rules.v4` (on a Debian-based system) or by installing the `iptables-persistent` package. For `nftables`, they save with `nft list ruleset > /etc/nftables.conf` and enable the `nftables` service.

Finally, they test the firewall. They try to SSH into the server from a different IP address than the office and confirm they get a timeout (meaning the packet was dropped). They visit the website from a browser and confirm it loads correctly. They check the log files (`/var/log/kern.log` or `/var/log/messages`) to see if any drops are logged, which helps them detect potential attacks. This whole process of planning, testing, and persisting firewall rules is what a Linux system administrator does daily to maintain system security.

## Exam focus

The LPIC-2 exam 202.4 requires you to demonstrate hands-on knowledge of configuring `iptables` and `nftables` firewalls. You will not be asked to write a 50-rule script from scratch, but you must know the syntax and structure of common commands. The exam is heavily focused on practical application, not just theory.

The exam loves to test your understanding of the basic building blocks: tables, chains, rules, and targets. For `iptables`, they expect you to know the three main tables (filter, nat, mangle) and their primary chains (INPUT, OUTPUT, FORWARD for filter; PREROUTING, POSTROUTING, OUTPUT for nat). Be prepared for questions that mix up these concepts. For example, a trap question might ask, "Which chain would you use to filter incoming packets destined for the local system?" The correct answer is the INPUT chain in the filter table. A common trap is offering the PREROUTING chain (which is for NAT, not filtering) as a distractor.

Another key area is the difference between `iptables` and `nftables`. The exam reflects that `nftables` is the modern replacement, but `iptables` is still widely used. You need to know at least how to list rules (`nft list ruleset`) and add a simple rule (`nft add rule inet filter input tcp dport 22 accept`) in `nftables`. They will test the concept of atomic rule updates in `nftables` versus iterative updates in `iptables`.

State tracking is another favourite. You must understand the meaning of the states: NEW (a new connection), ESTABLISHED (packets belonging to an existing connection), RELATED (packets related to an existing connection, like an FTP data connection), and INVALID (packets that are malformed or cannot be identified). The exam often asks how to allow only established connection replies, which requires the `-m state --state ESTABLISHED,RELATED` match.

Traps are set around the default policy. A question might describe a server with a default policy of ACCEPT and ask what the risk is. The answer is that it allows all traffic by default, which is insecure. They may also ask what happens when a packet does not match any rule in a chain whose default policy is DROP — the answer is the packet is dropped.

You must also know how to make rules persistent. The exam will ask about the correct way to save `iptables` rules for different distributions. For Debian/Ubuntu, the file is often `/etc/iptables/rules.v4`, and the command is `iptables-save`. For Red Hat/CentOS, the command is also `iptables-save`, but the file might be `/etc/sysconfig/iptables`. For `nftables`, the ruleset is saved with `nft list ruleset > /etc/nftables.conf` and loaded with `nft -f /etc/nftables.conf`.

Finally, the exam expects you to know how to insert a rule at a specific position (using `-I` with a number, like `iptables -I INPUT 3 ...`) and delete a rule by specification (`-D`) or by number (`iptables -D INPUT 3`). Understanding the order of rules is critical, as an incorrectly placed rule can accidentally block the administrator's own access.

## Step by step

1. **Assess the Current Firewall State** — Before making any changes, you must understand what rules are already active. On a system using `iptables`, you would run `sudo iptables -L -n -v` to list the rules in the filter table. On a system using `nftables`, you would run `sudo nft list ruleset`. This step identifies the default policy on each chain and any existing rules. It prevents you from accidentally duplicating or conflicting with existing configurations.
2. **Set a Secure Default Policy** — You set a secure default policy on the INPUT chain to DROP. This means any packet that does not match an explicit rule will be discarded. The command for `iptables` is `sudo iptables -P INPUT DROP`. For `nftables`, you would define the policy within the chain definition, for example, when creating the chain: `nft add chain inet filter input { type filter hook input priority 0; policy drop; }`. This step is fundamental to the principle of least privilege.
3. **Allow Essential Loopback and State Traffic** — You must allow traffic from your own machine (loopback interface, `lo`) because many internal services (like a database communicating with a web server) use it. You also need to allow established connection packets so that replies to outgoing requests (like a server fetching updates) are accepted. In `iptables`, you add rules: `sudo iptables -A INPUT -i lo -j ACCEPT` and `sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT`. These are safety nets that prevent you from breaking your own system.
4. **Add Application-Specific Allow Rules** — Now, you add rules for the specific services you intend to run. For a web server, you allow TCP traffic on ports 80 (HTTP) and 443 (HTTPS). For example: `sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT` and `sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT`. If you need SSH access from a specific location, you add a more restrictive rule, like `sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT`. Each rule should be as specific as possible to minimise the attack surface.
5. **Persist and Test the Rules** — Once the rules are applied, you must save them so they load again after a reboot. For `iptables` on a Debian system, you run `sudo iptables-save > /etc/iptables/rules.v4`. For `nftables`, you run `sudo nft list ruleset > /etc/nftables.conf`. Then, test the configuration by attempting to connect to the allowed services from an authorised and an unauthorised location. Also, test that essential local services still work. This ensures the firewall is both secure and functional.

## Comparisons

### iptables vs nftables

**iptables:**
- Uses multiple commands: iptables, ip6tables, arptables, ebtables
- Applies rules one-by-one, not atomically (risk of inconsistent state)
- Syntax is more complex and differs for each table (filter, nat, mangle)

**nftables:**
- Uses a single command: nft
- Supports atomic rule updates (all or nothing) for consistency
- Has a unified, consistent syntax across all tables and address families

### DROP target vs REJECT target

**DROP target:**
- Silently discards the packet without any response
- Hides the existence of the server from the sender
- More secure for preventing reconnaissance

**REJECT target:**
- Sends an error packet back to the sender (e.g., 'connection refused')
- Informs the sender that a host is reachable but the port is blocked
- Can be useful for debugging but reveals information

### Default policy ACCEPT vs Default policy DROP

**Default policy ACCEPT:**
- Allows all traffic that does not match a specific rule
- You must manually block malicious traffic, increasing the chance of missing something
- Highly insecure; any overlooked port is automatically accessible

**Default policy DROP:**
- Blocks all traffic that does not match a specific allow rule
- You must manually allow only necessary traffic (least privilege)
- Highly secure; unknown traffic is automatically denied

### INPUT chain vs FORWARD chain

**INPUT chain:**
- Filters packets destined for the local server itself
- Used to protect the host machine from incoming attacks
- The most commonly secured chain for a standalone server

**FORWARD chain:**
- Filters packets passing through the server destined for another network (router scenario)
- Used to protect other machines behind the firewall
- Critical when the server acts as a router or gateway

### State NEW vs State ESTABLISHED

**State NEW:**
- Matches the very first packet of a new connection
- Used in allow rules to permit new inbound requests (like a web visitor)
- Often restricted by source IP to limit who can initiate a connection

**State ESTABLISHED:**
- Matches packets belonging to an already established connection
- Used to allow return traffic from the server to the client
- Essential for most network services to function correctly

## Diagram

_Flowchart showing how a firewall packet traverses a chain of rules until a match is found or the default policy is applied._

```mermaid
flowchart TD
    A[Packet arrives from internet] --> B{Firewall checks INPUT chain}
    B --> C{Rule 1: match?}
    C -- Yes --> D[Execute target: ACCEPT or DROP]
    C -- No --> E{Rule 2: match?}
    E -- Yes --> D
    E -- No --> F[... Continue checking rules]
    F --> G{End of chain?}
    G -- Yes --> H[Apply default policy: DROP or ACCEPT]
    G -- No --> F
    D --> I[Packet processed / logged]
    H --> I
```

## Common misconceptions

- **Misconception:** Setting the default policy to ACCEPT and then adding rules to block specific things is more secure. **Reality:** The default policy should be DROP (deny all), and you only add rules to allow specific, necessary traffic. This is the principle of least privilege. (It feels safer to block bad things explicitly, but you cannot think of everything a bad actor might try. With a default-allow, if you forget a block rule, you are open. With a default-deny, if you forget an allow rule, you just temporarily block a service.)
- **Misconception:** The `REJECT` target is more secure than `DROP` because it tells the sender to go away. **Reality:** `DROP` is generally more secure because it does not inform the sender that a server exists at that address, making reconnaissance harder. (People intuitively think responding politely is better. But in security, you want to minimise the information you leak. A dropped packet times out; a rejected packet immediately tells the attacker your firewall is active.)
- **Misconception:** Once you write a firewall rule with `iptables`, it stays there forever. **Reality:** Rules are stored in memory and are lost after a reboot unless you explicitly save them to a configuration file using `iptables-save` or a similar tool. (Beginners often forget the persistence step because the `iptables` command runs silently and the rule works immediately. They assume it is written to disk, but it is only living in the kernel's memory.)
- **Misconception:** `nftables` and `iptables` are two completely separate firewall systems that cannot coexist. **Reality:** They can coexist on the same system, but it is discouraged because it can cause confusion and double processing of packets. On many modern distributions, installing `nftables` replaces the `iptables` command with a wrapper that uses the `nftables` kernel API. (The tools look different and have different commands, so it is easy to assume they conflict. In reality, they both manipulate the same Netfilter framework in the Linux kernel, but `nftables` is the newer interface.)
- **Misconception:** I only need to secure the INPUT chain because that is where incoming threats come from. **Reality:** The OUTPUT chain is also important. It controls traffic leaving the server, which can prevent malware from phoning home or limit data exfiltration. (Security is often seen as protecting against outsiders. But an infected server can be used to attack other systems, so restricting outbound traffic is a critical part of a defence-in-depth strategy.)
- **Misconception:** The order of rules in a firewall chain does not matter because the firewall checks all rules before making a decision. **Reality:** Order is critical. The firewall stops processing rules as soon as the first match is found. If a broad 'ACCEPT all' rule is placed at the top, subsequent 'DROP' rules will never be checked. (This is a classic programming logic error. Beginners often add a blanket allow rule first, thinking they can then refine it with other rules, but the blanket rule matches everything and ends the check.)

## Key takeaways

- A firewall's primary function is to control incoming and outgoing network packets based on a defined set of rules.
- The `iptables` command uses tables (filter, nat, mangle) and chains (INPUT, OUTPUT, FORWARD) to organise rules.
- The `nftables` command is the modern replacement for `iptables`, offering a simpler, unified syntax and atomic rule updates.
- The default policy on a firewall chain should almost always be DROP to block all traffic not explicitly allowed.
- Rules are processed in order until a match is found; placing a broad allow rule before a specific block rule will bypass the block.
- Firewall rules are volatile and must be saved to a file (e.g., using `iptables-save` or `nft list ruleset > file`) to persist across reboots.
- State tracking allows the firewall to recognise packets belonging to an existing connection using states like NEW, ESTABLISHED, and RELATED.
- The `REJECT` target sends an error packet back to the sender, while `DROP` silently discards the packet, making `DROP` more secure for concealing your server.
- Always test firewall rules from a separate session or terminal to avoid accidentally locking yourself out of the server.

## FAQ

**What is the difference between `iptables` and `nftables`?**

`nftables` is the modern replacement for `iptables`. It uses a single command-line tool (`nft`) instead of multiple tools (`iptables`, `ip6tables`, etc.), has a more consistent syntax, and supports atomic rule updates (applying all changes at once) to avoid leaving the firewall in an inconsistent state.

**How do I permanently save my `iptables` rules so they survive a reboot?**

You save `iptables` rules by running `sudo iptables-save > /path/to/file`. The exact path varies by distribution (Debian often uses `/etc/iptables/rules.v4`, Red Hat uses `/etc/sysconfig/iptables`). You then need to install a package (like `iptables-persistent` on Debian) or enable a service to load the file on boot.

**Why can I not connect to my server after I set up a firewall?**

You likely have no rule allowing SSH (port 22) from your IP address, or your default policy on the INPUT chain is set to DROP and you forgot to add a rule to allow SSH. Always test from a separate terminal or session so you do not get locked out permanently.

**What does the `-m state --state ESTABLISHED,RELATED` rule do?**

This rule allows packets that are part of an already established connection (like the server's reply to a web request) or are related to an existing connection (like an FTP data channel). Without this rule, your server would block its own outgoing responses, breaking most network services.

**What is the difference between `DROP` and `REJECT` in a firewall rule?**

`DROP` silently discards the packet, giving no indication to the sender that a server exists. `REJECT` sends an error packet (like 'connection refused') back to the sender. `DROP` is generally more secure because it does not leak information about your system's existence.

**How do I check the current rules on a system that uses `nftables`?**

You run the command `sudo nft list ruleset`. This displays all tables, chains, and rules currently loaded in the `nftables` framework. If the system uses `iptables` under the hood, `sudo iptables -L` is the equivalent command.

**What does it mean when people say `nftables` has 'atomic' rule updates?**

It means you can define a complete set of `nftables` rules in a file and apply them all at once with `nft -f file`. If any single rule has an error, the entire set is rejected, and the firewall remains in its previous state. In contrast, `iptables` applies rules one by one, so a failed rule in the middle can leave the firewall partially updated.

## Check your understanding

1. **What is the default policy that should be set on the INPUT chain for a secure server, and why?**

   Answer: The default policy should be DROP. This ensures that any packet that does not match an explicit allow rule is silently discarded, following the principle of least privilege and minimising the attack surface.

2. **In `iptables`, which table is primarily used for basic packet filtering (allowing or blocking traffic)?**

   Answer: The filter table is the default table for packet filtering. When you do not specify a table with `-t`, `iptables` assumes you mean the filter table.

3. **What is the command to list all current rules in `nftables`?**

   Answer: The command is `nft list ruleset`. This displays all tables, chains, and rules configured in the `nftables` framework.

4. **You just ran `iptables -A INPUT -j DROP` on a server with a default policy of ACCEPT. What effect does this rule have on incoming SSH traffic?**

   Answer: It blocks all incoming traffic, including SSH, because the `-j DROP` rule is at the end of the chain and matches any packet that has not matched an earlier rule. The administrator would likely be locked out.

5. **What is the difference between how `iptables` and `nftables` handle the application of multiple rules?**

   Answer: `iptables` applies rules one at a time, so a failed rule mid-apply can leave the firewall in an inconsistent state. `nftables` supports atomic updates, meaning all rules defined in a transaction are applied together or not at all.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/lpi-lpic2/system-security-and-firewalls
