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.
+
+