diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 4c1bceca5..aa405edb9 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -836,7 +836,7 @@ sub add_common_rules ( $ ) { my $interfaceref = find_interface $interface; - unless ( $interfaceref->{options}{ignore} & NO_SFILTER || $interfaceref->{options}{rpfilter} ) { + unless ( $interfaceref->{options}{ignore} & NO_SFILTER || $interfaceref->{options}{rpfilter} || $interfaceref->{physical} eq 'lo' ) { my @filters = @{$interfaceref->{filter}}; @@ -1520,7 +1520,7 @@ sub add_interface_jumps { my @interfaces = grep $_ ne '%vserver%', @_; my $dummy; my $loref = known_interface('lo'); - my $lo_jump_added = $loref && $loref->{options}{local} && ! $loref->{options}{destonly}; + my $lo_jump_added = local_zone; # # Add Nat jumps # @@ -2169,13 +2169,15 @@ sub generate_matrix() { # # FORWARDING Jump for non-IPSEC host group # - add_forward_jump( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) if $frwd_ref && ( $hostref->{ipsec} ne 'ipsec' && ! $hostref->{options}{local} ); + add_forward_jump( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) if $frwd_ref && $hostref->{ipsec} ne 'ipsec' && $zoneref->{type} ne LOCAL; } } # Subnet Loop } # Hostref Loop } # Interface Loop } #Type Loop + next if $zoneref->{type} == LOCAL; + if ( $frwd_ref ) { # # F O R W A R D I N G @@ -2197,6 +2199,8 @@ sub generate_matrix() { next if $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy} eq 'NONE'; + next if $zone1ref->{type} == LOCAL; + my $chain = rules_target $zone, $zone1; next unless $chain; # CONTINUE policy with no rules @@ -2216,7 +2220,7 @@ sub generate_matrix() { for my $typeref ( values %{$zone1ref->{hosts}} ) { for my $interface ( sort { interface_number( $a ) <=> interface_number( $b ) } keys %$typeref ) { for my $hostref ( @{$typeref->{$interface}} ) { - next if $hostref->{options}{sourceonly} || $hostref->{options}{local}; + next if $hostref->{options}{sourceonly}; if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) { my @ipsec_out_match = match_ipsec_out $zone1 , $hostref; my $dest_exclusion = dest_exclusion( $hostref->{exclusions}, $chain); diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index e7095e681..f2f4ee435 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -2441,15 +2441,15 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) { } } # - # Handle 'local' zone warnings + # Handle 'local' warnings # unless ( $wildcard ) { if ( $sourceref ) { warning_message( "The SOURCE zone in this rule is 'destonly'" ) if $sourceref->{destonly}; if ( $destref ) { - warning_message( "The SOURCE zone is local and the DEST zone is off-firewall" ) if $sourceref->{local} && ! ( $destref->{type} & ( FIREWALL | VSERVER ) ); - warning_message( "The SOURCE zone is off-firewall and the DEST zone is 'local'" ) if $destref->{local} && ! ( $sourceref->{type} & ( FIREWALL | VSERVER ) ); + warning_message( "The SOURCE zone is local and the DEST zone is off-firewall" ) if $sourceref->{type} == LOCAL && ! ( $destref->{type} & ( FIREWALL | VSERVER ) ); + warning_message( "The SOURCE zone is off-firewall and the DEST zone is 'local'" ) if $destref->{type} == LOCAL && ! ( $sourceref->{type} & ( FIREWALL | VSERVER ) ); } } } diff --git a/Shorewall/Perl/Shorewall/Zones.pm b/Shorewall/Perl/Shorewall/Zones.pm index 2abf7d8d2..d13f83ed7 100644 --- a/Shorewall/Perl/Shorewall/Zones.pm +++ b/Shorewall/Perl/Shorewall/Zones.pm @@ -38,6 +38,7 @@ our @EXPORT = ( qw( NOTHING IPSECMODE FIREWALL VSERVER + LOCAL IP BPORT IPSEC @@ -50,6 +51,7 @@ our @EXPORT = ( qw( NOTHING dump_zone_contents find_zone firewall_zone + local_zone defined_zone zone_type zone_interfaces @@ -58,6 +60,7 @@ our @EXPORT = ( qw( NOTHING all_parent_zones complex_zones vserver_zones + local_zone on_firewall_zones off_firewall_zones non_firewall_zones @@ -152,6 +155,7 @@ our @zones; our %zones; our %zonetypes; our $firewall_zone; +our $local_zone; our %reservedName = ( all => 1, any => 1, @@ -211,7 +215,9 @@ use constant { FIREWALL => 1, IP => 2, BPORT => 4, IPSEC => 8, - VSERVER => 16 }; + VSERVER => 16, + LOCAL => 32 + }; use constant { SIMPLE_IF_OPTION => 1, BINARY_IF_OPTION => 2, @@ -278,6 +284,7 @@ sub initialize( $$ ) { @zones = (); %zones = (); $firewall_zone = ''; + $local_zone = ''; $have_ipsec = undef; @interfaces = (); @@ -303,7 +310,6 @@ sub initialize( $$ ) { dhcp => SIMPLE_IF_OPTION, ignore => NUMERIC_IF_OPTION + IF_OPTION_WILDOK, maclist => SIMPLE_IF_OPTION + IF_OPTION_HOST, - local => SIMPLE_IF_OPTION + IF_OPTION_HOST, logmartians => BINARY_IF_OPTION, nets => IPLIST_IF_OPTION + IF_OPTION_ZONEONLY + IF_OPTION_VSERVER, norfc1918 => OBSOLETE_IF_OPTION, @@ -334,7 +340,7 @@ sub initialize( $$ ) { sourceonly => 1, mss => 1, ); - %zonetypes = ( 1 => 'firewall', 2 => 'ipv4', 4 => 'bport4', 8 => 'ipsec4', 16 => 'vserver' ); + %zonetypes = ( 1 => 'firewall', 2 => 'ipv4', 4 => 'bport4', 8 => 'ipsec4', 16 => 'vserver', 32 => 'local' ); } else { %validinterfaceoptions = ( accept_ra => NUMERIC_IF_OPTION, blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST, @@ -342,7 +348,6 @@ sub initialize( $$ ) { destonly => SIMPLE_IF_OPTION + IF_OPTION_HOST, dhcp => SIMPLE_IF_OPTION, ignore => NUMERIC_IF_OPTION + IF_OPTION_WILDOK, - local => SIMPLE_IF_OPTION + IF_OPTION_HOST, maclist => SIMPLE_IF_OPTION + IF_OPTION_HOST, nets => IPLIST_IF_OPTION + IF_OPTION_ZONEONLY + IF_OPTION_VSERVER, nosmurfs => SIMPLE_IF_OPTION + IF_OPTION_HOST, @@ -384,6 +389,8 @@ sub parse_zone_option_list($$\$$) my $fmt; if ( $list ne '-' ) { + fatal_error "The 'local' zone may not have $column OPTIONS" if $zonetype == LOCAL; + for my $e ( split_list $list, 'option' ) { my $val = undef; my $invert = ''; @@ -491,6 +498,11 @@ sub process_zone( \$ ) { } elsif ( $type eq '-' ) { $type = IP; $$ip = 1; + } elsif ( $type eq 'local' ) { + fatal_error 'The local zone may not be nested' if @parents; + fatal_error "Only one local zone may be defined ($zone)" if $local_zone; + $local_zone = $zone; + $type = LOCAL; } else { fatal_error "Invalid zone type ($type)"; } @@ -568,6 +580,8 @@ sub process_zone( \$ ) { # # Parse the zones file. # +sub vserver_zones(); + sub determine_zones() { my @z; @@ -586,6 +600,7 @@ sub determine_zones() fatal_error "No firewall zone defined" unless $firewall_zone; fatal_error "No IP zones defined" unless $ip; + fatal_error "The local zone and vserver zones are mutually exclusive" if $local_zone && vserver_zones; # # Topological sort to place sub-zones before all of their parents # @@ -750,7 +765,6 @@ sub add_group_to_zone($$$$$) $interfaceref = $interfaces{$interface}; $zoneref->{interfaces}{$interface} = 1; $zoneref->{destonly} ||= $interfaceref->{options}{destonly}; - $zoneref->{local} ||= $interfaceref->{options}{local}; $interfaceref->{zones}{$zone} = 1; @@ -892,6 +906,10 @@ sub firewall_zone() { $firewall_zone; } +sub local_zone() { + $local_zone; +} + # # Determine if the passed physical device is a bridge # @@ -1287,6 +1305,37 @@ sub process_interface( $$ ) { }; if ( $zone ) { + if ( $physical eq 'lo' ) { + fatal_error "Only a local zone may be assigned to 'lo'" unless $zoneref->{type} == LOCAL; + fatal_error "The local zone may not have nets specified" if $netsref; + fatal_error "Invalid definition of 'lo'" if $bridge ne $interface; + + for ( qw/arp_filter + arp_ignore + blacklist + bridge + detectnets + dhcp + maclist + logmartians + norfc1918 + nosmurts + proxyarp + routeback + routefilter + rpfilter + sfilter + sourceroute + upnp + upnpclient + mss + / ) { + fatal_error "The 'lo' interface may not specify the '$_' option" if supplied $options{$_}; + } + } else { + fatal_error "The local zone may only be assigned to 'lo'" if $zoneref->{type} == LOCAL; + } + $netsref ||= [ allip ]; add_group_to_zone( $zone, $zoneref->{type}, $interface, $netsref, $hostoptionsref ); add_group_to_zone( $zone, diff --git a/Shorewall/manpages/shorewall-interfaces.xml b/Shorewall/manpages/shorewall-interfaces.xml index 40e58d6f1..a50850ae2 100644 --- a/Shorewall/manpages/shorewall-interfaces.xml +++ b/Shorewall/manpages/shorewall-interfaces.xml @@ -150,6 +150,11 @@ loc eth2 - wait + + Beginning with Shorewall 4.5.17, if you specify a zone for the + 'lo' interface, then that zone must be defined as type + in shorewall6-zones(5). @@ -205,7 +210,7 @@ loc eth2 - changed; the value assigned to the setting will be the value specified (if any) or 1 if no value is given. - + This option does not work with a wild-card @@ -239,7 +244,7 @@ loc eth2 - 8 - do not reply for all local addresses - + This option does not work with a wild-card @@ -247,7 +252,7 @@ loc eth2 - the INTERFACE column. - + Do not specify - - local - - - Added in Shorewall 4.5.17. Causes the compiler to omit - rules from this interface to other interfaces and from other - interfaces to this interface. - - - logmartians[={0|1}] @@ -416,7 +411,7 @@ loc eth2 - 1 teastep@lists:~$ - + This option does not work with a wild-card diff --git a/Shorewall/manpages/shorewall-zones.xml b/Shorewall/manpages/shorewall-zones.xml index d9056ca7b..63942f9de 100644 --- a/Shorewall/manpages/shorewall-zones.xml +++ b/Shorewall/manpages/shorewall-zones.xml @@ -135,8 +135,8 @@ c:a,b ipv4 This is the standard Shorewall zone type and is the default if you leave this column empty or if you enter "-" in the column. Communication with some zone hosts may be - encrypted. Encrypted hosts are designated using the - 'ipsec' option in shorewall-hosts(5). @@ -187,6 +187,71 @@ c:a,b ipv4 firewall zone. + + + local + + + Added in Shorewall 4.5.17. + + Normally, Shorewall treats the loopback interface (lo) + in the following way: + + + + By default, all traffic through the interface is + ACCEPTed. + + + + If a $FW -> $FW policy is defined or $FW -> + $FW rules are defined, they are placed in a chain named + ${FW}2${F2} or ${FW}-${FW} (e.g., 'fw2fw' or 'fw-fw' ) + depending on the ZONE2ZONE setting in shorewall.conf(5). + + + + $FW -> $FW traffic is only filtered in the OUTPUT + chain. + + + + By defining a local + zone and associating it with the loopback interface in + shorewall-interfaces(5), you can effect a slightly different + model. Suppose that the local + zone name is 'local'; then: + + + + Both $FW -> local and local -> $FW chains are + created. + + + + The $FW -> local and local -> $FW policies may + be different. + + + + Both $FW -> local and local -> $FW rules may + be specified. + + + + Rules to/from the local + zone and any zone other than the firewall zone are ignored + with a warning. + + Only one local zone may + be defined. + + When a local zone is defined, you should ensure that the + $FW -> $FW policy is ACCEPT; otherwise, extraneous chains + and rules will be created. + + diff --git a/Shorewall6/manpages/shorewall6-interfaces.xml b/Shorewall6/manpages/shorewall6-interfaces.xml index a8cd61636..af8f1460e 100644 --- a/Shorewall6/manpages/shorewall6-interfaces.xml +++ b/Shorewall6/manpages/shorewall6-interfaces.xml @@ -84,6 +84,11 @@ loc eth1 - loc eth2 - + + Beginning with Shorewall 4.5.17, if you specify a zone for the + 'lo' interface, then that zone must be defined as type + in shorewall6-zones(5). @@ -315,16 +320,6 @@ loc eth2 - - - local - - - Added in Shorewall 4.5.17. Causes the compiler to omit - rules from this interface to other interfaces and from other - interfaces to this interface. - - - mss=number diff --git a/Shorewall6/manpages/shorewall6-zones.xml b/Shorewall6/manpages/shorewall6-zones.xml index ab40949cc..3640538c1 100644 --- a/Shorewall6/manpages/shorewall6-zones.xml +++ b/Shorewall6/manpages/shorewall6-zones.xml @@ -133,8 +133,8 @@ c:a,b ipv6 This is the standard Shorewall6 zone type and is the default if you leave this column empty or if you enter "-" in the column. Communication with some zone hosts may be - encrypted. Encrypted hosts are designated using the - 'ipsec' option in shorewall6-hosts(5). @@ -185,6 +185,71 @@ c:a,b ipv6 firewall zone. + + + local + + + Added in Shorewall 4.5.17. + + Normally, Shorewall treats the loopback interface (lo) + in the following way: + + + + By default, all traffic through the interface is + ACCEPTed. + + + + If a $FW -> $FW policy is defined or $FW -> + $FW rules are defined, they are placed in a chain named + ${FW}2${F2} or ${FW}-${FW} (e.g., 'fw2fw' or 'fw-fw' ) + depending on the ZONE2ZONE setting in shorewall6.conf(5). + + + + $FW -> $FW traffic is only filtered in the OUTPUT + chain. + + + + By defining a local + zone and associating it with the loopback interface in + shorewall-interfaces(5), you can effect a slightly different + model. Suppose that the local + zone name is 'local'; then: + + + + Both $FW -> local and local -> $FW chains are + created. + + + + The $FW -> local and local -> $FW policies may + be different. + + + + Both $FW -> local and local -> $FW rules may + be specified. + + + + Rules to/from the local + zone and any zone other than the firewall zone are ignored + with a warning. + + Only one local zone may + be defined. + + When a local zone is defined, you should ensure that the + $FW -> $FW policy is ACCEPT; otherwise, extraneous chains + and rules will be created. + +