Simple firewalld watcher

Posted on Thu 02 April 2026 • 2 min read

While doing HackTheBox, CTF’s or similar stuff, I sometimes need a reverse shell to connect back to my computer.

This is almost always using a VPN, so I don’t have to think about NAT, firewall openings, etc

But more than once I’ve struggled to get a rev shell to connect back. Why? My computer has a local firewall 🤦

The solution is simple: sudo systemctl stop firewalld.service - but I actually want firewalld running most of the time, so this is not a good long-term solution.

Instead wouldn’t it be nice to get a notification whenever firewalld blocked something, to quickly diagnose the problem?

firewalld alert using script below

We can do that by first configuring firewalld to log all blocked connections:

firewall-cmd --set-log-denied=all   # or: unicast, broadcast, multicast
firewall-cmd --runtime-to-permanent

By watching journalctl fun-fact: users aren’t allowed to read dmesg directly (why is that??), but journalctl --dmesg exposes it for REJECT log entries, we can use notify-send to spawn a GUI alert!

journalctl --follow --dmesg --grep="FINAL_REJECT|REJECT" | while read -r line; do
    src=$(grep -oP 'SRC=\K\S+' <<< "$line")
    dpt=$(grep -oP 'DPT=\K\d+' <<< "$line")
    notify-send -i network-error "firewalld blocked" "src=$src port=$dpt"
done

The above is a long-running process which will “hang” your terminal. If you background it, it will still be a child process, so it stops when your terminal dies.

We can solve this by disowning the process, but now we also need to make sure we don’t end up spawning multiple processes that monitors the same thing. One ugly hack is simply to pgrep the somewhat unique string, if it works, it works.

The full script to put in your ~/.*rc:

firewall-watcher() {
    if [[ $(firewall-cmd --get-log-denied) != "all" ]]; then
        echo "firewalld log-denied is not set to 'all'." >&2
        echo "Please run: firewall-cmd --set-log-denied=all" >&2
    fi
    pgrep -f 'journalctl.*REJECT' > /dev/null && return 0
    journalctl --follow --dmesg --grep="REJECT" | while read -r line; do
        src=$(grep -oP 'SRC=\K\S+' <<< "$line")
        dpt=$(grep -oP 'DPT=\K\d+' <<< "$line")
        notify-send -i network-error "firewalld blocked" "src=$src port=$dpt"
    done &
    disown
}