#!/bin/bash
#----------------------------------------------------------------
# Synflood-Defender
# Author: Volodymyr Kononenko - vmkononenko@gmail.com
#----------------------------------------------------------------

programpath="/etc/synflood-defender/"
configfile=$programpath"synflood-defender.conf"

declare -A config
declare -A normal
declare -A protect

while read line
do
    # Checking if the line in config is comment
    if [[ `echo ${line:0:1}` == "#" || $line == "" ]]
	then continue
    fi
    
    configparam=`echo $line | awk '{print $1}'`
    
    # Checking if the config parameter is kernel parameter
    if [[ `echo ${configparam:0:2}` != "__" ]]
	then 
	    config[$configparam]=`echo $line | awk '{print $3}'`
	    continue
    fi
    
    # Checking if dynamic protection is enabled
    if [ $configparam == "dynamic_protection" ]
	then
	    if [ `echo $line | awk '{print $3}'` -eq 0 ]
		then
		    break
		else continue
	    fi
    fi
    
    # If dynamic protection is enabled in config
    # Reading configuration in normal mode
    mode=`echo  $configparam | awk -F"__" '{print $2}'`		# Mode - normal or protect
    kernelparam=`echo  $configparam | awk -F"__" '{print $3}'`	# Kernel parameters
    if [ $mode == "normal" ]
	then
	    normal["$kernelparam"]=`echo $line | awk '{print $3}'`
	    continue
    fi
    
    if [ $mode == "protect" ]
	then
	    protect[$kernelparam]=`echo $line | awk '{print $3}'`
	    continue
    fi
    
done <$configfile

# Current SYN queue length
current_synqueue=`ss -nat | grep SYN-RECV | wc -l`
echo $current_synqueue

# Reading current protection mode
read state <$programpath"state"

if [ ${config[dynamic_protection]} -eq 1 ]
    then
	if [ $current_synqueue -ge ${config[threshold]} ]
	    then
		# If state is normal, protective parameters are set
		if [ $state == "normal" ]
		    then
			for p in ${!protect[@]}
			do
			    sysctl $p=${protect[$p]}
			    echo "protect" > $programpath"state"
			done
		fi
	    else
		# If state is protect, and force protection mode is disabled normal parameters are set
		if [ ${config[force_protection]} -ne 1 ]
		    then
			if [ $state == "protect" ]
			    then
				for p in ${!normal[@]}
				do
				    sysctl $p=${normal[$p]}
				    echo "normal" > $programpath"state"
				done
			fi
		else
		    for p in ${!protect[@]}
		    do
			sysctl $p=${protect[$p]}
			echo "protect" > $programpath"state"
		    done
		fi
	fi
    else
	if [ $state == "protect" ]
	    then
		for p in ${!normal[@]}
		do
		    sysctl $p=${normal[$p]}
		    echo "normal" > $programpath"state"
		done
	fi
fi