#!/usr/bin/bash
#
# log_traffic
#  
# This script maintains and logs the activity on the ip accounting rules.
# It updates the accounting rules based on the currently running interfaces,
# and then captures the current use, logs that, zeros the counters.
#
# This updates the accounting rules and logs as often as it is run. 
# Therefore this frequency determines the amount of resolution you will
# get in the logs and how long it will take for an ip to get accounted for
# after it is added.

# Hardcode locale to be English, otherwise we may utilities may output Japanese strings that would mess up our parsing.
LC_ALL="en_US"
LANG="en_US"

LOGFILE="/var/log/ipacct"           # log file we generate
IPTABLES="/sbin/iptables"           # iptable binary
IFCONFIG="/sbin/ifconfig"           # ifconfig binary
IPLISTNOW="/var/state/acct/iplist.now"      # Temp file - list of ip addresses from ifconfig
IPLISTBEFORE="/var/state/acct/iplist.before"    # Temp file - list of current ip addresses we monitor

# Disable error messages - Some IpTables commands we use to check status generate cosmetic errors. Lets suppress them
exec 3>&2
exec 2> /dev/null

# Is firewalld enabled?
FWDUP=$(LC_ALL=C systemctl status firewalld|grep "Loaded: loaded"|grep "; enabled;"|wc -l)

if [ -d "/etc/apf" ] || [ "$FWDUP" -gt "0" ];then
    # Wipe /etc/sysconfig/iptables clean. We do this so that an install/upgrade 
    # of 'iptables-services' doesn't bring a default config back:
    rm -f /etc/sysconfig/iptables
    touch /etc/sysconfig/iptables
    echo "# Empty, because APF is present" > /etc/sysconfig/iptables
    rm -f /etc/sysconfig/ip6tables
    touch /etc/sysconfig/ip6tables
    echo "# Empty, because APF is present" > /etc/sysconfig/ip6tables
    # We exit here. No point going further.
    exit
fi

# Command line option clean - to reset all rules that we use
if [ "$1" = "clean" ]; then
    iptables -D INPUT -j acctin 2>&1 > /dev/null
    iptables -D OUTPUT -j acctout 2>&1 > /dev/null
    iptables -F acctin 2>&1 > /dev/null
    iptables -F acctout 2>&1 > /dev/null
    iptables -X acctin 2>&1 > /dev/null
    iptables -X acctout 2>&1 > /dev/null
fi

# Create our accounting tables if required
for X in acctin acctout; do
    $IPTABLES -L $X -vn 2>&1 > /dev/null
    if [ $? -eq 1 ]; then
        $IPTABLES -N $X
        $IPTABLES -A $X -j RETURN
    fi
done

# Generate a list of IP's that we are already monitoring
$IPTABLES -Z -vS acctin | grep "acctin -d" | cut -d " " -f 4 | cut -d "/" -f 1 | sort | uniq > $IPLISTBEFORE

# Generate a list of IP's that appear in ifconfig
$IFCONFIG | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | grep -v "^255\|^0" | sort | uniq > $IPLISTNOW

# Add new IP addresses that are in ifconfig but not yet monitored
for ip in `diff $IPLISTBEFORE $IPLISTNOW | grep ">" | cut -d " " -f 2`
do
    $IPTABLES -I acctin -d "$ip/32" -j RETURN 
    $IPTABLES -I acctout -s "$ip/32" -j RETURN
done

# Generate our traffic file with a couple of one-liners
DATE=`date +"[%d/%b/%Y:%H:%M:%S %z]"`
$IPTABLES -Z -vS acctin | grep "^.A" | sed -e "s#acctin -c#acctin -d Other/32 -c#" -e "s/.* -d //" -e "s#/32##" | cut -d " " -f 1,4 | sed -e "s# # - - $DATE \"GET /acctin HTTP/1.1\" 200 #" -e 's#$# "" ""#' >> $LOGFILE

$IPTABLES -Z -vS acctout | grep "^.A.*-s" | sed -e "s#acctout -c#acctout -s Other/32 -c#" -e "s/.* -s //" -e "s#/32##" | cut -d " " -f 1,4 | sed -e "s# # - - $DATE \"GET /acctout HTTP/1.1\" 200 #" -e 's#$# "" ""#' >> $LOGFILE

# Delete IP addresses from rules for removed virtual interfaces
for X in `diff $IPLISTBEFORE $IPLISTNOW | grep "<" | grep -v 0.0.0.0 | cut -d " " -f 2`
do
    $IPTABLES -D acctin -d "$ip/32" -j RETURN
    $IPTABLES -D acctout -s "$ip/32" -j RETURN
done

# Check acctin reference from INPUT and add/repair if required
CHECK=`$IPTABLES --list INPUT -nv | grep all | grep -c acctin`
if [ $CHECK -eq 0 ]; then
    $IPTABLES -I INPUT -j acctin
else
    if [ $CHECK -gt 1 ]; then
        echo Error - multiple IP accounting references detected - trying to fix
        $IPTABLES -D INPUT -j acctin
    else
        # Be greedy - make us first in the list
        CHECK=`$IPTABLES --list INPUT -nv | grep all | head -1 | grep -c acctin`
        if [ $CHECK -eq 0 ]; then
            $IPTABLES -D INPUT -j acctin
            $IPTABLES -I INPUT -j acctin
        fi
    fi
fi

# Check acctout reference from OUTPUT and add/repair if required
CHECK=`$IPTABLES --list OUTPUT -nv | grep all | grep -c acctout`
if [ $CHECK -eq 0 ]; then
    $IPTABLES -I OUTPUT -j acctout
else
    if [ $CHECK -gt 1 ]; then
        echo Error - multiple IP accounting references detected - trying to fix
        $IPTABLES -D OUTPUT -j acctout
    else
        # Be greedy - make us first in the list
        CHECK=`$IPTABLES --list OUTPUT -nv | grep all | head -1 | grep -c acctout`
        if [ $CHECK -eq 0 ]; then
            $IPTABLES -D OUTPUT -j acctout
            $IPTABLES -I OUTPUT -j acctout
        fi
    fi
fi

if [ ! -d "/etc/apf" ];then
    # Save new iptables rules: We do this so that an install/upgrade 
    # of 'iptables-services' doesn't bring a default config back:
    iptables-save > /etc/sysconfig/iptables
fi

# Re-enable error messages
exec 2>&3

rm $IPLISTNOW $IPLISTBEFORE

# 
# Copyright (c) 2008-2022 Michael Stauber, SOLARSPEED.NET
# Copyright (c) 2008-2022 Team BlueOnyx, BLUEONYX.IT
# Copyright (c) 2003 Sun Microsystems, Inc. 
# All Rights Reserved.
# 
# 1. Redistributions of source code must retain the above copyright 
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in 
#    the documentation and/or other materials provided with the 
#    distribution.
# 
# 3. Neither the name of the copyright holder nor the names of its 
#    contributors may be used to endorse or promote products derived 
#    from this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.
# 
# You acknowledge that this software is not designed or intended for 
# use in the design, construction, operation or maintenance of any 
# nuclear facility.
# 