Skip to content

NetworkLogsPersistence

Linux Firewall Logs: iptables, nftables, ufw, firewalld

Netfilter packet log lines from iptables, nftables, ufw and firewalld, plus firewall rule files that reveal tampering, on Debian, Ubuntu and RHEL hosts.

Location
/var/log/ufw.log, /var/log/kern.log
Proves
Which connections the host blocked or logged, from which IPs and ports, and whether firewall rules were changed
Timestamps
Syslog/journal time of the kernel message (journal: UTC microseconds); rule files: file system times
Access
root (or adm group for /var/log files on Debian/Ubuntu)
Retention
Follows syslog rotation and journal limits; rule files until changed
Collection
UAC, Velociraptor, cp -a, nft list ruleset

What it is

The Linux packet filter (netfilter) logs nothing by default. A log line exists only when a rule with the iptables LOG target or the nftables log statement matches a packet. The kernel then writes a message into its ring buffer, from where journald and rsyslog pick it up. Front ends generate those rules for you: ufw logs blocked packets at its default low level, while firewalld logs denied packets only when LogDenied is set (default off).

Two kinds of evidence matter: the packet log lines (scans, blocked connections, sometimes allowed new connections), and the rule configuration itself, because disabling or opening the firewall is a common attacker step.

Where it lives

ItemDebian / UbuntuRHEL / FedoraNotes
Kernel log lines/var/log/kern.log, /var/log/syslog, journal/var/log/messages, journal_TRANSPORT=kernel in the journal
ufw packet log/var/log/ufw.log(ufw rarely used)Written by rsyslog via /etc/rsyslog.d/20-ufw.conf matching [UFW
ufw rules/etc/ufw/user.rules, user6.rules, before*.rules, after*.rules, /etc/ufw/ufw.conf, /etc/default/ufwbefore.init/after.init scripts run if executable
firewalld config/etc/firewalld/firewalld.conf, /etc/firewalld/zones/*.xml, defaults in /usr/lib/firewalld/LogDenied=, DefaultZone=
firewalld daemon log/var/log/firewalldDaemon debug and error messages, not packets
nftables rules/etc/nftables.conf/etc/sysconfig/nftables.conf including /etc/nftables/*.nftLoaded by nftables.service
iptables rules/etc/iptables/rules.v4, rules.v6 (iptables-persistent)/etc/sysconfig/iptables, ip6tables (iptables-services)Restored at boot
Connection trackingconntrack -L (live only)sameCurrent and recent flows in kernel memory

ufw also sends its messages with the kernel facility, so without a stop rule they appear in kern.log and syslog as well as ufw.log. On hosts without rsyslog, the journal is the only store.

What it proves

  • Blocked (and, depending on rules, allowed) packets with source and destination IP, ports, protocol, interface and TCP flags: port scans, brute-force sources, blocked C2 callbacks in OUTPUT rules.
  • That logging or filtering was changed: rule file mtimes, ufw state in ufw.conf (ENABLED=no), LogDenied=off, flushed rulesets.
  • With auditd, NETFILTER_CFG records show when netfilter tables were changed.
  • It does not prove a connection succeeded, and allowed traffic is usually not logged. ufw rate limits its log rules at every level below full, so counts are lower bounds.

Key fields

A kernel LOG line (the same layout is used by iptables LOG and nftables log):

Sep 20 03:12:40 web-prod-03 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:12:34:56:52:54:00:ab:cd:ef:08:00 SRC=203.0.113.50 DST=198.51.100.10 LEN=60 TOS=0x00 PREC=0x00 TTL=52 ID=43080 DF PROTO=TCP SPT=40022 DPT=23 WINDOW=64240 RES=0x00 SYN URGP=0
FieldMeaning
prefixText set by the rule: [UFW BLOCK], [UFW ALLOW], [UFW AUDIT], firewalld names such as filter_IN_public_REJECT or FINAL_REJECT, or a custom --log-prefix (max 29 characters)
IN= / OUT=Input and output interface; empty OUT= means the packet was for the host
MAC=Destination MAC, source MAC and EtherType concatenated
SRC= / DST=Source and destination IP
LEN, TOS, PREC, TTL, IDIP header values; TTL hints at the sender's OS and hop count
DFDon't Fragment flag set
PROTO=TCP, UDP, ICMP ...
SPT= / DPT=Source and destination port
WINDOW, RES, SYN/ACK/FIN/RST, URGPTCP window, reserved bits, flags, urgent pointer
UID=Local sending user, only with --log-uid (outbound packets)

Timestamps

The kernel line has no absolute time of its own in the text log; the timestamp is added by rsyslog (traditional local time or RFC 3339 depending on configuration, see auth.log) or by journald (UTC microseconds). Rule files carry only file system timestamps, so a change time on /etc/ufw/user.rules or /etc/nftables.conf is a timeline anchor.

journalctl -D /mnt/evidence/var/log/journal -b all _TRANSPORT=kernel --utc -o short-iso-precise | grep -E 'UFW|REJECT|DROP|SRC='

Retention

Packet logs share the fate of the file they are in: kern.log, syslog and messages rotate weekly with about four generations on default Debian and RHEL configurations; check /etc/logrotate.d/ for a ufw or rsyslog stanza covering ufw.log. Journal copies follow the journal's size limits, and a noisy LOG rule can push older entries out quickly. conntrack entries expire within minutes to days depending on protocol state and exist only in memory.

Collection

Collect the running ruleset before anything else: it lives in kernel memory and may differ from the files on disk.

# Live, as root
nft list ruleset > nft_ruleset.txt
iptables-save > iptables-save.txt; ip6tables-save > ip6tables-save.txt
iptables -V                               # "(nf_tables)" or "(legacy)" backend
ufw status verbose > ufw_status.txt 2>/dev/null
firewall-cmd --list-all-zones > firewalld_zones.txt 2>/dev/null
firewall-cmd --get-log-denied >> firewalld_zones.txt 2>/dev/null
conntrack -L > conntrack.txt 2>/dev/null
# Dead box
tar -C /mnt/evidence -cpf /cases/2026-017/fw.tar etc/ufw etc/default/ufw etc/firewalld etc/nftables.conf etc/sysconfig/nftables.conf etc/nftables etc/iptables etc/sysconfig/iptables etc/sysconfig/ip6tables var/log 2>/dev/null

UAC's live response runs iptables -L -v -n, nft list ruleset, ufw and firewall-cmd commands when the tools exist, and collects /var/log and /etc.

Parsing

# Top blocked sources and ports from ufw
zgrep -h 'UFW BLOCK' ufw.log* | grep -oE 'SRC=[^ ]+|DPT=[0-9]+' | paste - - | sort | uniq -c | sort -rn | head
# One source across all kernel logs
zgrep -h 'SRC=203.0.113.50' kern.log* syslog* messages* 2>/dev/null
# Compare the live ruleset (collected earlier) with the boot-time file; expect formatting noise
diff nft_ruleset.txt /mnt/evidence/etc/nftables.conf

Rule files are plain text; compare them against package defaults in /usr/lib/firewalld/ or the distribution package, and against configuration management copies. Plaso ingests the syslog files for timelines. In the browser, Linux Log Parser puts the kernel firewall lines from kern.log, syslog, messages and the journal on one timeline with logins and sudo; it does not split SRC= / DPT= into columns, so keep the zgrep counts above for traffic statistics.

Investigator tips

  • No firewall lines at all usually means no LOG rules, not deleted logs. Check the ufw logging level (LOGLEVEL= in /etc/ufw/ufw.conf) and LogDenied before drawing conclusions.
  • ENABLED=no in ufw.conf, an empty /etc/nftables.conf, iptables -F or ufw disable in shell history or auditd EXECVE records, and NETFILTER_CFG audit events near the incident indicate deliberate weakening.
  • ufw's before.init and after.init, and any script called from nftables.service or iptables-restore units, run as root at boot: check them as persistence alongside systemd units.
  • Look for ACCEPT rules for a single odd port or source IP added outside change windows; match them to SSH or web server activity from the same IP.
  • Blocked outbound packets from a server (non-empty OUT=, empty IN=) are a strong lead for malware beaconing; --log-uid output can name the local account.
  • Rule tables and conntrack are volatile; follow the order of volatility and capture them before a reboot or isolation change flushes them.

See also