#!/bin/bash
#
# fwall2: Alex' Firewall Script for Linux 2.4.x
# Copyright (c)2001-2003 by Alexander Barton, licensed under the GNU GPL.
# E-Mail: alex@barton.de, http://www.barton.de/, http://arthur.ath.cx/
#

RELEASE="5-pre5"
RELEASE_DATE="2003-05-02"

# --- Firewall ---

DEBUG=false

WORLD_IFACES=""

LAN_IFACES=""
LAN_NETS=""

SECURE_IFACES="lo"

IN_WORLD_ALLOW_TCP=""
IN_WORLD_ALLOW_UDP=""
IN_WORLD_ALLOW_PROTO=""
OUT_WORLD_ALLOW_TCP=""
OUT_WORLD_ALLOW_UDP=""
OUT_WORLD_ALLOW_PROTO=""
FWD_WORLD_DROP_TCP=""
FWD_WORLD_DROP_UDP=""
FWD_WORLD_REJECT_TCP=""
FWD_WORLD_REJECT_UDP=""

IN_LAN_ALLOW_TCP=""
IN_LAN_ALLOW_UDP=""
IN_LAN_ALLOW_PROTO=""
OUT_LAN_ALLOW_TCP=""
OUT_LAN_ALLOW_UDP=""
OUT_LAN_ALLOW_PROTO=""
FWD_LAN_DROP_TCP=""
FWD_LAN_DROP_UDP=""
FWD_LAN_REJECT_TCP=""
FWD_LAN_REJECT_UDP=""

BLOCK_IPS=""

# --- Masquerading ---

MASQ_IFACES=""
MASQ_NETS=""

# -- Options --

LOGLEVEL="7"
LIMIT="5/minute"

LOG_MARTIANS="yes"

#
# --- Dokumentation / Anmerkung / Hinweise ---
#
# Bisher gibt es hier nur ein paar (kleine) Anmerkungen:
#
# Firewall:
#
# - Alle Pakete (außer auf den SECURE_IFACES) durchlaufen die "Check"-Chain
#   und werden einer allgemeinen Prüfung unterzogen.
# - Pakete, die über Gateways gehen oder kommen werden entsprechend erkannt
#   und in die entsprechende Chain geleitet, die dem Ziel-Netz entspricht,
#   unabhängig vom Netzwerk-Interface, über das sie gehen bzw. kommen.
# - Mit dem Befehl "fwall2.sh block <ip>" kann eine beliebige IP im laufenden
#   Betrieb blockiert werden; Gegenstück: "fwall2.sh unlock <ip>".
#
# Masquerading:
#
# - es werden nur Pakete maskiert, die über eines der MASQ_IFACES den Rechner
#   verlassen und(!) aus einem der MASQ_NETS kommen.
# - wird die Firewall mit "fwall2.sh startmasqonly" wird nur das Masquerading,
#   nicht(!) aber die Firewall gestartet! Das kann nuetzlich sein, ist aber
#   auf jeden Fall auch gefaehrlich! Mit "fwall2.sh status" kann der Zustand
#   jederzeit ermittelt werden.
#

# --- ChangeLog ---
#
# 2003-05-01:
# - added undocumented variables LOGLEVEL and LIMIT to configuration
#   section. Documentation is still missing ...
#
# 2003-04-28:
# - added hooks for /etc/fwall2.local and /etc/fwall2.loca-masq scripts.
#
# 2003-02-24:
# - enhanced test for $rc_done and $rc_failed
# - implemented "debug mode": set $DEBUG to "true" or "false"
#
# 2003-02-04:
# - ip_conntrac_irc und ip_nat_irc in Modul-Liste aufgenommen.
#

#
# Ende des Konfigurations- und Dokumentationsabschnitts. Hier beginnt nun
# das "eigentliche" Script, Änderungen sind ab hier nicht mehr erforderlich.
#

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

NAME="fwall2"

# --- Initialisieren ---

$DEBUG && echo "[DEBUG] Initializing ..."

DefAction="REJECT"
DefActionTxt="Reject"

# versuchen, das ipchains-Modul zu entladen
$DEBUG && echo "[DEBUG] Unloading ipchains kernel module ..."
modprobe -r ipchains > /dev/null 2>&1

# ggf. IP-Tables-Modul laden
$DEBUG && echo "[DEBUG] Probing for iptables kernel module ..."
modprobe -a ip_tables > /dev/null 2>&1

# iptables ok?
$DEBUG && echo "[DEBUG] Testing iptables command ..."
iptables -L -n > /dev/null 2>&1
if [ $? -ne 0 ]; then
	echo -n "Oops, iptables reported error!? "
	echo -e $FAILED
	logger -t $NAME "Oops, iptables reported error!? Aborting."
	echo; exit 1
fi

$DEBUG && echo "[DEBUG] Reading /etc/rc.config ..."
[ -r /etc/rc.config ] && . /etc/rc.config

[ -n "$rc_done" ] && DONE=$rc_done || DONE="Ok."
[ -n "$rc_failed" ] && FAILED=$rc_failed || FAILED="FAILED!"

$DEBUG && echo "[DEBUG] Reading /etc/$NAME.conf ..."
[ -r /etc/$NAME.conf ] && . /etc/$NAME.conf

[ -z "$LOGLEVEL" ] && LOGLEVEL="7"
[ -z "$LIMIT" ] && LIMIT="5/minute"

MODULES="$MODULES \
 ip_conntrack ip_conntrack_ftp ip_conntrack_irc \
 iptable_nat ip_nat_ftp ip_nat_irc \
 ipt_LOG ipt_REJECT ipt_MASQUERADE"

export PATH="/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin"

# --- Funktionen ---

About( )
{
	$DEBUG && echo "[DEBUG] About() called ..."
	echo "$NAME, Alex' Firewall script (Release $RELEASE, $RELEASE_DATE)"
	echo "Copyright (c)2001,2002 by Alexander Barton, licensed under the GNU GPL."
	[ "$LOGHELLO" -ne 0 ] && logger -t $NAME "Alex' Firewall script (Release $RELEASE, $RELEASE_DATE)"
}

Init( )
{
	$DEBUG && echo "[DEBUG] Init() called ..."
	# Kernel-Module laden
	echo -n "- Initializing Kernel ... "
	test -n "$MODULES" && modprobe -a $MODULES > /dev/null 2>&1 || true
	if [ $? -ne 0 ]; then
		echo -e $FAILED
		exit 1
	fi
	# Kernel-Option "Always Defragment" einschalten
	test -f /proc/sys/net/ipv4/ip_always_defrag && echo 1 > /proc/sys/net/ipv4/ip_always_defrag
	# TCP SYN-Cookies einschalten
	test -f /proc/sys/net/ipv4/tcp_syncookies && echo 1 > /proc/sys/net/ipv4/tcp_syncookies
	# ICMP Echo-Broadcast verwerfen
	test -f /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts && echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
	# Gefährliche ICMP-Fehlermeldungen verwerfen
	test -f /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses && echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
	# Source Address Verification einschalten
	for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done
	# ICMP Redirect verwerfen
	for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f; done
	# Source Routed Packets verwerfen
	for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f; done
	# Spoofed Packets, Source Routed Packets und Redirect Packets loggen
	if [ "$LOG_MARTIANS" != "no" ]; then
		for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo 1 > $f; done
	else
		for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo 0 > $f; done
	fi
	# IP Forwarding einschalten
	test -f /proc/sys/net/ipv4/ip_forward && echo 1 > /proc/sys/net/ipv4/ip_forward
	echo -e $DONE
}

Start_Fwall( )
{
	$DEBUG \
	  && echo "[DEBUG] Start_Fwall() called ..." \
	  || echo -n "- Initializing Firewall ... "

	iptables -N Check
	iptables -N CheckBlock

	iptables -N In-World
	iptables -N Out-World
	iptables -N In-Lan
	iptables -N Out-Lan

	iptables -N Fwd-World
	iptables -N Fwd-Lan

	iptables -N In-Gate
	iptables -N Out-Gate

	# "Check-Chain" einhängen
	iptables -I In-World -j Check
	iptables -I Out-World -j Check
	iptables -I In-Lan -j Check
	iptables -I Out-Lan -j Check
	iptables -I Fwd-World -j Check
	iptables -I Fwd-Lan -j Check
	iptables -I In-Gate -j Check
	iptables -I Out-Gate -j Check

	# -- CheckBlock --

	$DEBUG && echo "[DEBUG]  - CheckBlock"
	for i in $BLOCK_IPS; do
	  iptables -A CheckBlock -s $i -j DROP
	  iptables -A CheckBlock -d $i -j DROP
	done

	# Default: Return
	iptables -A CheckBlock -j RETURN
	
	# -- Check --
	
	# Diese Chain wird von jedem Paket durchlaufen, welches durch ein
	# "legales" Interface (World, Local, ...) empfangen, gesendet oder
	# geforwarded wird.

	$DEBUG && echo "[DEBUG]  - Check"

	# zunaechst pruefen, ob IP blockiert
	iptables -A Check -j CheckBlock
	
	# Fragmente verwerfen (-> "always defragment" ist schließlich an!)
	iptables -A Check --fragment -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Fragment: "
	iptables -A Check --fragment -j DROP

	# Packete einer "ungültigen" Verbindung verwerfen
	#iptables -A Check -m state --state INVALID -m limit \
	# --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Invalid Packet: "
	#iptables -A Check -m state --state INVALID -j DROP
	
	# "unsaubere" Pakete verwerfen (Achtung: buggy in Kernel 2.4.[67]!)
	#iptables -A Check -m unclean -m limit \
	# --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Unclean Packet: "
	#iptables -A Check -m unclean -j DROP
	
	# FIN+URG+PSH ("XMAS-Scan")
	iptables -A Check -p tcp --tcp-flags ALL FIN,URG,PSH -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "XMAS Flags: "
	iptables -A Check -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
	
	# SYN+RST
	iptables -A Check -p tcp --tcp-flags SYN,RST SYN,RST -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "SYN+RST Flag: "
	iptables -A Check -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

	# SYN+FIN
	iptables -A Check -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "SYN+FIN Flag: "
	iptables -A Check -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
	
	# TCP-Options checken
	iptables -A Check -p tcp --tcp-option 64 -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Bogus TCP Option: "
	iptables -A Check -p tcp --tcp-option 64 -j DROP
	iptables -A Check -p tcp --tcp-option 128 -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Bogus TCP Option: "
	iptables -A Check -p tcp --tcp-option 128 -j DROP
	
	# Pakete, die zu einer aufgebauten Verbindung gehören, erlauben
	iptables -A Check -m state --state ESTABLISHED,RELATED -j ACCEPT

	# ICMP pauschal erlauben
	iptables -A Check -p icmp -j ACCEPT

	# Return-Regel
	iptables -A Check -j RETURN
	
	# -- In-World --

	$DEBUG && echo "[DEBUG]  - In-World"

	# Generische Port-Regeln
	for port in $IN_WORLD_ALLOW_TCP; do
		iptables -A In-World -p tcp --dport $port -j ACCEPT
	done
	for port in $IN_WORLD_ALLOW_UDP; do
		iptables -A In-World -p udp --dport $port -j ACCEPT
	done

	for proto in $IN_WORLD_ALLOW_PROTO; do
		iptables -A In-World -p $proto -j ACCEPT
	done

	# Default-Regel
	iptables -A In-World -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "$DefActionTxt In-World: "
	iptables -A In-World -j $DefAction
	
	# -- In-Lan --

	$DEBUG && echo "[DEBUG]  - In-Lan"

	# Generische Port-Regeln
	for port in $IN_LAN_ALLOW_TCP; do
		iptables -A In-Lan -p tcp --dport $port -j ACCEPT
	done
	for port in $IN_LAN_ALLOW_UDP; do
		iptables -A In-Lan -p udp --dport $port -j ACCEPT
	done

	for proto in $IN_LAN_ALLOW_PROTO; do
		iptables -A In-Lan -p $proto -j ACCEPT
	done

	# Default-Regel
	iptables -A In-Lan -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "$DefActionTxt In-Lan: "
	iptables -A In-Lan -j $DefAction
	
	# -- Out-World --

	$DEBUG && echo "[DEBUG]  - Out-World"

	# Generische Port-Regeln
	for port in $OUT_WORLD_ALLOW_TCP; do
		iptables -A Out-World -p tcp --dport $port -j ACCEPT
	done
	for port in $OUT_WORLD_ALLOW_UDP; do
		iptables -A Out-World -p udp --dport $port -j ACCEPT
	done

	for proto in $OUT_WORLD_ALLOW_PROTO; do
		iptables -A Out-World -p $proto -j ACCEPT
	done

	# Default-Regel
	iptables -A Out-World -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "$DefActionTxt Out-World: "
	iptables -A Out-World -j $DefAction
	
	# -- Out-Lan --

	$DEBUG && echo "[DEBUG]  - Out-Lan"

	# Generische Port-Regeln
	for port in $OUT_LAN_ALLOW_TCP; do
		iptables -A Out-Lan -p tcp --dport $port -j ACCEPT
	done
	for port in $OUT_LAN_ALLOW_UDP; do
		iptables -A Out-Lan -p udp --dport $port -j ACCEPT
	done

	for proto in $OUT_LAN_ALLOW_PROTO; do
		iptables -A Out-Lan -p $proto -j ACCEPT
	done
	
	# Default-Regel
	iptables -A Out-Lan -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "$DefActionTxt Out-Lan: "
	iptables -A Out-Lan -j $DefAction
	
	# -- Fwd-World --

	$DEBUG && echo "[DEBUG]  - Fwd-World"
	
	# Dises Chain durchläuft jewes geforwardede Paket in die weite Welt.
	# In dieser Chain wird nur explizit gefiltert! Der Default ist RETURN.
	
	# Generische Port-Regeln
	for port in $FWD_WORLD_DROP_TCP; do
		iptables -A Fwd-World -p tcp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Fwd-World: "
		iptables -A Fwd-World -p tcp --dport $port -j DROP
	done
	for port in $FWD_WORLD_DROP_UDP; do
		iptables -A Fwd-World -p udp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Fwd-World: "
		iptables -A Fwd-World -p udp --dport $port -j DROP
	done
	for port in $FWD_WORLD_REJECT_TCP; do
		iptables -A Fwd-World -p tcp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Reject Fwd-World: "
		iptables -A Fwd-World -p tcp --dport $port -j REJECT --reject-with tcp-reset
	done
	for port in $FWD_WORLD_REJECT_UDP; do
		iptables -A Fwd-World -p udp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Reject Fwd-World: "
		iptables -A Fwd-World -p udp --dport $port -j REJECT
	done

	# Default ACCEPT-Regel
	iptables -A Fwd-World -j ACCEPT

	# -- Fwd-Lan --

	$DEBUG && echo "[DEBUG]  - Fwd-Lan"
	
	# Dises Chain durchläuft jewes geforwardede Paket in die weite Welt.
	# In dieser Chain wird nur explizit gefiltert! Der Default ist RETURN.

	# Generische Port-Regeln
	for port in $FWD_LAN_DROP_TCP; do
		iptables -A Fwd-Lan -p tcp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Fwd-Lan: "
		iptables -A Fwd-Lan -p tcp --dport $port -j DROP
	done
	for port in $FWD_LAN_DROP_UDP; do
		iptables -A Fwd-Lan -p udp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Fwd-Lan: "
		iptables -A Fwd-Lan -p udp --dport $port -j DROP
	done
	for port in $FWD_LAN_REJECT_TCP; do
		iptables -A Fwd-Lan -p tcp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Reject Fwd-Lan: "
		iptables -A Fwd-Lan -p tcp --dport $port -j REJECT --reject-with tcp-reset
	done
	for port in $FWD_LAN_REJECT_UDP; do
		iptables -A Fwd-Lan -p udp --dport $port -m limit \
		  --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Reject Fwd-Lan: "
		iptables -A Fwd-Lan -p udp --dport $port -j REJECT
	done
	
	# Default ACCEPT-Regel
	iptables -A Fwd-Lan -j ACCEPT

	# -- In-Gate --

	$DEBUG && echo "[DEBUG]  - In-Gate"

	# Pakete in dieser Chain kommen zwar über ein lokales Interface,
	# stammen aber nicht aus dem LAN. Sie kamen also über ein Gate.

	# LAN Gate?
	for net in $LAN_NETS; do
		iptables -A In-Gate --src $net -j In-Lan
	done

	# Default: World Gate
	iptables -A In-Gate -j In-World

	# -- Out-Gate --

	$DEBUG && echo "[DEBUG]  - Out-Gate"

	# Pakete in dieser Chain gehen zwar auf ein lokales Interface, sind
	# aber nicht für das LAN bestimmt. Sie sollen also zu einem Gate.

	# LAN Gate?
	for net in $LAN_NETS; do
		iptables -A Out-Gate --dst $net -j Out-Lan
	done

	# Default: World Gate
	iptables -A Out-Gate -j Out-World
	
	# -- Haupt-Chains: Input & Output --

	$DEBUG && echo "[DEBUG]  - Input & Output"

	# World-Interfaces einhängen
	for iface in $WORLD_IFACES; do
		iptables -A INPUT -i $iface -j In-World
		iptables -A OUTPUT -o $iface -j Out-World
	done
	
	# Lokale-Interfaces einhängen
	for iface in $LAN_IFACES; do
		for net in $LAN_NETS; do
			iptables -A INPUT -i $iface --src $net -j In-Lan
			iptables -A OUTPUT -o $iface --dst $net -j Out-Lan
		done
		# Broadcasts
		iptables -A INPUT -i $iface --src 0.0.0.0 -j In-Lan
		iptables -A OUTPUT -o $iface --dst 255.255.255.255 -j Out-Lan
		# Geroutete Pakete
		iptables -A INPUT -i $iface -j In-Gate
		iptables -A OUTPUT -o $iface -j Out-Gate
	done

	# auf sicheren Interfaces ist alles erlaubt :-)
	for iface in $SECURE_IFACES; do
		iptables -A INPUT -i $iface -j ACCEPT
		iptables -A OUTPUT -o $iface -j ACCEPT
	done

	# Generische LOG- und DROP-Regeln für Input und Output
	# (die Default-Policies der Chains ist somit an sich überflüssig)
	iptables -A INPUT -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop In-Unknown: "
	iptables -A INPUT -j DROP
	iptables -A OUTPUT -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Out-Unknown: "
	iptables -A OUTPUT -j DROP

	# -- Haupt-Chains: Forward --

	$DEBUG && echo "[DEBUG]  - Forward"
	
	# Forward-Filter
	for iface in $WORLD_IFACES; do
		iptables -A FORWARD -o $iface -j Fwd-World
	done
	for iface in $LAN_IFACES; do
		iptables -A FORWARD -o $iface -j Fwd-Lan
	done

	# Generische LOG- und DROP-Regeln für Forward
	# (die Default-Policies der Chains ist somit ansich überflüssig)
	iptables -A FORWARD -m limit \
	 --limit $LIMIT -j LOG --log-level $LOGLEVEL --log-prefix "Drop Fwd-Unknown: "
	iptables -A FORWARD -j DROP

	logger -t $NAME "Firewall started."

	$DEBUG \
	  && echo "[DEBUG] Start_Fwall() done." \
	  || echo -e $DONE

	[ -r /etc/fwall2.local ] && . /etc/fwall2.local
}

Start_Masq( )
{
	if [ -n "$MASQ_IFACES" ]; then
		$DEBUG \
		  && echo "[DEBUG] Start_Masq() called ..." \
		  || echo -n "- Setting up Masquerading ... "
		for iface in $MASQ_IFACES; do
			for net in $MASQ_NETS; do
				iptables -t nat -A POSTROUTING -s $net -o $iface -j MASQUERADE
			done
		done
		logger -t $NAME "Masquerading started."
		$DEBUG \
		  && echo "[DEBUG] Start_Masq() done." \
		  || echo -e $DONE
	fi

	[ -r /etc/fwall2.local-masq ] && . /etc/fwall2.local-masq
}

Stop_Fwall( )
{
	$DEBUG \
	  && echo "[DEBUG] Stop_Fwall() called ..." \
	  || echo -n "- Stopping Firewall ... "
	iptables -F
	iptables -X
	logger -t $NAME "Firewall stopped."
	$DEBUG \
	  && echo "[DEBUG] Stop_Fwall() done." \
	  || echo -e $DONE
}

Stop_Masq( )
{
	$DEBUG \
	  && echo "[DEBUG] Stop_Masq() called ..." \
	  || echo -n "- Stopping Masquerading ... "
	iptables -t nat -F
	iptables -t nat -X
	logger -t $NAME "Masquerading stopped."
	$DEBUG \
	  && echo "[DEBUG] Stop_Masq() done." \
	  || echo -e $DONE
}

Set_Default_Policies( )
{
	$DEBUG && echo "[DEBUG] Set_Default_Policies() called ..."
	iptables -P INPUT $1
	iptables -P FORWARD $1
	iptables -P OUTPUT $1
	$DEBUG && echo "[DEBUG] Set_Default_Policies() done."
}

Check_Running( )
{
	$DEBUG && echo "[DEBUG] Check_Running() called ..."
	iptables -L -n | grep "In-World" > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		echo "Oops, fwall2 not active?"; echo
		exit 1
	fi
	$DEBUG && echo "[DEBUG] Check_Running() done."
}

Check_Not_Running( )
{
	$DEBUG && echo "[DEBUG] Check_Not_Running() called ..."
	iptables -L -n | grep "In-World" > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "Oops, fwall2 already active?"; echo
		exit 1
	fi
	$DEBUG && echo "[DEBUG] Check_Not_Running() done."
}

Do_Start( )
{
	$DEBUG && echo "[DEBUG] Do_Start() called ..."
	Check_Not_Running
	Set_Default_Policies DROP
	Init
	Start_Fwall
	Start_Masq
	$DEBUG && echo "[DEBUG] Do_Start() done."
}

Do_Stop( )
{
	$DEBUG && echo "[DEBUG] Do_Stop() called."
	Check_Running
	Set_Default_Policies DROP
	Stop_Masq
	Stop_Fwall
	$DEBUG && echo "[DEBUG] Do_Stop() done."
}

Do_Reload( )
{
	$DEBUG && echo "[DEBUG] Do_Reload() called ..."
	Check_Running
	Set_Default_Policies ACCEPT
	Stop_Masq
	Stop_Fwall
	Init
	Start_Fwall
	Start_Masq
	Set_Default_Policies DROP
	$DEBUG && echo "[DEBUG] Do_Reload() done."
}

Do_Masqonly_Start( )
{
	$DEBUG && echo "[DEBUG] Do_Masqonly_Start() called ..."
	Check_Running
	logger -t $NAME "Switching to masquerading-only mode ..."
	Set_Default_Policies ACCEPT
	Stop_Fwall
	$DEBUG && echo "[DEBUG] Do_Masqonly_Start() done."
}

Do_Masqonly_End( )
{
	$DEBUG && echo "[DEBUG] Do_Masqonly_End() called ..."
	Check_Not_Running
	logger -t $NAME "Switching to full firewall mode ..."
	Set_Default_Policies ACCEPT
	Start_Fwall
	Set_Default_Policies DROP
	$DEBUG && echo "[DEBUG] Do_Masqonly_End() done."
}

Do_Status( )
{
	# Exit-Status:
	#  10: Firewall und Masquerading laufen nicht;
	#  11: Alles (Firewall und Masquerading) ist aktiv;
	#  12: Nur das Masquerading ist aktiv, die Firewall nicht.

	echo -n "$NAME: "
	iptables -L -n | grep "In-World" > /dev/null 2>&1
	if [ $? -eq 0 ]; then
	  echo "Firewall up and running."; exit 11
	else
	  iptables -t nat -L -n | grep "MASQUERADE" > /dev/null 2>&1
	  if [ $? -eq 0 ]; then
	    echo "Masquerading only."; exit 12
	  else
	    echo "Not active."; exit 10
	  fi
	fi
}

LOGHELLO=0
case "$1" in
	--start|start)
		LOGHELLO=1
		echo; About
		Do_Start
		echo
		;;
	--stop|stop)
		LOGHELLO=1
		echo; About
		Do_Stop
		echo
		;;
	--startmasqonly|startmasqonly|--masqonly|masqonly|--masq|masq)
		LOGHELLO=1
		echo; About
		Do_Masqonly_Start
		echo
		;;
	--stopmasqonly|stopmasqonly)
		LOGHELLO=1
		echo; About
		Do_Masqonly_End
		echo
		;;
	--block|block)
		if [ "$2" ]; then
		  iptables -I CheckBlock -s $2 -j DROP > /dev/null 2>&1
		  iptables -I CheckBlock -d $2 -j DROP > /dev/null 2>&1
		  if [ $? -eq 0 ]; then
		    echo "$NAME: blocked \"$2\"."
		    logger -t $NAME "blocked \"$2\"."
		  else
		    echo "$NAME: can't block \"$2\"!?"
		    logger -t $NAME "can't block \"$2\"!?"
 		  fi
		else
		  echo "Usage: $name block <ip>"
		fi
		;;
	--unblock|unblock)
		if [ "$2" ]; then
		  iptables -D CheckBlock -s $2 -j DROP > /dev/null 2>&1
		  iptables -D CheckBlock -d $2 -j DROP > /dev/null 2>&1
		  if [ $? -eq 0 ]; then
		    echo "$NAME: unblocked $2."
		    logger -t $NAME "unblocked \"$2\"."
		  else
		    echo "$NAME: can't unblock $2!?"
		    logger -t $NAME "can't unblock \"$2\"!?"
		  fi
		else
		  echo "Usage: $name block <ip>"
		fi
		;;
	--reload|reload)
		LOGHELLO=1
		echo; About
		Do_Reload
		echo
		;;
	--restart|restart)
		LOGHELLO=1
		echo; About
		tty | grep "p" > /dev/null 2>&1
		if [ $? -ne 0 ]; then
			Do_Stop; Do_Start
		else
			echo;
			echo "ERROR: Can't restart firewall if terminal is not local!"
			logger -t $NAME "Can't restart firewall: terminal is not local!"
		fi
		echo
		;;
	--status|status)
		Do_Status
		;;
	--list|list|-L)
		iptables -L -n -v | less
		;;
	--version)
		About
		;;
	--help|*)
		echo; About; echo
		echo "Usage: $name {start|stop|reload|restart}"
		echo "       $name {startmasqonly|stopmasqonly}"
		echo "       $name {block|unblock} <ip>"
		echo "       $name {status|list}"
		echo; exit 2
		;;
esac

exit 0

# -eof-
