#!/bin/sh # # Shorewall Lite Packet Filtering Firewall Control Program - V4.4 # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 2006,2007,2008,2009,2010,2011 - Tom Eastep (teastep@shorewall.net) # # This file should be placed in /sbin/shorewall-lite. # # Shorewall documentation is available at http://shorewall.net # # This program is free software; you can redistribute it and/or modify # it under the terms of Version 2 of the GNU General Public License # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # If an error occurs while starting or restarting the firewall, the # firewall is automatically stopped. # # Set the configuration variables from shorewall-lite.conf # get_config() { [ -n "$PATH" ] || PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin [ -z "$LOGFILE" ] && LOGFILE=/var/log/messages if ( ps ax 2> /dev/null | grep -v grep | qt grep 'syslogd.*-C' ) ; then g_logread="logread | tac" elif [ -r $LOGFILE ]; then g_logread="tac $LOGFILE" else echo "LOGFILE ($LOGFILE) does not exist!" >&2 exit 2 fi # # See if we have a real version of "tail" -- use separate redirection so # that ash (aka /bin/sh on LRP) doesn't crap # if ( tail -n5 /dev/null > /dev/null 2> /dev/null ) ; then realtail="Yes" else realtail="" fi [ -n "$FW" ] || FW=fw if [ $g_family -eq 4 ]; then if [ -n "$IPTABLES" ]; then if [ ! -x "$IPTABLES" ]; then echo " ERROR: The program specified in IPTABLES does not exist or is not executable" >&2 exit 2 fi else IPTABLES=$(mywhich iptables 2> /dev/null) if [ -z "$IPTABLES" ] ; then echo " ERROR: Can't find iptables executable" >&2 exit 2 fi fi g_tool=$IPTABLES else if [ -n "$IP6TABLES" ]; then if [ ! -x "$IP6TABLES" ]; then echo " ERROR: The program specified in IP6TABLES does not exist or is not executable" >&2 exit 2 fi else IP6TABLES=$(mywhich ip6tables 2> /dev/null) if [ -z "$IP6TABLES" ] ; then echo " ERROR: Can't find ip6tables executable" >&2 exit 2 fi fi g_tool=$IP6TABLES fi if [ -n "$SHOREWALL_SHELL" ]; then if [ ! -x "$SHOREWALL_SHELL" ]; then echo " WARNING: The program specified in SHOREWALL_SHELL does not exist or is not executable; falling back to /bin/sh" >&2 SHOREWALL_SHELL=/bin/sh fi fi [ -n "$RESTOREFILE" ] || RESTOREFILE=restore validate_restorefile RESTOREFILE [ -n "${VERBOSITY:=2}" ] [ -n "$g_use_verbosity" ] && VERBOSITY=$g_use_verbosity || VERBOSITY=$(($g_verbose_offset + $VERBOSITY)) if [ $VERBOSITY -lt -1 ]; then VERBOSITY=-1 elif [ $VERBOSITY -gt 2 ]; then VERBOSITY=2 fi g_hostname=$(hostname 2> /dev/null) IP=$(mywhich ip 2> /dev/null) if [ -z "$IP" ] ; then echo " ERROR: Can't find ip executable" >&2 exit 2 fi IPSET=ipset TC=tc } # # Verify that we have a compiled firewall script # verify_firewall_script() { if [ ! -f $g_firewall ]; then echo " ERROR: $g_product is not properly installed" >&2 if [ -L $g_firewall ]; then echo " $g_firewall is a symbolic link to a" >&2 echo " non-existant file" >&2 else echo " The file $g_firewall does not exist" >&2 fi exit 2 fi } # # Fatal error # startup_error() { echo " ERROR: $@" >&2 kill $$ exit 1 } # # Start Command Executor # start_command() { local finished finished=0 do_it() { local rc rc=0 [ -n "$nolock" ] || mutex_on if [ -x ${LITEDIR}/firewall ]; then run_it ${LITEDIR}/firewall $debugging start rc=$? else error_message "${LITEDIR}/firewall is missing or is not executable" logger -p kern.err "ERROR:$g_product start failed" rc=2 fi [ -n "$nolock" ] || mutex_off exit $rc } verify_firewall_script if product_is_started; then if [ $g_family -eq 4 ]; then error_message "Shorewall is already running" else error_message "Shorewall6 is already running" fi exit 0 fi while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; f*) g_fast=Yes option=${option#f} ;; p*) [ -n "$(which conntrack)" ] || fatal_error "The '-p' option requires the conntrack utility which does not appear to be installed on this system" g_purge=Yes option=${option%p} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; *) usage 1 ;; esac if [ -n "$g_fast" ]; then if qt mywhich make; then export RESTOREFILE make -qf ${CONFDIR}/Makefile || g_fast= fi if [ -n "$g_fast" ]; then g_restorepath=${VARDIR}/$RESTOREFILE if [ -x $g_restorepath ]; then echo Restoring $g_product... run_it $g_restorepath restore date > ${VARDIR}/restarted progress_message3 $g_product restored from $g_restorepath else do_it fi else do_it fi else do_it fi } # # Restart Command Executor # restart_command() { local finished finished=0 local rc rc=0 verify_firewall_script while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; n*) g_noroutes=Yes option=${option#n} ;; p*) [ -n "$(which conntrack)" ] || fatal_error "The '-p' option requires the conntrack utility which does not appear to be installed on this system" g_purge=Yes option=${option%p} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; *) usage 1 ;; esac [ -n "$nolock" ] || mutex_on if [ -x ${LITEDIR}/firewall ]; then run_it ${LITEDIR}/firewall $debugging restart rc=$? else error_message "${LITEDIR}/firewall is missing or is not executable" logger -p kern.err "ERROR:$g_product restart failed" rc=2 fi [ -n "$nolock" ] || mutex_off return $rc } # # Give Usage Information # usage() # $1 = exit status { echo "Usage: $(basename $0) [debug|trace] [nolock] [ -q ] [ -v[-1|{0-2}] ] [ -t ] " echo "where is one of:" echo " add [:] ... " echo " allow
..." echo " clear" echo " delete [:] ... " echo " disable " echo " drop
..." echo " dump [ -x ]" echo " enable " echo " forget [ ]" echo " help" if [ $g_family -eq 4 ]; then echo " ipcalc {
/ |
}" echo " ipdecimal {
| }" echo " iprange
-
" fi echo " logdrop
..." echo " logreject
..." echo " logwatch []" echo " reject
..." echo " reset [ ... ]" echo " restart [ -n ] [ -p ] [ -f ] [ ]" echo " restore [ -n ] [ ]" echo " save [ ]" echo " show [ -x ] [ -t {filter|mangle|nat} ] [ {chain [ [ ... ]" echo " show [ -f ] capabilities" echo " show classifiers" echo " show config" echo " show connections" echo " show filters" echo " show ip" echo " show [ -m ] log []" echo " show [ -x ] mangle|nat|raw|rawpost|routing" echo " show policies" echo " show tc [ device ]" echo " show vardir" echo " show zones" echo " start [ -f ] [ -p ] [ ]" echo " stop" echo " status" echo " version [ -a ]" echo exit $1 } version_command() { local finished finished=0 local all all= local product while [ $finished -eq 0 -a $# -gt 0 ]; do option=$1 case $option in -*) option=${option#-} while [ -n "$option" ]; do case $option in -) finished=1 option= ;; a*) all=Yes option=${option#a} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ $# -gt 0 ] && usage 1 echo $SHOREWALL_VERSION if [ -n "$all" ]; then for product in shorewall shorewall6 shorewall-lite shorewall6-lite shorewall-init; do if [ $product != $g_program ] && [ -f /usr/share/$product/version ]; then echo "$product: $(cat /usr/share/$product/version)" fi done fi } # # Execution begins here # debugging= if [ $# -gt 0 ] && [ "$1" = "debug" -o "$1" = "trace" ]; then debugging=$1 shift fi nolock= if [ $# -gt 0 ] && [ "$1" = "nolock" ]; then nolock=nolock shift fi g_ipt_options="-nv" g_fast= g_verbose_offset=0 g_use_verbosity= g_noroutes= g_timestamp= g_recovering= g_purge= g_logread= g_program=$(basename $0) if [ $g_program = shorewall6-lite ]; then SHAREDIR=/usr/share/shorewall6-lite CONFDIR=/etc/shorewall6-lite g_product="Shorewall6 Lite" g_family=6 g_base=shorewall6 g_tool=ip6tables g_basedir=/usr/share/shorewall6-lite else g_program=shorewall-lite SHAREDIR=/usr/share/shorewall-lite CONFDIR=/etc/shorewall-lite g_product="Shorewall Lite" g_family=4 g_base=shorewall g_tool=iptables g_basedir=/usr/share/shorewall-lite fi # # Make sure that these variables are cleared # VERBOSE= VERBOSITY= finished=0 while [ $finished -eq 0 ]; do [ $# -eq 0 ] && usage 1 option=$1 case $option in -) finished=1 ;; -*) option=${option#-} [ -z "$option" ] && usage 1 while [ -n "$option" ]; do case $option in x*) g_ipt_options="-xnv" option=${option#x} ;; q*) g_verbose_offset=$(($g_verbose_offset - 1 )) option=${option#q} ;; f*) g_fast=Yes option=${option#f} ;; v*) option=${option#v} case $option in -1*) g_use_verbosity=-1 option=${option#-1} ;; 0*) g_use_verbosity=0 option=${option#0} ;; 1*) g_use_verbosity=1 option=${option#1} ;; 2*) g_use_verbosity=2 option=${option#2} ;; *) g_verbose_offset=$(($g_verbose_offset + 1 )) g_use_verbosity= ;; esac ;; n*) g_noroutes=Yes option=${option#n} ;; t*) g_timestamp=Yes option=${option#t} ;; -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done if [ $# -eq 0 ]; then usage 1 fi PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin MUTEX_TIMEOUT= g_libexec=share [ -f ${CONFDIR}/vardir ] && . ${CONFDIR}/vardir ] [ -n "${VARDIR:=/var/lib/${g_base}-lite}" ] [ -d $VARDIR ] || mkdir -p $VARDIR || fatal_error "Unable to create $VARDIR" version_file=$SHAREDIR/version for library in base cli; do . ${SHAREDIR}/lib.$library done ensure_config_path config=$(find_file ${g_base}-lite.conf) if [ -f $config ]; then if [ -r $config ]; then . $config else echo "Cannot read $config! (Hint: Are you root?)" >&2 exit 1 fi else echo "$config does not exist!" >&2 exit 2 fi ensure_config_path LITEDIR=${VARDIR} [ -f ${LITEDIR}/firewall.conf ] && . ${LITEDIR}/firewall.conf get_config g_firewall=$LITEDIR/firewall if [ -f $version_file ]; then SHOREWALL_VERSION=$(cat $version_file) else echo " ERROR: $g_product is not properly installed" >&2 echo " The file $version_file does not exist" >&2 exit 1 fi banner="$g_product $SHOREWALL_VERSION Status at $g_hostname -" case $(echo -e) in -e*) RING_BELL="echo \a" ECHO_E="echo" ;; *) RING_BELL="echo -e \a" ECHO_E="echo -e" ;; esac case $(echo -n "Testing") in -n*) ECHO_N= ;; *) ECHO_N=-n ;; esac COMMAND=$1 case "$COMMAND" in start) shift start_command $@ ;; stop|reset|clear) [ $# -ne 1 ] && usage 1 verify_firewall_script [ -n "$nolock" ] || mutex_on run_it $g_firewall $debugging $COMMAND [ -n "$nolock" ] || mutex_off ;; restart) shift restart_command $@ ;; show|list) shift show_command $@ ;; status) [ $# -eq 1 ] || usage 1 [ "$(id -u)" != 0 ] && fatal_error "The status command may only be run by root" echo "$g_product $SHOREWALL_VERSION Status at $g_hostname - $(date)" echo if product_is_started ; then echo "$g_product is running" status=0 else echo "$g_product is stopped" status=4 fi if [ -f ${VARDIR}/state ]; then state="$(cat ${VARDIR}/state)" case $state in Stopped*|Closed*|Clear*) status=3 ;; esac else state=Unknown fi echo "State:$state" echo exit $status ;; dump) shift dump_command $@ ;; hits) [ -n "$debugging" ] && set -x shift hits_command $@ ;; version) shift version_command $@ ;; logwatch) logwatch_command $@ ;; drop) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then [ -n "$nolock" ] || mutex_on block DROP Dropped $* [ -n "$nolock" ] || mutex_off else error_message "ERROR: $g_product is not started" exit 2 fi ;; logdrop) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then [ -n "$nolock" ] || mutex_on block logdrop Dropped $* [ -n "$nolock" ] || mutex_off else error_message "ERROR: $g_product is not started" exit 2 fi ;; reject|logreject) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if product_is_started ; then [ -n "$nolock" ] || mutex_on block $COMMAND Rejected $* [ -n "$nolock" ] || mutex_off else error_message "ERROR: $g_product is not started" exit 2 fi ;; allow) allow_command $@ ;; add) get_config shift add_command $@ ;; delete) get_config shift add_command $@ ;; disable|enable) get_config Yes if product_is_started; then run_it ${VARDIR}/firewall $g_debugging $@ else fatal_error "Shorewall is not running" fi ;; save) [ -n "$debugging" ] && set -x case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac g_restorepath=${VARDIR}/$RESTOREFILE [ "$nolock" ] || mutex_on save_config [ "$nolock" ] || mutex_off ;; forget) case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac g_restorepath=${VARDIR}/$RESTOREFILE if [ -x $g_restorepath ]; then rm -f $g_restorepath rm -f ${g_restorepath}-iptables rm -f ${g_restorepath}-ipsets echo " $g_restorepath removed" elif [ -f $g_restorepath ]; then echo " $g_restorepath exists and is not a saved Shorewall configuration" fi rm -f ${VARDIR}/save ;; ipcalc) [ -n "$debugging" ] && set -x if [ $# -eq 2 ]; then address=${2%/*} vlsm=${2#*/} elif [ $# -eq 3 ]; then address=$2 vlsm=$(ip_vlsm $3) else usage 1 fi valid_address $address || fatal_error "Invalid IP address: $address" [ -z "$vlsm" ] && exit 2 [ "x$address" = "x$vlsm" ] && usage 2 [ $vlsm -gt 32 ] && echo "Invalid VLSM: /$vlsm" >&2 && exit 2 address=$address/$vlsm echo " CIDR=$address" temp=$(ip_netmask $address); echo " NETMASK=$(encodeaddr $temp)" temp=$(ip_network $address); echo " NETWORK=$temp" temp=$(broadcastaddress $address); echo " BROADCAST=$temp" ;; iprange) [ -n "$g_debugging" ] && set -x range='' while [ $# -gt 0 ]; do shift range="${range}${1}" done case $range in *.*.*.*-*.*.*.*) for address in ${range%-*} ${range#*-}; do valid_address $address || fatal_error "Invalid IP address: $address" done ip_range $range ;; *) usage 1 ;; esac ;; ipdecimal) [ -n "$debugging" ] && set -x [ $# -eq 2 ] || usage 1 case $2 in *.*.*.*) valid_address $2 || fatal_error "Invalid IP address: $2" echo " $(decodeaddr $2)" ;; *) echo " $(encodeaddr $2)" ;; esac ;; restore) shift STARTUP_ENABLED=Yes restore_command $@ ;; call) [ -n "$debugging" ] && set -x # # Undocumented way to call functions in ${SHAREDIR}/functions directly # shift $@ ;; help) shift usage ;; *) usage 1 ;; esac