#!/bin/sh # # Shorewall Packet Filtering Firewall Control Program - V4.2 # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 - Tom Eastep (teastep@shorewall.net) # # This file should be placed in /sbin/shorewall. # # Shorewall documentation is available at http://www.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. # # The firewall uses configuration files in /etc/shorewall/ - skeleton # files are included with the firewall. # # Commands are: # # shorewall add [:] zone Adds a host or subnet to a zone # shorewall delete [:] zone Deletes a host or subnet from a zone # shorewall dump Dumps all Shorewall-related information # for problem analysis # shorewall start Starts the firewall # shorewall restart Restarts the firewall # shorewall stop Stops the firewall # shorewall status Displays firewall status # shorewall reset Resets iptables packet and # byte counts # shorewall clear Open the floodgates by # removing all iptables rules # and setting the three permanent # chain policies to ACCEPT # shorewall refresh Rebuild the common chain to # compensate for a change of # broadcast address on any "detect" # interface. # shorewall [re]load [ ] # Compile a script and install it on a # remote Shorewall Lite system. # shorewall show [ ... ] Display the rules in each listed # shorewall show actions Displays the available actions # shorewall show log Print the last 20 log messages # shorewall show connections Show the kernel's connection # tracking table # shorewall show nat Display the rules in the nat table # shorewall show {mangle|tos} Display the rules in the mangle table # shorewall show tc Display traffic control info # shorewall show classifiers Display classifiers # shorewall show capabilities Display iptables/kernel capabilities # shorewall show vardir Display the VARDIR setting. # shorewall version Display the installed version id # shorewall check [ -e ] [ ] Dry-run compilation. # shorewall try [ ] Try a new configuration and if # it doesn't work, revert to the # standard one. If a timeout is supplied # the command reverts back to the # standard configuration after that many # seconds have elapsed after successfully # starting the new configuration. # shorewall logwatch [ refresh-interval ] Monitor the local log for Shorewall # messages. # shorewall drop
... Temporarily drop all packets from the # listed address(es) # shorewall reject
... Temporarily reject all packets from the # listed address(es) # shorewall allow
... Reenable address(es) previously # disabled with "drop" or "reject" # shorewall save [ ] Save the list of "rejected" and # "dropped" addresses so that it will # be automatically reinstated the # next time that Shorewall starts. # Save the current state so that 'shorewall # restore' can be used. # # shorewall forget [ ] Discard the data saved by 'shorewall save' # # shorewall restore [ ] Restore the state of the firewall from # previously saved information. # # shorewall ipaddr {
/ |
} # # Displays information about the network # defined by the argument[s] # # shorewall iprange
-
Decomposes a range of IP addresses into # a list of network/host addresses. # # shorewall ipdecimal {
| } # # Displays the decimal equivalent of an IP # address and vice versa. # # shorewall safe-start [ ] Starts the firewall and promtp for a c # confirmation to accept or reject the new # configuration # # shorewall safe-restart [ ] Restarts the firewall and prompt for a # confirmation to accept or reject the new # configuration # # shorewall compile [ -e ] [ ] # Compile a firewall program file. # # Set the configuration variables from shorewall.conf # # $1 = Yes: read the params file # $2 = Yes: check for STARTUP_ENABLED # $3 = Yes: Check for LOGFILE # # get_config() { ensure_config_path if [ "$1" = Yes ]; then params=$(find_file params) if [ -f $params ]; then . $params fi fi config=$(find_file shorewall.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 if [ -z "$EXPORT" -a "$(id -u)" = 0 ]; then # # This block is avoided for compile for export and when the user isn't root # export CONFIG_PATH if [ "$3" = Yes ]; then [ -z "$LOGFILE" ] && LOGFILE=/var/log/messages if [ -n "$(syslog_circular_buffer)" ]; then LOGREAD="logread | tac" elif [ -f $LOGFILE ]; then LOGREAD="tac $LOGFILE" else echo "LOGFILE ($LOGFILE) does not exist!" >&2 exit 2 fi fi 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 export IPTABLES # # Compile by non-root needs no restore file # [ -n "$RESTOREFILE" ] || RESTOREFILE=restore validate_restorefile RESTOREFILE export RESTOREFILE if [ "$2" = Yes ]; then case $STARTUP_ENABLED in No|no|NO) echo " ERROR: Shorewall startup is disabled. To enable startup, set STARTUP_ENABLED=Yes in ${CONFDIR}/shorewall.conf" >&2 exit 2 ;; Yes|yes|YES) ;; *) if [ -n "$STARTUP_ENABLED" ]; then echo " ERROR: Invalid Value for STARTUP_ENABLE: $STARTUP_ENABLED" >&2 exit 2 fi ;; esac fi case ${TC_ENABLED:=Internal} in No|NO|no) TC_ENABLED= ;; esac [ -n "LOGFORMAT" ] && LOGFORMAT="${LOGFORMAT%%%*}" [ -n "$LOGFORMAT" ] || LOGFORMAT="Shorewall:" export LOGFORMAT if [ -n "$STARTUP_LOG" ]; then if [ -n "$LOG_VERBOSITY" ]; then case $LOG_VERBOSITY in -1) ;; 0|1|2) ;; *) echo " ERROR: Invalid LOG_VERBOSITY ($LOG_VERBOSITY)" >&2 exit 2; ;; esac else LOG_VERBOSITY=2; fi else LOG_VERBOSITY=-1; fi else STARTUP_LOG= LOG_VERBOSITY=-1 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 case $VERBOSITY in -1|0|1|2) ;; *) if [ -n "$VERBOSITY" ]; then echo " ERROR: Invalid VERBOSITY setting ($VERBOSITY)" >&2 exit 2 else VERBOSITY=2 fi ;; esac [ -n "$USE_VERBOSITY" ] && VERBOSE=$USE_VERBOSITY || VERBOSE=$(($VERBOSE_OFFSET + $VERBOSITY)) if [ $VERBOSE -lt -1 ]; then VERBOSE=-1 elif [ $VERBOSE -gt 2 ]; then VERBOSE=2 fi export VERBOSE [ -n "${HOSTNAME:=$(hostname)}" ] [ -n "$RSH_COMMAND" ] || RSH_COMMAND='ssh ${root}@${system} ${command}' [ -n "$RCP_COMMAND" ] || RCP_COMMAND='scp ${files} ${root}@${system}:${destination}' case $MANGLE_ENABLED in Yes|yes) ;; No|no) MANGLE_ENABLED= ;; *) if [ -n "$MANGLE_ENABLED" ]; then echo " ERROR: Invalid MANGLE_ENABLED setting ($MANGLE_ENABLED)" >&2 exit 2 fi ;; esac } # # Run the appropriate compiler # compiler() { local sc sc=${SHELLSHAREDIR}/compiler local pc pc=${PERLSHAREDIR}/compiler.pl startup_error() { echo " ERROR: $@" >&2 exit 1 } local command command=$1 shift if [ $(id -u) -ne 0 ]; then if [ -z "$SHOREWALL_DIR" -o "$SHOREWALL_DIR" = /etc/shorewall ]; then startup_error "Ordinary users may not compile the /etc/shorewall configuration" fi fi # # We've now set SHOREWALL_DIR so recalculate CONFIG_PATH # ensure_config_path compiler= haveparams= if [ -n "$SHOREWALL_COMPILER" ]; then compiler="$SHOREWALL_COMPILER" #Compiler specified in /etc/shorewall/shorewall.conf or on the run-line elif [ -x $sc ]; then if [ ! -x $pc ]; then compiler=shell fi elif [ -x $pc ]; then compiler=perl else fatal_error "No shorewall compiler installed" fi if [ -z "$compiler" ]; then # # Both compilers installed. Read the appropriate shorewall.conf to learn the setting of SHOREWALL_COMPILER # if [ -n "$SHOREWALL_DIR" ]; then shell=$SHOREWALL_SHELL [ -x $pc ] && set -a run_user_exit params set +a haveparams=Yes get_config No No No SHOREWALL_SHELL=$shell fi # # And initiate the appropriate compiler # if [ -n "$SHOREWALL_COMPILER" ]; then compiler="$SHOREWALL_COMPILER" elif [ -x $sc ]; then compiler=shell else compiler=perl fi fi case $COMMAND in *start|try|refresh) ;; *) STARTUP_LOG= LOG_VERBOSITY=-1 ;; esac [ $command = exec ] || command= case "$compiler" in perl) debugflags="-w" [ -n "$DEBUG" ] && debugflags='-wd' [ -n "$PROFILE" ] && debugflags='-wd:DProf' # Perl compiler only takes the output file as a argument [ "$1" = debug -o "$1" = trace ] && shift; [ "$1" = nolock ] && shift; shift options="--verbose=$VERBOSE" [ -n "$STARTUP_LOG" ] && options="$options --log=$STARTUP_LOG" [ -n "$LOG_VERBOSITY" ] && options="$options --log_verbosity=$LOG_VERBOSITY"; [ -n "$EXPORT" ] && options="$options --export" [ -n "$SHOREWALL_DIR" ] && options="$options --directory=$SHOREWALL_DIR" [ -n "$TIMESTAMP" ] && options="$options --timestamp" [ -n "$TEST" ] && options="$options --test" [ "$debugging" = trace ] && options="$options --debug" [ -n "$REFRESHCHAINS" ] && options="$options --refresh=$REFRESHCHAINS" [ -x $pc ] || startup_error "SHOREWALL_COMPILER=perl requires the shorewall-perl package which is not installed" # # Run the appropriate params file # if [ -z "$haveparams" ]; then set -a; run_user_exit params set +a fi $command perl $debugflags $pc $options $@ ;; shell) [ -x $sc ] || startup_error "SHOREWALL_COMPILER=shell requires the shorewall-shell package which is not installed" [ -n "$REFRESHCHAINS" ] && startup_error "Shorewall-shell does not support refresh of specific chains" $command $SHOREWALL_SHELL $sc $@ ;; *) startup_error "Invalid value ($SHOREWALL_COMPILER) for SHOREWALL_COMPILER" ;; esac } # # Start Command Executor # start_command() { local finished finished=0 do_it() { local rc rc=0 progress_message3 "Compiling..." if compiler run $debugging $nolock compile ${VARDIR}/.start; then [ -n "$nolock" ] || mutex_on ${VARDIR}/.start $debugging start rc=$? [ -n "$nolock" ] || mutex_off else rc=$? logger -p kern.err "ERROR:Shorewall start failed" fi exit $rc } if shorewall_is_started; then error_message "Shorewall is already running" exit 0 fi [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" 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= ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; d*) DEBUG=Yes option=${option#d} ;; f*) 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" PURGE=Yes option=${option%p} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" -o -n "$FAST" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) export SHOREWALL_DIR ;; *) usage 1 ;; esac export NOROUTES export PURGE if [ -n "$FAST" ]; then if qt mywhich make; then # # RESTOREFILE is exported by get_config() # make -qf ${CONFDIR}/Makefile || FAST= fi if [ -n "$FAST" ]; then RESTOREPATH=${VARDIR}/$RESTOREFILE if [ -x $RESTOREPATH ]; then if [ -x ${RESTOREPATH}-ipsets ]; then echo Restoring Ipsets... # # We must purge iptables to be sure that there are no # references to ipsets # iptables -F iptables -X $SHOREWALL_SHELL ${RESTOREPATH}-ipsets fi echo Restoring Shorewall... $SHOREWALL_SHELL $RESTOREPATH restore date > ${VARDIR}/restarted progress_message3 Shorewall restored from $RESTOREPATH else do_it fi else do_it fi else do_it fi } # # Compile Command Executor # compile_command() { local finished finished=0 while [ $finished -eq 0 ]; do [ $# -eq 0 ] && usage 1 option=$1 case $option in -*) shift option=${option#-} [ -z "$option" ] && usage 1 while [ -n "$option" ]; do case $option in e*) EXPORT=Yes option=${option#e} ;; p*) PROFILE=Yes option=${option#p} ;; C) [ $# -gt 0 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$1 option= shift ;; t*) TEST=Yes option=${option#t} ;; d*) DEBUG=Yes; option=${option#d} ;; -) finished=1 option= ;; *) usage 1 ;; esac done ;; *) finished=1 ;; esac done file= case $# in 1) file=$1 [ -d $file ] && echo " ERROR: $file is a directory" >&2 && exit 2; ;; 2) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) export SHOREWALL_DIR file=$2 ;; *) usage 1 ;; esac export EXPORT progress_message3 "Compiling..." compiler exec $debugging compile $file } # # Check Command Executor # check_command() { local finished finished=0 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= ;; e*) EXPORT=Yes option=${option#e} ;; p*) PROFILE=Yes option=${option#p} ;; d*) DEBUG=Yes; option=${option#d} ;; C) [ $# -gt 0 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) export SHOREWALL_DIR ;; *) usage 1 ;; esac export EXPORT progress_message3 "Checking..." compiler exec $debugging $nolock check } # # Restart Command Executor # restart_command() { local finished finished=0 local rc rc=0 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= ;; d*) DEBUG=Yes option=${option#d} ;; f*) FAST=Yes option=${option#f} ;; n*) NOROUTES=Yes option=${option#n} ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; p*) [ -n "$(which conntrack)" ] || fatal_error "The '-p' option requires the conntrack utility which does not appear to be installed on this system" PURGE=Yes option=${option%p} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) [ -n "$FAST" ] && fatal_error "Directory may not be specified with the -f option" export SHOREWALL_DIR ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" export NOROUTES export PURGE if [ -z "$FAST" ]; then progress_message3 "Compiling..." if compiler run $debugging $nolock compile ${VARDIR}/.restart; then [ -n "$nolock" ] || mutex_on $SHOREWALL_SHELL ${VARDIR}/.restart $debugging restart rc=$? [ -n "$nolock" ] || mutex_off else rc=$? logger -p kern.err "ERROR:Shorewall restart failed" fi else [ -x ${VARDIR}/.restore ] || fatal_error "No ${VARDIR}/.restore file found" [ -n "$nolock" ] || mutex_on $SHOREWALL_SHELL ${VARDIR}/.restore $debugging restart rc=$? [ -n "$nolock" ] || mutex_off fi return $rc } # # Refresh Command Executor # refresh_command() { local finished finished=0 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= ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done if [ $# -gt 0 ]; then REFRESHCHAINS=$1 shift while [ $# -gt 0 ]; do REFRESHCHAINS="$REFRESHCHAINS,$1" shift done fi shorewall_is_started || fatal_error "Shorewall is not running" [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" export NOROUTES progress_message3 "Compiling..." if compiler run $debugging $nolock compile ${VARDIR}/.refresh; then [ -n "$nolock" ] || mutex_on $SHOREWALL_SHELL ${VARDIR}/.refresh $debugging refresh rc=$? [ -n "$nolock" ] || mutex_off else rc=$? fi return $rc } # # Safe-start/safe-restart Command Executor # safe_commands() { local finished finished=0 # test is the shell supports timed read read -t 0 junk 2> /dev/null if [ $? -eq 2 -a ! -x /bin/bash ];then echo "Your shell does not support a feature required to execute this command". exit 2 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= ;; n*) NOROUTES=Yes option=${option#n} ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) export SHOREWALL_DIR ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" if shorewall_is_started; then running=Yes else running= fi if [ "$COMMAND" = "safe-start" -a -n "$running" ]; then # the command is safe-start but the firewall is already running error_message "Shorewall is already started" exit 0 fi if [ "$COMMAND" = "safe-start" -o -z "$running" ]; then # the command is safe-start or shorewall is not started yet command="start" else # the command is safe-restart and the firewall is already running command="restart" fi progress_message3 "Compiling..." if ! compiler run $debugging nolock compile ${VARDIR}/.$command; then status=$? exit $status fi case $command in start) export RESTOREFILE=NONE progress_message3 "Starting..." ;; restart) export RESTOREFILE=.safe RESTOREPATH=${VARDIR}/.safe save_config progress_message3 "Restarting..." ;; esac [ -n "$nolock" ] || mutex_on if ${VARDIR}/.$command $command; then echo -n "Do you want to accept the new firewall configuration? [y/n] " if read_yesno_with_timeout; then echo "New configuration has been accepted" else if [ "$command" = "restart" ]; then ${VARDIR}/.safe restore else ${VARDIR}/.$command clear fi [ -n "$nolock" ] || mutex_off echo "New configuration has been rejected and the old one restored" exit 2 fi fi [ -n "$nolock" ] || mutex_off } # # 'try' Command Executor # try_command() { local finished finished=0 local timeout timeout= handle_directory() { [ -n "$SHOREWALL_DIR" ] && usage 2 if [ ! -d $1 ]; then if [ -e $1 ]; then echo "$1 is not a directory" >&2 && exit 2 else echo "Directory $1 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $1) export SHOREWALL_DIR } 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*) NOROUTES=Yes option=${option#n} ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" SHOREWALL_COMPILER=$2 option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) usage 1 ;; 1) handle_directory $1 ;; 2) handle_directory $1 timeout=$2 case $timeout in *[!0-9]*) echo " ERROR: Invalid timeout ($timeout)" >&2; exit 1 ;; esac ;; *) usage 1 ;; esac [ -n "$STARTUP_ENABLED" ] || fatal_error "Startup is disabled" if shorewall_is_started; then running=Yes else running= fi if [ -z "$running" ]; then # shorewall is not started yet command="start" else # the firewall is already running command="restart" fi progress_message3 "Compiling..." if ! compiler run $debugging $nolock compile ${VARDIR}/.$command; then status=$? exit $status fi case $command in start) export RESTOREFILE=NONE progress_message3 "Starting..." ;; restart) export RESTOREFILE=.try RESTOREPATH=${VARDIR}/.try save_config progress_message3 "Restarting..." ;; esac [ -n "$nolock" ] || mutex_on if ${VARDIR}/.$command $command && [ -n "$timeout" ]; then sleep $timeout if [ "$command" = "restart" ]; then ${VARDIR}/.try restore else ${VARDIR}/.$command clear fi fi [ -n "$nolock" ] || mutex_off return 0 } rsh_command() { command="$*" eval $RSH_COMMAND } rcp_command() { files="$1" destination=$2 eval $RCP_COMMAND } # # [Re]load command executor # reload_command() # $* = original arguments less the command. { local verbose verbose=$(make_verbose) local file file= local capabilities capabilities= local finished finished=0 local saveit saveit= local result local directory local system local getcaps getcaps= local root root=root local compiler compiler= LITEDIR=/var/lib/shorewall-lite 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= ;; s*) saveit=Yes option=${option#s} ;; c*) getcaps=Yes option=${option#c} ;; r) [ $# -gt 1 ] || fatal_error "Missing Root User name" root=$2 option= shift ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" compiler="-C $2" option= shift ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 1) directory="." system=$1 ;; 2) directory=$1 system=$2 ;; *) usage 1 ;; esac litedir=$(rsh_command /sbin/shorewall-lite show config 2> /dev/null | grep ^LITEDIR | sed 's/LITEDIR is //') [ -n "$litedir" ] && LITEDIR=$litedir if [ -z "$getcaps" ]; then SHOREWALL_DIR=$(resolve_file $directory) ensure_config_path capabilities=$(find_file capabilities) [ -f $capabilities ] || getcaps=Yes fi if [ -n "$getcaps" ]; then if [ -f $directory/shorewall.conf ]; then . $directory/shorewall.conf ensure_config_path fi progress_message "Getting Capabilities on system $system..." if ! rsh_command "MODULESDIR=$MODULESDIR MODULE_SUFFIX=\"$MODULE_SUFFIX\" IPTABLES=$IPTABLES /usr/share/shorewall-lite/shorecap" > $directory/capabilities; then fatal_error "ERROR: Capturing capabilities on system $system failed" fi fi file=$(resolve_file $directory/firewall) [ -n "$TIMESTAMP" ] && timestamp='-t' || timestamp= if shorewall $debugging $verbose $timestamp compile -e $compiler $directory $directory/firewall && \ progress_message3 "Copying $file and ${file}.conf to ${system}:${LITEDIR}..." && \ rcp_command "$directory/firewall $directory/firewall.conf" ${LITEDIR} then save=$(find_file save); [ -f $save ] && progress_message3 "Copying $save to ${system}:/etc/shorewall-lite/" && rcp_command $save /etc/shorewall-lite/ progress_message3 "Copy complete" if [ $COMMAND = reload ]; then rsh_command "/sbin/shorewall-lite $debugging $verbose $timestamp restart" && \ progress_message3 "System $system reloaded" || saveit= else rsh_command "/sbin/shorewall-lite $debugging $verbose $timestamp start" && \ progress_message3 "System $system loaded" || saveit= fi if [ -n "$saveit" ]; then rsh_command "/sbin/shorewall-lite $debugging $verbose $timestamp save" && \ progress_message3 "Configuration on system $system saved" fi fi } # # Export command executor # export_command() # $* = original arguments less the command. { local verbose verbose=$(make_verbose) local file file= local finished finished=0 local directory local target local compiler compiler= 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= ;; C) [ $# -gt 1 ] || fatal_error "-C must be followed by a compiler name" compiler="-C $2" option= shift ;; *) fatal_error "Unrecognized option \"$option\"" ;; esac done shift ;; *) finished=1 ;; esac done case $# in 1) directory="." target=$1 ;; 2) directory=$1 target=$2 ;; *) fatal_error "ERROR: Invalid command syntax (\"man shorewall\" for help)" ;; esac case $target in *:*) ;; *) target=$target: ;; esac file=$(resolve_file $directory/firewall) if shorewall $debugging $verbose compile -e $compiler $directory $directory/firewall && \ echo "Copying $file and ${file}.conf to ${target#*@}..." && \ scp $directory/firewall $directory/firewall.conf $target then save=(find_file save); [ -f $save ] && progress_message3 "Copying $save to ${target#*}..." && rcp_command $save $target progress_message3 "Copy complete" fi } # # 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 " check [ -e ] [ -C {shell|perl} ] [ ]" echo " clear [ -f ]" echo " compile [ -e ] [ -C {shell|perl} ] [ ] " echo " delete [:] ... " echo " drop
..." echo " dump [ -x ]" echo " export [ -C {shell|perl} ] [ ] [@][:]" echo " forget [ ]" echo " help" echo " hits [ -t ]" echo " ipcalc {
/ |
}" echo " ipdecimal {
| }" echo " iprange
-
" echo " load [ -s ] [ -c ] [ -r ] [ -C {shell|perl} ] [ ] " echo " logdrop
..." echo " logreject
..." echo " logwatch []" echo " refresh [ -C {shell|perl} ] [ ... ]" echo " reject
..." echo " reload [ -s ] [ -c ] [ -r ] [ -C {shell|perl} ] [ ] " echo " reset" echo " restart [ -n ] [ -p ] [ -f ] [ -C {shell|perl} ] [ ]" echo " restore [ -n ] [ ]" echo " save [ ]" echo " show [ -x ] [ -m ] [-f] [ -t {filter|mangle|nat} ] [ {chain [ [ ... ]|actions|capabilities|classifiers|config|connections|filters|ip|log|macros|mangle|nat|routing|tc|vardir|zones} ]" echo " start [ -f ] [ -n ] [ -p ] [ -C {shell|perl} ] [ ]" echo " stop [ -f ]" echo " status" echo " try [ -C {shell|perl} ] [ ]" echo " version [ -a ]" echo " safe-start [ -C {shell|perl} ] [ ]" echo " safe-restart [ -C {shell|perl} ] [ ]" echo exit $1 } # # Execution begins here # debugging= if [ $# -gt 0 ] && [ "x$1" = "xdebug" -o "x$1" = "xtrace" ]; then debugging=$1 shift fi nolock= if [ $# -gt 0 ] && [ "$1" = "nolock" ]; then nolock=nolock shift fi SHOREWALL_DIR= IPT_OPTIONS="-nv" FAST= VERBOSE_OFFSET=0 USE_VERBOSITY= NOROUTES= PURGE= EXPORT= export TIMESTAMP= noroutes= finished=0 while [ $finished -eq 0 ]; do [ $# -eq 0 ] && usage 1 option=$1 case $option in -) finished=1 ;; -*) option=${option#-} while [ -n "$option" ]; do case $option in c) [ $# -eq 1 ] && usage 1 if [ ! -d $2 ]; then if [ -e $2 ]; then echo "$2 is not a directory" >&2 && exit 2 else echo "Directory $2 does not exist" >&2 && exit 2 fi fi SHOREWALL_DIR=$(resolve_file $2) option= shift ;; e*) EXPORT=Yes option=${option#e} ;; x*) IPT_OPTIONS="-xnv" option=${option#x} ;; q*) VERBOSE_OFFSET=$(($VERBOSE_OFFSET - 1 )) option=${option#q} ;; f*) FAST=Yes option=${option#f} ;; v*) option=${option#v} case $option in -1*) USE_VERBOSITY=-1 option=${option#-1} ;; 0*) USE_VERBOSITY=0 option=${option#0} ;; 1*) USE_VERBOSITY=1 option=${option#1} ;; 2*) USE_VERBOSITY=2 option=${option#2} ;; *) VERBOSE_OFFSET=$(($VERBOSE_OFFSET + 1 )) USE_VERBOSITY= ;; esac ;; n*) NOROUTES=Yes option=${option#n} ;; t*) TIMESTAMP=Yes option=${option#t} ;; -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done version_command() { local finished finished=0 local all all= 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 $version if [ -n "$all" ]; then if [ -f /usr/share/shorewall-shell/version ]; then echo "Shorewall-shell $(cat /usr/share/shorewall-shell/version)" fi if [ -f /usr/share/shorewall-perl/version ]; then echo "Shorewall-perl $(cat /usr/share/shorewall-perl/version)" fi fi } if [ $# -eq 0 ]; then usage 1 fi [ -n "$SHOREWALL_DIR" ] && export SHOREWALL_DIR PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin MUTEX_TIMEOUT= SHAREDIR=/usr/share/shorewall CONFDIR=/etc/shorewall export PRODUCT="Shorewall" [ -f ${CONFDIR}/vardir ] && . ${CONFDIR}/vardir [ -n "${VARDIR:=/var/lib/shorewall}" ] FIREWALL=$SHAREDIR/firewall LIBRARIES="$SHAREDIR/lib.base $SHAREDIR/lib.cli" VERSION_FILE=$SHAREDIR/version REFRESHCHAINS= for library in $LIBRARIES; do if [ -f $library ]; then . $library else echo "$library does not exist!" >&2 exit 2 fi done if [ ! -f $FIREWALL ]; then echo " ERROR: Shorewall is not properly installed" >&2 if [ -L $FIREWALL ]; then echo " $FIREWALL is a symbolic link to a" >&2 echo " non-existant file" >&2 else echo " The file $FIREWALL does not exist" >&2 fi exit 2 fi if [ -f $VERSION_FILE ]; then version=$(cat $VERSION_FILE) else echo " ERROR: Shorewall is not properly installed" >&2 echo " The file $VERSION_FILE does not exist" >&2 exit 1 fi banner="Shorewall-$version Status at $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) get_config Yes Yes shift start_command $@ ;; stop|clear) if [ "x$2" = x-f ]; then [ -x ${VARDIR}/.restore ] && FIREWALL=${VARDIR}/.restore shift; fi [ $# -ne 1 ] && usage 1 get_config export NOROUTES mutex_on $SHOREWALL_SHELL $FIREWALL $debugging $nolock $COMMAND mutex_off ;; reset) [ $# -ne 1 ] && usage 1 get_config export NOROUTES mutex_on $SHOREWALL_SHELL $FIREWALL $debugging $nolock reset mutex_off ;; compile) get_config Yes shift compile_command $@ ;; restart) get_config Yes Yes shift restart_command $@ ;; refresh) get_config Yes Yes shift refresh_command $@ ;; check) get_config Yes shift check_command $@ ;; add|delete) [ $# -lt 3 ] && usage 1 get_config mutex_on $SHOREWALL_SHELL $FIREWALL $debugging $nolock $@ mutex_off ;; show|list) get_config Yes No Yes shift show_command $@ ;; load|reload) get_config Yes shift reload_command $@ ;; export) get_config Yes shift export_command $@ ;; status) [ $# -eq 1 ] || usage 1 get_config echo "Shorewall-$version Status at $HOSTNAME - $(date)" echo if shorewall_is_started ; then echo "Shorewall is running" status=0 else echo "Shorewall is stopped" status=4 fi if [ -f ${VARDIR}/state ]; then state="$(cat ${VARDIR}/state)" case $state in Stopped*|Clear*) status=3 ;; esac else state=Unknown fi echo "State:$state" echo exit $status ;; dump) get_config Yes No Yes shift dump_command $@ ;; hits) get_config Yes No Yes [ -n "$debugging" ] && set -x shift hits_command $@ ;; version) shift version_command $@ ;; try) get_config Yes shift try_command $@ ;; logwatch) get_config Yes Yes Yes banner="Shorewall-$version Logwatch at $HOSTNAME -" logwatch_command $@ ;; drop) get_config [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then [ -n "$nolock" ] || mutex_on block DROP Dropped $* [ -n "$nolock" ] || mutex_off else fatal_error "Shorewall is not started" fi ;; logdrop) get_config [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then [ -n "$nolock" ] || mutex_on block logdrop Dropped $* [ -n "$nolock" ] || mutex_off else fatal_error "Shorewall is not started" fi ;; reject|logreject) get_config [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then [ -n "$nolock" ] || mutex_on block $COMMAND Rejected $* [ -n "$nolock" ] || mutex_off else fatal_error "Shorewall is not started" fi ;; allow) get_config allow_command $@ ;; save) get_config [ -n "$debugging" ] && set -x case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac RESTOREPATH=${VARDIR}/$RESTOREFILE [ -n "$nolock" ] || mutex_on save_config result=$? [ -n "$nolock" ] || mutex_off exit $result ;; forget) get_config case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac RESTOREPATH=${VARDIR}/$RESTOREFILE if [ -x $RESTOREPATH ]; then if [ -x ${RESTOREPATH}-ipsets ]; then rm -f ${RESTOREPATH}-ipsets echo " ${RESTOREPATH}-ipsets removed" fi rm -f $RESTOREPATH rm -f ${RESTOREPATH}-iptables echo " $RESTOREPATH removed" elif [ -f $RESTOREPATH ]; then echo " $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 "$debugging" ] && set -x case $2 in *.*.*.*-*.*.*.*) for address in ${2%-*} ${2#*-}; do valid_address $address || fatal_error "Invalid IP address: $address" done ip_range $2 ;; *) 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) get_config shift restore_command $@ ;; call) get_config [ -n "$debugging" ] && set -x # # Undocumented way to call functions in ${SHAREDIR}/functions directly # shift $@ ;; help) shift usage ;; safe-restart|safe-start) get_config Yes shift safe_commands $@ ;; *) usage 1 ;; esac