diff --git a/Shorewall-perl/Shorewall/Accounting.pm b/Shorewall-perl/Shorewall/Accounting.pm
index 5cad573ec..fdc237cd1 100644
--- a/Shorewall-perl/Shorewall/Accounting.pm
+++ b/Shorewall-perl/Shorewall/Accounting.pm
@@ -198,29 +198,16 @@ sub setup_accounting() {
if ( $filter_table->{accounting} ) {
for my $chain ( qw/INPUT FORWARD/ ) {
insert_rule $filter_table->{$chain}, 1, '-j accounting';
- insert_rule $filter_table->{$chain}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT};
- }
- } elsif ( $config{FASTACCEPT} ) {
- for my $chain ( qw/INPUT FORWARD/ ) {
- insert_rule $filter_table->{$chain}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT';
}
}
if ( $filter_table->{accountout} ) {
insert_rule $filter_table->{OUTPUT}, 1, '-j accountout';
- insert_rule $filter_table->{OUTPUT}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT};
- } elsif ( $config{FASTACCEPT} ) {
- insert_rule $filter_table->{OUTPUT}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT';
}
} else {
if ( $filter_table->{accounting} ) {
for my $chain ( qw/INPUT FORWARD OUTPUT/ ) {
insert_rule $filter_table->{$chain}, 1, '-j accounting';
- insert_rule $filter_table->{$chain}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT};
- }
- } elsif ( $config{FASTACCEPT} ) {
- for my $chain ( qw/INPUT FORWARD OUTPUT/ ) {
- insert_rule $filter_table->{$chain}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT';
}
}
}
diff --git a/Shorewall-perl/Shorewall/Actions.pm b/Shorewall-perl/Shorewall/Actions.pm
index ce898ae0d..b6facdfe5 100644
--- a/Shorewall-perl/Shorewall/Actions.pm
+++ b/Shorewall-perl/Shorewall/Actions.pm
@@ -54,7 +54,7 @@ our @EXPORT = qw( merge_levels
%macros
);
our @EXPORT_OK = qw( initialize );
-our $VERSION = 4.01;
+our $VERSION = 4.03;
#
# Used Actions. Each action that is actually used has an entry with value 1.
@@ -389,12 +389,14 @@ sub process_macro1 ( $$ ) {
$mtarget =~ s/:.*$//;
+ $mtarget = (split '/' , $mtarget)[0];
+
my $targettype = $targets{$mtarget};
$targettype = 0 unless defined $targettype;
fatal_error "Invalid target ($mtarget)"
- unless ( $targettype == STANDARD ) || ( $mtarget eq 'PARAM' ) || ( $mtarget eq 'LOG' );
+ unless ( $targettype == STANDARD ) || ( $mtarget eq 'PARAM' ) || ( $targettype & ( LOGRULE | NFQ ) );
}
progress_message " ..End Macro $macrofile";
@@ -412,7 +414,7 @@ sub process_action1 ( $$ ) {
my $targettype = $targets{$target};
if ( defined $targettype ) {
- return if ( $targettype == STANDARD ) || ( $targettype == MACRO ) || ( $targettype & LOGRULE );
+ return if ( $targettype == STANDARD ) || ( $targettype == MACRO ) || ( $targettype & ( LOGRULE | NFQ ) );
fatal_error "Invalid TARGET ($target)" if $targettype & STANDARD;
@@ -424,6 +426,8 @@ sub process_action1 ( $$ ) {
} else {
( $target, my $param ) = split '/', $target;
+ return if $target eq 'NFQUEUE';
+
if ( defined $param ) {
my $paramtype = $targets{$param} || 0;
@@ -462,8 +466,8 @@ sub process_actions1() {
next unless $action;
if ( $targets{$action} ) {
- next if $targets{$action} & ACTION;
- fatal_error "Invalid Action Name ($action)";
+ warning_message "Duplicate Action Name ($action) Ignored" unless $targets{$action} & ACTION;
+ next;
}
$targets{$action} = ACTION;
@@ -632,7 +636,7 @@ sub process_action3( $$$$$ ) {
if ( $action2type & ACTION ) {
$target2 = (find_logactionchain ( $target = $target2 ))->{name};
} else {
- die "Internal Error" unless $action2type == MACRO || $action2type & LOGRULE;
+ fatal_error "Internal Error" unless $action2type == MACRO || $action2type & ( LOGRULE | NFQ );
}
}
@@ -666,10 +670,10 @@ sub process_actions3 () {
add_rule $chainref, '-m addrtype --dst-type BROADCAST -j DROP';
} else {
add_command $chainref, 'for address in $ALL_BCASTS; do';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -d $address ' if $level ne '';
add_rule $chainref, '-d $address -j DROP';
- pop_cmd_mode $chainref;
+ decr_cmd_level $chainref;
add_command $chainref, 'done';
log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -d 224.0.0.0/4 ' if $level ne '';
@@ -690,10 +694,10 @@ sub process_actions3 () {
add_rule $chainref, '-m addrtype --dst-type BROADCAST -j ACCEPT';
} else {
add_command $chainref, 'for address in $ALL_BCASTS; do';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
log_rule_limit $level, $chainref, 'allowBcast' , 'ACCEPT', '', $tag, 'add', ' -d $address ' if $level ne '';
add_rule $chainref, '-d $address -j ACCEPT';
- pop_cmd_mode $chainref;
+ decr_cmd_level $chainref;
add_command $chainref, 'done';
log_rule_limit $level, $chainref, 'allowBcast' , 'ACCEPT', '', $tag, 'add', ' -d 224.0.0.0/4 ' if $level ne '';
diff --git a/Shorewall-perl/Shorewall/Chains.pm b/Shorewall-perl/Shorewall/Chains.pm
index 2f571ad94..bd6ad2bc1 100644
--- a/Shorewall-perl/Shorewall/Chains.pm
+++ b/Shorewall-perl/Shorewall/Chains.pm
@@ -44,6 +44,7 @@ our @EXPORT = qw( STANDARD
ACTION
MACRO
LOGRULE
+ NFQ
NO_RESTRICT
PREROUTE_RESTRICT
INPUT_RESTRICT
@@ -52,14 +53,15 @@ our @EXPORT = qw( STANDARD
ALL_RESTRICT
process_comment
- push_cmd_mode
- pop_cmd_mode
+ incr_cmd_level
+ decr_cmd_level
add_command
add_commands
mark_referenced
add_file
add_rule
insert_rule
+ insert_rule_nice
chain_base
forward_chain
input_chain
@@ -89,7 +91,6 @@ our @EXPORT = qw( STANDARD
clearrule
do_proto
mac_match
- numeric_value
verify_mark
verify_small_mark
validate_mark
@@ -128,7 +129,7 @@ our @EXPORT = qw( STANDARD
%targets
);
our @EXPORT_OK = qw( initialize );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
#
# Chain Table
@@ -138,16 +139,17 @@ our $VERSION = 4.02;
# %chain_table {
=> { => { name =>
# table =>
# is_policy => 0|1
-# is_optionsl => 0|1
+# is_optional => 0|1
# referenced => 0|1
# log =>
# policy =>
+# policychain => -- self-reference if this is a policy chain
+# policypair => [ , ] -- Used for reporting duplicated policies
# loglevel =>
# synparams =>
# synchain =>
# default =>
-# policy_chain => [
-# cmdmode =>
+# cmdlevel =>
# rules => [
#
# ...
@@ -188,6 +190,7 @@ use constant { STANDARD => 1, #defined by Netfilter
ACTION => 64, #An action (may be built-in)
MACRO => 128, #A Macro
LOGRULE => 256, #'LOG'
+ NFQ => 512, #'NFQUEUE'
};
our %targets;
@@ -276,6 +279,8 @@ sub initialize() {
'CONTINUE!' => STANDARD,
'QUEUE' => STANDARD,
'QUEUE!' => STANDARD,
+ 'NFQUEUE' => STANDARD + NFQ,
+ 'NFQUEUE!' => STANDARD + NFQ,
'SAME' => NATRULE,
'SAME-' => NATRULE + NATONLY,
'dropBcast' => BUILTIN + ACTION,
@@ -331,21 +336,21 @@ sub process_comment() {
}
}
#
-# Functions to manipulate cmdmode
+# Functions to manipulate cmdlevel
#
-sub push_cmd_mode( $ ) {
- $_[0]->{cmdmode}++;
+sub incr_cmd_level( $ ) {
+ $_[0]->{cmdlevel}++;
}
-sub pop_cmd_mode( $ ) {
- fatal_error "Internal error in pop_cmd_mode()" if --$_[0]->{cmdmode} < 0;
+sub decr_cmd_level( $ ) {
+ fatal_error "Internal error in decr_cmd_level()" if --$_[0]->{cmdlevel} < 0;
}
sub add_command($$)
{
my ($chainref, $command) = @_;
- push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdmode} , $command );
+ push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdlevel} , $command );
$chainref->{referenced} = 1;
}
@@ -354,7 +359,7 @@ sub add_commands {
my $chainref = shift @_;
for my $command ( @_ ) {
- push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdmode} , $command );
+ push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdlevel} , $command );
}
$chainref->{referenced} = 1;
@@ -403,7 +408,7 @@ sub add_rule($$)
$rule .= qq( -m comment --comment "$comment") if $comment;
- if ( $chainref->{cmdmode} ) {
+ if ( $chainref->{cmdlevel} ) {
$rule =~ s/"/\\"/g; #Must preserve quotes in the rule
add_command $chainref , qq(echo "-A $chainref->{name} $rule" >&3);
} else {
@@ -421,7 +426,7 @@ sub insert_rule($$$)
{
my ($chainref, $number, $rule) = @_;
- fatal_error 'Internal Error in insert_rule()' if $chainref->{cmdmode};
+ fatal_error 'Internal Error in insert_rule()' if $chainref->{cmdlevel};
$rule .= "-m comment --comment \"$comment\"" if $comment;
@@ -445,12 +450,16 @@ sub chain_base($) {
$chain;
}
+sub chain_base_cond($) {
+ $config{DYNAMIC_ZONES} ? chain_base($_[0]) : $_[0];
+}
+
#
# Forward Chain for an interface
#
sub forward_chain($)
{
- $_[0] . '_fwd';
+ chain_base_cond($_[0]) . '_fwd';
}
#
@@ -458,7 +467,7 @@ sub forward_chain($)
#
sub input_chain($)
{
- $_[0] . '_in';
+ chain_base_cond($_[0]) . '_in';
}
#
@@ -466,7 +475,7 @@ sub input_chain($)
#
sub output_chain($)
{
- $_[0] . '_out';
+ chain_base_cond($_[0]) . '_out';
}
#
@@ -474,7 +483,7 @@ sub output_chain($)
#
sub masq_chain($)
{
- $_[0] . '_masq';
+ chain_base_cond($_[0]) . '_masq';
}
#
@@ -489,12 +498,12 @@ sub syn_flood_chain ( $ ) {
#
sub mac_chain( $ )
{
- $_[0] . '_mac';
+ chain_base_cond($_[0]) . '_mac';
}
sub macrecent_target($)
{
- $config{MACLIST_TTL} ? $_[0] . '_rec' : 'RETURN';
+ $config{MACLIST_TTL} ? chain_base_cond($_[0]) . '_rec' : 'RETURN';
}
#
@@ -502,22 +511,22 @@ sub macrecent_target($)
#
sub dynamic_fwd( $ )
{
- $_[0] . '_dynf';
+ chain_base_cond($_[0]) . '_dynf';
}
sub dynamic_in( $ )
{
- $_[0] . '_dyni';
+ chain_base_cond($_[0]) . '_dyni';
}
sub dynamic_out( $ ) # $1 = interface
{
- $_[0] . '_dyno';
+ chain_base_cond($_[0]) . '_dyno';
}
sub dynamic_chains( $ ) #$1 = interface
{
- my $c = $_[0];
+ my $c = chain_base_cond($_[0]);
[ $c . '_dyni' , $c . '_dynf' , $c . '_dyno' ];
}
@@ -527,7 +536,7 @@ sub dynamic_chains( $ ) #$1 = interface
#
sub dnat_chain( $ )
{
- $_[0] . '_dnat';
+ chain_base_cond($_[0]) . '_dnat';
}
#
@@ -535,7 +544,7 @@ sub dnat_chain( $ )
#
sub snat_chain( $ )
{
- $_[0] . '_snat';
+ chain_base_cond($_[0]) . '_snat';
}
#
@@ -543,7 +552,7 @@ sub snat_chain( $ )
#
sub ecn_chain( $ )
{
- $_[0] . '_ecn';
+ chain_base_cond($_[0]) . '_ecn';
}
#
@@ -551,7 +560,7 @@ sub ecn_chain( $ )
#
sub first_chains( $ ) #$1 = interface
{
- my $c = $_[0];
+ my $c = chain_base_cond($_[0]);
[ $c . '_fwd', $c . '_in' ];
}
@@ -563,12 +572,14 @@ sub new_chain($$)
{
my ($table, $chain) = @_;
+ warning_message "Internal error in new_chain()" if $chain_table{$table}{$chain};
+
$chain_table{$table}{$chain} = { name => $chain,
rules => [],
table => $table,
loglevel => '',
log => 1,
- cmdmode => 0 };
+ cmdlevel => 0 };
}
#
@@ -668,7 +679,7 @@ sub initialize_chain_table()
new_builtin_chain 'nat', $chain, 'ACCEPT';
}
- for my $chain qw(PREROUTING INPUT FORWARD OUTPUT POSTROUTING) {
+ for my $chain qw(PREROUTING INPUT OUTPUT ) {
new_builtin_chain 'mangle', $chain, 'ACCEPT';
}
@@ -693,7 +704,7 @@ sub finish_chain_section ($$) {
if ( $chainref->{synparams} ) {
my $synchainref = ensure_chain 'filter', syn_flood_chain $chainref;
if ( $section eq 'DONE' ) {
- if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE)$/ ) {
+ if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE|NFQUEUE)/ ) {
add_rule $chainref, "-p tcp --syn -j $synchainref->{name}";
}
} else {
@@ -762,7 +773,7 @@ sub set_mss( $$$ ) {
}
#
-# Interate over non-firewall zones adding TCPMSS rules as appropriate
+# Interate over non-firewall zones and interfaces with 'mss=' setting adding TCPMSS rules as appropriate.
#
sub setup_zone_mss() {
for my $zone ( @zones ) {
@@ -984,15 +995,6 @@ sub mac_match( $ ) {
"--match mac --mac-source ${invert}$mac ";
}
-#
-# Convert value to decimal number
-#
-sub numeric_value ( $ ) {
- my $mark = $_[0];
- fatal_error "Invalid Numeric Value ($mark)" unless "\L$mark" =~ /^(0x[a-f0-9]+|0[0-7]*|[1-9]\d*)$/;
- $mark =~ /^0x/ ? hex $mark : $mark =~ /^0/ ? oct $mark : $mark;
-}
-
#
# Mark validatation functions
#
@@ -1224,8 +1226,10 @@ sub match_orig_dest ( $ ) {
if ( $net =~ /^!/ ) {
$net =~ s/!//;
+ validate_net $net;
"-m conntrack --ctorigdst ! $net ";
} else {
+ validate_net $net;
$net eq ALLIPv4 ? '' : "-m conntrack --ctorigdst $net ";
}
}
@@ -1301,7 +1305,7 @@ sub log_rule_limit( $$$$$$$$ ) {
}
if ( length $prefix > 29 ) {
- $prefix = substr $prefix, 0, 29;
+ $prefix = substr( $prefix, 0, 28 ) . ' ';
warning_message "Log Prefix shortened to \"$prefix\"";
}
@@ -1473,7 +1477,7 @@ sub expand_rule( $$$$$$$$$$ )
my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl );
my $chain = $chainref->{name};
- my $initialcmdmode = $chainref->{cmdmode};
+ my $initialcmdlevel = $chainref->{cmdlevel};
#
# Handle Log Level
@@ -1531,7 +1535,7 @@ sub expand_rule( $$$$$$$$$$ )
$rule .= '-s $source ';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
} else {
fatal_error "Source Interface ($iiface) not allowed when the source zone is $firewall_zone" if $restriction & OUTPUT_RESTRICT;
$rule .= match_source_dev( $iiface );
@@ -1560,7 +1564,7 @@ sub expand_rule( $$$$$$$$$$ )
add_command( $chainref , "for address in $list; do" );
$rule .= '-d $address ';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
} else {
$rule .= join ( '', '-d ', get_interface_address( $interfaces[0] ), ' ' );
}
@@ -1591,7 +1595,7 @@ sub expand_rule( $$$$$$$$$$ )
fatal_error "Bridge port ($diface) not allowed" if port_to_bridge( $diface );
add_command( $chainref , 'for dest in ' . get_interface_addresses( $diface) . '; do' );
$rule .= '-d $dest ';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
} else {
fatal_error "Bridge Port ($diface) not allowed in OUTPUT or POSTROUTING rules" if ( $restriction & ( POSTROUTE_RESTRICT + OUTPUT_RESTRICT ) ) && port_to_bridge( $diface );
fatal_error "Destination Interface ($diface) not allowed when the destination zone is $firewall_zone" if $restriction & INPUT_RESTRICT;
@@ -1625,7 +1629,7 @@ sub expand_rule( $$$$$$$$$$ )
add_command( $chainref , "for address in $list; do" );
$rule .= '-m conntrack --ctorigdst $address ';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
} else {
get_interface_address $interfaces[0];
$rule .= join( '', '-m conntrack --ctorigdst $', interface_address ( $interfaces[0] ), ' ' );
@@ -1649,7 +1653,7 @@ sub expand_rule( $$$$$$$$$$ )
unless ( $onets ) {
my @oexcl = mysplit $oexcl;
if ( @oexcl == 1 ) {
- $rule .= "-m conntrack --ctorigdst ! $oexcl ";
+ $rule .= match_orig_dest( "!$oexcl" );
$oexcl = '';
}
}
@@ -1727,19 +1731,13 @@ sub expand_rule( $$$$$$$$$$ )
for my $inet ( mysplit $inets ) {
for my $dnet ( mysplit $dnets ) {
#
- # We defer evaluating the source net match to accomodate system without $capabilities{KLUDGEFREE}
+ # 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), match_dest_net( $dnet ), $onet, "-j $echain" );
}
}
}
- #
- # The final rule in the exclusion chain will not qualify the source or destination
- #
- $inets = ALLIPv4;
- $dnets = ALLIPv4;
-
#
# Create the Exclusion Chain
#
@@ -1748,17 +1746,9 @@ sub expand_rule( $$$$$$$$$$ )
#
# Generate RETURNs for each exclusion
#
- for my $net ( mysplit $iexcl ) {
- add_rule $echainref, ( match_source_net $net ) . '-j RETURN';
- }
-
- for my $net ( mysplit $dexcl ) {
- add_rule $echainref, ( match_dest_net $net ) . '-j RETURN';
- }
-
- for my $net ( mysplit $oexcl ) {
- add_rule $echainref, ( match_orig_dest $net ) . '-j RETURN';
- }
+ add_rule $echainref, ( match_source_net $_ ) . '-j RETURN' for ( mysplit $iexcl );
+ add_rule $echainref, ( match_dest_net $_ ) . '-j RETURN' for ( mysplit $dexcl );
+ add_rule $echainref, ( match_orig_dest $_ ) . '-j RETURN' for ( mysplit $oexcl );
#
# Log rule
#
@@ -1800,8 +1790,8 @@ sub expand_rule( $$$$$$$$$$ )
}
}
- while ( $chainref->{cmdmode} > $initialcmdmode ) {
- pop_cmd_mode $chainref;
+ while ( $chainref->{cmdlevel} > $initialcmdlevel ) {
+ decr_cmd_level $chainref;
add_command $chainref, 'done';
}
@@ -1974,7 +1964,7 @@ sub create_netfilter_load() {
for my $chain ( @builtins ) {
my $chainref = $chain_table{$table}{$chain};
if ( $chainref ) {
- fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdmode};
+ fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdlevel};
emit_unindented ":$chain $chainref->{policy} [0:0]";
push @chains, $chainref;
}
@@ -1985,7 +1975,7 @@ sub create_netfilter_load() {
for my $chain ( grep $chain_table{$table}{$_}->{referenced} , ( sort keys %{$chain_table{$table}} ) ) {
my $chainref = $chain_table{$table}{$chain};
unless ( $chainref->{builtin} ) {
- fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdmode};
+ fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdlevel};
emit_unindented ":$chainref->{name} - [0:0]";
push @chains, $chainref;
}
diff --git a/Shorewall-perl/Shorewall/Compiler.pm b/Shorewall-perl/Shorewall/Compiler.pm
index a16a8e76b..3d0a15d09 100644
--- a/Shorewall-perl/Shorewall/Compiler.pm
+++ b/Shorewall-perl/Shorewall/Compiler.pm
@@ -41,7 +41,7 @@ use Shorewall::Proxyarp;
our @ISA = qw(Exporter);
our @EXPORT = qw( compiler EXPORT TIMESTAMP DEBUG );
our @EXPORT_OK = qw( $export );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
our $export;
@@ -85,7 +85,7 @@ sub generate_script_1() {
copy $globals{SHAREDIRPL} . 'prog.header';
- for my $exit qw/init start tcclear started stop stopped clear refresh refreshed/ {
+ for my $exit qw/init isusable start tcclear started stop stopped clear refresh refreshed/ {
emit "\nrun_${exit}_exit() {";
push_indent;
append_file $exit or emit 'true';
@@ -581,8 +581,6 @@ sub generate_script_2 () {
push_indent;
- setup_mss( $config{CLAMPMSS} ) if $config{CLAMPMSS};
-
}
#
@@ -775,6 +773,10 @@ sub compiler( $$$$ ) {
#
generate_script_2 unless $command eq 'check';
#
+ # Set up MSS rules
+ #
+ setup_mss;
+ #
# Do all of the zone-independent stuff
#
add_common_rules;
diff --git a/Shorewall-perl/Shorewall/Config.pm b/Shorewall-perl/Shorewall/Config.pm
index 34baac915..85a49b3da 100644
--- a/Shorewall-perl/Shorewall/Config.pm
+++ b/Shorewall-perl/Shorewall/Config.pm
@@ -93,7 +93,7 @@ our @EXPORT = qw(
%capabilities );
our @EXPORT_OK = qw( $shorewall_dir initialize read_a_line1 set_config_path );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
#
# describe the current command, it's present progressive, and it's completion.
@@ -198,8 +198,8 @@ sub initialize() {
ORIGINAL_POLICY_MATCH => '',
LOGPARMS => '',
TC_SCRIPT => '',
- VERSION => '4.0.2',
- CAPVERSION => 30405 ,
+ VERSION => '4.0.3',
+ CAPVERSION => 40003 ,
);
#
# From shorewall.conf file
@@ -247,6 +247,7 @@ sub initialize() {
REJECT_DEFAULT => undef,
ACCEPT_DEFAULT => undef,
QUEUE_DEFAULT => undef,
+ NFQUEUE_DEFAULT => undef,
#
# RSH/RCP Commands
#
@@ -328,6 +329,9 @@ sub initialize() {
MANGLE_FORWARD => undef,
COMMENTS => undef,
ADDRTYPE => undef,
+ TCPMSS_MATCH => undef,
+ HASHLIMIT_MATCH => undef,
+ NFQUEUE_TARGET => undef,
CAPVERSION => undef,
);
#
@@ -360,7 +364,9 @@ sub initialize() {
MANGLE_FORWARD => 'Mangle FORWARD Chain',
COMMENTS => 'Comments',
ADDRTYPE => 'Address Type Match',
- TCPMSS_MATCH => 'TCP MSS',
+ TCPMSS_MATCH => 'TCPMSS Match',
+ HASHLIMIT_MATCH => 'Hashlimit Match',
+ NFQUEUE_TARGET => 'NFQUEUE Target',
CAPVERSION => 'Capability Version',
);
#
@@ -1180,9 +1186,11 @@ sub determine_capabilities() {
}
}
- $capabilities{USEPKTTYPE} = qt( "$iptables -A $sillyname -m pkttype --pkt-type broadcast -j ACCEPT" );
- $capabilities{ADDRTYPE} = qt( "$iptables -A $sillyname -m addrtype --src-type BROADCAST -j ACCEPT" );
- $capabilities{TCPMSS_MATCH} = qt( "$iptables -A $sillyname -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT" );
+ $capabilities{USEPKTTYPE} = qt( "$iptables -A $sillyname -m pkttype --pkt-type broadcast -j ACCEPT" );
+ $capabilities{ADDRTYPE} = qt( "$iptables -A $sillyname -m addrtype --src-type BROADCAST -j ACCEPT" );
+ $capabilities{TCPMSS_MATCH} = qt( "$iptables -A $sillyname -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT" );
+ $capabilities{HASHLIMIT_MATCH} = qt( "$iptables -A $sillyname -m hashlimit --hashlimit 4 --hashlimit-burst 5 --hashlimit-name fooX1234 --hashlimit-mode dstip -j ACCEPT" );
+ $capabilities{NFQUEUE_TARGET} = qt( "$iptables -A $sillyname -j NFQUEUE --queue-num 4" );
qt( "$iptables -F $sillyname" );
qt( "$iptables -X $sillyname" );
@@ -1418,7 +1426,7 @@ sub get_configuration( $ ) {
default_yes_no 'EXPORTPARAMS' , '';
default_yes_no 'EXPAND_POLICIES' , '';
- default_yes_no 'ACCOUNTING_EXPERT' , '';
+ default_yes_no 'KEEP_RT_TABLES' , '';
default_yes_no 'MARK_IN_FORWARD_CHAIN' , '';
$capabilities{XCONNMARK} = '' unless $capabilities{XCONNMARK_MATCH} and $capabilities{XMARK};
@@ -1480,16 +1488,17 @@ sub get_configuration( $ ) {
}
default 'RESTOREFILE' , 'restore';
+ default 'IPSECFILE' , 'zones';
default 'DROP_DEFAULT' , 'Drop';
default 'REJECT_DEFAULT' , 'Reject';
default 'QUEUE_DEFAULT' , 'none';
+ default 'NFQUEUE_DEFAULT' , 'none';
default 'ACCEPT_DEFAULT' , 'none';
default 'OPTIMIZE' , 0;
- default 'IPSECFILE' , 'zones';
fatal_error 'IPSECFILE=ipsec is not supported by Shorewall-perl ' . $globals{VERSION} unless $config{IPSECFILE} eq 'zones';
- for my $default qw/DROP_DEFAULT REJECT_DEFAULT QUEUE_DEFAULT ACCEPT_DEFAULT/ {
+ for my $default qw/DROP_DEFAULT REJECT_DEFAULT QUEUE_DEFAULT NFQUEUE_DEFAULT ACCEPT_DEFAULT/ {
$config{$default} = 'none' if "\L$config{$default}" eq 'none';
}
diff --git a/Shorewall-perl/Shorewall/IPAddrs.pm b/Shorewall-perl/Shorewall/IPAddrs.pm
index ebe9b3ecb..111f991f0 100644
--- a/Shorewall-perl/Shorewall/IPAddrs.pm
+++ b/Shorewall-perl/Shorewall/IPAddrs.pm
@@ -41,7 +41,7 @@ our @EXPORT = qw( ALLIPv4
@rfc1918_networks
);
our @EXPORT_OK = qw( );
-our $VERSION = 4.00;
+our $VERSION = 4.03;
#
# Some IPv4 useful stuff
@@ -75,6 +75,8 @@ sub validate_address( $ ) {
sub validate_net( $ ) {
my ($net, $vlsm, $rest) = split( '/', $_[0], 3 );
+ fatal_error "An ipset name ($net) is not allowed in this context" if substr( $net, 0, 1 ) eq '+';
+
if ( defined $vlsm ) {
fatal_error "Invalid VLSM ($vlsm)" unless $vlsm =~ /^\d+$/ && $vlsm <= 32;
fatal_error "Invalid Network address ($_[0])" if defined $rest;
diff --git a/Shorewall-perl/Shorewall/Nat.pm b/Shorewall-perl/Shorewall/Nat.pm
index 4d71b0f92..e26a94ed5 100644
--- a/Shorewall-perl/Shorewall/Nat.pm
+++ b/Shorewall-perl/Shorewall/Nat.pm
@@ -36,7 +36,7 @@ use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( setup_masq setup_nat setup_netmap add_addresses );
our @EXPORT_OK = ();
-our $VERSION = 4.00;
+our $VERSION = 4.03;
our @addresses_to_add;
our %addresses_to_add;
@@ -212,7 +212,7 @@ sub setup_one_masq($$$$$$$)
add_commands( $chainref,
'',
"if [ \"$variable\" != 0.0.0.0 ]; then" );
- push_cmd_mode( $chainref );
+ incr_cmd_level( $chainref );
$detectaddress = 1;
}
} else {
@@ -249,7 +249,7 @@ sub setup_one_masq($$$$$$$)
$exceptionrule );
if ( $detectaddress ) {
- pop_cmd_mode( $chainref );
+ decr_cmd_level( $chainref );
add_command( $chainref , 'fi' );
}
diff --git a/Shorewall-perl/Shorewall/Policy.pm b/Shorewall-perl/Shorewall/Policy.pm
index 6de28294c..e9751f145 100644
--- a/Shorewall-perl/Shorewall/Policy.pm
+++ b/Shorewall-perl/Shorewall/Policy.pm
@@ -34,21 +34,32 @@ use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain sub setup_syn_flood_chains );
our @EXPORT_OK = qw( );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
#
-# Create a new policy chain and return a reference to it.
+# Convert a chain into a policy chain.
#
-sub new_policy_chain($$$)
+sub convert_to_policy_chain($$$$$)
{
- my ($chain, $policy, $optional) = @_;
-
- my $chainref = new_chain 'filter', $chain;
+ my ($chainref, $source, $dest, $policy, $optional ) = @_;
$chainref->{is_policy} = 1;
$chainref->{policy} = $policy;
$chainref->{is_optional} = $optional;
- $chainref->{policychain} = $chain;
+ $chainref->{policychain} = $chainref->{name};
+ $chainref->{policypair} = [ $source, $dest ];
+}
+
+#
+# Create a new policy chain and return a reference to it.
+#
+sub new_policy_chain($$$$)
+{
+ my ($source, $dest, $policy, $optional) = @_;
+
+ my $chainref = new_chain( 'filter', "${source}2${dest}" );
+
+ convert_to_policy_chain( $chainref, $source, $dest, $policy, $optional );
$chainref;
}
@@ -56,9 +67,9 @@ sub new_policy_chain($$$)
#
# Set the passed chain's policychain and policy to the passed values.
#
-sub set_policy_chain($$$)
+sub set_policy_chain($$$$$)
{
- my ($chain1, $chainref, $policy) = @_;
+ my ($source, $dest, $chain1, $chainref, $policy ) = @_;
my $chainref1 = $filter_table->{$chain1};
@@ -86,6 +97,7 @@ sub set_policy_chain($$$)
}
$chainref1->{policy} = $policy;
+ $chainref1->{policypair} = [ $source, $dest ];
}
}
@@ -97,8 +109,13 @@ sub validate_policy()
sub print_policy($$$$)
{
my ( $source, $dest, $policy , $chain ) = @_;
- progress_message " Policy for $source to $dest is $policy using chain $chain"
- unless ( $source eq $dest ) || ( $source eq 'all' ) || ( $dest eq 'all' );
+ unless ( ( $source eq 'all' ) || ( $dest eq 'all' ) ) {
+ if ( $policy eq 'CONTINUE' ) {
+ my ( $sourceref, $destref ) = @zones{$source,$dest};
+ warning_message "CONTINUE policy between two un-nested zones ($source, $dest)" if ! ( @{$sourceref->{parents}} || @{$destref->{parents}} );
+ }
+ progress_message " Policy for $source to $dest is $policy using chain $chain" unless $source eq $dest;
+ }
}
my %validpolicies = (
@@ -107,19 +124,21 @@ sub validate_policy()
DROP => undef,
CONTINUE => undef,
QUEUE => undef,
+ NFQUEUE => undef,
NONE => undef
);
- my %map = ( DROP_DEFAULT => 'DROP' ,
- REJECT_DEFAULT => 'REJECT' ,
- ACCEPT_DEFAULT => 'ACCEPT' ,
- QUEUE_DEFAULT => 'QUEUE' );
+ my %map = ( DROP_DEFAULT => 'DROP' ,
+ REJECT_DEFAULT => 'REJECT' ,
+ ACCEPT_DEFAULT => 'ACCEPT' ,
+ QUEUE_DEFAULT => 'QUEUE' ,
+ NFQUEUE_DEFAULT => 'NFQUEUE' );
my $zone;
use constant { OPTIONAL => 1 };
- for my $option qw/DROP_DEFAULT REJECT_DEFAULT ACCEPT_DEFAULT QUEUE_DEFAULT/ {
+ for my $option qw/DROP_DEFAULT REJECT_DEFAULT ACCEPT_DEFAULT QUEUE_DEFAULT NFQUEUE_DEFAULT/ {
my $action = $config{$option};
next if $action eq 'none';
my $actiontype = $targets{$action};
@@ -139,13 +158,13 @@ sub validate_policy()
}
for $zone ( @zones ) {
- push @policy_chains, ( new_policy_chain "${zone}2${zone}", 'ACCEPT', OPTIONAL );
+ push @policy_chains, ( new_policy_chain $zone, $zone, 'ACCEPT', OPTIONAL );
if ( $config{IMPLICIT_CONTINUE} && ( @{$zones{$zone}{parents}} ) ) {
for my $zone1 ( @zones ) {
next if $zone eq $zone1;
- push @policy_chains, ( new_policy_chain "${zone}2${zone1}", 'CONTINUE', OPTIONAL );
- push @policy_chains, ( new_policy_chain "${zone1}2${zone}", 'CONTINUE', OPTIONAL );
+ push @policy_chains, ( new_policy_chain $zone, $zone1, 'CONTINUE', OPTIONAL );
+ push @policy_chains, ( new_policy_chain $zone1, $zone, 'CONTINUE', OPTIONAL );
}
}
}
@@ -178,6 +197,8 @@ sub validate_policy()
fatal_error "Invalid default action ($default:$remainder)" if defined $remainder;
+ ( $policy , my $queue ) = split( '/' , $policy );
+
if ( $default ) {
if ( "\L$default" eq 'none' ) {
$default = 'none';
@@ -199,7 +220,13 @@ sub validate_policy()
fatal_error "Invalid policy $policy" unless exists $validpolicies{$policy};
- if ( $policy eq 'NONE' ) {
+ if ( defined $queue ) {
+ fatal_error "Invalid policy ($policy/$queue)" unless $policy eq 'NFQUEUE';
+ require_capability( 'NFQUEUE_TARGET', 'An NFQUEUE Policy', 's' );
+ $queue = numeric_value( $queue );
+ fatal_error "Invalid NFQUEUE queue number ($queue)" if $queue > 65535;
+ $policy = "$policy/$queue";
+ } elsif ( $policy eq 'NONE' ) {
fatal_error "NONE policy not allowed with \"all\""
if $clientwild || $serverwild;
fatal_error "NONE policy not allowed to/from firewall zone"
@@ -224,18 +251,16 @@ sub validate_policy()
$chainref->{is_optional} = 0;
$chainref->{policy} = $policy;
} else {
- fatal_error "Duplicate policy: $client $server $policy";
+ fatal_error qq(Policy "$client $server $policy" duplicates earlier policy "@{$chainref->{policypair}} $chainref->{policy}");
}
} elsif ( $chainref->{policy} ) {
- fatal_error "Duplicate policy: $client $server $policy";
+ fatal_error qq(Policy "$client $server $policy" duplicates earlier policy "@{$chainref->{policypair}} $chainref->{policy}");
} else {
- $chainref->{is_policy} = 1;
- $chainref->{policy} = $policy;
- $chainref->{policychain} = $chain;
+ convert_to_policy_chain( $chainref, $client, $server, $policy, 0 );
push @policy_chains, ( $chainref ) unless $config{EXPAND_POLICIES} && ( $clientwild || $serverwild );
}
} else {
- $chainref = new_policy_chain $chain, $policy, 0;
+ $chainref = new_policy_chain $client, $server, $policy, 0;
push @policy_chains, ( $chainref ) unless $config{EXPAND_POLICIES} && ( $clientwild || $serverwild );
}
@@ -252,19 +277,19 @@ sub validate_policy()
if ( $serverwild ) {
for my $zone ( @zones , 'all' ) {
for my $zone1 ( @zones , 'all' ) {
- set_policy_chain "${zone}2${zone1}", $chainref, $policy;
+ set_policy_chain $client, $server, "${zone}2${zone1}", $chainref, $policy;
print_policy $zone, $zone1, $policy, $chain;
}
}
} else {
for my $zone ( @zones ) {
- set_policy_chain "${zone}2${server}", $chainref, $policy;
+ set_policy_chain $client, $server, "${zone}2${server}", $chainref, $policy;
print_policy $zone, $server, $policy, $chain;
}
}
} elsif ( $serverwild ) {
for my $zone ( @zones , 'all' ) {
- set_policy_chain "${client}2${zone}", $chainref, $policy;
+ set_policy_chain $client, $server, "${client}2${zone}", $chainref, $policy;
print_policy $client, $zone, $policy, $chain;
}
@@ -284,7 +309,14 @@ sub policy_rules( $$$$ ) {
add_rule $chainref, "-j $default" if $default && $default ne 'none';
log_rule $loglevel , $chainref , $target , '' if $loglevel ne '';
fatal_error "Null target in policy_rules()" unless $target;
- add_rule $chainref , ( '-j ' . ( $target eq 'REJECT' ? 'reject' : $target ) ) unless $target eq 'CONTINUE';
+ if ( $target eq 'REJECT' ) {
+ $target = 'reject';
+ } elsif ( $target =~ /^NFQUEUE/ ) {
+ my $queue = ( split( '/', $target) )[1] || 0;
+ $target = "NFQUEUE --queue-num $queue";
+ }
+
+ add_rule( $chainref , "-j $target" ) unless $target eq 'CONTINUE';
}
}
@@ -305,7 +337,7 @@ sub default_policy( $$$ ) {
if ( $chainref eq $policyref ) {
policy_rules $chainref , $policy, $loglevel , $default;
} else {
- if ( $policy eq 'ACCEPT' || $policy eq 'QUEUE' ) {
+ if ( $policy eq 'ACCEPT' || $policy eq 'QUEUE' || $policy =~ /^NFQUEUE/ ) {
if ( $synparams ) {
report_syn_flood_protection;
policy_rules $chainref , $policy , $loglevel , $default;
@@ -374,6 +406,8 @@ sub apply_policy_rules() {
sub complete_standard_chain ( $$$ ) {
my ( $stdchainref, $zone, $zone2 ) = @_;
+ add_rule $stdchainref, '-m state --state ESTABLISHED,RELATED -j ACCEPT' unless $config{FASTACCEPT};
+
run_user_exit $stdchainref;
my $ruleschainref = $filter_table->{"${zone}2${zone2}"};
diff --git a/Shorewall-perl/Shorewall/Providers.pm b/Shorewall-perl/Shorewall/Providers.pm
index 2073f561e..e718331dc 100644
--- a/Shorewall-perl/Shorewall/Providers.pm
+++ b/Shorewall-perl/Shorewall/Providers.pm
@@ -316,8 +316,9 @@ sub add_an_rtrule( $$$$ ) {
if ( "\L$provider" =~ /^(0x[a-f0-9]+|0[0-7]*|[0-9]*)$/ ) {
my $provider_number = numeric_value $provider;
- for my $provider ( keys %providers ) {
- if ( $providers{$provider}{number} == $provider_number ) {
+ for ( keys %providers ) {
+ if ( $providers{$_}{number} == $provider_number ) {
+ $provider = $_;
$found = 1;
last;
}
diff --git a/Shorewall-perl/Shorewall/Rules.pm b/Shorewall-perl/Shorewall/Rules.pm
index a92deda6e..07a6974be 100644
--- a/Shorewall-perl/Shorewall/Rules.pm
+++ b/Shorewall-perl/Shorewall/Rules.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw( process_tos
dump_rule_chains
);
our @EXPORT_OK = qw( process_rule process_rule1 initialize );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
#
# Keep track of chains for the /var/lib/shorewall[-lite]/chains file
@@ -109,8 +109,8 @@ sub process_tos() {
my ($src, $dst, $proto, $sports, $ports , $tos, $mark ) = split_line 6, 7, 'tos file entry';
- fatal_error "TOS field required" unless $tos ne '-';
-
+ fatal_error "A value must be supplied in the TOS column" if $tos eq '-';
+
if ( defined ( my $tosval = $tosoptions{"\L$tos"} ) ) {
$tos = $tosval;
} elsif ( numeric_value( $tos ) > 0x1e ) {
@@ -501,6 +501,13 @@ sub add_common_rules() {
my $list;
my $chain;
+ if ( $config{FASTACCEPT} ) {
+ for $chain qw( INPUT FORWARD OUTPUT ) {
+ $chainref = $filter_table->{$chain};
+ add_rule( $chainref , "-m state --state ESTABLISHED,RELATED -j ACCEPT" );
+ }
+ }
+
my $rejectref = new_standard_chain 'reject';
$level = $config{BLACKLIST_LOGLEVEL};
@@ -533,10 +540,10 @@ sub add_common_rules() {
add_rule_pair $chainref, '-m addrtype --src-type BROADCAST ', 'DROP', $config{SMURF_LOG_LEVEL} ;
} else {
add_command $chainref, 'for address in $ALL_BCASTS; do';
- push_cmd_mode $chainref;
+ incr_cmd_level $chainref;
log_rule( $config{SMURF_LOG_LEVEL} , $chainref, 'DROP', '-s $address ' );
add_rule $chainref, '-s $address -j DROP';
- pop_cmd_mode $chainref;
+ decr_cmd_level $chainref;
add_command $chainref, 'done';
}
@@ -546,9 +553,9 @@ sub add_common_rules() {
add_rule $rejectref , '-m addrtype --src-type BROADCAST -j DROP';
} else {
add_command $rejectref, 'for address in $ALL_BCASTS; do';
- push_cmd_mode $rejectref;
+ incr_cmd_level $rejectref;
add_rule $rejectref, '-d $address -j DROP';
- pop_cmd_mode $rejectref;
+ decr_cmd_level $rejectref;
add_command $rejectref, 'done';
}
@@ -967,6 +974,14 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
$current_param = pop @param_stack if $param ne '';
return;
+
+ } elsif ( $actiontype & NFQ ) {
+ require_capability( 'NFQUEUE_TARGET', 'NFQUEUE Rules', '' );
+ $param = $param eq '' ? 0 : numeric_value( $param );
+ fatal_error "Invalid value ($param) for NFQUEUE queue number" if $param > 65535;
+ $action = "NFQUEUE/$param";
+ } else {
+ fatal_error "The $basictarget TARGET does not accept a parameter" unless $param eq '';
}
#
# We can now dispense with the postfix characters
@@ -1110,7 +1125,6 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
my $servport = $serverport ne '' ? $serverport : $ports;
fatal_error "A server must be specified in the DEST column in $action rules" unless ( $actiontype & REDIRECT ) || $server ne ALLIPv4;
- fatal_error "Invalid server ($server)" if $server =~ /:/;
#
# Generate the target
#
@@ -1118,6 +1132,17 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
if ( $actiontype & REDIRECT ) {
$target = '-j REDIRECT --to-port ' . ( $serverport ne '' ? $serverport : $ports );
+ if ( $origdest eq '' || $origdest eq '-' ) {
+ $origdest = ALLIPv4;
+ } elsif ( $origdest eq 'detect' ) {
+ if ( $config{DETECT_DNAT_IPADDRS} && $sourcezone ne $firewall_zone ) {
+ my $interfacesref = $zones{$sourcezone}{interfaces};
+ my @interfaces = keys %$interfacesref;
+ $origdest = @interfaces ? "detect:@interfaces" : ALLIPv4;
+ } else {
+ $origdest = ALLIPv4;
+ }
+ }
} else {
if ( $action eq 'SAME' ) {
fatal_error 'Port mapping not allowed in SAME rules' if $serverport;
@@ -1135,7 +1160,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
}
unless ( $origdest && $origdest ne '-' && $origdest ne 'detect' ) {
- if ( $config{DETECT_DNAT_IPADDRS} ) {
+ if ( $config{DETECT_DNAT_IPADDRS} && $sourcezone ne $firewall_zone ) {
my $interfacesref = $zones{$sourcezone}{interfaces};
my @interfaces = keys %$interfacesref;
$origdest = @interfaces ? "detect:@interfaces" : ALLIPv4;
@@ -1144,6 +1169,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
}
}
}
+
#
# And generate the nat table rule(s)
#
@@ -1217,7 +1243,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) {
$source ,
$dest ,
$origdest ,
- "-j $action " ,
+ $actiontype & NFQ ? "-j NFQUEUE --queue-num $param " : "-j $action " ,
$loglevel ,
$action ,
'' );
@@ -1849,25 +1875,58 @@ sub generate_matrix() {
}
}
-sub setup_mss( $ ) {
- my $clampmss = $_[0];
+sub setup_mss( ) {
+ my $clampmss = $config{CLAMPMSS};
my $option;
my $match = '';
+ my $chainref = $filter_table->{FORWARD};
- if ( "\L$clampmss" eq 'yes' ) {
- $option = '--clamp-mss-to-pmtu';
- } else {
- $match = "-m tcpmss --mss $clampmss: " if $capabilities{TCPMSS_MATCH};
- $option = "--set-mss $clampmss";
+ if ( $clampmss ) {
+ if ( "\L$clampmss" eq 'yes' ) {
+ $option = '--clamp-mss-to-pmtu';
+ } else {
+ $match = "-m tcpmss --mss $clampmss: " if $capabilities{TCPMSS_MATCH};
+ $option = "--set-mss $clampmss";
+ }
+
+ $match .= '-m policy --pol none --dir out ' if $capabilities{POLICY_MATCH};
}
- add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS $option";
+ my $interfaces = find_interfaces_by_option( 'mss' );
+
+ if ( @$interfaces ) {
+ #
+ # Since we will need multiple rules, we create a separate chain
+ #
+ $chainref = new_chain 'filter', 'settcpmss';
+ #
+ # Send all forwarded SYN packets to the 'settcpmss' chain
+ #
+ add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN -j settcpmss";
+
+ my $in_match = '';
+ my $out_match = '';
+
+ if ( $capabilities{POLICY_MATCH} ) {
+ $in_match = '-m policy --pol none --dir in ';
+ $out_match = '-m policy --pol none --dir out ';
+ }
+
+ for ( @$interfaces ) {
+ my $mss = $interfaces{$_}{options}{mss};
+ my $mssmatch = $capabilities{TCPMSS_MATCH} ? "-m tcpmss --mss $mss: " : '';
+ add_rule $chainref, "-o $_ -p tcp --tcp-flags SYN,RST SYN ${mssmatch}${out_match}-j TCPMSS --set-mss $mss";
+ add_rule $chainref, "-o $_ -j RETURN" if $clampmss;
+ add_rule $chainref, "-i $_ -p tcp --tcp-flags SYN,RST SYN ${mssmatch}${in_match}-j TCPMSS --set-mss $mss";
+ add_rule $chainref, "-i $_ -j RETURN" if $clampmss;
+ }
+ }
+
+ add_rule $chainref , "-p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS $option" if $clampmss;
}
sub dump_rule_chains() {
- for my $arrayref ( @rule_chains ) {
- emit_unindented "@$arrayref";
- }
+ emit_unindented "@$_" for ( @rule_chains );
}
1;
diff --git a/Shorewall-perl/Shorewall/Tc.pm b/Shorewall-perl/Shorewall/Tc.pm
index e931f3811..a0f9ba95e 100644
--- a/Shorewall-perl/Shorewall/Tc.pm
+++ b/Shorewall-perl/Shorewall/Tc.pm
@@ -39,7 +39,7 @@ use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( setup_tc );
our @EXPORT_OK = qw( process_tc_rule initialize );
-our $VERSION = 4.02;
+our $VERSION = 4.03;
our %tcs = ( T => { chain => 'tcpost',
connmark => 0,
@@ -184,7 +184,7 @@ sub process_tc_rule( $$$$$$$$$$ ) {
my $tcsref;
my $connmark = 0;
my $classid = 0;
- my $device;
+ my $device = '';
if ( $source ) {
if ( $source eq $firewall_zone ) {
@@ -268,21 +268,22 @@ sub process_tc_rule( $$$$$$$$$$ ) {
}
}
- if ( my $result = expand_rule(
- ensure_chain( 'mangle' , $chain ) ,
- NO_RESTRICT ,
- do_proto( $proto, $ports, $sports) . do_test( $testval, $mask ) . do_tos( $tos ) ,
- $source ,
- $dest ,
+ if ( ( my $result = expand_rule(
+ ensure_chain( 'mangle' , $chain ) ,
+ NO_RESTRICT ,
+ do_proto( $proto, $ports, $sports) . do_test( $testval, $mask ) . do_tos( $tos ) ,
+ $source ,
+ $dest ,
+ '' ,
+ "-j $target $mark" ,
'' ,
- "-j $target $mark" ,
- '' ,
- '' ,
- '' ) ) {
+ '' ,
+ '' ) )
+ && $device ) {
#
# expand_rule() returns destination device if any
#
- fatal_error "Class Id $original_mark is not associated with device $result" if $config{TC_ENABLED} eq 'internal' && $classid && $device ne $result;
+ fatal_error "Class Id $original_mark is not associated with device $result" if $device ne $result;
}
progress_message " TC Rule \"$currentline\" $done";
diff --git a/Shorewall-perl/Shorewall/Zones.pm b/Shorewall-perl/Shorewall/Zones.pm
index 330115acf..197a8e71b 100644
--- a/Shorewall-perl/Shorewall/Zones.pm
+++ b/Shorewall-perl/Shorewall/Zones.pm
@@ -37,6 +37,7 @@ our @EXPORT = qw( NOTHING
IPSECPROTO
IPSECMODE
+ numeric_value
determine_zones
zone_report
dump_zone_contents
@@ -59,7 +60,7 @@ our @EXPORT = qw( NOTHING
@bridges );
our @EXPORT_OK = qw( initialize );
-our $VERSION = 4.01;
+our $VERSION = 4.03;
#
# IPSEC Option types
@@ -76,7 +77,7 @@ use constant { NOTHING => 'NOTHING',
#
# @zones contains the ordered list of zones with sub-zones appearing before their parents.
#
-# %zones{ => {type = >
+# %zones{ => {type = > 'firewall', 'ipv4', 'ipsec4', 'bport4';
# options => { complex => 0|1
# in_out => < policy match string >
# in => < policy match string >
@@ -110,16 +111,6 @@ our %reservedName = ( all => 1,
SOURCE => 1,
DEST => 1 );
-se constant ( ZT_IPV4 => 1,
- ZT_IPSEC => 2,
- ZT_BPORT => 4,
- ZT_IPV6 => 8,
- ZT_FIREWALL => 16,
- ZT_IPSEC4 => ZT_IPV4 | ZT_IPSEC
- ZT_IPSEC6 => ZT_IPV6 | ZT_IPSEC
- ZT_BPORT4 => ZT_IPV4 | ZT_BPORT
- ZT_BPORT6 => ZT_IPV6 | ZT_BPORT
- );
#
# Interface Table.
#
@@ -162,6 +153,15 @@ INIT {
initialize;
}
+#
+# Convert value to decimal number
+#
+sub numeric_value ( $ ) {
+ my $mark = $_[0];
+ fatal_error "Invalid Numeric Value ($mark)" unless "\L$mark" =~ /^(0x[a-f0-9]+|0[0-7]*|[1-9]\d*)$/;
+ $mark =~ /^0/ ? oct $mark : $mark;
+}
+
#
# Parse the passed option list and return a reference to a hash as follows:
#
@@ -219,7 +219,7 @@ sub parse_zone_option_list($$)
if ( $key{$e} ) {
$h{$e} = $val;
} else {
- fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype & ZT_IPSEC;
+ fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype eq 'ipsec4';
$options .= $invert;
$options .= "--$e ";
$options .= "$val "if defined $val;
@@ -261,7 +261,7 @@ sub determine_zones()
for my $p ( @parents ) {
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} & ZT_FIREWALL;
+ fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} eq 'firewall';
push @{$zones{$p}{children}}, $zone;
}
}
@@ -273,20 +273,20 @@ sub determine_zones()
$type = "ipv4" unless $type;
if ( $type =~ /ipv4/i ) {
- $type = ZT_IPV4;
+ $type = 'ipv4';
} elsif ( $type =~ /^ipsec4?$/i ) {
- $type = ZT_IPSEC4;
+ $type = 'ipsec4';
} elsif ( $type =~ /^bport4?$/i ) {
warning_message "Bridge Port zones should have a parent zone" unless @parents;
- $type = ZT_BPORT4;
+ $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;
$firewall_zone = $zone;
$ENV{FW} = $zone;
- $type = ZT_FIREWALL;
+ $type = "firewall";
} elsif ( $type eq '-' ) {
- $type = ZT_IPV4;
+ $type = 'ipv4';
} else {
fatal_error "Invalid zone type ($type)" ;
}
@@ -302,7 +302,7 @@ sub determine_zones()
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 & ZT_IPSEC || $options || $in_options || $out_options ? 1 : 0) } ,
+ complex => ($type eq 'ipsec4' || $options || $in_options || $out_options ? 1 : 0) } ,
interfaces => {} ,
children => [] ,
hosts => {}
@@ -337,22 +337,12 @@ sub determine_zones()
#
sub haveipseczones() {
for my $zoneref ( values %zones ) {
- return 1 if $zoneref->{type} & ZT_IPSEC;
+ return 1 if $zoneref->{type} eq 'ipsec4';
}
0;
}
-my @typenames = ( Untyped, #0
- firewall, #1
- ipv4, #2
- Invalid, #3
- Invalid, #4
- Invalid, #5
- ipsec4, #6
- Invalid, #7
- Invalid, #8
-
#
# Report about zones.
#
@@ -551,9 +541,10 @@ sub validate_interfaces_file( $ )
use constant { SIMPLE_IF_OPTION => 1,
BINARY_IF_OPTION => 2,
ENUM_IF_OPTION => 3,
- MASK_IF_OPTION => 3,
+ NUMERIC_IF_OPTION => 4,
+ MASK_IF_OPTION => 7,
- IF_OPTION_ZONEONLY => 4 };
+ IF_OPTION_ZONEONLY => 8 };
my %validoptions = (arp_filter => BINARY_IF_OPTION,
arp_ignore => ENUM_IF_OPTION,
@@ -572,6 +563,7 @@ sub validate_interfaces_file( $ )
sourceroute => BINARY_IF_OPTION,
tcpflags => SIMPLE_IF_OPTION,
upnp => SIMPLE_IF_OPTION,
+ mss => NUMERIC_IF_OPTION,
);
my $fn = open_file 'interfaces';
@@ -701,6 +693,9 @@ sub validate_interfaces_file( $ )
} else {
fatal_error "Internal Error in validate_interfaces_file";
}
+ } elsif ( $type == NUMERIC_IF_OPTION ) {
+ fatal_error "The $option option requires a value" unless defined $value;
+ $options{$option} = numeric_value $value;
}
}
diff --git a/Shorewall-perl/install.sh b/Shorewall-perl/install.sh
index e73c57c61..1f6163252 100755
--- a/Shorewall-perl/install.sh
+++ b/Shorewall-perl/install.sh
@@ -22,7 +22,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
#
-VERSION=4.0.2
+VERSION=4.0.3
usage() # $1 = exit status
{
diff --git a/Shorewall-perl/prog.header b/Shorewall-perl/prog.header
index e275fbabd..08d5e6fd1 100644
--- a/Shorewall-perl/prog.header
+++ b/Shorewall-perl/prog.header
@@ -540,7 +540,7 @@ find_first_interface_address_if_any() # $1 = interface
#
interface_is_usable() # $1 = interface
{
- interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ]
+ interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ] && run_isusable_exit $1
}
#
diff --git a/Shorewall-perl/shorewall-perl.spec b/Shorewall-perl/shorewall-perl.spec
index aef481099..f33d1b09b 100644
--- a/Shorewall-perl/shorewall-perl.spec
+++ b/Shorewall-perl/shorewall-perl.spec
@@ -1,5 +1,5 @@
%define name shorewall-perl
-%define version 4.0.2
+%define version 4.0.3
%define release 1
Summary: Shoreline Firewall Perl-based compiler.
@@ -72,6 +72,8 @@ fi
%doc COPYING releasenotes.txt
%changelog
+* Mon Aug 13 2007 Tom Eastep tom@shorewall.net
+- Updated to 4.0.3-1
* Thu Aug 09 2007 Tom Eastep tom@shorewall.net
- Updated to 4.0.2-1
* Sat Jul 21 2007 Tom Eastep tom@shorewall.net
]