forked from extern/shorewall_code
Add new configuration options and optimization changes from 4.5
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
c39f3c12c9
commit
4bf0b8e1dd
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -35,7 +35,7 @@ use strict;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw( setup_accounting );
|
||||
our @EXPORT_OK = qw( );
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4.7';
|
||||
|
||||
#
|
||||
# Called by the compiler to [re-]initialize this module's state
|
||||
@ -185,17 +185,17 @@ sub setup_accounting() {
|
||||
if ( have_bridges ) {
|
||||
if ( $filter_table->{accounting} ) {
|
||||
for my $chain ( qw/INPUT FORWARD/ ) {
|
||||
insert_rule1 $filter_table->{$chain}, 0, '-j accounting';
|
||||
add_jump( $filter_table->{$chain}, 'accounting', 0, '', 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $filter_table->{accountout} ) {
|
||||
insert_rule1 $filter_table->{OUTPUT}, 0, '-j accountout';
|
||||
add_jump( $filter_table->{OUTPUT}, 'accountout', 0, '', 0, 0 );
|
||||
}
|
||||
} else {
|
||||
if ( $filter_table->{accounting} ) {
|
||||
for my $chain ( qw/INPUT FORWARD OUTPUT/ ) {
|
||||
insert_rule1 $filter_table->{$chain}, 0, '-j accounting';
|
||||
add_jump( $filter_table->{$chain}, 'accounting', 0, '', 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ our @EXPORT = qw( merge_levels
|
||||
$macro_commands
|
||||
);
|
||||
our @EXPORT_OK = qw( initialize );
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
#
|
||||
# Used Actions. Each action that is actually used has an entry with value 1.
|
||||
@ -305,10 +305,10 @@ sub map_old_actions( $ ) {
|
||||
# Create and record a log action chain -- Log action chains have names
|
||||
# that are formed from the action name by prepending a "%" and appending
|
||||
# a 1- or 2-digit sequence number. In the functions that follow,
|
||||
# the CHAIN, LEVEL and TAG variable serves as arguments to the user's
|
||||
# the $chain, $level and $tag variable serves as arguments to the user's
|
||||
# exit. We call the exit corresponding to the name of the action but we
|
||||
# set CHAIN to the name of the iptables chain where rules are to be added.
|
||||
# Similarly, LEVEL and TAG contain the log level and log tag respectively.
|
||||
# set $chain to the name of the iptables chain where rules are to be added.
|
||||
# Similarly, $level and $tag contain the log level and log tag respectively.
|
||||
#
|
||||
# The maximum length of a chain name is 30 characters -- since the log
|
||||
# action chain name is 2-3 characters longer than the base chain name,
|
||||
@ -341,6 +341,8 @@ sub createlogactionchain( $$ ) {
|
||||
|
||||
unless ( $targets{$action} & BUILTIN ) {
|
||||
|
||||
dont_optimize $chainref;
|
||||
|
||||
my $file = find_file $chain;
|
||||
|
||||
if ( -f $file ) {
|
||||
@ -367,6 +369,8 @@ sub createsimpleactionchain( $ ) {
|
||||
|
||||
unless ( $targets{$action} & BUILTIN ) {
|
||||
|
||||
dont_optimize $chainref;
|
||||
|
||||
my $file = find_file $action;
|
||||
|
||||
if ( -f $file ) {
|
||||
@ -384,7 +388,7 @@ sub createsimpleactionchain( $ ) {
|
||||
}
|
||||
|
||||
#
|
||||
# Create an action chain and run it's associated user exit
|
||||
# Create an action chain and run its associated user exit
|
||||
#
|
||||
sub createactionchain( $ ) {
|
||||
my ( $action , $level ) = split_action $_[0];
|
||||
@ -574,7 +578,7 @@ sub process_actions2 () {
|
||||
for my $target (keys %usedactions) {
|
||||
my ($action, $level) = split_action $target;
|
||||
my $actionref = $actions{$action};
|
||||
fatal_error "Null Action Reference in process_actions2" unless $actionref;
|
||||
assert( $actionref );
|
||||
for my $action1 ( keys %{$actionref->{requires}} ) {
|
||||
my $action2 = merge_levels $target, $action1;
|
||||
unless ( $usedactions{ $action2 } ) {
|
||||
@ -834,15 +838,15 @@ sub allowBcast( $$$ ) {
|
||||
sub dropNotSyn ( $$$ ) {
|
||||
my ($chainref, $level, $tag) = @_;
|
||||
|
||||
log_rule_limit $level, $chainref, 'dropNotSyn' , 'DROP', '', $tag, 'add', '-p tcp ! --syn ' if $level ne '';
|
||||
add_rule $chainref , '-p tcp ! --syn -j DROP';
|
||||
log_rule_limit $level, $chainref, 'dropNotSyn' , 'DROP', '', $tag, 'add', '-p 6 ! --syn ' if $level ne '';
|
||||
add_rule $chainref , '-p 6 ! --syn -j DROP';
|
||||
}
|
||||
|
||||
sub rejNotSyn ( $$$ ) {
|
||||
my ($chainref, $level, $tag) = @_;
|
||||
|
||||
log_rule_limit $level, $chainref, 'rejNotSyn' , 'REJECT', '', $tag, 'add', '-p tcp ! --syn ' if $level ne '';
|
||||
add_rule $chainref , '-p tcp ! --syn -j REJECT --reject-with tcp-reset';
|
||||
log_rule_limit $level, $chainref, 'rejNotSyn' , 'REJECT', '', $tag, 'add', '-p 6 ! --syn ' if $level ne '';
|
||||
add_rule $chainref , '-p 6 ! --syn -j REJECT --reject-with tcp-reset';
|
||||
}
|
||||
|
||||
sub dropInvalid ( $$$ ) {
|
||||
@ -860,18 +864,19 @@ sub allowInvalid ( $$$ ) {
|
||||
}
|
||||
|
||||
sub forwardUPnP ( $$$ ) {
|
||||
dont_optimize 'forwardUPnP';
|
||||
}
|
||||
|
||||
sub allowinUPnP ( $$$ ) {
|
||||
my ($chainref, $level, $tag) = @_;
|
||||
|
||||
if ( $level ne '' ) {
|
||||
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p udp --dport 1900 ';
|
||||
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p tcp --dport 49152 ';
|
||||
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p 17 --dport 1900 ';
|
||||
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p 6 --dport 49152 ';
|
||||
}
|
||||
|
||||
add_rule $chainref, '-p udp --dport 1900 -j ACCEPT';
|
||||
add_rule $chainref, '-p tcp --dport 49152 -j ACCEPT';
|
||||
add_rule $chainref, '-p 17 --dport 1900 -j ACCEPT';
|
||||
add_rule $chainref, '-p 6 --dport 49152 -j ACCEPT';
|
||||
}
|
||||
|
||||
sub Limit( $$$ ) {
|
||||
@ -897,7 +902,7 @@ sub Limit( $$$ ) {
|
||||
my $xchainref = new_chain 'filter' , "$chainref->{name}%";
|
||||
log_rule_limit $level, $xchainref, $tag[0], 'DROP', '', '', 'add', '';
|
||||
add_rule $xchainref, '-j DROP';
|
||||
add_rule $chainref, "-m recent --name $set --update --seconds $tag[2] --hitcount $count -j $xchainref->{name}";
|
||||
add_jump $chainref, $xchainref, 0, "-m recent --name $set --update --seconds $tag[2] --hitcount $count ";
|
||||
} else {
|
||||
add_rule $chainref, "-m recent --update --name $set --seconds $tag[2] --hitcount $count -j DROP";
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -42,6 +42,9 @@ our @EXPORT = qw(
|
||||
new_manual_chain
|
||||
ensure_manual_chain
|
||||
log_rule_limit
|
||||
dont_optimize
|
||||
dont_delete
|
||||
dont_move
|
||||
|
||||
%chain_table
|
||||
$raw_table
|
||||
@ -113,6 +116,8 @@ our %EXPORT_TAGS = (
|
||||
new_nat_chain
|
||||
ensure_filter_chain
|
||||
finish_section
|
||||
optimize_chain
|
||||
optimize_ruleset
|
||||
setup_zone_mss
|
||||
newexclusionchain
|
||||
newnonatchain
|
||||
@ -168,7 +173,7 @@ our %EXPORT_TAGS = (
|
||||
|
||||
Exporter::export_ok_tags('internal');
|
||||
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
#
|
||||
# Chain Table
|
||||
@ -181,6 +186,9 @@ our $VERSION = '4.4_6';
|
||||
# builtin => undef|1 -- If 1, one of Netfilter's built-in chains.
|
||||
# manual => undef|1 -- If 1, a manual chain.
|
||||
# accounting => undef|1 -- If 1, an accounting chain
|
||||
# dont_optimize=> undef|1 -- Don't optimize away if this chain is 'short'
|
||||
# dont_delete => undef|1 -- Don't delete if this chain is not referenced
|
||||
# dont_move => undef|1 -- Don't copy the rules of this chain somewhere else
|
||||
# log => <logging rule number for use when LOGRULENUMBERS>
|
||||
# policy => <policy>
|
||||
# policychain => <name of policy chain> -- self-reference if this is a policy chain
|
||||
@ -195,6 +203,8 @@ our $VERSION = '4.4_6';
|
||||
# <rule2>
|
||||
# ...
|
||||
# ]
|
||||
# logchains => { <key1> = <chainref1>, ... }
|
||||
# references => { <ref1> => <refs>, <ref2> => <refs>, ... }
|
||||
# } ,
|
||||
# <chain2> => ...
|
||||
# }
|
||||
@ -362,7 +372,9 @@ sub initialize( $ ) {
|
||||
$idiotcount = 0;
|
||||
$idiotcount1 = 0;
|
||||
$warningcount = 0;
|
||||
|
||||
#
|
||||
# The chain table is initialized via a call to initialize_chain_table() after the configuration and capabilities have been determined.
|
||||
#
|
||||
}
|
||||
|
||||
#
|
||||
@ -541,40 +553,14 @@ sub add_rule($$;$)
|
||||
}
|
||||
|
||||
#
|
||||
# Add a jump from the chain represented by the reference in the first argument to
|
||||
# the target in the second argument. The third argument determines if a GOTO may be
|
||||
# used rather than a jump. The optional fourth argument specifies any matches to be
|
||||
# included in the rule and must end with a space character if it is non-null. The
|
||||
# optional 5th argument causes long port lists to be split.
|
||||
# Make the first chain a referent of the second
|
||||
#
|
||||
sub add_reference ( $$ ) {
|
||||
my ( $fromref, $to ) = @_;
|
||||
|
||||
sub add_jump( $$$;$$ ) {
|
||||
my ( $fromref, $to, $goto_ok, $predicate, $expandports ) = @_;
|
||||
my $toref = reftype $to ? $to : $chain_table{$fromref->{table}}{$to};
|
||||
|
||||
$predicate |= '';
|
||||
|
||||
my $toref;
|
||||
#
|
||||
# The second argument may be a scalar (chain name or builtin target) or a chain reference
|
||||
#
|
||||
if ( reftype $to ) {
|
||||
$toref = $to;
|
||||
$to = $toref->{name};
|
||||
} else {
|
||||
#
|
||||
# Ensure that we have the chain unless it is a builtin like 'ACCEPT'
|
||||
#
|
||||
$toref = ensure_chain( $fromref->{table} , $to ) unless $builtin_target{ $to };
|
||||
}
|
||||
|
||||
#
|
||||
# If the destination is a chain, mark it referenced
|
||||
#
|
||||
$toref->{referenced} = 1 if $toref;
|
||||
|
||||
my $param = $goto_ok && $toref && $capabilities{GOTO_TARGET} ? 'g' : 'j';
|
||||
|
||||
add_rule ($fromref, join( '', $predicate, "-$param $to" ), $expandports || 0 );
|
||||
$toref->{references}{$fromref->{name}}++;
|
||||
}
|
||||
|
||||
#
|
||||
@ -586,7 +572,7 @@ sub purge_jump ( $$ ) {
|
||||
my $to = $toref->{name};
|
||||
|
||||
for ( @{$fromref->{rules}} ) {
|
||||
$_ = undef if / -[gj] ${to}\b/;
|
||||
$_ = undef if defined && / -[gj] ${to}\b/;
|
||||
}
|
||||
|
||||
$toref->{referenced} = 0 unless @{$toref->{rules}};
|
||||
@ -621,6 +607,49 @@ sub insert_rule($$$) {
|
||||
insert_rule1( $chainref, $number - 1, $rule );
|
||||
}
|
||||
|
||||
#
|
||||
# Add a jump from the chain represented by the reference in the first argument to
|
||||
# the target in the second argument. The third argument determines if a GOTO may be
|
||||
# used rather than a jump. The optional fourth argument specifies any matches to be
|
||||
# included in the rule and must end with a space character if it is non-null. The
|
||||
# optional 5th argument causes long port lists to be split. The optional 6th
|
||||
# argument, if passed, gives the 0-relative index where the jump is to be inserted.
|
||||
#
|
||||
|
||||
sub add_jump( $$$;$$$ ) {
|
||||
my ( $fromref, $to, $goto_ok, $predicate, $expandports, $index ) = @_;
|
||||
|
||||
$predicate |= '';
|
||||
|
||||
my $toref;
|
||||
#
|
||||
# The second argument may be a scalar (chain name or builtin target) or a chain reference
|
||||
#
|
||||
if ( reftype $to ) {
|
||||
$toref = $to;
|
||||
$to = $toref->{name};
|
||||
} else {
|
||||
#
|
||||
# Ensure that we have the chain unless it is a builtin like 'ACCEPT'
|
||||
#
|
||||
$toref = ensure_chain( $fromref->{table} , $to ) unless $builtin_target{ $to };
|
||||
}
|
||||
|
||||
#
|
||||
# If the destination is a chain, mark it referenced
|
||||
#
|
||||
$toref->{referenced} = 1, add_reference $fromref, $toref if $toref;
|
||||
|
||||
my $param = $goto_ok && $toref && $capabilities{GOTO_TARGET} ? 'g' : 'j';
|
||||
|
||||
if ( defined $index ) {
|
||||
assert( ! $expandports );
|
||||
insert_rule1( $fromref, $index, join( '', $predicate, "-$param $to" ));
|
||||
} else {
|
||||
add_rule ($fromref, join( '', $predicate, "-$param $to" ), $expandports || 0 );
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Insert a tunnel rule into the passed chain. Tunnel rules are inserted sequentially
|
||||
# at the beginning of the 'NEW' section.
|
||||
@ -643,6 +672,8 @@ sub move_rules( $$ ) {
|
||||
|
||||
if ( $chain1->{referenced} ) {
|
||||
my $name = $chain1->{name};
|
||||
my $rules = $chain2->{rules};
|
||||
my $count = @{$chain1->{rules}};
|
||||
#
|
||||
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
||||
#
|
||||
@ -650,11 +681,52 @@ sub move_rules( $$ ) {
|
||||
|
||||
( s/\-([AI]) $name /-$1 $chain2->{name} / ) for @{$chain1->{rules}};
|
||||
|
||||
splice @{$chain2->{rules}}, 0, 0, @{$chain1->{rules}};
|
||||
splice @{$rules}, 0, 0, @{$chain1->{rules}};
|
||||
#
|
||||
# In a firewall->x policy chain, multiple DHCP ACCEPT rules can be moved to the head of the chain.
|
||||
# This hack avoids that.
|
||||
#
|
||||
shift @{$rules} if @{$rules} > 1 && $rules->[0] eq $rules->[1];
|
||||
|
||||
$chain2->{referenced} = 1;
|
||||
$chain1->{referenced} = 0;
|
||||
$chain1->{rules} = [];
|
||||
$count;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Replace the jump at the end of one chain (chain2) with the rules from another chain (chain1).
|
||||
#
|
||||
|
||||
sub copy_rules( $$ ) {
|
||||
my ($chain1, $chain2 ) = @_;
|
||||
|
||||
my $name1 = $chain1->{name};
|
||||
my $name2 = $chain2->{name};
|
||||
my @rules = @{$chain1->{rules}};
|
||||
my $rules = $chain2->{rules};
|
||||
my $count = @{$chain1->{rules}};
|
||||
#
|
||||
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
||||
#
|
||||
$name1 =~ s/\+/\\+/;
|
||||
|
||||
( s/\-([AI]) $name1(\b)/-$1 ${name2}$2/ ) for @rules;
|
||||
|
||||
pop @$rules; # Delete the jump to chain1
|
||||
|
||||
push @$rules, @rules;
|
||||
#
|
||||
# Add chain1's references to $chain2
|
||||
#
|
||||
$chain2->{references}{$_} += $chain1->{references}{$_} for keys %{$chain1->{references}};
|
||||
|
||||
progress_message " $count rules from $chain1->{name} appended to $chain2->{name}";
|
||||
|
||||
unless ( --$chain1->{references}{$name2} ) {
|
||||
delete $chain1->{references}{$name2};
|
||||
$chain1->{referenced} = 0, progress_message " Unreferenced chain $name1 deleted" unless keys %{$chain1->{references}};
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,12 +966,13 @@ sub new_chain($$)
|
||||
|
||||
assert( $chain_table{$table} && ! ( $chain_table{$table}{$chain} || $builtin_target{ $chain } ) );
|
||||
|
||||
$chain_table{$table}{$chain} = { name => $chain,
|
||||
rules => [],
|
||||
table => $table,
|
||||
loglevel => '',
|
||||
log => 1,
|
||||
cmdlevel => 0 };
|
||||
$chain_table{$table}{$chain} = { name => $chain,
|
||||
rules => [],
|
||||
table => $table,
|
||||
loglevel => '',
|
||||
log => 1,
|
||||
cmdlevel => 0,
|
||||
references => {} };
|
||||
}
|
||||
|
||||
#
|
||||
@ -916,6 +989,45 @@ sub ensure_chain($$)
|
||||
$ref ? $ref : new_chain $table, $chain;
|
||||
}
|
||||
|
||||
#
|
||||
# Set the dont_optimize flag for a chain
|
||||
#
|
||||
sub dont_optimize( $ ) {
|
||||
my $chain = shift;
|
||||
|
||||
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
|
||||
|
||||
$chainref->{dont_optimize} = 1;
|
||||
|
||||
$chainref;
|
||||
}
|
||||
|
||||
#
|
||||
# Set the dont_optimize and dont_delete flags for a chain
|
||||
#
|
||||
sub dont_delete( $ ) {
|
||||
my $chain = shift;
|
||||
|
||||
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
|
||||
|
||||
$chainref->{dont_optimize} = $chainref->{dont_delete} = 1;
|
||||
|
||||
$chainref;
|
||||
}
|
||||
|
||||
#
|
||||
# Set the dont_move flag for a chain
|
||||
#
|
||||
sub dont_move( $ ) {
|
||||
my $chain = shift;
|
||||
|
||||
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
|
||||
|
||||
$chainref->{dont_move} = 1;
|
||||
|
||||
$chainref;
|
||||
}
|
||||
|
||||
sub finish_chain_section( $$ );
|
||||
|
||||
#
|
||||
@ -957,6 +1069,7 @@ sub ensure_accounting_chain( $ )
|
||||
$chainref = new_chain 'filter' , $chain;
|
||||
$chainref->{accounting} = 1;
|
||||
$chainref->{referenced} = 1;
|
||||
$chainref->{dont_optimize} = 1 unless $config{OPTIMIZE_ACCOUNTING};
|
||||
|
||||
if ( $chain ne 'accounting' ) {
|
||||
my $file = find_file $chain;
|
||||
@ -1010,9 +1123,11 @@ sub new_builtin_chain($$$)
|
||||
my ( $table, $chain, $policy ) = @_;
|
||||
|
||||
my $chainref = new_chain $table, $chain;
|
||||
$chainref->{referenced} = 1;
|
||||
$chainref->{policy} = $policy;
|
||||
$chainref->{builtin} = 1;
|
||||
$chainref->{referenced} = 1;
|
||||
$chainref->{policy} = $policy;
|
||||
$chainref->{builtin} = 1;
|
||||
$chainref->{dont_delete} = 1;
|
||||
$chainref->{dont_move} = 1;
|
||||
$chainref;
|
||||
}
|
||||
|
||||
@ -1188,6 +1303,335 @@ sub finish_section ( $ ) {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Delete redundant ACCEPT rules from the end of a policy chain whose policy is ACCEPT
|
||||
#
|
||||
sub optimize_chain( $ ) {
|
||||
my $chainref = shift;
|
||||
|
||||
if ( $chainref->{referenced} ) {
|
||||
my $rules = $chainref->{rules};
|
||||
my $count = 0;
|
||||
|
||||
pop @$rules;
|
||||
|
||||
pop @$rules, $count++ while @$rules && $rules->[-1] =~ /-j ACCEPT/;
|
||||
|
||||
if ( @${rules} ) {
|
||||
add_rule $chainref, '-j ACCEPT';
|
||||
progress_message " $count ACCEPT rules deleted from policy chain $chainref->{name}" if $count;
|
||||
} else {
|
||||
#
|
||||
# The chain is now empty -- change all references to ACCEPT
|
||||
#
|
||||
$count = 0;
|
||||
|
||||
for my $fromref ( map $filter_table->{$_} , keys %{$chainref->{references}} ) {
|
||||
defined && s/ -[jg] $chainref->{name}$/ -j ACCEPT/ && $count++ for @{$fromref->{rules}};
|
||||
}
|
||||
|
||||
progress_message " $count references to ACCEPT policy chain $chainref->{name} replaced";
|
||||
$chainref->{referenced} = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Delete the references to the passed chain
|
||||
#
|
||||
|
||||
sub delete_references( $ ) {
|
||||
my $chainref = shift;
|
||||
my $table = $chainref->{table};
|
||||
my $count = 0;
|
||||
|
||||
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
|
||||
for ( @{$fromref->{rules}} ) {
|
||||
$_ = undef, $count++ if defined && / -[jg] $chainref->{name}$/;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $count ) {
|
||||
progress_message " $count references to empty chain $chainref->{name} deleted";
|
||||
} else {
|
||||
progress_message " Empty chain $chainref->{name} deleted";
|
||||
}
|
||||
|
||||
$chainref->{referenced} = 0;
|
||||
|
||||
$count;
|
||||
}
|
||||
|
||||
#
|
||||
# Replace jumps to the passed chain with jumps to the passed target
|
||||
#
|
||||
sub replace_references( $$ ) {
|
||||
my ( $chainref, $target ) = @_;
|
||||
my $table = $chainref->{table};
|
||||
my $count = 0;
|
||||
|
||||
if ( defined $chain_table{$table}{$target} && ! $chain_table{$table}{$target}{builtin} ) {
|
||||
#
|
||||
# The target is a chain -- use the jump type from each referencing rule
|
||||
#
|
||||
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
|
||||
if ( $fromref->{referenced} ) {
|
||||
defined && s/ -([jg]) $chainref->{name}(\b)/ -$1 ${target}$2/ && $count++ for @{$fromref->{rules}};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# The target is a builtin -- we must use '-j'
|
||||
#
|
||||
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
|
||||
if ( $fromref->{referenced} ) {
|
||||
defined && s/ -[jg] $chainref->{name}(\b)/ -j ${target}$1/ && $count++ for @{$fromref->{rules}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress_message " $count references to 1-rule chain $chainref->{name} replaced" if $count;
|
||||
|
||||
$chainref->{referenced} = 0;
|
||||
}
|
||||
|
||||
#
|
||||
# Replace jumps to the passed chain with jumps to the passed target while
|
||||
# adding the passed matches to the rule.
|
||||
#
|
||||
sub replace_references1( $$$ ) {
|
||||
my ( $chainref, $target, $matches ) = @_;
|
||||
my $table = $chainref->{table};
|
||||
my $count = 0;
|
||||
#
|
||||
# Note: If $matches is non-empty, then it begins with white space
|
||||
#
|
||||
if ( defined $chain_table{$table}{$target} && ! $chain_table{$table}{$target}{builtin} ) {
|
||||
#
|
||||
# The target is a chain -- use the jump type from each referencing rule
|
||||
#
|
||||
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
|
||||
if ( $fromref->{referenced} ) {
|
||||
for ( @{$fromref->{rules}} ) {
|
||||
if ( defined && /^-A $fromref->{name} .*-[jg] $chainref->{name}\b/ ) {
|
||||
#
|
||||
# Prevent multiple '-p' matches
|
||||
#
|
||||
s/ -p [^ ]+ / / if / -p / && $matches =~ / -p /;
|
||||
s/\s+-([jg]) $chainref->{name}(\b)/$matches -$1 ${target}$2/;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# The target is a builtin -- we must use '-j'
|
||||
#
|
||||
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
|
||||
if ( $fromref->{referenced} ) {
|
||||
for ( @{$fromref->{rules}} ) {
|
||||
if ( defined && /^-A $fromref->{name} .*-[jg] $chainref->{name}\b/ ) {
|
||||
#
|
||||
# Prevent multiple '-p' matches
|
||||
#
|
||||
s/ -p [^ ]+ / / if / -p / && $matches =~ / -p /;
|
||||
s/\s+-[jg] $chainref->{name}(\b)/$matches -j ${target}$1/;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress_message " $count references to 1-rule chain $chainref->{name} replaced" if $count;
|
||||
|
||||
$chainref->{referenced} = 0;
|
||||
}
|
||||
|
||||
#
|
||||
# The passed builtin chain has a single rule. If the target is a user chain without 'dont"move', move the rules from the
|
||||
# chain to the builtin and return true; otherwise, do nothing and return false.
|
||||
#
|
||||
sub conditionally_move_rules( $$ ) {
|
||||
my ( $chainref, $target ) = @_;
|
||||
|
||||
if ( $target =~ /^\s*([^\s]+)/ ) {
|
||||
#
|
||||
# The above test is simply to isolate the basic target in $1
|
||||
#
|
||||
my $basictarget = $1;
|
||||
my $targetref = $chain_table{$chainref->{table}}{$basictarget};
|
||||
|
||||
if ( $targetref && ! $targetref->{dont_move} ) {
|
||||
#
|
||||
# Move is safe -- start with an empty rule list
|
||||
#
|
||||
$chainref->{rules} = [];
|
||||
my $count = move_rules( $targetref, $chainref );
|
||||
progress_message " $count rules moved from chain $targetref->{name} to chain $chainref->{name}" if $count;
|
||||
1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Perform Optimization
|
||||
#
|
||||
sub optimize_ruleset() {
|
||||
#
|
||||
# Make repeated passes through each table looking for short chains (those with less than 2 entries)
|
||||
#
|
||||
# When an unreferenced chain is found, it is deleted unless its 'dont_delete' flag is set.
|
||||
# When an empty chain is found, delete the references to it.
|
||||
# When a chain with a single entry is found, replace it's references by its contents
|
||||
#
|
||||
# The search continues until no short chains remain
|
||||
# Chains with 'dont_optimize = 1' are exempted from optimization
|
||||
#
|
||||
for my $table ( qw/ raw mangle nat filter/ ) {
|
||||
|
||||
next if $family == F_IPV6 && $table eq 'nat';
|
||||
|
||||
my $progress = 1;
|
||||
my $passes = 0;
|
||||
|
||||
while ( $progress ) {
|
||||
$progress = 0;
|
||||
$passes++;
|
||||
|
||||
for my $chainref ( grep $_->{referenced}, values %{$chain_table{$table}} ) {
|
||||
#
|
||||
# If the chain isn't branched to, then delete it
|
||||
#
|
||||
unless ( $chainref->{dont_delete} || keys %{$chainref->{references}} ) {
|
||||
$chainref->{referenced} = 0;
|
||||
progress_message " Unreferenced chain $chainref->{name} deleted";
|
||||
next;
|
||||
}
|
||||
|
||||
unless ( $chainref->{dont_optimize} ) {
|
||||
#
|
||||
# Next count the rules -- we must do that because
|
||||
# we delete rules by setting them
|
||||
# to nil.
|
||||
my $numrules = 0;
|
||||
my $firstrule;
|
||||
my $lastrule;
|
||||
|
||||
for ( @{$chainref->{rules}} ) {
|
||||
if ( defined ) {
|
||||
$numrules++;
|
||||
$lastrule = $_;
|
||||
$firstrule = $_ unless defined $firstrule;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $numrules == 0 ) {
|
||||
#
|
||||
# No rules in this chain
|
||||
#
|
||||
if ( $chainref->{builtin} ) {
|
||||
#
|
||||
# Built-in -- mark it 'dont_optimize' so we ignore it in follow-on passes
|
||||
#
|
||||
$chainref->{dont_optimize} = 1;
|
||||
} else {
|
||||
#
|
||||
# Not a built-in -- we can delete it and it's references
|
||||
#
|
||||
delete_references $chainref;
|
||||
$progress = 1;
|
||||
}
|
||||
} elsif ( $numrules == 1 ) {
|
||||
#
|
||||
# Chain has a single non-nil rule which is in $firstrule
|
||||
#
|
||||
if ( $firstrule =~ /^-A $chainref->{name} -[jg] (.*)$/ ) {
|
||||
#
|
||||
# Easy case -- the rule is a simple jump
|
||||
#
|
||||
if ( $chainref->{builtin} ) {
|
||||
#
|
||||
# A built-in chain. If the target is a user chain without 'dont_move',
|
||||
# we can move its rules to the built-in
|
||||
#
|
||||
if ( conditionally_move_rules $chainref, $1 ) {
|
||||
#
|
||||
# Target was a user chain -- rules moved
|
||||
#
|
||||
$progress = 1;
|
||||
} else {
|
||||
#
|
||||
# Target was a built-in. Ignore this chain in follow-on passes
|
||||
#
|
||||
$chainref->{dont_optimize} = 1;
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# Replace all references to this chain with references to the target
|
||||
#
|
||||
replace_references $chainref, $1;
|
||||
$progress = 1;
|
||||
}
|
||||
} elsif ( $firstrule =~ /-A $chainref->{name}( .*) -[jg] (.*)$/ ) {
|
||||
#
|
||||
# Not so easy -- the rule contains matches
|
||||
#
|
||||
if ( $chainref->{builtin} ) {
|
||||
#
|
||||
# This case requires a new rule merging algorithm. Ignore this chain for
|
||||
# now.
|
||||
#
|
||||
$chainref->{dont_optimize} = 1;
|
||||
} else {
|
||||
#
|
||||
# Replace references to this chain with the target and add the predicates
|
||||
#
|
||||
replace_references1 $chainref, $2, $1;
|
||||
$progress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# In this loop, we look for chains that end in an unconditional jump. If the target of the jump
|
||||
# is subject to optimization (dont_optimize = false), the jump is replaced by target's rules.
|
||||
#
|
||||
$progress = 1;
|
||||
|
||||
while ( $progress ) {
|
||||
$progress = 0;
|
||||
$passes++;
|
||||
|
||||
for my $chainref ( grep $_->{referenced}, values %{$chain_table{$table}} ) {
|
||||
my $lastrule;
|
||||
|
||||
for ( @{$chainref->{rules}} ) {
|
||||
$lastrule = $_ if defined;
|
||||
}
|
||||
|
||||
if ( defined $lastrule && $lastrule =~ /^-A $chainref->{name} -[jg] (.*)$/ ) {
|
||||
#
|
||||
# Last rule is a simple branch
|
||||
my $targetref = $chain_table{$table}{$1};
|
||||
|
||||
if ( $targetref && ! ( $targetref->{builtin} || $targetref->{dont_move} ) ) {
|
||||
copy_rules( $targetref, $chainref );
|
||||
$progress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress_message " Table $table Optimized -- Passes = $passes";
|
||||
progress_message '';
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Helper for set_mss
|
||||
#
|
||||
@ -1242,6 +1686,39 @@ sub newlogchain() {
|
||||
"log${seq}";
|
||||
}
|
||||
|
||||
#
|
||||
# If there is already a logging chain associated with the passed rules chain that matches these
|
||||
# parameters, then return a reference to it.
|
||||
#
|
||||
# Otherwise, create such a chain and store a reference in chainref's 'logchains' hash. Return the
|
||||
# reference.
|
||||
#
|
||||
sub logchain( $$$$$$ ) {
|
||||
my ( $chainref, $loglevel, $logtag, $exceptionrule, $disposition, $target ) = @_;
|
||||
my $key = join( ':', $loglevel, $logtag, $exceptionrule, $disposition, $target );
|
||||
my $logchainref = $chainref->{logchains}{$key};
|
||||
|
||||
unless ( $logchainref ) {
|
||||
$logchainref = $chainref->{logchains}{$key} = new_chain $chainref->{table}, newlogchain;
|
||||
#
|
||||
# Now add the log rule and target rule without matches to the log chain.
|
||||
#
|
||||
log_rule_limit(
|
||||
$loglevel ,
|
||||
$logchainref ,
|
||||
$chainref->{name} ,
|
||||
$disposition ,
|
||||
'',
|
||||
$logtag,
|
||||
'add',
|
||||
'' );
|
||||
|
||||
add_rule( $logchainref, $exceptionrule . $target );
|
||||
}
|
||||
|
||||
$logchainref;
|
||||
}
|
||||
|
||||
sub newnonatchain() {
|
||||
my $seq = $chainseq++;
|
||||
"nonat${seq}";
|
||||
@ -1915,7 +2392,7 @@ sub match_ipsec_out( $$ ) {
|
||||
# Generate a log message
|
||||
#
|
||||
sub log_rule_limit( $$$$$$$$ ) {
|
||||
my ($level, $chainref, $chain, $disposition, $limit, $tag, $command, $predicates ) = @_;
|
||||
my ($level, $chainref, $chain, $disposition, $limit, $tag, $command, $matches ) = @_;
|
||||
|
||||
my $prefix = '';
|
||||
|
||||
@ -1923,11 +2400,11 @@ sub log_rule_limit( $$$$$$$$ ) {
|
||||
|
||||
return 1 if $level eq '';
|
||||
|
||||
$predicates .= ' ' if $predicates && substr( $predicates, -1, 1 ) ne ' ';
|
||||
$matches .= ' ' if $matches && substr( $matches, -1, 1 ) ne ' ';
|
||||
|
||||
unless ( $predicates =~ /-m limit / ) {
|
||||
unless ( $matches =~ /-m limit / ) {
|
||||
$limit = $globals{LOGLIMIT} unless $limit && $limit ne '-';
|
||||
$predicates .= $limit if $limit;
|
||||
$matches .= $limit if $limit;
|
||||
}
|
||||
|
||||
if ( $config{LOGFORMAT} =~ /^\s*$/ ) {
|
||||
@ -1976,28 +2453,28 @@ sub log_rule_limit( $$$$$$$$ ) {
|
||||
}
|
||||
|
||||
if ( $command eq 'add' ) {
|
||||
add_rule ( $chainref, $predicates . $prefix , 1 );
|
||||
add_rule ( $chainref, $matches . $prefix , 1 );
|
||||
} else {
|
||||
insert_rule1 ( $chainref , 0 , $predicates . $prefix );
|
||||
insert_rule1 ( $chainref , 0 , $matches . $prefix );
|
||||
}
|
||||
}
|
||||
|
||||
sub log_rule( $$$$ ) {
|
||||
my ( $level, $chainref, $disposition, $predicates ) = @_;
|
||||
my ( $level, $chainref, $disposition, $matches ) = @_;
|
||||
|
||||
log_rule_limit $level, $chainref, $chainref->{name} , $disposition, $globals{LOGLIMIT}, '', 'add', $predicates;
|
||||
log_rule_limit $level, $chainref, $chainref->{name} , $disposition, $globals{LOGLIMIT}, '', 'add', $matches;
|
||||
}
|
||||
|
||||
#
|
||||
# If the destination chain exists, then at the end of the source chain add a jump to the destination.
|
||||
#
|
||||
sub addnatjump( $$$ ) {
|
||||
my ( $source , $dest, $predicates ) = @_;
|
||||
my ( $source , $dest, $matches ) = @_;
|
||||
|
||||
my $destref = $nat_table->{$dest} || {};
|
||||
|
||||
if ( $destref->{referenced} ) {
|
||||
add_rule $nat_table->{$source} , $predicates . "-j $dest";
|
||||
add_jump $nat_table->{$source} , $dest , 0, $matches;
|
||||
} else {
|
||||
clearrule;
|
||||
}
|
||||
@ -2371,7 +2848,7 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
$origdest, # ORIGINAL DEST
|
||||
$target, # Target ('-j' part of the rule)
|
||||
$loglevel , # Log level (and tag)
|
||||
$disposition, # Primative part of the target (RETURN, ACCEPT, ...)
|
||||
$disposition, # Primtive part of the target (RETURN, ACCEPT, ...)
|
||||
$exceptionrule,# Caller's matches used in exclusion case
|
||||
$logname, # Name of chain to name in log messages
|
||||
) = @_;
|
||||
@ -2424,9 +2901,12 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
#
|
||||
# Mark Target as referenced, if it's a chain
|
||||
#
|
||||
if ( $disposition ) {
|
||||
my $targetref = $chain_table{$chainref->{table}}{$disposition};
|
||||
$targetref->{referenced} = 1 if $targetref;
|
||||
if ( $target =~ /-[jg]\s+([^\s]+)\b/ ) {
|
||||
my $targetref = $chain_table{$chainref->{table}}{$1};
|
||||
if ( $targetref ) {
|
||||
$targetref->{referenced} = 1;
|
||||
add_reference $chainref, $targetref;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
@ -2704,8 +3184,13 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
#
|
||||
fatal_error "Exclusion is not possible in ACCEPT+/CONTINUE/NONAT rules" if $disposition eq 'RETURN';
|
||||
|
||||
#
|
||||
# Create the Exclusion Chain
|
||||
#
|
||||
my $echain = newexclusionchain;
|
||||
|
||||
my $echainref = new_chain $chainref->{table}, $echain;
|
||||
|
||||
#
|
||||
# Use the current rule and send all possible matches to the exclusion chain
|
||||
#
|
||||
@ -2716,16 +3201,11 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
#
|
||||
# We evaluate the source net match in the inner loop to accomodate systems without $capabilities{KLUDGEFREE}
|
||||
#
|
||||
add_rule( $chainref, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet, "-j $echain" ), 1 );
|
||||
add_jump( $chainref, $echainref, 0, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet ), 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Create the Exclusion Chain
|
||||
#
|
||||
my $echainref = new_chain $chainref->{table}, $echain;
|
||||
|
||||
#
|
||||
# Generate RETURNs for each exclusion
|
||||
#
|
||||
@ -2754,33 +3234,20 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
for my $dnet ( mysplit $dnets ) {
|
||||
$source_match = match_source_net( $inet, $restriction ) unless $capabilities{KLUDGEFREE};
|
||||
my $dest_match = match_dest_net( $dnet );
|
||||
my $predicates = join( '', $rule, $source_match, $dest_match, $onet );
|
||||
my $matches = join( '', $rule, $source_match, $dest_match, $onet );
|
||||
|
||||
if ( $loglevel ne '' ) {
|
||||
if ( $disposition ne 'LOG' ) {
|
||||
unless ( $logname ) {
|
||||
#
|
||||
# Create a chain that both logs and applies the target action
|
||||
# Find/Create a chain that both logs and applies the target action
|
||||
# and jump to the log chain if all of the rule's conditions are met
|
||||
#
|
||||
my $logchainref = new_chain $chainref->{table}, newlogchain;
|
||||
#
|
||||
# Jump to the log chain if all of the rule's conditions are met
|
||||
#
|
||||
add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 );
|
||||
#
|
||||
# Now add the log rule and target rule without predicates to the log chain.
|
||||
#
|
||||
log_rule_limit(
|
||||
$loglevel ,
|
||||
$logchainref ,
|
||||
$chain ,
|
||||
$disposition ,
|
||||
'',
|
||||
$logtag,
|
||||
'add',
|
||||
'' );
|
||||
|
||||
add_rule( $logchainref, $exceptionrule . $target );
|
||||
add_jump( $chainref,
|
||||
logchain( $chainref, $loglevel, $logtag, $exceptionrule , $disposition, $target ),
|
||||
$builtin_target{$disposition},
|
||||
$matches,
|
||||
1 );
|
||||
} else {
|
||||
log_rule_limit(
|
||||
$loglevel ,
|
||||
@ -2790,13 +3257,13 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
'',
|
||||
$logtag,
|
||||
'add',
|
||||
$predicates );
|
||||
$matches );
|
||||
|
||||
add_rule( $chainref, $predicates . $target, 1 );
|
||||
add_rule( $chainref, $matches . $target, 1 );
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# The log rule must be added with predicates to the rule chain
|
||||
# The log rule must be added with matches to the rule chain
|
||||
#
|
||||
log_rule_limit(
|
||||
$loglevel ,
|
||||
@ -2806,14 +3273,14 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
'' ,
|
||||
$logtag ,
|
||||
'add' ,
|
||||
$predicates
|
||||
$matches
|
||||
);
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# No logging -- add the target rule with predicates to the rule chain
|
||||
# No logging -- add the target rule with matches to the rule chain
|
||||
#
|
||||
add_rule( $chainref, $predicates . $target , 1 );
|
||||
add_rule( $chainref, $matches . $target , 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -43,7 +43,7 @@ use Shorewall::Raw;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw( compiler EXPORT TIMESTAMP DEBUG );
|
||||
our @EXPORT_OK = qw( $export );
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
our $export;
|
||||
|
||||
@ -816,7 +816,7 @@ sub compiler {
|
||||
#
|
||||
# Accounting.
|
||||
#
|
||||
setup_accounting;
|
||||
setup_accounting if $config{ACCOUNTING};
|
||||
|
||||
if ( $scriptfilename ) {
|
||||
#
|
||||
@ -824,6 +824,18 @@ sub compiler {
|
||||
#
|
||||
generate_matrix;
|
||||
|
||||
if ( $config{OPTIMIZE} & 6 ) {
|
||||
progress_message2 'Optimizing Ruleset...';
|
||||
#
|
||||
# Optimize Policy Chains
|
||||
#
|
||||
optimize_policy_chains if $config{OPTIMIZE} & 2;
|
||||
#
|
||||
# More Optimization
|
||||
#
|
||||
optimize_ruleset if $config{OPTIMIZE} & 4;
|
||||
}
|
||||
|
||||
enable_script;
|
||||
#
|
||||
# I N I T I A L I Z E
|
||||
@ -845,7 +857,7 @@ sub compiler {
|
||||
# S T O P _ F I R E W A L L
|
||||
# (Writes the stop_firewall() function to the compiled script)
|
||||
#
|
||||
compile_stop_firewall( $test );
|
||||
compile_stop_firewall( $test, $export );
|
||||
#
|
||||
# Copy the footer to the script
|
||||
#
|
||||
@ -868,10 +880,26 @@ sub compiler {
|
||||
enable_script, generate_aux_config if $export;
|
||||
} else {
|
||||
#
|
||||
# Checking the configuration only
|
||||
# Just checking the configuration
|
||||
#
|
||||
if ( $preview ) {
|
||||
#
|
||||
# User wishes to preview the ruleset -- generate the rule matrix
|
||||
#
|
||||
generate_matrix;
|
||||
|
||||
if ( $config{OPTIMIZE} & 6 ) {
|
||||
progress_message2 'Optimizing Ruleset...';
|
||||
#
|
||||
# Optimize Policy Chains
|
||||
#
|
||||
optimize_policy_chains if $config{OPTIMIZE} & 2;
|
||||
#
|
||||
# Ruleset Optimization
|
||||
#
|
||||
optimize_ruleset if $config{OPTIMIZE} & 4;
|
||||
}
|
||||
|
||||
preview_netfilter_load;
|
||||
}
|
||||
#
|
||||
|
@ -128,7 +128,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
|
||||
|
||||
Exporter::export_ok_tags('internal');
|
||||
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
#
|
||||
# describe the current command, it's present progressive, and it's completion.
|
||||
@ -445,6 +445,9 @@ sub initialize( $ ) {
|
||||
WIDE_TC_MARKS => undef,
|
||||
TRACK_PROVIDERS => undef,
|
||||
ZONE2ZONE => undef,
|
||||
ACCOUNTING => undef,
|
||||
OPTIMIZE_ACCOUNTING => undef,
|
||||
DYNAMIC_BLACKLIST => undef,
|
||||
#
|
||||
# Packet Disposition
|
||||
#
|
||||
@ -561,6 +564,9 @@ sub initialize( $ ) {
|
||||
WIDE_TC_MARKS => undef,
|
||||
TRACK_PROVIDERS => undef,
|
||||
ZONE2ZONE => undef,
|
||||
ACCOUNTING => undef,
|
||||
OPTIMIZE_ACCOUNTING => undef,
|
||||
DYNAMIC_BLACKLIST => undef,
|
||||
#
|
||||
# Packet Disposition
|
||||
#
|
||||
@ -2517,6 +2523,9 @@ sub get_configuration( $ ) {
|
||||
default_yes_no 'AUTOMAKE' , '';
|
||||
default_yes_no 'WIDE_TC_MARKS' , '';
|
||||
default_yes_no 'TRACK_PROVIDERS' , '';
|
||||
default_yes_no 'ACCOUNTING' , 'Yes';
|
||||
default_yes_no 'OPTIMIZE_ACCOUNTING' , '';
|
||||
default_yes_no 'DYNAMIC_BLACKLIST' , 'Yes';
|
||||
|
||||
numeric_option 'TC_BITS', $config{WIDE_TC_MARKS} ? 14 : 8 , 0;
|
||||
numeric_option 'MASK_BITS', $config{WIDE_TC_MARKS} ? 16 : 8, $config{TC_BITS};
|
||||
@ -2638,7 +2647,7 @@ sub get_configuration( $ ) {
|
||||
|
||||
$val = numeric_value $config{OPTIMIZE};
|
||||
|
||||
fatal_error "Invalid OPTIMIZE value ($config{OPTIMIZE})" unless defined( $val ) && $val >= 0 && $val <= 1;
|
||||
fatal_error "Invalid OPTIMIZE value ($config{OPTIMIZE})" unless defined( $val ) && $val >= 0 && $val <= 7;
|
||||
|
||||
$globals{MARKING_CHAIN} = $config{MARK_IN_FORWARD_CHAIN} ? 'tcfor' : 'tcpre';
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -32,9 +32,9 @@ use Shorewall::Actions;
|
||||
use strict;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain setup_syn_flood_chains save_policies );
|
||||
our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain setup_syn_flood_chains save_policies optimize_policy_chains);
|
||||
our @EXPORT_OK = qw( );
|
||||
our $VERSION = '4.4_4';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
# @policy_chains is a list of references to policy chains in the filter table
|
||||
|
||||
@ -362,7 +362,7 @@ sub policy_rules( $$$$$ ) {
|
||||
|
||||
unless ( $target eq 'NONE' ) {
|
||||
add_rule $chainref, "-d 224.0.0.0/4 -j RETURN" if $dropmulticast && $target ne 'CONTINUE' && $target ne 'ACCEPT';
|
||||
add_rule $chainref, "-j $default" if $default && $default ne 'none';
|
||||
add_jump $chainref, $default, 0 if $default && $default ne 'none';
|
||||
log_rule $loglevel , $chainref , $target , '' if $loglevel ne '';
|
||||
fatal_error "Null target in policy_rules()" unless $target;
|
||||
|
||||
@ -418,10 +418,21 @@ sub apply_policy_rules() {
|
||||
my $provisional = $chainref->{provisional};
|
||||
my $default = $chainref->{default};
|
||||
my $name = $chainref->{name};
|
||||
my $synparms = $chainref->{synparms};
|
||||
|
||||
if ( $policy ne 'NONE' ) {
|
||||
if ( ! $chainref->{referenced} && ( ! $provisional && $policy ne 'CONTINUE' ) ) {
|
||||
ensure_filter_chain $name, 1;
|
||||
unless ( $chainref->{referenced} || $provisional || $policy eq 'CONTINUE' ) {
|
||||
if ( $config{OPTIMIZE} & 2 ) {
|
||||
#
|
||||
# This policy chain is empty and the only thing that we would put in it is
|
||||
# the policy-related stuff. Don't create it if all we are going to put in it
|
||||
# is a single jump. Generate_matrix() will just use the policy target when
|
||||
# needed.
|
||||
#
|
||||
ensure_filter_chain $name, 1 if $default ne 'none' || $loglevel || $synparms || $config{MULTICAST} || ! ( $policy eq 'ACCEPT' || $config{FASTACCEPT} );
|
||||
} else {
|
||||
ensure_filter_chain $name, 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $name =~ /^all[-2]|[-2]all$/ ) {
|
||||
@ -487,4 +498,24 @@ sub setup_syn_flood_chains() {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Optimize Policy chains with ACCEPT policy
|
||||
#
|
||||
sub optimize_policy_chains() {
|
||||
for my $chainref ( grep $_->{policy} eq 'ACCEPT', @policy_chains ) {
|
||||
optimize_chain ( $chainref );
|
||||
}
|
||||
#
|
||||
# Often, fw->all has an ACCEPT policy. This code allows optimization in that case
|
||||
#
|
||||
my $outputrules = $filter_table->{OUTPUT}{rules};
|
||||
|
||||
if ( @{$outputrules} && $outputrules->[-1] =~ /-j ACCEPT/ ) {
|
||||
optimize_chain( $filter_table->{OUTPUT} );
|
||||
}
|
||||
|
||||
progress_message ' Policy chains optimized';
|
||||
progress_message '';
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -46,7 +46,7 @@ our @EXPORT = qw( process_tos
|
||||
compile_stop_firewall
|
||||
);
|
||||
our @EXPORT_OK = qw( process_rule process_rule1 initialize );
|
||||
our $VERSION = '4.4_6';
|
||||
our $VERSION = '4.4_7';
|
||||
|
||||
#
|
||||
# Set to one if we find a SECTION
|
||||
@ -157,8 +157,8 @@ sub process_tos() {
|
||||
}
|
||||
|
||||
unless ( $first_entry ) {
|
||||
add_rule $mangle_table->{$stdchain}, "-j $chain" if $pretosref->{referenced};
|
||||
add_rule $mangle_table->{OUTPUT}, "-j outtos" if $outtosref->{referenced};
|
||||
add_jump( $mangle_table->{$stdchain}, $chain, 0 ) if $pretosref->{referenced};
|
||||
add_jump( $mangle_table->{OUTPUT}, 'outtos', 0 ) if $outtosref->{referenced};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,7 @@ sub add_rule_pair( $$$$ ) {
|
||||
my ($chainref , $predicate , $target , $level ) = @_;
|
||||
|
||||
log_rule( $level, $chainref, "\U$target", $predicate ) if defined $level && $level ne '';
|
||||
add_rule $chainref , "${predicate}-j $target";
|
||||
add_jump( $chainref , $target, 0, $predicate );
|
||||
}
|
||||
|
||||
sub setup_blacklist() {
|
||||
@ -232,7 +232,7 @@ sub setup_blacklist() {
|
||||
|
||||
log_rule_limit( $level , $logchainref , 'blacklst' , $disposition , "$globals{LOGLIMIT}" , '', 'add', '' );
|
||||
|
||||
add_rule $logchainref, "-j $target" ;
|
||||
add_jump $logchainref, $target, 1;
|
||||
|
||||
$target = 'blacklog';
|
||||
}
|
||||
@ -419,17 +419,21 @@ sub setup_mss();
|
||||
sub add_common_rules() {
|
||||
my $interface;
|
||||
my $chainref;
|
||||
my $level;
|
||||
my $target;
|
||||
my $rule;
|
||||
my $list;
|
||||
my $chain;
|
||||
|
||||
new_standard_chain 'dynamic';
|
||||
my $state = $config{BLACKLISTNEWONLY} ? $globals{UNTRACKED} ? '-m state --state NEW,INVALID,UNTRACKED ' : '-m state --state NEW,INVALID ' : '';
|
||||
my $level = $config{BLACKLIST_LOGLEVEL};
|
||||
my $rejectref = dont_move new_standard_chain 'reject';
|
||||
|
||||
my $state = $config{BLACKLISTNEWONLY} ? $globals{UNTRACKED} ? '-m state --state NEW,INVALID,UNTRACKED ' : '-m state --state NEW,INVALID ' : '';
|
||||
|
||||
add_rule $filter_table->{$_}, "$state -j dynamic" for qw( INPUT FORWARD );
|
||||
if ( $config{DYNAMIC_BLACKLIST} ) {
|
||||
add_rule_pair dont_delete( new_standard_chain( 'logdrop' ) ), ' ' , 'DROP' , $level ;
|
||||
add_rule_pair dont_delete( new_standard_chain( 'logreject' ) ), ' ' , 'reject' , $level ;
|
||||
$chainref = dont_optimize( new_standard_chain( 'dynamic' ) );
|
||||
add_jump $filter_table->{$_}, $chainref, 0, $state for qw( INPUT FORWARD );
|
||||
}
|
||||
|
||||
setup_mss;
|
||||
|
||||
@ -437,13 +441,6 @@ sub add_common_rules() {
|
||||
add_rule( $filter_table->{$_} , "-m state --state ESTABLISHED,RELATED -j ACCEPT" ) for qw( INPUT FORWARD OUTPUT );
|
||||
}
|
||||
|
||||
my $rejectref = new_standard_chain 'reject';
|
||||
|
||||
$level = $config{BLACKLIST_LOGLEVEL};
|
||||
|
||||
add_rule_pair new_standard_chain( 'logdrop' ), ' ' , 'DROP' , $level ;
|
||||
add_rule_pair new_standard_chain( 'logreject' ), ' ' , 'reject' , $level ;
|
||||
|
||||
for $interface ( all_interfaces ) {
|
||||
ensure_chain( 'filter', $_ ) for first_chains( $interface ), output_chain( $interface );
|
||||
}
|
||||
@ -591,11 +588,11 @@ sub add_common_rules() {
|
||||
$disposition = $config{TCP_FLAGS_DISPOSITION};
|
||||
}
|
||||
|
||||
add_rule $chainref , "-p tcp --tcp-flags ALL FIN,URG,PSH -j $disposition";
|
||||
add_rule $chainref , "-p tcp --tcp-flags ALL NONE -j $disposition";
|
||||
add_rule $chainref , "-p tcp --tcp-flags SYN,RST SYN,RST -j $disposition";
|
||||
add_rule $chainref , "-p tcp --tcp-flags SYN,FIN SYN,FIN -j $disposition";
|
||||
add_rule $chainref , "-p tcp --syn --sport 0 -j $disposition";
|
||||
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags ALL FIN,URG,PSH ';
|
||||
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags ALL NONE ';
|
||||
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags SYN,RST SYN,RST ';
|
||||
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags SYN,FIN SYN,FIN ';
|
||||
add_jump $chainref , $disposition, 1, '-p tcp --syn --sport 0 ';
|
||||
|
||||
for my $hostref ( @$list ) {
|
||||
my $interface = $hostref->[0];
|
||||
@ -618,12 +615,12 @@ sub add_common_rules() {
|
||||
if ( @$list ) {
|
||||
progress_message2 "$doing UPnP";
|
||||
|
||||
new_nat_chain( 'UPnP' );
|
||||
dont_optimize new_nat_chain( 'UPnP' );
|
||||
|
||||
$announced = 1;
|
||||
|
||||
for $interface ( @$list ) {
|
||||
add_rule $nat_table->{PREROUTING} , match_source_dev ( $interface ) . '-j UPnP';
|
||||
add_jump $nat_table->{PREROUTING} , 'UPnP', 0, match_source_dev ( $interface );
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,7 +703,7 @@ sub setup_mac_lists( $ ) {
|
||||
my $chain = $chainref->{name};
|
||||
|
||||
add_rule $chainref, "-m recent --rcheck --seconds $ttl --name $chain -j RETURN";
|
||||
add_rule $chainref, "-j $chain1ref->{name}";
|
||||
add_jump $chainref, $chain1ref, 0;
|
||||
add_rule $chainref, "-m recent --update --name $chain -j RETURN";
|
||||
add_rule $chainref, "-m recent --set --name $chain";
|
||||
}
|
||||
@ -834,7 +831,7 @@ sub setup_mac_lists( $ ) {
|
||||
run_user_exit2( 'maclog', $chainref );
|
||||
|
||||
log_rule_limit $level, $chainref , $chain , $disposition, '', '', 'add', '' if $level ne '';
|
||||
add_rule $chainref, "-j $target";
|
||||
add_jump $chainref, $target, 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -958,7 +955,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
|
||||
my ( $basictarget, $param ) = get_target_param $action;
|
||||
my $rule = '';
|
||||
my $actionchainref;
|
||||
my $optimize = $wildcard ? ( $basictarget =~ /!$/ ? 0 : $config{OPTIMIZE} ) : 0;
|
||||
my $optimize = $wildcard ? ( $basictarget =~ /!$/ ? 0 : $config{OPTIMIZE} & 1 ) : 0;
|
||||
|
||||
$param = '' unless defined $param;
|
||||
|
||||
@ -1128,7 +1125,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
|
||||
}
|
||||
}
|
||||
|
||||
$chain = rules_chain( ${sourcezone}, ${destzone} );
|
||||
$chain = rules_chain( ${sourcezone}, ${destzone} );
|
||||
#
|
||||
# Ensure that the chain exists but don't mark it as referenced until after optimization is checked
|
||||
#
|
||||
@ -1154,12 +1151,22 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
|
||||
# Mark the chain as referenced and add appropriate rules from earlier sections.
|
||||
#
|
||||
$chainref = ensure_filter_chain $chain, 1;
|
||||
#
|
||||
# Don't let the rules in this chain be moved elsewhere
|
||||
#
|
||||
dont_move $chainref;
|
||||
}
|
||||
|
||||
#
|
||||
# Generate Fixed part of the rule
|
||||
#
|
||||
$rule = join( '', do_proto($proto, $ports, $sports), do_ratelimit( $ratelimit, $basictarget ) , do_user( $user ) , do_test( $mark , $globals{TC_MASK} ) , do_connlimit( $connlimit ), do_time( $time ) );
|
||||
$rule = join( '',
|
||||
do_proto($proto, $ports, $sports),
|
||||
do_ratelimit( $ratelimit, $basictarget ) ,
|
||||
do_user( $user ) ,
|
||||
do_test( $mark , $globals{TC_MASK} ) ,
|
||||
do_connlimit( $connlimit ),
|
||||
do_time( $time ) );
|
||||
|
||||
unless ( $section eq 'NEW' ) {
|
||||
fatal_error "Entries in the $section SECTION of the rules file not permitted with FASTACCEPT=Yes" if $config{FASTACCEPT};
|
||||
@ -1292,7 +1299,11 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
|
||||
# - the target will be ACCEPT.
|
||||
#
|
||||
unless ( $actiontype & NATONLY ) {
|
||||
$rule = join( '', do_proto( $proto, $ports, $sports ), do_ratelimit( $ratelimit, 'ACCEPT' ), do_user $user , do_test( $mark , $globals{TC_MASK} ) );
|
||||
$rule = join( '',
|
||||
do_proto( $proto, $ports, $sports ),
|
||||
do_ratelimit( $ratelimit, 'ACCEPT' ),
|
||||
do_user $user ,
|
||||
do_test( $mark , $globals{TC_MASK} ) );
|
||||
$loglevel = '';
|
||||
$dest = $server;
|
||||
$action = 'ACCEPT';
|
||||
@ -1370,7 +1381,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
|
||||
"-j $tgt",
|
||||
$loglevel ,
|
||||
$log_action ,
|
||||
''
|
||||
'' ,
|
||||
);
|
||||
#
|
||||
# Possible optimization if the rule just generated was a simple jump to the nonat chain
|
||||
@ -1624,7 +1635,7 @@ sub add_interface_jumps {
|
||||
my $fw = firewall_zone;
|
||||
my $chainref = $filter_table->{rules_chain( ${fw}, ${fw} )};
|
||||
|
||||
add_rule $filter_table->{OUTPUT} , "-o lo -j " . ($chainref->{referenced} ? "$chainref->{name}" : 'ACCEPT' );
|
||||
add_jump $filter_table->{OUTPUT} , ($chainref->{referenced} ? $chainref : 'ACCEPT' ), 0, '-o lo ';
|
||||
add_rule $filter_table->{INPUT} , '-i lo -j ACCEPT';
|
||||
}
|
||||
|
||||
@ -1657,7 +1668,8 @@ sub generate_matrix() {
|
||||
if ( $chainref->{policy} ne 'CONTINUE' ) {
|
||||
my $policyref = $filter_table->{$chainref->{policychain}};
|
||||
assert( $policyref );
|
||||
return $policyref->{name};
|
||||
return $policyref->{name} if $policyref ne $chainref;
|
||||
return $chainref->{policy} eq 'REJECT' ? 'reject' : $chainref->{policy};
|
||||
}
|
||||
|
||||
''; # CONTINUE policy
|
||||
@ -1739,7 +1751,7 @@ sub generate_matrix() {
|
||||
#
|
||||
# NOTRACK from firewall
|
||||
#
|
||||
add_rule $raw_table->{OUTPUT}, "-j $notrackref->{name}" if $notrackref->{referenced};
|
||||
add_jump $raw_table->{OUTPUT}, $notrackref, 0 if $notrackref->{referenced};
|
||||
#
|
||||
# Main source-zone matrix-generation loop
|
||||
#
|
||||
@ -1906,7 +1918,7 @@ sub generate_matrix() {
|
||||
my @dest_zones;
|
||||
my $last_chain = '';
|
||||
|
||||
if ( $config{OPTIMIZE} > 0 ) {
|
||||
if ( $config{OPTIMIZE} & 1 ) {
|
||||
my @temp_zones;
|
||||
|
||||
for my $zone1 ( @zones ) {
|
||||
@ -2007,7 +2019,7 @@ sub generate_matrix() {
|
||||
my $match_source_dev = '';
|
||||
my $forwardchainref = $filter_table->{forward_chain $interface};
|
||||
|
||||
if ( use_forward_chain( $interface ) || ( @{$forwardchainref->{rules} } && ! $chainref ) ) {
|
||||
if ( use_forward_chain $interface || ( @{$forwardchainref->{rules} } && ! $chainref ) ) {
|
||||
#
|
||||
# Either we must use the interface's forwarding chain or that chain has rules and we have nowhere to move them
|
||||
#
|
||||
@ -2122,7 +2134,7 @@ sub setup_mss( ) {
|
||||
#
|
||||
# Send all forwarded SYN packets to the 'settcpmss' chain
|
||||
#
|
||||
add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN -j settcpmss";
|
||||
add_jump $filter_table->{FORWARD} , $chainref, 0, '-p tcp --tcp-flags SYN,RST SYN ';
|
||||
|
||||
my $in_match = '';
|
||||
my $out_match = '';
|
||||
@ -2150,8 +2162,8 @@ sub setup_mss( ) {
|
||||
#
|
||||
# Compile the stop_firewall() function
|
||||
#
|
||||
sub compile_stop_firewall( $ ) {
|
||||
my $test = shift;
|
||||
sub compile_stop_firewall( $$ ) {
|
||||
my ( $test, $export ) = @_;
|
||||
|
||||
my $input = $filter_table->{INPUT};
|
||||
my $output = $filter_table->{OUTPUT};
|
||||
|
Loading…
Reference in New Issue
Block a user