Centralize iptables knowledge in the Chains module -- first phase

Signed-off-by: Tom Eastep <teastep@shorewall.net>

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@9742 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2009-03-28 19:21:36 +00:00
parent cc5c6b40aa
commit d9622dabfe
4 changed files with 55 additions and 387 deletions

View File

@ -144,6 +144,8 @@ our %EXPORT_TAGS = (
log_rule log_rule
expand_rule expand_rule
addnatjump addnatjump
set_chain_variables
mark_firewall_not_started
get_interface_address get_interface_address
get_interface_addresses get_interface_addresses
get_interface_bcasts get_interface_bcasts
@ -152,6 +154,7 @@ our %EXPORT_TAGS = (
get_interface_mac get_interface_mac
have_global_variables have_global_variables
set_global_variables set_global_variables
compile_stop_firewall
create_netfilter_load create_netfilter_load
create_chainlist_reload create_chainlist_reload
$section $section
@ -2001,6 +2004,46 @@ sub mysplit( $ ) {
@result; @result;
} }
#
# Set up the IPTABLES-related run-time variables
#
sub set_chain_variables() {
if ( $family == F_IPV4 ) {
if ( $config{IPTABLES} ) {
emit( qq(IPTABLES="$config{IPTABLES}"),
'[ -x "$IPTABLES" ] || startup_error "IPTABLES=$IPTABLES does not exist or is not executable"',
);
} else {
emit( '[ -z "$IPTABLES" ] && IPTABLES=$(mywhich iptables) # /sbin/shorewall exports IPTABLES',
'[ -n "$IPTABLES" -a -x "$IPTABLES" ] || startup_error "Can\'t find iptables executable"'
);
}
emit( 'IPTABLES_RESTORE=${IPTABLES}-restore',
'[ -x "$IPTABLES_RESTORE" ] || startup_error "$IPTABLES_RESTORE does not exist or is not executable"' );
} else {
if ( $config{IP6TABLES} ) {
emit( qq(IP6TABLES="$config{IP6TABLES}"),
'[ -x "$IP6TABLES" ] || startup_error "IP6TABLES=$IP6TABLES does not exist or is not executable"',
);
} else {
emit( '[ -z "$IP6TABLES" ] && IP6TABLES=$(mywhich ip6tables) # /sbin/shorewall6 exports IP6TABLES',
'[ -n "$IP6TABLES" -a -x "$IP6TABLES" ] || startup_error "Can\'t find ip6tables executable"'
);
}
emit( 'IP6TABLES_RESTORE=${IP6TABLES}-restore',
'[ -x "$IP6TABLES_RESTORE" ] || startup_error "$IP6TABLES_RESTORE does not exist or is not executable"' );
}
}
#
# Emit code that marks the firewall as not started.
#
sub mark_firewall_not_started() {
emit ( 'qt1 $IPTABLES -L shorewall -n && qt1 $IPTABLES -F shorewall && qt1 $IPTABLES -X shorewall' );
}
#################################################################################################################### ####################################################################################################################
# The following functions come in pairs. The first function returns the name of a run-time shell variable that # The following functions come in pairs. The first function returns the name of a run-time shell variable that
# will hold a piece of interface-oriented data detected at run-time. The second creates a code fragment to detect # will hold a piece of interface-oriented data detected at run-time. The second creates a code fragment to detect

View File

@ -208,33 +208,7 @@ sub generate_script_2() {
'' ''
); );
if ( $family == F_IPV4 ) { set_chain_variables;
if ( $config{IPTABLES} ) {
emit( qq(IPTABLES="$config{IPTABLES}"),
'[ -x "$IPTABLES" ] || startup_error "IPTABLES=$IPTABLES does not exist or is not executable"',
);
} else {
emit( '[ -z "$IPTABLES" ] && IPTABLES=$(mywhich iptables) # /sbin/shorewall exports IPTABLES',
'[ -n "$IPTABLES" -a -x "$IPTABLES" ] || startup_error "Can\'t find iptables executable"'
);
}
emit( 'IPTABLES_RESTORE=${IPTABLES}-restore',
'[ -x "$IPTABLES_RESTORE" ] || startup_error "$IPTABLES_RESTORE does not exist or is not executable"' );
} else {
if ( $config{IP6TABLES} ) {
emit( qq(IP6TABLES="$config{IP6TABLES}"),
'[ -x "$IP6TABLES" ] || startup_error "IP6TABLES=$IP6TABLES does not exist or is not executable"',
);
} else {
emit( '[ -z "$IP6TABLES" ] && IP6TABLES=$(mywhich ip6tables) # /sbin/shorewall6 exports IP6TABLES',
'[ -n "$IP6TABLES" -a -x "$IP6TABLES" ] || startup_error "Can\'t find ip6tables executable"'
);
}
emit( 'IP6TABLES_RESTORE=${IP6TABLES}-restore',
'[ -x "$IP6TABLES_RESTORE" ] || startup_error "$IP6TABLES_RESTORE does not exist or is not executable"' );
}
append_file 'params' if $config{EXPORTPARAMS}; append_file 'params' if $config{EXPORTPARAMS};
@ -294,354 +268,11 @@ sub generate_script_2() {
} }
sub compile_stop_firewall() {
emit <<'EOF';
#
# Stop/restore the firewall after an error or because of a 'stop' or 'clear' command
#
stop_firewall() {
EOF
if ( $family == F_IPV4 ) {
emit( ' deletechain() {',
' qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1' );
} else {
emit( ' deletechain() {',
' qt $IP6TABLES -L $1 -n && qt $IP6TABLES -F $1 && qt $IP6TABLES -X $1' );
}
emit <<'EOF';
}
deleteallchains() {
do_iptables -F
do_iptables -X
}
delete_nat() {
do_iptables -t nat -F
do_iptables -t nat -X
if [ -f ${VARDIR}/nat ]; then
while read external interface; do
del_ip_addr $external $interface
done < ${VARDIR}/nat
rm -f ${VARDIR}/nat
fi
}
case $COMMAND in
stop|clear|restore)
;;
*)
set +x
case $COMMAND in
start)
logger -p kern.err "ERROR:$PRODUCT start failed"
;;
restart)
logger -p kern.err "ERROR:$PRODUCT restart failed"
;;
restore)
logger -p kern.err "ERROR:$PRODUCT restore failed"
;;
esac
if [ "$RESTOREFILE" = NONE ]; then
COMMAND=clear
clear_firewall
echo "$PRODUCT Cleared"
kill $$
exit 2
else
RESTOREPATH=${VARDIR}/$RESTOREFILE
if [ -x $RESTOREPATH ]; then
echo Restoring ${PRODUCT:=Shorewall}...
if $RESTOREPATH restore; then
echo "$PRODUCT restored from $RESTOREPATH"
set_state "Started"
else
set_state "Unknown"
fi
kill $$
exit 2
fi
fi
;;
esac
set_state "Stopping"
STOPPING="Yes"
TERMINATOR=
deletechain shorewall
run_stop_exit
EOF
if ( $capabilities{MANGLE_ENABLED} && $config{MANGLE_ENABLED} ) {
emit <<'EOF';
run_iptables -t mangle -F
run_iptables -t mangle -X
for chain in PREROUTING INPUT FORWARD POSTROUTING; do
qt1 $IPTABLES -t mangle -P $chain ACCEPT
done
EOF
}
if ( $capabilities{RAW_TABLE} ) {
if ( $family == F_IPV4 ) {
emit <<'EOF';
run_iptables -t raw -F
run_iptables -t raw -X
for chain in PREROUTING OUTPUT; do
qt1 $IPTABLES -t raw -P $chain ACCEPT
done
EOF
} else {
emit <<'EOF';
run_iptables -t raw -F
run_iptables -t raw -X
for chain in PREROUTING OUTPUT; do
qt1 $IP6TABLES -t raw -P $chain ACCEPT
done
EOF
}
}
if ( $capabilities{NAT_ENABLED} ) {
emit <<'EOF';
delete_nat
for chain in PREROUTING POSTROUTING OUTPUT; do
qt1 $IPTABLES -t nat -P $chain ACCEPT
done
EOF
}
if ( $family == F_IPV4 ) {
emit <<'EOF';
if [ -f ${VARDIR}/proxyarp ]; then
while read address interface external haveroute; do
qt arp -i $external -d $address pub
[ -z "${haveroute}${NOROUTES}" ] && qt ip route del $address dev $interface
f=/proc/sys/net/ipv4/conf/$interface/proxy_arp
[ -f $f ] && echo 0 > $f
done < ${VARDIR}/proxyarp
fi
rm -f ${VARDIR}/proxyarp
EOF
}
push_indent;
emit 'delete_tc1' if $config{CLEAR_TC};
emit( 'undo_routing',
'restore_default_route'
);
my $criticalhosts = process_criticalhosts;
if ( @$criticalhosts ) {
if ( $config{ADMINISABSENTMINDED} ) {
emit ( 'for chain in INPUT OUTPUT; do',
' setpolicy $chain ACCEPT',
'done',
'',
'setpolicy FORWARD DROP',
'',
'deleteallchains',
''
);
for my $hosts ( @$criticalhosts ) {
my ( $interface, $host, $seq ) = ( split /\|/, $hosts );
my $source = match_source_net $host;
my $dest = match_dest_net $host;
emit( "do_iptables -A INPUT -i $interface $source -j ACCEPT",
"do_iptables -A OUTPUT -o $interface $dest -j ACCEPT"
);
}
emit( '',
'for chain in INPUT OUTPUT; do',
' setpolicy $chain DROP',
"done\n"
);
} else {
emit( '',
'for chain in INPUT OUTPUT; do',
' setpolicy $chain ACCEPT',
'done',
'',
'setpolicy FORWARD DROP',
'',
"deleteallchains\n"
);
for my $hosts ( @$criticalhosts ) {
my ( $interface, $host , $seq ) = ( split /|/, $hosts );
my $source = match_source_net $host;
my $dest = match_dest_net $host;
emit( "do_iptables -A INPUT -i $interface $source -j ACCEPT",
"do_iptables -A OUTPUT -o $interface $dest -j ACCEPT"
);
}
emit( "\nsetpolicy INPUT DROP",
'',
'for chain in INPUT FORWARD; do',
' setcontinue $chain',
"done\n"
);
}
} elsif ( $config{ADMINISABSENTMINDED} ) {
emit( 'for chain in INPUT FORWARD; do',
' setpolicy $chain DROP',
'done',
'',
'setpolicy OUTPUT ACCEPT',
'',
'deleteallchains',
'',
'for chain in INPUT FORWARD; do',
' setcontinue $chain',
"done\n",
);
} else {
emit( 'for chain in INPUT OUTPUT FORWARD; do',
' setpolicy $chain DROP',
'done',
'',
"deleteallchains\n"
);
}
if ( $family == F_IPV6 ) {
emit <<'EOF';
#
# Enable link local and multi-cast
#
run_iptables -A INPUT -s ff80::/10 -j ACCEPT
run_iptables -A INPUT -d ff80::/10 -j ACCEPT
run_iptables -A INPUT -d ff00::/10 -j ACCEPT
EOF
emit <<'EOF' unless $config{ADMINISABSENTMINDED};
run_iptables -A OUTPUT -d ff80::/10 -j ACCEPT
run_iptables -A OUTPUT -d ff00::/10 -j ACCEPT
EOF
}
process_routestopped;
emit( 'do_iptables -A INPUT -i lo -j ACCEPT',
'do_iptables -A OUTPUT -o lo -j ACCEPT'
);
emit 'do_iptables -A OUTPUT -o lo -j ACCEPT' unless $config{ADMINISABSENTMINDED};
my $interfaces = find_interfaces_by_option 'dhcp';
if ( @$interfaces ) {
my $ports = $family == F_IPV4 ? '67:68' : '546:547';
for my $interface ( @$interfaces ) {
emit "do_iptables -A INPUT -p udp -i $interface --dport $ports -j ACCEPT";
emit "do_iptables -A OUTPUT -p udp -o $interface --dport $ports -j ACCEPT" unless $config{ADMINISABSENTMINDED};
#
# This might be a bridge
#
emit "do_iptables -A FORWARD -p udp -i $interface -o $interface --dport $ports -j ACCEPT";
}
}
emit '';
if ( $family == F_IPV4 ) {
if ( $config{IP_FORWARDING} eq 'on' ) {
emit( 'echo 1 > /proc/sys/net/ipv4/ip_forward',
'progress_message2 IPv4 Forwarding Enabled' );
} elsif ( $config{IP_FORWARDING} eq 'off' ) {
emit( 'echo 0 > /proc/sys/net/ipv4/ip_forward',
'progress_message2 IPv4 Forwarding Disabled!'
);
}
} else {
for my $interface ( all_bridges ) {
emit "do_iptables -A FORWARD -p 58 -i $interface -o $interface -j ACCEPT";
}
if ( $config{IP_FORWARDING} eq 'on' ) {
emit( 'echo 1 > /proc/sys/net/ipv6/conf/all/forwarding',
'progress_message2 IPv6 Forwarding Enabled' );
} elsif ( $config{IP_FORWARDING} eq 'off' ) {
emit( 'echo 0 > /proc/sys/net/ipv6/conf/all/forwarding',
'progress_message2 IPv6 Forwarding Disabled!'
);
}
}
pop_indent;
emit '
run_stopped_exit';
my @ipsets = all_ipsets;
if ( @ipsets ) {
emit <<'EOF'
if [ -n "$(mywhich ipset)" ]; then
if ipset -S > ${VARDIR}/ipsets.tmp; then
#
# Don't save an 'empty' file
#
grep -q '^-N' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save
fi
fi
EOF
}
emit '
set_state "Stopped"
logger -p kern.info "$PRODUCT Stopped"
case $COMMAND in
stop|clear)
;;
*)
#
# The firewall is being stopped when we were trying to do something
# else. Kill the shell in case we\'re running in a subshell
#
kill $$
;;
esac
}
';
}
# #
# Final stage of script generation. # Final stage of script generation.
# #
# Copy prog.functions to the object file. # Copy prog.functions to the object file.
# Generate code for loading the various files in /var/lib/shorewall[-lite] # Generate code for loading the various files in /var/lib/shorewall[6][-lite]
# Generate code to add IP addresses under ADD_IP_ALIASES and ADD_SNAT_ALIASES # Generate code to add IP addresses under ADD_IP_ALIASES and ADD_SNAT_ALIASES
# #
# Generate the 'setup_netfilter()' function that runs iptables-restore. # Generate the 'setup_netfilter()' function that runs iptables-restore.
@ -697,17 +328,6 @@ sub generate_script_3($) {
} }
if ( $family == F_IPV4 ) { if ( $family == F_IPV4 ) {
emit ( '#',
'# Recent kernels are difficult to configure -- we see state match omitted a lot so we check for it here',
'#',
'qt1 $IPTABLES -N foox1234',
'qt1 $IPTABLES -A foox1234 -m state --state ESTABLISHED,RELATED -j ACCEPT',
'result=$?',
'qt1 $IPTABLES -F foox1234',
'qt1 $IPTABLES -X foox1234',
'[ $result = 0 ] || startup_error "Your kernel/iptables do not include state match support. No version of Shorewall will run on this system"',
'' );
for my $interface ( @{find_interfaces_by_option 'norfc1918'} ) { for my $interface ( @{find_interfaces_by_option 'norfc1918'} ) {
emit ( "addr=\$(ip -f inet addr show $interface 2> /dev/null | grep 'inet\ ' | head -n1)", emit ( "addr=\$(ip -f inet addr show $interface 2> /dev/null | grep 'inet\ ' | head -n1)",
'if [ -n "$addr" ]; then', 'if [ -n "$addr" ]; then',
@ -759,9 +379,11 @@ sub generate_script_3($) {
emit ( 'else' , emit ( 'else' ,
' run_init_exit', ' run_init_exit',
'fi', 'fi',
'', '' );
'qt1 $IPTABLES -L shorewall -n && qt1 $IPTABLES -F shorewall && qt1 $IPTABLES -X shorewall',
'', mark_firewall_not_started;
emit ('',
'delete_proxyarp', 'delete_proxyarp',
'' ''
); );

View File

@ -1850,6 +1850,9 @@ sub determine_capabilities( $ ) {
qt1( "$iptables -N $sillyname" ); qt1( "$iptables -N $sillyname" );
qt1( "$iptables -N $sillyname1" ); qt1( "$iptables -N $sillyname1" );
fatal_error 'Your kernel/iptables do not include state match support. No version of Shorewall will run on this system'
unless qt1( "$iptables -A $sillyname -m state --state ESTABLISHED,RELATED -j ACCEPT");
if ( $family == F_IPV4 ) { if ( $family == F_IPV4 ) {
$capabilities{CONNTRACK_MATCH} = qt1( "$iptables -A $sillyname -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT" ); $capabilities{CONNTRACK_MATCH} = qt1( "$iptables -A $sillyname -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT" );
} else { } else {

View File

@ -188,8 +188,8 @@ None.
/var/lib/shorewall[6]/firewall. /var/lib/shorewall[6]/firewall.
5) Dynamic zone support is once again available for IPv4. This support 5) Dynamic zone support is once again available for IPv4. This support
is built on top of ipsets so you must have installed the is built on top of ipsets so you must have the xtables-addons
xtable-addons. installed on the firewall system.
Dynamic zones are available when Shorewall-lite is used as well. Dynamic zones are available when Shorewall-lite is used as well.