From 8d731c81e460799590b39bc55409894fbd3c8d8c Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Tue, 4 Oct 2016 09:09:45 -0700 Subject: [PATCH] Add 'disconnect' option to ipset-based dynamic blacklisting Signed-off-by: Tom Eastep --- Shorewall-core/lib.cli | 110 +++++++++++++++++------- Shorewall/Perl/Shorewall/Config.pm | 10 ++- Shorewall/lib.cli-std | 30 +------ Shorewall/manpages/shorewall.conf.xml | 13 ++- Shorewall6/manpages/shorewall6.conf.xml | 11 ++- 5 files changed, 111 insertions(+), 63 deletions(-) diff --git a/Shorewall-core/lib.cli b/Shorewall-core/lib.cli index 503e90fa8..9ef63c511 100644 --- a/Shorewall-core/lib.cli +++ b/Shorewall-core/lib.cli @@ -3555,10 +3555,34 @@ blacklist_command() { ;; esac - $IPSET -A $g_blacklistipset $@ && progress_message2 "$1 Blacklisted" || { error_message "ERROR: Address $1 not blacklisted"; return 1; } + 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 @@ -3761,6 +3785,59 @@ verify_firewall_script() { 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 + [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 @@ -3920,35 +3997,7 @@ get_config() { fi if [ -n "$DYNAMIC_BLACKLIST" ]; then - case $DYNAMIC_BLACKLIST in - [Nn]o) - DYNAMIC_BLACKLIST=''; - ;; - [Yy]es) - ;; - ipset|ipset::*|ipset-only|ipset-only::*|ipset,src-dst|ipset-only,src-dst::*) - g_blacklistipset=SW_DBL$g_family - ;; - ipset:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset,src-dst:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset,src-dst:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset-only:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset-only,src-dst:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only,src-dst:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - *) - fatal_error "Invalid value ($DYNAMIC_BLACKLIST) for DYNAMIC_BLACKLIST" - ;; - esac + setup_dbl fi lib=$(find_file lib.cli-user) @@ -4294,6 +4343,7 @@ shorewall_cli() { g_compiled= g_pager= g_blacklistipset= + g_disconnect= VERBOSE= VERBOSITY=1 diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index bc0fb6c47..be18afb46 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -6253,9 +6253,17 @@ sub get_configuration( $$$$ ) { if ( supplied( $val = $config{DYNAMIC_BLACKLIST} ) ) { if ( $val =~ /^ipset/ ) { + my %valid_options = ( 'src-dst' => 1, 'disconnect' => 1 ); + my ( $key, $set, $level, $tag, $rest ) = split( ':', $val , 5 ); - fatal_error "Invalid DYNAMIC_BLACKLIST setting ( $val )" if $key !~ /^ipset(?:-only)?(?:,src-dst)?$/ || defined $rest; + ( $key, my @options ) = split_list( $key, 'option' ); + + for ( @options ) { + fatal_error "Invalid ipset option ($_)" unless $valid_options{$_}; + } + + fatal_error "Invalid DYNAMIC_BLACKLIST setting ( $val )" if $key !~ /^ipset(?:-only)?$/ || defined $rest; if ( supplied( $set ) ) { fatal_error "Invalid DYNAMIC_BLACKLIST ipset name" unless $set =~ /^[A-Za-z][\w-]*/; diff --git a/Shorewall/lib.cli-std b/Shorewall/lib.cli-std index 8cc91b555..bf82c0ea1 100644 --- a/Shorewall/lib.cli-std +++ b/Shorewall/lib.cli-std @@ -336,35 +336,7 @@ get_config() { fi if [ -n "$DYNAMIC_BLACKLIST" ]; then - case $DYNAMIC_BLACKLIST in - [Nn]o) - DYNAMIC_BLACKLIST=''; - ;; - [Yy]es) - ;; - ipset|ipset::*|ipset-only|ipset-only::*|ipset,src-dst|ipset-only,src-dst::*) - g_blacklistipset=SW_DBL$g_family - ;; - ipset:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset,src-dst:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset,src-dst:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset-only:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - ipset-only,src-dst:[a-zA-Z]*) - g_blacklistipset=${DYNAMIC_BLACKLIST#ipset-only,src-dst:} - g_blacklistipset=${g_blacklistipset%%:*} - ;; - *) - fatal_error "Invalid value ($DYNAMIC_BLACKLIST) for DYNAMIC_BLACKLIST" - ;; - esac + setup_dbl fi lib=$(find_file lib.cli-user) diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml index 4ab09ebfd..c964c0c0a 100644 --- a/Shorewall/manpages/shorewall.conf.xml +++ b/Shorewall/manpages/shorewall.conf.xml @@ -485,7 +485,7 @@ ALL sends all packets through the blacklist chains. Note: The ESTABLISHED state may not be specified if - FASTACCEPT=Yes is specified. + FASTACCEPT=Yes is specified. @@ -769,7 +769,8 @@ role="bold">No||ipset[-only][,src-dst][:[setname][:log_level|:log_tag]]]} + role="bold">src-dst][,disconnect][:[setname][:log_level|:log_tag]]]} Added in Shorewall 4.4.7. When set to src-dst is included, then packets whose destination address matches an entry in the ipset are also dropped. + The option was added in Shorewall + 5.0.13 and requires that the conntrack utility be installed on the + firewall system. When an address is blacklisted using the + blacklist command, all connections originating + from that address are disconnected. if the + option was also specified, then all connections to that address are + also disconnected. + When ipset-based dynamic blacklisting is enabled, the contents of the blacklist will be preserved over stop/reboot/start diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml index 74f5939a2..9a727fd45 100644 --- a/Shorewall6/manpages/shorewall6.conf.xml +++ b/Shorewall6/manpages/shorewall6.conf.xml @@ -630,7 +630,8 @@ role="bold">No||ipset[-only][,src-dst][:[setname][:log_level|:log_tag]]]} + role="bold">src-dst][,disconnect][:[setname][:log_level|:log_tag]]]} Added in Shorewall 4.4.7. When set to src-dst is included, then packets whose destination address matches an entry in the ipset are also dropped. + The option was added in Shorewall + 5.0.13 and requires that the conntrack utility be installed on the + firewall system. When an address is blacklisted using the + blacklist command, all connections originating + from that address are disconnected. if the + option was also specified, then all connections to that address are + also disconnected. + When ipset-based dynamic blacklisting is enabled, the contents of the blacklist will be preserved over stop/reboot/start