1
0
ketr.services/cron/entrypoint.sh
2023-10-10 11:45:38 -07:00

137 lines
3.5 KiB
Bash
Executable File

#!/bin/bash
CMD=$1
email_check() {
FILE=$1
FILE=${FILE:=mail.log}
NOFILTER=$2
function filterDate {
if [[ "${NOFILTER}" == "" ]]; then
DATE="$*"
else
DATE=""
fi
EXP1="s#^${DATE}"'.*pam\(([^,]*),([^)]*).*((auth_username_chars)|(password mismatch)).*#\1 \2#p'
EXP2="s#^${DATE}"'.*plain\(\?,([^,)]*)\).*disallowed by auth_username_chars.*username: ([^)]*).*#\2 \1#p'
sed -En \
-e "${EXP1}" \
-e "${EXP2}" \
"/var/log/${FILE}" |
sed -E 's,@ketrenos\.com,,g' |
sort |
uniq -f 1 --group=prepend |
sort |
uniq -c |
tail -n +2
}
mapfile -t data < <(
if [[ "${NOFILTER}" == "" ]]; then
filterDate "$(date --date yesterday +"%b %e")"
else
filterDate "$(date +"%b %e")"
fi)
declare -a ip_address=()
threshold=3
echo "IPs with >= ${threshold} hits"
printf "%6s %-17s %s\n" "Count" "IP"
declare -A ips
for line in "${data[@]}"; do
parts=(${line})
count=${parts[0]}
address=${parts[1]}
ip=${parts[2]}
if [[ "${ip}" == "" ]]; then
echo "Bad line: $line"
continue
fi
if [[ ! " ${ip} " =~ " ${ip_addresses[*]} " ]]; then
ip_addresses+=("${ip}")
fi
if [[ "${ips[${ip}]}" == "" ]]; then
ips[${ip}]=1
else
ips[${ip}]=$((ips[${ip}]+1))
fi
done
for key in "${!ips[@]}"; do
if (( ips[${key}] >= threshold )); then
printf "%6d %s\n" "${ips[${key}]}" "${key}"
fi
done | sort -n -r
echo "Addresses attempted to be breached"
printf "%6s %-17s %s\n" "Count" "IP" "Address"
for line in "${data[@]}"; do
parts=(${line})
count=${parts[0]}
address=${parts[1]}
ip=${parts[2]}
printf "%6s %-17s %s\n" "${count}" "${ip}" "${address}"
done
echo -e "\nIn progress netmask determination..."
# Call the Python routine with the IP addresses as arguments
python - "${ip_addresses[@]}" << END
import sys
import socket
import collections
import os
from collections import defaultdict
def validate_ip_addresses(ip_addresses):
for ip in ip_addresses:
try:
socket.inet_aton(ip)
except socket.error:
print("Invalid IP address:", ip)
sys.exit(1)
def calculate_netmask(ip_addresses):
binary_ips = [bin(int(socket.inet_aton(ip).encode('hex'), 16))[2:].zfill(32) for ip in ip_addresses]
common_prefix = os.path.commonprefix(binary_ips)
netmask = common_prefix + '0'*(32-len(common_prefix))
return '.'.join([str(int(netmask[i:i+8], 2)) for i in range(0, 32, 8)])
def count_netmasks(ip_addresses):
netmask_counts = defaultdict(int)
for ip in ip_addresses:
ip_octets = ip.split('.')
binary_ip = ''.join([bin(int(octet))[2:].zfill(8) for octet in ip_octets])
netmask = '1' * binary_ip.count('1') + '0' * (32 - binary_ip.count('1'))
netmask_counts[netmask] += 1
return netmask_counts
def to_bytes(n, length, byteorder='big'):
h = '%x' % n
s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex')
return s if byteorder == 'big' else s[::-1]
ip_addresses = sys.argv[1:]
validate_ip_addresses(ip_addresses)
netmask_counts = count_netmasks(ip_addresses)
# find_greatest_common_netmask(ip_addresses)
sorted_netmask_counts = sorted(netmask_counts.items(), key=lambda x: x[1], reverse=True)
for netmask, count in sorted_netmask_counts:
netmask_str = socket.inet_ntoa(to_bytes(int(str(netmask), 2), 4, byteorder='big'))
print(str(count) + ' ' + netmask_str + '/' + str(32-len(netmask)))
END
}
case "${CMD}" in
email-check)
email_check dovecot.log
;;
*)
while true; do
cron -f
echo "cron died: $?"
sleep 5
done
;;
esac