#
# Authors: Marc Heuse,
#          Volker Kuhlmann <kuhlmav@elec.canterbury.ac.nz>
#
# /etc/sysconfig/scripts/SuSEfirewall2-custom
#
# ------------------------------------------------------------------------
#
# This is file is for SuSEfirewall2 and is an example for using
# the hooks which are supplied to load customized iptables rules.
#
# THERE IS NO HELP FOR USING HOOKS EXCEPT THIS FILE ! SO READ CAREFULLY !
# IT IS USEFUL TO CROSS-READ /sbin/SuSEfirewall2 TO SEE HOW HOOKS WORK !
#
# ------------------------------------------------------------------------
#
# Note: always use iptables resp ip6tables without path. You are not actually
# calling the binary here. SuSEfirewall2 internally defines an alias to
# collect all rules and apply them in batch later. Set
# FW_USE_IPTABLES_BATCH="no" if you need the rules to be applied
# immediately.

fw_custom_after_chain_creation() {
    # these rules will be loaded after the various input_* and forward_* chains
    # are created.
    # You can use this hook to allow/deny certain IP protocols or TCP/UDP
    # ports before the SuSEfirewall2 generated rules are hit.

#example: always filter backorifice/netbus trojan connect requests and log them.
#for target in LOG DROP; do
#    for chain in input_ext input_dmz input_int forward_int forward_ext forward_dmz; do
#        iptables -A $chain -j $target -p tcp --dport 31337
#        iptables -A $chain -j $target -p udp --dport 31337
#        iptables -A $chain -j $target -p tcp --dport 12345:12346
#        iptables -A $chain -j $target -p udp --dport 12345:12346
#    done
#done
    #BEGIN SETUP_SNAT CATEGORIZE
    iptables -A INPUT   -j input_int    -s 10.250/16
    iptables -A FORWARD -j forward_int  -s 10.250/16

    #END   SETUP_SNAT CATEGORIZE

    true
}

# Fail2Ban settings
# Special protection for ssh port
SSHPORT=22
# Log rate limit
LOGLIM=6/min
# Attack detection for SSHPORT ASHIT1 in ASSEC1 (long term) or ASHIT2 in ASSEC2 (short term)
ASSEC1=300
ASHIT1=60
ASSEC2=42
ASHIT2=16
# Attack detection for general prot AGHIT1 in AGSEC1 (long term) or AGHIT2 in AGSEC2 (short term)
AGSEC1=600
AGHIT1=200
AGSEC2=60
AGHIT2=60
# Ban after attack detection for this man seconds (SSH/General)
SBAN=2700
GBAN=1800

ENABLEF2B="false"
fw_fail2ban() {
    if test "$ENABLEF2B" != "true"; then return; fi

    # This rulechain will be executed if a DoS attack has been detected
    iptables -N ATTACKED 
    iptables -F ATTACKED 
    iptables -A ATTACKED -m limit --limit $LOGLIM -j LOG --log-prefix "ATTACKED: " --log-level 7
    iptables -A ATTACKED -p tcp --dport $SSHPORT -m recent --set --name BANNED_SSH --rsource -j DROP
    iptables -A ATTACKED -m recent --set --name BANNED --rsource -j DROP
    # Packet is dropped by now ...
    
    # This chain will add the packets to lists for checking attack patterns
    iptables -N ATTK_CHECK
    iptables -F ATTK_CHECK
    # Add to ATTK_CK_SSH list
    iptables -A ATTK_CHECK -p tcp --dport $SSHPORT -m recent --set --name ATTK_CK_SSH --rsource
    # If we have enough hits in the list in the last period, determine that this is an attack ...
    iptables -A ATTK_CHECK -p tcp --dport $SSHPORT -m recent --update --seconds $ASSEC1 --hitcount $ASHIT1 --name ATTK_CK_SSH --rsource --rttl -j ATTACKED
    iptables -A ATTK_CHECK -p tcp --dport $SSHPORT -m recent --update --seconds $ASSEC2 --hitcount $ASHIT2 --name ATTK_CK_SSH --rsource --rttl -j ATTACKED
    # TODO: We could purge the host from the ATTK_CK_SSH list IF it successfully authenticated ...
    # ... but this is hard to tell from iptables ... 
    # And if we have not been identified as ssh attacker, add to ATTK_CK list
    iptables -A ATTK_CHECK -m recent --set --name ATTK_CK --rsource
    iptables -A ATTK_CHECK -m recent --update --seconds $AGSEC1 --hitcount $AGHIT1 --name ATTK_CK --rsource --rttl -j ATTACKED
    iptables -A ATTK_CHECK -m recent --update --seconds $AGSEC2 --hitcount $AGHIT2 --name ATTK_CK --rsource --rttl -j ATTACKED
    # Just return if no match ...
    # TODO: We could do --reap if we wanted to help the kernel's housekeeping ...
    
    # Hook into input chain, ESTABLISHED and RELATED have bee ACCEPTed already at this point
    iptables -A input_ext -p tcp --dport $SSHPORT -m recent --update --seconds $SBAN --name BANNED_SSH --rsource --rttl -j DROP
    iptables -A input_ext -m recent --update --seconds $GBAN --name BANNED --rsource --rttl -j DROP
    iptables -A input_ext -j ATTK_CHECK

    # This would be a simpler DoS protection using the hashlimit extension
    #iptables -A input_ext -j DROP -p tcp --dport $SSHPORT -m hashlimit --hashlimit-above 6/min --hashlimit-burst 8 --hashlimit-mode srcip --hashlimit-name DOS_SSH
    #iptables -A input_ext -j DROP -m hashlimit --hashlimit-above 20/min --hashlimit-burst 30 --hashlimit-mode srcip --hashlimit-name DOS
    
}

fw_custom_before_port_handling() { 
    # these rules will be loaded after the anti-spoofing and icmp handling
    # and after the input has been redirected to the input_XXX and 
    # forward_XXX chains and some basic chain-specific anti-circumvention
    # rules have been set,
    # but before any IP protocol or TCP/UDP port allow/protection rules
    # will be set.
    # You can use this hook to allow/deny certain IP protocols or TCP/UDP
    # ports before the SuSEfirewall2 generated rules are hit.
    fw_fail2ban

    true
}

fw_custom_before_masq() { # could also be named "after_port_handling()"
    # these rules will be loaded after the IP protocol and TCP/UDP port
    # handling, but before any IP forwarding (routing), masquerading
    # will be done.
    # NOTE: reverse masquerading is before directly after
    #       fw_custom_before_port_handling !!!!
    # You can use this hook to ... hmmm ... I'm sure you'll find a use for
    # this ...

    true
}

fw_custom_before_denyall() { # could also be named "after_forwardmasq()"
    # these are the rules to be loaded after IP forwarding and masquerading
    # but before the logging and deny all section is set by SuSEfirewall2.
    # You can use this hook to prevent the logging of annoying packets.

#example: prevent logging of talk requests from anywhere
#for chain in input_ext input_dmz input_int forward_int forward_ext forward_dmz; do
#    iptables -A $chain -j DROP -p udp --dport 517:518
#done

    # ALLOWINT # iptables -A forward_int -j ACCEPT -i eth0 -o eth0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED
    # ALLOWINT2 # iptables -A forward_ext -j ACCEPT -i eth0 -o eth0 -d INTERNALNET -m conntrack --ctstate RELATED,ESTABLISHED
    # ALLOWINT3 # iptables -A forward_dmz -j ACCEPT -i eth0 -o eth0 -d INTERNALNET -m conntrack --ctstate RELATED,ESTABLISHED
    # ALLOWDMZ # iptables -A forward_dmz -j ACCEPT -i eth0 -o eth0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED
    # ALLOWDMZ2 # iptables -A forward_ext -j ACCEPT -i eth0 -o eth0 -d DMZNET -m conntrack --ctstate RELATED,ESTABLISHED
    # ALLOWEXT # iptables -A forward_ext -j ACCEPT -i eth0 -o eth0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED
    true
}

fw_custom_after_finished() {
    # these are the rules to be loaded after the firewall is fully configured
    true
}
