diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index cd8d124fa..1c1711670 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -186,6 +186,8 @@ our %EXPORT_TAGS = ( use_forward_chain input_chain input_option_chain + nodbl_src_chain + nodbl_dst_chain zone_input_chain use_interface_chain output_chain @@ -2438,6 +2440,22 @@ sub output_option_chain($) { ( $config{USE_PHYSICAL_NAMES} ? chain_base( get_physical( $interface ) ) : get_logical( $interface ) ) . '_oop'; } +# +# Blacklist Source Exclusion Chain for an interface +# +sub nodbl_src_chain($$) { + my ( $interface, $end ) = ( $_[0], $_[1] ); + ( $config{USE_PHYSICAL_NAMES} ? chain_base( get_physical( $interface ) ) : get_logical( $interface ) ) . '_' . $end; +} + +# +# Blacklist Destination Exclusion Chain for an interface +# +sub nodbl_dst_chain($$) { + my ($interface, $end) = ( $_[0], $_[1] ); + ( $config{USE_PHYSICAL_NAMES} ? chain_base( get_physical( $interface ) ) : get_logical( $interface ) ) . '_' . $end; +} + # # Forward Option Chain for an interface # diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 87e02e6ba..3424d1ed6 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -951,25 +951,61 @@ sub add_common_rules ( $ ) { } } + my @nodbl = @{$interfaceref->{nodbl}}; + if ( $dbl_ipset && ( ( my $setting = get_interface_option( $interface, 'dbl' ) ) ne '0:0' ) ) { my ( $in, $out ) = split /:/, $setting; + my ( $src_target, $dst_target ) = ( $dbl_src_target, $dbl_dst_target ); + my ( @src_exclude, @dst_exclude ); + + if ( @nodbl ) { + + if ( @nodbl > 1 ) { + # + # We need to create an intermediate chain + # + $chainref = new_standard_chain( $src_target = nodbl_src_chain( $interface , $dbl_src_target )); + + for (@nodbl) { + add_ijump( $chainref, j => 'RETURN', s => $_ ); + } + + add_ijump( $chainref, j => $dbl_src_target ); + + if ( $dbl_src_target ne $dbl_dst_target ) { + $chainref = new_standard_chain( $dst_target = nodbl_dst_chain( $interface , $dbl_dst_target )); + + for ( @nodbl ){ + add_ijump( $chainref, j => 'RETURN', -d => $_ ); + } + + add_ijump( $chainref, j => $dbl_dst_target ); + } + } else { + # + # Easy case + # + @src_exclude = ( s => "! $nodbl[0]" ); + @dst_exclude = ( d => "! $nodbl[0]" ); + } + } if ( $in == 1 ) { # # src # - add_ijump_extended( $filter_table->{input_option_chain($interface)}, j => $dbl_src_target, $origin{DYNAMIC_BLACKLIST}, @state, set => "--match-set $dbl_ipset src" ); - add_ijump_extended( $filter_table->{forward_option_chain($interface)}, j => $dbl_src_target, $origin{DYNAMIC_BLACKLIST}, @state, set => "--match-set $dbl_ipset src" ); + add_ijump_extended( $filter_table->{input_option_chain($interface)}, j => $src_target, $origin{DYNAMIC_BLACKLIST}, @src_exclude, @state, set => "--match-set $dbl_ipset src" ); + add_ijump_extended( $filter_table->{forward_option_chain($interface)}, j => $src_target, $origin{DYNAMIC_BLACKLIST}, @dst_exclude, @state, set => "--match-set $dbl_ipset src" ); } elsif ( $in == 2 ) { - add_ijump_extended( $filter_table->{forward_option_chain($interface)}, j => $dbl_dst_target, $origin{DYNAMIC_BLACKLIST}, @state, set => "--match-set $dbl_ipset dst" ); + add_ijump_extended( $filter_table->{forward_option_chain($interface)}, j => $dst_target, $origin{DYNAMIC_BLACKLIST}, @dst_exclude, @state, set => "--match-set $dbl_ipset dst" ); } if ( $out == 2 ) { # # dst # - add_ijump_extended( $filter_table->{output_option_chain($interface)}, j => $dbl_dst_target, $origin{DYNAMIC_BLACKLIST}, @state, set => "--match-set $dbl_ipset dst" ); + add_ijump_extended( $filter_table->{output_option_chain($interface)}, j => $dbl_dst_target, $origin{DYNAMIC_BLACKLIST}, @dst_exclude, @state, set => "--match-set $dbl_ipset dst" ); } } diff --git a/Shorewall/Perl/Shorewall/Zones.pm b/Shorewall/Perl/Shorewall/Zones.pm index 3be33ecf7..5558ff8b7 100644 --- a/Shorewall/Perl/Shorewall/Zones.pm +++ b/Shorewall/Perl/Shorewall/Zones.pm @@ -410,6 +410,7 @@ sub initialize( $$ ) { destonly => 1, sourceonly => 1, mss => 1, + nodbl => 1 ); %zonetypes = ( 1 => 'firewall', @@ -456,6 +457,7 @@ sub initialize( $$ ) { routeback => 1, tcpflags => 1, mss => 1, + nodbl => 1 ); %zonetypes = ( 1 => 'firewall', @@ -1541,6 +1543,7 @@ sub process_interface( $$ ) { origin => shortlineinfo( '' ), wildcard => $wildcard, physwild => $physwild, + nodbl => [], }; $interfaces{$physical} = $interfaceref if $physical ne $interface; @@ -2229,6 +2232,11 @@ sub process_host( ) { require_capability 'TCPMSS_TARGET', $option, 's'; $options{mss} = $1; $zoneref->{options}{complex} = 1; + } elsif ( $option eq 'nodbl' ) { + fatal_error "The 'nodbl' option is only allowed when using ipset-based dynamic blacklisting" unless $config{DYNAMIC_BLACKLIST} =~ /^ipset/; + fatal_error "The 'nodbl' option is only allowed in 'ip' zones" unless $type & IP; + push @{$interfaceref->{nodbl}}, $hosts; + $options{nodbl} = 1; } elsif ( $validhostoptions{$option}) { fatal_error qq(The "$option" option is not allowed with Vserver zones) if $type & VSERVER && ! ( $validhostoptions{$option} & IF_OPTION_VSERVER ); $options{$option} = 1; diff --git a/Shorewall/manpages/shorewall-hosts.xml b/Shorewall/manpages/shorewall-hosts.xml index 6f3d8e807..7c9c14177 100644 --- a/Shorewall/manpages/shorewall-hosts.xml +++ b/Shorewall/manpages/shorewall-hosts.xml @@ -31,8 +31,8 @@ The order of entries in this file is not significant in determining zone composition. Rather, the order that the zones are declared in shorewall-zones(5) determines - the order in which the records in this file are interpreted. + url="shorewall-zones.html">shorewall-zones(5) determines the order + in which the records in this file are interpreted. The only time that you need this file is when you have more than @@ -41,9 +41,9 @@ If you have an entry for a zone and interface in shorewall-interfaces(5) - then do not include any entries in this file for that same (zone, - interface) pair. + url="shorewall-interfaces.html">shorewall-interfaces(5) then do + not include any entries in this file for that same (zone, interface) + pair. The columns in the file are as follows. @@ -55,8 +55,8 @@ The name of a zone declared in shorewall-zones(5). You - may not list the firewall zone in this column. + url="shorewall-zones.html">shorewall-zones(5). You may not + list the firewall zone in this column. @@ -69,9 +69,9 @@ The name of an interface defined in the shorewall-interfaces(5) - file followed by a colon (":") and a comma-separated list whose - elements are either: + url="shorewall-interfaces.html">shorewall-interfaces(5) file + followed by a colon (":") and a comma-separated list whose elements + are either: @@ -171,8 +171,8 @@ The zone is accessed via a kernel 2.6 ipsec SA. Note that if the zone named in the ZONE column is specified as an IPSEC zone in the shorewall-zones(5) - file then you do NOT need to specify the 'ipsec' option + url="shorewall-zones.html">shorewall-zones(5) file + then you do NOT need to specify the 'ipsec' option here. @@ -183,8 +183,8 @@ Connection requests from these hosts are compared against the contents of shorewall-maclist(5). - If this option is specified, the interface must be an Ethernet + url="shorewall-maclist.html">shorewall-maclist(5). If + this option is specified, the interface must be an Ethernet NIC or equivalent and must be up before Shorewall is started. @@ -214,8 +214,8 @@ Smurfs will be optionally logged based on the setting of SMURF_LOG_LEVEL in shorewall.conf(5). - After logging, the packets are dropped. + url="shorewall.conf.html">shorewall.conf(5). After + logging, the packets are dropped. @@ -243,6 +243,23 @@ according to the setting of TCP_FLAGS_LOG_LEVEL. + + + nodbl + + + This option was added in Shorewall 5.2.9. It causes + addresses in the HOSTS column to be exempted from ipset-based + dynamic blacklisting + (DYNAMIC_BLACKLIST={|)... + in Shorewall.conf(5)). It may + only be specified if the zone-name + listed in the ZONE column is defined as an + zone in shorewall-zones(5). + +