For legal obligations on an open public network, I had to work on connection log management. The architecture was based on a Debian 12 bookworm, which served as an Internet gateway for the clients, with nftables for the firewall. The aim was to log all packets passing through the router, retrieving the following informations: mac addresses, destination IPs and protocols used.
The problem is that now, with the implementation of systemd, all system messages are handled by it. Unfortunately, this isn't very configurable (or maybe I'm juste a big dummy 😅). Indeed, I haven't found a way to do what I've outlined above with systemd. To meet my needs, I used Rsyslog to sort log messages and logrotate to manage the history. To be quite precise, Rsyslog doesn't replace systemd/journal, in fact it will just retrieve the logs from the latter and enable us to meet the needs set out above.
Depending on the number of clients and their usage, the size of the systemd/journal file can be very large in a short space of time. By default, its size is limited to 10% of the size of the underlying file system and capped at 4 GiB. See here for more information: https://wiki.archlinux.org/. In any case, I'll first set the maximum size of the systemd/journal to 1 GiB maximum. As explained, we don't really need it anymore, as Rsyslog will write the same events to /var/logs/syslog and (this is what we'll set) to /var/logs/nftables/ for nftables logs.
SystemMaxUse=1G
root@host:~# systemctl restart systemd-journald.service
root@host:~# apt install rsyslog
root@host:~# mkdir /var/log/nftables/
# /etc/rsyslog.conf configuration file for rsyslog
#
# For more information install rsyslog-doc and see
# /usr/share/doc/rsyslog-doc/html/configuration/index.html
#################
#### MODULES ####
#################
module(load="imuxsock") # provides support for local system logging
module(load="imklog") # provides kernel logging support
#module(load="immark") # provides --MARK-- message capability
# provides UDP syslog reception
#module(load="imudp")
#input(type="imudp" port="514")
# provides TCP syslog reception
#module(load="imtcp")
#input(type="imtcp" port="514")
###########################
#### GLOBAL DIRECTIVES ####
###########################
#
# Set the default permissions for all log files.
#
$FileOwner root
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog
#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf
###############
#### RULES ####
###############
# the regex rule below corresponds to traditional nftables logs, which take the following form: IN=interface1 OUT=interface2.
# Each “match” will be written to /var/log/nftables/nftables.log
:msg, regex, "IN=[A-Za-z0-9_]* OUT=" -/var/log/nftables/nftables.log
# & stop means that the match will not write to another file
& stop
#
# Log anything besides private authentication messages to a single log file
#
*.*;auth,authpriv.none -/var/log/syslog
#
# Log commonly used facilities to their own log file
#
auth,authpriv.* /var/log/auth.log
cron.* -/var/log/cron.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
#
# Emergencies are sent to everybody logged in.
#
*.emerg :omusrmsg:*
root@host:~# systemctl restart rsyslog
/etc/logrotate.d/rsyslog
/var/log/syslog
/var/log/mail.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/cron.log
{
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
/var/log/nftables/nftables.log
{
rotate 365
size 100M
daily
missingok
notifempty
compress
delaycompress
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
dateext
dateformat .%Y.%m.%d
dateyesterday
}
root@host:~# systemctl restart logrotate.service
As explained, I needed to record the mac addresses, the protocols and the IP addresses. To do so, we juste need to add the mention log flags ether on our nftables rules. Use all to enable all flags. See official page to see others flags here: https://wiki.nftables.org/wiki-nftables/.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy drop; #by default, we drop traffic
ct state invalid drop
ip saddr 192.168.1.0/24 tcp dport { http, https } ct state { new, related, established } counter log flags ether accept comment "accept WEB"
ip saddr 192.168.1.0/24 udp dport { domain, ntp } ct state { new, related, established } counter log flags ether accept comment "DNS"
ip saddr 192.168.1.0/24 icmp type { echo-reply, echo-request} counter log flags ether accept comment "allow icmp"
ip daddr 192.168.1.0/24 ct state { established, related } counter accept
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table ip my_nat {
chain my_masquerade {
type nat hook postrouting priority 100; policy accept;
ip daddr != { 192.168.1.0/24 } oifname "wan" masquerade comment "outgoing NAT"
}
}
root@host:~# nft -f /etc/nftables.conf
root@host:~# ls /var/log/nftbles/
total 1,9G
-rw-r----- 1 root adm 457M 6 déc. 20:14 nftables.log
Note the size of the log file, which is larger than the size defined in the /etc/logrotate.d/rsyslog configuration file. This is because logrotate is run once a day. It is not triggered once a condition is met, but only if it is met when it is run at 00:00.
Contact :