shorewall_code/Shorewall-core/lib.cli

4717 lines
112 KiB
Plaintext
Raw Normal View History

#
# 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 [ "$LOGFILE" = "systemd" ]; then
g_logread="journalctl -r"
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 700 $g_restorepath
chmod 600 ${g_restorepath}-iptables
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
chmod 600 ${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 && chmod 600 ${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
2011-04-03 18:56:30 +02:00
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}"
2011-04-03 18:56:30 +02:00
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}"
2011-04-03 18:56:30 +02:00
fi
;;
chain)
shift
eval show_chain $@ $g_pager
;;
vardir)
echo $VARDIR;
;;
2009-11-15 18:24:56 +01:00
policies)
[ $# -gt 1 ] && too_many_arguments $2
eval show_policies $g_pager
2009-11-15 18:24:56 +01:00
;;
2011-02-02 02:15:49 +01:00
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
2011-02-02 01:47:20 +01:00
;;
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
2009-06-25 00:28:43 +02:00
if [ $1 = dynamic -a $# -gt 1 ]; then
shift
[ $# -eq 1 ] || too_many_arguments $2
list_zone $1
2009-06-25 00:28:43 +02:00
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
}
2011-02-02 01:47:20 +01:00
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'
2011-02-02 01:47:20 +01:00
echo
done
else
echo " No IP Accounting Tables Defined"
echo
2011-02-02 01:47:20 +01:00
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"
2011-02-02 01:47:20 +01:00
perip_accounting
fi
2011-02-02 01:47:20 +01:00
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
2010-08-11 02:33:50 +02:00
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
2010-08-11 02:33:50 +02:00
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
2011-09-01 01:38:58 +02:00
[ -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 allowed
local which
which='-s'
local range
range='--src-range'
local dynexists
if [ -n "$g_blacklistipset" ]; then
2010-08-11 02:33:50 +02:00
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
fi
if chain_exists dynamic; then
dynexists=Yes
elif [ -z "$g_blacklistipset" ]; 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
allowed=''
case $1 in
from)
which='-s'
range='--src-range'
continue
;;
to)
which='-d'
range='--dst-range'
continue
;;
*-*)
if [ -n "$g_blacklistipset" ]; then
if qt $IPSET -D $g_blacklistipset $1; then
allowed=Yes
fi
fi
if [ -n "$dynexists" ]; then
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
allowed=Yes
fi
fi
;;
*)
if [ -n "$g_blacklistipset" ]; then
if qt $IPSET -D $g_blacklistipset $1; then
allowed=Yes
fi
fi
if [ -n "$dynexists" ]; then
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
allowed=Yes
fi
fi
;;
esac
if [ -n "$allowed" ]; then
progress_message2 "$1 Allowed"
else
error_message "WARNING: $1 already allowed (not dynamically blacklisted)"
fi
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
2010-08-04 06:06:17 +02:00
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
2010-08-27 17:35:33 +02:00
report_capability1 MARK_ANYWHERE
2010-11-24 19:46:06 +01:00
report_capability1 HEADER_MATCH
2011-01-29 23:18:53 +01:00
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
if $IPSET -A $g_blacklistipset $@ -exist; then
local message
progress_message2 "$1 Blacklisted"
if [ -n "$g_disconnect" ]; then
message=$(conntrack -D -s $1 2>&1)
if [ -n "$message" ]; then
message=$(echo $message | sed 's/^.*: //; s/ / src /')
progress_message2 $message
fi
if [ $g_disconnect = src-dst ]; then
message=$(conntrack -D -d $1 2>&1)
if [ -n "$message" ]; then
message=$(echo $message | sed 's/^.*: //; s/ / dst /')
progress_message2 $message
fi
fi
fi
else
error_message "ERROR: Address $1 not blacklisted"
return 1
fi
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
}
setup_dbl() {
local original
original=$DYNAMIC_BLACKLIST
case $DYNAMIC_BLACKLIST in
*:*,)
fatal_error "Invalid value ($original) for DYNAMIC_BLACKLIST"
;;
ipset*,disconnect*)
if qt mywhich conntrack; then
g_disconnect=src
DYNAMIC_BLACKLIST=$(echo $DYNAMIC_BLACKLIST | sed 's/,disconnect//')
else
fatal_error "The 'disconnect' option requires that the conntrack utility be installed"
fi
;;
esac
case $DYNAMIC_BLACKLIST in
ipset*,src-dst*)
#
# This utility doesn't need to know about 'src-dst'
#
DYNAMIC_BLACKLIST=$(echo $DYNAMIC_BLACKLIST | sed 's/,src-dst//')
[ -n "$g_disconnect" ] && g_disconnect=src-dst
;;
esac
case $DYNAMIC_BLACKLIST in
ipset*,timeout*)
#
# This utility doesn't need to know about 'timeout=nnn'
#
DYNAMIC_BLACKLIST=$(echo $DYNAMIC_BLACKLIST | sed -r 's/,timeout=[[:digit:]]+//')
;;
esac
case $DYNAMIC_BLACKLIST in
[Nn]o)
DYNAMIC_BLACKLIST='';
;;
[Yy]es)
;;
ipset|ipset::*|ipset-only|ipset-only::*)
g_blacklistipset=SW_DBL$g_family
;;
ipset:[a-zA-Z]*)
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset:}
g_blacklistipset=${g_blacklistipset%%:*}
;;
ipset-only:[a-zA-Z]*)
g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only:}
g_blacklistipset=${g_blacklistipset%%:*}
;;
*)
fatal_error "Invalid value ($original) for DYNAMIC_BLACKLIST"
;;
esac
}
################################################################################
# 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)
[ -n "$PAGER" ] || PAGER=$DEFAULT_PAGER
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
setup_dbl
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=
g_disconnect=
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
#
$@
(Fwd) [Shorewall-users] Shorewall-lite on OpenWRT ------- 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>
2016-05-29 11:00:52 +02:00
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
}