# # Private BASHlib for Watcher-Report2 # declare -A grands=([records] [cidrs] [plain] [nodes] [label]) _LABELW=34 OUTFORM="%-34s : %8d %8d %8d %'15d\n" TOTFORM="%34s » %8d %8d %8d %'15d\n" DETFORM="%34s . %8d %8d %8d %'15d\n" COLFORM="%34s | %8s %8s %8s %15s\n" # Draw a section headline # $1 headline text # $2 character for line headline() { local funtag="[${FUNCNAME[0]}]" local total=78 awk -v text="$1" -v tot_width=$total -v char="$2" ' BEGIN { prefixlen=5 for (i=1; i<=prefixlen; i++) { prefix = prefix char } strlen = length(text); suffixlen = tot_width - length(prefix) - strlen - 1; # "- 2" für die Leerzeichen if (suffixlen < 0) suffixlen = 0; suffix = sprintf("%*s", suffixlen, ""); # Generiere leerzeichen-basiertes Padding gsub(" ", char, suffix); # Ersetze Leerzeichen mit "-" print "" print prefix " " text " " suffix; }' } # Draw a simple separation line # $1 character for line sepline() { local funtag="[${FUNCNAME[0]}]" local total=79 awk -v tot_width=$total -v char="$1" ' BEGIN { for (i=1; i<=tot_width; i++) { line = line char } # print "" print line; }' } # Print a section headline sec_headline() { # $1 Section name # $2 character to use local funtag="[${FUNCNAME[0]}]" local total=35 awk -v text="$1" -v tot_width=$total -v char="$2" ' BEGIN { prefixlen=5 for (i=1; i<=prefixlen; i++) { prefix = prefix char } strlen = length(text); suffixlen = tot_width - length(prefix) - strlen - 1; # "- 2" für die Leerzeichen if (suffixlen < 0) suffixlen = 0; suffix = sprintf("%*s", suffixlen, ""); # Generiere leerzeichen-basiertes Padding gsub(" ", char, suffix); # Ersetze Leerzeichen mit "-" print "" print prefix " " text " " suffix; }' } colheaders() { local funtag="[${FUNCNAME[0]}]" local prefix suffix printf "$COLFORM" "" "Records" "CIDRs" "nIPs" "xIPs" # prefix=`printf "%34s"` # suffix=`printf "%8s %8s %8s %15s" "Records" "CIDRs" "nIPs" "xIPs" | tr " " "_"` # echo "$prefix | $suffix" } lineout() { local funtag="[${FUNCNAME[0]}]" printf "$OUTFORM" "$1" $2 $3 $4 $5 } tot_out() { local funtag="[${FUNCNAME[0]}]" local tot_label local -n map=$1 : echo "$funtag" : echo "incomming tot lable '${map[label]}'" if [ -z "${map[label]}" ] then tot_label="Total records & DROPs" else tot_label="${map[label]}" fi if [ -z "$tot_label" ] then echo "BANG!"; return fi sepline _ printf "$TOTFORM" "$tot_label" ${map[records]} ${map[cidrs]} ${map[plain]} ${map[nodes]} } # Calculate total nodes for CIDRs # $1 DROP list name calc_subips() { local funtag="[${FUNCNAME[0]}]" local elems elems=`ipset list $1 | grep '^[1-9]' | grep "/"` awk ' BEGIN { total = 0 } { x = split($0, parts, "/" ) bits = (32 - parts[2]) range = 2^bits total += range } END { print total } ' <<< "$elems" } # # Conditionally dump detals for an IPset # dump_details() { # $1 the IPset's name local funtag="[${FUNCNAME[0]}]" : echo $funtag : echo "»» IPset $1 ««" [ -n "$_TRACE" ] && echo $funtag case $1 in WatchLG*) details_LG "$1" ;; WatchMX*) details_MX "$1" ;; WatchWB*) details_WB "$1" ;; *) echo "IPset $1 is not known" ;; esac } # # Common for detail output ... # process_details() { local all="$1" local num num_cidrs num_plain num_nodes local detail local details="$2" local set="$3" declare -A det sec_headline "$4" "$5" colheaders for detail in $details do num=$(grep "$detail" <<< "$all" | wc -l) num_cidrs=$(grep "$detail" <<< "$all" | grep -c "/") num_plain=$(grep "$detail" <<< "$all" | grep -vc "/") num_nodes=0 if [ $num_cidrs -gt 0 ] then num_nodes=$(calc_subips "$set") fi det[records]=$num det[cidrs]=$num_cidrs det[plain]=$num_plain det[nodes]=$num_nodes det[label]=$detail det[set]=$set detail_out det done } # # IPset details for the login module LG # details_LG() { # $1 the set name local funtag="[${FUNCNAME[0]}]" local module_txt='Login' local details="NXDOMAIN FAKEHOST TRUEHOST" local all=`grep "DB,$module_txt," <<< "$ALL"` process_details "$all" "$details" "$1" "$module_txt" "-" } # # Details MX # Views 'Mail' and 'Mailbox' details # details_MX() { # $1 The set name local funtag="[${FUNCNAME[0]}]" local all module_txt local details="NXDOMAIN FAKEHOST TRUEHOST" : echo $funtag # Phase #1 - Mail MTA module_txt='Mail' all=`grep "DB,$module_txt," <<< $ALL` process_details "$all" "$details" "$1" "$module_txt" "-" # Phase #2 - Mailbox POP/IMAP module_txt='Mailbox' all=`grep "DB,$module_txt," <<< $ALL` process_details "$all" "$details" "$1" "$module_txt" "-" } # # Details WB # The WEB module has arbitrary classes defined # by 'WEB_CLASS=...' in the *.rule files # details_WB() { # $1 The set name local funtag="[${FUNCNAME[0]}]" local module_txt='WEB' local all local details #declare -A det : echo $funtag details=`get_wb_details` all=`grep "DB,$module_txt," <<< $ALL` process_details "$all" "$details" "$1" "$module_txt" "-" } get_wb_details() { local funtag="[${FUNCNAME[0]}]" local all local section="DB,WEB," local details all=`ipset l | grep "$section"` awk ' BEGIN {} { split($0,parts,",") detail=parts[3] gsub("\"","",detail) details[detail]=detail } END { for (detail in details) { print detail } } ' <<< $all | sort } # # Switch some ugly row labels # pretty() { # $1 A row label local pretty case $1 in NXDOMAIN) pretty="NX Domains" ;; FAKEHOST) pretty="Fake hosts" ;; TRUEHOST) pretty="True hosts" ;; *) pretty="$1" esac echo "$pretty" } detail_out() { # $1 Map of detail values local funtag="[${FUNCNAME[0]}]" local -n map=$1 #local row_label="${map[set]},${map[label]}" local row_label=`pretty "${map[label]}"` [ -n "$_TRACE" ] && echo $funtag : echo ${map[*]} printf "$DETFORM" "$row_label" ${map[records]} ${map[cidrs]} ${map[plain]} ${map[nodes]} } # # Dump a single set # dump_set() { # $1 set name # $2 row label # $3 map for totals cumulation local funtag="[${FUNCNAME[0]}]" local -n map=$3 local set=$1 local row_label="$2" local all num num_cidrs num_plain num_nodes local detail_sets="WatchLG-DB WatchMX-DB WatchWB-DB" all=`$IPSET list $set | grep '^[1-9]'` # if [[ "$detail_sets" =~ "$set" ]] # then dump_details $set # fi case $set in Watch*) dump_details $set ;; esac num=`wc -l <<< $all` num_cidrs=`grep -c "/" <<< $all` num_plain=`grep -vc "/" <<< $all` if [ $num_cidrs -gt 0 ] then num_nodes=`calc_subips $set` else num_nodes=0 fi (( map[records] += num )) (( map[cidrs] += num_cidrs )) (( map[plain] += num_plain )) (( map[nodes] += num_nodes )) # Add to the grand-totals (global) as well .. (( grands[records] += num )) (( grands[cidrs] += num_cidrs )) (( grands[plain] += num_plain )) (( grands[nodes] += num_nodes )) lineout "$row_label" $num $num_cidrs $num_plain $num_nodes } # # Dump out a bunch of sets # dump_sets() { # $1 List of sets # $2 Row prefix # $3 Passed label for totals # $4 Section headings local funtag="[${FUNCNAME[0]}]" local set sets="$1" local row_label tot_label local section section_headers="$4" section_texts declare -A tot=([records]=0 [cidrs]=0 [plain]=0 [nodes]=0 [label]='') : echo "$funtag" if [ -z "$3" ] then tot[label]="Tot label empty, $funtag" else tot[label]="$3" fi for set in `echo $sets` do row_label="$2 '$set'" dump_set $set "$row_label" tot done tot_out tot } report_ipsets() { local funtag="[${FUNCNAME[0]}]" local row_label="Internal IPset" local tot_label="Totals internal IPsets" #local sets=`$IPSET l -n` #local sets='custody' local sets=$RELEVANT_SETS # from the conf file headline "Internal IP sets" _ colheaders dump_sets "$sets" "$row_label" "$tot_label" } report_module_dbs() { local funtag="[${FUNCNAME[0]}]" local modules="LG MX WB" local row_label="DROPs in module DB" local tot_label="Total of module DBs" local set sets db local sections="DB,Login DB,Mail DB,Mailbox DB,WEB" headline "Module databases" _ # colheaders sets=`printf "Watch%s-DB " $modules | xargs` dump_sets "$sets" "$row_label" "$tot_label" "$sections" } report_dynloader() { local funtag="[${FUNCNAME[0]}]" local sets="spamhaus nixspam" # should be in the conf file local row_label="DROPS contributed by" local tot_label="Total DROPS from dynloaders" headline "Dynloader" _ colheaders dump_sets "$sets" "$row_label" "$tot_label" } report_geo_tracker() { # the pseudo module's DB local funtag="[${FUNCNAME[0]}]" local modules="GeoTrack" local row_label="Pseudo module DB" local tot_label="Total DROPs in GeoTrack" local set sets db headline "Geo Tracker" _ colheaders sets=`printf "%s-DB " $modules` dump_sets "$sets" "$row_label" "$tot_label" } report_geo_blocker() { # stuff from ipdeny local funtag="[${FUNCNAME[0]}]" local row_label="DROPs contrib. by ipdeny" local tot_label="Total geo blockings" local sets CMD=`grep ZONES $MASTER_PATH/dynload/geo/geo.conf ` eval $CMD headline "Geo blockings" _ echo "($CMD)" colheaders sets=`printf "geo-%s " $ZONES | xargs` : echo "Sets: '$geosets'" dump_sets "$sets" "$row_label" "$tot_label" } report_black() { local funtag="[${FUNCNAME[0]}]" local sets="blacklist" local row_label="DROPs in" local tot_label="Blacklist totals" headline "Blacklist (manually maintained in $MASTER_PATH)" _ colheaders dump_sets "$sets" "$row_label" "$tot_label" } report_white() { local funtag="[${FUNCNAME[0]}]" local sets="whitelist" local row_label="ACCEPTS in" local tot_label="Whitelist totals" headline "Whitelist (manually maintained in $MASTER_PATH)" _ colheaders dump_sets "$sets" "$row_label" "$tot_label" } report_summary() { local funtag="[${FUNCNAME[0]}]" echo headline "Grand totals" "#" sepline "#" report_black report_white headline "Total firewall" = colheaders # lineout "Total drops in firewall" ${grands[records]} ${grands[cidrs]} ${grands[plain]} ${grands[nodes]} grands[label]="Total drops in firewall" tot_out grands } dropped-packets() { local all echo " ««««« Continued access of DROPed bandits »»»»» " all=`grep '\ packets\ [0-9]*' <<< $ALL` : echo "$all" awk ' function drawline (len,char, i,line) { for (i=1; i<=len; i++) { line = line char } print line } /(packets 0)/ { next } { # Extract IPSET Name ... match($0, /comment "([^"]+)"/, tmp) set = tmp[1] gsub(" ", "", set) # Entferne Leerzeichen aus dem Set-Namen sets[set] = set # Extract packet count ... match($0, /packets ([0-9]+)/, tmp) packets = tmp[1] # Extract byte count ... match($0, /bytes ([0-9]+)/, tmp) bytes = tmp[1] # printf "Packets: %8d, Bytes %15d\n", packets, bytes # Debug ... packet_sum[set] += packets byte_sum[set] += bytes } END { printf "%-30s %8s %15s\n", "IPset comment", "Packets","Bytes" #drawline (50,"-") print "-------------------------------------------------------" asort (sets) for (s in sets) { printf "%-30s %8d %15d\n", sets[s], packet_sum[sets[s]], byte_sum[sets[s]] total_packets += packet_sum[sets[s]] total_bytes += byte_sum[sets[s]] } print "-------------------------------------------------------" printf "%30s %8d %15d\n", "Totals:", total_packets, total_bytes } ' <<< $all }