#!/bin/bash # Copyright Dave Puchyr 2009. All Rights Reserved. # $Id: fifalobath 61 2010-04-14 19:31:31Z dave $ # important vars TC=tc IP=ip IPTABLES=iptables RESOLV=/etc/resolv.conf # uncomment these for dry-runs #TC="echo tc" #IP="echo ip" #IPTABLES="echo iptables" #RESOLV=/tmp/resolv.conf # rock 'n' roll . /etc/sysconfig/network ME=$(stat $0 -c "%N" | sed -e 's/.*-> `//' -e "s/[\`']//g") TAG=`basename $ME` ME="$(cd $(dirname "$ME"); pwd)/$TAG" LOG="logger -t $TAG" ERR="$LOG ERROR: " [ -z $1 ] && cat <&1 > /dev/null || exit -1 done echo "all good" && exit 0 fi # check for rt_tables entries if [ "$1" == "tcheck" ]; then RT_TABLES=`grep '^[0-9]' /etc/iproute2/rt_tables | sed 's/[\t ]/ /g'` # strip the comments out of rt_tables ALL_GOOD=1 for EXTIF in $EXTIFs; do if ! `echo -e $RT_TABLES | grep -q "[0-9] $EXTIF$TAG"`; then echo "$EXTIF$TAG entry in /etc/iproute2/rt_tables is REQUIRED" ALL_GOOD= fi done [ -n "$ALL_GOOD" ] && echo "all good" exit 0 fi # check if we're interested in the interface if ! `echo "$EXTIFs $INTIFs bootstrap reload" | fgrep -q "$1"`; then $LOG "$ME ignoring $1 and exiting since it's not one of $EXTIFs $INTIFs as defined in /etc/sysconfig/network" exit 0; fi # pppd and its call to /etc/ppp/ip-up are woefully inadequate since the DNS(s) are not provided! if `echo $1 | fgrep -q ppp`; then PPPHACK=`tac /var/log/messages | egrep -m 4 'pppd.*((((local|remote) +IP)|(primary|secondary) +DNS) address)'` DNS2=`echo $PPPHACK | sed -e 's/.*secondary DNS address //' -e 's/ .*//'` DNS1=`echo $PPPHACK | sed -e 's/.*primary DNS address //' -e 's/ .*//'` GATEWAY=`echo $PPPHACK | sed -e 's/.*remote IP address //' -e 's/ .*//'` IPADDR=`echo $PPPHACK | sed -e 's/.*local IP address //' -e 's/ .*//'` INTERFACE="$1" cat <> "$FIFALOBATH_DYN" # PPPHACK $INTERFACE IP$INTERFACE=$IPADDR; NM$INTERFACE=255.255.255.255; GW$INTERFACE=$GATEWAY; DNSs$INTERFACE='$DNS1 $DNS2'; DNS1$INTERFACE=$DNS1; DNS2$INTERFACE=$DNS2; EOS fi # at this point there's something more complex to do [ -s "$FIFALOBATH_DYN" ] && . "$FIFALOBATH_DYN" cd /etc/sysconfig/network-scripts . ./network-functions # functions act() { $1 && $LOG "did $1" || $ERR "puked on $1" } actlog() { $1 > /dev/null 2> /dev/null ; $LOG "$1 # exited with $?" } commit_resolv() { act "chmod a+r $1" act "mv $1 $RESOLV" } throttle_single_port() { SDPORT=$1 for DELIMITED in $2; do SERVICE=`echo $DELIMITED | cut -d'/' -f 2` PORT=`echo $DELIMITED | cut -d'/' -f 1` PROTOCOLS=`echo $DELIMITED | cut -d'/' -f 3 | sed 's/,/ /g'` if [ ! -n "$PROTOCOLS" ]; then PROTOCOLS=tcp; fi for PROTOCOL in $PROTOCOLS; do if ! `echo "tcp udp icmp" | fgrep -q "$PROTOCOL"`; then $ERR "invalid protocol '$PROTOCOL' extracted from '$DELIMITED'" continue fi act "$IPTABLES -t mangle -A THROTTLE -p $PROTOCOL --$SDPORT $PORT -j CLASSIFY --set-class $CLASS" done done } throttle_multi_port() { for DELIMITED in $1; do SERVICE=`echo $DELIMITED | cut -d'/' -f 2` PORT=`echo $DELIMITED | cut -d'/' -f 1` PROTOCOLS=`echo $DELIMITED | cut -d'/' -f 3 | sed 's/,/ /g'` if [ ! -n "$PROTOCOLS" ]; then PROTOCOLS=tcp; fi for PROTOCOL in $PROTOCOLS; do if ! `echo "tcp udp" | fgrep -q "$PROTOCOL"`; then # only tcp and udp allowed $ERR "invalid protocol '$PROTOCOL' extracted from '$DELIMITED'" continue fi act "$IPTABLES -t mangle -A THROTTLE -p $PROTOCOL -m multiport --ports $PORT -j CLASSIFY --set-class $CLASS" done done } # determine which interfaces are active and their ip addresses for INTERFACE in $EXTIFs $INTIFs; do if ! LC_ALL=C ip -o link 2> /dev/null | grep -q "${INTERFACE}[:@].*,UP"; then $LOG "$INTERFACE is down" continue fi if echo "$EXTIFs" | fgrep -q "$INTERFACE"; then ACTIVE_EXTIFs="$ACTIVE_EXTIFs $INTERFACE" else ACTIVE_INTIFs="$ACTIVE_INTIFs $INTERFACE" fi IPADDR= NETMASK= GATEWAY= DNSs= DNS1= DNS2= need_config $INTERFACE source_config # set the load balance weight [ -z "$WEIGHT" ] && WEIGHT=1 eval " UP$INTERFACE=$UPRATE; W$INTERFACE=$WEIGHT; " if [ -n "$IPADDR" ]; then eval " IP$INTERFACE=$IPADDR; NM$INTERFACE=$NETMASK; GW$INTERFACE=$GATEWAY; DNS1$INTERFACE=$DNS1; DNS2$INTERFACE=$DNS2; " else DYNAMIC_IFs="$DYNAMIC_IFs $INTERFACE" if [ "$1" == "bootstrap" ]; then INFO=`ifconfig $INTERFACE | fgrep 'inet addr:' | sed 's/.*inet addr:'//` IPADDR=`echo $INFO | sed 's/ .*//'`; NETMASK=`echo $INFO | sed 's/.*Mask://'` GATEWAY=`traceroute -n -i $INTERFACE 74.125.127.100 -m 1 | egrep '^ 1' | sed -e 's/ 1 //' -e 's/ .*//' | egrep '([0-9]+\.){3}[0-9]'` if [ "x$GATEWAY" == "x" ]; then MISSING="$MISSING $INTERFACE" cat <> "$FIFALOBATH_DYN" # TODO: manually configure $INTERFACE export IP$INTERFACE=$IPADDR; export NM$INTERFACE=$NETMASK; export GW$INTERFACE=$GATEWAY; export DNSs$INTERFACE='$DNSs'; export DNS1$INTERFACE=$DNS1; export DNS2$INTERFACE=$DNS2; EOS fi fi fi done if [ "$1" == "bootstrap" ]; then # abort if we're missing info [ -n "$MISSING" ] && echo "manually configure $MISSING in $FIFALOBATH_DYN" && exit -1 # otherwise force dns to use current values RESOLV_SEARCH=`egrep -v '^(^[;#])' /etc/resolv.conf | fgrep search` RESOLV_DNS=`egrep -v '^(^[;#])' /etc/resolv.conf | fgrep nameserver` RESOLV_SEARCH="; RESOLV_SEARCH and RESOLV_DNS from $ME boostrap\n$RESOLV_SEARCH" fi # generate resolv.conf RESOLV_TMP=`mktemp /tmp/XXXXXX` NOW=`date` echo "; written by $ME using /etc/sysconfig/network at $NOW" > "$RESOLV_TMP" [ -n "$RESOLV_SEARCH" ] && echo -e "$RESOLV_SEARCH ; from RESOLV_SEARCH" >> "$RESOLV_TMP" [ -n "$RESOLV_DNS" ] && echo -e "; from RESOLV_DNS\n$RESOLV_DNS" >> "$RESOLV_TMP" for EXTIF in $ACTIVE_EXTIFs; do echo "; from $EXTIF" >> "$RESOLV_TMP" eval "DNS=\$DNS1$EXTIF" [ -n "$DNS" ] && echo "nameserver $DNS" >> "$RESOLV_TMP" eval "DNS=\$DNS2$EXTIF" [ -n "$DNS" ] && echo "nameserver $DNS" >> "$RESOLV_TMP" done # firewall stuff first UNIVERSE="0.0.0.0/0" # rock 'n' roll $LOG "script: $0 $@ maps to $ME $@" $LOG "external interface(s): $ACTIVE_EXTIFs" $LOG "internal interface(s): $ACTIVE_INTIFs" if echo "$0" | fgrep -q "down"; then $LOG "bailing on $ME since $0 matches 'down'" exit 0 fi # clear existing rules $IPTABLES -P INPUT DROP $IPTABLES -F INPUT $IPTABLES -P OUTPUT DROP $IPTABLES -F OUTPUT $IPTABLES -P FORWARD DROP $IPTABLES -F FORWARD $IPTABLES -F -t nat $IPTABLES -F -t mangle `$IPTABLES -L | fgrep -q SYNFLOOD` && $IPTABLES -F SYNFLOOD && $IPTABLES -X SYNFLOOD $IPTABLES -N SYNFLOOD `$IPTABLES -L | fgrep -q DROPIT` && $IPTABLES -F DROPIT && $IPTABLES -X DROPIT $IPTABLES -N DROPIT $IPTABLES -Z # reset counters # limit syn flood attacks $IPTABLES -A INPUT -p tcp --syn -j SYNFLOOD && $IPTABLES -A SYNFLOOD -m limit --limit 1/s --limit-burst 3 -j RETURN && $IPTABLES -A SYNFLOOD -j DROP && $IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP && $IPTABLES -A INPUT -f -j DROP && $IPTABLES -A INPUT -p tcp --tcp-flags ALL ALL -j DROP && $IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -j DROP && $LOG "limited syn flood attacks" # http://www.netfilter.org/documentation/HOWTO/packet-filtering-HOWTO-7.html $IPTABLES -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT && $IPTABLES -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT && $IPTABLES -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT && $LOG "limited syn flood (again), furtive port scanner, and ping of death" if [ -z $LOG_DROPPED ]; then act "$IPTABLES -A DROPIT -j REJECT" else act "$IPTABLES -A DROPIT -j LOG --log-level info" fi # make lo good to go $IPTABLES -A INPUT -i lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT $IPTABLES -A OUTPUT -o lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT # make private NICs good to go nINTIFs=`echo "$ACTIVE_INTIFs" | wc -w` for INTIF in $ACTIVE_INTIFs; do # loop on ACTIVE_INTIFs eval " \ INTIP=\$IP$INTIF; \ INTMASK=\$NM$INTIF; \ " INTNET="$INTIP/$INTMASK" INTIP="$INTIP/32" $IPTABLES -A INPUT -i $INTIF -s $INTNET -d $UNIVERSE -j ACCEPT && $LOG "allowing $INTNET to connect anywhere" if [ ! -z $ALLOW_DHCPD ]; then $IPTABLES -A INPUT -i $INTIF -p tcp --sport 68 --dport 67 -j ACCEPT && $IPTABLES -A INPUT -i $INTIF -p udp --sport 68 --dport 67 -j ACCEPT && $LOG "allowing dhcpd request on $INTIF" $IPTABLES -A OUTPUT -o $INTIF -p tcp -s $INTIP --sport 67 -d 255.255.255.255 --dport 68 -j ACCEPT && $IPTABLES -A OUTPUT -o $INTIF -p udp -s $INTIP --sport 67 -d 255.255.255.255 --dport 68 -j ACCEPT && $LOG "allowing dhcpd requests from $INTIP" fi # allow internal interfaces to forward to each other for OTHERINTIF in $ACTIVE_INTIFs; do [ "$INTIF" == "$OTHERINTIF" ] && continue $IPTABLES -A FORWARD -i $INTIF -o $OTHERINTIF -j ACCEPT && $LOG "allowing forwarding between $INTIF and $OTHERINTIF" done # holes for the intranet [ -x "$ME.private" ] && . "$ME.private" $IPTABLES -A OUTPUT -o $INTIF -s $INTIP -d $INTNET -j ACCEPT && $LOG "allowing $INTNET from $INTIP" done # loop on ACTIVE_INTIFs # external (public) interface(s) for EXTIF in $ACTIVE_EXTIFs; do # loop on ACTIVE_EXTIFs eval "EXTIP=\$IP$EXTIF" # allow cross-traffic between the external interfaces for OTHEREXTIF in $ACTIVE_EXTIFs; do eval "OTHEREXTIP=\$IP$OTHEREXTIF" [ "$EXTIP" == "$OTHEREXTIP" ] && continue $IPTABLES -A INPUT -i $OTHEREXTIF -d $EXTIP -j ACCEPT $IPTABLES -A OUTPUT -o $EXTIF -s $OTHEREXTIP -j ACCEPT done # allow pings if [ ! -z $ALLOW_PING ]; then $IPTABLES -A INPUT -i $EXTIF -p ICMP -s $UNIVERSE -d $EXTIP -j ACCEPT && $LOG "allowing pings on $EXTIP" fi # allow ssh if [ ! -z $ALLOW_SSH ]; then $IPTABLES -A INPUT -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -p tcp -s $UNIVERSE -d $EXTIP --dport 22 -j ACCEPT && $LOG "allowing ssh on $EXTIP" fi # allow related back into the box $IPTABLES -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state --state ESTABLISHED,RELATED -j ACCEPT && $LOG "alowing establish/related on $EXTIP" # internal (private) interface(s) for INTIF in $ACTIVE_INTIFs; do # loop on ACTIVE_INTIFs eval " \ INTIP=\$IP$INTIF; \ INTMASK=\$NM$INTIF; \ " INTNET="$INTIP/$INTMASK" INTIP="$INTIP/32" $IPTABLES -A INPUT -i $EXTIF -s $INTNET -d $UNIVERSE -j DROPIT && $LOG "thwarting spoofing on $INTIF" $IPTABLES -A OUTPUT -o $INTIF -s $EXTIP -d $INTNET -j ACCEPT && $LOG "allowing $INTNET from $EXTIP" $IPTABLES -A OUTPUT -o $EXTIF -s $UNIVERSE -d $INTNET -j DROPIT && $LOG "dropping all outgoing to $INTNET on $EXTIF" $IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT && $LOG "allowing related connections into $INTIF" $IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT && $LOG "allowing all connections out of $INTIF" done # loop on ACTIVE_INTIFs # allow everything else out $IPTABLES -A OUTPUT -o $EXTIF -s $EXTIP -d $UNIVERSE -j ACCEPT && $LOG "allowing everything out from $EXTIP" # do masquerading $IPTABLES -t nat -A POSTROUTING -o $EXTIF -j SNAT --to $EXTIP && $LOG "SNATed $EXTIP" # holes in the firewall, ie ports/services that are accessible to the public [ -x "$ME.public" ] && . "$ME.public" done # loop on ACTIVE_EXTIFs # trusted and public get a loop of their own so that they can specify host names, not just interface names for EXTIF in $ACTIVE_EXTIFs; do # loop on ACTIVE_EXTIFs eval "EXTIP=\$IP$EXTIF" # peep holes in the firewall, ie ports/services that are accessible to trusted hosts [ -x "$ME.trusted" ] && . "$ME.trusted" # tunnels in the firewall, ie ports/services that are on the intranet but are accessible to the public [ -x "$ME.forwarding" ] && . "$ME.forwarding" done # loop on ACTIVE_EXTIFs # catch all on INPUT $IPTABLES -A INPUT -s $UNIVERSE -d $UNIVERSE -j DROPIT && $LOG "dropping all other incoming" # catch all on OUTPUT $IPTABLES -A OUTPUT -s $UNIVERSE -d $UNIVERSE -j DROPIT && $LOG "dropping all other outgoing" # catch all on FORWARD $IPTABLES -A FORWARD -j DROPIT && $LOG "dropping all other forwarding" # balancing, failover, and routing if (( $nINTIFs > 0 )); then echo "1" > /proc/sys/net/ipv4/ip_forward && $LOG "enabled ip forwarding" fi # failover nEXTIFs=`echo "$ACTIVE_EXTIFs" | wc -w` if (( $nEXTIFs > 1 )) && [ -n "$ROUTE_TIMEOUT" ]; then # set failover timeout echo "$ROUTE_TIMEOUT" > /proc/sys/net/ipv4/route/gc_timeout && $LOG "set gc_timeout to $ROUTE_TIMEOUT" fi # balancing: delete all routes and rules just to keep things simple actlog "$IP route del default" for EXTIF in $EXTIFs; do # loop on all EXTIFs, not just active ones eval "IPADDR=\$IP$EXTIF" if [ -n "$IPADDR" ]; then ROUTE=`ip route | fgrep -q $IPADDR` # not $IP so dry-runs work as expected if [ -n "$ROUTE" ]; then actlog "$IP route del $ROUTE"; fi fi actlog "$IP route del table $EXTIF$TAG" actlog "$IP rule del table $EXTIF$TAG" done # loop on all EXTIFs, not just active ones for EXTIF in $ACTIVE_EXTIFs; do # loop on ACTIVE_EXTIFs # get the "current" values eval " IPADDR=\$IP$EXTIF; NM=\$NM$EXTIF; GW=\$GW$EXTIF; W=\$W$EXTIF; " eval `ipcalc -p $IPADDR $NM` # sets PREFIX eval `ipcalc -n $IPADDR $NM` # sets NETWORK # add EXTIF's route actlog "$IP route add $NETWORK/$PREFIX dev $EXTIF src $IPADDR table $EXTIF$TAG" # add EXTIF as a default route actlog "$IP route add default via $GW table $EXTIF$TAG" # add EXTIF's route to the main table # automagically added? act "$IP route add $NETWORK/$PREFIX dev $EXTIF src $IPADDR" # add EXTIF's rule act "$IP rule add from $IPADDR table $EXTIF$TAG" # add default route if no load balancing if [ "$nEXTIFs" == "1" ] || [ -z $LOAD_BALANCE ] && [ -z $DEFAULTED ]; then act "$IP route add default via $GW" DEFAULTED=1 else WEIGHTS="$WEIGHTS nexthop via $GW dev $EXTIF weight $W" fi # add rules for marked packets MARK=`fgrep $EXTIF$TAG /etc/iproute2/rt_tables | sed 's/[ \t].*$//'` eval "export MARK$EXTIF=$MARK" # export to make MARKs available for $ME.mark act "$IP rule add from all fwmark $MARK table $EXTIF$TAG" done # mark [ -x "$ME.mark" ] && . "$ME.mark" # balance if [ -z $DEFAULTED ]; then act "$IP route add default scope global $WEIGHTS" fi act "$IP route flush cache" # prune $FIFALOBATH_DYN if all dynamic, external interfaces are active and all went well if echo "$ACTIVE_EXTIFs" | fgrep -q "$EXTIFs"; then for INTERFACE in $DYNAMIC_IFs; do eval " DYNIP=\$IP$INTERFACE; DYNNM=\$NM$INTERFACE; DYNGW=\$GW$INTERFACE; DYNDNS=\$DNSs$INTERFACE; DYNDNS1=\$DNS1$INTERFACE; DYNDNS2=\$DNS2$INTERFACE; " DYNINFO=`cat < "$FIFALOBATH_DYN" fi fi # throttle `$IPTABLES -t mangle -L | fgrep -q THROTTLE` || $IPTABLES -t mangle -N THROTTLE for i in $EXTIFs; do # reset tc and iptables actlog "$TC qdisc del dev $i root" actlog "$IPTABLES -t mangle -D POSTROUTING -o $i -j THROTTLE" done actlog "$IPTABLES -t mangle -F THROTTLE" # commit resolve.conf now commit_resolv $RESOLV_TMP # check if we want to throttle [ -z $THROTTLE ] && exit 0 xint() ( IFS=*; echo "$*" | bc -l | sed 's/\..*//') for EXTIF in $ACTIVE_EXTIFs; do eval "UPRATE=\$UP$EXTIF" if [ ! -n "$UPRATE" ]; then $ERR "ifcfg-$EXTIF must set variable UPRATE for throttling to work" continue fi UPLOAD=`echo $UPRATE | sed 's/[^0-9]//g'` UNITS=`echo $UPRATE | sed 's/[0-9]//g'` THROTTLED=`xint $THROTTLE $UPLOAD` UPREALTIME=`xint $THROTTLED $ALLOT_REALTIME` UPP2P=`xint $THROTTLED $ALLOT_P2P` UPOTHER=$(( $THROTTLED - $UPREALTIME - $UPP2P )) $LOG "throttling $EXTIF from $UPLOAD to $THROTTLED$UNITS to avoid choking; realtime:p2p:other = $UPREALTIME:$UPP2P:$UPOTHER$UNITS" UPRATE="$THROTTLED$UNITS" # add HTB root qdisc act "$TC qdisc add dev $EXTIF root handle 1: htb default 99" # add main rate limit classes act "$TC class add dev $EXTIF parent 1: classid 1:1 htb rate $UPRATE" # set classes; each class can lend and borrow bandwidth from each-other act "$TC class add dev $EXTIF parent 1:1 classid 1:10 htb rate $UPREALTIME$UNITS ceil $UPRATE quantum 1 prio 0" # realtime act "$TC class add dev $EXTIF parent 1:1 classid 1:20 htb rate $UPOTHER$UNITS ceil $UPRATE quantum 1 prio 1" # responsive act "$TC class add dev $EXTIF parent 1:1 classid 1:30 htb rate $UPOTHER$UNITS ceil $UPRATE quantum 1 prio 2" # interactive act "$TC class add dev $EXTIF parent 1:1 classid 1:40 htb rate $UPOTHER$UNITS ceil $UPRATE quantum 1 prio 3" # low ports act "$TC class add dev $EXTIF parent 1:1 classid 1:50 htb rate $UPOTHER$UNITS ceil $UPRATE quantum 1 prio 5" # data act "$TC class add dev $EXTIF parent 1:1 classid 1:99 htb rate $UPP2P$UNITS ceil $UPRATE quantum 1 prio 6" # p2p # attach qdisc to leaf classes act "$TC qdisc add dev $EXTIF parent 1:10 handle 10: pfifo limit 5" # no sfq; better to drop packets than delay them in realtime act "$TC qdisc add dev $EXTIF parent 1:20 handle 20: pfifo limit 30" act "$TC qdisc add dev $EXTIF parent 1:30 handle 30: pfifo limit 30" act "$TC qdisc add dev $EXTIF parent 1:40 handle 40: sfq perturb 10 limit 200" # long queue here and sqf to minimize drops act "$TC qdisc add dev $EXTIF parent 1:50 handle 50: sfq perturb 10 limit 200" act "$TC qdisc add dev $EXTIF parent 1:99 handle 99: sfq perturb 10 limit 300" # longest queue for p2p act "$IPTABLES -t mangle -I POSTROUTING -o $EXTIF -j THROTTLE" # setup chain for filtering and marking done # define classifications CLASS=1:10 # realtime act "$IPTABLES -t mangle -A THROTTLE -m tos --tos 0x10 -j CLASSIFY --set-class $CLASS" # ensure min delay by TOS field act "$IPTABLES -t mangle -A THROTTLE -p udp --dport 123 -j CLASSIFY --set-class $CLASS" # ntp [ -x "$ME.realtime" ] && . "$ME.realtime" CLASS=1:20 # responsive act "$IPTABLES -t mangle -A THROTTLE -p icmp -j CLASSIFY --set-class $CLASS" act "$IPTABLES -t mangle -A THROTTLE -p tcp --tcp-flags SYN,RST,ACK SYN,FIN -j CLASSIFY --set-class $CLASS" act "$IPTABLES -t mangle -A THROTTLE -p tcp -m multiport --ports ssh -m limit --limit 10/second -j CLASSIFY --set-class $CLASS" # ssh, not scp [ -x "$ME.responsive" ] && . "$ME.responsive" CLASS=1:30 # interactive act "$IPTABLES -t mangle -A THROTTLE -p tcp -m length --length 60 -j CLASSIFY --set-class $CLASS" # small packets (probably just ACKs) [ -x "$ME.interactive" ] && . "$ME.interactive" CLASS=1:40 # low port services act "$IPTABLES -t mangle -A THROTTLE -p tcp --sport 0:1024 -j CLASSIFY --set-class $CLASS" act "$IPTABLES -t mangle -A THROTTLE -p tcp --dport 0:1024 -j CLASSIFY --set-class $CLASS" CLASS=1:50 # data [ -x "$ME.data" ] && . "$ME.data"