Use iptables[6]-restore to instantiate the 'stopped' ruleset

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

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@9761 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2009-03-30 00:49:00 +00:00
parent 7210e8c15e
commit cddd1b1ae9
5 changed files with 162 additions and 219 deletions

View File

@ -156,6 +156,7 @@ our %EXPORT_TAGS = (
set_global_variables set_global_variables
create_netfilter_load create_netfilter_load
create_chainlist_reload create_chainlist_reload
create_stop_load
$section $section
%sections %sections
%targets %targets
@ -2972,4 +2973,97 @@ sub create_chainlist_reload($) {
emit "}\n"; emit "}\n";
} }
#
# Generate the netfilter input to stop the firewall
#
sub create_stop_load( $ ) {
my $test = shift;
my @table_list;
if ( $family == F_IPV4 ) {
push @table_list, 'raw' if $capabilities{RAW_TABLE};
push @table_list, 'nat' if $capabilities{NAT_ENABLED};
push @table_list, 'mangle' if $capabilities{MANGLE_ENABLED} && $config{MANGLE_ENABLED};
push @table_list, 'filter';
} else {
@table_list = qw( raw mangle filter );
}
$mode = NULL_MODE;
my $utility = $family == F_IPV4 ? 'iptables-restore' : 'ip6tables-restore';
my $UTILITY = $family == F_IPV4 ? 'IPTABLES_RESTORE' : 'IP6TABLES_RESTORE';
emit '';
emit "exec 3>\${VARDIR}/.${utility}-stop-input";
enter_cat_mode;
my $date = localtime;
unless ( $test ) {
emit_unindented '#';
emit_unindented "# Generated by Shorewall-perl $globals{VERSION} - $date";
emit_unindented '#';
}
for my $table ( @table_list ) {
emit_unindented "*$table";
my @chains;
#
# iptables-restore seems to be quite picky about the order of the builtin chains
#
for my $chain ( @builtins ) {
my $chainref = $chain_table{$table}{$chain};
if ( $chainref ) {
assert( $chainref->{cmdlevel} == 0 );
emit_unindented ":$chain $chainref->{policy} [0:0]";
push @chains, $chainref;
}
}
#
# First create the chains in the current table
#
for my $chain ( grep $chain_table{$table}{$_}->{referenced} , ( sort keys %{$chain_table{$table}} ) ) {
my $chainref = $chain_table{$table}{$chain};
unless ( $chainref->{builtin} ) {
assert( $chainref->{cmdlevel} == 0 );
emit_unindented ":$chainref->{name} - [0:0]";
push @chains, $chainref;
}
}
#
# Then emit the rules
#
for my $chainref ( @chains ) {
emitr $chainref->{name}, $_ for ( grep defined $_, @{$chainref->{rules}} );
}
#
# Commit the changes to the table
#
enter_cat_mode unless $mode == CAT_MODE;
emit_unindented 'COMMIT';
}
enter_cmd_mode;
#
# Now generate the actual ip[6]tables-restore command
#
emit( 'exec 3>&-',
'',
'[ -n "$DEBUG" ] && command=debug_restore_input || command=$' . $UTILITY,
'',
'progress_message2 "Running $command..."',
'',
"cat \${VARDIR}/.${utility}-stop-input | \$command # Use this nonsensical form to appease SELinux",
'if [ $? != 0 ]; then',
qq( fatal_error "$command Failed. Input is in \${VARDIR}/.${utility}-stop-input"),
"fi\n"
);
}
1; 1;

View File

@ -516,13 +516,6 @@ EOF
emit "}\n"; emit "}\n";
unless ( $test ) {
if ( $family == F_IPV4 ) {
copy $globals{SHAREDIRPL} . 'prog.footer';
} else {
copy $globals{SHAREDIRPL} . 'prog.footer6';
}
}
} }
# #
@ -805,7 +798,17 @@ sub compiler {
# S T O P _ F I R E W A L L # S T O P _ F I R E W A L L
# (Writes the stop_firewall() function to the compiled script) # (Writes the stop_firewall() function to the compiled script)
# #
compile_stop_firewall; compile_stop_firewall( $test );
#
# Copy the footer to the object
#
unless ( $test ) {
if ( $family == F_IPV4 ) {
copy $globals{SHAREDIRPL} . 'prog.footer';
} else {
copy $globals{SHAREDIRPL} . 'prog.footer6';
}
}
# #
# Close, rename and secure the object # Close, rename and secure the object
# #

View File

@ -39,7 +39,6 @@ our @EXPORT = qw( process_tos
setup_ecn setup_ecn
add_common_rules add_common_rules
setup_mac_lists setup_mac_lists
process_criticalhosts
process_routestopped process_routestopped
process_rules process_rules
generate_matrix generate_matrix
@ -364,52 +363,6 @@ sub setup_blacklist() {
} }
} }
sub process_criticalhosts() {
my @critical = ();
my $fn = open_file 'routestopped';
my $seq = 0;
first_entry "$doing $fn for critical hosts...";
while ( read_a_line ) {
my $routeback = 0;
my ($interface, $hosts, $options, $proto, $ports, $sports ) = split_line 1, 6, 'routestopped file';
fatal_error "Unknown interface ($interface)" unless known_interface $interface;
$hosts = ALLIP unless $hosts ne '-';
my @hosts;
$seq++;
for my $host ( split_list $hosts, 'host' ) {
validate_host $host, 1;
push @hosts, "$interface|$host|$seq";
}
unless ( $options eq '-' ) {
for my $option (split_list $options, 'option' ) {
unless ( $option eq 'routeback' || $option eq 'source' || $option eq 'dest' || $option eq 'notrack' ) {
if ( $option eq 'critical' ) {
fatal_error "PROTO may not be specified with 'critical'" if $proto ne '-';
push @critical, @hosts;
} else {
warning_message "Unknown routestopped option ( $option ) ignored";
}
}
}
}
}
\@critical;
}
sub process_routestopped() { sub process_routestopped() {
my ( @allhosts, %source, %dest , %notrack, @rule ); my ( @allhosts, %source, %dest , %notrack, @rule );
@ -472,6 +425,7 @@ sub process_routestopped() {
} }
} else { } else {
warning_message "Unknown routestopped option ( $option ) ignored" unless $option eq 'critical'; warning_message "Unknown routestopped option ( $option ) ignored" unless $option eq 'critical';
warning_message "The 'critical' option is no longer supported (or needed)";
} }
} }
} }
@ -479,8 +433,6 @@ sub process_routestopped() {
push @allhosts, @hosts; push @allhosts, @hosts;
} }
my $tool = $family == F_IPV4 ? '$IPTABLES' : '$IP6TABLES';
for my $host ( @allhosts ) { for my $host ( @allhosts ) {
my ( $interface, $h, $seq ) = split /\|/, $host; my ( $interface, $h, $seq ) = split /\|/, $host;
my $source = match_source_net $h; my $source = match_source_net $h;
@ -489,24 +441,24 @@ sub process_routestopped() {
my $desti = match_dest_dev $interface; my $desti = match_dest_dev $interface;
my $rule = shift @rule; my $rule = shift @rule;
emit "$tool -A INPUT $sourcei $source $rule -j ACCEPT"; add_rule $filter_table->{INPUT}, "$sourcei $source $rule -j ACCEPT";
emit "$tool -A OUTPUT $desti $dest $rule -j ACCEPT" unless $config{ADMINISABSENTMINDED}; add_rule $filter_table->{OUTPUT}, "$desti $dest $rule -j ACCEPT" unless $config{ADMINISABSENTMINDED};
my $matched = 0; my $matched = 0;
if ( $source{$host} ) { if ( $source{$host} ) {
emit "$tool -A FORWARD $sourcei $source $rule -j ACCEPT"; add_rule $filter_table->{FORWARD}, "$sourcei $source $rule -j ACCEPT";
$matched = 1; $matched = 1;
} }
if ( $dest{$host} ) { if ( $dest{$host} ) {
emit "$tool -A FORWARD $desti $dest $rule -j ACCEPT"; add_rule $filter_table->{FORWARD}, "$desti $dest $rule -j ACCEPT";
$matched = 1; $matched = 1;
} }
if ( $notrack{$host} ) { if ( $notrack{$host} ) {
emit "$tool -t raw -A PREROUTING $sourcei $source $rule -j NOTRACK"; add_rule $raw_table->{PREROUTING}, "$sourcei $source $rule -j NOTRACK";
emit "$tool -t raw -A OUTPUT $desti $dest $rule -j NOTRACK"; add_rule $raw_table->{OUTPUT}, "$desti $dest $rule -j NOTRACK";
} }
unless ( $matched ) { unless ( $matched ) {
@ -515,7 +467,7 @@ sub process_routestopped() {
my ( $interface1, $h1 , $seq1 ) = split /\|/, $host1; my ( $interface1, $h1 , $seq1 ) = split /\|/, $host1;
my $dest1 = match_dest_net $h1; my $dest1 = match_dest_net $h1;
my $desti1 = match_dest_dev $interface1; my $desti1 = match_dest_dev $interface1;
emit "$tool -A FORWARD $sourcei $desti1 $source $dest1 $rule -j ACCEPT"; add_rule $filter_table->{FORWARD}, "$sourcei $desti1 $source $dest1 $rule -j ACCEPT";
clearrule; clearrule;
} }
} }
@ -2117,7 +2069,8 @@ sub setup_mss( ) {
# #
# Compile the stop_firewall() function # Compile the stop_firewall() function
# #
sub compile_stop_firewall() { sub compile_stop_firewall( $ ) {
my $test = shift;
emit <<'EOF'; emit <<'EOF';
# #
@ -2126,6 +2079,14 @@ sub compile_stop_firewall() {
stop_firewall() { stop_firewall() {
EOF EOF
Shorewall::Chains::initialize( $family );
initialize_chain_table;
if ( $config{ADMINISABSENTMINDED} ) {
$filter_table->{OUTPUT}{policy} = 'ACCEPT';
}
if ( $family == F_IPV4 ) { if ( $family == F_IPV4 ) {
emit( ' deletechain() {', emit( ' deletechain() {',
' qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1' ); ' qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1' );
@ -2137,24 +2098,6 @@ EOF
emit <<'EOF'; 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 case $COMMAND in
stop|clear|restore) stop|clear|restore)
;; ;;
@ -2211,42 +2154,15 @@ EOF
run_stop_exit run_stop_exit
EOF 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} ) { if ( $capabilities{NAT_ENABLED} ) {
emit <<'EOF'; emit<<'EOF';
delete_nat if [ -f ${VARDIR}/nat ]; then
for chain in PREROUTING POSTROUTING OUTPUT; do while read external interface; do
qt1 $IPTABLES -t nat -P $chain ACCEPT del_ip_addr $external $interface
done done < ${VARDIR}/nat
rm -f ${VARDIR}/nat
fi
EOF EOF
} }
@ -2259,9 +2175,10 @@ EOF
f=/proc/sys/net/ipv4/conf/$interface/proxy_arp f=/proc/sys/net/ipv4/conf/$interface/proxy_arp
[ -f $f ] && echo 0 > $f [ -f $f ] && echo 0 > $f
done < ${VARDIR}/proxyarp done < ${VARDIR}/proxyarp
fi
rm -f ${VARDIR}/proxyarp rm -f ${VARDIR}/proxyarp
fi
EOF EOF
} }
@ -2273,109 +2190,27 @@ EOF
'restore_default_route' 'restore_default_route'
); );
my $criticalhosts = process_criticalhosts; my @chains = $config{ADMINISABSENTMINDED} ? qw/INPUT FORWARD/ : qw/INPUT OUTPUT FORWARD/;
if ( @$criticalhosts ) { add_rule $filter_table->{$_}, '-m state --state ESTABLISHED,RELATED -j ACCEPT' for @chains;
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 ) { if ( $family == F_IPV6 ) {
emit <<'EOF'; add_rule $filter_table->{INPUT}, '-s ff80::/10 -j ACCEPT';
# add_rule $filter_table->{INPUT}, '-d ff80::/10 -j ACCEPT';
# Enable link local and multi-cast add_rule $filter_table->{INPUT}, '-d ff00::/10 -j ACCEPT';
#
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}; unless ( $config{ADMINISABSENTMINDED} ) {
run_iptables -A OUTPUT -d ff80::/10 -j ACCEPT add_rule $filter_table->{OUTPUT}, '-d ff80::/10 -j ACCEPT';
run_iptables -A OUTPUT -d ff00::/10 -j ACCEPT add_rule $filter_table->{OUTPUT}, '-d ff00::/10 -j ACCEPT';
}
EOF
} }
process_routestopped; process_routestopped;
emit( 'do_iptables -A INPUT -i lo -j ACCEPT', add_rule $filter_table->{INPUT}, '-i lo -j ACCEPT';
'do_iptables -A OUTPUT -o lo -j ACCEPT' add_rule $filter_table->{INPUT}, '-i lo -j ACCEPT';
);
emit 'do_iptables -A OUTPUT -o lo -j ACCEPT' unless $config{ADMINISABSENTMINDED}; add_rule $filter_table->{OUTPUT}, '-o lo -j ACCEPT' unless $config{ADMINISABSENTMINDED};
my $interfaces = find_interfaces_by_option 'dhcp'; my $interfaces = find_interfaces_by_option 'dhcp';
@ -2383,17 +2218,19 @@ EOF
my $ports = $family == F_IPV4 ? '67:68' : '546:547'; my $ports = $family == F_IPV4 ? '67:68' : '546:547';
for my $interface ( @$interfaces ) { for my $interface ( @$interfaces ) {
emit "do_iptables -A INPUT -p udp -i $interface --dport $ports -j ACCEPT"; add_rule $filter_table->{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}; add_rule $filter_table->{OUTPUT}, "-p udp -o $interface --dport $ports -j ACCEPT" unless $config{ADMINISABSENTMINDED};
# #
# This might be a bridge # This might be a bridge
# #
emit "do_iptables -A FORWARD -p udp -i $interface -o $interface --dport $ports -j ACCEPT"; add_rule $filter_table->{FORWARD}, "-p udp -i $interface -o $interface --dport $ports -j ACCEPT";
} }
} }
emit ''; emit '';
create_stop_load $test;
if ( $family == F_IPV4 ) { if ( $family == F_IPV4 ) {
if ( $config{IP_FORWARDING} eq 'on' ) { if ( $config{IP_FORWARDING} eq 'on' ) {
emit( 'echo 1 > /proc/sys/net/ipv4/ip_forward', emit( 'echo 1 > /proc/sys/net/ipv4/ip_forward',
@ -2426,7 +2263,7 @@ EOF
my @ipsets = all_ipsets; my @ipsets = all_ipsets;
if ( @ipsets ) { if ( @ipsets ) {
emit <<'EOF' emit <<'EOF';
if [ -n "$(mywhich ipset)" ]; then if [ -n "$(mywhich ipset)" ]; then
if ipset -S > ${VARDIR}/ipsets.tmp; then if ipset -S > ${VARDIR}/ipsets.tmp; then
@ -2435,8 +2272,10 @@ EOF
# #
grep -q '^-N' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save grep -q '^-N' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save
fi fi
fi
EOF EOF
emit " ipset -X $_" for @ipsets;
emit "fi\n";
} }
emit ' emit '

View File

@ -10,6 +10,8 @@ Changes in Shorewall 4.3.8
5) Suppress leading whitespace on certain continuation lines. 5) Suppress leading whitespace on certain continuation lines.
6) Use iptables[6]-restore to stop the firewall.
Changes in Shorewall 4.3.7 Changes in Shorewall 4.3.7
1) Fix forward treatment of interface options. 1) Fix forward treatment of interface options.

View File

@ -83,6 +83,11 @@ None.
address is ignored so the SOURCE column effectively contains address is ignored so the SOURCE column effectively contains
"net:206.124.146.177,206.124.147.178,206.124.146.180". "net:206.124.146.177,206.124.147.178,206.124.146.180".
4) The generated script now uses iptables[6]-restore to instantiate
the Netfilter ruleset during processing of the 'stop' command. As a
consequence, the 'critical' option in /etc/shorewall/route_stopped
is no longer needed and will result in a warning.
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
N E W F E A T U R E S IN 4 . 3 N E W F E A T U R E S IN 4 . 3
---------------------------------------------------------------------------- ----------------------------------------------------------------------------