Change 'local' to 'loopback' and add 'local' zones that match non-loopback interfaces.

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2013-05-26 14:06:51 -07:00
parent f89c704d01
commit 2de0fbf7d0
5 changed files with 113 additions and 52 deletions

View File

@ -1423,11 +1423,11 @@ sub generate_source_rules( $$$;@ ) {
# Loopback traffic -- this is where we assemble the intra-firewall chains # Loopback traffic -- this is where we assemble the intra-firewall chains
# #
sub handle_loopback_traffic() { sub handle_loopback_traffic() {
my @zones = ( vserver_zones, firewall_zone ); my @zones = ( vserver_zones, firewall_zone );
my $natout = $nat_table->{OUTPUT}; my $natout = $nat_table->{OUTPUT};
my $rawout = $raw_table->{OUTPUT}; my $rawout = $raw_table->{OUTPUT};
my $rulenum = 0; my $rulenum = 0;
my $local = local_zone; my $loopback = loopback_zones;
my $outchainref; my $outchainref;
my @rule; my @rule;
@ -1456,7 +1456,7 @@ sub handle_loopback_traffic() {
# #
if ( $type1 == FIREWALL ) { if ( $type1 == FIREWALL ) {
for my $z2 ( @zones ) { for my $z2 ( @zones ) {
next if $local && $z1 eq $z2; next if $loopback && $z1 eq $z2;
my $chain = rules_target( $z1, $z2 ); my $chain = rules_target( $z1, $z2 );
@ -1522,7 +1522,7 @@ sub add_interface_jumps {
our %forward_jump_added; our %forward_jump_added;
my @interfaces = grep $_ ne '%vserver%', @_; my @interfaces = grep $_ ne '%vserver%', @_;
my $dummy; my $dummy;
my $lo_jump_added = local_zone && ! get_interface_option( 'lo', 'destonly' ); my $lo_jump_added = interface_zone( 'lo' ) && ! get_interface_option( 'lo', 'destonly' );
# #
# Add Nat jumps # Add Nat jumps
# #
@ -2121,6 +2121,7 @@ sub generate_matrix() {
my $nested = @{$zoneref->{parents}}; my $nested = @{$zoneref->{parents}};
my $parenthasnat = 0; my $parenthasnat = 0;
my $parenthasnotrack = 0; my $parenthasnotrack = 0;
my $type = $zoneref->{type};
# #
# Create the zone's dnat chain # Create the zone's dnat chain
# #
@ -2171,14 +2172,14 @@ sub generate_matrix() {
# #
# FORWARDING Jump for non-IPSEC host group # 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' && $zoneref->{type} ne LOCAL; add_forward_jump( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) if $frwd_ref && $hostref->{ipsec} ne 'ipsec' && $type ne LOOPBACK;
} }
} # Subnet Loop } # Subnet Loop
} # Hostref Loop } # Hostref Loop
} # Interface Loop } # Interface Loop
} #Type Loop } #Type Loop
next if $zoneref->{type} == LOCAL; next if $type == LOOPBACK;
if ( $frwd_ref ) { if ( $frwd_ref ) {
# #
@ -2198,10 +2199,14 @@ sub generate_matrix() {
# #
for my $zone1 ( @dest_zones ) { for my $zone1 ( @dest_zones ) {
my $zone1ref = find_zone( $zone1 ); my $zone1ref = find_zone( $zone1 );
my $type1 = $zone1ref->{type};
next if $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy} eq 'NONE'; next if $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy} eq 'NONE';
next if $zone1ref->{type} == LOCAL; next if $type1 == LOOPBACK;
next if $type == LOCAL && $type1 != LOCAL;
next if $type1 == LOCAL && $type != LOCAL;
my $chain = rules_target $zone, $zone1; my $chain = rules_target $zone, $zone1;
@ -2213,7 +2218,7 @@ sub generate_matrix() {
next if ( $num_ifaces = scalar( keys ( %{$zoneref->{interfaces}} ) ) ) < 2 && ! $zoneref->{options}{in_out}{routeback}; next if ( $num_ifaces = scalar( keys ( %{$zoneref->{interfaces}} ) ) ) < 2 && ! $zoneref->{options}{in_out}{routeback};
} }
if ( $zone1ref->{type} & BPORT ) { if ( $type1 & BPORT ) {
next unless $zoneref->{bridge} eq $zone1ref->{bridge}; next unless $zoneref->{bridge} eq $zone1ref->{bridge};
} }

View File

@ -2378,7 +2378,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
# #
$sourceref = find_zone( $chainref->{sourcezone} ) if $chainref->{sourcezone}; $sourceref = find_zone( $chainref->{sourcezone} ) if $chainref->{sourcezone};
# #
# And we need the dest zone for local/off-firewall/destonly checks # And we need the dest zone for local/loopback/off-firewall/destonly checks
# #
$destref = find_zone( $chainref->{destzone} ) if $chainref->{destzone}; $destref = find_zone( $chainref->{destzone} ) if $chainref->{destzone};
} else { } else {
@ -2441,16 +2441,18 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
} }
} }
# #
# Handle 'local' warnings # Handle 'local/loopback' warnings
# #
unless ( $wildcard ) { unless ( $wildcard ) {
if ( $sourceref ) { if ( $sourceref ) {
warning_message( "The SOURCE zone in this rule is 'destonly'" ) if $sourceref->{destonly}; warning_message( "The SOURCE zone in this rule is 'destonly'" ) if $sourceref->{destonly};
if ( $destref ) { if ( $destref ) {
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 loopback and the DEST zone is off-firewall" ) if $sourceref->{type} == LOOPBACK && ! ( $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 ) ); warning_message( "The SOURCE zone is off-firewall and the DEST zone is 'loopback'" ) if $destref->{type} == LOOPBACK && ! ( $sourceref->{type} & ( FIREWALL | VSERVER ) );
warning_message( "\$FW to \$FW rules are ignored when there is a defined 'local' zone" ) if local_zone && $sourceref->{type} == FIREWALL && $destref->{type} == FIREWALL; warning_message( "The SOURCE zone is 'local' and the DEST zone is off-firewall" ) if $sourceref->{type} == LOCAL && ! ( $destref->{type} & ( FIREWALL | VSERVER | LOCAL) );
warning_message( "The SOURCE zone is off-firewall and the DEST zone is 'loopback'" ) if $destref->{type} == LOCAL && ! ( $sourceref->{type} & ( FIREWALL | VSERVER | LOCAL) );
warning_message( "\$FW to \$FW rules are ignored when there is a defined 'loopback' zone" ) if loopback_zones && $sourceref->{type} == FIREWALL && $destref->{type} == FIREWALL;
} }
} }
} }

View File

@ -38,6 +38,7 @@ our @EXPORT = ( qw( NOTHING
IPSECMODE IPSECMODE
FIREWALL FIREWALL
VSERVER VSERVER
LOOPBACK
LOCAL LOCAL
IP IP
BPORT BPORT
@ -51,7 +52,8 @@ our @EXPORT = ( qw( NOTHING
dump_zone_contents dump_zone_contents
find_zone find_zone
firewall_zone firewall_zone
local_zone loopback_zones
local_zones
defined_zone defined_zone
zone_type zone_type
zone_interfaces zone_interfaces
@ -60,7 +62,6 @@ our @EXPORT = ( qw( NOTHING
all_parent_zones all_parent_zones
complex_zones complex_zones
vserver_zones vserver_zones
local_zone
on_firewall_zones on_firewall_zones
off_firewall_zones off_firewall_zones
non_firewall_zones non_firewall_zones
@ -87,6 +88,7 @@ our @EXPORT = ( qw( NOTHING
interface_has_option interface_has_option
set_interface_option set_interface_option
set_interface_provider set_interface_provider
interface_zone
interface_zones interface_zones
verify_required_interfaces verify_required_interfaces
validate_hosts_file validate_hosts_file
@ -155,7 +157,8 @@ our @zones;
our %zones; our %zones;
our %zonetypes; our %zonetypes;
our $firewall_zone; our $firewall_zone;
our $local_zone; our @loopback_zones;
our @local_zones;
our %reservedName = ( all => 1, our %reservedName = ( all => 1,
any => 1, any => 1,
@ -216,7 +219,8 @@ use constant { FIREWALL => 1,
BPORT => 4, BPORT => 4,
IPSEC => 8, IPSEC => 8,
VSERVER => 16, VSERVER => 16,
LOCAL => 32 LOOPBACK => 32,
LOCAL => 64,
}; };
use constant { SIMPLE_IF_OPTION => 1, use constant { SIMPLE_IF_OPTION => 1,
@ -283,8 +287,9 @@ sub initialize( $$ ) {
( $family , $upgrade ) = @_; ( $family , $upgrade ) = @_;
@zones = (); @zones = ();
%zones = (); %zones = ();
@loopback_zones = ();
@local_zones = ();
$firewall_zone = ''; $firewall_zone = '';
$local_zone = '';
$have_ipsec = undef; $have_ipsec = undef;
@interfaces = (); @interfaces = ();
@ -340,7 +345,7 @@ sub initialize( $$ ) {
sourceonly => 1, sourceonly => 1,
mss => 1, mss => 1,
); );
%zonetypes = ( 1 => 'firewall', 2 => 'ipv4', 4 => 'bport4', 8 => 'ipsec4', 16 => 'vserver', 32 => 'local' ); %zonetypes = ( 1 => 'firewall', 2 => 'ipv4', 4 => 'bport4', 8 => 'ipsec4', 16 => 'vserver', 32 => 'loopback', 64 => 'local' );
} else { } else {
%validinterfaceoptions = ( accept_ra => NUMERIC_IF_OPTION, %validinterfaceoptions = ( accept_ra => NUMERIC_IF_OPTION,
blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST, blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST,
@ -371,7 +376,7 @@ sub initialize( $$ ) {
tcpflags => 1, tcpflags => 1,
mss => 1, mss => 1,
); );
%zonetypes = ( 1 => 'firewall', 2 => 'ipv6', 4 => 'bport6', 8 => 'ipsec4', 16 => 'vserver' ); %zonetypes = ( 1 => 'firewall', 2 => 'ipv6', 4 => 'bport6', 8 => 'ipsec4', 16 => 'vserver', 32 => 'loopback', 64 => 'local' );
} }
} }
@ -389,7 +394,7 @@ sub parse_zone_option_list($$\$$)
my $fmt; my $fmt;
if ( $list ne '-' ) { if ( $list ne '-' ) {
fatal_error "The 'local' zone may not have $column OPTIONS" if $zonetype == LOCAL; fatal_error "The 'loopback' zone may not have $column OPTIONS" if $zonetype == LOOPBACK;
for my $e ( split_list $list, 'option' ) { for my $e ( split_list $list, 'option' ) {
my $val = undef; my $val = undef;
@ -499,10 +504,11 @@ sub process_zone( \$ ) {
$type = IP; $type = IP;
$$ip = 1; $$ip = 1;
} elsif ( $type eq 'local' ) { } elsif ( $type eq 'local' ) {
fatal_error 'The local zone may not be nested' if @parents; push @local_zones, $zone;
fatal_error "Only one local zone may be defined ($zone)" if $local_zone;
$local_zone = $zone;
$type = LOCAL; $type = LOCAL;
} elsif ( $type eq 'loopback' ) {
push @loopback_zones, $zone;
$type = LOOPBACK;
} else { } else {
fatal_error "Invalid zone type ($type)"; fatal_error "Invalid zone type ($type)";
} }
@ -515,6 +521,8 @@ sub process_zone( \$ ) {
fatal_error 'Subzones of a Vserver zone not allowed' if $ptype & VSERVER; fatal_error 'Subzones of a Vserver zone not allowed' if $ptype & VSERVER;
fatal_error 'Subzones of firewall zone not allowed' if $ptype & FIREWALL; fatal_error 'Subzones of firewall zone not allowed' if $ptype & FIREWALL;
fatal_error 'Loopback zones may only be subzones of other loopback zones' if ( $type | $ptype ) & LOOPBACK && $type != $ptype;
fatal_error 'Local zones may only be subzones of other local zones' if ( $type | $ptype ) & LOCAL && $type != $ptype;
set_super( $zones{$p} ) if $type & IPSEC && ! ( $ptype & IPSEC ); set_super( $zones{$p} ) if $type & IPSEC && ! ( $ptype & IPSEC );
@ -600,7 +608,7 @@ sub determine_zones()
fatal_error "No firewall zone defined" unless $firewall_zone; fatal_error "No firewall zone defined" unless $firewall_zone;
fatal_error "No IP zones defined" unless $ip; fatal_error "No IP zones defined" unless $ip;
fatal_error "The local zone and vserver zones are mutually exclusive" if $local_zone && vserver_zones; fatal_error "Loopback zones and vserver zones are mutually exclusive" if @loopback_zones && vserver_zones;
# #
# Topological sort to place sub-zones before all of their parents # Topological sort to place sub-zones before all of their parents
# #
@ -765,6 +773,7 @@ sub add_group_to_zone($$$$$)
$interfaceref = $interfaces{$interface}; $interfaceref = $interfaces{$interface};
$zoneref->{interfaces}{$interface} = 1; $zoneref->{interfaces}{$interface} = 1;
$zoneref->{destonly} ||= $interfaceref->{options}{destonly}; $zoneref->{destonly} ||= $interfaceref->{options}{destonly};
$options->{destonly} ||= $interfaceref->{options}{destonly};
$interfaceref->{zones}{$zone} = 1; $interfaceref->{zones}{$zone} = 1;
@ -906,8 +915,12 @@ sub firewall_zone() {
$firewall_zone; $firewall_zone;
} }
sub local_zone() { sub loopback_zones() {
$local_zone; @loopback_zones;
}
sub local_zones() {
@local_zones;
} }
# #
@ -1307,9 +1320,8 @@ sub process_interface( $$ ) {
if ( $zone ) { if ( $zone ) {
if ( $physical eq 'lo' ) { if ( $physical eq 'lo' ) {
fatal_error "Only a local zone may be assigned to 'lo'" unless $zoneref->{type} == LOCAL; fatal_error "Only a loopback zone may be assigned to 'lo'" unless $zoneref->{type} == LOOPBACK;
fatal_error "The local zone may not have nets specified" if $netsref; fatal_error "Invalid definition of 'lo'" if $bridge ne $interface;
fatal_error "Invalid definition of 'lo'" if $bridge ne $interface;
for ( qw/arp_filter for ( qw/arp_filter
arp_ignore arp_ignore
@ -1334,7 +1346,7 @@ sub process_interface( $$ ) {
fatal_error "The 'lo' interface may not specify the '$_' option" if supplied $options{$_}; fatal_error "The 'lo' interface may not specify the '$_' option" if supplied $options{$_};
} }
} else { } else {
fatal_error "The local zone may only be assigned to 'lo'" if $zoneref->{type} == LOCAL; fatal_error "A loopback zone may only be assigned to 'lo'" if $zoneref->{type} == LOOPBACK;
} }
$netsref ||= [ allip ]; $netsref ||= [ allip ];
@ -1558,6 +1570,15 @@ sub interface_zones( $ ) {
$interfaceref->{zones} || {}; $interfaceref->{zones} || {};
} }
#
# Returns the 'zone' member of the passed interface, if any
#
sub interface_zone( $ ) {
my $interfaceref = known_interface( $_[0] );
$interfaceref ? $interfaceref->{zone} : '';
}
# #
# Return the 'optional' setting of the passed interface # Return the 'optional' setting of the passed interface
# #
@ -1877,6 +1898,7 @@ sub process_host( ) {
$hosts = $2; $hosts = $2;
fatal_error "Unknown interface ($interface)" unless ($interfaceref = $interfaces{$interface}) && $interfaceref->{root}; fatal_error "Unknown interface ($interface)" unless ($interfaceref = $interfaces{$interface}) && $interfaceref->{root};
fatal_error "Loopback zones may only be associated with the loopback interface (lo)" if $type == LOOPBACK && $interfaceref->{name} ne 'lo';
} else { } else {
fatal_error "Invalid HOST(S) column contents: $hosts" fatal_error "Invalid HOST(S) column contents: $hosts"
} }

View File

@ -189,7 +189,7 @@ c:a,b ipv4</programlisting>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><emphasis role="bold">local</emphasis></term> <term><emphasis role="bold">loopback</emphasis></term>
<listitem> <listitem>
<para>Added in Shorewall 4.5.17.</para> <para>Added in Shorewall 4.5.17.</para>
@ -217,11 +217,12 @@ c:a,b ipv4</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>By defining a <emphasis role="bold">local</emphasis> <para>By defining a <emphasis role="bold">loopback</emphasis>
zone and associating it with the loopback interface in zone and associating it with the loopback interface in
shorewall-interfaces(5), you can effect a slightly different shorewall-interfaces(5), you can effect a slightly different
model. Suppose that the <emphasis role="bold">local</emphasis> model. Suppose that the <emphasis
zone name is 'local'; then:</para> role="bold">loopback</emphasis> zone name is 'local';
then:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -240,12 +241,27 @@ c:a,b ipv4</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>Rules to/from the <emphasis role="bold">local</emphasis> <para>Rules to/from the <emphasis
zone and any zone other than the firewall zone are ignored role="bold">loopback</emphasis> zone and any zone other than
with a warning.</para> the firewall zone are ignored with a warning.</para>
<para>Only one <emphasis role="bold">local</emphasis> zone may <para><emphasis role="bold">loopback</emphasis> zones may be
be defined.</para> nested within other <emphasis role="bold">loopback</emphasis>
zones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>local</term>
<listitem>
<para>Added in Shorewall 4.5.17. <emphasis
role="bold">local</emphasis> is the same as <emphasis
role="bold">ipv4</emphasis> with the exception that the zone
is only accessible from the <emphasis
role="bold">firewall</emphasis>, <emphasis
role="bold">vserver</emphasis> and other <emphasis
role="bold">local</emphasis> zones.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -187,7 +187,7 @@ c:a,b ipv6</programlisting>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><emphasis role="bold">local</emphasis></term> <term><emphasis role="bold">loopback</emphasis></term>
<listitem> <listitem>
<para>Added in Shorewall 4.5.17.</para> <para>Added in Shorewall 4.5.17.</para>
@ -215,11 +215,12 @@ c:a,b ipv6</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>By defining a <emphasis role="bold">local</emphasis> <para>By defining a <emphasis role="bold">loopback</emphasis>
zone and associating it with the loopback interface in zone and associating it with the loopback interface in
shorewall-interfaces(5), you can effect a slightly different shorewall-interfaces(5), you can effect a slightly different
model. Suppose that the <emphasis role="bold">local</emphasis> model. Suppose that the <emphasis
zone name is 'local'; then:</para> role="bold">loopback</emphasis> zone name is 'local';
then:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -238,12 +239,27 @@ c:a,b ipv6</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>Rules to/from the <emphasis role="bold">local</emphasis> <para>Rules to/from the <emphasis
zone and any zone other than the firewall zone are ignored role="bold">loopback</emphasis> zone and any zone other than
with a warning.</para> the firewall zone are ignored with a warning.</para>
<para>Only one <emphasis role="bold">local</emphasis> zone may <para><emphasis role="bold">loopback</emphasis> zones may be
be defined.</para> nested within other <emphasis role="bold">loopback</emphasis>
zones.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>local</term>
<listitem>
<para>Added in Shorewall 4.5.17. <emphasis
role="bold">local</emphasis> is the same as <emphasis
role="bold">ipv6</emphasis> with the exception that the zone
is only accessible from the <emphasis
role="bold">firewall</emphasis>, <emphasis
role="bold">vserver</emphasis> and other <emphasis
role="bold">local</emphasis> zones.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>