#!/bin/bash # # $Id: log_traffic,v 1.1.1.1 2005/08/12 16:41:11 dodell Exp $ # Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. # # 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" # don't run during build process /bin/hostname |/bin/grep mfg.cobaltmicro.com &>/dev/null && exit 0 STATUSFILE="/var/state/acct/last" # last count on basic chains LOGFILE="/var/log/ipacct" # log file we generate TRAFFICFILE="/var/state/acct/traffic" # current traffic we parse FWCONFIGFILE="/etc/ipchains.conf" # ipchains rules configuration IPCHAINS="/sbin/ipchains" IPTABLES="/sbin/iptables" IFCONFIG="/sbin/ifconfig" if [ -x $IPTABLES ]; then export TABLES=1 FWCONFIGFILE="/etc/sysconfig/iptables" # much like the ipchains rules configuration fi # Update the accounting rules and the ipchains/tables config file if [ $TABLES ]; then echo "# $FWCONFIGFILE # This file is automatically generated by log_traffic. # Any manual changes will be lost *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :acctin - [0:0] :acctout - [0:0] -A INPUT -j acctin -A OUTPUT -j acctout" > $FWCONFIGFILE else echo "# $FWCONFIGFILE # This file is automatically generated by log_traffic. # Any manual changes will be lost $IPCHAINS -N acctin $IPCHAINS -N acctout $IPCHAINS -F acctin $IPCHAINS -F acctout $IPCHAINS -I input 2 -j acctin $IPCHAINS -I output 2 -j acctout" > $FWCONFIGFILE fi # Get a list of the ips that are currently being accounted for (LAST_IPS) # and a list of the ips that should be monitored (UP_IPS). if [ $TABLES ]; then LAST_IPS=`$IPTABLES -L acctin -vn | awk '/all.*[[:digit:]]/ { print $8 }'` else LAST_IPS=`$IPCHAINS -L acctin -vn | awk '/all.*[[:digit:]]/ { print $10 }'` fi UP_IPS=`$IFCONFIG | grep "inet addr" | cut -f 2 -d":" | cut -f 1 -d" "` # Add rules for ips that are in use but not accounted for, # and add rules to config file for all IPs in use for ip in $UP_IPS; do if [ $TABLES ]; then echo -A acctin -d "$ip/32" >> $FWCONFIGFILE echo -A acctout -s "$ip/32" >> $FWCONFIGFILE else echo $IPCHAINS -I acctout -s "$ip/32" >> $FWCONFIGFILE fi if [ -z "`echo $LAST_IPS | grep $ip`" ]; then if [ $TABLES ]; then $IPTABLES -I acctin -d $ip/32 $IPTABLES -I acctout -s $ip/32 else $IPCHAINS -I acctin -d $ip/32 $IPCHAINS -I acctout -s $ip/32 fi fi done # Delete rules for ips that are no longer in use for ip in $LAST_IPS; do # FIXME: this test is not right. Try grepping 1.2.3.4 from 1.2.3.40. oops if [ -z "`echo $UP_IPS | grep $ip`" ]; then if [ $TABLES ]; then $IPTABLES -D acctin -d $ip/32 $IPTABLES -D acctout -s $ip/32 else $IPCHAINS -D acctin -d $ip/32 $IPCHAINS -D acctout -s $ip/32 fi fi done echo 'COMMIT' >> $FWCONFIGFILE # Now capture the lastest traffic and log it # zero and record the usage in one step so we don't miss a packet if [ $TABLES ]; then $IPTABLES -Z -L -xvn > $TRAFFICFILE else $IPCHAINS -Z -L -xvn > $TRAFFICFILE fi DATE=`date +"[%d/%b/%Y:%H:%M:%S %z]"` # you can't zero the default chains, # so we maintain the previous values in a file so we can do diffs if [ ! -e $STATUSFILE ]; then touch $STATUSFILE INITIALIZE=1 fi . $STATUSFILE OLD_INPUT=$INPUT OLD_FORWARD=$FORWARD OLD_OUTPUT=$OUTPUT ###### iptables format # Chain OUTPUT (policy ACCEPT 79 packets, 11646 bytes) # pkts bytes target prot opt in out source destination # 79 11646 acctout all -- * * 0.0.0.0/0 0.0.0.0/0 # 79 11646 acctout all -- * * 0.0.0.0/0 0.0.0.0/0 # 79 11646 acctout all -- * * 0.0.0.0/0 0.0.0.0/0 # # Chain acctin (24 references) # pkts bytes target prot opt in out source destination # 0 0 all -- * * 0.0.0.0/0 127.0.0.1 # 459 24108 all -- * * 0.0.0.0/0 10.9.28.134 # # Chain acctout (24 references) # pkts bytes target prot opt in out source destination # 0 0 all -- * * 127.0.0.1 0.0.0.0/0 # 0 0 all -- * * 127.0.0.1 0.0.0.0/0 # 237 34938 all -- * * 10.9.28.134 0.0.0.0/0 # 237 34938 all -- * * 10.9.28.134 0.0.0.0/0 ###### # parse the traffic file and update the log file cat $STATUSFILE | awk ' END { while (getline 0) { line = $0 if ( $line ~ /Chain.*\(/) { chain = $2 bytes = $7 if ( chain ~ /(input)|(output)|(forward)|(INPUT)|(OUTPUT)|(FORWARD)/ ) { traffic[chain] += bytes fastforward = 1 # fastforward means skip to next chain } else { fastforward = 0 # otherwise look at the lines for this chain } } if ( (line ~ /all/) && ( fastforward == 0 ) ) { bytes = $2 if ( chain ~ /acctin/ ) { if ( tables ) { ip = $8 } else { ip = $10 } traffic["acctin"] += bytes } else { traffic["acctout"] += bytes if ( tables ) { ip = $7 } else { ip = $9 } } printf("%s - - %s \"GET /%s HTTP/1.1\" 200 %s \"\" \"\"\n", ip, date, chain, bytes) } } if ( ! initialize ) { # * "other" traffic is traffic not destined for a specific ip # * we subtract the values from the last run for the default chains if ( ! tables) { # ipchains wont let you zero these traffic["otherin"] = traffic["input"] - oldin - traffic["acctin"] traffic["otherout"] = traffic["output"] - oldout - traffic["acctout"] traffic["otherforward"] = traffic["forward"] - oldforward } else { traffic["otherin"] = traffic["INPUT"] - traffic["acctin"] traffic["otherout"] = traffic["OUTPUT"] - traffic["acctout"] traffic["otherforward"] = traffic["FORWARD"] } printf("Other - - %s \"GET /input HTTP/1.1\" 200 %s \"\" \"\"\n", date, traffic["otherin"]) printf("Other - - %s \"GET /output HTTP/1.1\" 200 %s \"\" \"\"\n", date, traffic["otherout"]) printf("Other - - %s \"GET /forward HTTP/1.1\" 200 %s \"\" \"\"\n", date, traffic["otherforward"]) } # update our records for the last value of the default chains printf("INPUT=%s\nFORWARD=%s\nOUTPUT=%s\n", traffic["input"], traffic["forward"], traffic["output"]) >statusfile }' trafficfile=$TRAFFICFILE logfile=$LOGFILE tables=$TABLES statusfile=$STATUSFILE oldin=$OLD_INPUT oldout=$OLD_OUTPUT oldforward=$OLD_FORWARD "date=$DATE" initialize=$INITIALIZE >> $LOGFILE