Back to posts
Post

Monitoring /etc/hosts.allow and hosts.deny Changes with auditd

Learn how to use auditd to detect real-time modifications to TCP wrappers files and get instant alerts on unauthorized changes.

Siber GüvenlikauditdTCP wrapperslog monitoring

I recently had to harden a legacy application server that still relied on TCP wrappers for access control. While most of our services have moved to firewalld or nftables, this one box needed /etc/hosts.allow and /etc/hosts.deny monitored closely. Any unexpected edit could open a backdoor or break connectivity. Here’s how I set up auditd to watch those files in real time.

Why auditd for TCP wrappers files

TCP wrappers is simple but fragile. A single typo in hosts.allow or hosts.deny can lock you out or expose services. I’ve seen admins accidentally comment out a line during a rushed edit, leaving SSH open to the world. Because these files are plain text and edited frequently during troubleshooting, they’re perfect candidates for integrity monitoring. auditd gives me kernel-level visibility without needing a separate agent.

Setting up audit rules

First, I verified auditd was running:

systemctl status auditd

Then I added watches for both files with write and attribute change tracking:

auditctl -w /etc/hosts.allow -p wa -k hosts_file_change
auditctl -w /etc/hosts.deny -p wa -k hosts_file_change

The -p wa flag triggers on write (w) and attribute changes (a), like chown or chmod. The -k sets a filter key so I can easily search logs later. To make these rules survive reboots, I added them to /etc/audit/rules.d/hosts_file.rules:

-w /etc/hosts.allow -p wa -k hosts_file_change
-w /etc/hosts.deny -p wa -k hosts_file_change

After saving, I reloaded the rules:

augenrules --load

Watching for changes in real time

I use ausearch to filter by my key. For live tailing, I combine it with ausearch’s streaming mode:

ausearch -f /etc/hosts.allow -f /etc/hosts.deny -k hosts_file_change -i

The -i converts IDs to usernames and group names for readability. When I test by editing hosts.allow:

echo "sshd: 10.0.0.5" >> /etc/hosts.allow

I immediately see an event like:

type=PATH audit(1717000000.123:456): item=0 name="/etc/hosts.allow" inode=12345 dev=08:02 mode=0100644 ouid=0 ogid=0 ruid=0 rgid=0 pid=1234 auid=500 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 exe="/usr/bin/bash" hostname=? addr=? terminal=pts/0 res=success

This tells me who changed what, when, and from which terminal.

Automating alerts

I don’t want to watch a terminal all day. So I configured a simple alert via rsyslog. First, I ensured audit events are logged to /var/log/audit/audit.log (they are by default). Then I created a rsyslog snippet:

if $programname == 'auditd' and $msg contains 'hosts_file_change' then /var/log/hosts_warnings.log
& stop

I placed this in /etc/rsyslog.d/30-hosts-watch.conf and restarted rsyslog. Now every matching audit event gets copied to a dedicated log file. From there, I can hook it into monitoring tools like Zabbix or Prometheus node exporter with a textfile collector.

Common pitfalls

One mistake I made early was using -p r (read) instead of wa. That flooded the logs with every sshd or tcpd lookup—completely useless. Stick to write and attribute changes unless you’re debugging a specific access issue.

Another gotcha: if you edit the file with vim, it may create a temporary swap file and rename it. auditd still catches the rename as an attribute change, so you’re covered. But if you see multiple rapid events, that’s likely why.

Final thoughts

TCP wrappers isn’t modern, but it’s still in use. Monitoring its config files with auditd gives me peace of mind without overcomplicating the setup. It’s lightweight, native to the kernel, and integrates with existing audit pipelines. If you’re responsible for any legacy host with hosts.allow/deny, this is a low-effort, high-visibility control worth implementing.

As I mentioned before in my post about journald rate limiting, kernel auditing works best when paired with smart log rotation and alerting—don’t just collect data, act on it.

Quick reference commands

  • List active rules: auditctl -l
  • Search recent changes: ausearch -k hosts_file_change -i
  • Watch live: ausearch -f /etc/hosts.allow -f /etc/hosts.deny -k hosts_file_change -i
  • Make rules persistent: edit /etc/audit/rules.d/hosts_file.rules then augenrules --load

Cover image: West Virginia National Guard · PDM (Openverse / kamu malı) · https://www.flickr.com/photos/163885612@N02/55234262183