# # Shorewall -- /usr/share/shorewall/action.IfEvent # # Perform an Action based on a Event # # Parameters: # # Event - Must start with a letter and be composed of letters, digits, # '-', and '_'. # Action - Anything that can appear in the ACTION column of a rule. # Duration - Duration in seconds over which the event is to be tested. # Hit Count - Number of packets seen within the duration -- default is 1 # Src or Dest - 'src' (default) or 'dst'. Determines if the event is # associated with the source address (src) or destination # address (dst) # Command - 'check' (default) 'reset', or 'update'. If 'reset', # the event will be reset before the Action is taken. # If 'update', the timestamp associated with the event will # be updated and the action taken if the time limit/hitcount # are matched. # If '-', the action will be taken if the limit/hitcount are # matched but the event's timestamp will not be updated. # # If a duration is specified, then 'checkreap' and 'updatereap' # may also be used. These are like 'check' and 'update' # respectively, but they also remove any event entries for # the IP address that are older than seconds. # Disposition - Disposition for any event generated. # # For additional information, see https://shorewall.org/Events.html # ############################################################################### # DO NOT REMOVE THE FOLLOWING LINE ############################################################################### #ACTION SOURCE DEST PROTO DPORT SPORT DEFAULTS -,ACCEPT,-,1,src,check,- ?begin perl use Shorewall::Config qw(:DEFAULT :internal); use Shorewall::Chains; use Shorewall::Rules; use strict; my ( $event, $action, $duration, $hitcount, $destination, $command, $disposition ) = get_action_params( 7 ); fatal_error "An event name is required" unless supplied $event; fatal_error "Invalid event name ($event)" unless $event =~ /^[a-zA-z][-\w]*$/; if ( supplied $duration ) { fatal_error "Invalid time limit ($duration)" unless $duration =~ /^\d+$/; $duration = "--seconds $duration "; } else { $duration = ''; } fatal_error "Invalid hit count ($hitcount)" unless $hitcount =~ /^\d+$/; fatal_error "Invalid Src or Dest ($destination)" unless $destination =~ /^(?:src|dst)$/; my $srcdst = $destination eq 'src'? '--rsource' : '--rdest'; our $commands_defined; # # Can't 'use constant' here # my ( $UPDATE_CMD, $CHECK_CMD, $RESET_CMD, $REAP_OPT, $TTL_OPT ) = ( 1, 2, 4, 8, 16 ); my %command = ( check => $CHECK_CMD, update => $UPDATE_CMD, reset => $RESET_CMD ); my %commandopts = ( reap => $REAP_OPT, ttl => $TTL_OPT ); my @command = split(':', $command); $command = $command{shift @command} || 0; fatal_error "Command must be 'check', 'update' or 'reset" unless $command & ( $CHECK_CMD | $UPDATE_CMD | $RESET_CMD); for ( @command ) { fatal_error "Invalid command option ($_)" unless $commandopts{$_}; if ( $command & $commandopts{$_} ) { warning_message "Duplicate command ($_)"; } else { $command |= $commandopts{$_}; } } my $duplicate; set_action_disposition( $disposition) if supplied $disposition; set_action_name_to_caller; require_capability 'RECENT_MATCH', 'Use of events', 's'; if ( $command & $REAP_OPT ) { require_capability( 'REAP_OPTION', q(The 'reap' option), 's' ); fatal_error "${command}reap requires a time limit" unless $duration; $duration .= '--reap '; } $duration .= '--rttl ' if $command & $TTL_OPT; if ( ( $targets{$action} || 0 ) & NATRULE ) { perl_action_helper( "${action}-", "-m recent --rcheck ${duration}--hitcount $hitcount" ); $action = 'ACCEPT'; } if ( $command & $RESET_CMD ) { require_capability 'MARK_ANYWHERE', '"reset"', 's'; my $mark = $globals{EVENT_MARK}; # # The event mark bit must be within 32 bits # fatal_error "The mark layout does not permit resetting of events" unless $mark & 0xffffffff; # # Reset the event mark bit # perl_action_helper( 'INLINE', '-j MARK --and-mark '. in_hex( (~ $mark ) & 0xffffffff ) ); $mark = in_hex $mark; # # Mark the packet if event is armed # perl_action_helper( 'INLINE', "-m recent --rcheck ${duration}--hitcount $hitcount --name $event $srcdst -j MARK --or-mark $mark" ); # # if the event is armed, remove it and perform the action # perl_action_helper( $action , "-m mark --mark $mark/$mark -m recent --remove --name $event $srcdst" ); } elsif ( $command & $UPDATE_CMD ) { perl_action_helper( $action, "-m recent --update ${duration}--hitcount $hitcount --name $event $srcdst" ); } else { perl_action_helper( $action, "-m recent --rcheck ${duration}--hitcount $hitcount --name $event $srcdst" ); } 1; ?end perl