Better virtual zone implementation

This commit is contained in:
Tom Eastep 2009-11-25 18:14:14 -08:00
parent 8263ea1312
commit 8ff4d004c0
10 changed files with 94 additions and 26 deletions

View File

@ -167,7 +167,7 @@ our %EXPORT_TAGS = (
Exporter::export_ok_tags('internal');
our $VERSION = '4.4_4';
our $VERSION = '4.4_5';
#
# Chain Table
@ -1185,9 +1185,18 @@ sub finish_section ( $ ) {
$sections{$_} = 1 for split /,/, $sections;
for my $zone ( all_zones ) {
my $mark = defined_zone( $zone )->{mark};
for my $zone1 ( all_zones ) {
my $mark1 = ( defined_zone( $zone1 )->{mark} || 0 ) << VIRTUAL_BITS;
my $chainref = $chain_table{'filter'}{rules_chain( $zone, $zone1 )};
finish_chain_section $chainref, $sections if $chainref->{referenced};
finish_chain_section $chainref, $sections if $chainref->{referenced} || $mark || $mark1;
if ( $sections{RELATED} ) {
add_rule $chainref, '-j MARK --or-mark ' . in_hex($mark) if $mark;
add_rule $chainref, '-j MARK --or-mark ' . in_hex($mark1) if $mark1;
}
}
}
}

View File

@ -127,7 +127,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
Exporter::export_ok_tags('internal');
our $VERSION = '4.4_4';
our $VERSION = '4.4_5';
#
# describe the current command, it's present progressive, and it's completion.
@ -242,6 +242,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT',
IPMARK_TARGET => 'IPMARK Target',
PERSISTENT_SNAT => 'Persistent SNAT',
OLD_HL_MATCH => 'Old Hash Limit Match',
MARK_IN_FILTER => 'MARK in Filter Table',
CAPVERSION => 'Capability Version',
);
#
@ -327,8 +328,8 @@ sub initialize( $ ) {
TC_SCRIPT => '',
EXPORT => 0,
UNTRACKED => 0,
VERSION => "4.5.0",
CAPVERSION => 40402 ,
VERSION => "4.4.5",
CAPVERSION => 40405 ,
);
#
@ -619,6 +620,7 @@ sub initialize( $ ) {
LOG_TARGET => 1, # Assume that we have it.
PERSISTENT_SNAT => undef,
OLD_HL_MATCH => undef,
MARK_IN_FILTER => undef,
CAPVERSION => undef,
);
#
@ -2031,6 +2033,7 @@ sub determine_capabilities( $ ) {
$capabilities{LENGTH_MATCH} = qt1( "$iptables -A $sillyname -m length --length 10:20 -j ACCEPT" );
$capabilities{ENHANCED_REJECT} = qt1( "$iptables -A $sillyname -j REJECT --reject-with icmp6-admt-prohibited" );
$capabilities{COMMENTS} = qt1( qq($iptables -A $sillyname -j ACCEPT -m comment --comment "This is a comment" ) );
$capabilities{MARK_IN_FILTER} = qt1( "$iptables -A $sillyname -j MARK --set-mark 1" );
$capabilities{HASHLIMIT_MATCH} = qt1( "$iptables -A $sillyname -m hashlimit --hashlimit-upto 3/min --hashlimit-burst 3 --hashlimit-name $sillyname --hashlimit-mode srcip -j ACCEPT" );

View File

@ -348,8 +348,16 @@ sub validate_policy()
add_or_modify_policy_chain( $zone1, $zone );
}
}
} elsif ( defined_zone( $zone )->{virtual} ) {
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 );
}
}
}
} }
my $fn = open_file 'policy';

View File

@ -1724,10 +1724,11 @@ sub generate_matrix() {
for my $hostref ( @{$arrayref} ) {
my $ipsec_match = match_ipsec_in $zone , $hostref;
my $exclusion = source_exclusion( $hostref->{exclusions}, $frwd_ref );
for my $net ( @{$hostref->{hosts}} ) {
add_jump(
$sourcechainref,
source_exclusion( $hostref->{exclusions}, $frwd_ref ),
$exclusion,
! @{$zoneref->{parents}},
join( '', $interfacematch , match_source_net( $net ), $ipsec_match )
);
@ -1759,6 +1760,7 @@ sub generate_matrix() {
my $nested = $zoneref->{options}{nested};
my $parenthasnat = 0;
my $parenthasnotrack = 0;
my $virtual = $zoneref->{virtual};
if ( $nested ) {
#
@ -1823,6 +1825,8 @@ sub generate_matrix() {
my $outputref;
my $interfacematch = '';
add_jump $filter_table->{OUTPUT}, $chain1, 0, "-m mark --mark ! 0/" . in_hex($virtual) if $virtual;
if ( use_output_chain $interface ) {
$outputref = $filter_table->{output_chain $interface};
add_jump $filter_table->{OUTPUT}, $outputref, 0, match_dest_dev( $interface ) unless $output_jump_added{$interface}++;
@ -1881,6 +1885,7 @@ sub generate_matrix() {
}
if ( $chain2 ) {
add_jump $filter_table->{INPUT}, $chain2, 0, "-m mark --mark ! 0/" . in_hex($virtual) if $virtual;
add_jump $inputchainref, source_exclusion( $exclusions, $chain2 ), 0, join( '', $interfacematch, $source, $ipsec_in_match );
move_rules( $filter_table->{input_chain $interface} , $filter_table->{$chain2} ) unless use_input_chain $interface;
}
@ -1953,6 +1958,11 @@ sub generate_matrix() {
} else {
@dest_zones = @zones ;
}
if ( $frwd_ref ) {
add_jump $filter_table->{FORWARD}, $frwd_ref, 0, "-m mark --mark ! 0/" . in_hex($virtual) if $virtual;
}
#
# Here it is -- THE BIG UGLY!!!!!!!!!!!!
#
@ -1961,6 +1971,7 @@ sub generate_matrix() {
#
for my $zone1 ( @dest_zones ) {
my $zone1ref = find_zone( $zone1 );
my $virtual1 = $zone1ref->{virtual};
next if $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy} eq 'NONE';
@ -1990,8 +2001,9 @@ sub generate_matrix() {
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 $exclusion = dest_exclusion( $hostref->{exclusions}, $chain);
for my $net ( @{$hostref->{hosts}} ) {
add_jump $frwd_ref, dest_exclusion( $hostref->{exclusions}, $chain), 0, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match );
add_jump( $frwd_ref, $exclusion, 0, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match ) );
}
}
}
@ -2032,6 +2044,7 @@ sub generate_matrix() {
for my $host1ref ( @$array1ref ) {
next if $host1ref->{options}{sourceonly};
my $ipsec_out_match = match_ipsec_out $zone1 , $host1ref;
my $exclusion = dest_exclusion( $host1ref->{exclusions}, $chain );
for my $net1 ( @{$host1ref->{hosts}} ) {
unless ( $interface eq $interface1 && $net eq $net1 && ! $host1ref->{options}{routeback} ) {
#
@ -2039,7 +2052,7 @@ sub generate_matrix() {
#
add_jump(
$excl3ref ,
dest_exclusion( $host1ref->{exclusions}, $chain ),
$exclusion,
0,
join( '',
$match_source_dev,
@ -2048,6 +2061,11 @@ sub generate_matrix() {
match_dest_net($net1),
$ipsec_out_match )
);
add_jump($excl3ref ,
$exclusion,
0,
"-m mark ! --mark 0/" . in_hex($virtual1) ) if $virtual1;
}
}
}

View File

@ -40,7 +40,7 @@ use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( setup_tc );
our @EXPORT_OK = qw( process_tc_rule initialize );
our $VERSION = '4.4_4';
our $VERSION = '4.4_5';
our %tcs = ( T => { chain => 'tcpost',
connmark => 0,
@ -1235,6 +1235,7 @@ sub setup_tc() {
if ( $capabilities{MANGLE_FORWARD} ) {
add_rule $mangle_table->{FORWARD} , '-j tcfor';
add_rule $mangle_table->{POSTROUTING}, '-j MARK --and-mark 0xffffff'; # Clear virtual marks
add_rule $mangle_table->{POSTROUTING} , '-j tcpost';
}

View File

@ -40,6 +40,7 @@ our @EXPORT = qw( NOTHING
IP
BPORT
IPSEC
VIRTUAL_BITS
determine_zones
zone_report
@ -75,7 +76,7 @@ our @EXPORT = qw( NOTHING
);
our @EXPORT_OK = qw( initialize );
our $VERSION = '4.4_4';
our $VERSION = '4.4_5';
#
# IPSEC Option types
@ -104,6 +105,8 @@ use constant { NOTHING => 'NOTHING',
# children => [ <children> ]
# interfaces => { <interfaces1> => 1, ... }
# bridge => <bridge>
# virtual => <virtual zone mark>
# mark => <LORed virtual zone marks of parent virtual zones>
# hosts { <type> } => [ { <interface1> => { ipsec => 'ipsec'|'none'
# options => { <option1> => <value1>
# ...
@ -156,6 +159,7 @@ our @bport_zones;
our %ipsets;
our %physical;
our $family;
our $virtualmark;
use constant { FIREWALL => 1,
IP => 2,
@ -176,6 +180,11 @@ use constant { SIMPLE_IF_OPTION => 1,
IF_OPTION_HOST => 16,
};
use constant { VIRTUAL_BASE => 0x1000000 ,
VIRTUAL_LIMIT => 0x8000000 ,
VIRTUAL_BITS => 4 #Bits for virtual MASK numbers
};
our %validinterfaceoptions;
our %validhostoptions;
@ -201,6 +210,7 @@ sub initialize( $ ) {
@bport_zones = ();
%ipsets = ();
%physical = ();
$virtualmark = VIRTUAL_BASE;
if ( $family == F_IPV4 ) {
%validinterfaceoptions = (arp_filter => BINARY_IF_OPTION,
@ -353,6 +363,8 @@ sub process_zone( \$ ) {
my ($zone, $type, $options, $in_options, $out_options ) = split_line 1, 5, 'zones file';
my $mark = 0;
if ( $zone =~ /(\w+):([\w,]+)/ ) {
$zone = $1;
@parents = split_list $2, 'zone';
@ -361,6 +373,7 @@ sub process_zone( \$ ) {
fatal_error "Invalid Parent List ($2)" unless $p;
fatal_error "Unknown parent zone ($p)" unless $zones{$p};
fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} == FIREWALL;
$mark |= $zones{$p}{virtual};
push @{$zones{$p}{children}}, $zone;
}
}
@ -402,6 +415,17 @@ sub process_zone( \$ ) {
}
}
my $virtual = 0;
if ( $options eq 'virtual' ) {
require_capability 'MARK_IN_FILTER' , 'virtual zones', '';
fatal_error "Only ipv${family} zones may be virtual" unless $type == IP;
fatal_error "Too many virtual zones" if $virtualmark == VIRTUAL_LIMIT;
$virtual = $virtualmark;
$virtualmark = $virtualmark << 1;
$options = '';
}
for ( $options, $in_options, $out_options ) {
$_ = '' if $_ eq '-';
}
@ -409,6 +433,8 @@ sub process_zone( \$ ) {
$zones{$zone} = { type => $type,
parents => \@parents,
bridge => '',
virtual => $virtual,
mark => $mark ,
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 ) ,
@ -530,9 +556,8 @@ sub zone_report()
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 || ( $zoneref->{virtual} && @{$zoneref->{children}} );
}
}
}
@ -587,6 +612,12 @@ sub dump_zone_contents()
}
}
if ( $zoneref->{virtual} && @{$zoneref->{children}} ) {
$entry .= " (";
$entry .= "$_," for @{$zoneref->{children}};
$entry =~ s/,$/) /;
}
emit_unindented $entry;
}
}

View File

@ -12,7 +12,7 @@ Changes in Shorewall 4.4.5
6) Fix 'show policies' in Shorewall6.
7) Limit the maximum provider mark to 0xf0000.
7) Limit the maximum provider mark to 0xff0000.
Changes in Shorewall 4.4.4

View File

@ -30,7 +30,7 @@
#
SHOREWALL_LIBVERSION=40000
SHOREWALL_CAPVERSION=40402
SHOREWALL_CAPVERSION=40405
[ -n "${VARDIR:=/var/lib/shorewall}" ]
[ -n "${SHAREDIR:=/usr/share/shorewall}" ]
@ -828,6 +828,7 @@ determine_capabilities() {
IPMARK_TARGET=
LOG_TARGET=Yes
PERSISTENT_SNAT=
MARK_IN_FILTER=
chain=fooX$$
@ -958,6 +959,7 @@ determine_capabilities() {
qt $IPTABLES -A $chain -g $chain1 && GOTO_TARGET=Yes
qt $IPTABLES -A $chain -j LOGMARK && LOGMARK_TARGET=Yes
qt $IPTABLES -A $chain -j LOG || LOG_TARGET=
qt $IPTABLES -A $chain -j MARK --set-mark 1 && MARK_IN_FILTER=Yes
qt $IPTABLES -F $chain
qt $IPTABLES -X $chain
@ -1026,6 +1028,7 @@ report_capabilities() {
report_capability "IPMARK Target" $IPMARK_TARGET
report_capability "LOG Target" $LOG_TARGET
report_capability "Persistent SNAT" $PERSISTENT_SNAT
report_capability "Mark in Filter Table" $MARK_IN_FILTER
fi
[ -n "$PKTTYPE" ] || USEPKTTYPE=
@ -1085,6 +1088,7 @@ report_capabilities1() {
report_capability1 IPMARK_TARGET
report_capability1 LOG_TARGET
report_capability1 PERSISTENT_SNAT
report_capability1 MARK_IN_FILTER
echo CAPVERSION=$SHOREWALL_CAPVERSION
}

View File

@ -173,10 +173,6 @@ Shorewall 4.4.5
default. If, for some reason, you don't want 'track' then specify
'notrack' for the provider.
14) With HIGH_ROUTE_MARKS=Yes and WIDE_TC_MARKS=Yes, the maximum
provider mark value is 0xf0000. This limits the number of providers
to 15.
----------------------------------------------------------------------------
P R O B L E M S C O R R E C T E D I N 4 . 4 . 5
----------------------------------------------------------------------------
@ -234,10 +230,6 @@ None.
$FW dmz REJECT info
$FW all ACCEPT
3) With HIGH_ROUTE_MARKS=Yes and WIDE_TC_MARKS=Yes, the maximum
provider mark value is now 0xf0000. This limits the number of
providers to 15.
----------------------------------------------------------------------------
N E W F E A T U R E S I N 4 . 4 . 0
----------------------------------------------------------------------------

View File

@ -33,7 +33,7 @@
#
SHOREWALL_LIBVERSION=40300
SHOREWALL_CAPVERSION=40402
SHOREWALL_CAPVERSION=40405
[ -n "${VARDIR:=/var/lib/shorewall6}" ]
[ -n "${SHAREDIR:=/usr/share/shorewall6}" ]
@ -737,6 +737,7 @@ determine_capabilities() {
GOTO_TARGET=
IPMARK_TARGET=
LOG_TARGET=Yes
MARK_IN_FILTER=Yes
chain=fooX$$
@ -864,6 +865,7 @@ determine_capabilities() {
qt $IP6TABLES -A $chain -m connlimit --connlimit-above 8 -j DROP && CONNLIMIT_MATCH=Yes
qt $IP6TABLES -A $chain -m time --timestart 23:00 -j DROP && TIME_MATCH=Yes
qt $IP6TABLES -A $chain -g $chain1 && GOTO_TARGET=Yes
qt $IP6TABLES -A $chain -j MARK --set-mark 1 && MARK_IN_FILTER=Yes
qt $IP6TABLES -A $chain -j LOG || LOG_TARGET=
qt $IP6TABLES -F $chain