#!/bin/sh #################################################################### ## Netfilters Init-Script for Linux SOHO-Routers #################################################################### ## by Sebastian "blackwing" Werner (xwing@gmx.net) #################################################################### ## Current Version ## $Id: advanched.router.OLD.txt,v 1.2 2003/12/22 21:16:49 blackwing Exp $ #################################################################### ## ChangeLog ## $Log: advanched.router.OLD.txt,v $ ## Revision 1.2 2003/12/22 21:16:49 blackwing ## added rcs-tags. ## sw, 22/12/2003 ## #################################################################### ## Features: ## - Traffic classification by incming & outgoing inteferfaces ## - NAT support ## - Traffic forwarding to DMZ ## - Stateful filtering ## - Traffic shaping for lowering pings while downloading stuff ## - IPv6 filters in same style (with Tunneling setup support!) ## - ## ## Requires: ## - Kernel with netfilters (iptables support) i.e. 2.4.18 ## ## Optional: ## - IPv6 support (Kernel, programs, ip6tables) ## - Traffic shaping (QoS) support (Kernel, TC) ## ## This script is released under the terms of the ## GNU General Public License ## ## If you have suggestions, please contact me! #################################################################### ## Variables #################################################################### ## Use IPv6 options? WITH_IPv6="no" ## Use Traffic shaper for UPLOAD? WITH_UPSHAPE="yes" ## Use Traffic shaper for DOWNLOAD? WITH_DOWNSHAPE="no" ## Where is your IPTables binary? IPTABLES="/sbin/iptables" ## Where is your IP6Tables binary? IP6TABLES="/sbin/ip6tables" ## Where is your Traffic shaper binary? TC="/usr/sbin/tc" ## Where is your ip setup binary? IP="/usr/sbin/ip" ## Which Interface is connected to the TRUSTED Net? IF_INT="eth1" ## Which Interface is holding the Internetconnection? IF_EXT="ppp0" ## Download and Upload rate in Kilobits/sec RATE_EXT_UP="128" RATE_EXT_DOWN="768" ## Which Interface is connected to the DMZ? (if none: leave blank) IF_DMZ="eth2" ## Which interface is holding a the 6over4 Tunnel? # If tunnel is empty AND IPv6 is enabled, IF_EXT is used! IF_TUNNEL="sit1" #################################################################### ## Present Status if requested #################################################################### if [ "$1" = "status" ] then echo -e "\033[1mCurrent netfilter status (IPv4)\033[m" echo -e "\033[31m[iptables] GENERAL CHAINS\033[m" $IPTABLES -L all-in -v -n -x 2> /dev/null $IPTABLES -L int-in -v -n -x 2> /dev/null $IPTABLES -L ext-in -v -n -x 2> /dev/null $IPTABLES -L final -v -n -x 2> /dev/null echo -e "\033[31m[iptables] ROUTING CHAINS\033[m" $IPTABLES -L int2ext -v -n -x 2> /dev/null $IPTABLES -L ext2int -v -n -x 2> /dev/null $IPTABLES -L int2dmz -v -n -x 2> /dev/null $IPTABLES -L dmz2int -v -n -x 2> /dev/null $IPTABLES -L ext2dmz -v -n -x 2> /dev/null $IPTABLES -L dmz2ext -v -n -x 2> /dev/null echo -e "\033[31m[iptables] PRE- / POSTROUNTING CHAINS\033[m" $IPTABLES -t nat -L PREROUTING -v -n -x 2> /dev/null $IPTABLES -t nat -L POSTROUTING -v -n -x 2> /dev/null if [ "$WITH_UPSHAPE" = yes ] then echo -e "\033[31m[iptables] MANGLING CHAINS\033[m" $IPTABLES -t mangle -L outgoing -v -n -x 2> /dev/null $IPTABLES -t mangle -L incoming -v -n -x 2> /dev/null echo -e "\033[31m[tc] qdisc\033[m" $TC -s qdisc show dev $IF_EXT if [ "$WITH_DOWNSHAPE" = yes ] then $TC -s qdisc show dev imq0 fi echo -e "\033[31m[tc] class\033[m" $TC -s class show dev $IF_EXT if [ "$WITH_DOWNSHAPE" = yes ] then $TC -s class show dev imq0 fi echo -e "\033[31m[tc] filter\033[m" $TC -s filter show dev $IF_EXT if [ "$WITH_DOWNSHAPE" = yes ] then $TC -s filter show dev imq0 fi fi if [ $WITH_IPv6 = yes ] then echo -e "\033[1mCurrent netfilter status (IPv6)\033[m" echo -e "\033[31m[ip6tables] GENERAL CHAINS\033[m" $IP6TABLES -L all-in -v -n -x 2> /dev/null $IP6TABLES -L int-in -v -n -x 2> /dev/null $IP6TABLES -L ext-in -v -n -x 2> /dev/null $IP6TABLES -L final -v -n -x 2> /dev/null echo -e "\033[31m[ip6tables] ROUTING CHAINS\033[m" $IP6TABLES -L int2ext -v -n -x 2> /dev/null $IP6TABLES -L ext2int -v -n -x 2> /dev/null $IP6TABLES -L int2dmz -v -n -x 2> /dev/null $IP6TABLES -L dmz2int -v -n -x 2> /dev/null $IP6TABLES -L ext2dmz -v -n -x 2> /dev/null $IP6TABLES -L dmz2ext -v -n -x 2> /dev/null fi exit 0 fi #################################################################### ## Reset everything to the basics #################################################################### ## Delete all the rules already set $IPTABLES -F test $WITH_IPv6 = yes && $IP6TABLES -F $IPTABLES -F -t mangle test $WITH_IPv6 = yes && $IP6TABLES -t mangle -F $IPTABLES -F -t nat ## Set the default policies $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD DROP ## Clean up custom chains $IPTABLES -t mangle -F outgoing 2> /dev/null > /dev/null $IPTABLES -t mangle -X outgoing 2> /dev/null > /dev/null $IPTABLES -t mangle -F incoming 2> /dev/null > /dev/null $IPTABLES -t mangle -X incoming 2> /dev/null > /dev/null $IPTABLES -F all-in 2> /dev/null > /dev/null $IPTABLES -X all-in 2> /dev/null > /dev/null $IPTABLES -F int-in 2> /dev/null > /dev/null $IPTABLES -X int-in 2> /dev/null > /dev/null $IPTABLES -F ext-in 2> /dev/null > /dev/null $IPTABLES -X ext-in 2> /dev/null > /dev/null $IPTABLES -F ext2int 2> /dev/null > /dev/null $IPTABLES -X ext2int 2> /dev/null > /dev/null $IPTABLES -F int2ext 2> /dev/null > /dev/null $IPTABLES -X int2ext 2> /dev/null > /dev/null $IPTABLES -F ext2dmz 2> /dev/null > /dev/null $IPTABLES -X ext2dmz 2> /dev/null > /dev/null $IPTABLES -F dmz2ext 2> /dev/null > /dev/null $IPTABLES -X dmz2ext 2> /dev/null > /dev/null $IPTABLES -F int2dmz 2> /dev/null > /dev/null $IPTABLES -X int2dmz 2> /dev/null > /dev/null $IPTABLES -F dmz2int 2> /dev/null > /dev/null $IPTABLES -X dmz2int 2> /dev/null > /dev/null $IPTABLES -F final 2> /dev/null > /dev/null $IPTABLES -X final 2> /dev/null > /dev/null $IPTABLES -F limit10 2> /dev/null > /dev/null $IPTABLES -X limit10 2> /dev/null > /dev/null $IPTABLES -F limit100 2> /dev/null > /dev/null $IPTABLES -X limit100 2> /dev/null > /dev/null $IPTABLES -F limit1000 2> /dev/null > /dev/null $IPTABLES -X limit1000 2> /dev/null > /dev/null $IPTABLES -F deny 2> /dev/null > /dev/null $IPTABLES -X deny 2> /dev/null > /dev/null $TC qdisc del dev $IF_EXT root 2> /dev/null > /dev/null $TC qdisc del dev imq0 root 2> /dev/null > /dev/null $IP link set imq0 down 2> /dev/null > /dev/null #################################################################### ## Stop the netfilter functionality #################################################################### if [ "$1" = "stop" ] then echo -n "Shutting down netfilters: " echo 0 > /proc/sys/net/ipv4/ip_forward test $WITH_IPv6 = yes && echo 0 > /proc/sys/net/ipv6/conf/all/forward echo -e "\033[75G\033[32m[1mdone\033[m\017" exit fi #################################################################### ## Start or Restart the script #################################################################### echo -n "Setting up netfilters: " ############################################################### ## Kernel security settings ############################################################### ## Activate IP-Forwarding in kernel echo 1 > /proc/sys/net/ipv4/ip_forward test $WITH_IPv6 = yes && echo 1 > /proc/sys/net/ipv6/conf/all/forwarding ## 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 ## Don NOT 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 advanced modules ############################################################### modprobe ip_conntrack_ftp ports=21,21212 modprobe ip_nat_ftp modprobe ip_conntrack_irc ports=6667,6668,6669 modprobe ip_nat_irc ports=6667,6668,6669 ############################################################### ## Create chains and Route traffic into it ############################################################### ## filter chain for all incoming traffic (including forward) $IPTABLES -N all-in 2> /dev/null $IPTABLES -A INPUT -j all-in $IPTABLES -A FORWARD -j all-in if [ $WITH_IPv6 = yes ] then $IP6TABLES -N all-in 2> /dev/null $IP6TABLES -A INPUT -j all-in $IP6TABLES -A FORWARD -j all-in fi ## filter chain for local(to the firewall-box) incoming traffic $IPTABLES -N local-in 2> /dev/null $IPTABLES -A INPUT -j local-in if [ $WITH_IPv6 = yes ] then $IP6TABLES -N local-in 2> /dev/null $IP6TABLES -A INPUT -j local-in fi ## filter chain for external input (to router, not NET_INT!!!) $IPTABLES -N ext-in 2> /dev/null $IPTABLES -A INPUT -i $IF_EXT -j ext-in if [ $WITH_IPv6 = yes ] then $IP6TABLES -N ext-in 2> /dev/null if [ "$IF_TUNNEL" = "" ] then $IP6TABLES -A INPUT -i $IF_EXT -j ext-in else $IP6TABLES -A INPUT -i $IF_TUNNEL -j ext-in fi fi ## filter chain for internal input $IPTABLES -N int-in 2> /dev/null $IPTABLES -A INPUT -i $IF_INT -j int-in $IPTABLES -A INPUT -i lo -j int-in if [ $WITH_IPv6 = yes ] then $IP6TABLES -N int-in 2> /dev/null $IP6TABLES -A INPUT -i $IF_INT -j int-in $IP6TABLES -A INPUT -i lo -j int-in fi ## filter chain for EXTERNAL to INTERNAL $IPTABLES -N ext2int 2> /dev/null $IPTABLES -A FORWARD -i $IF_EXT -o $IF_INT -j ext2int if [ $WITH_IPv6 = yes ] then $IP6TABLES -N ext2int 2> /dev/null if [ "$IF_TUNNEL" = "" ] then $IP6TABLES -A FORWARD -i $IF_EXT -o $IF_INT -j ext2int else $IP6TABLES -A FORWARD -i $IF_TUNNEL -o $IF_INT -j ext2int fi fi ## filter chain for INTERNAL to EXTERNAL $IPTABLES -N int2ext 2> /dev/null $IPTABLES -A FORWARD -i $IF_INT -o $IF_EXT -j int2ext if [ $WITH_IPv6 = yes ] then $IP6TABLES -N int2ext 2> /dev/null if [ "$IF_TUNNEL" = "" ] then $IP6TABLES -A FORWARD -i $IF_INT -o $IF_EXT -j int2ext else $IP6TABLES -A FORWARD -i $IF_INT -o $IF_TUNNEL -j int2ext fi fi # Now create stuff, if IF_DMZ is set if [ ! -z $IF_DMZ ] then ## filter chain for EXTERNAL to DMZ $IPTABLES -N ext2dmz 2> /dev/null $IPTABLES -A FORWARD -i $IF_EXT -o $IF_DMZ -j ext2dmz if [ $WITH_IPv6 = yes ] then $IP6TABLES -N ext2dmz 2> /dev/null if [ "$IF_TUNNEL" = "" ] then $IP6TABLES -A FORWARD -i $IF_EXT -o $IF_DMZ -j ext2dmz else $IP6TABLES -A FORWARD -i $IF_TUNNEL -o $IF_DMZ -j ext2dmz fi fi ## filter chain for DMZ to EXTERNAL $IPTABLES -N dmz2ext 2> /dev/null $IPTABLES -A FORWARD -i $IF_DMZ -o $IF_EXT -j dmz2ext if [ $WITH_IPv6 = yes ] then $IP6TABLES -N dmz2ext 2> /dev/null if [ "$IF_TUNNEL" = "" ] then $IP6TABLES -A FORWARD -i $IF_DMZ -o $IF_EXT -j dmz2ext else $IP6TABLES -A FORWARD -i $IF_DMZ -o $IF_TUNNEL -j dmz2ext fi fi ## filter chain for INTERNAL to DMZ $IPTABLES -N int2dmz 2> /dev/null $IPTABLES -A FORWARD -i $IF_INT -o $IF_DMZ -j int2dmz if [ $WITH_IPv6 = yes ] then $IP6TABLES -N int2dmz 2> /dev/null $IP6TABLES -A FORWARD -i $IF_INT -o $IF_DMZ -j int2dmz fi ## filter chain for DMZ to INTERNAL $IPTABLES -N dmz2int 2> /dev/null $IPTABLES -A FORWARD -i $IF_DMZ -o $IF_INT -j dmz2int if [ $WITH_IPv6 = yes ] then $IP6TABLES -N dmz2int 2> /dev/null $IP6TABLES -A FORWARD -i $IF_DMZ -o $IF_INT -j dmz2int fi fi ## Shaper chains (currently no v6 shaping support! TO BE DONE!) if [ "$WITH_UPSHAPE" = yes ] then $IPTABLES -t mangle -N outgoing 2> /dev/null $IPTABLES -t mangle -I POSTROUTING -o $IF_EXT -j outgoing $IPTABLES -t mangle -N incoming 2> /dev/null $IPTABLES -t mangle -I PREROUTING -i $IF_EXT -j incoming fi ## accept all loop traffic $IPTABLES -A INPUT -i lo -j ACCEPT if [ $WITH_IPv6 = yes ] then $IP6TABLES -A INPUT -i lo -j ACCEPT fi ## final chain $IPTABLES -N final 2> /dev/null $IPTABLES -A INPUT -j final $IPTABLES -A FORWARD -j final if [ $WITH_IPv6 = yes ] then $IP6TABLES -N final 2> /dev/null $IP6TABLES -A INPUT -j final $IP6TABLES -A FORWARD -j final fi ## Deny chain (helper) $IPTABLES -N deny 2> /dev/null test $WITH_IPv6 = yes && $IP6TABLES -N deny 2> /dev/null ## Limit chains (helper) $IPTABLES -N limit10 2> /dev/null test $WITH_IPv6 = yes && $IP6TABLES -N limit10 2> /dev/null $IPTABLES -N limit100 2> /dev/null test $WITH_IPv6 = yes && $IP6TABLES -N limit100 2> /dev/null $IPTABLES -N limit1000 2> /dev/null test $WITH_IPv6 = yes && $IP6TABLES -N limit1000 2> /dev/null ############################################################### ## Accepting specific incoming traffic ############################################################### ## ALL ACCEPT: ipv6 over ipv4 tunnel $IPTABLES -A ext-in -p 41 -j ACCEPT ## ALL ACCEPT: ftp-data & ftp-control $IPTABLES -A all-in -p tcp --destination-port 21212 -j limit100 $IPTABLES -A all-in -p tcp --destination-port 20 -j limit100 ## 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 ## ALL ACCEPT: dns $IPTABLES -A all-in -p tcp --destination-port 53 -j limit100 $IPTABLES -A all-in -p udp --destination-port 53 -j limit100 ## ALL ACCEPT: http $IPTABLES -A all-in -p tcp --destination-port 80 -j limit100 ## ALL ACCEPT: irssi-proxy $IPTABLES -A all-in -p tcp --destination-port 6890 -j limit100 ## ALL ACCEPT: edonkey / mldonkey $IPTABLES -A all-in -p tcp --destination-port 4662 -j limit10 $IPTABLES -A all-in -p udp --destination-port 4672 -j limit10 $IPTABLES -A all-in -p tcp --destination-port 4440:4442 -j limit10 ## ALL ACCEPT: jabber $IPTABLES -A all-in -p tcp --destination-port 5222 -j limit10 $IPTABLES -A all-in -p udp --destination-port 5222 -j limit10 ## ALL ACCEPT: identd $IPTABLES -A all-in -p tcp --destination-port 113 -j limit10 $IPTABLES -A all-in -p udp --destination-port 113 -j limit10 ## ALL ACCEPT: ntp $IPTABLES -A all-in -p udp --destination-port 123 -j limit10 $IPTABLES -A all-in -p udp --source-port 123 -j limit10 ## 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 limit100 $IPTABLES -A int-in -p tcp --destination-port 445 -j limit10 ## EXT to INT ACCEPT: dcc $IPTABLES -A ext2int -p tcp --destination-port 1024:1030 -j limit10 $IPTABLES -A ext2int -p udp --destination-port 1024:1030 -j limit10 ## TEMPLATE # use one of the classifying chains and set ports # $IPTABLES -A MY_CHAIN -p TCP_UDP --destination-port THE_PORTS -j limit100 ############################################################### ## Routing stuff (IPv6 will make this junk obsolete hopefully) ############################################################### ## Masq externalif $IPTABLES -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE ## forward external ftp to an DMZ HOST # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 21 -j DNAT --to 192.168.99.200:21 # $IPTABLES -t nat -A ext2dmz -p tcp -i $IF_EXT --destination-port 20:21 -j ACCEPT ## forward 50 ports to an dmz host for incoming icq special events # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 2500:2600 -j DNAT --to 172.16.32.62 # $IPTABLES -A ext2int -p tcp -i $IF_EXT --destination-port 2500:2600 -j ACCEPT ## www # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 80 -j DNAT --to 192.168.99.200:80 # $IPTABLES -A ext2dmz -p tcp -i $IF_EXT --destination-port 80 -j ACCEPT ## Battlecom (forward battlecom to an internal host) # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 2300:2400 -j DNAT --to 172.16.32.61 # $IPTABLES -t nat -A PREROUTING -p udp -i $IF_EXT --destination-port 2300:2400 -j DNAT --to 172.16.32.61 # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 47624 -j DNAT --to 172.16.32.61 # $IPTABLES -t nat -A PREROUTING -p udp -i $IF_EXT --destination-port 47624 -j DNAT --to 172.16.32.61 # $IPTABLES -t nat -A PREROUTING -p udp -i $IF_EXT --destination-port 28800:28900 -j DNAT --to 172.16.32.61 ## TRANSPARENT PROXY (force internal surfers to be routed through a proxy) # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_INT --destination-port 80 -j REDIRECT --to-port 3128 # $IPTABLES -A local-in -p tcp -i $IF_INT --destination-port 3128 -j ACCEPT ## LOAD BALANCER (balance EXTERNAL port 80 traffic to three servers in DMZ # $IPTABLES -t nat -A PREROUTING -p tcp -i $IF_EXT --destination-port 80 -j DNAT --to 192.168.99.1-192.168.99.3 # $IPTABLES -A ext2dmz -p tcp -i $IF_EXT --destination-port 80 -j ACCEPT ############################################################### ## Traffic Shaping (uuuuh complex!) ############################################################### if [ "$WITH_UPSHAPE" = yes ] then ## Add a queue to the external interface of about 2 seconds for low prio traffic $IP link set dev $IF_EXT qlen 30 ## Add the root HTB interface $TC qdisc add dev $IF_EXT root handle 1: htb default 22 ## Add the main rate limit classes $TC class add dev $IF_EXT parent 1: classid 1:1 htb rate $[$RATE_EXT_UP]kbit ## Add leaf classes # We grant each class at LEAST it's "fair share" of bandwidth. # this way no class will ever be starved by another class. Each # class is also permitted to consume all of the available bandwidth # if no other classes are in use. $TC class add dev $IF_EXT parent 1:1 classid 1:20 htb rate 28kbit ceil 120kbit prio 0 $TC class add dev $IF_EXT parent 1:1 classid 1:21 htb rate 20kbit ceil 110kbit prio 1 $TC class add dev $IF_EXT parent 1:1 classid 1:22 htb rate 70kbit ceil 110kbit prio 2 $TC class add dev $IF_EXT parent 1:1 classid 1:23 htb rate 10kbit ceil 20kbit prio 3 ## Attach qdisc to leaf classes # here we at SFQ to each priority class. SFQ insures that # within each class connections will be treated (almost) fairly. $TC qdisc add dev $IF_EXT parent 1:20 handle 20: sfq perturb 10 $TC qdisc add dev $IF_EXT parent 1:21 handle 21: sfq perturb 10 $TC qdisc add dev $IF_EXT parent 1:22 handle 22: sfq perturb 10 $TC qdisc add dev $IF_EXT parent 1:23 handle 23: sfq perturb 10 ## filter traffic into classes by fwmark # here we direct traffic into priority class according to # the fwmark set on the packet (we set fwmark with iptables # later). Note that above we've set the default priority # class to 1:22 so unmarked packets (or packets marked with # unfamiliar IDs) will be defaulted to the lowest priority # class. $TC filter add dev $IF_EXT parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20 $TC filter add dev $IF_EXT parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21 $TC filter add dev $IF_EXT parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22 $TC filter add dev $IF_EXT parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23 ## ICMP (ping) - high prio, impress friends $IPTABLES -t mangle -A outgoing -p icmp -j MARK --set-mark 20 ## DNS name resolution (small packets) $IPTABLES -t mangle -A outgoing -p udp -j MARK --set-mark 20 ## small packets (probably just ACKs) $IPTABLES -t mangle -A outgoing -p tcp -m length --length :64 -j MARK --set-mark 20 ## secure shell $IPTABLES -t mangle -A outgoing -p tcp --dport ssh -j MARK --set-mark 20 $IPTABLES -t mangle -A outgoing -p tcp --sport ssh -j MARK --set-mark 20 ## games (hl & q3) $IPTABLES -t mangle -A outgoing -p tcp --dport 27010:27020 -j MARK --set-mark 21 $IPTABLES -t mangle -A outgoing -p tcp --dport 27960:27970 -j MARK --set-mark 21 ## Default for low port traffic $IPTABLES -t mangle -A outgoing -p tcp --dport 0:1024 -j MARK --set-mark 22 ## local web servers $IPTABLES -t mangle -A outgoing -p tcp --sport http -j MARK --set-mark 21 ## edonkey & other bulk $IPTABLES -t mangle -A outgoing -p tcp --sport 4661:4669 -j MARK --set-mark 23 $IPTABLES -t mangle -A outgoing -p tcp --dport 4661:4669 -j MARK --set-mark 23 $IPTABLES -t mangle -A outgoing -p tcp --sport 1540:1560 -j MARK --set-mark 23 $IPTABLES -t mangle -A outgoing -p tcp --dport 1540:1560 -j MARK --set-mark 23 $IPTABLES -t mangle -A outgoing -p tcp --sport 6699 -j MARK --set-mark 23 $IPTABLES -t mangle -A outgoing -p tcp --dport 6699 -j MARK --set-mark 23 ## redundant- mark any unmarked packets as 22 (low prio) $IPTABLES -t mangle -A outgoing -m mark --mark 0 -j MARK --set-mark 22 fi if [ "$WITH_DOWNSHAPE" = yes ] then ## Calculate Speed RATE_EXT_DOWN=$[$RATE_EXT_DOWN*10/7] ## Downstream slicing (init module, set up device) modprobe imq numdevs=1 $IP link set imq0 up ## Create main class $TC qdisc add dev imq0 handle 1: root htb default 22 $TC class add dev imq0 parent 1: classid 1:1 htb rate ${RATE_EXT_DOWN}kbit ## Add leaf classes - TCP traffic in 21, non TCP traffic in 20 $TC class add dev imq0 parent 1:1 classid 1:20 htb rate $[${RATE_EXT_DOWN}/3]kbit ceil ${RATEDN}kbit prio 0 $TC class add dev imq0 parent 1:1 classid 1:21 htb rate $[${RATE_EXT_DOWN}/3]kbit ceil ${RATEDN}kbit prio 1 $TC class add dev imq0 parent 1:1 classid 1:22 htb rate $[${RATE_EXT_DOWN}/3]kbit ceil ${RATEDN}kbit prio 2 ## Attach qdisc to leaf classes # here we at SFQ to each priority class. SFQ insures that # within each class connections will be treated (almost) fairly. $TC qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10 $TC qdisc add dev imq0 parent 1:21 handle 21: sfq perturb 10 $TC qdisc add dev imq0 parent 1:22 handle 22: red limit 1000000 min 5000 max 100000 avpkt 1000 burst 50 ## Filter traffic into classes by fwmark # here we direct traffic into priority class according to # the fwmark set on the packet (we set fwmark with iptables # later). Note that above we've set the default priority # class to 1:26 so unmarked packets (or packets marked with # unfamiliar IDs) will be defaulted to the lowest priority # class. $TC filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20 $TC filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21 $TC filter add dev imq0 parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22 ## Short TCP packets are probably ACKs, so rate up $IPTABLES -t mangle -A incoming -p tcp -m length --length :64 -j MARK --set-mark 20 ## Same for SSH $IPTABLES -t mangle -A incoming -p tcp --dport ssh -j MARK --set-mark 20 $IPTABLES -t mangle -A incoming -p tcp --sport ssh -j MARK --set-mark 20 ## None TCP traffic $IPTABLES -t mangle -A incoming -p ! tcp -j MARK --set-mark 21 ## All other traffic $IPTABLES -t mangle -A incoming -m mark --mark 0 -j MARK --set-mark 22 ## finally, instruct these packets to go through the imq0 we set up above $IPTABLES -t mangle -A incoming -j IMQ fi ############################################################### ## ICMP, stateful policies and simple flood protection ############################################################### ## Allow incoming ICMP $IPTABLES -A local-in -p icmp -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A local-in -p icmp -j ACCEPT ## Forward ICMP rules $IPTABLES -A int2ext -p icmp -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A int2ext -p icmp -j ACCEPT $IPTABLES -A ext2int -p icmp ! --icmp-type echo-request -m limit --limit 10/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A ext2int -p icmp ! --icmp-type echo-request -j ACCEPT if [ ! -z $IF_DMZ ] then $IPTABLES -A int2dmz -p icmp -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES $IPTABLES -A ext2dmz -p icmp ! --icmp-type echo-request -m limit --limit 10/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A ext2dmz -p icmp ! --icmp-type echo-request -j ACCEPT $IPTABLES -A dmz2int -p icmp -j DROP test $WITH_IPv6 = yes && $IP6TABLES -p icmp -j DROP $IPTABLES -A dmz2ext -p icmp -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A dmz2ext -p icmp -j ACCEPT fi ## 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 test $WITH_IPv6 = yes && $IP6TABLES -A all-in -p icmp --icmp-type echo-request -m limit --limit 10/s -j ACCEPT ## Deny Portscan, only accept 100 tcp control packets per second (increase number for larger DMZ/LANs) $IPTABLES -A ext2int -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 100/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A ext2int -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 100/s -j ACCEPT if [ ! -z $IF_DMZ ] then $IPTABLES -A ext2dmz -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 100/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A ext2dmz -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 100/s -j ACCEPT fi ## Deny all invalid packets $IPTABLES -A all-in -m state --state INVALID -j deny test $WITH_IPv6 = yes && $IP6TABLES -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 test $WITH_IPv6 = yes && $IP6TABLES -A ext-in -m state --state NEW -j deny $IPTABLES -A ext2int -m state --state NEW -j deny test $WITH_IPv6 = yes && $IP6TABLES -A ext2int -m state --state NEW -j deny if [ ! -z $IF_DMZ ] then $IPTABLES -A dmz2int -m state --state NEW -j deny test $WITH_IPv6 = yes && $IP6TABLES -A dmz2int -m state --state NEW -j deny fi ############################################################### ## The helper chains ############################################################### ## Accept finally all non new unprivate Traffic $IPTABLES -A final -p tcp --destination-port 1023:65535 -m state --state RELATED,ESTABLISHED -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A final -p tcp --destination-port 1023:65535 -m state --state RELATED,ESTABLISHED -j ACCEPT $IPTABLES -A final -p udp --destination-port 1023:65535 -m state --state RELATED,ESTABLISHED -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A final -p udp --destination-port 1023:65535 -m state --state RELATED,ESTABLISHED -j ACCEPT ## send all denied tcp packages a tcp reset (so nmap shows closed, not filtered!) $IPTABLES -A deny -p tcp -j REJECT --reject-with tcp-reset test $WITH_IPv6 = yes && $IP6TABLES -p tcp -j REJECT --reject-with tcp-reset ## all other connections get a icmp port unreachable :P $IPTABLES -A deny -j REJECT test $WITH_IPv6 = yes && $IP6TABLES -A deny -j REJECT ## Deny Synflood, only accept 10 new connections per second $IPTABLES -A limit10 -m state --state NEW -m limit --limit 10/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit10 -m state --state NEW -m limit --limit 1000/s -j ACCEPT $IPTABLES -A limit10 -m state ! --state NEW -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit10 -m state --state RELATED,ESTABLISHED -j ACCEPT ## Deny Synflood, only accept 100 new connections per second $IPTABLES -A limit100 -m state --state NEW -m limit --limit 100/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit100 -m state --state NEW -m limit --limit 1000/s -j ACCEPT $IPTABLES -A limit100 -m state ! --state NEW -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit100 -m state --state RELATED,ESTABLISHED -j ACCEPT ## Deny Synflood, only accept 1000 new connections per second $IPTABLES -A limit1000 -m state --state NEW -m limit --limit 1000/s -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit1000 -m state --state NEW -m limit --limit 1000/s -j ACCEPT $IPTABLES -A limit1000 -m state ! --state NEW -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A limit1000 -m state --state RELATED,ESTABLISHED -j ACCEPT ############################################################### ## Default policies for all chains ############################################################### ## Input policy (no packet should reach it, but we set it, just to make sure) $IPTABLES -P INPUT DROP test $WITH_IPv6 = yes && $IP6TABLES -P INPUT DROP ## Output policy (every packet from localhost to somewhere should be accepted) $IPTABLES -P OUTPUT ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -P OUTPUT ACCEPT ## Forward policy (no packet should reach it, but we set it, just to make sure) $IPTABLES -P FORWARD DROP test $WITH_IPv6 = yes && $IP6TABLES -P FORWARD DROP ## Accept all valid traffic from INTERNAL to EXTERNAL $IPTABLES -A int2ext -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A int2ext -j ACCEPT ## Deny all traffic from EXTERNAL to INTERNAL $IPTABLES -A ext2int -j RETURN test $WITH_IPv6 = yes && $IP6TABLES -A ext2int -j RETURN if [ ! -z $IF_DMZ ] then ## Accept all valid traffic from INTERNAL to DMZ $IPTABLES -A int2dmz -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A int2dmz -j ACCEPT ## Skip all traffic from DMZ to EXTERNAL (pass back to main chain) $IPTABLES -A dmz2ext -j ACCEPT test $WITH_IPv6 = yes && $IP6TABLES -A dmz2ext -j RETURN ## Deny all traffic from EXTERNAL to DMZ $IPTABLES -A ext2dmz -j RETURN test $WITH_IPv6 = yes && $IP6TABLES -A ext2dmz -j RETURN ## Skip all traffic from DMZ to INTERNAL (pass back to main chain) $IPTABLES -A dmz2int -j RETURN test $WITH_IPv6 = yes && $IP6TABLES -A dmz2int -j RETURN fi ## If no other rule matched, finally deny traffic $IPTABLES -A final -j deny test $WITH_IPv6 = yes && $IP6TABLES -A final -j deny ############################################################### ## DONE!!! ############################################################### #echo -e "\033[75G\033[32mdone\033[m\017" exit 0