NAME

Net::Firewall::BlockerHelper - Helps with managing firewalls for banning IPs.

VERSION

Version 0.2.0

SYNOPSIS

use Net::Firewall::BlockerHelper;

# create a instance named ssh with a ipfw backend for port 22 tcp
my $fw_helper;
eval {
    $fw_helper = Net::Firewall::BlockerHelper->new(
            backend => 'ipfw',
            ports => ['22'],
            protocols => ['tcp'],
            name => 'ssh',
        );
};
if ($@) {
    print 'Error: '
        . $Error::Helper::error
        . "\nError String: "
        . $Error::Helper::errorString
        . "\nError Flag: "
        . $Error::Helper::errorFlag . "\n";
}

# start the backend
$fw_helper->init_backend;

# ban some IPs
$fw_helper->ban(ban => '1.2.3.4');
$fw_helper->ban(ban => '5.6.7.8');

# unban a IP
$fw_helper->unban(ban => '1.2.3.4');

# get a list of banned IPs
my @banned = $fw_helper->list;
foreach my $ip (@banned) {
    print 'Banned IP: '.$ip."\n";
}

# teardown the backend, re-init, and re-ban everything
$fw_helper->re_init;

# teardown the backend
$fw_helper->teardown;

METHODS

new

Initiates the the object.

- backend :: The backend to use. This must be specified.
    - Default :: undef

- options :: Backend specific options that will be passed to the backend unchecked
        outside of making sure it is a hash ref if defined.
    - Default :: {}

- ports :: A array of ports to block. Checked to make sure they are ints within
        the range 1 to 65535 or a valid service name via getservbyname.
    - Default :: []

- protocols :: A array of protocols to block. By default will block all. This
        is checked against /etc/protocols via the function getprotobyname.
    - Default :: []

- prefix :: Prefix to use. Must match the regex /^[a-zA-Z0-9]+$/
    - default :: kur

- name :: Name of this specific instance.
    - default :: undef

- self_heal :: Before each ban or unban, verify the firewall setup is
        still present (via the backend's check) and re_init it if it was
        removed externally. This is the fail2ban actioncheck-before-action
        behavior. Adds one check probe per ban/unban. Can be overridden per
        call by passing self_heal to ban/unban.
    - default :: 1

All errors are considered fatal, meaning if new fails it will die.

my $fw_helper;
eval {
    $fw_helper = Net::Firewall::BlockerHelper->new(
            backend => 'ipfw',
            ports => ['22'],
            protocols => ['tcp'],
            name => 'ssh',
        );
};
if ($@) {
    print 'Error: '
        . $Error::Helper::error
        . "\nError String: "
        . $Error::Helper::errorString
        . "\nError Flag: "
        . $Error::Helper::errorFlag . "\n";
}

init_backend

Initiates the backend, creating the backend object and running its init. A failure is raised as backendInitError.

No arguments are taken.

$fw_helper->init_backend;

ban

Bans an IP. The value of ban is validated as being a IPv4 or IPv6 address and lowercased, then handed to the backend to ban. If self healing is enabled, the backend setup is checked and restored first. A backend failure is caught and re-raised as banFailed.

$fw_helper->ban(ban => $ip);

ban_cidr

Bans a CIDR range.

Only backends whose underlying firewall can match on a network prefix support this. For backends that do not, the cidrNotSupported error is set. See the individual backends for which support it.

$fw_helper->ban_cidr(ban => '1.2.3.0/24');

unban

Unbans an IP. The value of ban is validated as being a IPv4 or IPv6 address and lowercased, then handed to the backend to unban. If self healing is enabled, the backend setup is checked and restored first. A backend failure is caught and re-raised as unbanFailed.

$fw_helper->unban(ban => $ip);

unban_cidr

Unbans a CIDR range.

Only backends whose underlying firewall can match on a network prefix support this. For backends that do not, the cidrNotSupported error is set.

$fw_helper->unban_cidr(ban => '1.2.3.0/24');

list

List banned IPs. Returns an array of the currently banned single IPs as reported by the backend. CIDR range bans are not included; for those see "list_cidr".

my @banned = $fw_helper->list;

list_cidr

List banned CIDR ranges. Backends that do not support CIDR bans always return an empty list.

my @banned_cidrs = $fw_helper->list_cidr;

re_init

Tells the backend to re-init itself, rebuilding its firewall setup and re-applying the current ban list. A backend failure is caught and re-raised as reInitFailed.

The backend does not need to be inited for this to work, so as well as recovering a setup that was removed externally, this is what brings one back after a "teardown" or "stop". The ban list is held on the backend object and survives both, so the bans are re-applied rather than lost.

$fw_helper->re_init;

# resuming after a stop
$fw_helper->stop;
$fw_helper->re_init;

teardown

Tells the backend to tear down its firewall setup, the equivalent of fail2ban's actionstop. The ban list is retained by the backend so a following "re_init" restores it. A backend failure is caught and re-raised as teardownFailed.

$fw_helper->teardown;

stop

Alias for "teardown", provided for parity with the fail2ban actionstop concept.

$fw_helper->stop;

check

Asks the backend to verify that its firewall setup is still intact. This is the equivalent of fail2ban's actioncheck. Returns a true value if the setup is present and a false value if it appears to have been removed (in which case a "re_init" is warranted). On an internal error it sets the error and returns undef.

if ( !$fw_helper->check ) {
    $fw_helper->re_init;
}

flush

Removes all currently banned IPs at once while leaving the firewall rules in place. This is the equivalent of fail2ban's actionflush. Unlike "teardown", the blocking rules remain active, so new bans work without a "re_init".

$fw_helper->flush;

commit

Tells the backend to write out any state it has been holding back from persistent storage.

Most backends have nothing to hold back, as the firewall they drive is the only copy of the state, and those do not implement this at all; calling it for one of them sets the commitNotSupported error. Net::Firewall::BlockerHelper::backends::openwrt is currently the only backend that does implement it, where bans are applied to the live nftables sets straight away but only reach the UCI config, and so the router's flash, when this is called.

Where a backend does implement it, it is safe to call as often as wanted and is a noop when there is nothing outstanding. How often it is worth calling is a trade off between how much of the ban list can be lost and, for a backend writing to flash, how much wear is acceptable.

$fw_helper->ban(ban => '1.2.3.4');
$fw_helper->ban(ban => '5.6.7.8');
$fw_helper->commit;

ERROR CODES / FLAGS

Error handling is provided by Error::Helper. All errors are considered fatal.

1, noBackendSpecified

No backend was specified to use.

2, invalidPortSpecified

Port is either not an int within the range 1 to 65535 or a name that can be resolved by getservbyname.

3, portsNotArray

The data passed to new for ports is not an array.

4, protocolsNotArray

The data passed to new for protocols is not an array.

5, invalidPortSpecified

Port is either not an int within the range 1 to 65535 or a name that can be resolved by getservbyname.

6, invalidPrefixSpecified

The specified prefix did not match /^[a-zA-Z0-9]+$/.

7, invalidName

The name is either undef or does not match /^[a-zA-Z0-9\-]+$/.

8, optionsNotHash

The item passed to new for options is not a hash.

9, noBanItem

No IP specified to ban.

10, banItemNotIP

The item to ban is not an IP. Either wrong ref type or regexp test using Regexp::IPv4 and Regexp::IPv6 failed.

11, invalidBackend

The specified backend failed to pass a basic sanity check of making sure it matches the regexp /^[a-zA-Z0-9\_]+$/.

12, backendInitError

Failed to init the backend.

13, banFailed

Failed to ban the item.

14, unbanFailed

Failed to unban the item.

15, listFailed

Failed get a list of bans.

16, reInitFailed

Failed to re_init the backend.

17, teardownFailed

Failed to teardown the backend.

24, checkFailed

The backend check raised an error.

25, flushFailed

Failed to flush the bans.

26, banCidrFailed

Failed to ban the CIDR range.

27, unbanCidrFailed

Failed to unban the CIDR range.

28, cidrItemNotCidr

The item to ban is not a CIDR range. Either wrong ref type or it is not an IPv4 or IPv6 address followed by a prefix length valid for its family.

29, cidrNotSupported

The selected backend does not support CIDR bans.

30, listCidrFailed

Failed to get a list of CIDR bans.

31, commitFailed

Failed to commit the backend's outstanding state.

32, commitNotSupported

The selected backend does not implement commit, having no state that is held back from persistent storage.

AUTHOR

Zane C. Bowers-Hadley, <vvelox at vvelox.ent>

BUGS

Please report any bugs or feature requests to bug-net-firewall-blockerhelper at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Firewall-BlockerHelper. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Net::Firewall::BlockerHelper

You can also look for information at:

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by Zane C. Bowers-Hadley.

This is free software, licensed under:

The GNU Lesser General Public License, Version 2.1, February 1999