#!/bin/bash # info: update system firewall rules # options: NEED_IPT_SWITCH # if first parameter set and it's value is iptables # for rpm system, then need to activate iptables # # example: v-update-firewall # # This function updates iptables rules #----------------------------------------------------------# # Variables & Functions # #----------------------------------------------------------# need_ipt_switch="$1" # Defining absolute path for iptables and modprobe iptables="/sbin/iptables" modprobe="/sbin/modprobe" sysctl="/sbin/sysctl" # Includes source /etc/profile.d/hestia.sh # shellcheck source=/etc/hestiacp/hestia.conf source /etc/hestiacp/hestia.conf # shellcheck source=/usr/local/hestia/func/main.sh source $HESTIA/func/main.sh # shellcheck source=/usr/local/hestia/func/firewall.sh source $HESTIA/func/firewall.sh # load config file source_conf "$HESTIA/conf/hestia.conf" #----------------------------------------------------------# # Verifications # #----------------------------------------------------------# is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' #----------------------------------------------------------# # Action # #----------------------------------------------------------# if [ -f /etc/redhat-release ] && [ "$need_ipt_switch" = "iptables" ]; then # Revert from nftables to iptables only first time systemctl stop firewalld systemctl disable firewalld dnf erase nftables -y dnf install iptables-legacy iptables-legacy-libs iptables-services iptables-utils ipset -y systemctl enable iptables --now fi # Self heal iptables links heal_iptables_links # Checking local IPv4 rules rules="$HESTIA/data/firewall/rules.conf" if [ ! -e "$rules" ]; then exit fi # Checking conntrack module avaiabilty $modprobe nf_conntrack > /dev/null 2>&1 if [ $? -ne 0 ]; then $sysctl net.netfilter.nf_conntrack_max > /dev/null 2>&1 if [ $? -ne 0 ]; then conntrack='no' fi fi $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 # Load ipset lists before adding Hestia iptables rules $BIN/v-update-firewall-ipset load # 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' ] || grep --quiet container=lxc /proc/1/environ; then str="$iptables -A INPUT -m state" str="$str --state ESTABLISHED,RELATED -j ACCEPT" echo "$str" >> $tmp fi ips="$(ls $HESTIA/data/ips)" # Handling local traffic for ip in $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 parse_object_kv_list "$line" if [ "$SUSPENDED" = 'no' ]; then proto="-p $PROTOCOL" port="--dport $PORT" state="" action="-j $ACTION" if [[ "$IP" =~ ^ipset: ]]; then ipset_name="${IP#ipset:}" $(v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null) || log_event $E_NOTEXIST "IPset IP list ($ipset_name) not found" ip="-m set --match-set '${ipset_name}' src" else ip="-s $IP" fi # 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 hestia chain echo "$iptables -N hestia" >> $tmp # Applying rules bash $tmp 2> /dev/null # Deleting temporary file rm -f $tmp # Checking custom trigger if [ -x "$HESTIA/data/firewall/custom.sh" ]; then bash $HESTIA/data/firewall/custom.sh fi # Checking fail2ban support if [ -n "$FIREWALL_EXTENSION" ]; then for chain in $(cat $HESTIA/data/firewall/chains.conf 2> /dev/null); do parse_object_kv_list "$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 $HESTIA/data/firewall/banlist.conf 2> /dev/null); do parse_object_kv_list "$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 # Clean up and saving rules to the master iptables file if [ -d "/etc/sysconfig" ]; then /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/sysconfig/iptables else /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/iptables.rules iptablesversion="$(iptables --version | head -1 | awk '{print $2}' | cut -f -2 -d .)" sd_unit="/lib/systemd/system/hestia-iptables.service" if [ ! -e "$sd_unit" ]; then echo "[Unit]" >> $sd_unit echo "Description=Loading Hestia firewall rules" >> $sd_unit echo "DefaultDependencies=no" >> $sd_unit echo "Wants=network-pre.target local-fs.target" >> $sd_unit echo "Before=network-pre.target" >> $sd_unit echo "After=local-fs.target" >> $sd_unit echo "" >> $sd_unit echo "[Service]" >> $sd_unit echo "Type=oneshot" >> $sd_unit echo "RemainAfterExit=yes" >> $sd_unit echo "ExecStartPre=-${HESTIA}/bin/v-update-firewall-ipset load" >> $sd_unit if [ "$iptablesversion" = "v1.6" ]; then echo "ExecStart=/sbin/iptables-restore /etc/iptables.rules" >> $sd_unit else echo "ExecStart=/sbin/iptables-restore --wait=10 /etc/iptables.rules" >> $sd_unit fi echo "" >> $sd_unit echo "[Install]" >> $sd_unit echo "WantedBy=multi-user.target" >> $sd_unit systemctl -q daemon-reload fi systemctl -q is-enabled hestia-iptables 2> /dev/null || systemctl -q enable hestia-iptables fi #----------------------------------------------------------# # Hestia # #----------------------------------------------------------# exit