#!/bin/sh # # Shorewall Packet Filtering Firewall Control Program - V3.2 # # This program is under GPL [http://www.gnu.org/copyleft/gpl.htm] # # (c) 1999,2000,2001,2002,2003,2004,2005,2006 - Tom Eastep (teastep@shorewall.net) # # This file should be placed in /sbin/shorewall. # # Shorewall documentation is available at http://shorewall.sourceforge.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., 675 Mass Ave, Cambridge, MA 02139, 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 is included with the firewall. # # Commands are: # # 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 version Display the installed version id # shorewall check Verify the more heavily-used # configuration files. # 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. # # Fatal Error # fatal_error() # $@ = Message { echo " $@" >&2 exit 2 } # Display a chain if it exists # showfirstchain() # $1 = name of chain { awk \ 'BEGIN {prnt=0; rslt=1; }; \ /^$/ { next; };\ /^Chain/ {if ( prnt == 1 ) { rslt=0; exit 0; }; };\ /Chain '$1'/ { prnt=1; }; \ { if (prnt == 1) print; };\ END { exit rslt; }' $TMPFILE } showchain() # $1 = name of chain { if [ "$firstchain" = "Yes" ]; then if showfirstchain $1; then firstchain= fi else awk \ 'BEGIN {prnt=0;};\ /^$|^ pkts/ { next; };\ /^Chain/ {if ( prnt == 1 ) exit; };\ /Chain '$1'/ { prnt=1; };\ { if (prnt == 1) print; }' $TMPFILE fi } # # The 'awk' hack that compensates for bugs in iptables-save (or rather in the extension modules). # iptablesbug() { if qt mywhich awk ; then awk 'BEGIN { sline=""; };\ /^-j/ { print sline $0; next };\ /-m policy.*-j/ { print $0; next };\ /-m policy/ { sline=$0; next };\ /--mask ff/ { sub( /--mask ff/, "--mask 0xff" ) };\ { print ; sline="" }' else echo " WARNING: You don't have 'awk' on this system so the output of the save command may be unusable" >&2 cat fi } # # Validate the value of RESTOREFILE # validate_restorefile() # $* = label { case $RESTOREFILE in */*) error_message "ERROR: $@ must specify a simple file name: $RESTOREFILE" exit 2 ;; .*) error_message "ERROR: Reserved File Name: $RESTOREFILE" exit 2 ;; esac } # # Set the configuration variables from shorewall.conf # get_config() { if [ -z "$EXPORT" -a "$(whoami)" = root ]; then # # This block is avoided for compile for export and when the user isn't root # export CONFIG_PATH [ -z "$LOGFILE" ] && LOGFILE=/var/log/messages if [ ! -f $LOGFILE ]; then echo "LOGFILE ($LOGFILE) does not exist!" >&2 exit 2 fi if [ -n "$IPTABLES" ]; then if [ ! -e "$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 # # 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 $LOGFILE > /dev/null 2> /dev/null ) ; then realtail="Yes" else realtail="" fi # # Compile by non-root needs no restore file # [ -n "$RESTOREFILE" ] || RESTOREFILE=restore validate_restorefile RESTOREFILE export RESTOREFILE case $STARTUP_ENABLED in No|no|NO) echo " WARNING: Shorewall startup is disabled. To enable startup, set STARTUP_ENABLED=Yes in ${CONFDIR}/shorewall.conf" >&2 STARTUP_ENABLED= ;; Yes|yes|YES) ;; *) if [ -n "$STARTUP_ENABLED" ]; then echo " ERROR: Invalid Value for STARTUP_ENABLE: $STARTUP_ENABLED" >&2 exit 2 fi ;; esac case ${TC_ENABLED:=Internal} in No|NO|no) TC_ENABLED= ;; esac [ -n "LOGFORMAT" ] && LOGFORMAT="${LOGFORMAT%%%*}" [ -n "$LOGFORMAT" ] || LOGFORMAT="Shorewall:" export LOGFORMAT fi if [ -n "$SHOREWALL_SHELL" ]; then if [ ! -e "$SHOREWALL_SHELL" ]; then echo " ERROR: The program specified in SHOREWALL_SHELL does not exist or is not executable" >&2 exit 2 fi fi [ -n "${VERBOSITY:=2}" ] VERBOSE=$(($VERBOSE_OFFSET + $VERBOSITY)) export VERBOSE } # # Clear descriptor 1 if it is a terminal # clear_term() { [ -t 1 ] && clear } # # Delay $timeout seconds -- if we're running on a recent bash2 then allow # to terminate the delay # timed_read () { read -t $timeout foo 2> /dev/null test $? -eq 2 && sleep $timeout } # # Display the last $1 packets logged # packet_log() # $1 = number of messages { local options [ -n "$realtail" ] && options="-n$1" if [ -n "$SHOWMACS" -o $VERBOSE -gt 2 ]; then grep "${LOGFORMAT}" $LOGFILE | \ sed s/" kernel:"// | \ sed s/" $host $LOGFORMAT"/" "/ | \ tail $options else grep "${LOGFORMAT}" $LOGFILE | \ sed s/" kernel:"// | \ sed s/" $host $LOGFORMAT"/" "/ | \ sed 's/MAC=.* SRC=/SRC=/' | \ tail $options fi } # # Show traffic control information # show_tc() { show_one_tc() { local device=${1%@*} qdisc=$(tc qdisc list dev $device) if [ -n "$qdisc" ]; then echo Device $device: tc -s -d qdisc show dev $device tc -s -d class show dev $device echo fi } ip link list | \ while read inx interface details; do case $inx in [0-9]*) show_one_tc ${interface%:} ;; *) ;; esac done } # # Show classifier information # show_classifiers() { show_one_classifier() { local device=${1%@*} qdisc=$(tc qdisc list dev $device) if [ -n "$qdisc" ]; then echo Device $device: tc -s filter ls dev $device echo fi } ip link list | \ while read inx interface details; do case $inx in [0-9]*) show_one_classifier ${interface%:} ;; *) ;; esac done } # # Watch the Firewall Log # logwatch() # $1 = timeout -- if negative, prompt each time that # an 'interesting' packet count changes { host=$(echo $HOSTNAME | sed 's/\..*$//') oldrejects=$($IPTABLES -L -v -n | grep 'LOG') if [ $1 -lt 0 ]; then timeout=$((- $1)) pause="Yes" else pause="No" timeout=$1 fi qt mywhich awk && haveawk=Yes || haveawk= while true; do clear_term echo "$banner $(date)" echo echo "Dropped/Rejected Packet Log" echo show_reset rejects=$($IPTABLES -L -v -n | grep 'LOG') if [ "$rejects" != "$oldrejects" ]; then oldrejects="$rejects" $RING_BELL packet_log 40 if [ "$pause" = "Yes" ]; then echo echo $ECHO_N 'Enter any character to continue: ' read foo else timed_read fi else echo packet_log 40 timed_read fi done } # # Save currently running configuration # save_config() { if shorewall_is_started ; then [ -d ${VARDIR} ] || mkdir -p ${VARDIR} if [ -f $RESTOREPATH -a ! -x $RESTOREPATH ]; then echo " ERROR: $RESTOREPATH exists and is not a saved Shorewall configuration" else case $RESTOREFILE in save|restore-base) echo " ERROR: Reserved file name: $RESTOREFILE" ;; *) if $IPTABLES -L dynamic -n > ${VARDIR}/save; then echo " Dynamic Rules Saved" if [ -f ${VARDIR}/.restore ]; then if iptables-save | iptablesbug > ${VARDIR}/restore-$$; then cp -f ${VARDIR}/.restore $RESTOREPATH mv -f ${VARDIR}/restore-$$ ${RESTOREPATH}-iptables chmod +x $RESTOREPATH echo " Currently-running Configuration Saved to $RESTOREPATH" rm -f ${RESTOREPATH}-ipsets case ${SAVE_IPSETS:-No} in [Yy][Ee][Ss]) RESTOREPATH=${RESTOREPATH}-ipsets f=${VARDIR}/restore-$$ echo "#!/bin/sh" > $f echo "#This ipset restore file generated $(date) by Shorewall $version" >> $f echo >> $f echo ". ${SHAREDIR}/functions" >> $f echo >> $f grep '^MODULE' ${VARDIR}/restore-base >> $f echo "reload_kernel_modules << __EOF__" >> $f grep 'loadmodule ip_set' ${VARDIR}/restore-base >> $f echo "__EOF__" >> $f echo >> $f echo "ipset -U :all: :all:" >> $f echo "ipset -F" >> $f echo "ipset -X" >> $f echo "ipset -R << __EOF__" >> $f ipset -S >> $f echo "__EOF__" >> $f mv -f $f $RESTOREPATH chmod +x $RESTOREPATH echo " Current Ipset Contents Saved to $RESTOREPATH" ;; [Nn][Oo]) ;; *) echo " WARNING: Invalid value ($SAVE_IPSETS) for SAVE_IPSETS. Ipset contents not saved" ;; esac else rm -f ${VARDIR}/restore-$$ echo " ERROR: Currently-running Configuration Not Saved" fi else echo " ERROR: ${VARDIR}/.restore does not exist" fi else echo "Error Saving the Dynamic Rules" fi ;; esac fi else echo "Shorewall isn't started" fi } # # Start Command Executor # start_command() { local finished=0 do_it() { [ -n "$nolock" ] || mutex_on progress_message3 "Compiling..." if $SHOREWALL_SHELL ${SHAREDIR}/compiler $debugging $nolock compile ${VARDIR}/.start; then ${VARDIR}/.start $debugging start fi [ -n "$nolock" ] || mutex_off } if shorewall_is_started; then error_message "Shorewall is already running" exit 1 fi if [ -z "$STARTUP_ENABLED" ]; then error_message "ERROR: Startup is disabled" 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= ;; f*) FAST=Yes option=${option#f} ;; *) 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=$ export SHOREWALL_DIR ;; *) usage 1 ;; esac export NOROUTES 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=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} ;; -) finished=1 option= ;; *) usage 1 ;; esac done ;; *) finished=1 ;; esac done file= case $# in 1) file=$1 ;; 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=$1 export SHOREWALL_DIR file=$2 ;; *) usage 1 ;; esac export EXPORT progress_message3 "Compiling..." exec $SHOREWALL_SHELL ${SHAREDIR}/compiler $debugging compile $file } # # Check Command Executor # check_command() { local 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} ;; *) 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=$1 export SHOREWALL_DIR ;; *) usage 1 ;; esac export EXPORT progress_message3 "Checking..." exec $SHOREWALL_SHELL ${SHAREDIR}/compiler $debugging $nolock check } # # Restart Command Executor # restart_command() { local 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= ;; n*) NOROUTES=Yes option=${option#n} ;; *) 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=$1 export SHOREWALL_DIR ;; *) usage 1 ;; esac if [ -z "$STARTUP_ENABLED" ]; then error_message "ERROR: Startup is disabled" exit 2 fi export NOROUTES [ -n "$nolock" ] || mutex_on progress_message3 "Compiling..." if $SHOREWALL_SHELL ${SHAREDIR}/compiler $debugging $nolock compile ${VARDIR}/.restart; then $SHOREWALL_SHELL ${VARDIR}/.restart $debugging restart fi [ -n "$nolock" ] || mutex_off } # # Show Command Executor # show_command() { local 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= ;; v*) VERBOSE=$(($VERBOSE + 1 )) option=${option#v} ;; x*) IPT_OPTIONS="-xnv" option=${option#x} ;; m*) SHOWMACS=Yes option=${option#m} ;; f*) FILEMODE=Yes option=${option#f} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ -n "$debugging" ] && set -x case "$1" in connections) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version Connections at $HOSTNAME - $(date)" echo cat /proc/net/ip_conntrack ;; nat) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version NAT Table at $HOSTNAME - $(date)" echo show_reset $IPTABLES -t nat -L $IPT_OPTIONS ;; tos|mangle) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version Mangle Table at $HOSTNAME - $(date)" echo show_reset $IPTABLES -t mangle -L $IPT_OPTIONS ;; log) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version Log at $HOSTNAME - $(date)" echo show_reset host=$(echo $HOSTNAME | sed 's/\..*$//') packet_log 20 ;; tc) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version Traffic Control at $HOSTNAME - $(date)" echo show_tc ;; classifiers) [ $# -gt 1 ] && usage 1 echo "Shorewall-$version Clasifiers at $HOSTNAME - $(date)" echo show_classifiers ;; zones) [ $# -gt 1 ] && usage 1 if [ -f ${VARDIR}/zones ]; then echo "Shorewall-$version Zones at $HOSTNAME - $(date)" echo while read zone type hosts; do echo "$zone ($type)" for host in $hosts; do echo " $host" done done < ${VARDIR}/zones echo else echo " ERROR: ${VARDIR}/zones does not exist" >&2 exit 1 fi ;; capabilities) [ $# -gt 1 ] && usage 1 determine_capabilities VERBOSE=2 if [ -n "$FILEMODE" ]; then report_capabilities1 else report_capabilities fi ;; actions) [ $# -gt 1 ] && usage 1 echo "allowBcast # Silently Allow Broadcast/multicast" echo "dropBcast # Silently Drop Broadcast/multicast" echo "dropNotSyn # Silently Drop Non-syn TCP packets" echo "rejNotSyn # Silently Reject Non-syn TCP packets" echo "dropInvalid # Silently Drop packets that are in the INVALID conntrack state" echo "allowInvalid # Accept packets that are in the INVALID conntrack state." echo "allowoutUPnP # Allow traffic from local command 'upnpd'" echo "allowinUPnP # Allow UPnP inbound (to firewall) traffic" echo "forwardUPnP # Allow traffic that upnpd has redirected from" cat ${SHAREDIR}/actions.std ${CONFDIR}/actions | grep -Ev '^\#|^$' ;; macros) [ $# -gt 1 ] && usage 1 for macro in ${SHAREDIR}/macro.*; do foo=`grep 'This macro' $macro | head -n 1` if [ -n "$foo" ]; then macro=${macro#*.} foo=${foo%.*} echo " $macro ${foo#\#}" | sed 's/This macro //' fi done ;; config) . ${SHAREDIR}/configpath echo "Default CONFIG_PATH is $CONFIG_PATH" echo "LITEDIR is $LITEDIR" ;; *) echo "Shorewall-$version $([ $# -gt 0 ] && echo Chains || echo Chain) $* at $HOSTNAME - $(date)" echo show_reset if [ $# -gt 0 ]; then for chain in $*; do $IPTABLES -L $chain $IPT_OPTIONS done else $IPTABLES -L $IPT_OPTIONS fi ;; esac } # # Dump Command Executor # dump_command() { local 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= ;; x*) IPT_OPTIONS="-xnv" option=${option#x} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ -n "$debugging" ] && set -x [ $# -eq 0 ] || usage 1 clear_term echo "Shorewall-$version Dump at $HOSTNAME - $(date)" echo show_reset host=$(echo $HOSTNAME | sed 's/\..*$//') $IPTABLES -L $IPT_OPTIONS heading "Log ($LOGFILE)" packet_log 20 heading "NAT Table" $IPTABLES -t nat -L $IPT_OPTIONS heading "Mangle Table" $IPTABLES -t mangle -L $IPT_OPTIONS heading "Conntrack Table" cat /proc/net/ip_conntrack heading "IP Configuration" ip addr ls heading "IP Stats" ip -stat link ls if qt mywhich brctl; then heading "Bridges" brctl show fi heading "/proc" show_proc /proc/version show_proc /proc/sys/net/ipv4/ip_forward show_proc /proc/sys/net/ipv4/icmp_echo_ignore_all for directory in /proc/sys/net/ipv4/conf/*; do for file in proxy_arp arp_filter arp_ignore rp_filter log_martians; do show_proc $directory/$file done done if [ -n "$(ip rule ls)" ]; then heading "Routing Rules" ip rule ls ip rule ls | while read rule; do echo ${rule##* } done | sort -u | while read table; do heading "Table $table:" ip route ls table $table done else heading "Routing Table" ip route ls fi heading "ARP" arp -na if qt mywhich lsmod; then heading "Modules" lsmod | grep -E '^ip_|^ipt_|^iptable_' fi determine_capabilities echo report_capabilities if [ -n "$TC_ENABLED" ]; then heading "Traffic Control" show_tc heading "TC Filters" show_classifiers fi } # # Safe-start/safe-restart Command Executor # safe_commands() { local 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} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ $# -eq 0 ] || usage 2 if [ -z "$STARTUP_ENABLED" ]; then error_message "ERROR: Startup is disabled" exit 2 fi mutex_on 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" mutex_off exit 1 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 ! $SHOREWALL_SHELL ${SHAREDIR}/compiler $debugging nolock compile ${VARDIR}/.$command; then status=$? mutex_off exit $status fi RESTOREFILE=.safe RESTOREPATH=${VARDIR}/.safe save_config case $command in start) progress_message3 "Starting..." ;; restart) progress_message3 "Restarting..." ;; esac ${VARDIR}/.$command $command 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 mutex_off echo "New configuration has been rejected and the old one restored" exit 2 fi mutex_off [ $? -eq 0 ] && [ -n "$SUBSYSLOCK" ] && touch $SUBSYSLOCK } # # Restore Comand Executor # restore_command() { local 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= ;; n*) NOROUTES=Yes option=${option#n} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 0) ;; 1) RESTOREFILE="$1" validate_restorefile '' ;; *) usage 1 ;; esac if [ -z "$STARTUP_ENABLED" ]; then error_message "ERROR: Startup is disabled" exit 2 fi RESTOREPATH=${VARDIR}/$RESTOREFILE export NOROUTES [ -n "$nolock" ] || mutex_on if [ -x $RESTOREPATH ]; then if [ -x ${RESTOREPATH}-ipsets ] ; then echo Restoring Ipsets... iptables -F iptables -X $SHOREWALL_SHELL ${RESTOREPATH}-ipsets fi progress_message3 "Restoring Shorewall..." $SHOREWALL_SHELL $RESTOREPATH restore && progress_message3 "Shorewall restored from ${VARDIR}/$RESTOREFILE" [ -n "$nolock" ] || mutex_off else echo "File ${VARDIR}/$RESTOREFILE: file not found" [ -n "$nolock" ] || mutex_off exit 2 fi } # # [Re]load command executor # reload_command() # $* = original arguments less the command. { local verbose=$(make_verbose) file= finished=0 saveit= result directory system [ -n "$LITEDIR" ] || { echo " ERROR: LITEDIR not defined in ${SHAREDIR}/configpath" >&2; exit 2; } 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} ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done case $# in 1) directory="." system=$1 ;; 2) directory=$1 system=$2 ;; *) usage 1 ;; esac file=$(resolve_file $directory/firewall) if shorewall $debugging $verbose compile -e $directory $directory/firewall && \ echo "Copying $file and ${file}.conf to ${system}:${LITEDIR}..." && \ scp $directory/firewall $directory/firewall.conf root@${system}:${LITEDIR} then echo "Copy complete" if [ $COMMAND = reload ]; then ssh root@${system} "/sbin/shorewall-lite $debugging $verbose restart" && \ progress_message3 "System $system reloaded" || saveit= else ssh root@${system} "/sbin/shorewall-lite $debugging $verbose restart" && \ progress_message3 "System $system reloaded" || saveit= fi if [ -n "$saveit" ]; then ssh root@${system} "/sbin/shorewall-lite $debugging $verbose save" && \ progress_message3 "Configuration on system $system saved" fi fi } # # Help information # help() { [ -x $HELP ] && { export version; exec $HELP $*; } echo "Help subsystem is not installed at $HELP" } # # Give Usage Information # usage() # $1 = exit status { echo "Usage: $(basename $0) [debug|trace] [nolock] [ -q ] [ -v ] [ -t ] " echo "where is one of:" echo " allow
..." echo " check [ -e ] [ ]" echo " clear" echo " compile [ -e ] [ ] " echo " drop
..." echo " dump [ -x ]" echo " forget [ ]" echo " help [ | host | address ]" echo " hits" echo " ipcalc {
/ |
}" echo " ipdecimal {
| }" echo " iprange
-
" echo " load [ -s ] [ ] " echo " logdrop
..." echo " logreject
..." echo " logwatch []" echo " refresh" echo " reject
..." echo " reload [ -s ] [ ] " echo " reset" echo " restart [ -n ] [ ]" echo " restore [ -n ] [ ]" echo " save [ ]" echo " show [ -x ] [ -m ] [-f] [ [ ... ]|actions|capabilities|classifiers|config|connections|log|macros|mangle|nat|tc|zones]" echo " start [ -f ] [ -n ] [ ]" echo " stop" echo " status" echo " try [ ]" echo " version" echo " safe-start" echo " safe-restart" echo exit $1 } # # Display the time that the counters were last reset # show_reset() { [ -f ${VARDIR}/restarted ] && \ echo "Counters reset $(cat ${VARDIR}/restarted)" && \ echo } # # Display's the passed file name followed by "=" and the file's contents. # show_proc() # $1 = name of a file { [ -f $1 ] && echo " $1 = $(cat $1)" } read_yesno_with_timeout() { read -t 60 yn 2> /dev/null if [ $? -eq 2 ] then # read doesn't support timeout test -x /bin/bash || return 2 # bash is not installed so the feature is not available /bin/bash -c 'read -t 60 yn ; if [ "$yn" == "y" ] ; then exit 0 ; else exit 1 ; fi' # invoke bash and use its version of read return $? else # read supports timeout case "$yn" in y|Y) return 0 ;; *) return 1 ;; esac fi } # # Print a heading with leading and trailing black lines # heading() { echo echo "$@" echo } # # Create the appropriate -q option to pass onward # make_verbose() { local v=$VERBOSE_OFFSET option=- if [ $VERBOSE_OFFSET -gt 0 ]; then while [ $v -gt 0 ]; do option="${option}v" v=$(($v - 1)) done echo $option elif [ $VERBOSE_OFFSET -lt 0 ]; then while [ $v -lt 0 ]; do option="${option}q" v=$(($v + 1)) done echo $option fi } # # Execution begins here # debugging= if [ $# -gt 0 ] && [ "$1" = "debug" -o "$1" = "trace" ]; then debugging=debug shift fi nolock= if [ $# -gt 0 ] && [ "$1" = "nolock" ]; then nolock=nolock shift fi SHOREWALL_DIR= IPT_OPTIONS="-nv" FAST= VERBOSE_OFFSET=0 NOROUTES= EXPORT= export TIMESTAMP= noroutes= 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 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=$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*) VERBOSE_OFFSET=$(($VERBOSE_OFFSET + 1 )) option=${option#v} ;; n*) NOROUTES=Yes option=${option#n} ;; t*) TIMESTAMP=Yes option=${option#t} ;; -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done 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 VARDIR=/var/lib/shorewall CONFDIR=/etc/shorewall export PRODUCT="Shorewall" FIREWALL=$SHAREDIR/firewall FUNCTIONS=$SHAREDIR/functions VERSION_FILE=$SHAREDIR/version HELP=$SHAREDIR/help if [ -f $FUNCTIONS ]; then . $FUNCTIONS else echo "$FUNCTIONS does not exist!" >&2 exit 2 fi ensure_config_path 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 get_config 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" ;; *) RING_BELL="echo -e \a" ;; 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|refresh) [ $# -ne 1 ] && usage 1 export NOROUTES exec $SHOREWALL_SHELL $FIREWALL $debugging $nolock $COMMAND ;; compile) shift compile_command $@ ;; restart) shift restart_command $@ ;; check) shift check_command $@ ;; show|list) shift show_command $@ ;; load|reload) shift reload_command $@ ;; status) [ $# -eq 1 ] || usage 1 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) shift dump_command $@ ;; hits) [ -n "$debugging" ] && set -x [ $# -eq 1 ] || usage 1 clear_term echo "Shorewall-$version Hits at $HOSTNAME - $(date)" echo timeout=30 if [ $(grep -c "$LOGFORMAT" $LOGFILE ) -gt 0 ] ; then echo " HITS IP DATE" echo " ---- --------------- ------" grep "$LOGFORMAT" $LOGFILE | sed 's/\(.\{6\}\)\(.*SRC=\)\(.*\)\( DST=.*\)/\3 \1/' | sort | uniq -c | sort -rn | \ while read count address month day; do printf '%7d %-15s %3s %2d\n' $count $address $month $day done echo "" echo " HITS IP PORT" echo " ---- --------------- -----" grep "$LOGFORMAT" $LOGFILE | sed 's/\(.*SRC=\)\(.*\)\( DST=.*DPT=\)\([0-9]\{1,5\}\)\(.*\)/\2 \4/ t s/\(.*SRC=\)\(.*\)\( DST=.*\)/\2/' | sort | uniq -c | sort -rn | \ while read count address port; do printf '%7d %-15s %d\n' $count $address $port done echo "" echo " HITS DATE" echo " ---- ------" grep "$LOGFORMAT" $LOGFILE | sed 's/\(.\{6\}\)\(.*\)/\1/' | sort | uniq -c | sort -rn | \ while read count month day; do printf '%7d %3s %2d\n' $count $month $day done echo "" echo " HITS PORT SERVICE(S)" echo " ---- ----- ----------" grep "$LOGFORMAT.*DPT" $LOGFILE | sed 's/\(.*DPT=\)\([0-9]\{1,5\}\)\(.*\)/\2/' | sort | uniq -c | sort -rn | \ while read count port ; do # List all services defined for the given port srv=$(grep "^[^#].*\\b$port/" /etc/services | cut -f 1 | cut -f 1 -d' ' | sort -u) srv=$(echo $srv | sed 's/ /,/g') if [ -n "$srv" ] ; then printf '%7d %5d %s\n' $count $port $srv else printf '%7d %5d\n' $count $port fi done fi ;; version) echo $version ;; try) [ -n "$SHOREWALL_DIR" ] && startup_error "ERROR: -c option may not be used with \"try\"" [ $# -lt 2 -o $# -gt 3 ] && usage 1 VERBOSE=$(make_verbose) [ -n "$NOROUTES" ] && NOROUTES=-n export -n CONFIG_PATH if $0 $debugging $VERBOSE save; then if $0 $debugging $VERBOSE restart $2 ; then if [ $# -eq 3 ]; then sleep $3 $0 $VERBOSE $NOROUTES restore fi fi fi ;; logwatch) shift finished=0 while [ $finished -eq 0 -a $# -ne 0 ]; do option=$1 case $option in -*) option=${option#-} [ -z "$option" ] && usage 1 while [ -n "$option" ]; do case $option in v*) VERBOSE=$(($VERBOSE + 1 )) option=${option#v} ;; q*) VERBOSE=$(($VERBOSE - 1 )) option=${option#q} ;; m*) SHOWMACS=Yes option=${option#m} ;; -) finished=1 option= ;; *) usage 1 ;; esac done shift ;; *) finished=1 ;; esac done [ -n "$debugging" ] && set -x if [ $# -eq 1 ]; then logwatch $1 elif [ $# -eq 0 ]; then logwatch 30 else usage 1 fi ;; drop) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then mutex_on while [ $# -gt 1 ]; do shift qt $IPTABLES -D dynamic -s $1 -j reject qt $IPTABLES -D dynamic -s $1 -j DROP qt $IPTABLES -D dynamic -s $1 -j logreject qt $IPTABLES -D dynamic -s $1 -j logdrop $IPTABLES -A dynamic -s $1 -j DROP || break 1 echo "$1 Dropped" done mutex_off else error_message "ERROR: Shorewall is not started" exit 2 fi ;; logdrop) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then mutex_on while [ $# -gt 1 ]; do shift qt $IPTABLES -D dynamic -s $1 -j reject qt $IPTABLES -D dynamic -s $1 -j DROP qt $IPTABLES -D dynamic -s $1 -j logreject qt $IPTABLES -D dynamic -s $1 -j logdrop $IPTABLES -A dynamic -s $1 -j logdrop || break 1 echo "$1 Dropped" done mutex_off else error_message "ERROR: Shorewall is not started" exit 2 fi ;; reject|logreject) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then mutex_on while [ $# -gt 1 ]; do shift qt $IPTABLES -D dynamic -s $1 -j reject qt $IPTABLES -D dynamic -s $1 -j DROP qt $IPTABLES -D dynamic -s $1 -j logreject qt $IPTABLES -D dynamic -s $1 -j logdrop $IPTABLES -A dynamic -s $1 -j $COMMAND || break 1 echo "$1 Rejected" done mutex_off else error_message "ERROR: Shorewall is not started" exit 2 fi ;; allow) [ -n "$debugging" ] && set -x [ $# -eq 1 ] && usage 1 if shorewall_is_started ; then mutex_on while [ $# -gt 1 ]; do shift if qt $IPTABLES -D dynamic -s $1 -j reject ||\ qt $IPTABLES -D dynamic -s $1 -j DROP ||\ qt $IPTABLES -D dynamic -s $1 -j logdrop ||\ qt $IPTABLES -D dynamic -s $1 -j logreject then echo "$1 Allowed" else echo "$1 Not Dropped or Rejected" fi done mutex_off else error_message "ERROR: Shorewall is not started" exit 2 fi ;; save) [ -n "$debugging" ] && set -x case $# in 1) ;; 2) RESTOREFILE="$2" validate_restorefile '' ;; *) usage 1 ;; esac RESTOREPATH=${VARDIR}/$RESTOREFILE [ "$nolock" ] || mutex_on save_config [ "$nolock" ] || mutex_off ;; forget) 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 [ -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 *.*.*.*-*.*.*.*) ip_range $2 ;; *) usage 1 ;; esac ;; ipdecimal) [ -n "$debugging" ] && set -x case $2 in *.*.*.*) echo " $(decodeaddr $2)" ;; *) echo " $(encodeaddr $2)" ;; esac ;; restore) shift restore_command $@ ;; call) [ -n "$debugging" ] && set -x # # Undocumented way to call functions in ${SHAREDIR}/functions directly # shift $@ ;; help) shift [ $# -ne 1 ] && usage 1 help $@ ;; safe-restart|safe-start) shift safe_commands $@ ;; *) usage 1 ;; esac