mirror of
https://gitlab.com/shorewall/code.git
synced 2024-12-23 06:38:53 +01:00
Add 'virtual' zone support
This commit is contained in:
parent
4c40b205f8
commit
a2cd4bd1f4
@ -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].
|
||||
|
@ -327,7 +327,7 @@ sub initialize( $ ) {
|
||||
TC_SCRIPT => '',
|
||||
EXPORT => 0,
|
||||
UNTRACKED => 0,
|
||||
VERSION => "4.5.0",
|
||||
VERSION => "4.4.5",
|
||||
CAPVERSION => 40402 ,
|
||||
);
|
||||
|
||||
|
@ -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}";
|
||||
|
||||
}
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
----------------------------------------------------------------------------
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user