A possible implementation to find out signs of network traffic generated by SSH sessions is via firewall rules:
- Initially, rules matching traffic coming to and coming from port 22/tcp are loaded at boot time;
- Then, a script periodically retrieves statistics information from firewall and stores hit counts of those rules into a temporary file;
- The script will be able to detect network traffic by detecting changes in any hit count.
That approach would also detect traffic generated by SFTP and RSYNC, as both applications run over SSH protocol.
Detection of update activities would be hard to perform via firewall because package downloads use FTP, HTTP and HTTPS protocol and firewall rules would need to be tuned to differentiate software updates from recorded HTTP traffic. Because of that, my suggestion is to detect software updates by checking modification time of /var/lib/apt/lists
, /var/cache/apt/archives
and /var/lib/dpkg/lock
.
My implementation proposal is as follows:
These command lines set up iptables
and ip6tables
rules.
# apt-get install iptables-persistent
# iptables -w -N fwstats
# iptables -w -A fwstats
# iptables -w -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# iptables -w -A OUTPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# iptables-save > /etc/iptables/rules.v4
# ip6tables -w -N fwstats
# ip6tables -w -A fwstats
# ip6tables -w -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# ip6tables -w -A OUTPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# ip6tables-save > /etc/iptables/rules.v6
This is the equivalent setup for nftables
:
# apt-get install nftables
# nft add chain inet filter fwstats
# nft add rule inet filter fwstats counter
# nft add rule inet filter input tcp dport ssh ct state established jump fwstats
# nft add rule inet filter output tcp dport ssh ct state established jump fwstats
# echo -e \#\!`which nft` -f\\nflush ruleset > /etc/nftables.conf
# nft list ruleset >> /etc/nftables.conf
And this is a template of a monitoring script. The getStats
function should be adjusted according to the firewall in use.
#!/bin/bash
getStats () {
if using_nftables; then
nft list chain inet filter fwstats | grep counter
elif using_xtables; then
for xtable in iptables ip6tables; do
"${xtable}" -w -xnvL fwstats | egrep '^([[:space:]]+[0-9]+){2,2}'
done
fi
}
stateFile="/run/hibernation_state"
currentStats="`getStats`"
if [ "x${currentStats}" != "x" ]; then
previousStats="`cat \"${stateFile}\"`"
if [ "x${currentStats}" == "x${previousStats}" ]; then
# No network traffic has been detected. Check files related do DPKG and APT
clearToHibernate='true'
now="`date '+%s'`"
for path in "${stateFile}" \
'/var/lib/apt/lists' \
'/var/cache/apt/archives' \
'/var/lib/dpkg/lock' ; do
pathModTime="`stat -c '%Y' "${path}"`"
# 10800 seconds = 3 hours
if [ "$((now-10800))" -lt "${pathModTime}" ]; then
clearToHibernate='false'
fi
done
if "${clearToHibernate}"; then
# OK to hibernate.
systemctl hibernate
fi
else
# Network traffic has been detected. Refresh stats.
echo "${currentStats}" > "${stateFile}"
fi
fi