#!/bin/bash
#################################################################
# Criado por: Eduardo Jonck                                     #
# Email: eduardo@eduardojonck.com                               #
# Site: http://openfw.com.br                           # 
#################################################################


#Variaveis
TURNOFF=`cat /var/efw/fail2ban/settings |grep FAIL2BAN_ENABLE |cut -d= -f2`
BANTIME=`cat /var/efw/fail2ban/settings |grep BANTIME= |cut -d"=" -f2`
MAXRETRYWEBGUI=`cat /var/efw/fail2ban/settings |grep MAXRETRYWEBGUI= |cut -d"=" -f2`
MAXRETRYSSH=`cat /var/efw/fail2ban/settings |grep MAXRETRYSSH= |cut -d"=" -f2`
MAXRETRYOPENVPN=`cat /var/efw/fail2ban/settings |grep MAXRETRYOPENVPN= |cut -d"=" -f2`
PORTOPENVPN=`cat /var/efw/fail2ban/settings |grep PORTOPENVPN= |cut -d"=" -f2`
PORTSSH=`cat /var/efw/fail2ban/settings |grep PORTSSH= |cut -d"=" -f2`
WHITELIST=`cat /var/efw/fail2ban/whitelist | awk '{a=$0;printf "%s ",a,$0}'`
DROPPERMANENTE=`cat /var/efw/fail2ban/settings |grep FAIL2BAN_DROP_PERM |cut -d= -f2`

#Função de Help
print_help() {
  echo "Utilize: fail2ban-webgui [OPTIONS]."
  echo
  echo -e "Options:"
  echo
  echo -e "   --restart - Reiniciar o serviço Fail2ban"
  echo -e "   --reports - Gera um relatório de acordo com os dias solicitados"
  echo -e "   --archiving-ips - Envia os IPs bloqueados para um arquivo para uso do bloqueio permanente"
  echo -e "   --drop-permanent - Bloqueia os IPs atacantes de forma permanente"
  echo -e "   --update-geoip - Atualiza a base de dados GeoIP dos paises atacantes"
  echo -e "   --status - Consulta se o serviço do Fail2Ban está em execução"

              }




#Função para reiniciar o serviço
restart() {

if [ $TURNOFF == "on" ]; then



echo "[DEFAULT]

ignoreip = $WHITELIST

bantime = $BANTIME

banaction = iptables-multiport

[sshd]
enabled = true
port = $PORTSSH
protocol = tcp
logpath = /var/log/messages
maxretry = $MAXRETRYSSH
backend = polling

[sshd-ddos]
enabled = true
port = $PORTSSH
protocol = tcp
logpath = /var/log/messages
maxretry = $MAXRETRYSSH

[apache-auth]
enabled  = true
port     = 80,443,10443
protocol = tcp
filter   = apache-auth
logpath  = /var/log/httpd/error_log
maxretry = $MAXRETRYWEBGUI

[apache-noscript]
enabled  = true
port     = 80,443,10443
protocol = tcp
filter   = apache-noscript
logpath  = /var/log/httpd/error_log
maxretry = $MAXRETRYWEBGUI

[apache-botsearch]
enabled  = true
port     = 80,443,10443
protocol = tcp
logpath  = /var/log/httpd/error_log
maxretry = $MAXRETRYWEBGUI

[openvpn-tcp]
enabled  = true
port     = $PORTOPENVPN
filter   = openvpn
protocol = tcp
logpath  = /var/log/openvpn/openvpn.log
maxretry = $MAXRETRYOPENVPN

[openvpn-udp]
enabled  = true
port     = $PORTOPENVPN
filter   = openvpn
protocol = udp
logpath  = /var/log/openvpn/openvpn.log
maxretry = $MAXRETRYOPENVPN" > /etc/fail2ban/jail.local


echo "[Init]
chain = INPUT
name = default
port = ssh
protocol = tcp
blocktype = REJECT --reject-with icmp-port-unreachable
returntype = RETURN
lockingopt =
iptables = iptables <lockingopt>

[Init?family=inet6]
blocktype = REJECT --reject-with icmp6-port-unreachable
iptables = ip6tables <lockingopt>" > /etc/fail2ban/action.d/iptables-common.conf

echo "[DEFAULT]
loglevel = INFO
logtarget = SYSLOG[facility=local0]
syslogsocket = auto
socket = /var/run/fail2ban/fail2ban.sock
pidfile = /var/run/fail2ban/fail2ban.pid
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 1d
dbmaxmatches = 10

[Definition]

[Thread]" > /etc/fail2ban/fail2ban.conf


echo "[INCLUDES]

before = iptables-common.conf

[Definition]

actionstart = <iptables> -N f2b-<name>
              <iptables> -A f2b-<name> -j <returntype>
              <iptables> -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>

actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
             <actionflush>
             <iptables> -X f2b-<name>

actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]'

actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
            <iptables> -I f2b-<name> 1 -s <ip> -j NFLOG --nflog-prefix 'FAIL2BAN-SERVICE:DROP'

actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype>
              <iptables> -D f2b-<name> -s <ip> -j NFLOG --nflog-prefix 'FAIL2BAN-SERVICE:DROP'

[Init]" > /etc/fail2ban/action.d/iptables-multiport.conf


/etc/init.d/fail2ban restart &>/dev/null
chmod 755 /var/run/fail2ban/fail2ban.pid
rm -rf /tmp/nohup-fail2ban-webgui-restart.err
rm -rf /tmp/fail2ban-webgui-restart.out

if [ -f /var/efw/inithooks/start.local ]; then
	sed -i '/fail2ban-webgui/d' /var/efw/inithooks/start.local
	echo "/usr/local/bin/fail2ban-webgui --restart" >> /var/efw/inithooks/start.local
else
	echo "#!/bin/bash" > /var/efw/inithooks/start.local
	echo "/usr/local/bin/fail2ban-webgui --restart" >> /var/efw/inithooks/start.local
	chmod 755 /var/efw/inithooks/start.local
fi

	else

	#Remove o comando de inicializacao e para o serviço e remove as regras de firewall aplicadas
	sed -i '/fail2ban/d' /var/efw/inithooks/start.local
	/etc/init.d/fail2ban stop &>/dev/null
	iptables -F FAIL2BAN_DROP_PERM &>/dev/null
    ipset flush fail2ban-drop-perm &>/dev/null
	ipset destroy fail2ban-drop-perm &>/dev/null

fi


}

#Função para atualizar o arquivo GeoIP
update-geoip() {
rm -rf /var/efw/fail2ban/geoip/dbip4.dat &>/dev/null
echo "Atualizando o Banco de Dados do GeoIP....."
wget https://dl.miyuru.lk/geoip/dbip/country/dbip4.dat.gz --no-check-certificate -O /var/efw/fail2ban/geoip/dbip4.dat.gz &>/dev/null
gunzip /var/efw/fail2ban/geoip/dbip4.dat.gz &>/dev/null
data=$(date "+%b %d %H:%M:%S efw")
echo "$data Banco de Dados do GeoIP atualizado!" >> /var/log/fail2ban/fail2ban.log
echo "Banco de Dados do GeoIP atualizado!"
}


#Função de drop permanente
drop-permanent () {
			if [ "$DROPPERMANENTE" == "on" ]; then

				CHAIN_FAIL2BAN_DROP_PERM=$(iptables -L FAIL2BAN_DROP_PERM |grep Chain |wc -l)
				INPUT_FAIL2BAN_DROP_PERM=$(iptables -L INPUT |grep FAIL2BAN_DROP_PERM |wc -l)
				CHECK_RUN_IPSET_FAIL2BAN=$(ipset --list fail2ban-drop-perm |wc -l)

				if [ $CHAIN_FAIL2BAN_DROP_PERM -eq 0 ]; then
					iptables -N FAIL2BAN_DROP_PERM &>/dev/null
				fi

				if [ $INPUT_FAIL2BAN_DROP_PERM -eq 0 ]; then
					iptables -I INPUT -j FAIL2BAN_DROP_PERM &>/dev/null
				fi

				#Remove as regras atuais se existir para serem recriadas
				if [ $CHECK_RUN_IPSET_FAIL2BAN -ne 0 ];then
					ipset flush fail2ban-drop-perm &>/dev/null
					ipset destroy fail2ban-drop-perm &>/dev/null
				fi

				#Cria o ipset e adiciona os IPs para dentro do ipset criado
				    ipset create fail2ban-drop-perm hash:net &>/dev/null
				for ips in `cat /var/efw/fail2ban/ips_ban.db`;do		
					ipset add fail2ban-drop-perm $ips &>/dev/null	
				done
				
				#Limpa as regras atuais de firewal
				iptables -F FAIL2BAN_DROP_PERM &>/dev/null
				#Cria as regras iptables para dropar
				iptables -A FAIL2BAN_DROP_PERM -p tcp -m multiport --dport $PORTOPENVPN -m set --match-set fail2ban-drop-perm src -j NFLOG --nflog-prefix "FAIL2BAN-PERM:DROP"
				iptables -A FAIL2BAN_DROP_PERM -p tcp -m multiport --dport $PORTOPENVPN -m set --match-set fail2ban-drop-perm src -j DROP
				iptables -A FAIL2BAN_DROP_PERM -p udp -m multiport --dport $PORTOPENVPN -m set --match-set fail2ban-drop-perm src -j NFLOG --nflog-prefix "FAIL2BAN-PERM:DROP"
				iptables -A FAIL2BAN_DROP_PERM -p udp -m multiport --dport $PORTOPENVPN -m set --match-set fail2ban-drop-perm src -j DROP			
				iptables -A FAIL2BAN_DROP_PERM -p tcp -m multiport --dport $PORTSSH -m set --match-set fail2ban-drop-perm src -j NFLOG --nflog-prefix "FAIL2BAN-PERM:DROP"
				iptables -A FAIL2BAN_DROP_PERM -p tcp -m multiport --dport $PORTSSH -m set --match-set fail2ban-drop-perm src -j DROP
				iptables -A FAIL2BAN_DROP_PERM -p tcp --dport 10443 -m set --match-set fail2ban-drop-perm src -j NFLOG --nflog-prefix "FAIL2BAN-PERM:DROP"
				iptables -A FAIL2BAN_DROP_PERM -p tcp --dport 10443 -m set --match-set fail2ban-drop-perm src -j DROP
				
				#Cria as regras de Whitelist se acaso foi selecionado a opção de drop permanente
					iptables -F FAIL2BAN_WHITELIST &>/dev/null
					iptables -D INPUT -j FAIL2BAN_WHITELIST &>/dev/null
					iptables -X FAIL2BAN_WHITELIST &>/dev/null
					iptables -N FAIL2BAN_WHITELIST &>/dev/null
					iptables -I INPUT -j FAIL2BAN_WHITELIST &>/dev/null	
				for whitelist in `cat /var/efw/fail2ban/whitelist`;do		
					iptables -I FAIL2BAN_WHITELIST -s $whitelist -p tcp -m multiport --dport $PORTOPENVPN -j ACCEPT
					iptables -I FAIL2BAN_WHITELIST -s $whitelist -p tcp -m multiport --dport $PORTSSH -j ACCEPT
					iptables -I FAIL2BAN_WHITELIST -s $whitelist -p tcp --dport 10443 -j ACCEPT			
				done
				
				
                
                #Agenda para ser executado o drop permanente 2X ao dia (11 e 23 horas)
                check_cron=$(cat /etc/cron.d/fail2ban |grep "drop-permanent" |wc -l)
                if [ $check_cron -eq 0 ]; then
                echo "0 11,23 * * * /usr/local/bin/fail2ban-webgui --drop-permanent" >>  /etc/cron.d/fail2ban
                /etc/init.d/fcron restart &>/dev/null
                fi


			else
    
	#Limpa todas as regras de firewall carregadas
    iptables -F FAIL2BAN_DROP_PERM &>/dev/null
	#Remove as regras atuais se existir para serem recriadas
	ipset flush fail2ban-drop-perm &>/dev/null
	ipset destroy fail2ban-drop-perm &>/dev/null

    check_cron=$(cat /etc/cron.d/fail2ban |grep "drop-permanent" |wc -l)
    if [ "$check_cron" != "0" ]; then
    sed -i '/drop-permanent/d'  /etc/cron.d/fail2ban
    /etc/init.d/fcron restart &>/dev/null
	fi
	
    echo "Opção de bloquear os IPs atacantes permanente está desativada! Ative na GUI se deseja usar esse recurso!"
            fi
}

#Função de arquivamento de logs
archiving-ips() {

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select ip TEXT from bans" >> /var/efw/fail2ban/ips_ban.db
cat /var/efw/fail2ban/ips_ban.db | sort | uniq > /var/efw/fail2ban/tmp_ips_ban.db
mv /var/efw/fail2ban/tmp_ips_ban.db /var/efw/fail2ban/ips_ban.db
}


#Função que faz a consulta de todos os IPs da lista par saber de qual pais o IP pertence
reports() {
#Coleta os dias que deseja de relatório
dias=$(cat /var/efw/fail2ban/consult-reports |cut -d= -f2)


#Limpa os dados atuais dos gráficos
sed -i '/^\[/d' /home/httpd/cgi-bin/fail2ban_reports.cgi &>/dev/null

#Faz a busca dos ips atacantes nos arquivos de logs arquivados e de hoje
rm -rf /tmp/ips_atacantes
for logs in `find /var/log/archives -mtime -$dias -ls |grep firewall |awk '{print $11}'`;do
    zgrep FAIL2BAN-SERVICE $logs |awk '{print $10}' |sed 's/SRC=//g' >> /tmp/ips_atacantes
done 
    zgrep FAIL2BAN-SERVICE /var/log/firewall |awk '{print $10}' |sed 's/SRC=//g' >> /tmp/ips_atacantes
    cat /tmp/ips_atacantes | sort | uniq > /tmp/ips_atacantes_old
    mv /tmp/ips_atacantes_old /tmp/ips_atacantes

#Faz a busca de qual pais os ips pertencem
rm -rf /tmp/query_geoip
echo "Atualizando o mapa GeoIP dos países atacantes. Isso pode levar um tempo dependendo da quantidade de IPs a ser consultado..... Aguarde........"
for ip in `cat /tmp/ips_atacantes`; do
    geoiplookup -f /var/efw/fail2ban/geoip/dbip4.dat $ip |awk '{print $4}' |sed "s/,//g" >> /tmp/query_geoip
done

#Imprime os dados no CGI
old_IFS=$IFS
IFS=$'\n'
for i in `cat /tmp/query_geoip |sort -n |uniq -c |sort -nr | tr 'a-z' 'A-Z' |sed '/FOUND/d' |awk '{print "[ " "\x27"$2,"\x27" ", "$1   " ]" ","}'`;do
    sed  -i "/delimitador_paises_atacantes/i $i" /home/httpd/cgi-bin/fail2ban_reports.cgi
done
IFS=$old_IFS

#Atualiza as portas mais atacadas
rm -rf /tmp/portas_atacadas
for portas in `find /var/log/archives -mtime -$dias -ls |grep firewall |awk '{print $11}'`;do
    zgrep FAIL2BAN-SERVICE $portas |awk -F= '{print $14}' |awk '{print $1}' >> /tmp/portas_atacadas
done
    zgrep FAIL2BAN-SERVICE /var/log/firewall |awk -F= '{print $14}' |awk '{print $1}' >> /tmp/portas_atacadas

old_IFS=$IFS
IFS=$'\n'
for ports in `sort /tmp/portas_atacadas |uniq -c |awk '{print"[""\x27"$2"\x27"",",$1"]"","}'`; do
    sed  -i "/delimitador_portas_atacadas/i $ports" /home/httpd/cgi-bin/fail2ban_reports.cgi
done
IFS=$old_IFS


#Busca os ataques separados por dias
rm -rf /tmp/dias_atacados
for dia in `find /var/log/archives -mtime -$dias -ls |grep firewall |awk '{print $11}'`;do
    zgrep FAIL2BAN-SERVICE $dia |awk '{print $1,$2}' |uniq -c |tail -1 >> /tmp/dias_atacados
done
    zgrep FAIL2BAN-SERVICE /var/log/firewall |awk '{print $1,$2}' |uniq -c  |tail -1 >> /tmp/dias_atacados

old_IFS=$IFS
IFS=$'\n'
for d in `sort /tmp/dias_atacados |awk '{print $3,$2,$1}' |sort -n |awk '{print"[""\x27"$1,$2"\x27"",",$3"]"","}'`; do
    sed  -i "/delimitador_ataques_dia/i $d" /home/httpd/cgi-bin/fail2ban_reports.cgi
done
IFS=$old_IFS


#Data da ultima atualização
data=$(date "+%d/%m/%Y %H:%M:%S")
sed -i '/gerados:/d' /home/httpd/cgi-bin/fail2ban_reports.cgi &>/dev/null
sed  -i "/delimitador_grafico_gerado/i Data em que os gráficos foram gerados: $data" /home/httpd/cgi-bin/fail2ban_reports.cgi

#Dias da ultima solicitacao
sed -i '/solicitados/d' /home/httpd/cgi-bin/fail2ban_reports.cgi &>/dev/null
sed  -i "/delimitador_dias_solicitado_reports/i Dias que foram solicitados na última vez: $dias" /home/httpd/cgi-bin/fail2ban_reports.cgi

#Limpa informações dos dias gerados no ultimo relatório
echo > /var/efw/fail2ban/consult-reports

}


#Função para checar se o serviço está UP

status() {
service=`iptables -L -n |grep "Chain f2b" | wc -l`

if [ $service -gt 0 ]; then
/etc/init.d/fail2ban status
echo
echo " - Regras Iptables Fail2Ban estao ativas! Nada a ser feito...."
echo
else
echo "Regras fail2Ban nao estavam aplicadas. Aplicando regras Iptables para Fail2Ban...."
/usr/local/bin/fail2ban-webgui --restart &>/dev/null
fi

}



#Case das escolhas possíveis
case "$1" in
         --help)
         	print_help
	 	exit;
	 ;;
         -h)
	         print_help
        	 exit;
         ;;


         --restart)	
		restart
		drop-permanent
        exit;
         ;;

         --reports)	
        reports
        exit;
         ;;

        --archiving-ips)	
        archiving-ips
        exit
         ;;

        --drop-permanent)	
        drop-permanent
        exit
         ;;

        --update-geoip)	
        update-geoip
        exit
         ;;

         --status)	
        status
        exit
         ;;

         *)
        	 print_help
         	 exit 3 
         ;;
esac