forked from extern/shorewall_code
First installment of New Bridge Code
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@6468 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
61638c996c
commit
a8cb589333
@ -84,6 +84,15 @@ sub validate_hosts_file()
|
||||
fatal_error "Invalid HOST(S) column contents: $hosts";
|
||||
}
|
||||
|
||||
if ( $type eq 'bport4' ) {
|
||||
if ( $zoneref->{bridge} eq '' ) {
|
||||
fatal_error 'Bridge Port Zones may only be associated with bridge ports' unless $interfaces{$interface}{options}{port};
|
||||
$zoneref->{bridge} = $interfaces{$interface}{bridge};
|
||||
} elsif ( $zoneref->{bridge} ne $interfaces{$interface}{bridge} ) {
|
||||
fatal_error "Interface $interface is not a port on bridge $zoneref->{bridge}";
|
||||
}
|
||||
}
|
||||
|
||||
my $optionsref = {};
|
||||
|
||||
if ( $options ne '-' ) {
|
||||
|
@ -56,6 +56,7 @@ our @VERSION = 1.00;
|
||||
# ...
|
||||
# }
|
||||
# zone => <zone name>
|
||||
# bridge => <bridge>
|
||||
# }
|
||||
# }
|
||||
#
|
||||
@ -161,6 +162,7 @@ sub validate_interfaces_file()
|
||||
my %validoptions = (arp_filter => BINARY_IF_OPTION,
|
||||
arp_ignore => ENUM_IF_OPTION,
|
||||
blacklist => SIMPLE_IF_OPTION,
|
||||
bridge => SIMPLE_IF_OPTION,
|
||||
detectnets => SIMPLE_IF_OPTION,
|
||||
dhcp => SIMPLE_IF_OPTION,
|
||||
maclist => SIMPLE_IF_OPTION,
|
||||
@ -189,6 +191,7 @@ sub validate_interfaces_file()
|
||||
|
||||
my ($zone, $interface, $networks, $options ) = split_line 2, 4, 'interfaces file';
|
||||
my $zoneref;
|
||||
my $bridge = '';
|
||||
|
||||
if ( $zone eq '-' ) {
|
||||
$zone = '';
|
||||
@ -202,9 +205,26 @@ sub validate_interfaces_file()
|
||||
$networks = '' if $networks eq '-';
|
||||
$options = '' if $options eq '-';
|
||||
|
||||
( $interface, my ($port, $extra) ) = split /:/ , $interface, 3;
|
||||
|
||||
fatal_error "Invalid INTERFACE" if defined $extra || ! $interface;
|
||||
|
||||
fatal_error "Duplicate Interface ($interface)" if $interfaces{$interface};
|
||||
|
||||
fatal_error "Invalid Interface Name: $interface" if $interface =~ /:|^\+$/;
|
||||
fatal_error "Invalid Interface Name: $interface" if $interface eq '+';
|
||||
|
||||
if ( defined $port ) {
|
||||
require_capability( 'PHYSDEV_MATCH', 'Bridge Ports', '');
|
||||
require_capability( 'KLUDGEFREE', 'Bridge Ports', '');
|
||||
fatal_error "$interface is not a defined bridge" unless $interfaces{$interface} && $interfaces{$interface}{options}{bridge};
|
||||
fatal_error "Invalid Bridge Port Name ($port)" unless $port =~ /^([\w.@%-]+\+?)$/;
|
||||
fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} ne 'bport4';
|
||||
$interfaces{$port}{bridge} = $bridge = $interface;
|
||||
$interface = $port;
|
||||
} else {
|
||||
fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} eq 'bport4';
|
||||
$interfaces{$interface}{bridge} = $interface;
|
||||
}
|
||||
|
||||
my $wildcard = 0;
|
||||
|
||||
@ -229,6 +249,8 @@ sub validate_interfaces_file()
|
||||
my %options;
|
||||
|
||||
if ( $options ) {
|
||||
fatal_error "Bridge Ports may not have options" if defined $port;
|
||||
|
||||
for my $option (split ',', $options ) {
|
||||
next if $option eq '-';
|
||||
|
||||
@ -266,7 +288,14 @@ sub validate_interfaces_file()
|
||||
}
|
||||
}
|
||||
|
||||
$zoneref->{options}{in_out}{routeback} = 1 if $options{routeback};
|
||||
$zoneref->{options}{in_out}{routeback} = 1 if $zoneref && $options{routeback};
|
||||
|
||||
if ( $options{bridge} ) {
|
||||
require_capability( 'PHYSDEV_MATCH', 'The "bridge" option', 's');
|
||||
fatal_error "Bridges may not have wildcard names" if $wildcard;
|
||||
}
|
||||
} elsif ( defined $port ) {
|
||||
$options{port} = 1;
|
||||
}
|
||||
|
||||
$interfaces{$interface}{options} = $optionsref = \%options;
|
||||
|
@ -782,13 +782,13 @@ sub setup_mac_lists( $ ) {
|
||||
}
|
||||
}
|
||||
|
||||
sub process_rule1 ( $$$$$$$$$$ );
|
||||
sub process_rule1 ( $$$$$$$$$$$ );
|
||||
|
||||
#
|
||||
# Expand a macro rule from the rules file
|
||||
#
|
||||
sub process_macro ( $$$$$$$$$$$$ ) {
|
||||
my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark ) = @_;
|
||||
sub process_macro ( $$$$$$$$$$$$$ ) {
|
||||
my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $wildcard ) = @_;
|
||||
|
||||
progress_message "..Expanding Macro $macrofile...";
|
||||
|
||||
@ -847,7 +847,7 @@ sub process_macro ( $$$$$$$$$$$$ ) {
|
||||
$mrate = merge_macro_column $mrate, $rate;
|
||||
$muser = merge_macro_column $muser, $user;
|
||||
|
||||
process_rule1 $mtarget, $msource, $mdest, $mproto, $mports, $msports, $origdest, $mrate, $muser, $mark;
|
||||
process_rule1 $mtarget, $msource, $mdest, $mproto, $mports, $msports, $origdest, $mrate, $muser, $mark, $wildcard;
|
||||
|
||||
progress_message " Rule \"$line\" $done";
|
||||
}
|
||||
@ -864,8 +864,8 @@ my @param_stack;
|
||||
#
|
||||
# Once a rule has been completely resolved by macro expansion and wildcard (source and/or dest zone == 'all'), it is processed by this function.
|
||||
#
|
||||
sub process_rule1 ( $$$$$$$$$$ ) {
|
||||
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark ) = @_;
|
||||
sub process_rule1 ( $$$$$$$$$$$ ) {
|
||||
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $wildcard ) = @_;
|
||||
my ( $action, $loglevel) = split_action $target;
|
||||
my ( $basictarget, $param ) = split '/', $action;
|
||||
my $rule = '';
|
||||
@ -902,7 +902,8 @@ sub process_rule1 ( $$$$$$$$$$ ) {
|
||||
$origdest,
|
||||
$ratelimit,
|
||||
$user,
|
||||
$mark );
|
||||
$mark,
|
||||
$wildcard );
|
||||
|
||||
$macro_nest_level--;
|
||||
|
||||
@ -974,6 +975,15 @@ sub process_rule1 ( $$$$$$$$$$ ) {
|
||||
$restriction = INPUT_RESTRICT if $destzone eq $firewall_zone;
|
||||
}
|
||||
#
|
||||
# Check for illegal bridge port rule
|
||||
#
|
||||
if ( $zones{$sourcezone}->{type} eq 'bport4' ) {
|
||||
unless ( $zones{$sourcezone}{bridge} eq $zones{$destzone}{bridge} ) {
|
||||
return 1 if $wildcard;
|
||||
fatal_error "Rules with a DESTINATION Bridge Port zone must have a SOURCE zone on the same bridge";
|
||||
}
|
||||
}
|
||||
#
|
||||
# Take care of chain
|
||||
#
|
||||
my $chain = "${sourcezone}2${destzone}";
|
||||
@ -982,8 +992,13 @@ sub process_rule1 ( $$$$$$$$$$ ) {
|
||||
# Validate Policy
|
||||
#
|
||||
my $policy = $chainref->{policy};
|
||||
|
||||
fatal_error "No policy defined from zone $sourcezone to zone $destzone" unless $policy;
|
||||
fatal_error "Rules may not override a NONE policy" if $policy eq 'NONE';
|
||||
|
||||
if ( $policy eq 'NONE' ) {
|
||||
return 1 if $wildcard;
|
||||
fatal_error "Rules may not override a NONE policy";
|
||||
}
|
||||
#
|
||||
# For compatibility with older Shorewall versions
|
||||
#
|
||||
@ -1211,17 +1226,15 @@ sub process_rule ( $$$$$$$$$$ ) {
|
||||
my $policychainref = $filter_table->{"${zone}2${zone1}"}{policychain};
|
||||
fatal_error "No policy from zone $zone to zone $zone1" unless $policychainref;
|
||||
my $policy = $policychainref->{policy};
|
||||
unless ( $policy eq 'NONE' ) {
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '' ) {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '' ) {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark;
|
||||
}
|
||||
process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1232,17 +1245,15 @@ sub process_rule ( $$$$$$$$$$ ) {
|
||||
if ( $intrazone || ( $zone ne $destzone ) ) {
|
||||
fatal_error "No policy from zone $zone to zone $destzone" unless $policychainref;
|
||||
my $policy = $policychainref->{policy};
|
||||
unless ( $policy eq 'NONE' ) {
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '') {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '') {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark;
|
||||
}
|
||||
process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1254,21 +1265,19 @@ sub process_rule ( $$$$$$$$$$ ) {
|
||||
fatal_error "Unknown source zone ($sourcezone)" unless $zones{$sourcezone};
|
||||
my $policychainref = $filter_table->{"${sourcezone}2${zone}"}{policychain};
|
||||
my $policy = $policychainref->{policy};
|
||||
unless ( $policy eq 'NONE' ) {
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '' ) {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
if ( $optimize > 0 ) {
|
||||
my $loglevel = $policychainref->{loglevel};
|
||||
if ( $loglevel ne '' ) {
|
||||
next if $target eq "${policy}:$loglevel}";
|
||||
} else {
|
||||
next if $action eq $policy;
|
||||
}
|
||||
}
|
||||
process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark;
|
||||
process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark;
|
||||
process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 0;
|
||||
}
|
||||
|
||||
progress_message " Rule \"$thisline\" $done";
|
||||
@ -1365,6 +1374,32 @@ sub generate_matrix() {
|
||||
add_rule $chainref, "-j $name";
|
||||
}
|
||||
|
||||
#
|
||||
# Match Source Interface
|
||||
#
|
||||
sub match_source_dev( $ ) {
|
||||
my $interface = shift;
|
||||
my $interfaceref = $interfaces{$interface};
|
||||
if ( $interfaceref->{options}{port} ) {
|
||||
"-i $interfaceref->{bridge} -m physdev --physdev-in $interface ";
|
||||
} else {
|
||||
"-i $interface ";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Match Dest device
|
||||
#
|
||||
sub match_dest_dev( $ ) {
|
||||
my $interface = shift;
|
||||
my $interfaceref = $interfaces{$interface};
|
||||
if ( $interfaceref->{options}{port} ) {
|
||||
"-o $interfaceref->{bridge} -m physdev --physdev-out $interface ";
|
||||
} else {
|
||||
"-o $interface ";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Insert the passed exclusions at the front of the passed chain.
|
||||
#
|
||||
@ -1375,7 +1410,7 @@ sub generate_matrix() {
|
||||
|
||||
for my $host ( @{$exclusionsref} ) {
|
||||
my ( $interface, $net ) = split /:/, $host;
|
||||
insert_rule $chainref , $num++, join( '', "-i $interface ", match_source_net( $net ), '-j RETURN' );
|
||||
insert_rule $chainref , $num++, join( '', match_source_dev $interface , match_source_net( $net ), '-j RETURN' );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1387,7 +1422,7 @@ sub generate_matrix() {
|
||||
|
||||
for my $host ( @{$exclusionsref} ) {
|
||||
my ( $interface, $net ) = split /:/, $host;
|
||||
add_rule $chainref , join( '', "-i $interface ", match_source_net( $net ), '-j RETURN' );
|
||||
add_rule $chainref , join( '', match_source_dev $interface, match_source_net( $net ), '-j RETURN' );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1409,12 +1444,12 @@ sub generate_matrix() {
|
||||
my %policy_exclusions;
|
||||
|
||||
for my $interface ( @interfaces ) {
|
||||
addnatjump 'POSTROUTING' , snat_chain( $interface ), "-o $interface ";
|
||||
addnatjump 'POSTROUTING' , snat_chain( $interface ), match_dest_dev( $interface );
|
||||
}
|
||||
|
||||
if ( $config{DYNAMIC_ZONES} ) {
|
||||
for my $interface ( @interfaces ) {
|
||||
addnatjump 'PREROUTING' , dynamic_in( $interface ), "-i $interface ";
|
||||
addnatjump 'PREROUTING' , dynamic_in( $interface ), match_source_dev( $interface );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1422,8 +1457,8 @@ sub generate_matrix() {
|
||||
addnatjump 'POSTROUTING' , 'nat_out' , '';
|
||||
|
||||
for my $interface ( @interfaces ) {
|
||||
addnatjump 'PREROUTING' , input_chain( $interface ) , "-i $interface ";
|
||||
addnatjump 'POSTROUTING' , output_chain( $interface ) , "-o $interface ";
|
||||
addnatjump 'PREROUTING' , input_chain( $interface ) , match_source_dev( $interface );
|
||||
addnatjump 'POSTROUTING' , output_chain( $interface ) , match_dest_dev( $interface );
|
||||
}
|
||||
|
||||
for my $zone ( grep $zones{$_}{options}{complex} , @zones ) {
|
||||
@ -1440,9 +1475,10 @@ sub generate_matrix() {
|
||||
|
||||
for my $host ( @$exclusions ) {
|
||||
my ( $interface, $net ) = split /:/, $host;
|
||||
add_rule $frwd_ref , "-i $interface -s $net -j RETURN";
|
||||
add_rule $in_ref , "-i $interface -s $net -j RETURN";
|
||||
add_rule $out_ref , "-i $interface -s $net -j RETURN";
|
||||
my $rule = match_source_interface( $interface ) . "-s $net -j RETURN";
|
||||
add_rule $frwd_ref , $rule;
|
||||
add_rule $in_ref , $rule;
|
||||
add_rule $out_ref , $rule;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1520,7 +1556,7 @@ sub generate_matrix() {
|
||||
|
||||
my $source = match_source_net $net;
|
||||
|
||||
insertnatjump 'PREROUTING' , dnat_chain $zone, \$prerouting_rule, join( '', "-i $interface ", $source, $ipsec_in_match );
|
||||
insertnatjump 'PREROUTING' , dnat_chain $zone, \$prerouting_rule, join( '', match_source_dev( $interface), $source, $ipsec_in_match );
|
||||
|
||||
if ( $chain2 ) {
|
||||
if ( @$exclusions ) {
|
||||
@ -1665,7 +1701,7 @@ sub generate_matrix() {
|
||||
if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) {
|
||||
my $ipsec_out_match = match_ipsec_out $zone1 , $hostref;
|
||||
for my $net ( @{$hostref->{hosts}} ) {
|
||||
add_rule $frwd_ref, join( '', "-o $interface ", match_dest_net($net), $ipsec_out_match, "-j $chain" );
|
||||
add_rule $frwd_ref, join( '', match_dest_dev( $interface) , match_dest_net($net), $ipsec_out_match, "-j $chain" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1690,7 +1726,7 @@ sub generate_matrix() {
|
||||
#
|
||||
add_rule(
|
||||
$chain3ref ,
|
||||
join( '', "-o $interface1 ", match_source_net($net), match_dest_net($net1), $ipsec_out_match, "-j $chain" )
|
||||
join( '', match_dest_dev($interface), match_source_net($net), match_dest_net($net1), $ipsec_out_match, "-j $chain" )
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1730,10 +1766,10 @@ sub generate_matrix() {
|
||||
# Now add the jumps to the interface chains from FORWARD, INPUT, OUTPUT and POSTROUTING
|
||||
#
|
||||
for my $interface ( @interfaces ) {
|
||||
add_rule $filter_table->{FORWARD} , "-i $interface -j " . forward_chain $interface;
|
||||
add_rule $filter_table->{INPUT} , "-i $interface -j " . input_chain $interface;
|
||||
add_rule $filter_table->{OUTPUT} , "-o $interface -j " . output_chain $interface;
|
||||
addnatjump 'POSTROUTING' , masq_chain( $interface ) , "-o $interface ";
|
||||
add_rule $filter_table->{FORWARD} , match_source_dev( $interface ) . "-j " . forward_chain $interface;
|
||||
add_rule $filter_table->{INPUT} , match_source_dev( $interface ) . "-j " . input_chain $interface;
|
||||
add_rule $filter_table->{OUTPUT} , "-o $interface -j " . output_chain $interface unless $interfaces{$interface}{options}{port};
|
||||
addnatjump 'POSTROUTING' , masq_chain( $interface ) , match_dest_dev( $interface );
|
||||
}
|
||||
|
||||
my $chainref = $filter_table->{"${firewall_zone}2${firewall_zone}"};
|
||||
|
@ -73,6 +73,7 @@ use constant { NOTHING => 'NOTHING',
|
||||
# parents => [ <parents> ] Parents, Children and interfaces are listed by name
|
||||
# children => [ <children> ]
|
||||
# interfaces => [ <interfaces> ]
|
||||
# bridge => <bridge>
|
||||
# hosts { <type> } => [ { <interface1> => { ipsec => 'ipsec'|'none'
|
||||
# options => { <option1> => <value1>
|
||||
# ...
|
||||
@ -223,6 +224,7 @@ sub determine_zones()
|
||||
my $zoneref = $zones{$zone} = {};
|
||||
$zoneref->{parents} = \@parents;
|
||||
$zoneref->{exclusions} = [];
|
||||
$zoneref->{bridge} = '';
|
||||
|
||||
$type = "ipv4" unless $type;
|
||||
|
||||
@ -230,6 +232,16 @@ sub determine_zones()
|
||||
$zoneref->{type} = 'ipv4';
|
||||
} elsif ( $type =~ /^ipsec4?$/i ) {
|
||||
$zoneref->{type} = 'ipsec4';
|
||||
} elsif ( $type =~ /^bport4?$/i ) {
|
||||
fatal_error "Bridge Port zones must have a single parent zone" unless @parents == 1;
|
||||
|
||||
for my $p ( @parents ) {
|
||||
my $interfaceref = $interfaces{$1};
|
||||
fatal_error "Parent Zone $p is not associated with device $1" unless $interfaceref && $interfaceref->{zone} eq $zone;
|
||||
}
|
||||
|
||||
$zoneref->{type} = 'bport4';
|
||||
|
||||
} elsif ( $type eq 'firewall' ) {
|
||||
fatal_error 'Firewall zone may not be nested' if @parents;
|
||||
fatal_error "Only one firewall zone may be defined: $zone" if $firewall_zone;
|
||||
|
Loading…
Reference in New Issue
Block a user