diff --git a/fail2ban/lang/en b/fail2ban/lang/en index d42794642..4b8099417 100644 --- a/fail2ban/lang/en +++ b/fail2ban/lang/en @@ -178,9 +178,16 @@ status_head_total_failed=Total failed status_head_currently_banned=Currently banned status_head_total_banned=Total banned status_head_banned_ip_list=Banned IP list +status_jail_unblock_ip=Remove $1 from banned list +status_jail_permblock_ip=Permanently block this IP status_jail_unblock=Unblock All IPs for Selected Jails status_jail_block=Permanently Block All IPs in Banned List for Selected Jails status_jail_noactive=There are no active jails enabled yet. +status_err_set=Failed set action +status_err_unblock=Failed to unblock action +status_err_nojail=No jails has been selected +status_err_unban=Cannot un-ban $1 IP address +status_err_ban=Cannot ban $1 IP address syslog_logtarget=Fail2Ban action log diff --git a/fail2ban/list_status.cgi b/fail2ban/list_status.cgi index 4fe53a3b6..173d18d5b 100755 --- a/fail2ban/list_status.cgi +++ b/fail2ban/list_status.cgi @@ -16,12 +16,14 @@ if (@jails) { my @links = ( &select_all_link("jail"), &select_invert_link("jail") ); my $head; + my @jipsall; foreach my $jail (@jails) { my $fh = 'cmdjail'; my $cmd = "$config{'client_cmd'} status ".quotemeta($jail); my $jcmd = "$cmd 2>&1 ".&html_escape($jail)."")); + my $jips; &open_execute_command($fh, $jcmd, 1); while(<$fh>) { if (/-\s+(.*):\s*(.*)/) { @@ -32,8 +34,17 @@ if (@jails) { if ($col !~ /journal_matches/) { push(@head, $text{"status_head_$col"}); if ($col =~ /banned_ip_list/) { + $jips = $val; my @ips = split(/\s+/, $val); - $val =~ s/\s+/
/g; + @ips = map { &ui_link("unblock_jail.cgi?unblock=1&jips-@{[&urlize($jail)]}=@{[&urlize($_)]}&jail=@{[&urlize($jail)]}", $_, undef, + "title=\"@{[&text('status_jail_unblock_ip', "e_escape($_))]}\" onmouseover=\"this.style.textDecoration='line-through'\" onmouseout=\"this.style.textDecoration='none'\"" + ) . "   " . + &ui_link("unblock_jail.cgi?permblock=1&jips-@{[&urlize($jail)]}=@{[&urlize($_)]}&jail=@{[&urlize($jail)]}", "∅", undef, + "title=\"@{[&text('status_jail_permblock_ip', "e_escape($_))]}\" onmouseover=\"this.style.opacity='1';this.style.filter='grayscale(0)'\" onmouseout=\"this.style.opacity='0.25';this.style.filter='grayscale(100%)'\" style=\"font-size: 125%; filter: grayscale(100%); opacity: .25\"" + ) } @ips; + $val = "
" if ($val); + $val .= join('
', @ips); + $val .= "

" if ($val); } push(@body, $val); } @@ -46,10 +57,14 @@ if (@jails) { print &ui_columns_start(\@head); } print &ui_checked_columns_row(\@body, ['width=5', undef, $tdc, $tdc, $tdc, $tdc], "jail", $jail); + push(@jipsall, ["$jail" => $jips]); } if ($head) { print &ui_columns_end(); print &ui_links_row(\@links); + foreach my $j (@jipsall) { + print &ui_hidden("jips-$j->[0]", "$j->[1]"); + } print &ui_form_end([ [ 'unblock', $text{'status_jail_unblock'} ], [ 'permblock', $text{'status_jail_block'} ] ]); }; diff --git a/fail2ban/unblock_jail.cgi b/fail2ban/unblock_jail.cgi new file mode 100755 index 000000000..7037d1828 --- /dev/null +++ b/fail2ban/unblock_jail.cgi @@ -0,0 +1,54 @@ +#!/usr/local/bin/perl +# Create, update or delete a action + +use strict; +use warnings; +require './fail2ban-lib.pl'; +our (%in, %text, %config); +&ReadParse(); +&error_setup($text{'status_err_set'}); + +my @jails = split(/\0/, $in{'jail'}); +my $action = $in{'permblock'} ? 'block' : $in{'unblock'} ? 'unblock' : undef; + +# Error checks +!$action || $in{'jail'} || &error($text{'status_err_nojail'}); + +# Unblock given IP in given jail +my $unblock_jailed_ip = sub { + my ($jail, $ip) = @_; + my $cmd = "$config{'client_cmd'} set ".quotemeta($jail)." unbanip ".quotemeta($ip)." 2>&1 {'action'}) + if ($opts->{'action'} && + $opts->{'action'} =~ /^accept|reject|drop|mark$/); +} + +# Default zone +if (!$zone) { + my @zones = &list_firewalld_zones(); + ($zone) = grep { $_->{'default'} } @zones; + } +my $zone_name = $zone->{'name'}; +$zone_name =~ tr/A-Za-z0-9\-\_//cd; + +# Validate action +$action eq 'add' || $action eq 'remove' || &error($text{'richrule_actionerr'}); + +# Validate IP +&$ip_validate($ip) || &error($text{'richrule_iperr'}); + +# Set family +my $family = $ip =~ /:/ ? 'ipv6' : 'ipv4'; + +# Apply block (you cannot quotemeta IP address and +# other params, i.e. must be validated manually) +my $get_cmd = sub { + my ($rtype) = @_; + my $type; + $type = " --permanent" if ($rtype eq 'permanent'); + return "$config{'firewall_cmd'} --zone=".$zone_name."$type --$action-rich-rule=\"rule family='$family' source address='$ip' $action_type\""; + }; +my $out = &backquote_logged(&$get_cmd()." 2>&1 &1