From 3858683e942fefe0546c3b9827501a97e0c587d3 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sun, 28 Sep 2014 11:19:41 -0700 Subject: [PATCH] Allow saving a specified list of ipsets Signed-off-by: Tom Eastep --- Shorewall-core/lib.cli | 74 ++++++++------- Shorewall/Perl/Shorewall/Chains.pm | 121 ++++++++++++++++++------ Shorewall/Perl/Shorewall/Compiler.pm | 1 + Shorewall/Perl/Shorewall/Config.pm | 11 ++- Shorewall/Perl/prog.footer | 8 ++ Shorewall/manpages/shorewall.conf.xml | 7 +- Shorewall6/manpages/shorewall6.conf.xml | 19 ++++ 7 files changed, 175 insertions(+), 66 deletions(-) diff --git a/Shorewall-core/lib.cli b/Shorewall-core/lib.cli index 105aef5f2..28900709a 100644 --- a/Shorewall-core/lib.cli +++ b/Shorewall-core/lib.cli @@ -428,45 +428,47 @@ do_save() { ;; esac - 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= + if ! run_it ${VARDIR}/firewall savesets ${g_restorepath}-ipsets; 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 [ -f /etc/debian_version ] && [ $(cat /etc/debian_version) = 5.0.3 ]; then + # + # The 'grep -v' is a hack for a bug in ipset's nethash implementation when xtables-addons is applied to Lenny + # + hack='| grep -v /31' + else + hack= 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 [ -f /etc/debian_version ] && [ $(cat /etc/debian_version) = 5.0.3 ]; then - # - # The 'grep -v' is a hack for a bug in ipset's nethash implementation when xtables-addons is applied to Lenny - # - hack='| grep -v /31' - else - hack= + if eval $IPSET -S $hack > ${VARDIR}/ipsets.tmp; then + # + # Don't save an 'empty' file + # + grep -qE -- '^(-N|create )' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${g_restorepath}-ipsets + fi fi - - if eval $IPSET -S $hack > ${VARDIR}/ipsets.tmp; then - # - # Don't save an 'empty' file - # - grep -qE -- '^(-N|create )' ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${g_restorepath}-ipsets - fi - fi - ;; - [Nn]o) - ;; - *) - error_message "WARNING: Invalid value ($SAVE_IPSETS) for SAVE_IPSETS" - ;; - esac + ;; + [Nn]o) + ;; + *) + error_message "WARNING: Invalid value ($SAVE_IPSETS) for SAVE_IPSETS" + ;; + esac + fi return $status } diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index f678ed328..9f2c6a422 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -262,6 +262,7 @@ our %EXPORT_TAGS = ( set_global_variables save_dynamic_chains load_ipsets + create_save_ipsets validate_nfobject create_nfobjects create_netfilter_load @@ -7995,11 +7996,77 @@ sub ensure_ipset( $ ) { } } +# +# Generate the save_ipsets() function +# +sub create_save_ipsets() { + my @ipsets = all_ipsets; + + emit( "#\n#Save the ipsets specified by the SAVE_IPSETS setting and by dynamic zones\n#", + 'save_ipsets() {' ); + + if ( @ipsets || @{$globals{SAVED_IPSETS}} || ( $config{SAVE_IPSETS} && have_ipset_rules ) ) { + emit( ' local file' , + '', + ' file=$1', + '' + ); + + if ( @ipsets ) { + ensure_ipset( $_ ) for @ipsets; + } + + emit( '' , + ' rm -f ${VARDIR}/ipsets.save' , + '' ); + + if ( $config{SAVE_IPSETS} ) { + if ( $family == F_IPV4 ) { + emit ( ' if [ -f /etc/debian_version ] && [ $(cat /etc/debian_version) = 5.0.3 ]; then' , + ' #', + ' # The \'grep -v\' is a hack for a bug in ipset\'s nethash implementation when xtables-addons is applied to Lenny' , + ' #', + ' hack=\'| grep -v /31\'' , + ' else' , + ' hack=' , + ' fi' , + '', + ' if eval $IPSET -S $hack > ${VARDIR}/ipsets.tmp; then' , + " grep -qE -- \"^(-N|create )\" \${VARDIR}/ipsets.tmp && mv -f \${VARDIR}/ipsets.tmp \$file" , + ' fi' ); + } else { + emit ( ' if eval $IPSET -S > ${VARDIR}/ipsets.tmp; then' , + " grep -qE -- \"^(-N|create )\" \${VARDIR}/ipsets.tmp && mv -f \${VARDIR}/ipsets.tmp \$file" , + ' fi' ); + } + } elsif ( @ipsets || $globals{SAVED_IPSETS} ) { + emit( ' rm -f ${VARDIR}/ipsets.tmp' , + ' touch ${VARDIR}/ipsets.tmp' , + '' ); + + emit( " \$IPSET -S $_ >> >> \${VARDIR}/ipsets.tmp" ) for @ipsets; + + emit( " if qt \$IPSET list $_; then" , + " \$IPSET save $_ >> \${VARDIR}/ipsets.tmp" , + ' else' , + " error_message 'ipset $_ not saved (not found)'" , + " fi\n" ) for @{$globals{SAVED_IPSETS}}; + + emit( " grep -qE -- \"(-N|^create )\" \${VARDIR}/ipsets.tmp && cat \${VARDIR}/ipsets.tmp >> \$file\n" ); + emit( '' , + "}\n" ); + } + } else { + emit( ' error_message "WARNING: No ipsets were saved"', + "}\n" ); + } +} + sub load_ipsets() { my @ipsets = all_ipsets; - if ( @ipsets || ( $config{SAVE_IPSETS} && have_ipset_rules ) ) { + if ( @ipsets || @{$globals{SAVED_IPSETS}} || ( $config{SAVE_IPSETS} && have_ipset_rules ) ) { emit ( '', 'local hack', '', @@ -8026,9 +8093,25 @@ sub load_ipsets() { emit ( '' ); ensure_ipset( $_ ) for @ipsets; emit ( '' ); + + emit ( ' if [ -f ${VARDIR}/ipsets.save ]; then' , + ' $IPSET flush' , + ' $IPSET destroy' , + ' $IPSET restore < ${VARDIR}/ipsets.save' , + " fi\n" ) for @{$globals{SAVED_IPSETS}}; } } else { ensure_ipset( $_ ) for @ipsets; + + if ( @{$globals{SAVED_IPSETS}} ) { + emit ( '' ); + + emit ( ' if [ -f ${VARDIR}/ipsets.save ]; then' , + ' $IPSET flush' , + ' $IPSET destroy' , + ' $IPSET restore < ${VARDIR}/ipsets.save' , + " fi\n" ) for @{$globals{SAVED_IPSETS}}; + } } emit ( 'elif [ "$COMMAND" = restore -a -z "$g_recovering" ]; then' ); @@ -8052,6 +8135,12 @@ sub load_ipsets() { } } else { ensure_ipset( $_ ) for @ipsets; + + emit ( ' if [ -f ${VARDIR}/ipsets.save ]; then' , + ' $IPSET flush' , + ' $IPSET destroy' , + ' $IPSET restore < ${VARDIR}/ipsets.save' , + " fi\n" ) for @{$globals{SAVED_IPSETS}}; } if ( @ipsets ) { @@ -8059,36 +8148,14 @@ sub load_ipsets() { ensure_ipset( $_ ) for @ipsets; } - emit( 'elif [ "$COMMAND" = stop ]; then' ); - - if ( @ipsets ) { - ensure_ipset( $_ ) for @ipsets; - emit( '' ); - } - - if ( $family == F_IPV4 ) { - emit ( ' if [ -f /etc/debian_version ] && [ $(cat /etc/debian_version) = 5.0.3 ]; then' , - ' #', - ' # The \'grep -v\' is a hack for a bug in ipset\'s nethash implementation when xtables-addons is applied to Lenny' , - ' #', - ' hack=\'| grep -v /31\'' , - ' else' , - ' hack=' , - ' fi' , - '', - ' if eval $IPSET -S $hack > ${VARDIR}/ipsets.tmp; then' , - ' grep -qE -- "^(-N|create )" ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save' , - ' fi' ); - } else { - emit ( ' if eval $IPSET -S > ${VARDIR}/ipsets.tmp; then' , - ' grep -qE -- "^(-N|create )" ${VARDIR}/ipsets.tmp && mv -f ${VARDIR}/ipsets.tmp ${VARDIR}/ipsets.save' , - ' fi' ); - } + emit( 'elif [ "$COMMAND" = stop ]; then' , + ' save_ipsets' + ); if ( @ipsets ) { emit( 'elif [ "$COMMAND" = refresh ]; then' ); ensure_ipset( $_ ) for @ipsets; - } + }; emit ( 'fi' , '' ); diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index d03e31566..2951b148f 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -348,6 +348,7 @@ sub generate_script_3($) { create_netfilter_load( $test ); create_arptables_load( $test ) if $have_arptables; create_chainlist_reload( $_[0] ); + create_save_ipsets; emit "#\n# Start/Restart the Firewall\n#"; diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 228f9b370..5f0d42873 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -1106,7 +1106,8 @@ sub initialize( $;$$) { $family == F_IPV4 ? 'shorewall' : 'shorewall6' ) if defined $shorewallrc; - $globals{SHAREDIRPL} = "$shorewallrc{SHAREDIR}/shorewall/"; + $globals{SHAREDIRPL} = "$shorewallrc{SHAREDIR}/shorewall/"; + $globals{SAVED_IPSETS} = []; if ( $family == F_IPV4 ) { $globals{SHAREDIR} = "$shorewallrc{SHAREDIR}/shorewall"; @@ -5570,7 +5571,13 @@ sub get_configuration( $$$$$ ) { unsupported_yes_no 'BRIDGING'; unsupported_yes_no_warning 'RFC1918_STRICT'; - default_yes_no 'SAVE_IPSETS' , ''; + unless (default_yes_no 'SAVE_IPSETS', '', '*' ) { + my @sets = (split_list( $val= $config{SAVE_IPSETS}, 'ipset' )); + $globals{SAVED_IPSETS} = \@sets; + require_capability 'IPSET_V5', 'A saved ipset list', 's'; + $config{SAVE_IPSETS} = ''; + } + default_yes_no 'SAVE_ARPTABLES' , ''; default_yes_no 'STARTUP_ENABLED' , 'Yes'; default_yes_no 'DELAYBLACKLISTLOAD' , ''; diff --git a/Shorewall/Perl/prog.footer b/Shorewall/Perl/prog.footer index b27938cc5..0c44dd420 100644 --- a/Shorewall/Perl/prog.footer +++ b/Shorewall/Perl/prog.footer @@ -20,6 +20,7 @@ usage() { echo " run [ ... ]" echo " status" echo " up " + echo " savesets " echo " version" echo echo "Options are:" @@ -383,6 +384,13 @@ case "$COMMAND" in error_message "ERROR: Missing command" fi ;; + savesets) + if [ $# -eq 2 ]; then + save_ipsets $2 + else + usage 2 + fi + ;; version) [ $# -ne 1 ] && usage 2 echo $SHOREWALL_VERSION diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml index 07df996ee..cbcc91b82 100644 --- a/Shorewall/manpages/shorewall.conf.xml +++ b/Shorewall/manpages/shorewall.conf.xml @@ -2469,7 +2469,8 @@ INLINE - - - ; -j REJECT SAVE_IPSETS={Yes|No} + role="bold">Yes|No|setlist} Re-enabled in Shorewall 4.4.6. If SAVE_IPSETS=Yes, then the @@ -2478,6 +2479,10 @@ INLINE - - - ; -j REJECT role="bold">shorewall save commands and restored by the shorewall start and shorewall restore commands. + + Beginning with Shorewall 4.6.4, you can restrict the set of + ipsets saved by specifying a setlist (a comma-separated list of ipv4 + ipset names). diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml index c9dd8c199..be535f1e4 100644 --- a/Shorewall6/manpages/shorewall6.conf.xml +++ b/Shorewall6/manpages/shorewall6.conf.xml @@ -2122,6 +2122,25 @@ INLINE - - - ; -j REJECT + + SAVE_IPSETS={Yes|No|setlist} + + + Re-enabled in Shorewall 4.4.6. If SAVE_IPSETS=Yes, then the + current contents of your ipsets will be saved by the shorewall stop and shorewall save commands and restored by the + shorewall start and shorewall restore commands. + + Beginning with Shorewall 4.6.4, you can restrict the set of + ipsets saved by specifying a setlist (a comma-separated list of ipv6 + ipset names). + + + SHOREWALL_SHELL=[pathname]