Add support for timeouts in temporary rules in FirewallD

https://forum.virtualmin.com/t/fantastic-new-addition-to-firewall-module/134328/10?u=ilia
This commit is contained in:
Ilia Ross
2025-07-25 02:05:50 +03:00
parent f130112177
commit fe8545703d
6 changed files with 79 additions and 3 deletions

View File

@@ -2,3 +2,4 @@ firewall_cmd=firewall-cmd
init_name=firewalld
config_dir=/etc/firewalld
packet_handling=0
timeout=0

View File

@@ -2,3 +2,4 @@ firewall_cmd=Full path to firewall-cmd program,0
init_name=FirewallD init script name,0
config_dir=FirewallD configuration directory,0
packet_handling=Default packet handling action,1,0-<tt>drop</tt>,1-<tt>reject</tt>
timeout=Timeout for temporary rules,15,timeout_data

48
firewalld/config_info.pl Executable file
View File

@@ -0,0 +1,48 @@
require './firewalld-lib.pl';
# show_timeout_data(value, config-option-name)
# Returns a radio button and a select box for timeout values
sub show_timeout_data
{
my ($value, $name) = @_;
$name = &format_option_name($name);
my $radio = &ui_radio(
"${name}_def", !$value ? 1 : 0,
[ [ 1, $text{'config_timeout_none'} ],
[ 0, ' ' ] ] );
my @list = &get_timeouts();
my @opts = map { [ $_, $text{"config_timeout_$_"} ] } @list;
my $select = &ui_select($name, !$value ? $list[3] : $value, \@opts);
return $radio . '&nbsp;' . $select;
}
# parse_timeout_data(old-value, config-option-name)
# Parses the timeout value from the form input
sub parse_timeout_data
{
my ($oldval, $name) = @_;
$name = &format_option_name($name);
my $val = $in{$name} // '';
return 0 if ($in{"${name}_def"});
my %valid = map { $_ => 1 } &get_timeouts();
&error(&text('config_timeout_err', $val)) unless($valid{$val});
return $val;
}
# get_timeouts
# Returns a list of valid timeout values for the select box
sub get_timeouts
{
return qw(1m 5m 15m 30m 1h 3h 6h 12h 1d 3d 7d 30d);
}
# format_option_name(name)
# Formats the option name for use in HTML element names
sub format_option_name
{
my ($name) = @_;
$name =~ s/\s+/_/g;
$name =~ s/[^\x00-\x7F]/_/g;
$name = lc($name);
return $name;
}

View File

@@ -540,6 +540,14 @@ if (!$zone) {
$zone = $zone->{'name'};
}
# Timeout
my $timeout = $opts->{'timeout'};
if ($timeout) {
# Validate timeout format
&error(&text('config_timeout_err', $timeout))
if ($timeout !~ /^(\d+)([smhd]?)$/);
}
# Permanent rule
my $permanent = $opts->{'permanent'};
@@ -548,7 +556,8 @@ my $get_cmd = sub {
my ($rtype) = @_;
my $type = $rtype ? " --permanent" : "";
return "$config{'firewall_cmd'} --zone=\"".quotemeta($zone)."\"".
"$type --".quotemeta($action)."-rich-rule='$opts->{'rule'}'";
"$type --".quotemeta($action)."-rich-rule='$opts->{'rule'}'".
($timeout ? " --timeout=".quotemeta($timeout) : "");
};
for my $type (0..1) {

View File

@@ -50,6 +50,21 @@ index_dependent=Failed to restart $1 dependent service
index_manual=Edit Config Files.
index_downrules=FirewallD rules cannot be created or edited and are not enforced unless the server is running.
config_timeout_none=None
config_timeout_1m=1 minute
config_timeout_5m=5 minutes
config_timeout_15m=15 minutes
config_timeout_30m=30 minutes
config_timeout_1h=1 hour
config_timeout_3h=3 hours
config_timeout_6h=6 hours
config_timeout_12h=12 hours
config_timeout_1d=1 day
config_timeout_3d=3 days
config_timeout_7d=7 days
config_timeout_30d=30 days
config_timeout_err=Invalid timeout value <tt>$1</tt>
manual_title=Edit Config Files
manual_editsel=Edit FirewallD configuration file
manual_err=Failed to save config file

View File

@@ -6,7 +6,7 @@ use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
require './firewalld-lib.pl';
our (%in, %text);
our (%in, %text, %config);
&ReadParse();
# Setup error messages
@@ -31,6 +31,7 @@ $ip =~ s/\Q$mask\E// if ($mask);
# Block the IP
my $perm = $in{'permanent'} ? 'perm' : '';
my $timeout = $config{'timeout'} unless ($perm && $config{'timeout'});
my ($out, $rs) = &rich_rule('add',
{ 'rule' =>
&construct_rich_rule(
@@ -38,7 +39,8 @@ my ($out, $rs) = &rich_rule('add',
'action' => $allow ? 'accept' : undef,
'priority' => $allow ? -32767 : -32766,
),
'zone' => $zone->{'name'}, 'permanent' => $perm });
'zone' => $zone->{'name'}, 'permanent' => $perm,
'timeout' => $timeout });
&error($out) if ($rs);
&apply_firewalld() if ($perm);