> For the complete documentation index, see [llms.txt](https://docs.glesys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.glesys.com/products/compute/guides-for-server-management/logging-with-iptables-and-nftables.md).

# Logging with iptables and nftables

***

Sometimes it’s helpful to log all inbound and outbound connections on a server—for example, when you need evidence to create firewall rules or to troubleshoot a misconfigured firewall.

The default firewall tool in Debian 9 and previous versions is `iptables`. This tool has been replaced by `nftables` since Debian 10.

{% tabs %}
{% tab title="iptables (Debian 9 and older)" %}
If you run the following commands (as root), all firewall rules will be cleared, and all connections will be logged to `/var/log/messages`:

{% code title="Multiple commands" %}

```
iptables -F
iptables -I INPUT -m state --state NEW -j LOG --log-level 4 --log-prefix "INCOMING: "
iptables -I OUTPUT -m state --state NEW -j LOG --log-level 4 --log-prefix "OUTGOING: "
```

{% endcode %}

Because each connection is logged on a separate line, this quickly becomes hard to read. On a server with heavy traffic, the log file can grow to contain a very large number of lines.

This short and simple one‑liner below summarizes all connections recorded in `/var/log/messages`. Each host/port combination appears on its own line, and the number of connections is counted. Keep in mind that `/var/log/messages` may be rotated.

{% code title="Command" %}

```
cat /var/log/messages | grep "IN=" | awk -F'[= ]+' '{for (i=1;i < NF;i++) { if ($i=="DST") dst=$(i+1);if ($i=="SRC") src=$(i+1); if ($i=="PROTO") proto=$(i+1); if ($i=="DPT") dpt=$(i+1); if($i=="INCOMING:"||$i=="OUTGOING:") dir=$i} printf "%s %-20s %-20s %-15s %s \n",dir," DST:"dst," SRC:"src," PROTO:"proto," DPT:"dpt}' |sort | uniq -c
```

{% endcode %}

The same method can be used to log all blocked connections, which can be very useful for troubleshooting. Below is a complete example of a firewall script that **only allows incoming SSH connections from `10.10.10.10` and blocks and logs all other connections**:

{% code title="firewall-script.sh" %}

```bash
#!/bin/bash
I=/sbin/iptables
$I -F
$I -A OUTPUT -s 0/0 -m state --state RELATED,ESTABLISHED -j ACCEPT

#SSH in
$I -A INPUT -p TCP --dport 22 -s 10.10.10.10 -j ACCEPT

$I -A INPUT -m state --state NEW -j LOG --log-level 4 --log-prefix "INCOMING: "
$I -A OUTPUT -m state --state NEW -j LOG --log-level 4 --log-prefix "OUTGOING: "
$I -A INPUT -j DROP
$I -A OUTPUT -j DROP

exit 0
```

{% endcode %}
{% endtab %}

{% tab title="nftables (Debian 10 and newer)" %}
Create a file named `log-everything.conf` in your home directory, and give it the following content:

{% code title="log-everything.conf" %}

```
#!/usr/sbin/nft -f

flush ruleset

table ip filter {
    chain INPUT {
        type filter hook input priority 0; policy accept;
        ct state new log prefix "INCOMING: " level info
    }

    chain OUTPUT {
        type filter hook output priority 0; policy accept;
        ct state new log prefix "OUTGOING: " level info
    }
}
```

{% endcode %}

Run the following command to clear all firewall rules and log all connections:

{% code title="Command" %}

```
sudo nft -f log-everyting.conf
```

{% endcode %}

You can now follow all connections using:

```
sudo journalctl -k --follow
```

To stop following the log, press <kbd>Ctrl</kbd>+<kbd>C</kbd>.

Because each connection is logged on a separate line, this quickly becomes hard to read. On a server with heavy traffic, the logs can grow to contain a very large number of lines.

This short and simple one‑liner below summarizes all connections recorded in the journal. Each host/port combination appears on its own line, and the number of connections is counted:

{% code title="Command" %}

```
sudo journalctl -k | grep "IN=" | awk -F'[= ]+' '{for (i=1;i < NF;i++) { if ($i=="DST") dst=$(i+1);if ($i=="SRC") src=$(i+1); if ($i=="PROTO") proto=$(i+1); if ($i=="DPT") dpt=$(i+1); if($i=="INCOMING:"||$i=="OUTGOING:") dir=$i} printf "%s %-20s %-20s %-15s %s \n",dir," DST:"dst," SRC:"src," PROTO:"proto," DPT:"dpt}' |sort | uniq -c
```

{% endcode %}

The same method can be used to log all blocked connections, which can be very useful for troubleshooting. Below is a complete example of a firewall configuration that only allows incoming SSH connections from `10.10.10.10` and blocks and logs all other connections. Save the below content to a file called `drop-and-log.conf`.

{% code title="drop-and-log.conf" %}

```
#!/usr/sbin/nft -f

flush ruleset

table ip filter {
    chain INPUT {
        type filter hook input priority 0; policy drop;
        ct state related,established accept
        ip saddr 10.10.10.10 tcp dport 22 accept
        ct state new log prefix "INCOMING: " level info
        drop
    }

    chain OUTPUT {
        type filter hook output priority 0; policy drop;
        ct state related,established accept
        ct state new log prefix "OUTGOING: " level info
        drop
    }
}
```

{% endcode %}

To load this firewall configuration (note that **everything will be blocked except for SSH** **from 10.10.10.10**), run the following:

{% code title="Command" %}

```
sudo nft -f drop-and-log.conf
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.glesys.com/products/compute/guides-for-server-management/logging-with-iptables-and-nftables.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
