Add 'virtual' zone support

This commit is contained in:
Tom Eastep 2009-11-25 09:42:28 -08:00
parent 4c40b205f8
commit a2cd4bd1f4
9 changed files with 261 additions and 66 deletions

View File

@ -145,6 +145,8 @@ our %EXPORT_TAGS = (
log_rule
expand_rule
addnatjump
rules_target
continuation_target
set_chain_variables
mark_firewall_not_started
mark_firewall6_not_started
@ -167,7 +169,7 @@ our %EXPORT_TAGS = (
Exporter::export_ok_tags('internal');
our $VERSION = '4.4_4';
our $VERSION = '4.4_5';
#
# Chain Table
@ -2017,6 +2019,50 @@ sub addnatjump( $$$ ) {
}
}
#
# Return the target for rules from $zone to $zone1.
#
sub continuation_target( $$ );
sub rules_target( $$ ) {
my ( $zone, $zone1 ) = @_;
my $chain = rules_chain( ${zone}, ${zone1} );
my $chainref = $filter_table->{$chain};
return $chain if $chainref && $chainref->{referenced};
return 'ACCEPT' if $zone eq $zone1;
assert( $chainref );
if ( $chainref->{policy} ne 'CONTINUE' ) {
my $policyref = $filter_table->{$chainref->{policychain}};
assert( $policyref );
return $policyref->{name};
}
continuation_target $zone, $zone1
}
sub continuation_target( $$ ) {
my ( $zone, $zone1 ) = @_;
my $zoneref = defined_zone( $zone );
my $chain;
for ( @{$zoneref->{parents}} ) {
return $chain if virtual_zone( $_ ) && ( $chain = rules_target( $_, $zone1 ) );
}
$zoneref = defined_zone( $zone1 );
for ( @{$zoneref->{parents}} ) {
return $chain if virtual_zone( $_) && ( $chain = rules_target( $zone, $_ ) );
}
'';
}
#
# Split a comma-separated source or destination host list but keep [...] together. Used for spliting address lists
# where an element of the list might be +ipset[binding].

View File

@ -327,7 +327,7 @@ sub initialize( $ ) {
TC_SCRIPT => '',
EXPORT => 0,
UNTRACKED => 0,
VERSION => "4.5.0",
VERSION => "4.4.5",
CAPVERSION => 40402 ,
);

View File

@ -341,13 +341,22 @@ sub validate_policy()
for $zone ( all_zones ) {
push @policy_chains, ( new_policy_chain $zone, $zone, 'ACCEPT', OPTIONAL );
if ( $config{IMPLICIT_CONTINUE} && ( @{find_zone( $zone )->{parents}} ) ) {
if ( $config{IMPLICIT_CONTINUE} && ( @{defined_zone( $zone )->{parents}} ) ) {
for my $zone1 ( all_zones ) {
unless( $zone eq $zone1 ) {
add_or_modify_policy_chain( $zone, $zone1 );
add_or_modify_policy_chain( $zone1, $zone );
}
}
} elsif ( virtual_zone( $zone ) ) {
for my $zone1 ( @{defined_zone( $zone )->{children}} ) {
for my $zone2 ( all_zones ) {
unless ( $zone1 eq $zone2 ) {
add_or_modify_policy_chain( $zone1, $zone2 );
add_or_modify_policy_chain( $zone2, $zone1 );
}
}
}
}
}
@ -385,7 +394,7 @@ sub report_syn_flood_protection() {
}
sub default_policy( $$$ ) {
my $chainref = $_[0];
my ( $chainref, $zone, $zone1 ) = @_;
my $policyref = $filter_table->{$chainref->{policychain}};
my $synparams = $policyref->{synparams};
my $default = $policyref->{default};
@ -395,7 +404,13 @@ sub default_policy( $$$ ) {
assert( $policyref );
if ( $chainref eq $policyref ) {
policy_rules $chainref , $policy, $loglevel , $default, $config{MULTICAST};
policy_rules $chainref, $policy, $loglevel, $default, $config{MULTICAST};
if ( $policy eq 'CONTINUE' ) {
if ( my $continuation = continuation_target( $zone, $zone1 ) ) {
add_jump( $chainref, $continuation, 1 );
$chainref = $filter_table->{$continuation};
}
}
} else {
if ( $policy eq 'ACCEPT' || $policy eq 'QUEUE' || $policy =~ /^NFQUEUE/ ) {
if ( $synparams ) {
@ -408,6 +423,10 @@ sub default_policy( $$$ ) {
} elsif ( $policy eq 'CONTINUE' ) {
report_syn_flood_protection if $synparams;
policy_rules $chainref , $policy , $loglevel , $default, $config{MULTICAST};
if ( my $continuation = continuation_target( $zone, $zone1 ) ) {
add_jump( $chainref, $continuation, 1 );
$chainref = $filter_table->{$continuation};
}
} else {
report_syn_flood_protection if $synparams;
add_jump $chainref , $policyref, 1;
@ -415,7 +434,7 @@ sub default_policy( $$$ ) {
}
}
progress_message_nocompress " Policy $policy from $_[1] to $_[2] using chain $chainref->{name}";
progress_message_nocompress " Policy $policy from $zone to $zone1 using chain $chainref->{name}";
}

View File

@ -1639,42 +1639,7 @@ sub add_interface_jumps {
# The function traverses the full "source-zone by destination-zone" matrix and generates the rules necessary to direct traffic through the right set of filter-table rules.
#
sub generate_matrix() {
#
# Helper functions for generate_matrix()
#-----------------------------------------
#
# Return the target for rules from $zone to $zone1.
#
sub rules_target( $$ ) {
my ( $zone, $zone1 ) = @_;
my $chain = rules_chain( ${zone}, ${zone1} );
my $chainref = $filter_table->{$chain};
return $chain if $chainref && $chainref->{referenced};
return 'ACCEPT' if $zone eq $zone1;
assert( $chainref );
if ( $chainref->{policy} ne 'CONTINUE' ) {
my $policyref = $filter_table->{$chainref->{policychain}};
assert( $policyref );
return $policyref->{name};
}
''; # CONTINUE policy
}
#
# Set a breakpoint in this function if you want to step through generate_matrix().
#
sub start_matrix() {
progress_message2 'Generating Rule Matrix...';
}
#
# G e n e r a t e _ M a t r i x ( ) S t a r t s H e r e
#
start_matrix;
progress_message2 'Generating Rule Matrix...';
my @interfaces = ( all_interfaces );
my $preroutingref = ensure_chain 'nat', 'dnat';

View File

@ -53,6 +53,7 @@ our @EXPORT = qw( NOTHING
all_parent_zones
complex_zones
non_firewall_zones
virtual_zone
single_interface
validate_interfaces_file
all_interfaces
@ -96,9 +97,11 @@ use constant { NOTHING => 'NOTHING',
# options => { complex => 0|1
# nested => 0|1
# super => 0|1
# in_out => < policy match string >
# in => < policy match string >
# out => < policy match string >
# in_out => { ipsec => < policy match string > ,
# mss => <mss>
# virtual => 0|1 }
# in => ...
# out => ...
# }
# parents => [ <parents> ] Parents, Children and interfaces are listed by name
# children => [ <children> ]
@ -269,6 +272,7 @@ sub initialize( $ ) {
sub parse_zone_option_list($$)
{
my %validoptions = ( mss => NUMERIC,
virtual => NOTHING,
strict => NOTHING,
next => NOTHING,
reqid => NUMERIC,
@ -281,7 +285,7 @@ sub parse_zone_option_list($$)
#
# Hash of options that have their own key in the returned hash.
#
my %key = ( mss => 'mss' );
my %key = ( mss => 1 , virtual => 1 );
my ( $list, $zonetype ) = @_;
my %h;
@ -314,7 +318,7 @@ sub parse_zone_option_list($$)
}
if ( $key{$e} ) {
$h{$e} = $val;
$h{$e} = $val || 1;
} else {
fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype == IPSEC;
$options .= $invert;
@ -406,20 +410,27 @@ sub process_zone( \$ ) {
$_ = '' if $_ eq '-';
}
$zones{$zone} = { type => $type,
parents => \@parents,
bridge => '',
options => { in_out => parse_zone_option_list( $options || '', $type ) ,
in => parse_zone_option_list( $in_options || '', $type ) ,
out => parse_zone_option_list( $out_options || '', $type ) ,
complex => ($type == IPSEC || $options || $in_options || $out_options ? 1 : 0) ,
nested => @parents > 0 ,
super => 0 ,
} ,
interfaces => {} ,
children => [] ,
hosts => {}
};
my $zoneref = $zones{$zone} = { type => $type,
parents => \@parents,
bridge => '',
options => $options = { in_out => parse_zone_option_list( $options, $type ) ,
in => parse_zone_option_list( $in_options, $type ) ,
out => parse_zone_option_list( $out_options, $type ) ,
complex => ($type == IPSEC || $options || $in_options || $out_options ? 1 : 0) ,
nested => @parents > 0 ,
super => 0 ,
} ,
interfaces => {} ,
children => [] ,
hosts => {}
};
fatal_error "'virtual' is not permitted in IN OPTIONS or in OUT OPTIONS" if $options->{in}{virtual} || $options->{out}{virtual};
if ( $options->{in_out}{virtual} ) {
fatal_error "Nested virtual Zones are not supported" if $options->{nested};
fatal_error "Only IP zones are allowed to be virtual" unless $type == IP;
}
return $zone;
@ -523,14 +534,13 @@ sub zone_report()
$printed = 1;
}
}
}
}
}
unless ( $printed ) {
fatal_error "No bridge has been associated with zone $zone" if $type == BPORT && ! $zoneref->{bridge};
warning_message "*** $zone is an EMPTY ZONE ***" unless $type == FIREWALL;
warning_message "*** $zone is an EMPTY ZONE ***" unless $type == FIREWALL || ( $optionref->{in_out}{virtual} && @{$zoneref->{children}} );
}
}
@ -587,6 +597,12 @@ sub dump_zone_contents()
}
}
if ( $zoneref->{options}{in_out}{virtual} && @{$zoneref->{children}} ) {
$entry .= " (";
$entry .= "$_," for @{$zoneref->{children}};
$entry =~ s/,$/) /;
}
emit_unindented $entry;
}
}
@ -614,6 +630,8 @@ sub add_group_to_zone($$$$$)
my $zoneref = $zones{$zone};
my $zonetype = $zoneref->{type};
fatal_error "Zone $zone is virtual and may not be defined in the interfaces and hosts files" if $zoneref->{options}{in_out}{virtual};
$zoneref->{interfaces}{$interface} = 1;
my @newnetworks;
@ -719,6 +737,10 @@ sub firewall_zone() {
$firewall_zone;
}
sub virtual_zone( $ ) {
$zones{$_[0]}{options}{in_out}{virtual};
}
#
# Process a record in the interfaces file
#

View File

@ -12,6 +12,8 @@ Changes in Shorewall 4.4.5
6) Fix 'show policies' in Shorewall6.
7) Implement 'virtual' zones.
Changes in Shorewall 4.4.4
1) Change STARTUP_LOG and LOG_VERBOSITY in default shorewall6.conf.

View File

@ -230,6 +230,39 @@ None.
$FW dmz REJECT info
$FW all ACCEPT
3) Shorewall 4.4.5 introduces 'virtual' zones. A virtual zone is used
to group together a set of sub-zones. A virtual zone must by an
ipv4 zone (Shorewall) or an ipv6 zone (Shorewall6) and is declared
with the 'virtual' OPTION in /etc/shorewall/zones.
Example:
virt ipv4 virtual
The virtual zone must have no definition in
/etc/shorewall/interfaces or /etc/shorewall/hosts. In this first
release, virtual zones cannot themselves be nested.
Virtual zones are use as parent zones for other zones using the
<zone>:<parent> syntax in /etc/shorewall/zones:
Example:
virt ipv4 virtual
loc:virt ipv4
vpn:virt ipsec
As shown in that example, a virtual zone may be a parent for
multiple zone types.
Virtual zones are intended to be used with
IMPLICIT_CONTINUE=No. They provide semantic behavior similar to
IMPLICIT_CONTINUE=Yes in that connections that do not match rules
for the sub-zone are applied to the parent zone.
For more information, see
http://www.shorewall.net/manpages/shorewall-nesting.html
----------------------------------------------------------------------------
N E W F E A T U R E S I N 4 . 4 . 0
----------------------------------------------------------------------------

View File

@ -154,14 +154,14 @@
to change the 'net' interface to something other than ppp0. That way, it
won't match ppp+.</para>
<para>If you are running Shorewall version 4.1.4 or later, a second way is
to simply make the nested zones explicit:<programlisting> #ZONE TYPE OPTION
<para>A second way is to simply make the nested zones
explicit:<programlisting> #ZONE TYPE OPTION
fw firewall
loc ipv4
net:loc ipv4
dmz ipv4</programlisting></para>
<para>If you take this approach, be sure to set IMPLICIT_CONTINUE=No in
<para>If you take this approach, be sure to set IMPLICIT_CONTINUE=Yes in
<filename>shorewall.conf</filename>.</para>
<para>When using other Shorewall versions, another way is to rewrite the
@ -183,6 +183,60 @@
loc ppp+:192.168.2.0/23</programlisting></para>
</refsect1>
<refsect1 id="Virtual">
<title>Virtual Zones</title>
<para>Beginning with Shorewall 4.4.5, Shorewall allows the declaration of
<firstterm>virtual</firstterm> zones. A virtual zone has no definition in
<filename>/etc/shorewall/interfaces</filename> or in
<filename>/etc/shorewall/hosts</filename>. Rather, it is used as a parent
zone for other zones in <filename>/etc/shorewall/zones</filename>.</para>
<para>Example:</para>
<para><filename>/etc/shorewall/zones</filename>:</para>
<programlisting> #ZONE TYPE OPTIONS
fw firewall
net ipv4
loc ipv4 virtual
loc1:loc ipv4
loc2:loc ipv4</programlisting>
<para><filename>/etc/shorewall/interfaces</filename>:</para>
<programlisting> #ZONE INTERFACE BROADCAST OPTIONS
net eth0 detect dhcp,tcpflags,nosmurfs,routefilter,logmartians
- eth1 detect tcpflags,nosmurfs,routefilter,logmartians</programlisting>
<para><filename>/etc/shorewall/hosts</filename>:</para>
<programlisting> #ZONE HOST(S) OPTIONS
loc1 eth1:192.168.1.0/24
loc2 eth1:192.168.2.0/24</programlisting>
<para>There are several restrictions on virtual zones:</para>
<itemizedlist>
<listitem>
<para>They must have type <option>ipv4</option>.</para>
</listitem>
<listitem>
<para>They may not themselves be nested.</para>
</listitem>
<listitem>
<para>They should not be used with IMPLICIT_CONTINUE=Yes in <ulink
url="shorewall.conf.html">shorewall.conf</ulink>(5).</para>
</listitem>
</itemizedlist>
<para>When a connection request to/from a sub-zone of a virtual zone does
not match the rules for the sub-zone, the connection is compared against
the rules (and policies) for the parent virtual zone.</para>
</refsect1>
<refsect1>
<title>FILES</title>

View File

@ -87,6 +87,60 @@
significant.</para>
</refsect1>
<refsect1 id="Virtual">
<title>Virtual Zones</title>
<para>Beginning with Shorewall 4.4.5, Shorewall allows the declaration of
<firstterm>virtual</firstterm> zones. A virtual zone has no definition in
<filename>/etc/shorewall6/interfaces</filename> or in
<filename>/etc/shorewall6/hosts</filename>. Rather, it is used as a parent
zone for other zones in <filename>/etc/shorewall6/zones</filename>.</para>
<para>Example:</para>
<para><filename>/etc/shorewall6/zones</filename>:</para>
<programlisting> #ZONE TYPE OPTIONS
fw firewall
net ipv6
loc ipv6 virtual
loc1:loc ipv6
loc2:loc ipv6</programlisting>
<para><filename>/etc/shorewall/interfaces</filename>:</para>
<programlisting> #ZONE INTERFACE BROADCAST OPTIONS
net eth0 detect dhcp,tcpflags
- eth1 detect tcpflags</programlisting>
<para><filename>/etc/shorewall/hosts</filename>:</para>
<programlisting> #ZONE HOST(S) OPTIONS
loc1 eth1:2001:19f0:feee:1::/48
loc2 eth1:2001:19f0:feee:2::/48</programlisting>
<para>There are several restrictions on virtual zones:</para>
<itemizedlist>
<listitem>
<para>They must have type <option>ipv6</option>.</para>
</listitem>
<listitem>
<para>They may not themselves be nested.</para>
</listitem>
<listitem>
<para>They should not be used with IMPLICIT_CONTINUE=Yes in <ulink
url="shorewall6.conf.html">shorewall6.conf</ulink>(5).</para>
</listitem>
</itemizedlist>
<para>When a connection request to/from a sub-zone of a virtual zone does
not match the rules for the sub-zone, the connection is compared against
the rules (and policies) for the parent virtual zone.</para>
</refsect1>
<refsect1>
<title>FILES</title>