#!/bin/bash
# info: update system firewall rules
# options: NONE
#
# The function updates iptables rules


#----------------------------------------------------------#
#                    Variable&Function                     #
#----------------------------------------------------------#

# Defining absolute path for iptables and modprobe
iptables="/sbin/iptables"
modprobe="/sbin/modprobe"
sysctl="/sbin/sysctl"

# Includes
source /etc/profile.d/vesta.sh
source $VESTA/func/main.sh
source $VESTA/conf/vesta.conf


#----------------------------------------------------------#
#                    Verifications                         #
#----------------------------------------------------------#

is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'


#----------------------------------------------------------#
#                       Action                             #
#----------------------------------------------------------#

# Checking local IPv4 rules
rules="$VESTA/data/firewall/rules.conf"
ports="$VESTA/data/firewall/ports.conf"

if [ ! -e "$rules" ]; then
    exit
fi

$sysctl net.netfilter.nf_conntrack_max >/dev/null 2>&1
if [ $? -ne 0 ]; then
    conntrack='no'
fi

# Checking conntrack module avaiabilty
$modprobe nf_conntrack >/dev/null 2>&1
$modprobe nf_conntrack_ftp >/dev/null 2>&1
if [ $? -ne 0 ]; then
    conntrack_ftp='no'
fi

# Checking custom OpenSSH  port
sshport=$(grep '^Port ' /etc/ssh/sshd_config | head -1 | cut -d ' ' -f 2)
if [[ "$sshport" =~ ^[0-9]+$ ]] && [ "$sshport" -ne "22"  ]; then
    sed -i "s/PORT='22'/PORT=\'$sshport\'/" $rules
fi

# Creating temporary file
tmp=$(mktemp)

# Flushing INPUT chain
echo "$iptables -P INPUT ACCEPT" >> $tmp
echo "$iptables -F INPUT" >> $tmp

# Enabling stateful support
if [ "$conntrack" != 'no' ]; then
    str="$iptables -A INPUT -m state"
    str="$str --state ESTABLISHED,RELATED -j ACCEPT"
    echo "$str" >> $tmp
fi

# Handling local traffic
for ip in $(ls $VESTA/data/ips); do
    echo "$iptables -A INPUT -s $ip -j ACCEPT" >> $tmp
done
echo "$iptables -A INPUT -s 127.0.0.1 -j ACCEPT" >> $tmp

# Pasring iptables rules
IFS=$'\n'
for line in $(sort -r -n -k 2 -t \' $rules); do
    eval $line
    if [ "$SUSPENDED" = 'no' ]; then
        proto="-p $PROTOCOL"
        port="--dport $PORT"
        ip="-s $IP"
        state=""
        action="-j $ACTION"

        # Adding multiport module
        if [[ "$PORT" =~ ,|-|: ]] ; then
            port="-m multiport --dports ${PORT//-/:}"
        fi

        # Accepting all dst ports
        if [[ "$PORT" = "0" ]] || [ "$PROTOCOL" = 'ICMP' ]; then
            port=""
        fi

        # Checking FTP for contrack module
        if [ "$TYPE" = "FTP" ] || [ "$PORT" = '21' ]; then
            if [ "$conntrack_ftp" != 'no' ]; then
                state="-m conntrack --ctstate NEW"
            else
                port="-m multiport --dports 20,21,12000:12100"
            fi
            ftp="yes"
        fi

        # Adding firewall rule
        echo "$iptables -A INPUT $proto $port $ip $state $action" >> $tmp
    fi
done

# Switching chain policy to DROP
echo "$iptables -P INPUT DROP" >> $tmp

# Adding vesta chain
echo "$iptables -N vesta" >> $tmp

# Applying rules
bash $tmp 2>/dev/null

# Deleting temporary file
rm -f $tmp

# Checking custom trigger
if [ -x "$VESTA/data/firewall/custom.sh" ]; then
    bash $VESTA/data/firewall/custom.sh
fi

# Checking fail2ban support
if [ ! -z "$FIREWALL_EXTENSION" ]; then
    for chain in $(cat $VESTA/data/firewall/chains.conf 2>/dev/null); do
        eval $chain
        if [[ "$PORT" =~ ,|-|: ]] ; then
            port="-m multiport --dports $PORT"
        else
            port="--dport $PORT"
        fi
        echo "$iptables -N fail2ban-$CHAIN" >> $tmp
        echo "$iptables -F fail2ban-$CHAIN" >> $tmp
        echo "$iptables -I fail2ban-$CHAIN -s 0.0.0.0/0 -j RETURN" >> $tmp
        echo "$iptables -I INPUT -p $PROTOCOL $port -j fail2ban-$CHAIN" >>$tmp
    done
    bash $tmp 2>/dev/null
    rm -f $tmp

    for ban in $(cat $VESTA/data/firewall/banlist.conf 2>/dev/null); do
        eval $ban
        echo -n "$iptables -I fail2ban-$CHAIN 1 -s $IP" >> $tmp
        echo " -j REJECT --reject-with icmp-port-unreachable" >> $tmp
    done
    bash $tmp 2>/dev/null
    rm -f $tmp
fi

# Saving rules to the master iptables file
if [ -d "/etc/sysconfig" ]; then
    /sbin/iptables-save > /etc/sysconfig/iptables
    if [ -z "$(ls /etc/rc3.d/S*iptables 2>/dev/null)" ]; then
        /sbin/chkconfig iptables on
    fi
else
    /sbin/iptables-save > /etc/iptables.rules
    preup="/etc/network/if-pre-up.d/iptables"
    if [ ! -e "$preup" ]; then
        echo '#!/bin/sh' > $preup
        echo "/sbin/iptables-restore < /etc/iptables.rules" >> $preup
        echo "exit 0" >> $preup
        chmod +x $preup
    fi
fi

# Worarkound for OpenVZ
if [ -e "/proc/vz/veinfo" ]; then
    dig @8.8.8.8 google.com +time=1 +tries=1 >/dev/null 2>&1
    if [ "$?" -ne 0 ]; then
        $BIN/v-stop-firewall
    fi
fi


#----------------------------------------------------------#
#                       Vesta                              #
#----------------------------------------------------------#

exit
