#!/bin/sh
####################################################################
## Netfilters Init-Script for knot                                ##
####################################################################
## by Sebastian "blackwing" Werner (xwing@gmx.net)                ##
####################################################################

####################################################################
## Variables
####################################################################
IPTABLES="/usr/bin/iptables"

#
# ipchains setup stuff
#
START_NETFILTERS="yes"
INTERNALIF="eth1"
EXTERNALIF="ppp0"
INTERNALIP="172.16.32.100"
EXTERNALIP="0.0.0.0"
INTERNALNET="172.16.32.0/255.255.255.0"
EXTERNALNET="0.0.0.0"
PRIV_MACHINE="172.16.32.60"

. /etc/rc.config

# Determine the base and follow a runlevel link name.
base=${0##*/}
link=${base#*[SK][0-9][0-9]}

# Force execution if not called by a runlevel directory.
test $link = $base && START_IPCHAINS=yes
test "$START_NETFILTERS" = yes || exit 0

return=$rc_done

case "$1" in
  start)
    echo -n "Setting up netfilters: "
    
    ###############################################################
    ## Kernel security settings
    ###############################################################
    
    ## Activate IP-Forwarding in kernel
      echo 1 > /proc/sys/net/ipv4/ip_forward
      
    ## Activate Syncookie Support
      echo 1 > /proc/sys/net/ipv4/tcp_syncookies
      
    ## DynIP Patch
      echo 1 > /proc/sys/net/ipv4/ip_dynaddr
      
    ## Ignore Dead Error Messages
      echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
      
    ## Ignore all Broadcasts pings
      echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 
      
    ## Enable route verification
      for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
         echo 1 > $f
      done
      
    ## Deny source routed packages
      echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route 
      
    ## Disable ICMP redirect acceptance
      echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects 
      
    ## Enable bad error message protection
      echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 
      
    ## Log impossible packets
      echo 0 >/proc/sys/net/ipv4/conf/all/log_martians
      
    ## Set local port range
      echo "50000 60999" >/proc/sys/net/ipv4/ip_local_port_range

    ## Decrease tcp timeouts to prevent DoS
      echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
      echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
      echo 1 > /proc/sys/net/ipv4/tcp_window_scaling
      echo 0 > /proc/sys/net/ipv4/tcp_sack
      
      
    ###############################################################
    ## Load all the required modules
    ###############################################################
      
      modprobe iptable_filter
      modprobe iptable_mangle
      modprobe iptable_nat
      modprobe ipt_TCPMSS
      modprobe ipt_MASQUERADE
      modprobe ipt_LOG
      modprobe ipt_REJECT
      modprobe ipt_REDIRECT
      modprobe ipt_MARK
      modprobe ipt_limit
      modprobe ipt_multiport
      modprobe ipt_state
#      modprobe ipt_unclean 
      modprobe ip_conntrack
      modprobe ip_conntrack_ftp
      modprobe ip_conntrack_irc ports=6667,6668,6669
      modprobe ip_nat_ftp
      modprobe ip_nat_irc ports=6667,6668,6669
      modprobe ip_queue
      
      
    ###############################################################
    ## Reset all iptable values
    ###############################################################
    
    ## Flush all existing policies
      $IPTABLES -F
      $IPTABLES -F -t nat
      
    ## Set default policies
      $IPTABLES -P INPUT DROP
      $IPTABLES -P OUTPUT ACCEPT
      $IPTABLES -P FORWARD DROP
      
    ###############################################################
    ## Create chains
    ###############################################################
     
    ## Deny chain
      $IPTABLES -N deny 2> /dev/null
    
    ## Limit chains
      $IPTABLES -N limit1 2> /dev/null
      $IPTABLES -N limit10 2> /dev/null
      $IPTABLES -N limit50 2> /dev/null
      $IPTABLES -N limit100 2> /dev/null
      $IPTABLES -N limit1000 2> /dev/null
      
    ## filter chain for all incoming traffic (including forward)
      $IPTABLES -N all-in 2> /dev/null
      
    ## filter chain for local(to the firewall-box) incoming traffic
      $IPTABLES -N local-in 2> /dev/null
      
    ## filter chain for external input
      $IPTABLES -N ext-in 2> /dev/null
      
    ## filter chain for internal input
      $IPTABLES -N int-in 2> /dev/null
      
    ## filter chain for forward input going into lan
      $IPTABLES -N ext2int 2> /dev/null
      
    ## filter chain for forward input going into inet
      $IPTABLES -N int2ext 2> /dev/null
      
    ## final chain
      $IPTABLES -N final 2> /dev/null

      
    ###############################################################
    ## Chain routing
    ###############################################################
    
    ## All traffic from anywhere to anywhere to all-in
      $IPTABLES -A INPUT -j all-in
      $IPTABLES -A FORWARD -j all-in
      
    ## All traffic to localhost to local-in
      $IPTABLES -A INPUT -j local-in
      
    ## All traffic from INTERNAL to EXTERNALIF to int2ext
      $IPTABLES -A FORWARD ! -i ${EXTERNALIF} -j int2ext
      
    ## All traffic from EXTERNALIF to INTERNALIF to ext2int
      $IPTABLES -A FORWARD -i ${EXTERNALIF} -j ext2int
      
    ## All traffic from INTERNAL (lo + all other) to localhost to int-in
      $IPTABLES -A INPUT ! -i ${EXTERNALIF} -j int-in
      
    ## All traffic from EXTERNALIF to localhost to ext-in
      $IPTABLES -A INPUT -i ${EXTERNALIF} -j ext-in
    
    ## All traffic from anywhere to anywhere to all-in
      $IPTABLES -A INPUT -j final
      $IPTABLES -A FORWARD -j final

      
    ###############################################################
    ## Accepting specific incoming traffic
    ###############################################################
    
    ## Deny all invalid packets
      $IPTABLES -A all-in -m state --state INVALID -j deny
      $IPTABLES -A all-in -m unclean -j deny
    
    ## ALL ACCEPT: ntp
      $IPTABLES -A all-in -p udp --destination-port 123 -j limit10
      $IPTABLES -A all-in -p udp --source-port 123  -j ACCEPT  
      
    ## INT ACCEPT: NetBEUI
      $IPTABLES -A int-in -p tcp --destination-port 135:139 -j limit1000
      $IPTABLES -A int-in -p udp --destination-port 135:139 -j ACCEPT
      $IPTABLES -A int-in -p tcp --destination-port 445 -j limit10
      
    ## ALL ACCEPT: remotely anywhere
      $IPTABLES -A all-in -p tcp --destination-port 2000 -j limit10
      
    ## INT ACCEPT: mySQL
      $IPTABLES -A int-in -p tcp --destination-port 3306 -j limit1
      
    ## INT ACCEPT: eggdrop-admin
      $IPTABLES -A int-in -p tcp --destination-port 3333:3335 -j limit1
    
    ## INT ACCEPT: snmp
      $IPTABLES -A int-in -p udp --destination-port 161 -j limit1
      
    ## INT ACCEPT: opennap
      $IPTABLES -A int-in -p tcp --destination-port 8888 -j limit50

    ## INT ACCEPT: ed2k
      $IPTABLES -A int-in -p tcp --destination-port 4662:4663 -j limit50
      
    ## EXT ACCEPT: remotely anywhere
      $IPTABLES -A ext-in -p tcp --destination-port 2000 -j limit1
      
    ## ALL ACCEPT: ssh
      $IPTABLES -A all-in -p tcp --destination-port 22 -j limit100
      $IPTABLES -A all-in -p tcp --source-port 22 ! --syn -j ACCEPT
      
    ## LOCAL ACCEPT: dns
      $IPTABLES -A all-in -p tcp --destination-port 53 -j limit1000
      $IPTABLES -A all-in -p udp --destination-port 53 -j ACCEPT
      
    ## INT ACCEPT: http
      $IPTABLES -A all-in -p tcp --destination-port 80 -j limit1000
      
    ## INT ACCEPT: irc
      $IPTABLES -A int-in -p tcp --destination-port 6667 -j limit50
      
    ## INT ACCEPT: irc Server-2-Server
      $IPTABLES -A int-in -p tcp --destination-port 7000 -j limit10
      
    ## ALL ACCEPT: ftp-data & ftp-control
      $IPTABLES -A all-in -p tcp --destination-port 20:21 -j limit100
      
    ## ALL ACCEPT: identd
      $IPTABLES -A all-in -p tcp --destination-port 113 -j limit10
      $IPTABLES -A all-in -p udp --destination-port 113 -j ACCEPT
      
    ## ALL ACCEPT: dcc
      $IPTABLES -A all-in -p tcp --destination-port 1024:1030 -j limit10
      $IPTABLES -A all-in -p udp --destination-port 1024:1030 -j ACCEPT
      
      
    ###############################################################
    ## ICMP
    ###############################################################
    
    ## Allow incoming ICMP
      $IPTABLES -A all-in -p icmp --icmp-type echo-reply -j ACCEPT
      $IPTABLES -A all-in -p icmp --icmp-type host-unreachable -j ACCEPT
      $IPTABLES -A all-in -p icmp --icmp-type port-unreachable -j ACCEPT
      $IPTABLES -A all-in -p icmp --icmp-type host-prohibited -j ACCEPT
    
    ## Allow forward ICMP
      $IPTABLES -A int2ext -p icmp -j ACCEPT
      
      
    ###############################################################
    ## Flood Protection
    ###############################################################
      
    ## Deny Portscan, only accept 100 tcp control packets per second
      $IPTABLES -A ext2int -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1000/s -j ACCEPT
      
    ## Deny Ping of Death, only accept 10 pings per second
      $IPTABLES -A all-in -p icmp --icmp-type echo-request -m limit --limit 10/s -j ACCEPT
      
      
    ###############################################################
    ## NAT stuff
    ###############################################################
    
    ## Masq externalif
      $IPTABLES -A POSTROUTING -o ${EXTERNALIF} -t nat -j MASQUERADE
      
      
    ###############################################################
    ## State filtering
    ###############################################################

    ## Deny all invalid packets
      $IPTABLES -A all-in -m state --state INVALID -j deny
      
    ## Deny NEW packets from external if
      $IPTABLES -A ext-in -m state --state NEW -j deny
      $IPTABLES -A ext2int -m state --state NEW -j deny
    
    ## Protect Localhost from internalnet
      $IPTABLES -A int-in -m state --state NEW -j deny
      
      
    ###############################################################
    ## Routing stuff
    ###############################################################
    
    ## ftp
      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 21 -j DNAT --to 172.16.32.200:21
    ## www
      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 80 -j DNAT --to 172.16.32.200:80
      
    ## Battlecom
#      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 2300:2400 -j DNAT --to ${PRIV_MACHINE}
#      $IPTABLES -A PREROUTING -t nat -p udp -i ${EXTERNALIF} --destination-port 2300:2400 -j DNAT --to ${PRIV_MACHINE}
#      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 47624 -j DNAT --to ${PRIV_MACHINE}
#      $IPTABLES -A PREROUTING -t nat -p udp -i ${EXTERNALIF} --destination-port 47624 -j DNAT --to ${PRIV_MACHINE}
#      $IPTABLES -A PREROUTING -t nat -p udp -i ${EXTERNALIF} --destination-port 28800:28900 -j DNAT --to ${PRIV_MACHINE}
      
    ## identd
#      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 113 -j DNAT --to ${PRIV_MACHINE}:113
      
    ## remotely anywhere
      $IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 2000 -j DNAT --to ${PRIV_MACHINE}:2000
      
    ## TRANSPARENT PROXY
#      #$IPTABLES -A PREROUTING -t nat -p tcp -i ${INTERNALIF} --destination-port 80 -j REDIRECT --to-port 3128
      
    ## LOAD BALANCER
#      #$IPTABLES -A PREROUTING -t nat -p tcp -i ${EXTERNALIF} --destination-port 80 -j DNAT --to 192.168.99.1-192.168.99.3
    
    ## Keep irc:7000 for servers only -> Redirect traffic to 6667
#      $IPTABLES -A PREROUTING -t nat -p tcp ! -s 192.168.99.60 --dport 7000 -j REDIRECT --to-port 6667
      
    ###############################################################
    ## TOS BITS
    ###############################################################
    
      $IPTABLES -A PREROUTING -t mangle -p tcp --sport telnet -j TOS --set-tos Minimize-Delay
      $IPTABLES -A PREROUTING -t mangle -p tcp --sport ftp -j TOS --set-tos Minimize-Delay
      $IPTABLES -A PREROUTING -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
      
      
    ###############################################################
    ## UnprivatePort Policies
    ###############################################################
    
    ## Accept unprivate Traffic from everywhere
      $IPTABLES -A final -p tcp --destination-port 1023:65535 -m state ! --state NEW -j ACCEPT
      $IPTABLES -A final -p udp --destination-port 1023:65535 -m state ! --state NEW -j ACCEPT
      $IPTABLES -A final -j deny
      
      
    ###############################################################
    ## Default policies
    ###############################################################
    
    ## Finally accept all traffic coming from the localnet, going to internet
      $IPTABLES -A int2ext -j ACCEPT
      
      
    ###############################################################
    ## The deny chain
    ###############################################################
    
    ## send all denied tcp packages a tcp reset
      $IPTABLES -A deny -p tcp -j REJECT --reject-with tcp-reset
      
    ## all other connections get a host unreachable :P
      $IPTABLES -A deny -p udp -j REJECT --reject-with icmp-port-closed
      $IPTABLES -A deny -j DROP
      
      
    ###############################################################
    ## The limit chains (synfloodprotection)
    ###############################################################
    
    ## Deny Synflood, only accept 1 new connection per second
      $IPTABLES -A limit1 -p tcp --syn -m limit --limit 1/s -j ACCEPT
      $IPTABLES -A limit1 -p tcp ! --syn -j ACCEPT
      
    ## Deny Synflood, only accept 10 new connection per second
      $IPTABLES -A limit10 -p tcp --syn -m limit --limit 10/s -j ACCEPT
      $IPTABLES -A limit10 -p tcp ! --syn -j ACCEPT
      
    ## Deny Synflood, only accept 50 new connection per second
      $IPTABLES -A limit50 -p tcp --syn -m limit --limit 50/s -j ACCEPT
      $IPTABLES -A limit50 -p tcp ! --syn -j ACCEPT
      
    ## Deny Synflood, only accept 100 new connection per second
      $IPTABLES -A limit100 -p tcp --syn -m limit --limit 100/s -j ACCEPT
      $IPTABLES -A limit100 -p tcp ! --syn -j ACCEPT
      
    ## Deny Synflood, only accept 1000 new connection per second
      $IPTABLES -A limit1000 -p tcp --syn -m limit --limit 1000/s -j ACCEPT
      $IPTABLES -A limit1000 -p tcp ! --syn -j ACCEPT
    
    echo -e "$return"
  ;;
  stop)
    echo -n "Shutting down netfilters: "

    ## Delete all the rules already set
      $IPTABLES -F
    
    ## Set the default policies
      $IPTABLES -P INPUT ACCEPT
      $IPTABLES -P OUTPUT ACCEPT
      $IPTABLES -P FORWARD DROP
     
    ## Disabling the IP-Forward-Kernel-Feature
      echo 0 > /proc/sys/net/ipv4/ip_forward
 
    echo -e "$return"
  ;;

  *)
    echo ""
    echo "Usage: $0 {start|stop}"
    exit 1
    ;;  
esac

# Inform the caller not only verbosely and set an exit status.
test "$return" = "$rc_done" || exit 1

exit 0





