#!/bin/bash

# ----------------------------------------------------------------------

EXTERNAL_INTERFACE="ppp0"		# External Internet interface

# ----------------------------------------------------------------------
# SSH starts at 1023 and works down to 513 for
# each additional simultaneous incoming connection.
SSH_PORTS="1022:1023"			# SSH privilege ports

FTP_DATA_PORT="20"			# FTP DATA port
FTP_PORT="21"				# FTP port
SSH_PORT="22"				# SSH port
SMTP_PORT="25"				# SMTP port
DNS_PORT="53"				# DNS port
DHCP_PORT="67"				# DHCP port
HTTP_PORT="80"				# HTTP port
POP3_PORT="110"				# POP3 port
NTP_PORT="123"				# NTP port
IMAP_PORT="143"				# IMAP port
HTTPS_PORT="443"			# HTTPS port
SSMTP_PORT="465"			# SSMTP port
IMAPS_PORT="993"			# IMAPS port
POP3S_PORT="995"			# POP3S port
SOCKS_PORT="1080"			# SOCKS port
OPENVPN_PORT="1194"			# OPENVPN port
SQUID_PORT="3128"			# SQUID port
EMULE_PORT="4662"			# EMULE port
WEBCACHE_PORT="8080"			# WEBCACHE port
PROXY_PORT="8118"			# PROXY port
TOR_OR_PORT="9001"			# TOR OR port
TOR_DIR_PORT="9030"			# TOR DIR port
XWINDOW_PORTS="6000:6063"		# XWINDOW ports

# ----------------------------------------------------------------------
# QOS

tc qdisc del dev "$EXTERNAL_INTERFACE" root &>/dev/null

CEIL="512kbit"

tc qdisc add dev "$EXTERNAL_INTERFACE" root handle 1: htb default 106

tc class add dev "$EXTERNAL_INTERFACE" parent 1: classid 1:1 \
	htb rate "${CEIL}" ceil "${CEIL}"

# This is the highest priority class.  The packets in this class will
# have the lowest delay and would get the excess of bandwith first.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:101 \
	htb rate 128kbit ceil 128kbit prio 0

# Here we have the first class in which we can start to put bulk traffic.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:102 \
	htb rate 128kbit ceil "${CEIL}" prio 1

# I will put traffic with Maximize-Throughput TOS bit set and the rest of
# the traffic that goes from local processes on the router to the Internet.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:103 \
	htb rate 24kbit ceil "${CEIL}" prio 2

# This class is for the traffic of other NATed machines that need higher
# priority in their bulk traffic.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:104 \
	htb rate 24kbit ceil "${CEIL}" prio 2

# Here goes mail traffic (SMTP, POP3...) and packets with
# Minimize-Cost TOS bit set.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:105 \
	htb rate 16kbit ceil "${CEIL}" prio 3

# And finally here we have bulk traffic from the NATed machines behind
# the router.  All kazaa, edonkey, and others will go here, in order to
# not interfere with other services.
tc class add dev "$EXTERNAL_INTERFACE" parent 1:1 classid 1:106 \
	htb rate 32kbit ceil "${CEIL}" prio 3

tc qdisc add dev "$EXTERNAL_INTERFACE" parent 1:103 handle 130: sfq perturb 10
tc qdisc add dev "$EXTERNAL_INTERFACE" parent 1:104 handle 140: sfq perturb 10
tc qdisc add dev "$EXTERNAL_INTERFACE" parent 1:105 handle 150: sfq perturb 10
tc qdisc add dev "$EXTERNAL_INTERFACE" parent 1:106 handle 160: sfq perturb 10

tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 1 handle 1 fw classid 1:101
tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 2 handle 2 fw classid 1:102
tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 3 handle 3 fw classid 1:103
tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 4 handle 4 fw classid 1:104
tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 5 handle 5 fw classid 1:105
tc filter add dev "$EXTERNAL_INTERFACE" parent 1:0 protocol ip \
	prio 6 handle 6 fw classid 1:106

# ----------------------------------------------------------------------
# IP MANGLE

MARK_PRIO_1="0x1"
MARK_PRIO_2="0x2"
MARK_PRIO_3="0x3"
MARK_PRIO_4="0x4"
MARK_PRIO_5="0x5"
MARK_PRIO_6="0x6"

# PRIORITY 1

# ICMP
iptables -t mangle -A PREROUTING -p icmp -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A PREROUTING -p icmp -j RETURN
iptables -t mangle -A OUTPUT -p icmp -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p icmp -j RETURN

# TCP Packets with SYN Flag Set
iptables -t mangle -A PREROUTING -p tcp \
	--tcp-flags SYN,RST,FIN,ACK SYN -j MARK --set-mark "$MARK_PRIO_1"
iptables -t mangle -A PREROUTING -p tcp \
	--tcp-flags SYN,RST,FIN,ACK SYN -j RETURN
iptables -t mangle -A OUTPUT -p tcp \
	--tcp-flags SYN,RST,FIN,ACK SYN -j MARK --set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p tcp \
	--tcp-flags SYN,RST,FIN,ACK SYN -j RETURN

# SSH
iptables -t mangle -A PREROUTING -p tcp --sport "$SSH_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A PREROUTING -p tcp --sport "$SSH_PORT" -j RETURN
iptables -t mangle -A PREROUTING -p tcp --dport "$SSH_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A PREROUTING -p tcp --dport "$SSH_PORT" -j RETURN
iptables -t mangle -A OUTPUT -p tcp --sport "$SSH_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p tcp --sport "$SSH_PORT" -j RETURN
iptables -t mangle -A OUTPUT -p tcp --dport "$SSH_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p tcp --dport "$SSH_PORT" -j RETURN

# DNS
iptables -t mangle -A OUTPUT -p udp --dport "$DNS_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p udp --dport "$DNS_PORT" -j RETURN
iptables -t mangle -A OUTPUT -p tcp --dport "$DNS_PORT" -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A OUTPUT -p tcp --dport "$DNS_PORT" -j RETURN

# PRIORITY 2

# HTTP
iptables -t mangle -A PREROUTING -p tcp -m multiport \
	--dports "$HTTP_PORT,$HTTPS_PORT,$SQUID_PORT,$WEBCACHE_PORT" -j MARK \
	--set-mark "$MARK_PRIO_2"
iptables -t mangle -A PREROUTING -p tcp -m multiport \
	--dports "$HTTP_PORT,$HTTPS_PORT,$SQUID_PORT,$WEBCACHE_PORT" -j RETURN

# FTP
iptables -t mangle -A PREROUTING -p tcp --sport "$FTP_PORT" -j MARK \
	--set-mark "$MARK_PRIO_2"
iptables -t mangle -A PREROUTING -p tcp --sport "$FTP_PORT" -j RETURN
iptables -t mangle -A PREROUTING -p tcp --dport "$FTP_PORT" -j MARK \
	--set-mark "$MARK_PRIO_2"
iptables -t mangle -A PREROUTING -p tcp --dport "$FTP_PORT" -j RETURN

# PRIORITY 3

iptables -t mangle -A OUTPUT -j MARK --set-mark "$MARK_PRIO_3"

# PRIORITY 4

# FTP DATA
iptables -t mangle -A PREROUTING -p tcp --sport "$FTP_DATA_PORT" -j MARK \
	--set-mark "$MARK_PRIO_4"
iptables -t mangle -A PREROUTING -p tcp --sport "$FTP_DATA_PORT" -j RETURN
iptables -t mangle -A PREROUTING -p tcp --dport "$FTP_DATA_PORT" -j MARK \
	--set-mark "$MARK_PRIO_4"
iptables -t mangle -A PREROUTING -p tcp --dport "$FTP_DATA_PORT" -j RETURN

# All the UDP Packets for Routing
iptables -t mangle -A PREROUTING -p udp -j MARK --set-mark "$MARK_PRIO_4"
iptables -t mangle -A PREROUTING -p udp -j RETURN

# PRIORITY 5

iptables -t mangle -A PREROUTING -p tcp -m multiport --dports \
	"$SMTP_PORT,$POP3_PORT,$IMAP_PORT,$SSMTP_PORT,$IMAPS_PORT,$POP3S_PORT" \
	-j MARK --set-mark "$MARK_PRIO_5"
iptables -t mangle -A PREROUTING -p tcp -m multiport --dports \
	"$SMTP_PORT,$POP3_PORT,$IMAP_PORT,$SSMTP_PORT,$IMAPS_PORT,$POP3S_PORT" \
	-j RETURN

# Remaining packets are marked according to TOS
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay -j MARK \
	--set-mark "$MARK_PRIO_1"
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Delay -j RETURN
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost -j MARK \
	--set-mark "$MARK_PRIO_5"
iptables -t mangle -A PREROUTING -m tos --tos Minimize-Cost -j RETURN
iptables -t mangle -A PREROUTING -m tos --tos Maximize-Throughput -j MARK \
	--set-mark "$MARK_PRIO_6"
iptables -t mangle -A PREROUTING -m tos --tos Maximize-Throughput -j RETURN

# All remaining packets are PRIORITY 6
iptables -t mangle -A PREROUTING -j MARK --set-mark "$MARK_PRIO_6"

# ----------------------------------------------------------------------
