# # Shorewall version 5 - Perform an Action based on a Event # # /etc/shorewall/action.IfEvent # # 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 http://www.shorewall.net/Events.html # ####################################################################################################### # DO NOT REMOVE THE FOLLOWING LINE ?format 2 ################################################################################################################################################################################################# #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS SWITCH HELPER # PORT PORT(S) DEST LIMIT GROUP 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 ( $command & $RESET_CMD ) { require_capability 'MARK_ANYWHERE', '"reset"', 's'; print "Resetting....\n"; 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" ); } 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