forked from extern/shorewall_code
cd4e9654d8
------- Forwarded message follows ------- From: istvan@istvan.org To: shorewall-users@lists.sourceforge.net Date sent: Thu, 19 May 2016 09:10:21 +0200 Subject: [Shorewall-users] Shorewall-lite on OpenWRT Send reply to: Shorewall Users <shorewall-users@lists.sourceforge.net> <mailto:shorewall-users-request@lists.sourceforge.net?subject=unsubscribe> <mailto:shorewall-users-request@lists.sourceforge.net?subject=subscribe> Hi there, I use Shorewall on an OpenWRT distribution and I experience 2 problems. I have solved them myself and report them here to help others with it. Shorewall version: shorewall[6]-lite 5.0.4 OpenWRT version: Chaos Calmer 15.05, r46767 Problem 1: Shorewall uses the lock utility from openwrt. I believe it is used in the wrong way. File lib.common line 775 First it passes arguments which the utility doesn't use/know. The util accepts them dumbly and continues to create a lockfile. It has no time-out functionality. I do not know the meaning of the r1 argument. Second the mutex_off simply deletes the lockfile by using the utility rm. This way a stale lock process keeps running. After a while the router is running a high number of stale processes which has impact on the load of the router. The correct way is to use "lock -u /lib/shorewall-lite/lock". This way the lockfile will be removed and the process will be terminated accordingly. To make it work for me, I no more let shorewall use the lock utility by using an ugly hack. Problem 2: An fgrep on the output of the type utility is wrongly coded. The output of the type command probably has been changed. File lib.cli line 4343 It is coded: "if type $1 2> /dev/null | fgrep -q 'is a function'; then" To make it work for me, it should be coded: "if type $1 2> /dev/null | fgrep -q 'is a shell function'; then" With regards, Stefan ------- End of forwarded message ------- Tom, attached as code.patch, are the patches that I believe will correct those issues In addition to those patches I've also added 3 patches: - Patch 1 will emulate the -p flag of the ps utility which is not available on openwrt. - The last two patches will add "file" to the progress message of SYSCONFFILE to make it more consistent among the installers. In shorewall-init/install.sh the else clause between the line 586 and 597 will only work for a sysvinit script. Should I make it also work for a systemd service script or can't we simply remove that else clause? In the compiled firewall script the comments before and after the functions imported from lib.common have two slashes in the path: $ grep -H lib.common firewall firewall:# Functions imported from /usr/share/shorewall//lib.common firewall:# End of imports from /usr/share/shorewall//lib.common -Matt -------------- Enclosure number 1 ---------------- >From 6ff651108df33ab8be4562caef03a8582e9eac5e Mon Sep 17 00:00:00 2001 From: Matt Darfeuille <matdarf@gmail.com> Date: Tue, 24 May 2016 13:10:28 +0200 Subject: [PATCH 1/8] Emulate 'ps -p' using grep to work on openwrt Signed-off-by: Matt Darfeuille <matdarf@gmail.com> Signed-off-by: Tom Eastep <teastep@shorewall.net>
4608 lines
110 KiB
Plaintext
4608 lines
110 KiB
Plaintext
#
|
|
# Shorewall 5.0 -- /usr/share/shorewall/lib.cli.
|
|
#
|
|
# (c) 1999-2015 - Tom Eastep (teastep@shorewall.net)
|
|
#
|
|
# Complete documentation is available at http://shorewall.net
|
|
#
|
|
# This program is part of Shorewall.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by the
|
|
# Free Software Foundation, either version 2 of the license or, at your
|
|
# option, any later version.
|
|
#
|
|
# 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, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# This library contains the command processing code common to /sbin/shorewall[6] and
|
|
# /sbin/shorewall[6]-lite. In Shorewall and Shorewall6, the lib.cli-std library is
|
|
# loaded after this one and replaces some of the functions declared here.
|
|
#
|
|
|
|
SHOREWALL_CAPVERSION=50004
|
|
|
|
[ -n "${g_program:=shorewall}" ]
|
|
|
|
if [ -z "$g_readrc" ]; then
|
|
#
|
|
# This is modified by the installer when ${SHAREDIR} <> /usr/share
|
|
#
|
|
. /usr/share/shorewall/shorewallrc
|
|
|
|
g_sharedir="$SHAREDIR"/$g_program
|
|
g_confdir="$CONFDIR"/$g_program
|
|
g_readrc=1
|
|
fi
|
|
|
|
. ${SHAREDIR}/shorewall/lib.base
|
|
|
|
#
|
|
# Issue an error message and die
|
|
#
|
|
startup_error() {
|
|
echo " ERROR: $@" >&2
|
|
kill $$
|
|
exit 1
|
|
}
|
|
|
|
#
|
|
# 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 [ $g_family -eq 4 ]; then
|
|
if qt mywhich awk ; then
|
|
awk 'BEGIN { sline=""; };\
|
|
/^-[jg]/ { print sline $0; next };\
|
|
/-m policy.*-[jg] / { 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
|
|
else
|
|
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
|
|
;;
|
|
.safe|.try)
|
|
;;
|
|
.*|NONE)
|
|
error_message "ERROR: Reserved File Name: $RESTOREFILE"
|
|
exit 2
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# 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
|
|
# <enter> to terminate the delay
|
|
#
|
|
timed_read ()
|
|
{
|
|
read -t $timeout foo 2> /dev/null
|
|
|
|
test $? -eq 2 && sleep $timeout
|
|
}
|
|
|
|
#
|
|
# Determine if 'syslogd -C' or logd -S is running
|
|
#
|
|
syslog_circular_buffer() {
|
|
local pid
|
|
local tty
|
|
local flags
|
|
local time
|
|
local path
|
|
local args
|
|
local arg
|
|
|
|
ps w 2> /dev/null | (
|
|
while read pid tty stat time path args; do
|
|
case $path in
|
|
syslogd|*/syslogd)
|
|
for arg in $args; do
|
|
case $arg in
|
|
-C*)
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
logd|*/logd)
|
|
for arg in $args; do
|
|
case $arg in
|
|
-S*)
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
;;
|
|
esac
|
|
done
|
|
|
|
return 1 )
|
|
}
|
|
|
|
setup_logread() {
|
|
[ -z "$LOGFILE" ] && LOGFILE=/var/log/messages
|
|
|
|
if syslog_circular_buffer; then
|
|
LOGFILE=logread
|
|
if qt mywhich tac; then
|
|
g_logread="logread | tac"
|
|
else
|
|
g_logread="logread"
|
|
fi
|
|
elif [ -r $LOGFILE ]; then
|
|
if qt mywhich tac; then
|
|
g_logread="tac $LOGFILE"
|
|
else
|
|
g_logread="cat $LOGFILE"
|
|
fi
|
|
else
|
|
fatal_error "LOGFILE ($LOGFILE) does not exist or is not readable!"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Display the last $1 packets logged
|
|
#
|
|
packet_log() # $1 = number of messages
|
|
{
|
|
if qt mywhich tac; then
|
|
if [ -n "$g_showmacs" -o $VERBOSITY -gt 2 ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | head -n$1 | tac | sed 's/ kernel://; s/\[.*\] //' | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*:.*DST=' | head -n$1 | tac | sed -r 's/ kernel://; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
elif [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | head -n$1 | tac | sed 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] '// | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*:.*DST=' | head -n$1 | tac | sed -r 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
else
|
|
if [ -n "$g_showmacs" -o $VERBOSITY -gt 2 ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | tail -n$1 | sed 's/ kernel://; s/\[.*\] //' | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*:.*DST=' | tail -n$1 | sed -r 's/ kernel://; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
elif [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | tail -n$1 | sed 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] '// | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*:.*DST=' | tail -n$1 | sed -r 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
fi
|
|
}
|
|
|
|
search_log() # $1 = IP address to search for
|
|
{
|
|
if qt mywhich tac; then
|
|
if [ -n "$g_showmacs" -o $VERBOSITY -gt 2 ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | tac | sed 's/ kernel://; s/\[.*\] //' | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | tac | sed -r 's/ kernel://; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
elif [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | tac | sed 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] '// | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | tac | sed -r 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
else
|
|
if [ -n "$g_showmacs" -o $VERBOSITY -gt 2 ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | sed 's/ kernel://; s/\[.*\] //' | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | sed -r 's/ kernel://; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
elif [ $g_family -eq 4 ]; then
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | sed 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] '// | sed s/" $host $LOGFORMAT"/" "/
|
|
else
|
|
$g_logread | grep 'IN=.* OUT=.*SRC=.*\..*DST=' | grep "$1" | sed -r 's/ kernel://; s/MAC=.* SRC=/SRC=/; s/\[.*\] //; s/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | sed s/" $host $LOGFORMAT"/" "/
|
|
fi
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Show traffic control information
|
|
#
|
|
show_tc1() {
|
|
|
|
show_one_tc() {
|
|
local device
|
|
device=${1%@*}
|
|
qdisc=$(tc qdisc list dev $device)
|
|
|
|
if [ -n "$qdisc" ]; then
|
|
echo Device $device:
|
|
tc -s -d qdisc show dev $device
|
|
echo
|
|
tc -s -d class show dev $device
|
|
echo
|
|
fi
|
|
}
|
|
|
|
if [ $# -gt 0 ]; then
|
|
show_one_tc $1
|
|
else
|
|
ip -o link list | while read inx interface details; do
|
|
show_one_tc ${interface%:}
|
|
done
|
|
fi
|
|
|
|
}
|
|
|
|
show_tc() {
|
|
echo "$g_product $SHOREWALL_VERSION Traffic Control at $g_hostname - $(date)"
|
|
echo
|
|
shift
|
|
|
|
if [ -z "$1" ]; then
|
|
$g_tool -t mangle -L -n -v | $output_filter
|
|
echo
|
|
fi
|
|
|
|
show_tc1 $1
|
|
}
|
|
|
|
#
|
|
# Show classifier information
|
|
#
|
|
show_classifiers() {
|
|
|
|
show_one_classifier() {
|
|
local device
|
|
device=${1%@*}
|
|
qdisc=$(tc qdisc list dev $device)
|
|
|
|
if [ -n "$qdisc" ]; then
|
|
echo Device $device:
|
|
qt tc -s filter ls root dev $device && tc -s filter ls root dev $device | grep -v '^$'
|
|
tc filter show dev $device
|
|
tc class show dev $device | fgrep 'leaf ' | fgrep -v ' hfsc' | sed 's/^.*leaf //;s/ .*//' | while read class; do
|
|
if [ -n "$class" ]; then
|
|
echo
|
|
echo Node $class
|
|
tc filter show dev $device parent $class
|
|
fi
|
|
done
|
|
echo
|
|
fi
|
|
}
|
|
|
|
ip -o link list | while read inx interface details; do
|
|
show_one_classifier ${interface%:}
|
|
done
|
|
|
|
}
|
|
|
|
#
|
|
# Display blacklist chains
|
|
#
|
|
blacklist_filter() {
|
|
awk \
|
|
'BEGIN { prnt=0; }; \
|
|
/^Members:/ { print "Dynamic:"; prnt=1; next; }; \
|
|
{ if (prnt == 1) print; };'
|
|
}
|
|
|
|
show_bl() {
|
|
[ -n "$g_blacklistipset" ] && ipset -L $g_blacklistipset | blacklist_filter && echo
|
|
$g_tool -L $g_ipt_options | \
|
|
awk 'BEGIN {prnt=0; };
|
|
/^$/ {if (prnt == 1) print ""; prnt=0; };
|
|
/Chain .*~ / {prnt=1; };
|
|
/Chain dynamic / {prnt=1; };
|
|
{if (prnt == 1) print; };
|
|
END {if (prnt == 1 ) print "" };'
|
|
}
|
|
|
|
#
|
|
# Watch the Firewall Log
|
|
#
|
|
logwatch() # $1 = timeout -- if negative, prompt each time that
|
|
# an 'interesting' packet count changes
|
|
{
|
|
setup_logread
|
|
|
|
host=$(echo $g_hostname | sed 's/\..*$//')
|
|
oldrejects=$($g_tool -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 ($LOGFILE)"
|
|
echo
|
|
|
|
show_reset
|
|
|
|
rejects=$($g_tool -L -v -n | grep 'LOG')
|
|
|
|
if [ "$rejects" != "$oldrejects" ]; then
|
|
oldrejects="$rejects"
|
|
|
|
$g_ring_bell
|
|
|
|
packet_log 40
|
|
|
|
if [ "$pause" = "Yes" ]; then
|
|
echo
|
|
echo $g_echo_n 'Enter any character to continue: '
|
|
read foo
|
|
else
|
|
timed_read
|
|
fi
|
|
else
|
|
echo
|
|
packet_log 40
|
|
timed_read
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
#
|
|
# Try to find the arptables binary -- sets the variable 'arptables'
|
|
#
|
|
resolve_arptables() {
|
|
arptables="$ARPTABLES"
|
|
|
|
[ -n "${arptables:=arptables}" ]
|
|
|
|
case $arptables in
|
|
*/*)
|
|
;;
|
|
*)
|
|
arptables=$(mywhich "$arptables")
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# Try to run the 'savesets' command
|
|
#
|
|
savesets() {
|
|
local supported
|
|
|
|
supported=$(run_it ${VARDIR}/firewall help | fgrep savesets )
|
|
|
|
[ -n "$supported" ] && run_it ${VARDIR}/firewall savesets ${g_restorepath}-ipsets
|
|
}
|
|
|
|
#
|
|
# Proactive save of the current ipset contents
|
|
#
|
|
savesets1() {
|
|
local supported
|
|
|
|
supported=$(run_it ${VARDIR}/firewall help | fgrep savesets )
|
|
|
|
[ -n "$supported" ] && run_it ${VARDIR}/firewall savesets ${VARDIR}/ipsets.save && progress_message3 "The ipsets have been saved to ${VARDIR}/ipsets.save"
|
|
}
|
|
|
|
#
|
|
# Save currently running configuration
|
|
#
|
|
do_save() {
|
|
local status
|
|
local arptables
|
|
status=0
|
|
|
|
if [ -f ${VARDIR}/firewall ]; then
|
|
if $iptables_save | grep -v -- '-A dynamic.* -j ACCEPT' > ${VARDIR}/restore-$$; then
|
|
cp -f ${VARDIR}/firewall $g_restorepath
|
|
mv -f ${VARDIR}/restore-$$ ${g_restorepath}-iptables
|
|
chmod +x $g_restorepath
|
|
echo " Currently-running Configuration Saved to $g_restorepath"
|
|
run_user_exit save
|
|
else
|
|
rm -f ${VARDIR}/restore-$$
|
|
echo " ERROR: Currently-running Configuration Not Saved" >&2
|
|
status=1
|
|
fi
|
|
else
|
|
echo " ERROR: ${VARDIR}/firewall does not exist" >&2
|
|
status=1
|
|
fi
|
|
|
|
case ${SAVE_ARPTABLES:=No} in
|
|
[Yy]es)
|
|
resolve_arptables
|
|
|
|
if [ -n "$arptables" ]; then
|
|
if ${arptables}-save > ${VARDIR}/restore-$$; then
|
|
if grep -q '^-A' ${VARDIR}/restore-$$; then
|
|
mv -f ${VARDIR}/restore-$$ ${g_restorepath}-arptables
|
|
else
|
|
rm -f ${VARDIR}/restore-$$
|
|
fi
|
|
fi
|
|
else
|
|
case "$ARPTABLES" in
|
|
*/*)
|
|
error_message "ERROR: ARPTABLES=$ARPTABLES does not exist or is not executable - arptables not saved"
|
|
;;
|
|
*)
|
|
error_message "ERROR: The arptables utility cannot be located - arptables not saved"
|
|
;;
|
|
esac
|
|
|
|
rm -f ${g_restorepath}-arptables
|
|
fi
|
|
;;
|
|
[Nn]o)
|
|
rm -f ${g_restorepath}-arptables
|
|
;;
|
|
*)
|
|
error_message "WARNING: Invalid value ($SAVE_ARPTABLES) for SAVE_ARPTABLES"
|
|
;;
|
|
esac
|
|
|
|
if ! savesets; then
|
|
case ${SAVE_IPSETS:=No} in
|
|
[Yy]es)
|
|
case ${IPSET:=ipset} in
|
|
*/*)
|
|
if [ ! -x "$IPSET" ]; then
|
|
error_message "ERROR: IPSET=$IPSET does not exist or is not executable - ipsets are not saved"
|
|
IPSET=
|
|
fi
|
|
;;
|
|
*)
|
|
IPSET="$(mywhich $IPSET)"
|
|
[ -n "$IPSET" ] || error_message "ERROR: The ipset utility cannot be located - ipsets are not saved"
|
|
;;
|
|
esac
|
|
|
|
if [ -n "$IPSET" ]; then
|
|
if eval $IPSET -S > ${VARDIR}/ipsets.tmp; then
|
|
#
|
|
# Don't save an 'empty' file
|
|
#
|
|
grep -qE -- '^(-N|create )' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${g_restorepath}-ipsets
|
|
fi
|
|
fi
|
|
;;
|
|
[Nn]o|ipv4|ipv6)
|
|
;;
|
|
*)
|
|
error_message "WARNING: Invalid value ($SAVE_IPSETS) for SAVE_IPSETS"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
return $status
|
|
}
|
|
|
|
save_config() {
|
|
|
|
local result
|
|
result=1
|
|
|
|
iptables_save=${g_tool}-save
|
|
|
|
[ -x $iptables_save ] || echo "$iptables-save does not exist or is not executable" >&2
|
|
|
|
[ -n "$g_counters" ] && iptables_save="$iptables_save --counters"
|
|
|
|
if product_is_started ; then
|
|
[ -d ${VARDIR} ] || mkdir -p ${VARDIR}
|
|
|
|
if [ -f $g_restorepath -a ! -x $g_restorepath ]; then
|
|
echo " ERROR: $g_restorepath exists and is not a saved $g_product configuration" >&2
|
|
else
|
|
case $RESTOREFILE in
|
|
capabilities|chains|default_route|firewall|firewall.conf|nat|proxyarp|restarted|rt_tables|save|state|undo_routing|zones)
|
|
echo " ERROR: Reserved file name: $RESTOREFILE" >&2
|
|
;;
|
|
*)
|
|
validate_restorefile RESTOREFILE
|
|
if do_save; then
|
|
rm -f ${VARDIR}/save
|
|
result=0
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
else
|
|
echo "$g_product isn't started" >&2
|
|
fi
|
|
|
|
return $result
|
|
|
|
}
|
|
|
|
#
|
|
# Recent Linux systems seem to like to print a randomly-ordered
|
|
# view of routing tables. This hack sorts the output into the
|
|
# order we all know and love
|
|
#
|
|
sort_routes() {
|
|
local dest
|
|
local second
|
|
local rest
|
|
local vlsm
|
|
local maxvlsm
|
|
local rule
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
maxvlsm=032
|
|
else
|
|
maxvlsm=128
|
|
fi
|
|
|
|
while read dest second rest; do
|
|
if [ -n "$dest" ]; then
|
|
rule="$dest $second $rest"
|
|
case "$dest" in
|
|
default)
|
|
echo "000 $rule"
|
|
;;
|
|
blackhole|local)
|
|
case "$second" in
|
|
*/*)
|
|
vlsm=${second#*/}
|
|
printf "%03d %s\n" $vlsm "$rule"
|
|
;;
|
|
*)
|
|
echo "$maxvlsm $rule"
|
|
;;
|
|
esac
|
|
;;
|
|
*/*)
|
|
vlsm=${dest#*/}
|
|
printf "%03d %s\n" $vlsm "$rule"
|
|
;;
|
|
*)
|
|
echo "$maxvlsm $rule"
|
|
;;
|
|
esac
|
|
fi
|
|
done | sort -r | while read dest rest; do echo $rest; done
|
|
}
|
|
|
|
#
|
|
# Isolate the table in the routing rules being read from stdin.
|
|
# Piping through sed to remove trailing whitespace works around
|
|
# recent 'features' in dash and ip.
|
|
#
|
|
find_tables() {
|
|
sed -r 's/[[:space:]]+$//' | while read rule; do
|
|
echo ${rule##* }
|
|
done
|
|
}
|
|
|
|
#
|
|
# Show routing configuration
|
|
#
|
|
show_routing() {
|
|
local rule
|
|
local table
|
|
|
|
if [ -n "$(ip -$g_family rule list)" ]; then
|
|
heading "Routing Rules"
|
|
ip -$g_family rule list
|
|
ip -$g_family rule list | find_tables | sort -u | while read table; do
|
|
heading "Table $table:"
|
|
if [ $g_family -eq 6 ]; then
|
|
ip -$g_family -o route list table $table | grep -vF cache | sort_routes
|
|
else
|
|
ip -4 -o route list table $table | sort_routes
|
|
fi
|
|
done
|
|
|
|
if [ -n "$g_routecache" ]; then
|
|
heading "Route Cache"
|
|
ip -$g_family route list cache
|
|
fi
|
|
else
|
|
heading "Routing Table"
|
|
if [ $g_family -eq 6 ]; then
|
|
ip -$g_family -o route list | grep -vF cache | sort_routes
|
|
else
|
|
ip -4 -o route list table $table | sort_routes
|
|
fi
|
|
fi
|
|
}
|
|
|
|
determine_ipset_version() {
|
|
local setname
|
|
|
|
if [ -z "$IPSET" -o "$IPSET" = "ipset" ]; then
|
|
IPSET=$(mywhich ipset)
|
|
[ -n "$IPSET" ] || fatal_error "The ipset utility cannot be located"
|
|
fi
|
|
|
|
setname=fooX$$
|
|
|
|
qt ipset -X $setname # Just in case something went wrong the last time
|
|
|
|
if qt ipset -N $setname hash:ip family inet; then
|
|
qt ipset -X $setname
|
|
IPSETN="$IPSET"
|
|
else
|
|
IPSETN="$IPSET -n"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# 'list dynamic' command executor
|
|
#
|
|
find_sets() {
|
|
local junk
|
|
local setname
|
|
|
|
$IPSETN -L | egrep "^Name: ${1}(_.+)?$" | while read junk setname; do echo $setname; done
|
|
}
|
|
|
|
list_zone() {
|
|
|
|
local sets
|
|
local setname
|
|
|
|
determine_ipset_version
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
sets=$($IPSETN -L | egrep "^$1(_.+)?");
|
|
else
|
|
sets=$($IPSETN -L | egrep "^6_$1(_.+)?")
|
|
fi
|
|
|
|
[ -n "$sets" ] || sets=$(find_sets $1)
|
|
|
|
for setname in $sets; do
|
|
echo "${setname#${1}_}:"
|
|
$IPSETN -L $setname | awk 'BEGIN {prnt=0;}; \
|
|
/^Members:/ {prnt=1; next; }; \
|
|
/^Bindings:/ {prnt=0; }; \
|
|
{ if (prnt == 1) print " ", $1; };'
|
|
done
|
|
}
|
|
|
|
option_error() {
|
|
fatal_error "The $COMMAND command does not accept this option: -$1"
|
|
}
|
|
|
|
too_many_arguments() {
|
|
fatal_error "Too many arguments: $1"
|
|
}
|
|
|
|
missing_argument() {
|
|
fatal_error "Missing argument"
|
|
}
|
|
|
|
missing_option_value() {
|
|
fatal_error "The $1 option requires a value"
|
|
}
|
|
|
|
version_command() {
|
|
local finished
|
|
finished=0
|
|
local all
|
|
all=
|
|
local product
|
|
local compiletime
|
|
|
|
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}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ $# -gt 0 ] && too_many_arguments
|
|
|
|
if [ -n "$all" ]; then
|
|
echo "shorewall-core: $(cat ${SHAREDIR}/shorewall/coreversion)"
|
|
|
|
for product in shorewall shorewall6 shorewall-lite shorewall6-lite shorewall-init; do
|
|
if [ -f ${SHAREDIR}/$product/version ]; then
|
|
echo "$product: $(cat ${SHAREDIR}/$product/version)"
|
|
fi
|
|
done
|
|
|
|
if [ "$(id -u)" -eq 0 -a -f $g_firewall ]; then
|
|
compiletime=$(run_it $g_firewall info 2>/dev/null)
|
|
|
|
case $compiletime in
|
|
compiled\ *)
|
|
echo "$g_firewall was $compiletime"
|
|
;;
|
|
*)
|
|
echo "$g_firewall was compiled by Shorewall version $(run_it $g_firewall version))"
|
|
;;
|
|
esac
|
|
fi
|
|
else
|
|
echo $SHOREWALL_VERSION
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Show Filter - For Shorewall[6]-lite, if there was an scfilter file at compile-time,
|
|
# then the compiler generated another version of this function and
|
|
# embedded it in the firewall.conf file. That version supersedes this
|
|
# one.
|
|
#
|
|
show_connections_filter() {
|
|
local filter
|
|
local command
|
|
local first
|
|
|
|
command=${SHOREWALL_SHELL}
|
|
|
|
filter=$(find_file scfilter)
|
|
|
|
if [ -f $filter ]; then
|
|
first=$(head -n1 $filter)
|
|
|
|
case $first in
|
|
\#!*)
|
|
command=${first#\#!}
|
|
;;
|
|
esac
|
|
|
|
$command $filter
|
|
else
|
|
cat -
|
|
fi
|
|
}
|
|
|
|
show_nfacct() {
|
|
if [ -n "$NFACCT" -a ! -x "$NFACCT" ]; then
|
|
error_message "WARNING: NFACCT=$NFACCT does not exist or is not executable"
|
|
NFACCT=
|
|
else
|
|
NFACCT=$(mywhich nfacct)
|
|
[ -n "$NFACCT" ] || echo "No NF Accounting defined (nfacct not found)"
|
|
fi
|
|
|
|
if [ -n "$NFACCT" ]; then
|
|
$NFACCT list
|
|
echo
|
|
fi
|
|
}
|
|
|
|
show_event() {
|
|
local address
|
|
local ttl_label
|
|
local ttl
|
|
local last_seen
|
|
local last
|
|
local oldest_pkt
|
|
local oldest
|
|
local intimes
|
|
local outtimes1
|
|
local outtimes2
|
|
local time
|
|
local count
|
|
|
|
while read address ttl_label ttl last_seen last oldest_pkt oldest intimes; do
|
|
case $address in
|
|
*.*)
|
|
[ $g_family -eq 4 ] || continue
|
|
;;
|
|
*:*)
|
|
[ $g_family -eq 6 ] || continue
|
|
;;
|
|
*)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
outtimes1=''
|
|
outtimes2=''
|
|
count=0
|
|
last=$((($currenttime - $last)/1000))
|
|
for time in $intimes; do
|
|
time=${time%,}
|
|
time=$(($currenttime - $time))
|
|
if [ $time -lt 10 ]; then
|
|
time="000$time"
|
|
elif [ $time -lt 100 ]; then
|
|
time="00$time"
|
|
elif [ $time -lt 1000 ]; then
|
|
time="0$time"
|
|
fi
|
|
|
|
if [ $count -lt $oldest ]; then
|
|
outtimes2="$outtimes2 $time"
|
|
else
|
|
outtimes1="$outtimes1 $time"
|
|
fi
|
|
|
|
count=$(($count + 1))
|
|
done
|
|
|
|
outtimes1="${outtimes1}${outtimes2}"
|
|
|
|
[ -n "$outtimes1" ] && outtimes1=$(echo "$outtimes1 " | sed -r 's/([[:digit:]]{3}) /\.\1, /g') && outtimes1=${outtimes1%, }
|
|
|
|
echo " $address : ${outtimes1}"
|
|
done < /proc/net/xt_recent/$1
|
|
}
|
|
|
|
show_events() {
|
|
local file
|
|
local base
|
|
local currenttime
|
|
|
|
if [ -f /proc/net/xt_recent/%CURRENTTIME ]; then
|
|
echo -127.0.0.1 > /proc/net/xt_recent/%CURRENTTIME
|
|
echo +127.0.0.1 > /proc/net/xt_recent/%CURRENTTIME
|
|
currenttime=$(cat /proc/net/xt_recent/%CURRENTTIME | cut -d ' ' -f 5 -)
|
|
# echo Current time: $currenttime
|
|
# echo
|
|
else
|
|
currenttime=0
|
|
fi
|
|
|
|
if [ $# -gt 0 ]; then
|
|
for event in $@ ; do
|
|
if [ -f /proc/net/xt_recent/$event ]; then
|
|
echo $event:
|
|
show_event $event
|
|
echo
|
|
else
|
|
error_message "WARNING: Event $event not found"
|
|
fi
|
|
done
|
|
else
|
|
for file in /proc/net/xt_recent/*; do
|
|
base=$(basename $file)
|
|
|
|
if [ $base != %CURRENTTIME ]; then
|
|
echo $base
|
|
show_event $base
|
|
echo
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
show_actions() {
|
|
if [ -f ${g_confdir}/actions ]; then
|
|
cat ${g_sharedir}/actions.std ${g_confdir}/actions | grep -Ev '^[#?[:space:]]|^$'
|
|
else
|
|
grep -Ev '^[#?[:space:]]|^$' ${g_sharedir}/actions.std
|
|
fi
|
|
}
|
|
|
|
show_chain() {
|
|
echo "$g_product $SHOREWALL_VERSION $([ $# -gt 1 ] && echo "Chains " || [ $# -gt 0 ] && echo "Chain " || echo $table Table)$* at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
if [ $# -gt 0 ]; then
|
|
for chain in $*; do
|
|
$g_tool -t $table -L $chain $g_ipt_options | $output_filter
|
|
echo
|
|
done
|
|
else
|
|
$g_tool -t $table -L $g_ipt_options | $output_filter
|
|
fi
|
|
}
|
|
|
|
show_chains() {
|
|
echo "$g_product $SHOREWALL_VERSION $([ $# -gt 1 ] && echo "Chains " || echo "Chain ")$* at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
for chain in $*; do
|
|
$g_tool -t $table -L $chain $g_ipt_options | $output_filter
|
|
echo
|
|
done
|
|
}
|
|
|
|
show_table() {
|
|
echo "$g_product $SHOREWALL_VERSION $table Table at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
$g_tool -t $table -L $g_ipt_options | $output_filter
|
|
}
|
|
|
|
show_nat() {
|
|
echo "$g_product $SHOREWALL_VERSION NAT Table at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
$g_tool -t nat -L $g_ipt_options | $output_filter
|
|
}
|
|
|
|
show_raw() {
|
|
echo "$g_product $SHOREWALL_VERSION RAW Table at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
$g_tool -t raw -L $g_ipt_options | $output_filter
|
|
}
|
|
|
|
show_rawpost() {
|
|
echo "$g_product $SHOREWALL_VERSION RAWPOST Table at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
$g_tool -t rawpost -L $g_ipt_options | $output_filter
|
|
}
|
|
|
|
show_mangle() {
|
|
echo "$g_product $SHOREWALL_VERSION Mangle Table at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
$g_tool -t mangle -L $g_ipt_options | $output_filter
|
|
}
|
|
|
|
show_classifiers_command() {
|
|
echo "$g_product $SHOREWALL_VERSION Classifiers at $g_hostname - $(date)"
|
|
echo
|
|
show_classifiers
|
|
}
|
|
|
|
show_ip_addresses() {
|
|
echo "$g_product $SHOREWALL_VERSION IP at $g_hostname - $(date)"
|
|
echo
|
|
ip -$g_family addr list
|
|
}
|
|
|
|
show_routing_command() {
|
|
echo "$g_product $SHOREWALL_VERSION Routing at $g_hostname - $(date)"
|
|
echo
|
|
show_routing
|
|
}
|
|
|
|
show_policies() {
|
|
echo "$g_product $SHOREWALL_VERSION Policies at $g_hostname - $(date)"
|
|
echo
|
|
[ -f ${VARDIR}/policies ] && cat ${VARDIR}/policies
|
|
}
|
|
|
|
show_ipa() {
|
|
echo "$g_product $SHOREWALL_VERSION per-IP Accounting at $g_hostname - $(date)"
|
|
echo
|
|
perip_accounting
|
|
}
|
|
|
|
show_arptables() {
|
|
echo "$g_product $SHOREWALL_VERSION arptables at $g_hostname - $(date)"
|
|
echo
|
|
$arptables -L -n -v
|
|
}
|
|
|
|
show_log() {
|
|
echo "$g_product $SHOREWALL_VERSION Log ($LOGFILE) at $g_hostname - $(date)"
|
|
echo
|
|
show_reset
|
|
host=$(echo $g_hostname | sed 's/\..*$//')
|
|
|
|
if [ $# -eq 2 ]; then
|
|
eval search_log $2
|
|
elif [ -n "$g_pager" ]; then
|
|
packet_log 100
|
|
else
|
|
packet_log 20
|
|
fi
|
|
}
|
|
|
|
show_connections() {
|
|
if [ $g_family -eq 4 ]; then
|
|
if [ -d /proc/sys/net/netfilter/ ]; then
|
|
local count
|
|
local max
|
|
count=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
|
|
max=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
|
|
echo "$g_product $SHOREWALL_VERSION Connections ($count out of $max) at $g_hostname - $(date)"
|
|
else
|
|
echo "$g_product $SHOREWALL_VERSION Connections at $g_hostname - $(date)"
|
|
fi
|
|
|
|
echo
|
|
|
|
if qt mywhich conntrack ; then
|
|
shift
|
|
conntrack -f ipv4 -L $@ | show_connections_filter
|
|
else
|
|
[ $# -gt 1 ] && too_many_arguments
|
|
if [ -f /proc/net/ip_conntrack ]; then
|
|
cat /proc/net/ip_conntrack | show_connections_filter
|
|
else
|
|
grep -v '^ipv6' /proc/net/nf_conntrack | show_connections_filter
|
|
fi
|
|
fi
|
|
elif qt mywhich conntrack ; then
|
|
shift
|
|
echo "$g_product $SHOREWALL_VERSION Connections at $g_hostname - $(date)"
|
|
echo
|
|
conntrack -f ipv6 -L $@ | show_connections_filter
|
|
else
|
|
[ $# -gt 1 ] && too_many_arguments
|
|
if [ -f /proc/sys/net/netfilter/nf_conntrack_count -a -f /proc/sys/net/nf_conntrack ]; then
|
|
local count=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
|
|
local max=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
|
|
echo "$g_product $SHOREWALL_VERSION Connections ($count of $max) at $g_hostname - $(date)"
|
|
echo
|
|
grep '^ipv6' /proc/net/nf_conntrack | sed -r 's/0000:/:/g; s/:::+/::/g; s/:0+/:/g' | show_connections_filter
|
|
fi
|
|
fi
|
|
}
|
|
|
|
show_nfacct_command() {
|
|
echo "$g_product $SHOREWALL_VERSION NF Accounting at $g_hostname - $(date)"
|
|
echo
|
|
show_nfacct
|
|
}
|
|
|
|
show_events_command() {
|
|
echo "$g_product $SHOREWALL_VERSION events at $g_hostname - $(date)"
|
|
echo
|
|
show_events
|
|
}
|
|
|
|
show_blacklists() {
|
|
echo "$g_product $SHOREWALL_VERSION blacklist chains at $g_hostname - $(date)"
|
|
echo
|
|
show_bl;
|
|
}
|
|
|
|
show_actions_sorted() {
|
|
show_actions | sort
|
|
}
|
|
|
|
show_macros() {
|
|
for directory in $(split $CONFIG_PATH); do
|
|
temp=
|
|
for macro in ${directory}/macro.*; do
|
|
case $macro in
|
|
*\*)
|
|
;;
|
|
*)
|
|
if [ -z "$temp" ]; then
|
|
echo
|
|
echo "Macros in $directory:"
|
|
echo
|
|
temp=Yes
|
|
fi
|
|
show_macro
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
}
|
|
|
|
#
|
|
# Show Command Executor
|
|
#
|
|
show_command() {
|
|
local finished
|
|
finished=0
|
|
local table
|
|
table=filter
|
|
local table_given
|
|
table_given=
|
|
local output_filter
|
|
output_filter=cat
|
|
local arptables
|
|
local macro
|
|
|
|
show_macro() {
|
|
foo=`grep 'This macro' $macro | sed 's/This macro //'`
|
|
if [ -n "$foo" ]; then
|
|
macro=${macro#*.}
|
|
foo=${foo%.*}
|
|
if [ ${#macro} -gt 10 ]; then
|
|
echo " $macro ${foo#\#}"
|
|
else
|
|
$g_echo_e " $macro \t${foo#\#}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# eliminates rules which have not been used from ip*tables' output
|
|
brief_output() {
|
|
awk \
|
|
'/^Chain / { heading1 = $0; getline heading2; printed = 0; next; };
|
|
/^ +0 +0 / { next; };
|
|
/^$/ { if ( printed == 1 ) { print $0; }; next; };
|
|
{ if ( printed == 0 ) { print heading1; print heading2; printed = 1 }; };
|
|
{ print; }';
|
|
}
|
|
|
|
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*)
|
|
VERBOSITY=$(($VERBOSITY + 1 ))
|
|
option=${option#v}
|
|
;;
|
|
x*)
|
|
g_ipt_options="-xnv"
|
|
option=${option#x}
|
|
;;
|
|
m*)
|
|
g_showmacs=Yes
|
|
option=${option#m}
|
|
;;
|
|
f*)
|
|
g_filemode=Yes
|
|
option=${option#f}
|
|
;;
|
|
t)
|
|
[ $# -eq 1 ] && missing_option_value -t
|
|
|
|
case $2 in
|
|
mangle|nat|filter|raw|rawpost)
|
|
table=$2
|
|
table_given=Yes
|
|
;;
|
|
*)
|
|
fatal_error "Invalid table name ($s)"
|
|
;;
|
|
esac
|
|
|
|
option=
|
|
shift
|
|
;;
|
|
l*)
|
|
g_ipt_options1="--line-numbers"
|
|
option=${option#l}
|
|
;;
|
|
c*)
|
|
g_routecache=Yes
|
|
option=${option#c}
|
|
;;
|
|
b*)
|
|
output_filter=brief_output
|
|
option=${option#b}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
g_ipt_options="$g_ipt_options $g_ipt_options1"
|
|
|
|
|
|
[ -n "$g_debugging" ] && set -x
|
|
|
|
case "$1" in
|
|
connections)
|
|
eval show_connections $@ $g_pager
|
|
;;
|
|
nat)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_nat $g_pager
|
|
;;
|
|
raw)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_raw $g_pager
|
|
;;
|
|
rawpost)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_rawpost $g_pager
|
|
;;
|
|
tos|mangle)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_mangle $g_pager
|
|
;;
|
|
log)
|
|
[ $# -gt 2 ] && too_many_arguments $2
|
|
|
|
setup_logread
|
|
eval show_log $g_pager
|
|
;;
|
|
tc)
|
|
[ $# -gt 2 ] && too_many_arguments $2
|
|
eval show_tc $@ $g_pager
|
|
;;
|
|
classifiers|filters)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_classifiers_command $g_pager
|
|
;;
|
|
zones)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
if [ -f ${VARDIR}/zones ]; then
|
|
echo "$g_product $SHOREWALL_VERSION Zones at $g_hostname - $(date)"
|
|
echo
|
|
while read zone type hosts; do
|
|
echo "$zone ($type)"
|
|
for host in $hosts; do
|
|
case $host in
|
|
exclude)
|
|
echo " exclude:"
|
|
;;
|
|
*)
|
|
echo " $host"
|
|
;;
|
|
esac
|
|
done
|
|
done < ${VARDIR}/zones
|
|
echo
|
|
else
|
|
fatal_error "${VARDIR}/zones does not exist"
|
|
fi
|
|
;;
|
|
capabilities)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
determine_capabilities
|
|
VERBOSITY=2
|
|
if [ -n "$g_filemode" ]; then
|
|
eval report_capabilities1 $g_pager
|
|
else
|
|
eval report_capabilities $g_pager
|
|
fi
|
|
;;
|
|
ip)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_ip_addresses $g_pager
|
|
;;
|
|
routing)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_routing_command $g_pager
|
|
;;
|
|
config)
|
|
. ${g_sharedir}/configpath
|
|
if [ -n "$g_filemode" ]; then
|
|
echo "CONFIG_PATH=$CONFIG_PATH"
|
|
echo "VARDIR=$VARDIR"
|
|
echo "LIBEXEC=${LIBEXECDIR}"
|
|
echo "SBINDIR=${SBINDIR}"
|
|
echo "CONFDIR=${CONFDIR}"
|
|
[ -n "$g_lite" ] && [ ${VARDIR} != /var/lib/$g_program ] && echo "LITEDIR=${VARDIR}"
|
|
else
|
|
echo "Default CONFIG_PATH is $CONFIG_PATH"
|
|
echo "Default VARDIR is /var/lib/$g_program"
|
|
echo "LIBEXEC is ${LIBEXECDIR}"
|
|
echo "SBINDIR is ${SBINDIR}"
|
|
echo "CONFDIR is ${CONFDIR}"
|
|
[ -n "$g_lite" ] && [ ${VARDIR} != /var/lib/$g_program ] && echo "LITEDIR is ${VARDIR}"
|
|
fi
|
|
;;
|
|
chain)
|
|
shift
|
|
eval show_chain $@ $g_pager
|
|
;;
|
|
vardir)
|
|
echo $VARDIR;
|
|
;;
|
|
policies)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_policies $g_pager
|
|
;;
|
|
ipa)
|
|
[ $g_family -eq 4 ] || fatal_error "'show ipa' is now available in $g_product"
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_ipa $g_pager
|
|
;;
|
|
marks)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
echo "$g_product $SHOREWALL_VERSION Mark Layout at $g_hostname - $(date)"
|
|
echo
|
|
[ -f ${VARDIR}/marks ] && cat ${VARDIR}/marks;
|
|
;;
|
|
nfacct)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_nfacct_command $g_pager
|
|
;;
|
|
arptables)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
resolve_arptables
|
|
if [ -n "$arptables" -a -x $arptables ]; then
|
|
eval show_arptables $g_pager
|
|
else
|
|
error_message "Cannot locate the arptables executable"
|
|
fi
|
|
;;
|
|
event)
|
|
[ $# -gt 1 ] || too_many_arguments $2
|
|
echo "$g_product $SHOREWALL_VERSION events at $g_hostname - $(date)"
|
|
echo
|
|
shift
|
|
show_events $@
|
|
;;
|
|
events)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_events_command $g_pager
|
|
;;
|
|
bl|blacklists)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_blacklists $g_pager
|
|
;;
|
|
opens)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
echo "$g_product $SHOREWALL_VERSION Temporarily opened connections at $g_hostname - $(date)"
|
|
|
|
if chain_exists dynamic; then
|
|
g_ipt_options="$g_ipt_options --line-numbers"
|
|
$g_tool -t filter -L dynamic $g_ipt_options | head -n2
|
|
$g_tool -t filter -L dynamic $g_ipt_options | fgrep ACCEPT | $output_filter
|
|
fi
|
|
;;
|
|
*)
|
|
case "$g_program" in
|
|
*-lite)
|
|
;;
|
|
*)
|
|
case $1 in
|
|
actions)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_actions_sorted $g_pager
|
|
return
|
|
;;
|
|
macro)
|
|
[ $# -ne 2 ] && too_many_arguments $2
|
|
for directory in $(split $CONFIG_PATH); do
|
|
if [ -f ${directory}/macro.$2 ]; then
|
|
echo "Shorewall $SHOREWALL_VERSION Macro $2 at $g_hostname - $(date)"
|
|
cat ${directory}/macro.$2
|
|
return
|
|
fi
|
|
done
|
|
echo " WARNING: Macro $2 not found" >&2
|
|
return
|
|
;;
|
|
macros)
|
|
[ $# -gt 1 ] && too_many_arguments $2
|
|
eval show_macros $g_pager
|
|
return
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
if [ $# -gt 0 ]; then
|
|
if [ $1 = dynamic -a $# -gt 1 ]; then
|
|
shift
|
|
[ $# -eq 1 ] || too_many_arguments $2
|
|
list_zone $1
|
|
return;
|
|
fi
|
|
|
|
[ -n "$table_given" ] || for chain in $*; do
|
|
if ! qt $g_tool -t $table -L $chain $g_ipt_options; then
|
|
error_message "ERROR: Chain '$chain' is not recognized by $g_tool."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
eval show_chains $@ $g_pager
|
|
else
|
|
eval show_table $g_pager
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
perip_accounting() {
|
|
if qt mywhich iptaccount; then
|
|
local hnames
|
|
local hname
|
|
|
|
hnames=$(iptaccount -a | grep '^Found table:' | cut -d ' ' -f 3)
|
|
|
|
if [ -n "$hnames" ]; then
|
|
for hname in $hnames; do
|
|
iptaccount -l $hname | egrep '^IP:|^Show'
|
|
echo
|
|
done
|
|
else
|
|
echo " No IP Accounting Tables Defined"
|
|
echo
|
|
fi
|
|
else
|
|
echo " iptaccount is not installed"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Dump Filter - For Shorewall-lite, if there was a dumpfilter file at compile-time,
|
|
# then the compiler generated another version of this function and
|
|
# embedded it in the firewall.conf file. That version supersedes this
|
|
# one.
|
|
#
|
|
dump_filter() {
|
|
local filter
|
|
local command
|
|
local first
|
|
|
|
command=${SHOREWALL_SHELL}
|
|
|
|
filter=$(find_file dumpfilter)
|
|
|
|
if [ -f $filter ]; then
|
|
first=$(head -n1 $filter)
|
|
|
|
case $first in
|
|
\#!*)
|
|
command=${first#\#!}
|
|
;;
|
|
esac
|
|
|
|
eval $command $filter $g_pager
|
|
else
|
|
cat -
|
|
fi
|
|
}
|
|
|
|
dump_filter_wrapper() {
|
|
eval dump_filter $g_pager
|
|
}
|
|
|
|
show_status() {
|
|
local compiletime
|
|
local state
|
|
|
|
if product_is_started ; then
|
|
[ $VERBOSITY -ge 1 ] && echo "$g_product is running"
|
|
status=0
|
|
else
|
|
[ $VERBOSITY -ge 1 ] && 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
|
|
|
|
if [ $VERBOSITY -ge 1 ]; then
|
|
if [ -f $g_firewall ]; then
|
|
compiletime=$(run_it $g_firewall info 2>/dev/null)
|
|
|
|
case $compiletime in
|
|
compiled\ *)
|
|
state="$state ($g_firewall $compiletime)"
|
|
;;
|
|
*)
|
|
state="$state ($g_firewall compiled by Shorewall version $(run_it $g_firewall version))"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
echo "State:$state"
|
|
echo
|
|
fi
|
|
|
|
}
|
|
|
|
#
|
|
# Dump Command Executor
|
|
#
|
|
do_dump_command() {
|
|
local finished
|
|
finished=0
|
|
local arptables
|
|
|
|
resolve_arptables
|
|
|
|
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*)
|
|
g_ipt_options="-xnv"
|
|
option=${option#x}
|
|
;;
|
|
m*)
|
|
g_showmacs=Yes
|
|
option=${option#m}
|
|
;;
|
|
l*)
|
|
g_ipt_options1="--line-numbers"
|
|
option=${option#l}
|
|
;;
|
|
c*)
|
|
g_routecache=Yes
|
|
option=${option#c}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
setup_logread
|
|
|
|
g_ipt_options="$g_ipt_options $g_ipt_options1"
|
|
|
|
[ $VERBOSITY -lt 2 ] && VERBOSITY=2
|
|
|
|
[ -n "$g_debugging" ] && set -x
|
|
[ $# -eq 0 ] || too_many_arguments $1
|
|
clear_term
|
|
echo "$g_product $SHOREWALL_VERSION Dump at $g_hostname - $(date)"
|
|
echo
|
|
|
|
if [ $g_family -eq 6 ] && [ -f ${SHAREDIR}/shorewall/version ]; then
|
|
echo " Shorewall $(cat ${SHAREDIR}/shorewall/version)"
|
|
echo
|
|
fi
|
|
show_status
|
|
show_reset
|
|
host=$(echo $g_hostname | sed 's/\..*$//')
|
|
$g_tool -L $g_ipt_options
|
|
|
|
if [ -n "$arptables" -a -x "$arptables" ]; then
|
|
heading "ARP rules"
|
|
$arptables -L -n -v
|
|
fi
|
|
|
|
heading "Log ($LOGFILE)"
|
|
packet_log 20
|
|
|
|
if qt $g_tool -t nat -L -n; then
|
|
heading "NAT Table"
|
|
$g_tool -t nat -L $g_ipt_options
|
|
fi
|
|
|
|
if qt $g_tool -t mangle -L -n; then
|
|
heading "Mangle Table"
|
|
$g_tool -t mangle -L $g_ipt_options
|
|
fi
|
|
|
|
if qt $g_tool -t raw -L -n; then
|
|
heading "Raw Table"
|
|
$g_tool -t raw -L $g_ipt_options
|
|
fi
|
|
|
|
if qt $g_tool -t rawpost -L -n; then
|
|
heading "Rawpost Table"
|
|
$g_tool -t rawpost -L $g_ipt_options
|
|
fi
|
|
|
|
local count
|
|
local max
|
|
|
|
if [ -f /proc/sys/net/netfilter/nf_conntrack_count ]; then
|
|
count=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
|
|
max=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
|
|
|
|
heading "Conntrack Table ($count out of $max)"
|
|
elif [ -f /proc/sys/net/ipv4/netfilter/ip_conntrack_count ]; then
|
|
count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count)
|
|
max=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max)
|
|
|
|
heading "Conntrack Table ($count out of $max)"
|
|
else
|
|
heading "Conntrack Table"
|
|
fi
|
|
|
|
if qt mywhich conntrack; then
|
|
conntrack -f ipv${g_family} -L 2> /dev/null
|
|
elif [ $g_family -eq 4 ]; then
|
|
[ -f /proc/net/ip_conntrack ] && cat /proc/net/ip_conntrack || grep -v '^ipv6' /proc/net/nf_conntrack
|
|
else
|
|
grep '^ipv6' /proc/net/nf_conntrack
|
|
fi
|
|
|
|
heading "IP Configuration"
|
|
ip -$g_family addr list
|
|
|
|
heading "IP Stats"
|
|
ip -stat link list
|
|
|
|
if qt mywhich brctl; then
|
|
heading "Bridges"
|
|
brctl show
|
|
fi
|
|
|
|
show_routing
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
heading "Per-IP Counters"
|
|
|
|
perip_accounting
|
|
fi
|
|
|
|
heading "NF Accounting"
|
|
show_nfacct
|
|
|
|
heading "Events"
|
|
show_events
|
|
|
|
if qt mywhich setkey; then
|
|
heading "PFKEY SPD"
|
|
setkey -DP
|
|
heading "PFKEY SAD"
|
|
setkey -D | grep -Ev '^[[:space:]](A:|E:)' # Don't divulge the keys
|
|
fi
|
|
|
|
heading "/proc"
|
|
show_proc /proc/version
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
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
|
|
else
|
|
for directory in /proc/sys/net/ipv6/conf/*; do
|
|
for file in forwarding proxy_ra proxy_ndp; do
|
|
show_proc $directory/$file
|
|
done
|
|
done
|
|
fi
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
heading "ARP"
|
|
if qt mywhich arp; then
|
|
arp -na
|
|
else
|
|
ip -4 neigh ls
|
|
ip -4 neigh ls proxy
|
|
fi
|
|
else
|
|
heading "Neighbors"
|
|
ip -6 neigh ls
|
|
fi
|
|
|
|
if qt mywhich lsmod; then
|
|
heading "Modules"
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
lsmod | grep -E '^(ip_|ipt_|iptable_|nf_|xt_)' | sort
|
|
else
|
|
lsmod | grep -E '^(x_|ip6|nf_|xt_)' | sort
|
|
fi
|
|
fi
|
|
|
|
determine_capabilities
|
|
echo
|
|
report_capabilities
|
|
|
|
echo
|
|
|
|
qt mywhich ss && ss -${g_family}tunap || { qt mywhich netstat && netatat -tunap; }
|
|
|
|
if [ -n "$TC_ENABLED" ]; then
|
|
heading "Traffic Control"
|
|
show_tc1
|
|
heading "TC Filters"
|
|
show_classifiers
|
|
fi
|
|
}
|
|
|
|
dump_command() {
|
|
do_dump_command $@ | dump_filter_wrapper
|
|
}
|
|
|
|
#
|
|
# Restore Comand Executor
|
|
#
|
|
restore_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=
|
|
;;
|
|
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}
|
|
;;
|
|
C*)
|
|
g_counters=Yes
|
|
option=${option#C}
|
|
;;
|
|
*)
|
|
option_error
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case $# in
|
|
0)
|
|
;;
|
|
1)
|
|
RESTOREFILE="$1"
|
|
validate_restorefile '<restore file>'
|
|
;;
|
|
*)
|
|
too_many_arguments $2
|
|
;;
|
|
esac
|
|
|
|
if [ -z "$STARTUP_ENABLED" ]; then
|
|
error_message "ERROR: Startup is disabled"
|
|
exit 6
|
|
fi
|
|
|
|
g_restorepath=${VARDIR}/$RESTOREFILE
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
|
|
if [ -x $g_restorepath ]; then
|
|
progress_message3 "Restoring $g_product..."
|
|
|
|
run_it $g_restorepath restore && progress_message3 "$g_product restored from ${VARDIR}/$RESTOREFILE"
|
|
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
else
|
|
echo "File $g_restorepath: file not found"
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
#
|
|
# 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() {
|
|
local timeout
|
|
timeout=${1:-60}
|
|
|
|
case $timeout in
|
|
*s)
|
|
;;
|
|
*m)
|
|
timeout=$((${timeout%m} * 60))
|
|
;;
|
|
*h)
|
|
timeout=$((${timeout%h} * 3600))
|
|
;;
|
|
esac
|
|
|
|
read -t $timeout 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 $timeout 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
|
|
v=$g_verbose_offset
|
|
local option
|
|
option=-
|
|
|
|
if [ -n "$g_use_verbosity" ]; then
|
|
echo "-v$g_use_verbosity"
|
|
elif [ $g_verbose_offset -gt 0 ]; then
|
|
while [ $v -gt 0 ]; do
|
|
option="${option}v"
|
|
v=$(($v - 1))
|
|
done
|
|
|
|
echo $option
|
|
elif [ $g_verbose_offset -lt 0 ]; then
|
|
while [ $v -lt 0 ]; do
|
|
option="${option}q"
|
|
v=$(($v + 1))
|
|
done
|
|
|
|
echo $option
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Executor for drop,reject,... commands
|
|
#
|
|
block() # $1 = command, $2 = Finished, $3 - $n addresses
|
|
{
|
|
local chain
|
|
chain=$1
|
|
local finished
|
|
finished=$2
|
|
local which
|
|
which='-s'
|
|
local range
|
|
range='--src-range'
|
|
|
|
if ! chain_exists dynamic; then
|
|
echo "Dynamic blacklisting is not enabled in the current $g_product configuration" >&2
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
exit 2
|
|
fi
|
|
|
|
shift 3
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case $1 in
|
|
from)
|
|
which='-s'
|
|
range='--src-range'
|
|
shift
|
|
continue
|
|
;;
|
|
to)
|
|
which='-d'
|
|
range='--dst-range'
|
|
shift
|
|
continue
|
|
;;
|
|
*-*)
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j reject
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j DROP
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j logreject
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j logdrop
|
|
$g_tool -A dynamic -m iprange $range $1 -j $chain || break 1
|
|
;;
|
|
*)
|
|
qt $g_tool -D dynamic $which $1 -j reject
|
|
qt $g_tool -D dynamic $which $1 -j DROP
|
|
qt $g_tool -D dynamic $which $1 -j logreject
|
|
qt $g_tool -D dynamic $which $1 -j logdrop
|
|
$g_tool -A dynamic $which $1 -j $chain || break 1
|
|
;;
|
|
esac
|
|
|
|
echo "$1 $finished"
|
|
shift
|
|
done
|
|
}
|
|
|
|
#
|
|
# Replace commas with spaces and echo the result
|
|
#
|
|
separate_list() {
|
|
local list
|
|
list="$@"
|
|
local part
|
|
local newlist
|
|
local firstpart
|
|
local lastpart
|
|
local enclosure
|
|
|
|
case "$list" in
|
|
*,|,*|*,,*|*[[:space:]]*)
|
|
#
|
|
# There's been whining about us not catching embedded white space in
|
|
# comma-separated lists. This is an attempt to snag some of the cases.
|
|
#
|
|
echo "WARNING -- invalid comma-separated list \"$@\"" >&2
|
|
;;
|
|
*\[*\]*)
|
|
#
|
|
# Where we need to embed comma-separated lists within lists, we enclose them
|
|
# within square brackets.
|
|
#
|
|
firstpart=${list%%\[*}
|
|
lastpart=${list#*\[}
|
|
enclosure=${lastpart%%\]*}
|
|
lastpart=${lastpart#*\]}
|
|
case $lastpart in
|
|
\,*)
|
|
case $firstpart in
|
|
*\,)
|
|
echo "$(separate_list ${firstpart%,}) [$enclosure] $(separate_list ${lastpart#,})"
|
|
;;
|
|
*)
|
|
echo "$(separate_list $firstpart)[$enclosure] $(separate_list ${lastpart#,})"
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
case $firstpart in
|
|
*\,)
|
|
echo "$(separate_list ${firstpart%,}) [$enclosure]$(separate_list $lastpart)"
|
|
;;
|
|
*)
|
|
echo "$(separate_list $firstpart)[$enclosure]$(separate_list $lastpart)"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
return
|
|
;;
|
|
esac
|
|
|
|
list="$@"
|
|
part="${list%%,*}"
|
|
newlist="$part"
|
|
|
|
while [ "x$part" != "x$list" ]; do
|
|
list="${list#*,}";
|
|
part="${list%%,*}";
|
|
newlist="$newlist $part";
|
|
done
|
|
|
|
echo "$newlist"
|
|
}
|
|
|
|
#
|
|
# add command executor
|
|
#
|
|
add_command() {
|
|
local interface host hostlist zone ipset
|
|
if ! product_is_started ; then
|
|
fatal_error "$g_product Not Started"
|
|
fi
|
|
|
|
determine_ipset_version
|
|
|
|
case $1 in
|
|
*:*)
|
|
while [ $# -gt 1 ]; do
|
|
if [ $g_family -eq 4 ]; then
|
|
interface=${1%%:*}
|
|
host=${1#*:}
|
|
else
|
|
interface=${1%%|*}
|
|
host=${1#*|}
|
|
fi
|
|
|
|
[ "$host" = "$1" ] && host=
|
|
|
|
if [ -z "$host" ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
hostlist="$hostlist $interface:0.0.0.0/0"
|
|
else
|
|
hostlist="$hostlist $interface:::/0"
|
|
fi
|
|
else
|
|
for h in $(separate_list $host); do
|
|
hostlist="$hostlist $interface:$h"
|
|
done
|
|
fi
|
|
|
|
shift
|
|
done
|
|
;;
|
|
*)
|
|
ipset=$1
|
|
shift
|
|
while [ $# -gt 0 ]; do
|
|
for h in $(separate_list $1); do
|
|
hostlist="$hostlist $h"
|
|
done
|
|
shift
|
|
done
|
|
;;
|
|
esac
|
|
|
|
zone=$1
|
|
|
|
if [ -n "$zone" ]; then
|
|
for host in $hostlist; do
|
|
if [ $g_family -eq 4 ]; then
|
|
interface=${host%:*}
|
|
ipset=${zone}_${interface};
|
|
else
|
|
interface=${host%%:*}
|
|
ipset=6_${zone}_${interface};
|
|
fi
|
|
|
|
ipset=$(echo $ipset | sed 's/\./_/g');
|
|
|
|
if ! qt $IPSET -L $ipset; then
|
|
fatal_error "Zone $zone, interface $interface does not have a dynamic host list"
|
|
fi
|
|
|
|
host=${host#*:}
|
|
|
|
if $IPSET -A $ipset $host; then
|
|
echo "Host $interface:$host added to zone $zone"
|
|
else
|
|
fatal_error "Unable to add $interface:$host to zone $zone"
|
|
fi
|
|
done
|
|
else
|
|
qt $IPSET -L $ipset || fatal_error "Zone $ipset is not dynamic"
|
|
|
|
for host in $hostlist; do
|
|
if $IPSET -A $ipset $host; then
|
|
echo "Host $host added to zone $ipset"
|
|
else
|
|
fatal_error "Unable to add $host to zone $ipset"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
#
|
|
# delete command executor
|
|
#
|
|
delete_command() {
|
|
local interface host hostent hostlist zone ipset
|
|
if ! product_is_started ; then
|
|
fatal_error "$g_product Not Started"
|
|
fi
|
|
|
|
determine_ipset_version
|
|
|
|
case $1 in
|
|
*:*)
|
|
while [ $# -gt 1 ]; do
|
|
if [ $g_family -eq 4 ]; then
|
|
interface=${1%%:*}
|
|
host=${1#*:}
|
|
else
|
|
interface=${1%%|*}
|
|
host=${1#*|}
|
|
fi
|
|
|
|
[ "$host" = "$1" ] && host=
|
|
|
|
if [ -z "$host" ]; then
|
|
if [ $g_family -eq 4 ]; then
|
|
hostlist="$hostlist $interface:0.0.0.0/0"
|
|
else
|
|
hostlist="$hostlist $interface:::/0"
|
|
fi
|
|
else
|
|
for h in $(separate_list $host); do
|
|
hostlist="$hostlist $interface:$h"
|
|
done
|
|
fi
|
|
|
|
shift
|
|
done
|
|
;;
|
|
*)
|
|
ipset=$1
|
|
shift
|
|
while [ $# -gt 0 ]; do
|
|
for h in $(separate_list $1); do
|
|
hostlist="$hostlist $h"
|
|
done
|
|
shift
|
|
done
|
|
;;
|
|
esac
|
|
|
|
zone=$1
|
|
|
|
if [ -n "$zone" ]; then
|
|
for host in $hostlist; do
|
|
if [ $g_family -eq 4 ]; then
|
|
interface=${host%:*}
|
|
ipset=${zone}_${interface};
|
|
else
|
|
interface=${host%%:*}
|
|
ipset=6_${zone}_${interface};
|
|
fi
|
|
|
|
ipset=$(echo $ipset | sed 's/./_/g');
|
|
|
|
if ! qt $IPSET -L $ipset -n; then
|
|
fatal_error "Zone $zone, interface $interface does not have a dynamic host list"
|
|
fi
|
|
|
|
host=${host#*:}
|
|
|
|
if $IPSET -D $ipset $host; then
|
|
echo "Host $host deleted from zone $zone"
|
|
else
|
|
echo " WARNING: Unable to delete host $hostent to zone $zone" >&2
|
|
fi
|
|
done
|
|
else
|
|
qt $IPSET -L $ipset -n || fatal_error "Zone $ipset is not dynamic"
|
|
|
|
for host in $hostlist; do
|
|
if $IPSET -D $ipset $host; then
|
|
echo "Host $host deleted from to zone $ipset"
|
|
else
|
|
echo " WARNING: Unable to delete host $host from zone $zone" >&2
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
open_close_command() {
|
|
local command
|
|
local desc
|
|
local proto
|
|
local icmptype
|
|
|
|
open_close_setup() {
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
|
|
if ! product_is_started ; then
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
fatal_error "The $COMMAND command requires the firewall to be running"
|
|
fi
|
|
|
|
if ! chain_exists dynamic; then
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
fatal_error "The $COMMAND command requires DYNAMIC_BLACKLIST=Yes in the running configuration"
|
|
fi
|
|
}
|
|
|
|
[ $# -le 4 ] || fatal_error "Too many parameters"
|
|
|
|
if [ $COMMAND = open ]; then
|
|
[ $# -ge 2 ] || fatal_error "Too few parameters"
|
|
else
|
|
[ $# -ge 1 ] || fatal_error "Too few parameters"
|
|
fi
|
|
|
|
if [ $# -eq 1 ]; then
|
|
#
|
|
# close <rule number>
|
|
#
|
|
case $1 in
|
|
[1-9]|[1-9][0-9]|[1-9][0-9][0-9]*)
|
|
;;
|
|
*)
|
|
fatal_error "$1 is not a valid temporary open number"
|
|
;;
|
|
esac
|
|
|
|
open_close_setup #Conditionally acquires mutex
|
|
|
|
if $g_tool -L dynamic --line-numbers | grep -q "^$1 .* ACCEPT "; then
|
|
if $g_tool -D dynamic $1; then
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
echo "Temporary open #$1 closed"
|
|
return 0
|
|
fi
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
return 2
|
|
else
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
fatal_error "$1 is not a valid temporary open number"
|
|
fi
|
|
else
|
|
if [ $1 = all ]; then
|
|
command=dynamic
|
|
else
|
|
command="dynamic -s $1"
|
|
fi
|
|
|
|
if [ $2 != all ]; then
|
|
command="$command -d $2"
|
|
fi
|
|
|
|
desc="from $1 to $2"
|
|
|
|
if [ $# -ge 3 ]; then
|
|
proto=$3
|
|
|
|
[ $proto = icmp -a $g_family -eq 6 ] && proto=58
|
|
|
|
command="$command -p $proto"
|
|
|
|
case $3 in
|
|
[0-9]*)
|
|
desc="$desc protocol $3"
|
|
;;
|
|
*)
|
|
desc="$desc $3"
|
|
;;
|
|
esac
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
if [ $proto = 6 -o $proto = icmp ]; then
|
|
proto=icmp
|
|
icmptype='--icmp-type'
|
|
fi
|
|
else
|
|
if [ $proto = 58 -o $proto = ipv6-icmp ]; then
|
|
proto=icmp
|
|
icmptype='--icmpv6-type'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ $# -eq 4 ]; then
|
|
if [ $proto = icmp ]; then
|
|
case $4 in
|
|
*,*)
|
|
fatal_error "Only a single ICMP type may be specified"
|
|
;;
|
|
[0-9]*)
|
|
desc="$desc type $4"
|
|
;;
|
|
*)
|
|
desc="$desc $4"
|
|
;;
|
|
esac
|
|
|
|
command="$command $icmptype $4"
|
|
else
|
|
case $4 in
|
|
*,*)
|
|
command="$command -m multiport --dports $4"
|
|
;;
|
|
*)
|
|
command="$command --dport $4"
|
|
;;
|
|
esac
|
|
|
|
case $4 in
|
|
[0-9]*,)
|
|
desc="$desc ports $4"
|
|
;;
|
|
[0-9]*)
|
|
desc="$desc port $4"
|
|
;;
|
|
*)
|
|
desc="$desc $4"
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
|
|
command="$command -j ACCEPT"
|
|
|
|
open_close_setup #Conditionally acquires mutex
|
|
|
|
if [ $COMMAND = open ]; then
|
|
if $g_tool -I $command ; then
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
echo "Firewall dynamically opened for connections $desc"
|
|
return 0
|
|
fi
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
return 2
|
|
fi
|
|
|
|
if $g_tool -D $command 2> /dev/null; then
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
echo "Firewall dynamically closed for connections $desc (may still be permitted by rules/policies)"
|
|
return 0
|
|
fi
|
|
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
fatal_error "Connections $desc are not currently opened"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# 'hits' commmand executor
|
|
#
|
|
hits_command() {
|
|
local finished
|
|
finished=0
|
|
local today
|
|
today=
|
|
|
|
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=
|
|
;;
|
|
t*)
|
|
today=$(date +'^%b %_d.*')
|
|
option=${option#t}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ $# -eq 0 ] || too_many_arguments $1
|
|
|
|
clear_term
|
|
echo "$g_product $SHOREWALL_VERSION Hits at $g_hostname - $(date)"
|
|
echo
|
|
|
|
timeout=30
|
|
|
|
if $g_logread | grep -q "${today}IN=.* OUT=" ; then
|
|
echo " HITS IP DATE"
|
|
echo " ---- --------------- ------"
|
|
$g_logread | grep "${today}IN=.* OUT=" | 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 " ---- --------------- -----"
|
|
$g_logread | grep "${today}IN=.* OUT=" | 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
|
|
[ -z "$port" ] && port=0
|
|
printf '%7d %-15s %d\n' $count $address $port
|
|
done
|
|
|
|
echo ""
|
|
|
|
echo " HITS DATE"
|
|
echo " ---- ------"
|
|
$g_logread | grep "${today}IN=.* OUT=" | 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 " ---- ----- ----------"
|
|
$g_logread | grep "${today}IN=.* OUT=.*DPT" | 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
|
|
}
|
|
|
|
#
|
|
# 'allow' command executor
|
|
#
|
|
allow_command() {
|
|
[ -n "$g_debugging" ] && set -x
|
|
[ $# -eq 1 ] && missing_argument
|
|
if product_is_started ; then
|
|
local which
|
|
which='-s'
|
|
local range
|
|
range='--src-range'
|
|
|
|
if ! chain_exists dynamic; then
|
|
fatal_error "Dynamic blacklisting is not enabled in the current $g_product configuration"
|
|
fi
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
while [ $# -gt 1 ]; do
|
|
shift
|
|
case $1 in
|
|
from)
|
|
which='-s'
|
|
range='--src-range'
|
|
continue
|
|
;;
|
|
to)
|
|
which='-d'
|
|
range='--dst-range'
|
|
continue
|
|
;;
|
|
*-*)
|
|
if qt $g_tool -D dynamic -m iprange $range $1 -j reject ||\
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j DROP ||\
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j logdrop ||\
|
|
qt $g_tool -D dynamic -m iprange $range $1 -j logreject
|
|
then
|
|
echo "$1 Allowed"
|
|
else
|
|
echo "$1 Not Dropped or Rejected"
|
|
fi
|
|
;;
|
|
*)
|
|
if qt $g_tool -D dynamic $which $1 -j reject ||\
|
|
qt $g_tool -D dynamic $which $1 -j DROP ||\
|
|
qt $g_tool -D dynamic $which $1 -j logdrop ||\
|
|
qt $g_tool -D dynamic $which $1 -j logreject
|
|
then
|
|
echo "$1 Allowed"
|
|
else
|
|
echo "$1 Not Dropped or Rejected"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
else
|
|
error_message "ERROR: $g_product is not started"
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
#
|
|
# 'logwatch' command executor
|
|
#
|
|
logwatch_command() {
|
|
shift
|
|
|
|
finished=0
|
|
|
|
while [ $finished -eq 0 -a $# -ne 0 ]; do
|
|
option=$1
|
|
case $option in
|
|
-*)
|
|
option=${option#-}
|
|
|
|
while [ -n "$option" ]; do
|
|
case $option in
|
|
v*)
|
|
VERBOSITY=$(($VERBOSITY + 1 ))
|
|
option=${option#v}
|
|
;;
|
|
q*)
|
|
VERBOSITY=$(($VERBOSITY - 1 ))
|
|
option=${option#q}
|
|
;;
|
|
m*)
|
|
g_showmacs=Yes
|
|
option=${option#m}
|
|
;;
|
|
-)
|
|
finished=1
|
|
option=
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ -n "$g_debugging" ] && set -x
|
|
|
|
if [ $# -eq 1 ]; then
|
|
logwatch $1
|
|
elif [ $# -eq 0 ]; then
|
|
logwatch 30
|
|
else
|
|
too_many_arguments $2
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Determine which optional facilities are supported by iptables/netfilter
|
|
#
|
|
determine_capabilities() {
|
|
|
|
local tool
|
|
local chain
|
|
local chain1
|
|
local arptables
|
|
local helper
|
|
|
|
if [ -z "$g_tool" ]; then
|
|
[ $g_family -eq 4 ] && tool=iptables || tool=ip6tables
|
|
|
|
g_tool=$(mywhich $tool)
|
|
|
|
if [ -z "$g_tool" ]; then
|
|
fatal-error "No executable $tool binary can be found on your PATH"
|
|
fi
|
|
fi
|
|
|
|
qt $g_tool -t nat -L -n && NAT_ENABLED=Yes || NAT_ENABLED=
|
|
qt $g_tool -t mangle -L -n && MANGLE_ENABLED=Yes || MANGLE_ENABLED=
|
|
|
|
[ "$IP" = ip -o -z "$IP" ] && IP=$(which ip)
|
|
|
|
[ -n "$IP" -a -x "$IP" ] || IP=
|
|
|
|
[ "$TC" = tc -o -z "$TC" ] && TC=$(which tc)
|
|
|
|
[ -n "$TC" -a -x "$TC" ] || TC=
|
|
|
|
CONNTRACK_MATCH=
|
|
NEW_CONNTRACK_MATCH=
|
|
OLD_CONNTRACK_MATCH=
|
|
MULTIPORT=
|
|
XMULTIPORT=
|
|
EMULTIPORT=
|
|
POLICY_MATCH=
|
|
PHYSDEV_MATCH=
|
|
PHYSDEV_BRIDGE=
|
|
IPRANGE_MATCH=
|
|
RECENT_MATCH=
|
|
REAP_OPTION=
|
|
OWNER_MATCH=
|
|
OWNER_NAME_MATCH=
|
|
IPSET_MATCH=
|
|
OLD_IPSET_MATCH=
|
|
IPSET_MATCH_NOMATCH=
|
|
IPSET_MATCH_COUNTERS=
|
|
IPSET_V5=
|
|
CONNMARK=
|
|
XCONNMARK=
|
|
CONNMARK_MATCH=
|
|
XCONNMARK_MATCH=
|
|
RAW_TABLE=
|
|
RAWPOST_TABLE=
|
|
IPP2P_MATCH=
|
|
OLD_IPP2P_MATCH=
|
|
LENGTH_MATCH=
|
|
CLASSIFY_TARGET=
|
|
ENHANCED_REJECT=
|
|
USEPKTTYPE=
|
|
KLUDGEFREE=
|
|
MARK=
|
|
XMARK=
|
|
EXMARK=
|
|
TPROXY_TARGET=
|
|
MANGLE_FORWARD=
|
|
COMMENTS=
|
|
ADDRTYPE=
|
|
TCPMSS_MATCH=
|
|
HASHLIMIT_MATCH=
|
|
NFQUEUE_TARGET=
|
|
REALM_MATCH=
|
|
HELPER_MATCH=
|
|
CONNLIMIT_MATCH=
|
|
TIME_MATCH=
|
|
GOTO_TARGET=
|
|
LOGMARK_TARGET=
|
|
IPMARK_TARGET=
|
|
LOG_TARGET=Yes
|
|
ULOG_TARGET=
|
|
NFLOG_TARGET=
|
|
PERSISTENT_SNAT=
|
|
FLOW_FILTER=
|
|
FWMARK_RT_MASK=
|
|
MARK_ANYWHERE=
|
|
HEADER_MATCH=
|
|
ACCOUNT_TARGET=
|
|
AUDIT_TARGET=
|
|
CONDITION_MATCH=
|
|
IPTABLES_S=
|
|
BASIC_FILTER=
|
|
BASIC_EMATCH=
|
|
CT_TARGET=
|
|
STATISTIC_MATCH=
|
|
IMQ_TARGET=
|
|
DSCP_MATCH=
|
|
DSCP_TARGET=
|
|
GEOIP_MATCH=
|
|
RPFILTER_MATCH=
|
|
NFACCT_MATCH=
|
|
CHECKSUM_TARGET=
|
|
ARPTABLESJF=
|
|
MASQUERADE_TGT=
|
|
UDPLITEREDIRECT=
|
|
NEW_TOS_MATCH=
|
|
TARPIT_TARGET=
|
|
IFACE_MATCH=
|
|
TCPMSS_TARGET=
|
|
WAIT_OPTION=
|
|
|
|
AMANDA_HELPER=
|
|
FTP_HELPER=
|
|
FTP0_HELPER=
|
|
IRC_HELPER=
|
|
IRC0_HELPER=
|
|
NETBIOS_NS_HELPER=
|
|
H323_HELPER=
|
|
PPTP_HELPER=
|
|
SANE_HELPER=
|
|
SANE0_HELPER=
|
|
SIP_HELPER=
|
|
SIP0_HELPER=
|
|
SNMP_HELPER=
|
|
TFTP_HELPER=
|
|
TFTP0_HELPER=
|
|
|
|
resolve_arptables
|
|
|
|
if [ -n "$arptables" -a -x "$arptables" ]; then
|
|
qt $arptables -L OUT && ARPTABLESJF=Yes
|
|
fi
|
|
|
|
if qt $g_tool --wait -t filter -L INPUT -n -v; then
|
|
WAIT_OPTION=Yes
|
|
tool="$tool --wait"
|
|
fi
|
|
|
|
chain=fooX$$
|
|
|
|
if [ -n "$NAT_ENABLED" ]; then
|
|
if qt $g_tool -t nat -N $chain; then
|
|
if [ $g_family -eq 4 ]; then
|
|
qt $g_tool -t nat -A $chain -j SNAT --to-source 1.2.3.4 --persistent && PERSISTENT_SNAT=Yes
|
|
else
|
|
qt $g_tool -t nat -A $chain -j SNAT --to-source 2001::1 --persistent && PERSISTENT_SNAT=Yes
|
|
fi
|
|
qt $g_tool -t nat -A $chain -j MASQUERADE && MASQUERADE_TGT=Yes
|
|
qt $g_tool -t nat -A $chain -p udplite -m multiport --dport 33 -j REDIRECT --to-port 22 && UDPREDIRECT=Yes
|
|
qt $g_tool -t nat -F $chain
|
|
qt $g_tool -t nat -X $chain
|
|
fi
|
|
fi
|
|
|
|
qt $g_tool -F $chain
|
|
qt $g_tool -X $chain
|
|
if ! $g_tool -N $chain; then
|
|
fatal_error "The command \"$g_tool -N $chain\" failed"
|
|
fi
|
|
|
|
chain1=${chain}1
|
|
|
|
qt $g_tool -F $chain1
|
|
qt $g_tool -X $chain1
|
|
if ! $g_tool -N $chain1; then
|
|
qt $g_tool -X $CHAIN
|
|
fatal_error "The command \"$g_tool -N $chain1\" failed"
|
|
fi
|
|
|
|
if ! qt $g_tool -A $chain -m state --state ESTABLISHED,RELATED -j ACCEPT &&
|
|
! qt $g_tool -A $chain -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT; then
|
|
qt $g_tool -x $chain
|
|
qt $g_tool -x $chain1
|
|
fatal_error "Your kernel lacks connection tracking and/or state matching -- $g_product will not run on this system"
|
|
fi
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
qt $g_tool -A $chain -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT && CONNTRACK_MATCH=Yes
|
|
else
|
|
qt $g_tool -A $chain -m conntrack --ctorigdst ::1 -j ACCEPT && CONNTRACK_MATCH=Yes
|
|
fi
|
|
|
|
if [ -n "$CONNTRACK_MATCH" ]; then
|
|
qt $g_tool -A $chain -m conntrack -p tcp --ctorigdstport 22 -j ACCEPT && NEW_CONNTRACK_MATCH=Yes
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
qt $g_tool -A $chain -m conntrack ! --ctorigdst 1.2.3.4 || OLD_CONNTRACK_MATCH=Yes
|
|
else
|
|
qt $g_tool -A $chain -m conntrack ! --ctorigdst ::1 || OLD_CONNTRACK_MATCH=Yes
|
|
fi
|
|
fi
|
|
|
|
if qt $g_tool -A $chain -p tcp -m multiport --dports 21,22 -j ACCEPT; then
|
|
MULTIPORT=Yes
|
|
qt $g_tool -A $chain -p tcp -m multiport --sports 60 -m multiport --dports 99 -j ACCEPT && KLUDEFREE=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -p tcp -m multiport --dports 21:22 -j ACCEPT && XMULTIPORT=Yes
|
|
qt $g_tool -A $chain -p sctp -m multiport --dports 21,22 -j ACCEPT && EMULTIPORT=Yes
|
|
qt $g_tool -A $chain -m policy --pol ipsec --mode tunnel --dir in -j ACCEPT && POLICY_MATCH=Yes
|
|
|
|
if qt $g_tool -A $chain -m physdev --physdev-out eth0 -j ACCEPT; then
|
|
PHYSDEV_MATCH=Yes
|
|
qt $g_tool -A $chain -m physdev --physdev-is-bridged --physdev-in eth0 --physdev-out eth0 -j ACCEPT && PHYSDEV_BRIDGE=Yes
|
|
if [ -z "${KLUDGEFREE}" ]; then
|
|
qt $g_tool -A $chain -m physdev --physdev-in eth0 -m physdev --physdev-out eth0 -j ACCEPT && KLUDGEFREE=Yes
|
|
fi
|
|
fi
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
if qt $g_tool -A $chain -m iprange --src-range 192.168.1.5-192.168.1.124 -j ACCEPT; then
|
|
IPRANGE_MATCH=Yes
|
|
if [ -z "${KLUDGEFREE}" ]; then
|
|
qt $g_tool -A $chain -m iprange --src-range 192.168.1.5-192.168.1.124 -m iprange --dst-range 192.168.1.5-192.168.1.124 -j ACCEPT && KLUDGEFREE=Yes
|
|
fi
|
|
fi
|
|
elif qt $g_tool -A $chain -m iprange --src-range ::1-::2 -j ACCEPT; then
|
|
IPRANGE_MATCH=Yes
|
|
if [ -z "${KLUDGEFREE}" ]; then
|
|
qt $g_tool -A $chain -m iprange --src-range ::1-::2 -m iprange --dst-range ::1-::2 -j ACCEPT && KLUDGEFREE=Yes
|
|
fi
|
|
fi
|
|
|
|
if qt $g_tool -A $chain -m recent --update -j ACCEPT; then
|
|
RECENT_MATCH=Yes
|
|
qt $g_tool -A $chain -m recent --rcheck --seconds 10 --reap && REAP_OPTION=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -m owner --uid-owner 0 -j ACCEPT && OWNER_MATCH=Yes
|
|
|
|
local name
|
|
name=$(id -un 2> /dev/null)
|
|
|
|
[ -n "$name" ] && qt $g_tool -A $chain -m owner --uid-owner $name -j ACCEPT && OWNER_NAME_MATCH=Yes
|
|
|
|
if qt $g_tool -A $chain -m connmark --mark 2 -j ACCEPT; then
|
|
CONNMARK_MATCH=Yes
|
|
qt $g_tool -A $chain -m connmark --mark 2/0xFF -j ACCEPT && XCONNMARK_MATCH=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -p tcp -m ipp2p --edk -j ACCEPT && IPP2P_MATCH=Yes
|
|
if [ -n "$IPP2P_MATCH" ]; then
|
|
qt $g_tool -A $chain -p tcp -m ipp2p --ipp2p -j ACCEPT && OLD_IPP2P_MATCH=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -m length --length 10:20 -j ACCEPT && LENGTH_MATCH=Yes
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
qt $g_tool -A $chain -j REJECT --reject-with icmp-host-prohibited && ENHANCED_REJECT=Yes
|
|
else
|
|
qt $g_tool -A $chain -j REJECT --reject-with icmp6-adm-prohibited && ENHANCED_REJECT=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -j ACCEPT -m comment --comment "This is a comment" && COMMENTS=Yes
|
|
|
|
if [ -n "$NFACCT" -a ! -x "$NFACCT" ]; then
|
|
error_message "WARNING: NFACCT=$NFACCT does not exist or is not executable"
|
|
NFACCT=
|
|
else
|
|
NFACCT=$(mywhich nfacct)
|
|
fi
|
|
|
|
if [ -n "$NFACCT" ] && qt $NFACCT add $chain; then
|
|
qt $g_tool -A $chain -m nfacct --nfacct-name $chain && NFACCT_MATCH=Yes
|
|
qt $g_tool -D $chain -m nfacct --nfacct-name $chain
|
|
qt $NFACCT del $chain
|
|
fi
|
|
|
|
qt $g_tool -A $chain -p tcp -j TARPIT && TARPIT_TARGET=Yes
|
|
|
|
qt $g_tool -A $chain -m iface --iface lo --loopback && IFACE_MATCH=Yes
|
|
|
|
qt $g_tool -A $chain -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu && TCPMSS_TARGET=Yes
|
|
|
|
if [ -n "$MANGLE_ENABLED" ]; then
|
|
qt $g_tool -t mangle -N $chain
|
|
|
|
if qt $g_tool -t mangle -A $chain -j MARK --set-mark 1; then
|
|
MARK=Yes
|
|
qt $g_tool -t mangle -A $chain -j MARK --and-mark 0xFF && XMARK=Yes
|
|
qt $g_tool -t mangle -A $chain -j MARK --set-mark 1/0xFF && EXMARK=Yes
|
|
fi
|
|
|
|
if qt $g_tool -t mangle -A $chain -j CONNMARK --save-mark; then
|
|
CONNMARK=Yes
|
|
qt $g_tool -t mangle -A $chain -j CONNMARK --save-mark --mask 0xFF && XCONNMARK=Yes
|
|
fi
|
|
|
|
qt $g_tool -t mangle -A $chain -j CLASSIFY --set-class 1:1 && CLASSIFY_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -j IPMARK --addr src && IPMARK_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -p tcp -j TPROXY --on-port 0 --tproxy-mark 1 && TPROXY_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -j IMQ --todev 0 && IMQ_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -m dscp --dscp 0 && DSCP_MATCH=Yes
|
|
qt $g_tool -t mangle -A $chain -j DSCP --set-dscp 0 && DSCP_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -m rpfilter && RPFILTER_MATCH=Yes
|
|
qt $g_tool -t mangle -A $chain -j CHECKSUM --checksum-fill && CHECKSUM_TARGET=Yes
|
|
qt $g_tool -t mangle -A $chain -m tos --tos 0x10/0xff && NEW_TOS_MATCH=Yes
|
|
|
|
qt $g_tool -t mangle -F $chain
|
|
qt $g_tool -t mangle -X $chain
|
|
|
|
qt $g_tool -t mangle -L FORWARD -n && MANGLE_FORWARD=Yes
|
|
fi
|
|
|
|
qt $g_tool -t raw -L -n && RAW_TABLE=Yes
|
|
qt $g_tool -t rawpost -L -n && RAWPOST_TABLE=Yes
|
|
|
|
if [ -n "$RAW_TABLE" ]; then
|
|
qt $g_tool -t raw -F $chain
|
|
qt $g_tool -t raw -X $chain
|
|
qt $g_tool -t raw -N $chain
|
|
|
|
if qt $g_tool -t raw -A $chain -j CT --notrack; then
|
|
CT_TARGET=Yes;
|
|
|
|
for helper in amanda ftp ftp0 h323 irc irc0 netbios_ns pptp sane sane0 sip sip0 snmp tftp tftp0; do
|
|
eval ${helper}_ENABLED=''
|
|
done
|
|
|
|
if [ -n "$HELPERS" ]; then
|
|
for helper in $(split_list "$HELPERS"); do
|
|
case $helper in
|
|
none)
|
|
;;
|
|
amanda|ftp|ftp0|h323|irc|irc0|netbios_ns|pptp|sane|sane0|sip|sip0|snmp|tftp|tftp0)
|
|
eval ${helper}_ENABLED=Yes
|
|
;;
|
|
*)
|
|
error_message "WARNING: Invalid helper ($helper) ignored"
|
|
;;
|
|
esac
|
|
done
|
|
else
|
|
for helper in amanda ftp ftp0 h323 irc irc0 netbios_ns pptp sane sane0 sip sip0 snmp tftp tftp0; do
|
|
eval ${helper}_ENABLED=Yes
|
|
done
|
|
fi
|
|
|
|
[ -n "$amanda_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 10080 -j CT --helper amanda && AMANDA_HELPER=Yes
|
|
[ -n "$ftp_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 21 -j CT --helper ftp && FTP_HELPER=Yes
|
|
[ -n "$ftp0_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 21 -j CT --helper ftp-0 && FTP0_HELPER=Yes
|
|
[ -n "$h323_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 1719 -j CT --helper RAS && H323_HELPER=Yes
|
|
[ -n "$irc_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 6667 -j CT --helper irc && IRC_HELPER=Yes
|
|
[ -n "$irc0_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 6667 -j CT --helper irc-0 && IRC0_HELPER=Yes
|
|
[ -n "$netbios_ns_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 137 -j CT --helper netbios-ns && NETBIOS_NS_HELPER=Yes
|
|
[ -n "$pptp_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 1729 -j CT --helper pptp && PPTP_HELPER=Yes
|
|
[ -n "$sane_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 6566 -j CT --helper sane && SANE_HELPER=Yes
|
|
[ -n "$sane0_ENABLED" ] && qt $g_tool -t raw -A $chain -p tcp --dport 6566 -j CT --helper sane-0 && SANE0_HELPER=Yes
|
|
[ -n "$sip_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 5060 -j CT --helper sip && SIP_HELPER=Yes
|
|
[ -n "$sip0_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 5060 -j CT --helper sip-0 && SIP0_HELPER=Yes
|
|
[ -n "$snmp_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 161 -j CT --helper snmp && SNMP_HELPER=Yes
|
|
[ -n "$tftp_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 69 -j CT --helper tftp && TFTP_HELPER=Yes
|
|
[ -n "$tftp0_ENABLED" ] && qt $g_tool -t raw -A $chain -p udp --dport 69 -j CT --helper tftp-0 && TFTP0_HELPER=Yes
|
|
fi
|
|
|
|
qt $g_tool -t raw -F $chain
|
|
qt $g_tool -t raw -X $chain
|
|
fi
|
|
|
|
if qt mywhich ipset; then
|
|
qt ipset -X $chain # Just in case something went wrong the last time
|
|
|
|
local have_ipset
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
if qt ipset -N $chain hash:ip family inet; then
|
|
IPSET_V5=Yes
|
|
have_ipset=Yes
|
|
elif qt ipset -N $chain iphash ; then
|
|
have_ipset=Yes
|
|
fi
|
|
|
|
if [ -n "$have_ipset" ]; then
|
|
if qt $g_tool -A $chain -m set --match-set $chain src -j ACCEPT; then
|
|
qt $g_tool -A $chain -m set --match-set $chain src --return-nomatch -j ACCEPT && IPSET_MATCH_NOMATCH=Yes
|
|
qt $g_tool -A $chain -m set --match-set $chain src --packets-lt 100 -j ACCEPT && IPSET_MATCH_COUNTERS=Yes
|
|
qt $g_tool -F $chain
|
|
IPSET_MATCH=Yes
|
|
elif qt $g_tool -A $chain -m set --set $chain src -j ACCEPT; then
|
|
qt $g_tool -F $chain
|
|
IPSET_MATCH=Yes
|
|
OLD_IPSET_MATCH=Yes
|
|
fi
|
|
qt ipset -X $chain
|
|
fi
|
|
elif qt ipset -N $chain hash:ip family inet6; then
|
|
IPSET_V5=Yes
|
|
if qt $g_tool -A $chain -m set --match-set $chain src -j ACCEPT; then
|
|
qt $g_tool -F $chain
|
|
IPSET_MATCH=Yes
|
|
elif qt $g_tool -A $chain -m set --set $chain src -j ACCEPT; then
|
|
qt $g_tool -F $chain
|
|
IPSET_MATCH=Yes
|
|
OLD_IPSET_MATCH=Yes
|
|
fi
|
|
qt ipset -X $chain
|
|
fi
|
|
fi
|
|
|
|
qt $g_tool -A $chain -m pkttype --pkt-type broadcast -j ACCEPT && USEPKTTYPE=Yes
|
|
qt $g_tool -A $chain -m addrtype --src-type BROADCAST -j ACCEPT && ADDRTYPE=Yes
|
|
qt $g_tool -A $chain -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT && TCPMSS_MATCH=Yes
|
|
qt $g_tool -A $chain -m hashlimit --hashlimit-upto 4 --hashlimit-burst 5 --hashlimit-name $chain --hashlimit-mode dstip -j ACCEPT && HASHLIMIT_MATCH=Yes
|
|
if [ -z "$HASHLIMIT_MATCH" ]; then
|
|
qt $g_tool -A $chain -m hashlimit --hashlimit 4 --hashlimit-burst 5 --hashlimit-name $chain --hashlimit-mode dstip -j ACCEPT && OLD_HL_MATCH=Yes
|
|
HASHLIMIT_MATCH=$OLD_HL_MATCH
|
|
fi
|
|
qt $g_tool -A $chain -j NFQUEUE --queue-num 4 && NFQUEUE_TARGET=Yes
|
|
qt $g_tool -A $chain -m realm --realm 4 && REALM_MATCH=Yes
|
|
|
|
#
|
|
# -m helper doesn't verify the existence of the specified helper :-(
|
|
#
|
|
if qt $g_tool -A $chain -p tcp --dport 21 -m helper --helper ftp; then
|
|
HELPER_MATCH=Yes
|
|
|
|
if [ -z "$CT_TARGET" ]; then
|
|
AMANDA_HELPER=Yes
|
|
FTP_HELPER=Yes
|
|
FTP_HELPER=Yes
|
|
H323_HELPER=Yes
|
|
IRC_HELPER=Yes
|
|
NS_HELPER=Yes
|
|
PPTP_HELPER=Yes
|
|
SANE_HELPER=Yes
|
|
SIP_HELPER=Yes
|
|
SNMP_HELPER=Yes
|
|
TFTP_HELPER=Yes
|
|
fi
|
|
fi
|
|
|
|
qt $g_tool -A $chain -m connlimit --connlimit-above 8 -j DROP && CONNLIMIT_MATCH=Yes
|
|
qt $g_tool -A $chain -m time --timestart 23:00 -j DROP && TIME_MATCH=Yes
|
|
qt $g_tool -A $chain -g $chain1 && GOTO_TARGET=Yes
|
|
qt $g_tool -A $chain -j LOGMARK && LOGMARK_TARGET=Yes
|
|
qt $g_tool -A $chain -j LOG || LOG_TARGET=
|
|
qt $g_tool -A $chain -j ULOG && ULOG_TARGET=Yes
|
|
qt $g_tool -A $chain -j NFLOG && NFLOG_TARGET=Yes
|
|
qt $g_tool -A $chain -j MARK --set-mark 5 && MARK_ANYWHERE=Yes
|
|
qt $g_tool -A $chain -m statistic --mode nth --every 2 --packet 1 && STATISTIC_MATCH=Yes
|
|
qt $g_tool -A $chain -m geoip --src-cc US && GEOIP_MATCH=Yes
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
qt $g_tool -A $chain -j ACCOUNT --addr 192.168.1.0/29 --tname $chain && ACCOUNT_TARGET=Yes
|
|
else
|
|
qt $g_tool -A $chain -m ipv6header --header 255 && HEADER_MATCH=Yes
|
|
qt $g_tool -A $chain -j ACCOUNT --addr ::1/122 --tname $chain && ACCOUNT_TARGET=Yes
|
|
fi
|
|
|
|
qt $g_tool -A $chain -j AUDIT --type drop && AUDIT_TARGET=Yes
|
|
|
|
qt $g_tool -A $chain -m condition --condition foo && CONDITION_MATCH=Yes
|
|
|
|
qt $g_tool -S INPUT && IPTABLES_S=Yes
|
|
qt $g_tool -F $chain
|
|
qt $g_tool -X $chain
|
|
qt $g_tool -F $chain1
|
|
qt $g_tool -X $chain1
|
|
|
|
if [ -n "$TC" ]; then
|
|
$TC filter add flow help 2>&1 | grep -q ^Usage && FLOW_FILTER=Yes
|
|
|
|
if $TC filter add basic help 2>&1 | grep -q ^Usage; then
|
|
BASIC_FILTER=Yes
|
|
$TC filter add basic help 2>&1 | egrep -q match && BASIC_EMATCH=Yes
|
|
fi
|
|
fi
|
|
|
|
[ -n "$IP" ] && $IP rule add help 2>&1 | grep -q /MASK && FWMARK_RT_MASK=Yes
|
|
|
|
CAPVERSION=$SHOREWALL_CAPVERSION
|
|
|
|
KERNELVERSION=$(uname -r 2> /dev/null | sed -e 's/-.*//')
|
|
|
|
case "$KERNELVERSION" in
|
|
*.*.*)
|
|
KERNELVERSION=$(printf "%d%02d%02d" $(echo $KERNELVERSION | sed -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2 \3/g'))
|
|
;;
|
|
*)
|
|
KERNELVERSION=$(printf "%d%02d00" $(echo $KERNELVERSION | sed -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/g'))
|
|
;;
|
|
esac
|
|
}
|
|
|
|
report_capabilities_unsorted() {
|
|
report_capability() # $1 = Capability Description , $2 Capability Setting (if any)
|
|
{
|
|
local setting
|
|
setting=
|
|
|
|
[ "x$2" = "xYes" ] && setting="Available" || setting="Not available"
|
|
|
|
echo " " $1: $setting
|
|
}
|
|
|
|
report_capability "NAT (NAT_ENABLED)" $NAT_ENABLED
|
|
report_capability "Packet Mangling (MANGLE_ENABLED)" $MANGLE_ENABLED
|
|
report_capability "Multi-port Match (MULTIPORT)" $MULTIPORT
|
|
[ -n "$MULTIPORT" ] && report_capability "Extended Multi-port Match (XMULIPORT)" $XMULTIPORT
|
|
[ -n "$EMULTIPORT" ] && report_capability "Enhanced Multi-port Match (EMULIPORT)" $EMULTIPORT
|
|
report_capability "Connection Tracking Match (CONNTRACK_MATCH)" $CONNTRACK_MATCH
|
|
if [ -n "$CONNTRACK_MATCH" ]; then
|
|
report_capability "Extended Connection Tracking Match Support (NEW_CONNTRACK_MATCH)" $NEW_CONNTRACK_MATCH
|
|
[ -n "$OLD_CONNTRACK_MATCH" ] && report_capability "Old Connection Tracking Match Syntax (OLD_CONNTRACK_MATCH)" $OLD_CONNTRACK_MATCH
|
|
fi
|
|
report_capability "Packet Type Match (USEPKTTYPE)" $USEPKTTYPE
|
|
report_capability "Policy Match (POLICY_MATCH)" $POLICY_MATCH
|
|
report_capability "Physdev Match (PHYSDEV_MATCH)" $PHYSDEV_MATCH
|
|
report_capability "Physdev-is-bridged Support (PHYSDEV_BRIDGE)" $PHYSDEV_BRIDGE
|
|
report_capability "Packet length Match (LENGTH_MATCH)" $LENGTH_MATCH
|
|
report_capability "IP range Match(IPRANGE_MATCH)" $IPRANGE_MATCH
|
|
report_capability "Recent Match (RECENT_MATCH)" $RECENT_MATCH
|
|
[ -n "$RECENT_MATCH" ] && report_capability 'Recent Match "--reap" option (REAP_OPTION)' $REAP_OPTION
|
|
report_capability "Owner Match (OWNER_MATCH)" $OWNER_MATCH
|
|
report_capability "Owner Name Match (OWNER_NAME_MATCH)" $OWNER_NAME_MATCH
|
|
if [ -n "$IPSET_MATCH" ]; then
|
|
report_capability "Ipset Match (IPSET_MATCH)" $IPSET_MATCH
|
|
[ -n "$OLD_IPSET_MATCH" ] && report_capability "OLD_Ipset Match (OLD_IPSET_MATCH)" $OLD_IPSET_MATCH
|
|
[ -n "$IPSET_MATCH_NOMATCH" ] && report_capability "Ipset Match Nomatch (IPSET_MATCH_NOMATCH)" $IPSET_MATCH_NOMATCH
|
|
[ -n "$IPSET_MATCH_NOMATCH" ] && report_capability "Ipset Match Counters (IPSET_MATCH_COUNTERS)" $IPSET_MATCH_COUNTERS
|
|
fi
|
|
report_capability "CONNMARK Target (CONNMARK)" $CONNMARK
|
|
[ -n "$CONNMARK" ] && report_capability "Extended CONNMARK Target (XCONNMARK)" $XCONNMARK
|
|
report_capability "Connmark Match (CONNMARK_MATCH)" $CONNMARK_MATCH
|
|
[ -n "$CONNMARK_MATCH" ] && report_capability "Extended Connmark Match (XCONNMARK_MATCH)" $XCONNMARK_MATCH
|
|
report_capability "Raw Table (RAW_TABLE)" $RAW_TABLE
|
|
report_capability "Rawpost Table (RAWPOST_TABLE)" $RAWPOST_TABLE
|
|
report_capability "IPP2P Match (IPP2P_MATCH)" $IPP2P_MATCH
|
|
[ -n "$OLD_IPP2P_MATCH" ] && report_capability "Old IPP2P Match Syntax (OLD_IPP2P_MATCH)" $OLD_IPP2P_MATCH
|
|
report_capability "CLASSIFY Target (CLASSIFY_TARGET)" $CLASSIFY_TARGET
|
|
report_capability "Extended REJECT (ENHANCED_REJECT)" $ENHANCED_REJECT
|
|
report_capability "Repeat match (KLUDGEFREE)" $KLUDGEFREE
|
|
report_capability "MARK Target (MARK)" $MARK
|
|
[ -n "$MARK" ] && report_capability "Extended MARK Target (XMARK)" $XMARK
|
|
[ -n "$XMARK" ] && report_capability "Extended MARK Target 2 (EXMARK)" $EXMARK
|
|
report_capability "Mangle FORWARD Chain (MANGLE_FORWARD)" $MANGLE_FORWARD
|
|
report_capability "Comments (COMMENTS)" $COMMENTS
|
|
report_capability "Address Type Match (ADDRTYPE)" $ADDRTYPE
|
|
report_capability "TCPMSS Match (TCPMSS_MATCH)" $TCPMSS_MATCH
|
|
report_capability "Hashlimit Match (HASHLIMIT_MATCH)" $HASHLIMIT_MATCH
|
|
[ -n "$OLD_HL_MATCH" ] && report_capability "Old Hashlimit Match (OLD_HL_MATCH)" $OLD_HL_MATCH
|
|
report_capability "NFQUEUE Target (NFQUEUE_TARGET)" $NFQUEUE_TARGET
|
|
report_capability "Realm Match (REALM_MATCH)" $REALM_MATCH
|
|
report_capability "Helper Match (HELPER_MATCH)" $HELPER_MATCH
|
|
report_capability "Connlimit Match (CONNLIMIT_MATCH)" $CONNLIMIT_MATCH
|
|
report_capability "Time Match (TIME_MATCH)" $TIME_MATCH
|
|
report_capability "Goto Support (GOTO_TARGET)" $GOTO_TARGET
|
|
report_capability "LOGMARK Target (LOGMARK_TARGET)" $LOGMARK_TARGET
|
|
report_capability "IPMARK Target (IPMARK_TARGET)" $IPMARK_TARGET
|
|
report_capability "LOG Target (LOG_TARGET)" $LOG_TARGET
|
|
report_capability "ULOG Target (ULOG_TARGET)" $ULOG_TARGET
|
|
report_capability "NFLOG Target (NFLOG_TARGET)" $NFLOG_TARGET
|
|
report_capability "Persistent SNAT (PERSISTENT_SNAT)" $PERSISTENT_SNAT
|
|
report_capability "TPROXY Target (TPROXY_TARGET)" $TPROXY_TARGET
|
|
report_capability "FLOW Classifier (FLOW_FILTER)" $FLOW_FILTER
|
|
report_capability "fwmark route mask (FWMARK_RT_MASK)" $FWMARK_RT_MASK
|
|
report_capability "Mark in the filter table (MARK_ANYWHERE)" $MARK_ANYWHERE
|
|
report_capability "Header Match (HEADER_MATCH)" $HEADER_MATCH
|
|
report_capability "ACCOUNT Target (ACCOUNT_TARGET)" $ACCOUNT_TARGET
|
|
report_capability "AUDIT Target (AUDIT_TARGET)" $AUDIT_TARGET
|
|
report_capability "ipset V5 (IPSET_V5)" $IPSET_V5
|
|
report_capability "Condition Match (CONDITION_MATCH)" $CONDITION_MATCH
|
|
report_capability "Statistic Match (STATISTIC_MATCH)" $STATISTIC_MATCH
|
|
report_capability "IMQ Target (IMQ_TARGET)" $IMQ_TARGET
|
|
report_capability "DSCP Match (DSCP_MATCH)" $DSCP_MATCH
|
|
report_capability "DSCP Target (DSCP_TARGET)" $DSCP_TARGET
|
|
report_capability "Geo IP Match (GEOIP_MATCH)" $GEOIP_MATCH
|
|
report_capability "RPFilter Match (RPFILTER_MATCH)" $RPFILTER_MATCH
|
|
report_capability "NFAcct Match" $NFACCT_MATCH
|
|
report_capability "Checksum Target (CHECKSUM_TARGET)" $CHECKSUM_TARGET
|
|
report_capability "Arptables JF (ARPTABLESJF)" $ARPTABLESJF
|
|
report_capability "MASQUERADE Target (MASQUERADE_TGT)" $MASQUERADE_TGT
|
|
report_capability "UDPLITE Port Redirection (UDPLITEREDIRECT)" $UDPLITEREDIRECT
|
|
report_capability "New tos Match (NEW_TOS_MATCH)" $NEW_TOS_MATCH
|
|
report_capability "TARPIT Target (TARPIT_TARGET)" $TARPIT_TARGET
|
|
report_capability "Iface Match (IFACE_MATCH)" $IFACE_MATCH
|
|
report_capability "TCPMSS Target (TCPMSS_TARGET)" $TCPMSS_TARGET
|
|
|
|
report_capability "Amanda Helper" $AMANDA_HELPER
|
|
report_capability "FTP Helper" $FTP_HELPER
|
|
report_capability "FTP-0 Helper" $FTP0_HELPER
|
|
report_capability "IRC Helper" $IRC_HELPER
|
|
report_capability "IRC-0 Helper" $IRC0_HELPER
|
|
report_capability "Netbios_ns Helper" $NETBIOS_NS_HELPER
|
|
report_capability "H323 Helper" $H323_HELPER
|
|
report_capability "PPTP Helper" $PPTP_HELPER
|
|
report_capability "SANE Helper" $SANE_HELPER
|
|
report_capability "SANE-0 Helper" $SANE0_HELPER
|
|
report_capability "SIP Helper" $SIP_HELPER
|
|
report_capability "SIP-0 Helper" $SIP0_HELPER
|
|
report_capability "SNMP Helper" $SNMP_HELPER
|
|
report_capability "TFTP Helper" $TFTP_HELPER
|
|
report_capability "TFTP-0 Helper" $TFTP0_HELPER
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
report_capability "iptables -S (IPTABLES_S)" $IPTABLES_S
|
|
report_capability "iptables --wait option (WAIT_OPTION)" $WAIT_OPTION
|
|
else
|
|
report_capability "ip6tables -S (IPTABLES_S)" $IPTABLES_S
|
|
report_capability "ip6tables --wait option (WAIT_OPTION)" $WAIT_OPTION
|
|
fi
|
|
|
|
report_capability "Basic Filter (BASIC_FILTER)" $BASIC_FILTER
|
|
report_capability "Basic Ematch (BASIC_EMATCH)" $BASIC_EMATCH
|
|
report_capability "CT Target (CT_TARGET)" $CT_TARGET
|
|
|
|
echo " Kernel Version (KERNELVERSION): $KERNELVERSION"
|
|
echo " Capabilities Version (CAPVERSION): $CAPVERSION"
|
|
}
|
|
|
|
report_capabilities() {
|
|
|
|
if [ $VERBOSITY -gt 1 ]; then
|
|
echo "$g_product has detected the following iptables/netfilter capabilities:"
|
|
report_capabilities_unsorted | sort
|
|
fi
|
|
|
|
[ -n "$PKTTYPE" ] || USEPKTTYPE=
|
|
|
|
}
|
|
|
|
report_capabilities_unsorted1() {
|
|
report_capability1() # $1 = Capability
|
|
{
|
|
eval echo $1=\$$1
|
|
}
|
|
|
|
report_capability1 NAT_ENABLED
|
|
report_capability1 MANGLE_ENABLED
|
|
report_capability1 MULTIPORT
|
|
report_capability1 XMULTIPORT
|
|
report_capability1 EMULTIPORT
|
|
report_capability1 CONNTRACK_MATCH
|
|
report_capability1 NEW_CONNTRACK_MATCH
|
|
report_capability1 OLD_CONNTRACK_MATCH
|
|
report_capability1 USEPKTTYPE
|
|
report_capability1 POLICY_MATCH
|
|
report_capability1 PHYSDEV_MATCH
|
|
report_capability1 PHYSDEV_BRIDGE
|
|
report_capability1 LENGTH_MATCH
|
|
report_capability1 IPRANGE_MATCH
|
|
report_capability1 RECENT_MATCH
|
|
report_capability1 REAP_OPTION
|
|
report_capability1 OWNER_MATCH
|
|
report_capability1 OWNER_NAME_MATCH
|
|
report_capability1 IPSET_MATCH
|
|
report_capability1 OLD_IPSET_MATCH
|
|
report_capability1 IPSET_MATCH_NOMATCH
|
|
report_capability1 IPSET_MATCH_COUNTERS
|
|
report_capability1 CONNMARK
|
|
report_capability1 XCONNMARK
|
|
report_capability1 CONNMARK_MATCH
|
|
report_capability1 XCONNMARK_MATCH
|
|
report_capability1 RAW_TABLE
|
|
report_capability1 RAWPOST_TABLE
|
|
report_capability1 IPP2P_MATCH
|
|
report_capability1 OLD_IPP2P_MATCH
|
|
report_capability1 CLASSIFY_TARGET
|
|
report_capability1 ENHANCED_REJECT
|
|
report_capability1 KLUDGEFREE
|
|
report_capability1 MARK
|
|
report_capability1 XMARK
|
|
report_capability1 EXMARK
|
|
report_capability1 MANGLE_FORWARD
|
|
report_capability1 COMMENTS
|
|
report_capability1 ADDRTYPE
|
|
report_capability1 TCPMSS_MATCH
|
|
report_capability1 HASHLIMIT_MATCH
|
|
report_capability1 OLD_HL_MATCH
|
|
report_capability1 NFQUEUE_TARGET
|
|
report_capability1 REALM_MATCH
|
|
report_capability1 HELPER_MATCH
|
|
report_capability1 CONNLIMIT_MATCH
|
|
report_capability1 TIME_MATCH
|
|
report_capability1 GOTO_TARGET
|
|
report_capability1 LOGMARK_TARGET
|
|
report_capability1 IPMARK_TARGET
|
|
report_capability1 LOG_TARGET
|
|
report_capability1 ULOG_TARGET
|
|
report_capability1 NFLOG_TARGET
|
|
report_capability1 PERSISTENT_SNAT
|
|
report_capability1 TPROXY_TARGET
|
|
report_capability1 FLOW_FILTER
|
|
report_capability1 FWMARK_RT_MASK
|
|
report_capability1 MARK_ANYWHERE
|
|
report_capability1 HEADER_MATCH
|
|
report_capability1 ACCOUNT_TARGET
|
|
report_capability1 AUDIT_TARGET
|
|
report_capability1 IPSET_V5
|
|
report_capability1 CONDITION_MATCH
|
|
report_capability1 IPTABLES_S
|
|
report_capability1 BASIC_FILTER
|
|
report_capability1 BASIC_EMATCH
|
|
report_capability1 CT_TARGET
|
|
report_capability1 STATISTIC_MATCH
|
|
report_capability1 IMQ_TARGET
|
|
report_capability1 DSCP_MATCH
|
|
report_capability1 DSCP_TARGET
|
|
report_capability1 GEOIP_MATCH
|
|
report_capability1 RPFILTER_MATCH
|
|
report_capability1 NFACCT_MATCH
|
|
report_capability1 CHECKSUM_TARGET
|
|
report_capability1 ARPTABLESJF
|
|
report_capability1 MASQUERADE_TGT
|
|
report_capability1 UDPLITEREDIRECT
|
|
report_capability1 NEW_TOS_MATCH
|
|
report_capability1 TARPIT_TARGET
|
|
report_capability1 IFACE_MATCH
|
|
report_capability1 TCPMSS_TARGET
|
|
report_capability1 WAIT_OPTION
|
|
|
|
report_capability1 AMANDA_HELPER
|
|
report_capability1 FTP_HELPER
|
|
report_capability1 FTP0_HELPER
|
|
report_capability1 IRC_HELPER
|
|
report_capability1 IRC0_HELPER
|
|
report_capability1 NETBIOS_NS_HELPER
|
|
report_capability1 H323_HELPER
|
|
report_capability1 PPTP_HELPER
|
|
report_capability1 SANE_HELPER
|
|
report_capability1 SANE0_HELPER
|
|
report_capability1 SIP_HELPER
|
|
report_capability1 SIP0_HELPER
|
|
report_capability1 SNMP_HELPER
|
|
report_capability1 TFTP_HELPER
|
|
report_capability1 TFTP0_HELPER
|
|
|
|
echo CAPVERSION=$SHOREWALL_CAPVERSION
|
|
echo KERNELVERSION=$KERNELVERSION
|
|
}
|
|
|
|
report_capabilities1() {
|
|
echo "#"
|
|
echo "# $g_product $SHOREWALL_VERSION detected the following iptables/netfilter capabilities - $(date)"
|
|
echo "#"
|
|
report_capabilities_unsorted1 | sort
|
|
}
|
|
|
|
interface_status() {
|
|
case $(cat $1) in
|
|
0)
|
|
echo Enabled
|
|
;;
|
|
1)
|
|
echo Disabled
|
|
;;
|
|
*)
|
|
echo Unknown
|
|
;;
|
|
esac
|
|
}
|
|
|
|
show_interfaces() {
|
|
local f
|
|
local interface
|
|
local printed
|
|
|
|
for f in ${VARDIR}/*.status; do
|
|
if [ -f $f ]; then
|
|
interface=$(basename $f)
|
|
echo " Interface ${interface%.status} is $(interface_status $f)"
|
|
printed=Yes
|
|
fi
|
|
done
|
|
|
|
[ -n "$printed" ] && echo
|
|
}
|
|
|
|
status_command() {
|
|
local finished
|
|
finished=0
|
|
local option
|
|
local interfaces
|
|
|
|
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=
|
|
;;
|
|
i*)
|
|
interfaces=Yes
|
|
option=${option#i}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ $# -eq 0 ] || missing_argument
|
|
|
|
[ $VERBOSITY -ge 1 ] && echo "${g_product}-$SHOREWALL_VERSION Status at $g_hostname - $(date)" && echo
|
|
show_status
|
|
[ -n "$interfaces" ] && show_interfaces
|
|
exit $status
|
|
}
|
|
|
|
drop_command() {
|
|
if product_is_started ; then
|
|
if ! chain_exists dynamic; then
|
|
echo "Dynamic blacklisting is not supported in the current $g_product configuration"
|
|
exit 2
|
|
fi
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
block DROP Dropped $*
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
else
|
|
fatal_error "$g_product is not started"
|
|
fi
|
|
}
|
|
|
|
logdrop_command() {
|
|
if product_is_started ; then
|
|
if ! chain_exists dynamic; then
|
|
echo "Dynamic blacklisting is not supported in the current $g_product configuration"
|
|
exit 2
|
|
fi
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
block logdrop Dropped $*
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
else
|
|
fatal_error "$g_product is not started"
|
|
fi
|
|
}
|
|
|
|
reject_command() {
|
|
if product_is_started ; then
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
block $1 Rejected $*
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
else
|
|
fatal_error "$g_product is not started"
|
|
fi
|
|
}
|
|
|
|
blacklist_command() {
|
|
local family
|
|
|
|
[ $# -gt 0 ] || fatal_error "Missing address"
|
|
|
|
[ -z "$g_blacklistipset" ] && fatal_error "The blacklist command is not supported in the current $g_product configuration"
|
|
|
|
case ${IPSET:=ipset} in
|
|
*/*)
|
|
if [ ! -x "$IPSET" ]; then
|
|
fatal_error "IPSET=$IPSET does not exist or is not executable"
|
|
fi
|
|
;;
|
|
*)
|
|
IPSET="$(mywhich $IPSET)"
|
|
[ -n "$IPSET" ] || fatal_error "The ipset utility cannot be located"
|
|
;;
|
|
esac
|
|
|
|
$IPSET -A $g_blacklistipset $@ || { error_message "ERROR: Address $1 not blacklisted"; return 1; }
|
|
|
|
return 0
|
|
}
|
|
save_command() {
|
|
local finished
|
|
finished=0
|
|
|
|
shift
|
|
|
|
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*)
|
|
g_counters=Yes
|
|
option=${option#C}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case $# in
|
|
0)
|
|
;;
|
|
1)
|
|
RESTOREFILE="$1"
|
|
validate_restorefile '<restore file>'
|
|
;;
|
|
*)
|
|
too_many_arguments $2
|
|
;;
|
|
esac
|
|
|
|
g_restorepath=${VARDIR}/$RESTOREFILE
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
|
|
save_config
|
|
|
|
result=$?
|
|
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
|
|
exit $result
|
|
}
|
|
|
|
forget_command() {
|
|
case $# in
|
|
0)
|
|
missing_argument
|
|
;;
|
|
1)
|
|
;;
|
|
2)
|
|
RESTOREFILE="$2"
|
|
validate_restorefile '<restore file>'
|
|
;;
|
|
*)
|
|
too_many_arguments $3
|
|
;;
|
|
esac
|
|
|
|
g_restorepath=${VARDIR}/$RESTOREFILE
|
|
|
|
if [ -x $g_restorepath ]; then
|
|
rm -f $g_restorepath
|
|
rm -f ${g_restorepath}-iptables
|
|
rm -f ${g_restorepath}-ipsets
|
|
rm -f ${g_restorepath}-arptables
|
|
echo " $g_restorepath removed"
|
|
elif [ -f $g_restorepath ]; then
|
|
echo " $g_restorepath exists and is not a saved $g_product configuration"
|
|
fi
|
|
rm -f ${VARDIR}/save
|
|
}
|
|
|
|
ipcalc_command() {
|
|
local address
|
|
local vlsm
|
|
|
|
[ $g_family -eq 6 ] && fatal_error "$g_product does not support the ipcalc command"
|
|
|
|
if [ $# -eq 2 ]; then
|
|
address=${2%/*}
|
|
vlsm=${2#*/}
|
|
elif [ $# -eq 3 ]; then
|
|
address=$2
|
|
vlsm=$(ip_vlsm $3)
|
|
elif [ $# -eq 0 ]; then
|
|
missing_argument
|
|
else
|
|
too_many_arguments $4
|
|
fi
|
|
|
|
valid_address $address || fatal_error "Invalid IP address: $address"
|
|
[ -z "$vlsm" ] && fatal_error "Missing VLSM"
|
|
[ "x$address" = "x$vlsm" ] && "Invalid VLSM"
|
|
[ $vlsm -gt 32 ] && fatal_error "Invalid VLSM: /$vlsm"
|
|
|
|
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_command() {
|
|
local range
|
|
|
|
[ $g_family -eq 6 ] && fatal_error "$g_product does not support the iprange command"
|
|
|
|
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
|
|
;;
|
|
*)
|
|
fatal_error "Invalid ip range: $range"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
ipdecimal_command() {
|
|
if [ $# eq 1 ]; then
|
|
missing_argument
|
|
else
|
|
[ $# -eq 2 ] || too_many_arguments $3
|
|
fi
|
|
|
|
[ $g_family -eq 6 ] && fatal_error "$g_product does not support the iprange command"
|
|
|
|
case $2 in
|
|
*.*.*.*)
|
|
valid_address $2 || fatal_error "Invalid IP address: $2"
|
|
echo " $(decodeaddr $2)"
|
|
;;
|
|
*)
|
|
echo " $(encodeaddr $2)"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
iptrace_command() {
|
|
if product_is_started ; then
|
|
$g_tool -t raw -A PREROUTING $@ -j TRACE
|
|
$g_tool -t raw -A OUTPUT $@ -j TRACE
|
|
else
|
|
fatal_error "$g_product is not started"
|
|
fi
|
|
}
|
|
|
|
noiptrace_command() {
|
|
if product_is_started ; then
|
|
$g_tool -t raw -D PREROUTING $@ -j TRACE
|
|
$g_tool -t raw -D OUTPUT $@ -j TRACE
|
|
else
|
|
fatal_error "$g_product is not started"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# 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
|
|
}
|
|
|
|
################################################################################
|
|
# The remaining functions are used by the Lite cli - they are overloaded by
|
|
# the Standard CLI by loading lib.cli-std
|
|
################################################################################
|
|
#
|
|
# Set the configuration variables from shorewall[6]-lite.conf.
|
|
#
|
|
get_config() {
|
|
local config
|
|
local lib
|
|
|
|
ensure_config_path
|
|
|
|
config=$(find_file ${g_program}.conf)
|
|
|
|
if [ -f $config ]; then
|
|
if [ -r $config ]; then
|
|
. $config
|
|
else
|
|
fatal_error "Cannot read $config! (Hint: Are you root?)"
|
|
fi
|
|
else
|
|
fatal_error "$config does not exist!"
|
|
fi
|
|
|
|
ensure_config_path
|
|
|
|
[ -f ${VARDIR}/firewall.conf ] && . ${VARDIR}/firewall.conf
|
|
|
|
[ -n "$PATH" ] || PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
|
|
|
|
setup_logread
|
|
#
|
|
# 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
|
|
fatal_error "The program specified in IPTABLES does not exist or is not executable"
|
|
fi
|
|
else
|
|
IPTABLES=$(mywhich iptables 2> /dev/null)
|
|
if [ -z "$IPTABLES" ] ; then
|
|
fatal_error "Can't find iptables executable"
|
|
fi
|
|
fi
|
|
|
|
g_tool=$IPTABLES
|
|
else
|
|
if [ -n "$IP6TABLES" ]; then
|
|
if [ ! -x "$IP6TABLES" ]; then
|
|
fatal_error "The program specified in IP6TABLES does not exist or is not executable"
|
|
fi
|
|
else
|
|
IP6TABLES=$(mywhich ip6tables 2> /dev/null)
|
|
if [ -z "$IP6TABLES" ] ; then
|
|
fatal_error "Can't find ip6tables executable"
|
|
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
|
|
|
|
if qt mywhich hostname; then
|
|
g_hostname=$(hostname 2> /dev/null)
|
|
elif qt mywhich uname; then
|
|
g_hostname=$(uname -n 2> /dev/null)
|
|
else
|
|
g_hostname=localhost
|
|
fi
|
|
|
|
if [ -n "$IPSET" ]; then
|
|
case "$IPSET" in
|
|
*/*)
|
|
if [ ! -x "$IPSET" ] ; then
|
|
fatal_error "The program specified in IPSET ($IPSET) does not exist or is not executable"
|
|
fi
|
|
;;
|
|
*)
|
|
prog="$(mywhich $IPSET 2> /dev/null)"
|
|
if [ -z "$prog" ] ; then
|
|
fatal_error "Can't find $IPSET executable"
|
|
fi
|
|
IPSET=$prog
|
|
;;
|
|
esac
|
|
else
|
|
IPSET=''
|
|
fi
|
|
|
|
if [ -n "$WORKAROUNDS" ]; then
|
|
case $WORKAROUNDS in
|
|
[Yy]es)
|
|
;;
|
|
[Nn]o)
|
|
WORKAROUNDS=''
|
|
;;
|
|
*)
|
|
fatal_error "Invalid setting ($WORKAROUNDS) for WORKAROUNDS"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
TC=tc
|
|
|
|
IP=$(mywhich ip 2> /dev/null)
|
|
|
|
g_loopback=$(find_loopback_interfaces)
|
|
|
|
if [ -n "$PAGER" -a -t 1 ]; then
|
|
case $PAGER in
|
|
/*)
|
|
g_pager="$PAGER"
|
|
[ -f "$g_pager" ] || fatal_error "PAGER=$PAGER does not exist"
|
|
;;
|
|
*)
|
|
g_pager=$(mywhich pager 2> /dev/null)
|
|
[ -n "$g_pager" ] || fatal_error "PAGER=$PAGER does not exist"
|
|
;;
|
|
esac
|
|
|
|
[ -x "$g_pager" ] || fatal_error "PAGER $g_pager is not executable"
|
|
|
|
g_pager="| $g_pager"
|
|
fi
|
|
|
|
if [ -n "$DYNAMIC_BLACKLIST" ]; then
|
|
case $DYNAMIC_BLACKLIST in
|
|
[Nn]o)
|
|
DYNAMIC_BLACKLIST='';
|
|
;;
|
|
[Yy]es)
|
|
;;
|
|
ipset|ipset::*|ipset-only|ipset-only::*|ipset,src-dst|ipset-only,src-dst::*)
|
|
g_blacklistipset=SW_DBL$g_family
|
|
;;
|
|
ipset:[a-zA-Z]*)
|
|
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset:}
|
|
g_blacklistipset=${g_blacklistipset%%:*}
|
|
;;
|
|
ipset,src-dst:[a-zA-Z]*)
|
|
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset,src-dst:}
|
|
g_blacklistipset=${g_blacklistipset%%:*}
|
|
;;
|
|
ipset-only:[a-zA-Z]*)
|
|
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only:}
|
|
g_blacklistipset=${g_blacklistipset%%:*}
|
|
;;
|
|
ipset-only,src-dst:[a-zA-Z]*)
|
|
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only,src-dst:}
|
|
g_blacklistipset=${g_blacklistipset%%:*}
|
|
;;
|
|
*)
|
|
fatal_error "Invalid value ($DYNAMIC_BLACKLIST) for DYNAMIC_BLACKLIST"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
lib=$(find_file lib.cli-user)
|
|
|
|
[ -f $lib ] && . $lib
|
|
|
|
}
|
|
#
|
|
# Start Command Executor
|
|
#
|
|
start_command() {
|
|
local finished
|
|
finished=0
|
|
|
|
do_it() {
|
|
local rc
|
|
rc=0
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
|
|
if [ -x ${VARDIR}/firewall ]; then
|
|
if [ -n "$g_fast" -a -x ${VARDIR}/${RESTOREFILE} -a ! ${VARDIR}/firewall -nt ${VARDIR}/${RESTOREFILE} ]; then
|
|
run_it ${VARDIR}/${RESTOREFILE} $g_debugging restore
|
|
else
|
|
run_it ${VARDIR}/firewall $g_debugging start
|
|
fi
|
|
rc=$?
|
|
else
|
|
error_message "${VARDIR}/firewall is missing or is not executable"
|
|
mylogger kern.err "ERROR:$g_product start failed"
|
|
rc=6
|
|
fi
|
|
|
|
[ -n "$g_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}
|
|
;;
|
|
C*)
|
|
g_counters=Yes
|
|
option=${option#C}
|
|
;;
|
|
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}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case $# in
|
|
0)
|
|
;;
|
|
*)
|
|
too_many_arguments $1
|
|
;;
|
|
esac
|
|
|
|
do_it
|
|
}
|
|
|
|
#
|
|
# Reload/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 "$(mywhich 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}
|
|
;;
|
|
C*)
|
|
g_counters=Yes
|
|
option=${option#C}
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
esac
|
|
done
|
|
shift
|
|
;;
|
|
*)
|
|
finished=1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case $# in
|
|
0)
|
|
;;
|
|
*)
|
|
too_many_arguments $1
|
|
;;
|
|
esac
|
|
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
|
|
if [ -x ${VARDIR}/firewall ]; then
|
|
run_it ${VARDIR}/firewall $g_debugging $COMMAND
|
|
rc=$?
|
|
else
|
|
error_message "${VARDIR}/firewall is missing or is not executable"
|
|
mylogger kern.err "ERROR:$g_product $COMMAND failed"
|
|
rc=6
|
|
fi
|
|
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
return $rc
|
|
}
|
|
|
|
run_command() {
|
|
if [ -x ${VARDIR}/firewall ] ; then
|
|
run_it ${VARDIR}/firewall $g_debugging $@
|
|
else
|
|
fatal_error "${VARDIR}/firewall does not exist or is not executable"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Echo the parameters if product is Shorewall or Shorewall6
|
|
#
|
|
ecko() {
|
|
[ -z "$g_lite" ] && echo "$@"
|
|
}
|
|
#
|
|
# Give Usage Information
|
|
#
|
|
usage() # $1 = exit status
|
|
{
|
|
echo "Usage: $(basename $0) [debug|trace] [nolock] [ -q ] [ -v[-1|{0-2}] ] [ -t ] <command>"
|
|
echo "where <command> is one of:"
|
|
echo " add <interface>[:<host-list>] ... <zone>"
|
|
echo " allow <address> ..."
|
|
echo " blacklist <address> [ <option> ... ]"
|
|
ecko " [ check | ck ] [ -e ] [ -r ] [ -p ] [ -r ] [ -T ] [ -i ] [ <directory> ]"
|
|
echo " clear"
|
|
ecko " [ compile | co ] [ -e ] [ -p ] [ -t ] [ -c ] [ -d ] [ -T ] [ -i ] [ <directory name> ] [ <path name> ]"
|
|
echo " close <source> <dest> [ <protocol> [ <port> ] ]"
|
|
echo " delete <interface>[:<host-list>] ... <zone>"
|
|
echo " disable <interface>"
|
|
echo " drop <address> ..."
|
|
echo " dump [ -x ] [ -l ] [ -m ]"
|
|
echo " enable <interface>"
|
|
ecko " export [ <directory1> ] [<user>@]<system>[:<directory2>]"
|
|
echo " forget [ <file name> ]"
|
|
echo " help"
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
echo " ipcalc { <address>/<vlsm> | <address> <netmask> }"
|
|
echo " ipdecimal { <address> | <integer> }"
|
|
echo " iprange <address>-<address>"
|
|
fi
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
echo " iptrace <iptables match expression>"
|
|
else
|
|
echo " iptrace <ip6tables match expression>"
|
|
fi
|
|
|
|
ecko " load [ -s ] [ -c ] [ -r <root user> ] [ -T ] [ -i ] [ <directory> ] <system>"
|
|
echo " logdrop <address> ..."
|
|
echo " logreject <address> ..."
|
|
echo " logwatch [<refresh interval>]"
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
echo " noiptrace <iptables match expression>"
|
|
else
|
|
echo " noiptrace <ip6tables match expression>"
|
|
fi
|
|
|
|
echo " open <source> <dest> [ <protocol> [ <port> ] ]"
|
|
echo " reenable <interface>"
|
|
ecko " refresh [ -d ] [ -n ] [ -T ] [ -D <directory> ] [ <chain>... ]"
|
|
echo " reject <address> ..."
|
|
ecko " reload [ -s ] [ -c ] [ -r <root user> ] [ -T ] [ -i ] [ <directory> ] <system>"
|
|
|
|
if [ -z "$g_lite" ]; then
|
|
echo " remote-reload [ -s ] [ -c ] [ -r <root-name> ] [ -T ] [ -i ] [ <directory> ] <system>"
|
|
echo " remote-restart [ -s ] [ -c ] [ -r <root-name> ] [ -T ] [ -i ] [ <directory> ] <system>"
|
|
echo " remote-start [ -s ] [ -c ] [ -r <root-name> ] [ -T ] [ -i ] [ <directory> ] <system>"
|
|
fi
|
|
|
|
echo " reset [ <chain> ... ]"
|
|
|
|
if [ -n "$g_lite" ]; then
|
|
echo " restart [ -n ] [ -p ] [ -f ] [ -C ] [ <directory> ]"
|
|
else
|
|
echo " restart [ -n ] [ -p ] [-d] [ -f ] [ -c ] [ -T ] [ -i ] [ -C ] [ <directory> ]"
|
|
fi
|
|
|
|
echo " restore [ -n ] [ -p ] [ -C ] [ <file name> ]"
|
|
echo " run <command> [ <parameter> ... ]"
|
|
ecko " safe-restart [ -t <timeout> ] [ <directory> ]"
|
|
ecko " safe-start [ -t <timeout> ] [ <directory> ]"
|
|
echo " save [ -C ] [ <file name> ]"
|
|
echo " savesets"
|
|
echo " [ show | list | ls ] [ -b ] [ -x ] [ -t {filter|mangle|nat} ] [ {chain [<chain> [ <chain> ... ]"
|
|
ecko " [ show | list | ls ] actions"
|
|
echo " [ show | list | ls ] arptables"
|
|
echo " [ show | list | ls ] [ -f ] capabilities"
|
|
echo " [ show | list | ls ] [ -x ] {bl|blacklists}"
|
|
echo " [ show | list | ls ] classifiers"
|
|
echo " [ show | list | ls ] config"
|
|
echo " [ show | list | ls ] connections"
|
|
echo " [ show | list | ls ] event [ <event> ...]"
|
|
echo " [ show | list | ls ] events"
|
|
echo " [ show | list | ls ] filters"
|
|
echo " [ show | list | ls ] ip"
|
|
|
|
if [ $g_family -eq 4 ]; then
|
|
echo " [ show | list | ls ] ipa"
|
|
fi
|
|
|
|
echo " [ show | list | ls ] [ -m ] log [<regex>]"
|
|
echo " [ show | list | ls ] [ -x ] mangle|nat|raw|rawpost"
|
|
ecko " [ show | list | ls ] macro <macro>"
|
|
ecko " [ show | list | ls ] macros"
|
|
echo " [ show | list | ls ] nfacct"
|
|
echo " [ show | list | ls ] opens"
|
|
echo " [ show | list | ls ] policies"
|
|
echo " [ show | list | ls ] routing"
|
|
echo " [ show | list | ls ] tc [ device ]"
|
|
echo " [ show | list | ls ] vardir"
|
|
echo " [ show | list | ls ] zones"
|
|
|
|
if [ -n "$g_lite" ]; then
|
|
echo " start [ -f ] [ -p ] [ -C ] [ <directory> ]"
|
|
else
|
|
echo " start [ -f ] [ -n ] [ -p ] [ -c ] [ -T ] [ -i ] [ -C ] [ <directory> ]"
|
|
fi
|
|
|
|
echo " status [ -i ]"
|
|
echo " stop"
|
|
ecko " try <directory> [ <timeout> ]"
|
|
ecko " update [ -a ] [ -b ] [ -r ] [ -T ] [ -D ] [ -i ] [-t] [-s] [-n] [-A] [ <directory> ]"
|
|
echo " version [ -a ]"
|
|
echo
|
|
exit $1
|
|
}
|
|
|
|
#
|
|
# This is the main entry point into the CLI. It directly handles all commands supported
|
|
# by both the full and lite versions. Note, however, that functions such as start_command()
|
|
# appear in both this library and it lib.cli-std. The ones in cli-std overload the ones
|
|
# here if that lib is loaded below.
|
|
#
|
|
shorewall_cli() {
|
|
g_debugging=
|
|
|
|
if [ $# -gt 0 ] && [ "x$1" = "xdebug" -o "x$1" = "xtrace" ]; then
|
|
g_debugging=$1
|
|
shift
|
|
fi
|
|
|
|
g_nolock=
|
|
|
|
if [ $# -gt 0 ] && [ "$1" = "nolock" ]; then
|
|
g_nolock=nolock
|
|
shift
|
|
fi
|
|
|
|
g_noroutes=
|
|
g_purge=
|
|
g_ipt_options="-nv"
|
|
g_fast=
|
|
g_verbose_offset=0
|
|
g_use_verbosity=
|
|
g_debug=
|
|
g_export=
|
|
g_refreshchains=:none:
|
|
g_confess=
|
|
g_update=
|
|
g_annotate=
|
|
g_recovering=
|
|
g_timestamp=
|
|
g_shorewalldir=
|
|
g_haveconfig=
|
|
g_conditional=
|
|
g_file=
|
|
g_doing="Compiling"
|
|
g_inline=
|
|
g_counters=
|
|
g_loopback=
|
|
g_compiled=
|
|
g_pager=
|
|
g_blacklistipset=
|
|
|
|
VERBOSE=
|
|
VERBOSITY=1
|
|
|
|
[ -n "$g_lite" ] || . ${g_basedir}/lib.cli-std
|
|
|
|
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 ] && missing_option_value -c
|
|
[ -n "$g_lite" ] && fatal_error "$g_product does not support the -c option"
|
|
|
|
if [ ! -d $2 ]; then
|
|
if [ -e $2 ]; then
|
|
fatal_error "$2 is not a directory"
|
|
else
|
|
fatal_error "Directory $2 does not exist"
|
|
fi
|
|
fi
|
|
|
|
g_shorewalldir=$(resolve_file $2)
|
|
option=
|
|
shift
|
|
;;
|
|
e*)
|
|
[ -n "$g_lite" ] && fatal_error "$g_product does not support the -e option"
|
|
g_export=Yes
|
|
option=${option#e}
|
|
;;
|
|
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}
|
|
;;
|
|
[vV]*)
|
|
case $option in
|
|
v*)
|
|
option=${option#v}
|
|
;;
|
|
*)
|
|
option=${option#V}
|
|
;;
|
|
esac
|
|
|
|
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=
|
|
;;
|
|
*)
|
|
option_error $option
|
|
;;
|
|
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=
|
|
|
|
[ -f ${g_confdir}/vardir ] && . ${g_confdir}/vardir
|
|
|
|
[ -n "${VARDIR:=/var/lib/$g_program}" ]
|
|
|
|
g_firewall=${VARDIR}/firewall
|
|
|
|
version_file=${g_sharedir}/version
|
|
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*)
|
|
g_ring_bell="echo \a"
|
|
g_echo_e="echo"
|
|
;;
|
|
*)
|
|
g_ring_bell="echo -e \a"
|
|
g_echo_e="echo -e"
|
|
;;
|
|
esac
|
|
|
|
case $(echo -n "Testing") in
|
|
-n*)
|
|
g_echo_n=
|
|
;;
|
|
*)
|
|
g_echo_n=-n
|
|
;;
|
|
esac
|
|
|
|
COMMAND=$1
|
|
|
|
case "$COMMAND" in
|
|
start)
|
|
get_config Yes Yes
|
|
shift
|
|
start_command $@
|
|
;;
|
|
stop|clear)
|
|
[ $# -ne 1 ] && too_many_arguments $2
|
|
get_config
|
|
[ -x $g_firewall ] || fatal_error "$g_product has never been started"
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
run_it $g_firewall $g_debugging $COMMAND
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
;;
|
|
reset)
|
|
get_config
|
|
shift
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
[ -x $g_firewall ] || fatal_error "$g_product has never been started"
|
|
run_it $g_firewall $g_debugging reset $@
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
;;
|
|
reload|restart)
|
|
get_config Yes Yes
|
|
shift
|
|
restart_command $@
|
|
;;
|
|
disable|enable|reenable)
|
|
get_config Yes
|
|
if product_is_started; then
|
|
run_it ${VARDIR}/firewall $g_debugging $@
|
|
else
|
|
fatal_error "$g_product is not running"
|
|
fi
|
|
;;
|
|
blacklist)
|
|
get_config Yes
|
|
shift
|
|
[ -n "$g_nolock" ] || mutex_on
|
|
blacklist_command $@
|
|
[ -n "$g_nolock" ] || mutex_off
|
|
;;
|
|
run)
|
|
[ $# -gt 1 ] || fatal_error "Missing function name"
|
|
get_config Yes
|
|
run_command $@
|
|
;;
|
|
show|list|ls)
|
|
get_config Yes No Yes
|
|
shift
|
|
show_command $@
|
|
;;
|
|
status)
|
|
[ "$(id -u)" != 0 ] && fatal_error "The status command may only be run by root"
|
|
get_config
|
|
shift
|
|
status_command $@
|
|
;;
|
|
dump)
|
|
get_config Yes No Yes
|
|
shift
|
|
dump_command $@
|
|
;;
|
|
hits)
|
|
[ $g_family -eq 6 ] && fatal_error "$g_product does not support the hits command"
|
|
get_config Yes No Yes
|
|
[ -n "$g_debugging" ] && set -x
|
|
shift
|
|
hits_command $@
|
|
;;
|
|
version)
|
|
shift
|
|
version_command $@
|
|
;;
|
|
logwatch)
|
|
get_config Yes Yes Yes
|
|
banner="${g_product}-$SHOREWALL_VERSION Logwatch at $g_hostname -"
|
|
logwatch_command $@
|
|
;;
|
|
drop)
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
[ $# -eq 1 ] && missing_argument
|
|
drop_command $@
|
|
;;
|
|
logdrop)
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
[ $# -eq 1 ] && missing_argument
|
|
logdrop_command $@
|
|
;;
|
|
reject|logreject)
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
[ $# -eq 1 ] && missing_argument
|
|
reject_command $@
|
|
;;
|
|
open|close)
|
|
get_config
|
|
shift
|
|
open_close_command $@
|
|
;;
|
|
allow)
|
|
get_config
|
|
allow_command $@
|
|
;;
|
|
add)
|
|
get_config
|
|
shift
|
|
add_command $@
|
|
;;
|
|
delete)
|
|
get_config
|
|
shift
|
|
delete_command $@
|
|
;;
|
|
save)
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
save_command $@
|
|
;;
|
|
forget)
|
|
get_config
|
|
forget_command $@
|
|
;;
|
|
ipcalc)
|
|
[ -n "$g_debugging" ] && set -x
|
|
ipcalc_command $@
|
|
;;
|
|
iprange)
|
|
[ -n "$g_debugging" ] && set -x
|
|
iprange_command $@
|
|
;;
|
|
ipdecimal)
|
|
[ -n "$g_debugging" ] && set -x
|
|
ipdecimal_command $@
|
|
;;
|
|
restore)
|
|
get_config
|
|
shift
|
|
restore_command $@
|
|
;;
|
|
call)
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
#
|
|
# Way to call functions in the libraries directly
|
|
#
|
|
shift
|
|
|
|
if [ $# -gt 0 ]; then
|
|
#
|
|
# First look for it here
|
|
#
|
|
if type $1 2> /dev/null | fgrep -q 'is a function'; then
|
|
#
|
|
# It's a shell function -- call it
|
|
#
|
|
$@
|
|
elif type $1 2> /dev/null | fgrep -q 'is a shell function'; then
|
|
#
|
|
# It's a shell function -- call it
|
|
#
|
|
$@
|
|
else
|
|
#
|
|
# It isn't a function visible to this script -- try
|
|
# the compiled firewall
|
|
#
|
|
run_it $g_firewall $g_debugging call $@
|
|
fi
|
|
else
|
|
missing_argument
|
|
fi
|
|
;;
|
|
help)
|
|
shift
|
|
usage
|
|
;;
|
|
iptrace)
|
|
get_config
|
|
shift
|
|
iptrace_command $@
|
|
;;
|
|
noiptrace)
|
|
get_config
|
|
shift
|
|
noiptrace_command $@
|
|
;;
|
|
savesets)
|
|
[ $# -eq 1 ] || too_many_arguments $2
|
|
get_config
|
|
[ -n "$g_debugging" ] && set -x
|
|
savesets1
|
|
;;
|
|
*)
|
|
if [ -z "$g_lite" ]; then
|
|
compiler_command $@
|
|
else
|
|
fatal_error "Invalid command: $COMMAND"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|