====== Netfilter/Iptables script, with traffic control (QoS) ====== {{tag>netfilter networking iptables tc qos}} The script below is used on production systems to enable Firewalling with Netfilter/Iptables and QOS with Traffic Control. More detailled information about Netfilter and TC can be found in other articles on this wiki. #! /bin/bash # ### BEGIN INIT INFO # Provides: netfilter_qos.sh # Required-Start: $syslog # Required-Stop: $syslog # Should-Start: $local_fs # Should-Stop: $local_fs # Default-Start: 2 # Default-Stop: 0 1 6 # Short-Description: starts/stops netfilter_qos.sh # Description: starts and stops netfilter and qos rules ### END INIT INFO NETCARD=eth0 # network card to apply the QoS to IP=1.2.3.4 # local ip address LAN=1.2.3.0/24 # lan address UPLINK=1024 # upload in kbits/s #within http class, list hosts and allow them [ 1/(total nb of host) ] bandwidth HTTPPRIORITIES="www.example.net website.example.com static.myexample.eu" LISTENTCP="ssh http https imap" LISTENUDP="domain" TC=/sbin/tc IPT=/sbin/iptables case "$1" in start) echo "~~~~ LOADING $NETCARD NETFILTER/QOS RULES FOR `uname -n` ~~~~" echo echo "#-cleanup" $TC qdisc del dev $NETCARD root $IPT -t mangle -F echo echo "##################### FIREWALL ###############################" echo echo "create LOGACCEPT: LOG to syslog and ACCEPT packet" $IPT -N LOGACCEPT $IPT -t filter -A LOGACCEPT -j LOG --log-prefix "NETFILTER ACCEPT => " --log-level debug $IPT -t filter -A LOGACCEPT -j ACCEPT echo "ACCEPT localhost packets" $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT echo "accept packets from ESTABLISHED connections without LOGGING" $IPT -A INPUT -i $NETCARD -p tcp -m state --state ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o $NETCARD -p tcp -m state --state ESTABLISHED -j ACCEPT $IPT -A INPUT -i $NETCARD -p udp -m state --state ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o $NETCARD -p udp -m state --state ESTABLISHED -j ACCEPT for service in $LISTENTCP do echo "LOGACCEPT incoming TCP/$service" $IPT -A INPUT -t filter -i $NETCARD -p tcp --dport $service -m state --state NEW -j LOGACCEPT done for service in $LISTENUDP do echo "LOGACCEPT incoming UDP/$service" $IPT -A INPUT -t filter -i $NETCARD -p udp --dport $service -m state --state NEW -j LOGACCEPT done echo "LOGACCEPT incoming TCP/10035 (dspam)" $IPT -A INPUT -t filter -i $NETCARD -p tcp --dport 10035 -s dspam.example.net -m state --state NEW -j LOGACCEPT $IPT -A OUTPUT -t filter -o $NETCARD -p tcp --dport 10034 -d dspam.example.net -m state --state NEW -j LOGACCEPT echo "LOGACCEPT incoming TCP/LDAPS (OpenLDAP sync)" $IPT -A INPUT -t filter -i $NETCARD -p tcp --dport ldaps -s ldapmaster.example.net -m state --state NEW -j LOGACCEPT echo "LOGACCEPT incoming TCP/LDAPS from nagios" $IPT -A INPUT -t filter -i $NETCARD -p tcp --dport ldaps -s nagios.example.net -m state --state NEW -j LOGACCEPT echo "LOGACCEPT incoming ping from iruel (nagios check)" $IPT -A INPUT -t filter -i $NETCARD -p icmp --icmp-type 8 -s nagios.example.net -j LOGACCEPT $IPT -A OUTPUT -t filter -o $NETCARD -p icmp --icmp-type 0 -d nagios.example.net -j LOGACCEPT echo "LOGACCEPT outgoing DNS requests" $IPT -A OUTPUT -t filter -o $NETCARD -p udp --dport domain -j LOGACCEPT $IPT -A OUTPUT -t filter -o $NETCARD -p tcp --dport domain -m state --state NEW -j LOGACCEPT $IPT -A INPUT -t filter -i $NETCARD -p udp --sport domain -m state --state ESTABLISHED -j LOGACCEPT echo "LOGACCEPT outgoing NTP requests" $IPT -A OUTPUT -t filter -o $NETCARD -p udp --dport ntp -m state --state NEW -j LOGACCEPT $IPT -A INPUT -t filter -i $NETCARD -p udp --sport ntp -m state --state ESTABLISHED -j LOGACCEPT echo "LOGACCEPT outgoing SMTP requests" $IPT -A OUTPUT -t filter -o $NETCARD -p tcp --dport smtp -m state --state NEW -j LOGACCEPT echo "LOGACCEPT root outgoing connexions" $IPT -A OUTPUT -t filter -o $NETCARD -m owner --uid-owner 0 -j LOGACCEPT echo "LOGACCEPT user=julien outgoing connexions" $IPT -A OUTPUT -t filter -o $NETCARD -m owner --uid-owner 1000 -j LOGACCEPT echo echo "##################### QOS ####################################" echo echo "#-root" $TC qdisc add dev $NETCARD root handle 1: htb default 999 r2q 5000 echo "#--uplink - rate $UPLINK kbit ceil $UPLINK kbit" $TC class add dev $NETCARD parent 1:0 classid 1:1 htb rate $(($UPLINK))kbit ceil $(($UPLINK))kbit echo "#---interactive - id 100 -rate $(( $UPLINK / 48 )) kbit ceil $(( $UPLINK / 3 )) kbit" $TC class add dev $NETCARD parent 1:1 classid 1:100 htb rate $(( $UPLINK / 48 ))kbit ceil $(( $UPLINK / 3 ))kbit burst 5k prio 1 linklayer atm echo "#--- ~ sub interactive: pfifo" $TC qdisc add dev $NETCARD parent 1:100 handle 1100: pfifo limit 10000 echo "#--- ~ interactive filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 1 handle 100 fw flowid 1:100 echo "#--- ~ netfilter rule - DNS, NTP, SNMP at 100" $IPT -t mangle -A OUTPUT -o $NETCARD -p udp -m multiport --sports 53,123,161:162 -j CONNMARK --set-mark 100 $IPT -t mangle -A OUTPUT -o $NETCARD -p udp --dport 53 -j CONNMARK --set-mark 100 echo "#---tcp acks - id 200 - rate $(( $UPLINK / 12 )) kbit ceil $(( $UPLINK / 8 )) kbit" $TC class add dev $NETCARD parent 1:1 classid 1:200 htb rate $(( $UPLINK / 12 ))kbit ceil $(( $UPLINK / 8 ))kbit burst 8k prio 2 echo "#--- ~ sub tcp acks: pfifo" $TC qdisc add dev $NETCARD parent 1:200 handle 1200: pfifo limit 10000 echo "#--- ~ filtre tcp acks" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 2 handle 200 fw flowid 1:200 echo "#--- ~ netfilter rule will be loaded at the end" echo "#---ssh - id 300 - rate $(( $UPLINK / 100 )) kbit ceil $(( $UPLINK / 8 )) kbit" $TC class add dev $NETCARD parent 1:1 classid 1:300 htb rate $(( $UPLINK / 100 ))kbit ceil $(( $UPLINK / 8 ))kbit burst 8k prio 3 echo "#--- ~ sub ssh: sfq" $TC qdisc add dev $NETCARD parent 1:300 handle 1300: sfq perturb 10 echo "#--- ~ ssh filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 3 handle 300 fw flowid 1:300 echo "#--- ~ netfilter rule - SSH at 300" $IPT -t mangle -A OUTPUT -o $NETCARD -p tcp --tcp-flags SYN,ACK SYN,ACK --sport 22 -j CONNMARK --set-mark 300 echo "#---http branch - id 400 - rate $(( $UPLINK / 3 )) kbit ceil $UPLINK kbit" $TC class add dev $NETCARD parent 1:1 classid 1:400 htb rate $(( $UPLINK / 3 ))kbit ceil $(( $UPLINK ))kbit burst 20k prio 4 echo "#--- ~ sub http branch: sfq" $TC qdisc add dev $NETCARD parent 1:400 handle 1400: sfq perturb 10 echo "#--- ~ http branch filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 4 handle 400 fw flowid 1:400 # first count the number of website webcount=1 #start at 1 to include the default fallback for i in $HTTPPRIORITIES do webcount=$(( webcount + 1 )) done # then create the rules counter=0 for i in $HTTPPRIORITIES do counter=$(( counter + 1 )) echo "#---http leaf $i - id 40$counter - rate $(( $UPLINK / 3 / $webcount )) kbit ceil $UPLINK kbit" $TC class add dev $NETCARD parent 1:400 classid 1:40$counter htb rate $(( $UPLINK / 3 / $webcount ))kbit ceil $(( $UPLINK ))kbit burst 20k prio 4 echo "#--- ~ sub http $i: sfq" $TC qdisc add dev $NETCARD parent 1:40$counter handle 140$counter: sfq perturb 10 echo "#--- ~ http filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 4 handle 40$counter fw flowid 1:40$counter echo "#--- ~ netfilter rule - $i" $IPT -t mangle -A INPUT -i $NETCARD -p tcp --dport 80 -m string --string "Host: $i" --algo bm -j CONNMARK --set-mark 40$counter done # finally, create the default HTTP class for non classified traffic echo "#---http default leaf - id 499 - rate $(( $UPLINK / 3 / $webcount )) kbit ceil $UPLINK kbit" $TC class add dev $NETCARD parent 1:400 classid 1:499 htb rate $(( $UPLINK / 3 / $webcount ))kbit ceil $(( $UPLINK ))kbit burst 20k prio 4 echo "#--- ~ sub http default leaf: sfq" $TC qdisc add dev $NETCARD parent 1:499 handle 1499: sfq perturb 10 echo "#--- ~ http filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 4 handle 499 fw flowid 1:499 echo "#--- ~ netfilter rule - http default leaf" $IPT -t mangle -A OUTPUT -o $NETCARD -p tcp --tcp-flags SYN,ACK ACK --sport 80 -m connmark --mark 0 -j CONNMARK --set-mark 499 $IPT -t mangle -A OUTPUT -o $NETCARD -p tcp --tcp-flags SYN,ACK ACK --sport 443 -m connmark --mark 0 -j CONNMARK --set-mark 499 echo "#---files xfer - id 500 - rate $(( $UPLINK / 3 )) kbit ceil $UPLINK kbit" $TC class add dev $NETCARD parent 1:1 classid 1:500 htb rate $(( $UPLINK / 3 ))kbit ceil $(( $UPLINK ))kbit burst 2k prio 5 linklayer atm echo "#--- ~ sub files xfer: sfq" $TC qdisc add dev $NETCARD parent 1:500 handle 1500: sfq perturb 10 echo "#--- ~ files xfer filter" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 7 handle 500 fw flowid 1:500 echo "#--- ~ netfilter rule - FTP and everything bigger than 10MB" $IPT -t mangle -A INPUT -i $NETCARD -p tcp --dport 20:21 -j CONNMARK --set-mark 500 $IPT -t mangle -A OUTPUT -o $NETCARD -p tcp -m connbytes --connbytes 10000000: --connbytes-mode bytes --connbytes-dir both -j CONNMARK --set-mark 500 echo "#---default - id 999 - rate $(( $UPLINK / 5 ))kbit ceil $(( $UPLINK ))kbit" $TC class add dev $NETCARD parent 1:1 classid 1:999 htb rate $(( $UPLINK / 5 ))kbit ceil $(( $UPLINK ))kbit burst 2k prio 9 linklayer atm echo "#--- ~ sub default: sfq" $TC qdisc add dev $NETCARD parent 1:999 handle 1999: sfq perturb 10 echo "#--- ~ filtre default" $TC filter add dev $NETCARD parent 1:0 protocol ip prio 99 handle 999 fw flowid 1:999 echo "#--- ~ propagating marks on connections" $IPT -t mangle -A POSTROUTING -j CONNMARK --restore-mark echo "#--- ~ TCP ACKS at 200" $IPT -t mangle -A POSTROUTING -p tcp --tcp-flags URG,ACK,PSH,RST,SYN,FIN ACK -m length --length 40:64 -j MARK --set-mark 200 echo "Default policy: DROP EVERYTHING ELSE" $IPT -N LOGDROP $IPT -A LOGDROP -j LOG --log-prefix "NETFILTER DROP => " --log-level debug $IPT -A LOGDROP -j DROP $IPT -A INPUT -i $NETCARD -j LOGDROP $IPT -A FORWARD -i $NETCARD -j LOGDROP $IPT -A OUTPUT -o $NETCARD -j LOGDROP echo echo "Firewall is up and running" echo ;; stop) $IPT -t nat -F $IPT -t nat -X $IPT -t filter -F $IPT -t filter -X $IPT -t mangle -F $IPT -t mangle -X $TC qdisc del dev $NETCARD root handle 1 exit 0 ;; restart) $0 stop $0 start exit 0 ;; *) echo "usage:$0 {start|stop|restart}" echo "julien vehent - 2011 - julien@linuxwall.info" ;; esac ~~DISCUSSION~~