diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index 1949a3d25..1d4a9fdbf 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -2788,8 +2788,8 @@ sub initialize_chain_table($) {
'DROP!' => STANDARD,
'A_DROP' => STANDARD + AUDIT,
'A_DROP!' => STANDARD + AUDIT,
- 'REJECT' => STANDARD,
- 'REJECT!' => STANDARD,
+ 'REJECT' => STANDARD + OPTIONS,
+ 'REJECT!' => STANDARD + OPTIONS,
'A_REJECT' => STANDARD + AUDIT,
'A_REJECT!' => STANDARD + AUDIT,
'DNAT' => NATRULE + OPTIONS,
@@ -2852,8 +2852,8 @@ sub initialize_chain_table($) {
'DROP!' => STANDARD,
'A_DROP' => STANDARD + AUDIT,
'A_DROP!' => STANDARD + AUDIT,
- 'REJECT' => STANDARD,
- 'REJECT!' => STANDARD,
+ 'REJECT' => STANDARD + OPTIONS,
+ 'REJECT!' => STANDARD + OPTIONS,
'A_REJECT' => STANDARD + AUDIT,
'A_REJECT!' => STANDARD + AUDIT,
'DNAT' => NATRULE + OPTIONS,
diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm
index 7d8b38a10..a6ff12195 100644
--- a/Shorewall/Perl/Shorewall/Compiler.pm
+++ b/Shorewall/Perl/Shorewall/Compiler.pm
@@ -850,6 +850,10 @@ sub compiler {
#
apply_policy_rules;
#
+ # Reject Action
+ #
+ process_reject_action if $config{REJECT_ACTION};
+ #
# Accounting.
#
setup_accounting if $config{ACCOUNTING};
diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm
index ff66adf68..5f524414f 100644
--- a/Shorewall/Perl/Shorewall/Config.pm
+++ b/Shorewall/Perl/Shorewall/Config.pm
@@ -819,6 +819,7 @@ sub initialize( $;$$) {
USE_RT_NAMES => undef,
CHAIN_SCRIPTS => undef,
TRACK_RULES => undef,
+ REJECT_ACTION => undef,
#
# Packet Disposition
#
@@ -5392,6 +5393,12 @@ sub get_configuration( $$$$ ) {
default_yes_no 'CHAIN_SCRIPTS' , 'Yes';
default_yes_no 'TRACK_RULES' , '';
+ if ( $val = $config{REJECT_ACTION} ) {
+ fatal_error "Invalid Reject Action Name ($val)" unless $val =~ /^[a-zA-Z][\w-]*$/;
+ } else {
+ $config{REJECT_ACTION} = '';
+ }
+
require_capability 'COMMENTS', 'TRACK_RULES=Yes', 's' if $config{TRACK_RULES};
default_yes_no 'MANGLE_ENABLED' , have_capability( 'MANGLE_ENABLED' ) ? 'Yes' : '';
diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm
index 120310aec..c64369b1d 100644
--- a/Shorewall/Perl/Shorewall/Misc.pm
+++ b/Shorewall/Perl/Shorewall/Misc.pm
@@ -983,42 +983,44 @@ sub add_common_rules ( $ ) {
}
}
- if ( have_capability( 'ADDRTYPE' ) ) {
- add_ijump $rejectref , j => 'DROP' , addrtype => '--src-type BROADCAST';
- } else {
- if ( $family == F_IPV4 ) {
- add_commands $rejectref, 'for address in $ALL_BCASTS; do';
+ unless ( $config{REJECT_ACTION} ) {
+ if ( have_capability( 'ADDRTYPE' ) ) {
+ add_ijump $rejectref , j => 'DROP' , addrtype => '--src-type BROADCAST';
} else {
- add_commands $rejectref, 'for address in $ALL_ACASTS; do';
+ if ( $family == F_IPV4 ) {
+ add_commands $rejectref, 'for address in $ALL_BCASTS; do';
+ } else {
+ add_commands $rejectref, 'for address in $ALL_ACASTS; do';
+ }
+
+ incr_cmd_level $rejectref;
+ add_ijump $rejectref, j => 'DROP', d => '$address';
+ decr_cmd_level $rejectref;
+ add_commands $rejectref, 'done';
}
- incr_cmd_level $rejectref;
- add_ijump $rejectref, j => 'DROP', d => '$address';
- decr_cmd_level $rejectref;
- add_commands $rejectref, 'done';
- }
-
- if ( $family == F_IPV4 ) {
- add_ijump $rejectref , j => 'DROP', s => '224.0.0.0/4';
- } else {
- add_ijump $rejectref , j => 'DROP', s => IPv6_MULTICAST;
- }
-
- add_ijump $rejectref , j => 'DROP', p => 2;
- add_ijump $rejectref , j => 'REJECT', targetopts => '--reject-with tcp-reset', p => 6;
-
- if ( have_capability( 'ENHANCED_REJECT' ) ) {
- add_ijump $rejectref , j => 'REJECT', p => 17;
-
if ( $family == F_IPV4 ) {
- add_ijump $rejectref, j => 'REJECT --reject-with icmp-host-unreachable', p => 1;
- add_ijump $rejectref, j => 'REJECT --reject-with icmp-host-prohibited';
+ add_ijump $rejectref , j => 'DROP', s => '224.0.0.0/4';
} else {
- add_ijump $rejectref, j => 'REJECT --reject-with icmp6-addr-unreachable', p => 58;
- add_ijump $rejectref, j => 'REJECT --reject-with icmp6-adm-prohibited';
+ add_ijump $rejectref , j => 'DROP', s => IPv6_MULTICAST;
+ }
+
+ add_ijump $rejectref , j => 'DROP', p => 2;
+ add_ijump $rejectref , j => 'REJECT', targetopts => '--reject-with tcp-reset', p => 6;
+
+ if ( have_capability( 'ENHANCED_REJECT' ) ) {
+ add_ijump $rejectref , j => 'REJECT', p => 17;
+
+ if ( $family == F_IPV4 ) {
+ add_ijump $rejectref, j => 'REJECT --reject-with icmp-host-unreachable', p => 1;
+ add_ijump $rejectref, j => 'REJECT --reject-with icmp-host-prohibited';
+ } else {
+ add_ijump $rejectref, j => 'REJECT --reject-with icmp6-addr-unreachable', p => 58;
+ add_ijump $rejectref, j => 'REJECT --reject-with icmp6-adm-prohibited';
+ }
+ } else {
+ add_ijump $rejectref , j => 'REJECT';
}
- } else {
- add_ijump $rejectref , j => 'REJECT';
}
$list = find_interfaces_by_option 'dhcp';
diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm
index 9855e1ece..7d8c82900 100644
--- a/Shorewall/Perl/Shorewall/Rules.pm
+++ b/Shorewall/Perl/Shorewall/Rules.pm
@@ -54,6 +54,7 @@ our @EXPORT = qw(
perl_action_helper
perl_action_tcp_helper
check_state
+ process_reject_action
);
our @EXPORT_OK = qw( initialize process_rule );
@@ -1635,90 +1636,6 @@ my %builtinops = ( 'dropBcast' => \&dropBcast,
'Limit' => \&Limit,
);
-#
-# This function is called prior to processing of the policy file. It:
-#
-# - Adds the builtin actions to the target table
-# - Reads actions.std and actions (in that order) and for each entry:
-# o Adds the action to the target table
-# o Verifies that the corresponding action file exists
-#
-
-sub process_actions() {
-
- progress_message2 "Locating Action Files...";
- #
- # Add built-in actions to the target table and create those actions
- #
- $targets{$_} = new_action( $_ , ACTION + BUILTIN, 1, 0 ) for @builtins;
-
- for my $file ( qw/actions.std actions/ ) {
- open_file( $file, 2 );
-
- while ( read_a_line( NORMAL_READ ) ) {
- my ( $action, $options ) = split_line 'action file' , { action => 0, options => 1 };
-
- my $type = ACTION;
- my $noinline = 0;
- my $nolog = 0;
- my $builtin = 0;
-
- if ( $action =~ /:/ ) {
- warning_message 'Default Actions are now specified in /etc/shorewall/shorewall.conf';
- $action =~ s/:.*$//;
- }
-
- fatal_error "Invalid Action Name ($action)" unless $action =~ /^[a-zA-Z][\w-]*$/;
-
- if ( $options ne '-' ) {
- for ( split_list( $options, 'option' ) ) {
- if ( $_ eq 'inline' ) {
- $type = INLINE;
- } elsif ( $_ eq 'noinline' ) {
- $noinline = 1;
- } elsif ( $_ eq 'nolog' ) {
- $nolog = 1;
- } elsif ( $_ eq 'builtin' ) {
- $builtin = 1;
- } else {
- fatal_error "Invalid option ($_)";
- }
- }
- }
-
- fatal_error "Conflicting OPTIONS ($options)" if $noinline && $type == INLINE;
-
- if ( my $actiontype = $targets{$action} ) {
- if ( ( $actiontype & ACTION ) && ( $type == INLINE ) ) {
- if ( $actions{$action}->{noinline} ) {
- warning_message "'inline' option ignored on action $action -- that action may not be in-lined";
- next;
- }
-
- delete $actions{$action};
- delete $targets{$action};
- } else {
- warning_message "Duplicate Action Name ($action) Ignored" unless $actiontype & ( ACTION | INLINE );
- next;
- }
- }
-
- if ( $builtin ) {
- $targets{$action} = USERBUILTIN + OPTIONS;
- $builtin_target{$action} = 1;
- } else {
- new_action $action, $type, $noinline, $nolog;
-
- my $actionfile = find_file( "action.$action" );
-
- fatal_error "Missing Action File ($actionfile)" unless -f $actionfile;
-
- $inlines{$action} = { file => $actionfile, nolog => $nolog } if $type == INLINE;
- }
- }
- }
-}
-
sub process_rule ( $$$$$$$$$$$$$$$$$$$ );
#
@@ -1809,6 +1726,96 @@ sub process_action($$) {
pop_action_params( $oldparms );
}
+#
+# This function is called prior to processing of the policy file. It:
+#
+# - Adds the builtin actions to the target table
+# - Reads actions.std and actions (in that order) and for each entry:
+# o Adds the action to the target table
+# o Verifies that the corresponding action file exists
+#
+
+sub process_actions() {
+
+ progress_message2 "Locating Action Files...";
+ #
+ # Add built-in actions to the target table and create those actions
+ #
+ $targets{$_} = new_action( $_ , ACTION + BUILTIN, 1, 0 ) for @builtins;
+
+ for my $file ( qw/actions.std actions/ ) {
+ open_file( $file, 2 );
+
+ while ( read_a_line( NORMAL_READ ) ) {
+ my ( $action, $options ) = split_line 'action file' , { action => 0, options => 1 };
+
+ my $type = ACTION;
+ my $noinline = 0;
+ my $nolog = ( $action eq $config{REJECT_ACTION} ) || 0;
+ my $builtin = 0;
+
+ if ( $action =~ /:/ ) {
+ warning_message 'Default Actions are now specified in /etc/shorewall/shorewall.conf';
+ $action =~ s/:.*$//;
+ }
+
+ fatal_error "Invalid Action Name ($action)" unless $action =~ /^[a-zA-Z][\w-]*$/;
+
+ if ( $options ne '-' ) {
+ for ( split_list( $options, 'option' ) ) {
+ if ( $_ eq 'inline' ) {
+ $type = INLINE;
+ } elsif ( $_ eq 'noinline' ) {
+ $noinline = 1;
+ } elsif ( $_ eq 'nolog' ) {
+ $nolog = 1;
+ } elsif ( $_ eq 'builtin' ) {
+ $builtin = 1;
+ } else {
+ fatal_error "Invalid option ($_)";
+ }
+ }
+ }
+
+ fatal_error "Conflicting OPTIONS ($options)" if $noinline && $type == INLINE;
+
+ if ( my $actiontype = $targets{$action} ) {
+ if ( ( $actiontype & ACTION ) && ( $type == INLINE ) ) {
+ if ( $actions{$action}->{noinline} ) {
+ warning_message "'inline' option ignored on action $action -- that action may not be in-lined";
+ next;
+ }
+
+ delete $actions{$action};
+ delete $targets{$action};
+ } else {
+ warning_message "Duplicate Action Name ($action) Ignored" unless $actiontype & ( ACTION | INLINE );
+ next;
+ }
+ }
+
+ if ( $builtin ) {
+ $targets{$action} = USERBUILTIN + OPTIONS;
+ $builtin_target{$action} = 1;
+ } else {
+ new_action $action, $type, $noinline, $nolog;
+
+ my $actionfile = find_file( "action.$action" );
+
+ fatal_error "Missing Action File ($actionfile)" unless -f $actionfile;
+
+ $inlines{$action} = { file => $actionfile, nolog => $nolog } if $type == INLINE;
+ }
+ }
+ }
+
+ if ( my $action = $config{REJECT_ACTION} ) {
+ my $type = $targets{$action};
+ fatal_error "REJECT_ACTION ($action) was not defined" unless $type;
+ fatal_error "REJECT_ACTION ($action) is not an action" unless $type & (ACTION | INLINE);
+ }
+}
+
#
# Create a policy action if it doesn't already exist
#
@@ -1823,6 +1830,41 @@ sub use_policy_action( $$ ) {
$ref;
}
+#
+# Process the REJECT_ACTION
+#
+sub process_reject_action() {
+ my $rejectref = $filter_table->{reject};
+ my $action = $config{REJECT_ACTION};
+
+ if ( ( $targets{$action} || 0 ) == ACTION ) {
+ add_ijump $rejectref, j => use_policy_action( $action, $rejectref->{name} );
+ } else {
+ process_inline( $action, #Inline
+ $rejectref, #Chain
+ '', #Matches
+ '', #Log Level and Tag
+ $action, #Target
+ '', #Param
+ '-', #Source
+ '-', #Dest
+ '-', #Proto
+ '-', #Ports
+ '-', #Sports
+ '-', #Original Dest
+ '-', #Rate
+ '-', #User
+ '-', #Mark
+ '-', #ConnLimit
+ '-', #Time
+ '-', #Headers
+ '-', #Condition
+ '-', #Helper
+ 0, #Wildcard
+ );
+ }
+}
+
################################################################################
# End of functions moved from the Actions module in 4.4.16
################################################################################
@@ -2007,7 +2049,7 @@ sub process_inline ($$$$$$$$$$$$$$$$$$$$$) {
my $actiontype = $targets{$action} || find_macro( $action );
- fatal_error( "Invalid Action ($mtarget) in inline action" ) unless $actiontype & ( ACTION + STANDARD + NATRULE + MACRO + CHAIN + INLINE );
+ fatal_error( "Invalid Action ($mtarget) in inline action" ) unless $actiontype & ( ACTION + STANDARD + NATRULE + MACRO + CHAIN + INLINE + INLINERULE );
if ( $msource ) {
if ( $msource eq '-' ) {
diff --git a/Shorewall/Samples/Universal/shorewall.conf b/Shorewall/Samples/Universal/shorewall.conf
index afb3ae13b..9f8870129 100644
--- a/Shorewall/Samples/Universal/shorewall.conf
+++ b/Shorewall/Samples/Universal/shorewall.conf
@@ -194,6 +194,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=Yes
RESTORE_DEFAULT_ROUTE=Yes
diff --git a/Shorewall/Samples/one-interface/shorewall.conf b/Shorewall/Samples/one-interface/shorewall.conf
index 3c56f3e98..655dbf444 100644
--- a/Shorewall/Samples/one-interface/shorewall.conf
+++ b/Shorewall/Samples/one-interface/shorewall.conf
@@ -205,6 +205,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_DEFAULT_ROUTE=Yes
diff --git a/Shorewall/Samples/three-interfaces/shorewall.conf b/Shorewall/Samples/three-interfaces/shorewall.conf
index 06ab0f54e..e0fcc9cd6 100644
--- a/Shorewall/Samples/three-interfaces/shorewall.conf
+++ b/Shorewall/Samples/three-interfaces/shorewall.conf
@@ -203,6 +203,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_DEFAULT_ROUTE=Yes
diff --git a/Shorewall/Samples/two-interfaces/shorewall.conf b/Shorewall/Samples/two-interfaces/shorewall.conf
index b0fdb02cf..36722e902 100644
--- a/Shorewall/Samples/two-interfaces/shorewall.conf
+++ b/Shorewall/Samples/two-interfaces/shorewall.conf
@@ -206,6 +206,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_DEFAULT_ROUTE=Yes
diff --git a/Shorewall/configfiles/shorewall.conf b/Shorewall/configfiles/shorewall.conf
index 4a7343363..452124046 100644
--- a/Shorewall/configfiles/shorewall.conf
+++ b/Shorewall/configfiles/shorewall.conf
@@ -194,6 +194,8 @@ OPTIMIZE=0
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_DEFAULT_ROUTE=Yes
diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml
index 584fe8fd9..b7fd8ff11 100644
--- a/Shorewall/manpages/shorewall.conf.xml
+++ b/Shorewall/manpages/shorewall.conf.xml
@@ -2000,7 +2000,7 @@ LOG:info:,bar net fw
PROVIDER_OFFSET=[number]
+ role="bold">PROVIDER_OFFSET=[number]If
Added in Shorewall 4.4.26. The offset from the right
@@ -2095,6 +2095,49 @@ LOG:info:,bar net fw
+
+ REJECT_ACTION=action
+
+
+ Added in Shorewall 4.5.21. When a REJECT target is specified,
+ Shorewall normally handles the response as follows:
+
+
+
+ If the destination address of the packet is a broadcast or
+ multicast address, the packet is dropped.
+
+
+
+ if the protocol is ICMP (2) then the packet is
+ dropped.
+
+
+
+ if the protocol is TCP (6) then the packet is rejected
+ with an RST.
+
+
+
+ if the protocol is ICMP (1) then the packet is rejected
+ with a 'host-unreachable' ICMP.
+
+
+
+ otherwise, the packet is rejected with a 'host-prohibited'
+ ICMP.
+
+
+
+ You can modify this behavior by implementing your own
+ action that handles REJECT and specifying
+ it's name in this option. The nolog
+ option will automatically be assumed for the specified
+ action.
+
+
+
REQUIRE_INTERFACE=[Yes|No]
diff --git a/Shorewall6/Samples6/Universal/shorewall6.conf b/Shorewall6/Samples6/Universal/shorewall6.conf
index 767f08f30..8b9be48d0 100644
--- a/Shorewall6/Samples6/Universal/shorewall6.conf
+++ b/Shorewall6/Samples6/Universal/shorewall6.conf
@@ -177,6 +177,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=Yes
RESTORE_ROUTEMARKS=Yes
diff --git a/Shorewall6/Samples6/one-interface/shorewall6.conf b/Shorewall6/Samples6/one-interface/shorewall6.conf
index 6ca292c39..f2b6781d4 100644
--- a/Shorewall6/Samples6/one-interface/shorewall6.conf
+++ b/Shorewall6/Samples6/one-interface/shorewall6.conf
@@ -177,6 +177,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_ROUTEMARKS=Yes
diff --git a/Shorewall6/Samples6/three-interfaces/shorewall6.conf b/Shorewall6/Samples6/three-interfaces/shorewall6.conf
index 935796ab8..83a1a5e1a 100644
--- a/Shorewall6/Samples6/three-interfaces/shorewall6.conf
+++ b/Shorewall6/Samples6/three-interfaces/shorewall6.conf
@@ -177,6 +177,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_ROUTEMARKS=Yes
diff --git a/Shorewall6/Samples6/two-interfaces/shorewall6.conf b/Shorewall6/Samples6/two-interfaces/shorewall6.conf
index c7e7a3f4d..ecf5de65d 100644
--- a/Shorewall6/Samples6/two-interfaces/shorewall6.conf
+++ b/Shorewall6/Samples6/two-interfaces/shorewall6.conf
@@ -177,6 +177,8 @@ OPTIMIZE=All
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_ROUTEMARKS=Yes
diff --git a/Shorewall6/configfiles/shorewall6.conf b/Shorewall6/configfiles/shorewall6.conf
index 86e2be387..935af8328 100644
--- a/Shorewall6/configfiles/shorewall6.conf
+++ b/Shorewall6/configfiles/shorewall6.conf
@@ -177,6 +177,8 @@ OPTIMIZE=1
OPTIMIZE_ACCOUNTING=No
+REJECT_ACTION=
+
REQUIRE_INTERFACE=No
RESTORE_ROUTEMARKS=Yes
diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml
index 0d08d7524..e4869a5ec 100644
--- a/Shorewall6/manpages/shorewall6.conf.xml
+++ b/Shorewall6/manpages/shorewall6.conf.xml
@@ -1816,6 +1816,8 @@ LOG:info:,bar net fw
on the remote system that the files are to be copied
into.
+
+
@@ -1849,6 +1851,69 @@ LOG:info:,bar net fw
+
+ REJECT_ACTION=action
+
+
+ Added in Shorewall 4.5.21. When a REJECT target is specified,
+ Shorewall normally handles the response as follows:
+
+
+
+ If the destination address of the packet is a broadcast or
+ multicast address, the packet is dropped.
+
+
+
+ if the protocol is ICMP (58) then the packet is
+ dropped.
+
+
+
+ if the protocol is TCP (6) then the packet is rejected
+ with an RST.
+
+
+
+ if the protocol is ICMP (1) then the packet is rejected
+ with a 'addr-unreachable' ICMP.
+
+
+
+ otherwise, the packet is rejected with a 'adm-prohibited'
+ ICMP.
+
+
+
+ You can modify this behavior by implementing your own
+ action that handles REJECT and specifying
+ it's name in this option. The nolog
+ option will automatically be assumed for the specified
+ action.
+
+ The following action implements the standard behavior:
+
+ ?format 2
+#TARGET SOURCE DEST PROTO
+Broadcast(DROP) - - -
+DROP - - 2
+INLINE - - 6 ; -j REJECT --reject-with tcp-reset
+?if __ENHANCED_REJECT
+INLINE - - 17 ; -j REJECT
+?if __IPV4
+INLINE - - 1 ; -j REJECT --reject-with icmp-host-unreachable
+INLINE - - - ; -j REJECT --reject-with icmp-host-prohibited
+?else
+INLINE - - 58 ; -j REJECT --reject-with icmp6-addr-unreachable
+INLINE - - - ; -j REJECT --reject-with icmp6-adm-prohibited
+?endif
+?else
+INLINE - - - ; -j REJECT
+?endif
+
+
+
REQUIRE_INTERFACE=[Yes|No]