HEX
Server: Apache
System: Linux falcon1.webguru.ng 5.15.0-177-generic #187-Ubuntu SMP Sat Apr 11 22:54:33 UTC 2026 x86_64
User: property (1150)
PHP: 8.1.34
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //sbin/csf
#!/usr/local/cpanel/3rdparty/bin/perl
###############################################################################
# Copyright (C) 2006-2025 Jonathan Michaelson
#
# https://github.com/waytotheweb/scripts
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, see <https://www.gnu.org/licenses>.
###############################################################################

# Strip PERL5LIB paths when running csf in the event of rogue .bashrc environment variables.
BEGIN {
    index( $^X, '/usr/local/cpanel/3rdparty' ) == 0 or die "This program requires cpanel-perl\n";

    if ( length $ENV{'PERL5LIB'} ) {
        shift @INC while ( $INC[0] ne '/usr/local/cpanel' );
    }
}

package sbin::csf;
use cPstrict;
no warnings;

use lib '/usr/local/csf/lib';
use Fcntl qw(:DEFAULT :flock);
use File::Basename;
use IO::Handle;
use IPC::Open3 ();
use IO::Select;
use Net::CIDR::Lite;
use Socket;
use ConfigServer::Config;
use ConfigServer::Slurp   qw(slurp slurpee);
use ConfigServer::CheckIP qw(checkip cccheckip);
use ConfigServer::Ports;
use ConfigServer::URLGet;
use ConfigServer::Sanity ();
use ConfigServer::ServerCheck;
use ConfigServer::ServerStats;
use ConfigServer::Service;
use ConfigServer::Messenger;
use ConfigServer::RBLCheck;
use ConfigServer::GetEthDev ();
use ConfigServer::Sendmail;
use ConfigServer::LookUpIP qw(iplookup);

umask(0177);

our (
    $verbose,        $version,     $logintarget,    $noowner,         $warning,  $accept, $ipscidr,
    $ipv6reg,        $ipv4reg,     $ethdevin,       $ethdevout,       $ipscidr6, $eth6devin,
    $eth6devout,     $statemodule, $logouttarget,   $cleanreg,        $slurpreg,
    $faststart,      $urlget,      $statemodulenew, $statemodule6new, $cxsreputation,
    $csflockfile_fh, $iptableslock_fh
);

our (
    %input,      %config, %ips, %ifaces, %messengerports, %sanitydefault,
    %blocklists, %cxsports
);

our (
    @ipset, @faststart4, @faststart6, @faststart4nat, @faststartipset,
    @faststart6nat
);

# Run main script logic only when executed directly, not when loaded as module
__PACKAGE__->run() unless caller;

sub run {
    my $class = shift;

    # Initialize package variables
    $version = version();

    $ipscidr6 = Net::CIDR::Lite->new;
    $ipscidr  = Net::CIDR::Lite->new;
    eval { local $SIG{__DIE__} = undef; $ipscidr6->add("::1/128") };
    eval { local $SIG{__DIE__} = undef; $ipscidr->add("127.0.0.0/8") };

    $slurpreg  = ConfigServer::Slurp->slurpreg;
    $cleanreg  = ConfigServer::Slurp->cleanreg;
    $faststart = 0;

    process_input();
    load_config();

    $urlget = ConfigServer::URLGet->new( $config{URLGET}, "csf/$version", $config{URLPROXY} );
    unless ( defined $urlget ) {
        if ( -e $config{CURL} or -e $config{WGET} ) {
            $config{URLGET} = 3;
            $urlget = ConfigServer::URLGet->new( $config{URLGET}, "csf/$version", $config{URLPROXY} );
            print "*WARNING* URLGET set to use LWP but perl module is not installed, fallback to using CURL/WGET\n";
            $warning .= "*WARNING* URLGET set to use LWP but perl module is not installed, fallback to using CURL/WGET\n";
        }
        else {
            $config{URLGET} = 1;
            $urlget = ConfigServer::URLGet->new( $config{URLGET}, "csf/$version", $config{URLPROXY} );
            print "*WARNING* URLGET set to use LWP but perl module is not installed, reverting to HTTP::Tiny\n";
            $warning .= "*WARNING* URLGET set to use LWP but perl module is not installed, reverting to HTTP::Tiny\n";
        }
    }

    if ( ( -e "/etc/csf/csf.disable" ) and ( $input{command} ne "--enable" ) and ( $input{command} ne "-e" ) ) {
        print "csf and lfd have been disabled, use 'csf -e' to enable\n";
        my $ok = 0;
        foreach my $opt ( "--version", "-v", "--check", "-c", "--ports", "-p", "--help", "-h", "--update", "-u", "-uf", "--flush", "-f", "--profile", "" ) {
            if ( $input{command} eq $opt ) {
                $ok = 1;
                last;
            }
        }
        unless ($ok) { return 1 }
    }
    unless ( -e $config{IPTABLES} )                         { error( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} (iptables binary location) does not exist!" ) }
    if     ( $config{IPV6} and !( -e $config{IP6TABLES} ) ) { error( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} (ip6tables binary location) does not exist!" ) }

    if ( ( -e "/etc/csf/csf.error" ) and ( $input{command} ne "--startf" ) and ( $input{command} ne "-sf" ) and ( $input{command} ne "-q" ) and ( $input{command} ne "--startq" ) and ( $input{command} ne "--start" ) and ( $input{command} ne "-s" ) and ( $input{command} ne "--restart" ) and ( $input{command} ne "-r" ) and ( $input{command} ne "--enable" ) and ( $input{command} ne "-e" ) ) {
        my ($error) = slurpee( "/etc/csf/csf.error", 'fatal' => 1 );
        chomp $error;
        print "You have an unresolved error when starting csf:\n$error\n\nYou need to restart csf successfully to remove this warning, or delete /etc/csf/csf.error\n";
        return 1;
    }

    unless ( $input{command} =~ /^--(stop|initdown|initup)$/ ) {
        if ( -e "/var/lib/csf/csf.4.saved" )  { unlink "/var/lib/csf/csf.4.saved" }
        if ( -e "/var/lib/csf/csf.4.ipsets" ) { unlink "/var/lib/csf/csf.4.ipsets" }
        if ( -e "/var/lib/csf/csf.6.saved" )  { unlink "/var/lib/csf/csf.6.saved" }
    }

    if    ( ( $input{command} eq "--status" ) or ( $input{command} eq "-l" ) )   { dostatus() }
    elsif ( ( $input{command} eq "--status6" ) or ( $input{command} eq "-l6" ) ) { dostatus6() }
    elsif ( ( $input{command} eq "--version" ) or ( $input{command} eq "-v" ) )  { doversion() }
    elsif ( ( $input{command} eq "--stop" ) or ( $input{command} eq "-f" ) )     { csflock("lock"); dostop(0); csflock("unlock") }
    elsif ( ( $input{command} eq "--startf" ) or ( $input{command} eq "-sf" ) )  { csflock("lock"); dostop(1); dostart(); csflock("unlock") }
    elsif ( ( $input{command} eq "--start" ) or ( $input{command} eq "-s" ) or ( $input{command} eq "--restart" ) or ( $input{command} eq "-r" ) ) {
        if   ( $config{LFDSTART} ) { lfdstart() }
        else                       { csflock("lock"); dostop(1); dostart(); csflock("unlock") }
    }
    elsif ( ( $input{command} eq "--startq" ) or ( $input{command} eq "-q" ) )       { lfdstart() }
    elsif ( ( $input{command} eq "--restartall" ) or ( $input{command} eq "-ra" ) )  { dorestartall() }
    elsif ( ( $input{command} eq "--add" ) or ( $input{command} eq "-a" ) )          { doadd() }
    elsif ( ( $input{command} eq "--deny" ) or ( $input{command} eq "-d" ) )         { dodeny() }
    elsif ( ( $input{command} eq "--denyrm" ) or ( $input{command} eq "-dr" ) )      { dokill() }
    elsif ( ( $input{command} eq "--denyf" ) or ( $input{command} eq "-df" ) )       { dokillall() }
    elsif ( ( $input{command} eq "--addrm" ) or ( $input{command} eq "-ar" ) )       { doakill() }
    elsif ( ( $input{command} eq "--disable" ) or ( $input{command} eq "-x" ) )      { csflock("lock"); dodisable(); csflock("unlock") }
    elsif ( ( $input{command} eq "--enable" ) or ( $input{command} eq "-e" ) )       { csflock("lock"); doenable();  csflock("unlock") }
    elsif ( ( $input{command} eq "--check" ) or ( $input{command} eq "-c" ) )        { docheck() }
    elsif ( ( $input{command} eq "--grep" ) or ( $input{command} eq "-g" ) )         { dogrep() }
    elsif ( ( $input{command} eq "--iplookup" ) or ( $input{command} eq "-i" ) )     { doiplookup() }
    elsif ( ( $input{command} eq "--temp" ) or ( $input{command} eq "-t" ) )         { dotempban() }
    elsif ( ( $input{command} eq "--temprm" ) or ( $input{command} eq "-tr" ) )      { dotemprm() }
    elsif ( ( $input{command} eq "--temprma" ) or ( $input{command} eq "-tra" ) )    { dotemprma() }
    elsif ( ( $input{command} eq "--temprmd" ) or ( $input{command} eq "-trd" ) )    { dotemprmd() }
    elsif ( ( $input{command} eq "--tempdeny" ) or ( $input{command} eq "-td" ) )    { dotempdeny() }
    elsif ( ( $input{command} eq "--tempallow" ) or ( $input{command} eq "-ta" ) )   { dotempallow() }
    elsif ( ( $input{command} eq "--tempf" ) or ( $input{command} eq "-tf" ) )       { dotempf() }
    elsif ( ( $input{command} eq "--mail" ) or ( $input{command} eq "-m" ) )         { domail() }
    elsif ( ( $input{command} eq "--cdeny" ) or ( $input{command} eq "-cd" ) )       { doclusterdeny() }
    elsif ( ( $input{command} eq "--ctempdeny" ) or ( $input{command} eq "-ctd" ) )  { doclustertempdeny() }
    elsif ( ( $input{command} eq "--callow" ) or ( $input{command} eq "-ca" ) )      { doclusterallow() }
    elsif ( ( $input{command} eq "--ctempallow" ) or ( $input{command} eq "-cta" ) ) { doclustertempallow() }
    elsif ( ( $input{command} eq "--crm" ) or ( $input{command} eq "-cr" ) )         { doclusterrm() }
    elsif ( ( $input{command} eq "--carm" ) or ( $input{command} eq "-car" ) )       { doclusterarm() }
    elsif ( ( $input{command} eq "--cignore" ) or ( $input{command} eq "-ci" ) )     { doclusterignore() }
    elsif ( ( $input{command} eq "--cirm" ) or ( $input{command} eq "-cir" ) )       { doclusterirm() }
    elsif ( ( $input{command} eq "--cping" ) or ( $input{command} eq "-cp" ) )       { clustersend("PING") }
    elsif ( ( $input{command} eq "--cgrep" ) or ( $input{command} eq "-cg" ) )       { doclustergrep() }
    elsif ( ( $input{command} eq "--cconfig" ) or ( $input{command} eq "-cc" ) )     { docconfig() }
    elsif ( ( $input{command} eq "--cfile" ) or ( $input{command} eq "-cf" ) )       { docfile() }
    elsif ( ( $input{command} eq "--crestart" ) or ( $input{command} eq "-crs" ) )   { docrestart() }
    elsif ( ( $input{command} eq "--watch" ) or ( $input{command} eq "-w" ) )        { dowatch() }
    elsif ( ( $input{command} eq "--logrun" ) or ( $input{command} eq "-lr" ) )      { dologrun() }
    elsif ( ( $input{command} eq "--ports" ) or ( $input{command} eq "-p" ) )        { doports() }
    elsif ( $input{command} eq "--cloudflare" )                                      { docloudflare() }
    elsif ( $input{command} eq "--graphs" )                                          { dographs() }
    elsif ( $input{command} eq "--lfd" )                                             { dolfd() }
    elsif ( $input{command} eq "--rbl" )                                             { dorbls() }
    elsif ( $input{command} eq "--initup" )                                          { doinitup() }
    elsif ( $input{command} eq "--initdown" )                                        { doinitdown() }
    elsif ( $input{command} eq "--profile" )                                         { doprofile() }
    elsif ( $input{command} eq "--mregen" )                                          { domessengerv2() }
    elsif ( $input{command} eq "--trace" )                                           { dotrace() }
    else                                                                             { dohelp() }

    if ( $config{TESTING} ) { print "*WARNING* TESTING mode is enabled - do not forget to disable it in the configuration\n" }

    if ( ( $input{command} eq "--start" ) or ( $input{command} eq "-s" ) or ( $input{command} eq "--restart" ) or ( $input{command} eq "-r" ) or ( $input{command} eq "--restartall" ) or ( $input{command} eq "-ra" ) ) {
        if ($warning) { print $warning }
        foreach my $key ( keys %config ) {
            my ( $insane, $range, $default ) = ConfigServer::Sanity::sanity( $key, $config{$key} );
            if ($insane) { print "*WARNING* $key sanity check. $key = $config{$key}. Recommended range: $range (Default: $default)\n" }
        }
        unless ( $config{RESTRICT_SYSLOG} ) { print "\n*WARNING* RESTRICT_SYSLOG is disabled. See SECURITY WARNING in /etc/csf/csf.conf.\n" }
    }

    return 0;
}

# End of run() subroutine - all other subroutines follow below

sub csflock {
    my $lock = shift;
    if ( $lock eq "lock" ) {
        sysopen( $csflockfile_fh, "/var/lib/csf/csf.lock", O_RDWR | O_CREAT ) or die("Error: Unable to open csf lock file: $!");
        flock( $csflockfile_fh, LOCK_EX | LOCK_NB )                           or die "Error: csf is being restarted, try again in a moment: $!";
    }
    else {
        close($csflockfile_fh) if defined $csflockfile_fh;
    }
    return;
}

sub load_config {
    my $config = ConfigServer::Config->loadconfig();
    %config = $config->config;
    my %configsetting = $config->configsetting;
    $ipv4reg = $config->ipv4reg;
    $ipv6reg = $config->ipv6reg;
    $warning .= $config->{warning} // "";

    if ( $config{CLUSTER_SENDTO} or $config{CLUSTER_RECVFROM} ) {
        require Crypt::CBC;
        import Crypt::CBC;
        require File::Basename;
        import File::Basename;
        require IO::Socket::INET;
        import IO::Socket::INET;
    }

    if ( $config{CF_ENABLE} ) {
        require ConfigServer::CloudFlare;
        import ConfigServer::CloudFlare;
    }

    $verbose = "";
    if ( $config{VERBOSE} or $config{DEBUG} >= 1 ) { $verbose = "-v" }

    $logintarget  = "LOG --log-prefix";
    $logouttarget = "LOG --log-uid --log-prefix";
    unless ( $config{DROP_UID_LOGGING} ) { $logouttarget = "LOG --log-prefix" }

    $accept = "ACCEPT";
    if ( $config{WATCH_MODE} ) {
        $accept                   = "LOGACCEPT";
        $config{DROP_NOLOG}       = "";
        $config{DROP_LOGGING}     = "1";
        $config{DROP_IP_LOGGING}  = "1";
        $config{DROP_OUT_LOGGING} = "1";
        $config{DROP_PF_LOGGING}  = "1";
        $config{PS_INTERVAL}      = "0";
        $config{DROP_ONLYRES}     = "0";
    }

    if ( $config{MESSENGER} ) {
        foreach my $port ( split( /\,/, $config{MESSENGER_HTTPS_IN} ) ) { $messengerports{$port} = 1 }
        foreach my $port ( split( /\,/, $config{MESSENGER_HTML_IN} ) )  { $messengerports{$port} = 1 }
        foreach my $port ( split( /\,/, $config{MESSENGER_TEXT_IN} ) )  { $messengerports{$port} = 1 }
    }

    $statemodule = "-m state --state";
    if ( $config{USE_CONNTRACK} ) { $statemodule = "-m conntrack --ctstate" }
    if ( $config{LF_SPI} ) {
        $statemodulenew = "$statemodule NEW";
    }
    else {
        $statemodulenew = "";
    }
    if ( $config{IPV6_SPI} ) {
        $statemodule6new = "$statemodule NEW";
    }
    else {
        $statemodule6new = "";
    }

    my @entries = slurp("/etc/csf/csf.blocklists");
    foreach my $line (@entries) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @entries, @incfile;
        }
    }
    foreach my $line (@entries) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $name, $interval, $max, $url ) = split( /\|/, $line );
        if ( $name =~ /^\w+$/ ) {
            $name = substr( uc $name, 0, 25 );
            if ( $name =~ /^CXS_/ ) { $name =~ s/^CXS_/X_CXS_/ }
            if ( $interval < 3600 ) { $interval = 3600 }
            if ( $max eq "" )       { $max = 0 }
            $blocklists{$name}{interval} = $interval;
            $blocklists{$name}{max}      = $max;
            $blocklists{$name}{url}      = $url;
        }
    }
    if ( -e "/etc/cxs/cxs.reputation" and -e "/usr/local/csf/lib/ConfigServer/cxs.pm" ) {
        require ConfigServer::cxs;
        import ConfigServer::cxs;
        $cxsreputation = 1;
        if ( -e "/etc/cxs/cxs.blocklists" ) {
            my $all   = 0;
            my @lines = slurp("/etc/cxs/cxs.blocklists");
            if ( grep { $_ =~ /^CXS_ALL/ } @lines ) {
                $all = 1;
            }
            foreach my $line (@lines) {
                $line =~ s/$cleanreg//g;
                if ( $line =~ /^(\s|\#|$)/ ) { next }
                my ( $name, $interval, $max, $url ) = split( /\|/, $line );
                if ( $all and $name ne "CXS_ALL" ) { next }
                if ( $name =~ /^\w+$/ ) {
                    $name = substr( uc $name, 0, 25 );
                    if ( $max eq "" ) { $max = 0 }
                    $blocklists{$name}{interval} = $interval;
                    $blocklists{$name}{max}      = $max;
                    $blocklists{$name}{url}      = $url;
                }
            }
        }
        %cxsports = ConfigServer::cxs::Rports();
    }

    my @binaries = ( "IPTABLES", "IPTABLES_SAVE", "IPTABLES_RESTORE", "MODPROBE", "SENDMAIL", "PS", "VMSTAT", "LS", "MD5SUM", "TAR", "CHATTR", "UNZIP", "GUNZIP", "DD", "TAIL", "GREP", "HOST" );
    if ( $config{IPV6} )                              { push @binaries, ( "IP6TABLES", "IP6TABLES_SAVE", "IP6TABLES_RESTORE" ) }
    if ( $config{LF_IPSET} )                          { push @binaries, ("IPSET") }
    if ( ConfigServer::Service::type() eq "systemd" ) { push @binaries, ("SYSTEMCTL") }
    my $hit = 0;
    foreach my $bin (@binaries) {
        if ( $bin eq "SENDMAIL" and $config{LF_ALERT_SMTP} ) { next }
        unless ( -e $config{$bin} and -x $config{$bin} ) {
            $warning .= "*WARNING* Binary location for [$bin] [$config{$bin}] in /etc/csf/csf.conf is either incorrect, is not installed or is not executable\n";
            $hit = 1;
        }
    }
    my $iphit = 0;
    if     ( -e $config{IP} or -e $config{IFCONFIG} ) { $iphit = 1 }
    unless ($iphit) {
        $warning .= "*WARNING* Binary location for either [IP] [$config{IP}] or [IFCONFIG] [$config{IFCONFIG}] in /etc/csf/csf.conf must be set correctly, installed and executable\n";
        $hit = 1;
    }
    if ($hit) { $warning .= "*WARNING* Missing or incorrect binary locations will break csf and lfd functionality\n" }
    return;
}

sub process_input {

    # Make a copy of @ARGV to avoid modifying it as it is used elsewhere in the script
    my @arguments = @ARGV;
    $input{command}  = lc shift @arguments;
    $input{argument} = \@arguments;

    # Some functions use the rest of the arguments as a comment
    $input{comment} = join( " ", @arguments[ 1 .. $#arguments ] );
    return;
}

sub dostatus {
    print "iptables filter table\n";
    print "=====================\n";
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers" );
    if ( $config{MANGLE} ) {
        print "\n\n";
        print "iptables mangle table\n";
        print "=====================\n";
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers" );
    }
    if ( $config{RAW} ) {
        print "\n\n";
        print "iptables raw table\n";
        print "==================\n";
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers" );
    }
    if ( $config{NAT} ) {
        print "\n\n";
        print "iptables nat table\n";
        print "==================\n";
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers" );
    }
    return;
}

sub dostatus6 {
    if ( $config{IPV6} ) {
        print "ip6tables filter table\n";
        print "======================\n";
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers" );
        if ( $config{MANGLE6} ) {
            print "\n\n";
            print "ip6tables mangle table\n";
            print "======================\n";
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers" );
        }
        if ( $config{RAW6} ) {
            print "\n\n";
            print "ip6tables raw table\n";
            print "===================\n";
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers" );
        }
        if ( $config{NAT6} ) {
            print "\n\n";
            print "ip6tables nat table\n";
            print "===================\n";
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers" );
        }
    }
    else {
        print "csf: IPV6 firewall not enabled\n";
    }
    return;
}

sub doversion {
    print "csf: v$version (cPanel)\n";
    return;
}

sub dolfd {
    my $lfd = $input{argument}[0];
    if    ( $lfd eq "start" )   { ConfigServer::Service::startlfd() }
    elsif ( $lfd eq "stop" )    { ConfigServer::Service::stoplfd() }
    elsif ( $lfd eq "restart" ) { ConfigServer::Service::restartlfd() }
    elsif ( $lfd eq "status" )  { ConfigServer::Service::statuslfd() }
    else                        { print "csf: usage: csf --lfd [stop|start|restart|status]\n" }
    return;
}

sub dorestartall {
    csflock("lock");
    dostop(1);
    dostart();
    csflock("unlock");
    ConfigServer::Service::restartlfd();
    return;
}

sub doinitup {
    csflock("lock");
    if ( $config{FASTSTART} ) {
        modprobe();
        if ( -e "/var/lib/csf/csf.4.saved" ) {
            if ( $config{LF_IPSET} ) {
                if ( -x $config{IPSET} ) {
                    print "(restoring ipsets) ";

                    my @data = slurpee( "/var/lib/csf/csf.4.ipsets", 'fatal' => 1 );
                    chomp @data;
                    my ( $childin, $childout );
                    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "restore" );
                    print $childin join( "\n", @data ) . "\n";
                    close $childin;
                    my @results = <$childout>;
                    waitpid( $cmdpid, 0 );
                    chomp @results;

                    unlink "/var/lib/csf/csf.4.ipsets";
                }
            }
            print "(restoring iptables) ";

            my @data = slurpee( "/var/lib/csf/csf.4.saved", 'fatal' => 1 );
            chomp @data;
            my ( $childin, $childout );
            my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPTABLES_RESTORE} );
            print $childin join( "\n", @data ) . "\n";
            close $childin;
            my @results = <$childout>;
            waitpid( $cmdpid, 0 );
            chomp @results;

            unlink "/var/lib/csf/csf.4.saved";
        }
        else {
            dostop(1);
            dostart();
            exit 0;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command completion after restart
        }
        if ( $config{IPV6} ) {
            if ( -e "/var/lib/csf/csf.6.saved" ) {
                print "(restoring ip6tables) ";

                my @data = slurpee( "/var/lib/csf/csf.6.saved", 'fatal' => 1 );
                chomp @data;
                my ( $childin, $childout );
                my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IP6TABLES_RESTORE} );
                print $childin join( "\n", @data ) . "\n";
                close $childin;
                my @results = <$childout>;
                waitpid( $cmdpid, 0 );
                chomp @results;

                unlink "/var/lib/csf/csf.6.saved";
            }
            else {
                dostop(1);
                dostart();
                exit 0;
            }
        }
    }
    else {
        dostop(1);
        dostart();
    }
    csflock("unlock");
    return;
}

sub doinitdown {
    if ( $config{FASTSTART} ) {
        if ( -x $config{IPTABLES_SAVE} ) {
            print "(saving iptables) ";

            my ( $childin, $childout );
            my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPTABLES_SAVE} );
            close $childin;
            my @results = <$childout>;
            waitpid( $cmdpid, 0 );
            chomp @results;
            open( my $OUT, ">", "/var/lib/csf/csf.4.saved" );
            flock( $OUT, LOCK_EX );
            print $OUT join( "\n", @results ) . "\n";
            close($OUT);

            if ( $config{LF_IPSET} ) {
                if ( -x $config{IPSET} ) {
                    print "(saving ipsets) ";

                    my ( $childin, $childout );
                    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "save" );
                    close $childin;
                    my @results = <$childout>;
                    waitpid( $cmdpid, 0 );
                    chomp @results;
                    open( my $OUT, ">", "/var/lib/csf/csf.4.ipsets" );
                    flock( $OUT, LOCK_EX );
                    print $OUT join( "\n", @results ) . "\n";
                    close($OUT);
                }
            }
        }
        if ( $config{IPV6} and -x $config{IP6TABLES_SAVE} ) {
            print "(saving ip6tables) ";

            my ( $childin, $childout );
            my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IP6TABLES_SAVE} );
            close $childin;
            my @results = <$childout>;
            waitpid( $cmdpid, 0 );
            chomp @results;
            open( my $OUT, ">", "/var/lib/csf/csf.6.saved" );
            flock( $OUT, LOCK_EX );
            print $OUT join( "\n", @results ) . "\n";
            close($OUT);
        }
    }
    return;
}

sub doclusterdeny {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("D $ip 1 * inout 3600 $comment");
    return;
}

sub doclustertempdeny {
    my ( $ip, $timeout, $portdir ) = @{ $input{argument} }[ 0 .. 2 ];
    my $inout = "in";
    my $ports = "";
    my $perm  = 0;
    if ( $timeout =~ /^(\d*)([mhd])/i ) {
        my $secs = $1;
        my $dur  = lc $2;
        if    ( $dur eq "m" ) { $timeout = $secs * 60 }
        elsif ( $dur eq "h" ) { $timeout = $secs * 60 * 60 }
        elsif ( $dur eq "d" ) { $timeout = $secs * 60 * 60 * 24 }
        else                  { $timeout = $secs }
    }

    my $iptype = checkip( \$ip );
    if ( !$iptype ) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }

    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    if ( $timeout =~ /\D/ ) {
        $portdir = join( " ", $timeout, $portdir );
        $timeout = 0;
    }

    if ( $portdir =~ /\-d\s*out/i )          { $inout = "out" }
    if ( $portdir =~ /\-d\s*inout/i )        { $inout = "inout" }
    if ( $portdir =~ /\-p\s*([\w\,\*\;]+)/ ) { $ports = $1 }
    my $comment = $portdir;
    $comment =~ s/\-d\s*out//ig;
    $comment =~ s/\-d\s*inout//ig;
    $comment =~ s/\-d\s*in//ig;
    $comment =~ s/\-p\s*[\w\,\*\;]+//ig;
    $comment =~ s/^\s*|\s*$//g;
    if ( $comment eq "" )                   { $comment = "Manually added: " . iplookup($ip) }
    if ( !length $timeout || $timeout < 2 ) { $timeout = 3600 }
    if ( $ports eq "" )                     { $ports   = "*" }

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("TD $ip $perm $ports $inout $timeout $comment");
    return;
}

sub doclusterrm {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("R $ip");
    return;
}

sub doclusterarm {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("AR $ip");
    return;
}

sub doclusterallow {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("A $ip 1 * inout 3600 $comment");
    return;
}

sub doclustertempallow {
    my ( $ip, $timeout, $portdir ) = @{ $input{argument} }[ 0 .. 2 ];
    my $inout = "in";
    my $ports = "";
    my $perm  = 0;
    if ( $timeout =~ /^(\d*)([mhd])/i ) {
        my $secs = $1;
        my $dur  = lc $2;
        if    ( $dur eq "m" ) { $timeout = $secs * 60 }
        elsif ( $dur eq "h" ) { $timeout = $secs * 60 * 60 }
        elsif ( $dur eq "d" ) { $timeout = $secs * 60 * 60 * 24 }
        else                  { $timeout = $secs }
    }

    my $iptype = checkip( \$ip );
    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    unless ($iptype) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }

    if ( $timeout =~ /\D/ ) {
        $portdir = join( " ", $timeout, $portdir );
        $timeout = 0;
    }

    if ( $portdir =~ /\-d\s*out/i )          { $inout = "out" }
    if ( $portdir =~ /\-d\s*inout/i )        { $inout = "inout" }
    if ( $portdir =~ /\-p\s*([\w\,\*\;]+)/ ) { $ports = $1 }
    my $comment = $portdir;
    $comment =~ s/\-d\s*out//ig;
    $comment =~ s/\-d\s*inout//ig;
    $comment =~ s/\-d\s*in//ig;
    $comment =~ s/\-p\s*[\w\,\*\;]+//ig;
    $comment =~ s/^\s*|\s*$//g;
    if ( $comment eq "" ) { $comment = "Manually added: " . iplookup($ip) }
    if ( $timeout < 2 )   { $timeout = 3600 }
    if ( $ports eq "" )   { $ports   = "*" }

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("TA $ip $perm $ports $inout $timeout $comment");
    return;
}

sub doclusterignore {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("I $ip     $comment");
    return;
}

sub doclusterirm {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("IR $ip");
    return;
}

sub docconfig {
    my ( $name, $value ) = @{ $input{argument} }[ 0, 1 ];
    unless ( $config{CLUSTER_CONFIG} ) { print "No configuration setting requests allowed\n"; return }
    unless ($name)                     { print "No configuration setting entered\n";          return }

    clustersend("C $name $value");
    return;
}

sub doclustergrep {
    my $ip = $input{argument}[0];
    if ( !checkip( \$ip ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    clustersend("G $ip");
    return;
}

sub docfile {
    my $name = $input{argument}[0];
    unless ( $config{CLUSTER_CONFIG} ) { print "No configuration setting requests allowed\n"; return }
    unless ($name)                     { print "No file entered\n";                           return }

    if ( -e $name ) {
        my @data = slurpee( $name, 'fatal' => 1 );

        my ( $file, $filedir ) = File::Basename::fileparse($name);
        my $send = "FILE $file\n";
        foreach my $line (@data) { $send .= $line }

        clustersend($send);
    }
    else {
        print "csf: Error [$name] does not exist\n";
    }
    return;
}

sub docrestart {
    clustersend("RESTART");
    return;
}

sub clustersend {
    my $text = shift;

    my $cipher    = Crypt::CBC->new( -key => $config{CLUSTER_KEY}, -cipher => 'Blowfish' );
    my $encrypted = $cipher->encrypt($text) . "END\n";

    foreach my $cip ( split( /\,/, $config{CLUSTER_SENDTO} ) ) {
        my $localaddr = "0.0.0.0";
        if ( $config{CLUSTER_LOCALADDR} ) { $localaddr = $config{CLUSTER_LOCALADDR} }
        my $sock;
        eval { $sock = IO::Socket::INET->new( PeerAddr => $cip, PeerPort => $config{CLUSTER_PORT}, LocalAddr => $localaddr, Timeout => '10' ) or print "Cluster error connecting to $cip: $!\n"; };
        unless ( defined $sock ) {
            print "Failed to connect to $cip\n";
        }
        else {
            my $status = send( $sock, $encrypted, 0 );
            unless ($status) {
                print "Failed for $cip: $status\n";
            }
            else {
                print "Sent request to $cip";
                my $select = IO::Select->new($sock);
                if ( $select->can_read(5) ) {
                    my $line;
                    while (<$sock>) { $line .= $_ }
                    chomp $line;
                    if ( $text =~ /^G / ) {
                        print ", reply:\n";
                        print "=" x 80;
                        print $line;
                        print "=" x 80;
                        print "\n";
                    }
                    else {
                        print ", replied: [$line]";
                    }
                }
                else {
                    print ", no reply";
                }
                print "\n";
            }
            shutdown( $sock, 2 );
        }
    }
    return;
}

sub lfdstart {
    open( my $FH, ">", "/var/lib/csf/csf.restart" ) or die "Failed to create csf.restart - $!";
    flock( $FH, LOCK_EX );
    close($FH);
    print "lfd will restart csf within the next $config{LF_PARSE} seconds\n";
    return;
}

sub dostop {
    my $restart = shift;
    syscommand( __LINE__, "$config{IPTABLES} $verbose --policy INPUT ACCEPT" );
    syscommand( __LINE__, "$config{IPTABLES} $verbose --policy OUTPUT ACCEPT" );
    syscommand( __LINE__, "$config{IPTABLES} $verbose --policy FORWARD ACCEPT" );
    syscommand( __LINE__, "$config{IPTABLES} $verbose --flush" );
    syscommand( __LINE__, "$config{IPTABLES} $verbose --delete-chain" );
    if ( $config{NAT} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t nat --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t nat --delete-chain" );
    }
    if ( $config{RAW} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t raw --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t raw --delete-chain" );
    }
    if ( $config{MANGLE} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t mangle --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t mangle --delete-chain" );
    }

    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $verbose --policy INPUT ACCEPT" );
        syscommand( __LINE__, "$config{IP6TABLES} $verbose --policy OUTPUT ACCEPT" );
        syscommand( __LINE__, "$config{IP6TABLES} $verbose --policy FORWARD ACCEPT" );
        syscommand( __LINE__, "$config{IP6TABLES} $verbose --flush" );
        syscommand( __LINE__, "$config{IP6TABLES} $verbose --delete-chain" );
        if ( $config{NAT6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t nat --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t nat --delete-chain" );
        }
        if ( $config{RAW6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t raw --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t raw --delete-chain" );
        }
        if ( $config{MANGLE6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t mangle --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t mangle --delete-chain" );
        }
    }
    if ( $config{LF_IPSET} ) {
        syscommand( __LINE__, "$config{IPSET} flush" );
        syscommand( __LINE__, "$config{IPSET} destroy" );
    }

    if ( $config{TESTING} ) { crontab("remove") }
    return;
}

sub dostart {
    if ( ConfigServer::Service::type() eq "systemd" ) {
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{SYSTEMCTL}, "is-active", "firewalld" );
        my @reply  = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @reply;
        if ( $reply[0] eq "active" or $reply[0] eq "activating" ) {
            error( __LINE__, "*Error* firewalld found to be running. You must stop and disable firewalld when using csf" );
            exit 1;    ## no critic (Cpanel::NoExitsFromSubroutines) - Fatal configuration error - conflicting firewall service
        }
    }

    if   ( $config{TESTING} ) { crontab("add") }
    else                      { crontab("remove") }
    if ( -e "/etc/csf/csf.error" ) { unlink("/etc/csf/csf.error") }

    getethdev();
    modprobe();

    $noowner = 0;
    if ( $config{VPS} and $config{SMTP_BLOCK} ) {
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, "$config{IPTABLES} $config{IPTABLESWAIT} -I OUTPUT -p tcp --dport 9999 -m owner --uid-owner 0 -j $accept" );
        my @ipdata = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @ipdata;
        if ( $ipdata[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @ipdata }
        if ( $ipdata[0] =~ /^iptables/ ) {
            $warning .= "*WARNING* Cannot use SMTP_BLOCK on this VPS as the Monolithic kernel does not support the iptables module ipt_owner/xt_owner - SMTP_BLOCK disabled\n";
            $config{SMTP_BLOCK} = 0;
            $noowner = 1;
        }
        else {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -D OUTPUT -p tcp --dport 9999 -m owner --uid-owner 0 -j $accept", 0 );
        }
    }

    my $path    = "PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin";
    my $csfpre  = "";
    my $csfpost = "";
    if    ( -e "/usr/local/csf/bin/csfpre.sh" )  { $csfpre  = "/usr/local/csf/bin/csfpre.sh" }
    elsif ( -e "/etc/csf/csfpre.sh" )            { $csfpre  = "/etc/csf/csfpre.sh" }
    if    ( -e "/usr/local/csf/bin/csfpost.sh" ) { $csfpost = "/usr/local/csf/bin/csfpost.sh" }
    elsif ( -e "/etc/csf/csfpost.sh" )           { $csfpost = "/etc/csf/csfpost.sh" }

    if ( $csfpre ne "" ) {
        chmod( 0700, $csfpre );
        my @conf = slurp($csfpre);
        if ( $conf[0] !~ /^\#\!/ ) {
            open( my $CONF, ">", $csfpre );
            flock( $CONF, LOCK_EX );
            print $CONF "#!/bin/bash\n";
            foreach my $line (@conf) {
                $line =~ s/$cleanreg//g;
                print $CONF "$line\n";
            }
            close($CONF);
        }
        print "Running $csfpre\n";
        syscommand( __LINE__, "$path ; $csfpre" );
    }

    if ( $config{WATCH_MODE} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGACCEPT" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGACCEPT -j ACCEPT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGACCEPT" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGACCEPT -j ACCEPT" );
        }
    }

    foreach my $name ( keys %blocklists ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N $name" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N $name" );
        }
    }
    if ( $config{CC_ALLOW_FILTER} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWF" ) }
    if ( $config{CC_ALLOW_PORTS} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWPORTS" );
    }
    if ( $config{CC_DENY_PORTS} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYPORTS" );
    }
    if ( $config{CC_ALLOW} )                                                             { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOW" ) }
    if ( $config{CC_DENY} )                                                              { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENY" ) }
    if ( scalar( keys %blocklists ) > 0 and $config{DROP_IP_LOGGING} )                   { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N BLOCKDROP" ) }
    if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CCDROP" ) }
    if ( $config{IPV6} ) {
        if ( $config{CC_ALLOW_FILTER} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWF" ) }
        if ( $config{CC_ALLOW_PORTS} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWPORTS" );
        }
        if ( $config{CC_DENY_PORTS} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYPORTS" );
        }
        if ( $config{CC_ALLOW} )                                                             { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOW" ) }
        if ( $config{CC_DENY} )                                                              { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENY" ) }
        if ( scalar( keys %blocklists ) > 0 and $config{DROP_IP_LOGGING} )                   { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N BLOCKDROP" ) }
        if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CCDROP" ) }
    }

    if ( $config{GLOBAL_ALLOW} )  { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GALLOWIN" ) }
    if ( $config{GLOBAL_ALLOW} )  { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GALLOWOUT" ) }
    if ( $config{GLOBAL_DENY} )   { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDENYIN" ) }
    if ( $config{GLOBAL_DENY} )   { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDENYOUT" ) }
    if ( $config{DYNDNS} )        { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNIN" ) }
    if ( $config{DYNDNS} )        { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNOUT" ) }
    if ( $config{GLOBAL_DYNDNS} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDYNIN" ) }
    if ( $config{GLOBAL_DYNDNS} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDYNOUT" ) }
    if ( $config{SYNFLOOD} )      { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N SYNFLOOD" ) }
    if ( $config{PORTFLOOD} )     { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N PORTFLOOD" ) }
    if ( $config{CONNLIMIT} )     { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CONNLIMIT" ) }
    if ( $config{UDPFLOOD} )      { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N UDPFLOOD" ) }

    if ( $config{IPV6} ) {
        if ( $config{GLOBAL_ALLOW} )  { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GALLOWIN" ) }
        if ( $config{GLOBAL_ALLOW} )  { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GALLOWOUT" ) }
        if ( $config{GLOBAL_DENY} )   { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDENYIN" ) }
        if ( $config{GLOBAL_DENY} )   { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDENYOUT" ) }
        if ( $config{DYNDNS} )        { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNIN" ) }
        if ( $config{DYNDNS} )        { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNOUT" ) }
        if ( $config{GLOBAL_DYNDNS} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDYNIN" ) }
        if ( $config{GLOBAL_DYNDNS} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDYNOUT" ) }
        if ( $config{SYNFLOOD} )      { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N SYNFLOOD" ) }
        if ( $config{PORTFLOOD6} )    { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N PORTFLOOD" ) }
        if ( $config{CONNLIMIT6} )    { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CONNLIMIT" ) }
        if ( $config{UDPFLOOD} )      { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N UDPFLOOD" ) }
    }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPIN" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPOUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DENYIN" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DENYOUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWIN" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWOUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOCALINPUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOCALOUTPUT" );

    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPIN" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPOUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DENYIN" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DENYOUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWIN" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWOUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOCALINPUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOCALOUTPUT" );
    }

    if ( $config{DROP_LOGGING} ) {
        my $dports = "";
        if ( $config{DROP_ONLYRES} ) { $dports = "--dport 0:1023" }
        $config{DROP_NOLOG} =~ s/\s//g;
        if ( $config{DROP_NOLOG} ne "" ) {
            if ( $config{FASTSTART} ) { $faststart = 1 }
            foreach my $port ( split( /\,/, $config{DROP_NOLOG} ) ) {
                if ( $port eq "" )         { next }
                if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid DROP_NOLOG port [$port]" ) }
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp --dport $port -j $config{DROP}" );
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp --dport $port -j $config{DROP}" );
                if ( $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp --dport $port -j $config{DROP}" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp --dport $port -j $config{DROP}" );
                }
            }
            if ( $config{FASTSTART} ) { faststart("DROP no logging") }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *TCP_IN Blocked* '" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p tcp --syn -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *TCP_OUT Blocked* '" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *UDP_IN Blocked* '" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p udp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDP_OUT Blocked* '" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p icmp -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ICMP_IN Blocked* '" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p icmp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *ICMP_OUT Blocked* '" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *TCP6IN Blocked* '" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p tcp --syn -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *TCP6OUT Blocked* '" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *UDP6IN Blocked* '" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p udp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDP6OUT Blocked* '" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p icmpv6 -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ICMP6IN Blocked* '" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p icmpv6 -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *ICMP6OUT Blocked* '" );
        }
        if ( scalar( keys %blocklists ) > 0                   and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *BLOCK_LIST* '" ); }
        if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *CC_DENY* '" ); }
        if ( $config{PORTFLOOD} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *Port Flood* '" ); }
        if ( $config{IPV6} ) {
            if ( scalar( keys %blocklists ) > 0 and $config{DROP_IP_LOGGING} )                   { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *BLOCK_LIST* '" ); }
            if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *CC_DENY* '" ); }
            if ( $config{PORTFLOOD6} )                                                           { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *Port Flood* '" ); }
        }
    }

    if ( scalar( keys %blocklists ) > 0                   and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -j $config{DROP}" ); }
    if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -j $config{DROP}" ); }
    if ( $config{IPV6} ) {
        if ( scalar( keys %blocklists ) > 0                   and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -j $config{DROP}" ); }
        if ( ( $config{CC_DENY} or $config{CC_ALLOW_FILTER} ) and $config{DROP_IP_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -j $config{DROP}" ); }
    }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -j $config{DROP}" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -j $config{DROP_OUT}" );
    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -j $config{DROP}" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -j $config{DROP_OUT}" );
    }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j DENYOUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j DENYIN" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWOUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWIN" );
    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j DENYOUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j DENYIN" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWOUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWIN" );
    }

    if ( $config{MESSENGER} ) {
        if ( $config{LF_IPSET} ) {
            ipsetcreate("MESSENGER");
            if ( $config{MESSENGER6} ) { ipsetcreate("MESSENGER_6") }
            domessenger( "-m set --match-set MESSENGER src", "A" );
        }
    }

    dopacketfilters();
    doportfilters();

    my $skipin   = 1;
    my $skipout  = 1;
    my $skipin6  = 1;
    my $skipout6 = 1;

    my $dropout = $config{DROP_OUT};
    if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT  -i lo -j $accept" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o lo -j $accept" );
    unless ( $config{LF_SPI} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -j $accept" ) }
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -j $dropout" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -j LOGDROPIN" );
    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT  -i lo -j $accept" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o lo -j $accept" );
        unless ( $config{IPV6_SPI} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -j $accept" ) }
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -j $dropout" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -j LOGDROPIN" );
    }

    if ( $config{SMTP_BLOCK} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N SMTPOUTPUT" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -j SMTPOUTPUT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N SMTPOUTPUT" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -j SMTPOUTPUT" );
        }
        if ( $config{FASTSTART} ) { $faststart = 1 }
        my $dropout = $config{DROP_OUT};
        if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }
        $config{SMTP_PORTS} =~ s/\s//g;
        if ( $config{SMTP_PORTS} ne "" ) {
            unless ( $config{SMTP_REDIRECT} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j $dropout", 1 ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j $accept", 1 );
            if ( $config{IPV6} ) {
                unless ( $config{SMTP_REDIRECT} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j $dropout", 1 ) }
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j $accept", 1 );
            }
            foreach my $item ( split( /\,/, $config{SMTP_ALLOWUSER} ) ) {
                $item =~ s/\s//g;
                my $uid = ( getpwnam($item) )[2];
                if ($uid) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j $accept", 1 );
                    if ( $config{IPV6} ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j $accept", 1 );
                    }
                }
            }
            foreach my $item ( split( /\,/, $config{SMTP_ALLOWGROUP} ) ) {
                $item =~ s/\s//g;
                my $gid = ( getgrnam($item) )[2];
                if ($gid) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j $accept", 1 );
                    if ( $config{IPV6} ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j $accept", 1 );
                    }
                }
            }
            if ( $config{SMTP_ALLOWLOCAL} ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j $accept", 1 );
                if ( $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j $accept", 1 );
                }
            }
            if ( $config{SMTP_REDIRECT} ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j REDIRECT",                      1 );
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j RETURN", 1 );
                if ( $config{IPV6} and $config{SMTP_REDIRECT6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j REDIRECT",                      1 );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j RETURN", 1 );
                }
                foreach my $item ( split( /\,/, $config{SMTP_ALLOWUSER} ) ) {
                    $item =~ s/\s//g;
                    my $uid = ( getpwnam($item) )[2];
                    if ($uid) {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j RETURN", 1 );
                        if ( $config{IPV6} and $config{SMTP_REDIRECT6} ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j RETURN", 1 );
                        }
                    }
                }
                foreach my $item ( split( /\,/, $config{SMTP_ALLOWGROUP} ) ) {
                    $item =~ s/\s//g;
                    my $gid = ( getgrnam($item) )[2];
                    if ($gid) {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j RETURN", 1 );
                        if ( $config{IPV6} and $config{SMTP_REDIRECT6} ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j RETURN", 1 );
                        }
                    }
                }
                if ( $config{SMTP_ALLOWLOCAL} ) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j RETURN", 1 );
                    if ( $config{IPV6} and $config{SMTP_REDIRECT6} ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j RETURN", 1 );
                    }
                }
            }
        }
        if ( $config{FASTSTART} ) { faststart("SMTP Block") }
    }

    if     ( $config{FASTSTART} ) { $faststart = 1 }
    unless ( $config{DNS_STRICT} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p udp --sport 53 -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport 53 -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p udp --dport 53 -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --dport 53 -j $accept" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p udp --sport 53 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp --sport 53 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p udp --dport 53 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp --dport 53 -j $accept" );
        }
    }

    unless ( $config{DNS_STRICT_NS} ) {
        foreach my $line ( slurp("/etc/resolv.conf") ) {
            $line =~ s/$cleanreg//g;
            if ( $line =~ /^(\s|\#|$)/ ) { next }
            if ( $line =~ /^nameserver\s+($ipv4reg)/ ) {
                my $ip = $1;
                unless ( $ips{$ip} or $ipscidr->find($ip) ) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --dport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --dport 53 -j $accept" );
                    $skipin += 4;
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --dport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --dport 53 -j $accept" );
                    $skipout += 4;
                }
            }
            if ( $line =~ /^nameserver\s+($ipv6reg)/ ) {
                my $ip = $1;
                unless ( $ips{$ip} or $ipscidr6->find($ip) ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --dport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --dport 53 -j $accept" );
                    $skipin6 += 4;
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --sport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --dport 53 -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --dport 53 -j $accept" );
                    $skipout6 += 4;
                }
            }
        }
    }
    if ( $config{FASTSTART} ) { faststart("DNS") }

    if ( $config{MESSENGER} ) {
        $skipin  += 2;
        $skipout += 2;
        if ( $config{MESSENGER_HTTPS_IN} ) {
            $skipin  += 1;
            $skipout += 1;
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        if ( $config{MESSENGER6} ) {
            $skipin6  += 2;
            $skipout6 += 2;
            if ( $config{MESSENGER_HTTPS_IN} ) {
                $skipin6  += 1;
                $skipout6 += 1;
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
            }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept" );
        }
    }

    if ( $config{DOCKER} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DOCKER" );
        if ( $config{NAT} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -N DOCKER" );
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING -s $config{DOCKER_NETWORK4} ! -o $config{DOCKER_DEVICE} -j MASQUERADE" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -o $config{DOCKER_DEVICE} $statemodule RELATED,ESTABLISHED -j ACCEPT" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} ! -o $config{DOCKER_DEVICE} -j ACCEPT" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} -o $config{DOCKER_DEVICE} -j ACCEPT" );
        if ( $config{IPV6} and $config{NAT6} and $config{DOCKER_NETWORK6} ne "" ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DOCKER" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING -s $config{DOCKER_NETWORK6} ! -o $config{DOCKER_DEVICE} -j MASQUERADE" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -o $config{DOCKER_DEVICE} $statemodule RELATED,ESTABLISHED -j ACCEPT" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} ! -o $config{DOCKER_DEVICE} -j ACCEPT" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} -o $config{DOCKER_DEVICE} -j ACCEPT" );
        }
    }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $skipout $ethdevout -j LOCALOUTPUT" );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $skipin $ethdevin -j LOCALINPUT" );
    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $skipout6 $eth6devout -j LOCALOUTPUT" );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $skipin6 $eth6devin -j LOCALINPUT" );
    }

    $config{ETH_DEVICE_SKIP} =~ s/\s//g;
    if ( $config{ETH_DEVICE_SKIP} ne "" ) {
        foreach my $device ( split( /\,/, $config{ETH_DEVICE_SKIP} ) ) {
            if ( $ifaces{$device} ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT  -i $device -j $accept" );
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o $device -j $accept" );
                if ( $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT  -i $device -j $accept" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o $device -j $accept" );
                }
            }
            else {
                $warning .= "*WARNING* ETH_DEVICE_SKIP device [$device] not listed in ip/ifconfig\n";
            }
        }
    }

    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy INPUT   DROP", 1 );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy OUTPUT  DROP", 1 );
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy FORWARD DROP", 1 );
    if ( $config{IPV6} ) {
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy INPUT   DROP", 1 );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy OUTPUT  DROP", 1 );
        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy FORWARD DROP", 1 );
    }

    if ( $csfpost ne "" ) {
        chmod( 0700, $csfpost );
        my @conf = slurp($csfpost);

        if ( $conf[0] !~ /^\#\!/ ) {
            open( my $CONF, ">", $csfpost );
            flock( $CONF, LOCK_EX );
            print $CONF "#!/bin/bash\n";
            foreach my $line (@conf) {
                $line =~ s/$cleanreg//g;
                print $CONF "$line\n";
            }
            close($CONF);
        }
        print "Running $csfpost\n";
        syscommand( __LINE__, "$path ; $csfpost" );
    }

    if ( $config{VPS} ) {
        my @data = slurpee( "/proc/sys/kernel/osrelease", 'fatal' => 1 );
        chomp @data;
        if ( $data[0] =~ /^(\d+)\.(\d+)\.(\d+)/ ) {
            my $maj = $1;
            my $mid = $2;
            my $min = $3;
            if ( ( $maj > 2 ) or ( ( $maj > 1 ) and ( $mid > 5 ) and ( $min > 26 ) ) ) {
            }
            else {
                my $status = 0;
                if ( -e "/etc/pure-ftpd.conf" ) {
                    my @conf = slurp("/etc/pure-ftpd.conf");
                    if ( my @ls = grep { $_ =~ /^PassivePortRange\s+(\d+)\s+(\d+)/ } @conf ) {
                        if ( $ls[0] =~ /^PassivePortRange\s+(\d+)\s+(\d+)/ ) {
                            if ( $config{TCP_IN} !~ /\b$1:$2\b/ ) { $status = 1 }
                        }
                    }
                    else         { $status = 1 }
                    if ($status) { $warning .= "*WARNING* Since the Virtuozzo VPS iptables ip_conntrack_ftp kernel module is currently broken you have to open a PASV port hole in iptables for incoming FTP connections to work correctly. See the csf readme.txt under 'A note about FTP Connection Issues' on how to do this if you have not already done so.\n" }
                }
                elsif ( -e "/etc/proftpd.conf" ) {
                    my @conf = slurp("/etc/proftpd.conf");
                    if ( my @ls = grep { $_ =~ /^PassivePorts\s+(\d+)\s+(\d+)/ } @conf ) {
                        if ( $ls[0] =~ /^PassivePorts\s+(\d+)\s+(\d+)/ ) {
                            if ( $config{TCP_IN} !~ /\b$1:$2\b/ ) { $status = 1 }
                        }
                    }
                    else         { $status = 1 }
                    if ($status) { $warning .= "*WARNING* Since the Virtuozzo VPS iptables ip_conntrack_ftp kernel module is currently broken you have to open a PASV port hole in iptables for incoming FTP connections to work correctly. See the csf readme.txt under 'A note about FTP Connection Issues' on how to do this if you have not already done so.\n" }
                }
            }
        }
    }
    return;
}

sub doadd {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    my $checkip = checkip( \$ip );

    getethdev();

    if ( $ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip) ) {
        print "add failed: $ip is one of this servers addresses!\n";
        return;
    }

    if ( $checkip and $checkip == 6 and !$config{IPV6} ) {
        print "add failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
        return;
    }

    if ( !$checkip and !( ( $ip =~ /[:|]/ ) and ( $ip =~ /=/ ) ) ) {
        print "add failed: [$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    my $hit;
    my @deny = slurp("/etc/csf/csf.deny");
    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ip ) {
            $hit = 1;
            last;
        }
    }
    if ($hit) {
        print "Removing $ip from csf.deny...\n";
        $input{argument}[0] = $ip;
        dokill();
    }

    my $allowmatches;
    my @allow = slurp("/etc/csf/csf.allow");
    foreach my $line (@allow) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @allow, @incfile;
        }
    }
    foreach my $line (@allow) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ip ) {
            $allowmatches = 1;
            last;
        }
    }

    my $ipstring = quotemeta($ip);
    sysopen( my $ALLOW, "/etc/csf/csf.allow", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/csf/csf.allow: $!" );
    flock( $ALLOW, LOCK_EX )                                     or error( __LINE__, "Could not lock /etc/csf/csf.allow: $!" );
    my $text = join( "", <$ALLOW> );
    @allow = split( /$slurpreg/, $text );
    chomp @allow;
    unless ($allowmatches) {
        if ( $comment eq "" ) { $comment = "Manually allowed: " . iplookup($ip) }
        print $ALLOW "$ip \# $comment - " . localtime(time) . "\n";
        if ( $config{TESTING} ) {
            print "Adding $ip to csf.allow only while in TESTING mode (not iptables ACCEPT)\n";
        }
        else {
            print "Adding $ip to csf.allow and iptables ACCEPT...\n";
            linefilter( $ip, "allow" );
        }
    }
    else {
        print "add failed: $ip is in already in the allow file /etc/csf/csf.allow\n";
    }
    close($ALLOW) or error( __LINE__, "Could not close /etc/csf/csf.allow: $!" );
    return;
}

sub dodeny {
    my $ip      = $input{argument}[0];
    my $comment = $input{comment};

    my $checkip = checkip( \$ip );

    getethdev();

    if ( $ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip) ) {
        print "deny failed: [$ip] is one of this servers addresses!\n";
        return;
    }

    if ( $checkip and $checkip == 6 and !$config{IPV6} ) {
        print "deny failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
        return;
    }

    if ( !$checkip and !( ( $ip =~ /[:|]/ ) and ( $ip =~ /=/ ) ) ) {
        print "deny failed: [$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    my @allow = slurp("/etc/csf/csf.allow");
    foreach my $line (@allow) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @allow, @incfile;
        }
    }
    foreach my $line (@allow) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ip ) {
            print "deny failed: $ip is in the allow file /etc/csf/csf.allow\n";
            return;
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ip) ) {
                    print "deny failed: $ip is in the allow file /etc/csf/csf.allow\n";
                    return;
                }
            }
        }
    }

    my @ignore = slurp("/etc/csf/csf.ignore");
    foreach my $line (@ignore) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @ignore, @incfile;
        }
    }
    foreach my $line (@ignore) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ip ) {
            print "deny failed: $ip is in the ignore file /etc/csf/csf.ignore\n";
            return;
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ip) ) {
                    print "deny failed: $ip is in the ignore file /etc/csf/csf.ignore\n";
                    return;
                }
            }
        }
    }

    my $denymatches = 0;
    my @deny        = slurp("/etc/csf/csf.deny");
    foreach my $line (@deny) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @deny, @incfile;
        }
    }
    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ip ) {
            $denymatches = 1;
            last;
        }
    }

    sysopen( my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/csf/csf.deny: $!" );
    flock( $DENY, LOCK_EX )                                    or error( __LINE__, "Could not lock /etc/csf/csf.deny: $!" );
    my $text = join( "", <$DENY> );
    @deny = split( /$slurpreg/, $text );
    chomp @deny;
    if ( $config{LF_REPEATBLOCK} and $denymatches < $config{LF_REPEATBLOCK} ) { $denymatches = 0 }
    if ( $denymatches == 0 ) {
        my $ipcount = 0;
        my @denyips;
        foreach my $line (@deny) {
            $line =~ s/$cleanreg//g;
            if ( $line eq "" )               { next }
            if ( $line =~ /^\s*\#|Include/ ) { next }
            if ( $line =~ /do not delete/i ) { next }
            my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
            $ipd //= '';
            $ipcount++;
            push @denyips, $line;
        }
        if ( ( $config{DENY_IP_LIMIT} > 0 ) and ( $ipcount >= $config{DENY_IP_LIMIT} ) ) {
            seek( $DENY, 0, 0 );
            truncate( $DENY, 0 );
            foreach my $line (@deny) {
                my $hit = 0;
                for ( my $x = 0; $x < ( $ipcount - $config{DENY_IP_LIMIT} ) + 1; $x++ ) {
                    if ( $line eq $denyips[$x] ) { $hit = 1; }
                }
                if ($hit) { next }
                print $DENY $line . "\n";
            }
            print "csf: DENY_IP_LIMIT ($config{DENY_IP_LIMIT}), the following IP's were removed from /etc/csf/csf.deny:\n";
            for ( my $x = 0; $x < ( $ipcount - $config{DENY_IP_LIMIT} ) + 1; $x++ ) {
                print "$denyips[$x]\n";
                my ( $kip, undef ) = split( /\s/, $denyips[$x], 2 );
                linefilter( $kip, "deny", "", 1 );

                #				sysopen (my $TEMPIP, "/var/lib/csf/csf.tempip", O_RDWR | O_CREAT);
                #				flock ($TEMPIP, LOCK_EX);
                #				my @data = <$TEMPIP>;
                #				chomp @data;
                #				seek ($TEMPIP, 0, 0);
                #				truncate ($TEMPIP, 0);
                #				foreach my $line (@data) {
                #					my ($oip,undef,undef,undef) = split(/\|/,$line,4);
                #					checkip(\$oip);
                #					if ($oip eq $kip) {next}
                #					print $TEMPIP "$line\n";
                #				}
                #				close ($TEMPIP);
            }

        }

        if ( $comment eq "" ) { $comment = "Manually denied: " . iplookup($ip) }
        print $DENY "$ip \# $comment - " . localtime(time) . "\n";

        if ( $config{TESTING} ) {
            print "Adding $ip to csf.deny only while in TESTING mode (not iptables DROP)\n";
        }
        else {
            print "Adding $ip to csf.deny and iptables DROP...\n";
            linefilter( $ip, "deny" );
        }
    }
    else {
        print "deny failed: $ip is in already in the deny file /etc/csf/csf.deny $denymatches times\n";
    }
    close($DENY) or error( __LINE__, "Could not close /etc/csf/csf.deny: $!" );
    return;
}

sub dokill {
    my $ip    = $input{argument}[0];
    my $is_ip = 0;
    if ( checkip( \$ip ) ) { $is_ip = 1 }

    if ( !$is_ip and !( ( $ip =~ /[:|]/ ) and ( $ip =~ /=/ ) ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    getethdev();

    sysopen( my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/csf/csf.deny: $!" );
    flock( $DENY, LOCK_EX )                                    or error( __LINE__, "Could not lock /etc/csf/csf.deny: $!" );
    my $text = join( "", <$DENY> );
    my @deny = split( /$slurpreg/, $text );
    chomp @deny;
    seek( $DENY, 0, 0 );
    truncate( $DENY, 0 );
    my $hit = 0;

    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        my $ipmatch = $ipd;
        if ( $is_ip and $ipd =~ /($ipv4reg|$ipv6reg)/ ) {
            $ipmatch = $1;
            if ( $ipd =~ /(\/\d+)$/ ) { $ipmatch .= $1 }
        }
        checkip( \$ipd );
        if ( uc $ip eq uc $ipmatch ) {
            if ( $commentd =~ /do not delete/i ) {
                print "csf: $ip set as \"do not delete\" - not removed\n";
                $hit = -1;
            }
            else {
                print "Removing rule...\n";
                linefilter( $ipd, "deny", "", 1 );
                $hit = 1;
                next;
            }
        }
        print $DENY $line . "\n";
    }
    close($DENY) or error( __LINE__, "Could not close /etc/csf/csf.deny: $!" );

    if ( $hit and ( $config{LF_PERMBLOCK} or $config{LF_NETBLOCK} ) ) {
        sysopen( my $TEMPIP, "/var/lib/csf/csf.tempip", O_RDWR | O_CREAT );
        flock( $TEMPIP, LOCK_EX );
        my @data = <$TEMPIP>;
        chomp @data;
        seek( $TEMPIP, 0, 0 );
        truncate( $TEMPIP, 0 );
        foreach my $line (@data) {
            my ( $oip, undef, undef, undef ) = split( /\|/, $line, 4 );
            if ( $oip eq $ip ) { next }
            print $TEMPIP "$line\n";
        }
        close($TEMPIP);
    }
    elsif ( $hit == -1 ) { }
    elsif ( !$hit ) {
        print "csf: $ip not found in csf.deny\n";
    }
    return;
}

sub dokillall {

    getethdev();

    sysopen( my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/csf/csf.deny: $!" );
    flock( $DENY, LOCK_EX )                                    or error( __LINE__, "Could not lock /etc/csf/csf.deny: $!" );
    my $text = join( "", <$DENY> );
    my @deny = split( /$slurpreg/, $text );
    chomp @deny;
    seek( $DENY, 0, 0 );
    truncate( $DENY, 0 );
    my $hit = 0;

    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        if ( $line =~ /^([#\n]|Include)/ ) {
            print $DENY $line . "\n";
        }
        elsif ( $line =~ /do not delete/i ) {
            print $DENY $line . "\n";
            print "csf: skipped line: $line\n";
        }
        else {
            my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
            $ipd //= '';
            linefilter( $ipd, "deny", "", 1 );
        }
    }
    close($DENY) or error( __LINE__, "Could not close /etc/csf/csf.deny: $!" );
    print "csf: all entries removed from csf.deny\n";
    return;
}

sub doakill {
    my $ip = $input{argument}[0];

    if ( !checkip( \$ip ) and !( ( $ip =~ /[:|]/ ) and ( $ip =~ /=/ ) ) ) {
        print "[$ip] is not a valid PUBLIC IP/CIDR\n";
        return;
    }

    getethdev();

    sysopen( my $ALLOW, "/etc/csf/csf.allow", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/csf/csf.allow: $!" );
    flock( $ALLOW, LOCK_EX )                                     or error( __LINE__, "Could not lock /etc/csf/csf.allow: $!" );
    my $text  = join( "", <$ALLOW> );
    my @allow = split( /$slurpreg/, $text );
    chomp @allow;
    seek( $ALLOW, 0, 0 );
    truncate( $ALLOW, 0 );
    my $hit = 0;

    foreach my $line (@allow) {
        $line =~ s/$cleanreg//g;
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( uc $ipd eq uc $ip ) {
            print "Removing rule...\n";
            linefilter( $ipd, "allow", "", 1 );
            $hit = 1;
            next;
        }
        print $ALLOW $line . "\n";
    }
    close($ALLOW) or error( __LINE__, "Could not close /etc/csf/csf.allow: $!" );
    unless ($hit) {
        print "csf: $ip not found in csf.allow\n";
    }
    return;
}

sub dohelp {
    print "csf: v$version (cPanel)\n";
    print slurpee( "/usr/local/csf/lib/csf.help", 'fatal' => 1, 'wantarray' => 0 );
    return;
}

sub dopacketfilters {
    if ( $config{PACKET_FILTER} and $config{LF_SPI} ) {
        if ( $config{FASTSTART} ) { $faststart = 1 }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N INVALID" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID $statemodule INVALID -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL NONE -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL ALL -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,RST SYN,RST -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags FIN,RST FIN,RST -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,FIN FIN -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,PSH PSH -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,URG URG -j INVDROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp ! --syn $statemodulenew -j INVDROP" );

        if ( $config{IPV6} and $config{IPV6_SPI} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N INVALID" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID $statemodule INVALID -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL NONE -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL ALL -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,RST SYN,RST -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags FIN,RST FIN,RST -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,FIN FIN -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,PSH PSH -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,URG URG -j INVDROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp ! --syn $statemodule6new -j INVDROP" );
        }
        if ( $config{FASTSTART} ) { faststart("Packet Filter") }

        if ( $config{DROP_PF_LOGGING} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP $statemodule INVALID -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INVALID* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL NONE -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AN* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL ALL -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AA* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SFSF* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SRSR* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags FIN,RST FIN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_FRFR* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,FIN FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AFF* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,PSH PSH -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_APP* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,URG URG -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AUU* '" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp ! --syn $statemodulenew -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_NOSYN* '" );

            if ( $config{IPV6} and $config{IPV6_SPI} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP $statemodule INVALID -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INVALID* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL NONE -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AN* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL ALL -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AA* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SFSF* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SRSR* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags FIN,RST FIN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_FRFR* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,FIN FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AFF* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,PSH PSH -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_APP* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,URG URG -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AUU* '" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp ! --syn $statemodule6new -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_NOSYN* '" );
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -j $config{DROP}" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp -j INVALID" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp -j INVALID" );
        if ( $config{IPV6} and $config{IPV6_SPI} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -j $config{DROP}" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $eth6devin -p tcp -j INVALID" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp -j INVALID" );
        }
    }
    return;
}

sub doportfilters {
    my $dropin  = $config{DROP};
    my $dropout = $config{DROP_OUT};
    if ( $config{DROP_LOGGING} ) { $dropin  = "LOGDROPIN" }
    if ( $config{DROP_LOGGING} ) { $dropout = "LOGDROPOUT" }

    my @entries = slurp("/etc/csf/csf.sips");
    foreach my $line (@entries) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @entries, @incfile;
        }
    }
    foreach my $line (@entries) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ip, $comment ) = split( /\s/, $line, 2 );
        my $iptype = checkip( \$ip );
        if ( $iptype == 4 ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -d $ip -j $dropin" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -s $ip -j $dropout" );
        }
        elsif ( $iptype == 6 ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $eth6devin -d $ip -j $dropin" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $eth6devout -s $ip -j $dropout" );
        }
    }

    if ( $config{GLOBAL_DENY} ) {
        if ( $config{LF_IPSET} ) {
            my $pktin  = $config{DROP};
            my $pktout = $config{DROP_OUT};
            if ( $config{DROP_IP_LOGGING} )  { $pktin  = "LOGDROPIN" }
            if ( $config{DROP_OUT_LOGGING} ) { $pktout = "LOGDROPOUT" }
            ipsetcreate("chain_GDENY");
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDENYIN -m set --match-set chain_GDENY src -j $pktin" );
            unless ( $config{LF_BLOCKINONLY} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDENYOUT -m set --match-set chain_GDENY dst -j $pktout" ) }
            if     ( $config{IPV6} ) {
                ipsetcreate("chain_6_GDENY");
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDENYIN -m set --match-set chain_6_GDENY src -j $pktin" );
                unless ( $config{LF_BLOCKINONLY} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDENYOUT -m set --match-set chain_6_GDENY dst -j $pktout" ) }
            }
        }
        if ( -e "/var/lib/csf/csf.gdeny" ) {
            if ( $config{FASTSTART} ) { $faststart = 1 }
            foreach my $line ( slurp("/var/lib/csf/csf.gdeny") ) {
                $line =~ s/$cleanreg//g;
                if ( $line =~ /^(\s|\#|$)/ ) { next }
                my ( $ip, $comment ) = split( /\s/, $line, 2 );
                linefilter( $ip, "deny", "GDENY" );
            }
            if ( $config{FASTSTART} ) { faststart("Global Deny") }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j GDENYIN" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j GDENYOUT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $eth6devin -j GDENYIN" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $eth6devout -j GDENYOUT" );
        }
    }

    my @deny = slurp("/etc/csf/csf.deny");
    foreach my $line (@deny) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @deny, @incfile;
        }
    }
    if ( $config{FASTSTART} ) { $faststart = 1 }
    if ( $config{LF_IPSET} ) {
        my $pktin  = $config{DROP};
        my $pktout = $config{DROP_OUT};
        if ( $config{DROP_IP_LOGGING} )  { $pktin  = "LOGDROPIN" }
        if ( $config{DROP_OUT_LOGGING} ) { $pktout = "LOGDROPOUT" }
        ipsetcreate("chain_DENY");
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN -m set --match-set chain_DENY src -j $pktin" );
        unless ( $config{LF_BLOCKINONLY} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT -m set --match-set chain_DENY dst -j $pktout" ) }
        if     ( $config{IPV6} ) {
            ipsetcreate("chain_6_DENY");
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN -m set --match-set chain_6_DENY src -j $pktin" );
            unless ( $config{LF_BLOCKINONLY} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT -m set --match-set chain_6_DENY dst -j $pktout" ) }
        }
    }
    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ip, $comment ) = split( /\s/, $line, 2 );
        linefilter( $ip, "deny" );
    }
    if ( $config{FASTSTART} ) { faststart("csf.deny") }

    if ( !-z "/var/lib/csf/csf.tempban" ) {
        my $dropin  = $config{DROP};
        my $dropout = $config{DROP_OUT};
        if ( $config{DROP_IP_LOGGING} )  { $dropin  = "LOGDROPIN" }
        if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }

        sysopen( my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT );
        flock( $TEMPBAN, LOCK_EX );
        my @data = <$TEMPBAN>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $ip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            my $iptype = checkip( \$ip );
            if ( $iptype == 6 and !$config{IPV6} ) { next }
            if ( ( ( ( time - $time ) < $timeout ) and $iptype ) or ( $message =~ /\(CF:([^\)]+)\)/ ) ) {
                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A", $dport ) }
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A", $dport ) }
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -s $ip -j $dropin" );
                            if ( $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A" ) }
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -s $ip -j $dropin" );
                            if ( $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A" ) }
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -d $ip -j $dropout" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -d $ip -j $dropout" );
                        }
                    }
                }
                push @newdata, $line;
            }
        }
        seek( $TEMPBAN, 0, 0 );
        truncate( $TEMPBAN, 0 );
        foreach my $line (@newdata) { print $TEMPBAN "$line\n" }
        close($TEMPBAN);
    }

    if ( !-z "/var/lib/csf/csf.tempallow" ) {
        sysopen( my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT );
        flock( $TEMPALLOW, LOCK_EX );
        my @data = <$TEMPALLOW>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $ip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            my $iptype = checkip( \$ip );
            if ( $iptype == 6 and !$config{IPV6} ) { next }
            if ( ( ( ( time - $time ) < $timeout ) and $iptype ) or ( $message =~ /\(CF:([^\)]+)\)/ ) ) {
                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -s $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -s $ip -j $accept" );
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -d $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -d $ip -j $accept" );
                        }
                    }
                }
                push @newdata, $line;
            }
        }
        seek( $TEMPALLOW, 0, 0 );
        truncate( $TEMPALLOW, 0 );
        foreach my $line (@newdata) { print $TEMPALLOW "$line\n" }
        close($TEMPALLOW);
    }

    if ( $config{GLOBAL_ALLOW} ) {
        if ( $config{LF_IPSET} ) {
            ipsetcreate("chain_GALLOW");
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GALLOWIN -m set --match-set chain_GALLOW src -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GALLOWOUT -m set --match-set chain_GALLOW dst -j $accept" );
            if ( $config{IPV6} ) {
                ipsetcreate("chain_6_GALLOW");
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GALLOWIN -m set --match-set chain_6_GALLOW src -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GALLOWOUT -m set --match-set chain_6_GALLOW dst -j $accept" );
            }
        }
        if ( -e "/var/lib/csf/csf.gallow" ) {
            if ( $config{FASTSTART} ) { $faststart = 1 }
            foreach my $line ( slurp("/var/lib/csf/csf.gallow") ) {
                $line =~ s/$cleanreg//g;
                if ( $line =~ /^(\s|\#|$)/ ) { next }
                my ( $ip, $comment ) = split( /\s/, $line, 2 );
                linefilter( $ip, "allow", "GALLOW" );
            }
            if ( $config{FASTSTART} ) { faststart("Global Allow") }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GALLOWIN" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GALLOWOUT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $eth6devin -j GALLOWIN" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $eth6devout -j GALLOWOUT" );
        }
    }

    $config{CC_ALLOW} //= "";
    $config{CC_ALLOW} =~ s/\s//g;
    if ( $config{CC_ALLOW} ) {
        foreach my $cc ( split( /\,/, $config{CC_ALLOW} ) ) {
            $cc = lc $cc;
            if ( $config{LF_IPSET} ) {
                ipsetcreate("cc_$cc");
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -m set --match-set cc_$cc src -j $accept" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    ipsetcreate("cc_6_$cc");
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -m set --match-set cc_6_$cc src -j $accept" );
                }
            }
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_$cc $ip" }
                    }
                    ipsetrestore("cc_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                                my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                                if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                                if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                            }
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -s $ip -j $accept" );
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW [$cc]") }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_6_$cc $ip" }
                    }
                    ipsetrestore("cc_6_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -s $ip -j $accept" );
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW [$cc]") }
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j CC_ALLOW" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j CC_ALLOW" );
        }
    }

    if ( $config{DYNDNS} ) {
        if ( $config{LF_IPSET} ) {
            ipsetcreate("chain_ALLOWDYN");
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNIN -m set --match-set chain_ALLOWDYN src -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNOUT -m set --match-set chain_ALLOWDYN dst -j $accept" );
            if ( $config{IPV6} ) {
                ipsetcreate("chain_6_ALLOWDYN");
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNIN -m set --match-set chain_6_ALLOWDYN src -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNOUT -m set --match-set chain_6_ALLOWDYN dst -j $accept" );
            }
        }
        if ( -e "/var/lib/csf/csf.tempdyn" ) {
            foreach my $line ( slurp("/var/lib/csf/csf.tempdyn") ) {
                $line =~ s/$cleanreg//g;
                if ( $line =~ /^(\s|\#|$)/ ) { next }
                my ( $ip, $comment ) = split( /\s/, $line, 2 );
                linefilter( $ip, "allow", "ALLOWDYN" );
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWDYNIN" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWDYNOUT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWDYNIN" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWDYNOUT" );
        }
    }
    if ( $config{GLOBAL_DYNDNS} ) {
        if ( $config{LF_IPSET} ) {
            ipsetcreate("chain_GDYN");
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDYNIN -m set --match-set chain_GDYN src -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDYNOUT -m set --match-set chain_GDYN dst -j $accept" );
            if ( $config{IPV6} ) {
                ipsetcreate("chain_6_GDYN");
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDYNIN -m set --match-set chain_6_GDYN src -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDYNOUT -m set --match-set chain_6_GDYN dst -j $accept" );
            }
        }
        if ( -e "/var/lib/csf/csf.tempgdyn" ) {
            if ( $config{FASTSTART} ) { $faststart = 1 }
            foreach my $line ( slurp("/var/lib/csf/csf.tempgdyn") ) {
                $line =~ s/$cleanreg//g;
                if ( $line =~ /^(\s|\#|$)/ ) { next }
                my ( $ip, $comment ) = split( /\s/, $line, 2 );
                linefilter( $ip, "allow", "GDYN" );
            }
            if ( $config{FASTSTART} ) { faststart("Global Dynamic DNS") }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GDYNIN" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GDYNOUT" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GDYNIN" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GDYNOUT" );
        }
    }

    my @allow = slurp("/etc/csf/csf.allow");
    foreach my $line (@allow) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @allow, @incfile;
        }
    }
    if ( $config{FASTSTART} ) { $faststart = 1 }
    if ( $config{LF_IPSET} ) {
        ipsetcreate("chain_ALLOW");
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWIN -m set --match-set chain_ALLOW src -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWOUT -m set --match-set chain_ALLOW dst -j $accept" );
        if ( $config{IPV6} ) {
            ipsetcreate("chain_6_ALLOW");
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWIN -m set --match-set chain_6_ALLOW src -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWOUT -m set --match-set chain_6_ALLOW dst -j $accept" );
        }
    }
    foreach my $line (@allow) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ip, $comment ) = split( /\s/, $line, 2 );
        linefilter( $ip, "allow" );
    }
    if ( $config{FASTSTART} ) { faststart("csf.allow") }

    foreach my $name ( keys %blocklists ) {
        my $drop = $config{DROP};
        if ( $config{DROP_IP_LOGGING} ) { $drop = "BLOCKDROP" }
        if ( $config{LF_IPSET} ) {
            ipsetcreate("bl_$name");
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $name -m set --match-set bl_$name src -j $drop" );
            if ( $config{IPV6} ) {
                ipsetcreate("bl_6_$name");
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $name -m set --match-set bl_6_$name src -j $drop" );
            }
        }
        if ( -e "/var/lib/csf/csf.block.$name" ) {
            if ( $config{LF_IPSET} ) {
                undef @ipset;
                my @ipset6;
                foreach my $line ( slurp("/var/lib/csf/csf.block.$name") ) {
                    $line =~ s/$cleanreg//g;
                    if ( $line =~ /^(\s|\#|$)/ ) { next }
                    my ( $ip, $comment ) = split( /\s/, $line, 2 );
                    my $iptype = checkip( \$ip );
                    if ( $iptype == 4 ) {
                        push @ipset, "add -exist bl_$name $ip";
                    }
                    elsif ( $iptype == 6 and $config{IPV6} ) {
                        push @ipset6, "add -exist bl_6_$name $ip";
                    }
                }
                ipsetrestore("bl_$name");
                if ( $config{IPV6} ) {
                    @ipset = @ipset6;
                    ipsetrestore("bl_6_$name");
                }
            }
            else {
                if ( $config{FASTSTART} ) { $faststart = 1 }
                foreach my $line ( slurp("/var/lib/csf/csf.block.$name") ) {
                    $line =~ s/$cleanreg//g;
                    if ( $line =~ /^(\s|\#|$)/ ) { next }
                    my ( $ip, $comment ) = split( /\s/, $line, 2 );
                    my $iptype = checkip( \$ip );
                    if ( $iptype == 4 ) {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $name -s $ip -j $drop" );
                    }
                    elsif ( $iptype == 6 and $config{IPV6} ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $name -s $ip -j $drop" );
                    }
                }
                if ( $config{FASTSTART} ) { faststart("Blocklist $name") }
            }
        }
        $config{LF_BOGON_SKIP} =~ s/\s//g;
        if ( $name eq "BOGON" and $config{LF_BOGON_SKIP} ne "" ) {
            foreach my $device ( split( /\,/, $config{LF_BOGON_SKIP} ) ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I BOGON -i $device -j RETURN" );
            }
        }
        if ( $cxsreputation and $name =~ /^CXS_/ and $name ne "CXS_ALL" and $cxsports{$name} ne "" ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name" );
            if ( $config{IPV6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name" );
            }
        }
        else {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j $name" );
            if ( $config{IPV6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j $name" );
            }
        }
    }

    $config{CC_ALLOW_SMTPAUTH} //= "";
    $config{CC_ALLOW_SMTPAUTH} =~ s/\s//g;
    if ( $config{SMTPAUTH_RESTRICT} ) {
        if ($verbose) { print "csf: Generating /etc/exim.smtpauth\n" }
        sysopen( my $SMTPAUTH, "/etc/exim.smtpauth", O_WRONLY | O_CREAT );
        flock( $SMTPAUTH, LOCK_EX );
        seek( $SMTPAUTH, 0, 0 );
        truncate( $SMTPAUTH, 0 );
        print $SMTPAUTH "# DO NOT EDIT THIS FILE\n#\n";
        print $SMTPAUTH "# Modify /etc/csf/csf.smtpauth and then restart csf and then lfd\n\n";
        print $SMTPAUTH "127.0.0.0/8\n";
        print $SMTPAUTH "\"::1\"\n";
        print $SMTPAUTH "\"::1/128\"\n";

        if ( -e "/etc/csf/csf.smtpauth" ) {
            my @entries = slurp("/etc/csf/csf.smtpauth");
            foreach my $line (@entries) {
                if ( $line =~ /^Include\s*(.*)$/ ) {
                    my @incfile = slurp($1);
                    push @entries, @incfile;
                }
            }
            foreach my $line (@entries) {
                $line =~ s/$cleanreg//g;
                if ( $line eq "" )               { next }
                if ( $line =~ /^\s*\#|Include/ ) { next }
                my ( $ip, undef ) = split( /\s/, $line, 2 );
                my $status = checkip( \$ip );
                if    ( $status == 4 ) { print $SMTPAUTH "$ip\n" }
                elsif ( $status == 6 ) { print $SMTPAUTH "\"$ip\"\n" }
            }
        }
        foreach my $cc ( split( /\,/, $config{CC_ALLOW_SMTPAUTH} ) ) {
            $cc = lc $cc;
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                print $SMTPAUTH "\n# IPv4 addresses for [" . uc($cc) . "]:\n";
                foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                    $line =~ s/$cleanreg//g;
                    if ( $line =~ /^(\s|\#|$)/ ) { next }
                    my ( $ip, undef ) = split( /\s/, $line, 2 );
                    if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                        my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                        if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                        if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                    }
                    my $status = cccheckip( \$ip );
                    if    ( $status == 4 ) { print $SMTPAUTH "$ip\n" }
                    elsif ( $status == 6 ) { print $SMTPAUTH "\"$ip\"\n" }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                print $SMTPAUTH "\n# IPv6 addresses for [" . uc($cc) . "]:\n";
                foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                    $line =~ s/$cleanreg//g;
                    if ( $line =~ /^(\s|\#|$)/ ) { next }
                    my ( $ip, undef ) = split( /\s/, $line, 2 );
                    my $status = cccheckip( \$ip );
                    if    ( $status == 4 ) { print $SMTPAUTH "$ip\n" }
                    elsif ( $status == 6 ) { print $SMTPAUTH "\"$ip\"\n" }
                }
            }
        }
        close($SMTPAUTH);
        chmod( 0644, "/etc/exim.smtpauth" );
    }

    $config{CC_DENY} //= "";
    $config{CC_DENY} =~ s/\s//g;
    if ( $config{CC_DENY} ) {
        foreach my $cc ( split( /\,/, $config{CC_DENY} ) ) {
            $cc = lc $cc;
            my $drop = $config{DROP};
            if ( $config{DROP_IP_LOGGING} ) { $drop = "CCDROP" }
            if ( $config{LF_IPSET} ) {
                ipsetcreate("cc_$cc");
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -m set --match-set cc_$cc src -j $drop" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    ipsetcreate("cc_6_$cc");
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -m set --match-set cc_6_$cc src -j $drop" );
                }
            }
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_$cc $ip" }
                    }
                    ipsetrestore("cc_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -s $ip -j $drop" );
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_DENY [$cc]") }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_6_$cc $ip" }
                    }
                    ipsetrestore("cc_6_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -s $ip -j $drop" );
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_DENY [$cc]") }
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENY" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENY" );
        }
    }

    $config{CC_ALLOW_FILTER} //= "";
    $config{CC_ALLOW_FILTER} =~ s/\s//g;
    if ( $config{CC_ALLOW_FILTER} ) {
        my $cnt  = 0;
        my $cnt6 = 0;
        foreach my $cc ( split( /\,/, $config{CC_ALLOW_FILTER} ) ) {
            $cc = lc $cc;
            if ( $config{LF_IPSET} ) {
                ipsetcreate("cc_$cc");
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -m set --match-set cc_$cc src -j RETURN" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    ipsetcreate("cc_6_$cc");
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -m set --match-set cc_6_$cc src -j RETURN" );
                }
            }
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) {
                            push @ipset, "add -exist cc_$cc $ip";
                            $cnt++;
                        }
                    }
                    ipsetrestore("cc_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                                my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                                if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                                if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                            }
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -s $ip -j RETURN" );
                            $cnt++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW_FILTER [$cc]") }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            push @ipset, "add -exist cc_6_$cc $ip";
                            $cnt6++;
                        }
                    }
                    ipsetrestore("cc_6_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -s $ip -j RETURN" );
                            $cnt6++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW_FILTER [$cc]") }
                }
            }
        }
        my $drop = $config{DROP};
        if ( $config{DROP_IP_LOGGING} ) { $drop = "CCDROP" }
        if ( $cnt > 0 )                 { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -j $drop" ) }
        if ( $config{LF_SPI} ) {
            if ( $config{USE_FTPHELPER} ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept" );

                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept" );
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept" );
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWF" );
        if ( $config{IPV6} ) {
            if ( $cnt6 > 0 ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -j $drop" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWF" );
            if ( $config{IPV6_SPI} ) {
                if ( $config{USE_FTPHELPER} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept" );

                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept" );
                }
                else {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept" );
                }
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -I CC_ALLOWF $eth6devin -p icmpv6 -j $accept" );
            }
        }
    }

    $config{CC_ALLOW_PORTS} //= "";
    $config{CC_ALLOW_PORTS} =~ s/\s//g;
    if ( $config{CC_ALLOW_PORTS} ) {
        $config{CC_ALLOW_PORTS_TCP} //= "";
        $config{CC_ALLOW_PORTS_TCP} =~ s/\s//g;
        $config{CC_ALLOW_PORTS_UDP} //= "";
        $config{CC_ALLOW_PORTS_UDP} =~ s/\s//g;
        if ( $config{CC_ALLOW_PORTS_TCP} ne "" ) {
            foreach my $port ( split( /\,/, $config{CC_ALLOW_PORTS_TCP} ) ) {
                if ( $port eq "" )         { next }
                if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid CC_ALLOW_PORTS_TCP port [$port]" ) }
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p tcp $statemodulenew --dport $port -j $accept" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p tcp $statemodulenew --dport $port -j $accept" );
                }
            }
        }
        if ( $config{CC_ALLOW_PORTS_UDP} ne "" ) {
            foreach my $port ( split( /\,/, $config{CC_ALLOW_PORTS_UDP} ) ) {
                if ( $port eq "" )         { next }
                if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid CC_ALLOW_PORTS_UDP port [$port]" ) }
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p udp $statemodulenew --dport $port -j $accept" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p udp $statemodulenew --dport $port -j $accept" );
                }
            }
        }
        my $cnt = 0;
        foreach my $cc ( split( /\,/, $config{CC_ALLOW_PORTS} ) ) {
            $cc = lc $cc;
            if ( $config{LF_IPSET} ) {
                ipsetcreate("cc_$cc");
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -m set --match-set cc_$cc src -j CC_ALLOWPORTS" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    ipsetcreate("cc_6_$cc");
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -m set --match-set cc_6_$cc src -j CC_ALLOWPORTS" );
                }
            }
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_$cc $ip" }
                    }
                    ipsetrestore("cc_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                                my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                                if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                                if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                            }
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS" );
                            $cnt++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW_PORTS [$cc]") }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_6_$cc $ip" }
                    }
                    ipsetrestore("cc_6_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS" );
                            $cnt++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_ALLOW_PORTS [$cc]") }
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWP" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWP" );
        }
    }

    $config{CC_DENY_PORTS} //= "";
    $config{CC_DENY_PORTS} =~ s/\s//g;
    if ( $config{CC_DENY_PORTS} ) {
        $config{CC_DENY_PORTS_TCP} //= "";
        $config{CC_DENY_PORTS_TCP} =~ s/\s//g;
        $config{CC_DENY_PORTS_UDP} //= "";
        $config{CC_DENY_PORTS_UDP} =~ s/\s//g;
        if ( $config{CC_DENY_PORTS_TCP} ne "" ) {
            foreach my $port ( split( /\,/, $config{CC_DENY_PORTS_TCP} ) ) {
                if ( $port eq "" )         { next }
                if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid CC_DENY_PORTS_TCP port [$port]" ) }
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p tcp --dport $port -j $config{DROP}" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p tcp --dport $port -j $config{DROP}" );
                }
            }
        }
        if ( $config{CC_DENY_PORTS_UDP} ne "" ) {
            foreach my $port ( split( /\,/, $config{CC_DENY_PORTS_UDP} ) ) {
                if ( $port eq "" )         { next }
                if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid CC_DENY_PORTS_UDP port [$port]" ) }
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p udp --dport $port -j $config{DROP}" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p udp --dport $port -j $config{DROP}" );

                }
            }
        }
        my $cnt = 0;
        foreach my $cc ( split( /\,/, $config{CC_DENY_PORTS} ) ) {
            $cc = lc $cc;
            if ( $config{LF_IPSET} ) {
                ipsetcreate("cc_$cc");
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENYP -m set --match-set cc_$cc src -j CC_DENYPORTS" );
                if ( $config{CC6_LOOKUPS} and $config{IPV6} ) {
                    ipsetcreate("cc_6_$cc");
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENYP -m set --match-set cc_6_$cc src -j CC_DENYPORTS" );
                }
            }
            if ( -e "/var/lib/csf/zone/$cc.zone" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                            my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                            if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                            if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                        }
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_$cc $ip" }
                    }
                    ipsetrestore("cc_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            if ( $config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33 ) {
                                my ( $drop_ip, $drop_cidr ) = split( /\//, $ip );
                                if ( !length $drop_cidr )                 { $drop_cidr = "32" }
                                if ( $drop_cidr > $config{CC_DROP_CIDR} ) { next }
                            }
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYP -s $ip -j CC_DENYPORTS" );
                            $cnt++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_DENY_PORTS [$cc]") }
                }
            }
            if ( $config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6" ) {
                if ( $config{LF_IPSET} ) {
                    undef @ipset;
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) { push @ipset, "add -exist cc_6_$cc $ip" }
                    }
                    ipsetrestore("cc_6_$cc");
                }
                else {
                    if ( $config{FASTSTART} ) { $faststart = 1 }
                    foreach my $line ( slurp("/var/lib/csf/zone/$cc.zone6") ) {
                        $line =~ s/$cleanreg//g;
                        if ( $line =~ /^(\s|\#|$)/ ) { next }
                        my ( $ip, undef ) = split( /\s/, $line, 2 );
                        if ( cccheckip( \$ip ) ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYP -s $ip -j CC_DENYPORTS" );
                            $cnt++;
                        }
                    }
                    if ( $config{FASTSTART} ) { faststart("CC_DENY_PORTS [$cc]") }
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENYP" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENYP" );
        }
    }

    if ( $config{CLUSTER_SENDTO} ) {
        foreach my $ip ( split( /\,/, $config{CLUSTER_SENDTO} ) ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -p tcp -d $ip --dport $config{CLUSTER_PORT} -j $accept" );
        }
    }
    if ( $config{CLUSTER_RECVFROM} ) {
        foreach my $ip ( split( /\,/, $config{CLUSTER_RECVFROM} ) ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -p tcp -s $ip --dport $config{CLUSTER_PORT} -j $accept" );
        }
    }

    if ( $config{SYNFLOOD} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit $config{SYNFLOOD_RATE} --limit-burst $config{SYNFLOOD_BURST} -j RETURN" );
        if ( $config{DROP_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *SYNFLOOD Blocked* '" ) }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -j DROP" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --syn -j SYNFLOOD" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit $config{SYNFLOOD_RATE} --limit-burst $config{SYNFLOOD_BURST} -j RETURN" );
            if ( $config{DROP_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *SYNFLOOD Blocked* '" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -j DROP" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --syn -j SYNFLOOD" );
        }
    }

    $config{PORTFLOOD} =~ s/\s//g;
    if ( $config{PORTFLOOD} ) {
        my $maxrecent = 20;
        if ( -e "/sys/module/ipt_recent/parameters/ip_pkt_list_tot" ) {
            my @new = slurp("/sys/module/ipt_recent/parameters/ip_pkt_list_tot");
            if ( $new[0] > 1 ) { $maxrecent = $new[0] }
        }
        if ( -e "/sys/module/xt_recent/parameters/ip_pkt_list_tot" ) {
            my @new = slurp("/sys/module/xt_recent/parameters/ip_pkt_list_tot");
            if ( $new[0] > 1 ) { $maxrecent = $new[0] }
        }
        foreach my $portflood ( split( /\,/, $config{PORTFLOOD} ) ) {
            my ( $port, $proto, $count, $seconds ) = split( /\;/, $portflood );
            if ( ( ( $port < 0 ) or ( $port > 65535 ) ) or ( $proto !~ /icmp|tcp|udp/ ) or ( $seconds !~ /\d+/ ) ) { error( __LINE__, "csf: Incorrect PORTFLOOD setting: [$portflood]" ) }
            if ( ( $count < 1 ) or ( $count > $maxrecent ) ) {
                print "WARNING: count in PORTFLOOD setting must be between 1 and $maxrecent: [$portflood]\n";
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --set --name $port" );
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --update --seconds $seconds --hitcount $count --name $port -j PORTFLOOD" );
                if ( $config{PORTFLOOD6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --set --name $port" );
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --update --seconds $seconds --hitcount $count --name $port -j PORTFLOOD" );
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -j $config{DROP}" );
        if ( $config{PORTFLOOD6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -j $config{DROP}" );
        }
    }

    $config{CONNLIMIT} =~ s/\s//g;
    if ( $config{CONNLIMIT} ) {
        foreach my $connlimit ( split( /\,/, $config{CONNLIMIT} ) ) {
            my ( $port, $limit ) = split( /\;/, $connlimit );
            if ( ( $port < 0 ) or ( $port > 65535 ) or ( $limit < 1 ) or ( $limit !~ /\d+/ ) ) { error( __LINE__, "csf: Incorrect CONNLIMIT setting: [$connlimit]" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp --syn --dport $port -m connlimit --connlimit-above $limit -j CONNLIMIT" );
            if ( $config{CONNLIMIT6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp --syn --dport $port -m connlimit --connlimit-above $limit -j CONNLIMIT" );
            }
        }
        if ( $config{CONNLIMIT_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ConnLimit* '" ); }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -p tcp -j REJECT --reject-with tcp-reset" );
        if ( $config{CONNLIMIT6} ) {
            if ( $config{CONNLIMIT_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ConnLimit* '" ); }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -p tcp -j REJECT --reject-with tcp-reset" );
        }
    }

    if ( $config{UDPFLOOD} ) {
        foreach my $item ( split( /\,/, $config{UDPFLOOD_ALLOWUSER} ) ) {
            $item =~ s/\s//g;
            my $uid = ( getpwnam($item) )[2];
            if ($uid) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner $uid -j RETURN", 1 );
                if ( $config{IPV6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner $uid -j RETURN", 1 );
                }
            }
        }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner 0 -j RETURN", 1 );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -m limit --limit $config{UDPFLOOD_LIMIT} --limit-burst $config{UDPFLOOD_BURST} -j RETURN" );
        if ( $config{UDPFLOOD_LOGGING} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDPFLOOD* '" ); }
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -j $config{DROP_OUT}" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -p udp -j UDPFLOOD" );
        if ( $config{IPV6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner 0 -j RETURN", 1 );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -m limit --limit $config{UDPFLOOD_LIMIT} --limit-burst $config{UDPFLOOD_BURST} -j RETURN" );
            if ( $config{UDPFLOOD_LOGGING} ) { syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDPFLOOD* '" ); }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -j $config{DROP_OUT}" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -p udp -j UDPFLOOD" );
        }
    }
    my $icmp_in_rate  = "";
    my $icmp_out_rate = "";
    if ( $config{ICMP_IN_RATE} )  { $icmp_in_rate  = "-m limit --limit $config{ICMP_IN_RATE}" }
    if ( $config{ICMP_OUT_RATE} ) { $icmp_out_rate = "-m limit --limit $config{ICMP_OUT_RATE}" }

    if ( $config{ICMP_IN} ) {
        if ( $config{ICMP_IN_RATE} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request $icmp_in_rate -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request -j $dropin" );
        }
    }
    else {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request -j $dropin" );
    }
    if ( $config{ICMP_TIMESTAMPDROP} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type timestamp-request -j $dropin" );
    }
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp -j $accept" );

    if ( $config{ICMP_OUT} ) {
        if ( $config{ICMP_OUT_RATE} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request $icmp_out_rate -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request -j $dropout" );
        }
    }
    else {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request -j $dropout" );
    }
    if ( $config{ICMP_TIMESTAMPDROP} ) {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type timestamp-reply -j $dropout" );
    }
    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp -j $accept" );

    if ( $config{IPV6} ) {
        if ( $config{IPV6_ICMP_STRICT} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type destination-unreachable -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type packet-too-big -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type time-exceeded -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type parameter-problem -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-request -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-reply -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept" );
        }
        else {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 -j $accept" );
        }

        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 -j $accept" );

        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type destination-unreachable -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type packet-too-big -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type time-exceeded -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type parameter-problem -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-request -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-reply -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept");
        #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept");
    }

    if ( $config{LF_SPI} ) {
        if ( $config{USE_FTPHELPER} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -A PREROUTING -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -A OUTPUT -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule RELATED -m helper --helper ftp -j $accept" );

            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule ESTABLISHED -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule ESTABLISHED -j $accept" );
        }
        else {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule ESTABLISHED,RELATED -j $accept" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule ESTABLISHED,RELATED -j $accept" );
        }
    }
    else {
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p udp -m udp --dport 32768:61000 -j $accept" );
        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp -m tcp --dport 32768:61000 ! --syn -j $accept" );
    }
    if ( $config{IPV6} ) {
        if ( $config{IPV6_SPI} ) {
            if ( $config{USE_FTPHELPER} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -A PREROUTING -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -A OUTPUT -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule RELATED -m helper --helper ftp -j $accept" );

                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin $statemodule ESTABLISHED -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout $statemodule ESTABLISHED -j $accept" );
            }
            else {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin $statemodule ESTABLISHED,RELATED -j $accept" );
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout $statemodule ESTABLISHED,RELATED -j $accept" );
            }
        }
        else {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp -m udp --dport 32768:61000 -j $accept" );
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p tcp -m tcp --dport 32768:61000 ! --syn -j $accept" );
        }
    }

    $config{PORTKNOCKING} =~ s/\s//g;
    if ( $config{PORTKNOCKING} ) {
        foreach my $portknock ( split( /\,/, $config{PORTKNOCKING} ) ) {
            my ( $port, $proto, $timeout, $knocks ) = split( /\;/, $portknock, 4 );
            my @steps  = split( /\;/, $knocks );
            my $nsteps = @steps;
            if ( $nsteps < 3 ) {
                print "csf: Error - not enough Port Knocks for port $port [$knocks]\n";
                next;
            }
            for ( my $step = 1; $step < $nsteps + 1; $step++ ) {
                my $ar = $step - 1;
                if ( $step == 1 ) {
                    if ( $config{PORTKNOCKING_LOG} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_S$step* '" ) }
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m recent --set --name PK\_$port\_S$step" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -j DROP" );
                }
                else {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N PK\_$port\_S$step\_IN" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m recent --name PK\_$port\_S" . ( $step - 1 ) . " --remove" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m recent --name PK\_$port\_S$step --set" );
                    if ( $config{PORTKNOCKING_LOG} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_S$step* '" ) }
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -j DROP" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S" . ( $step - 1 ) . " -j PK\_$port\_S$step\_IN" );
                }
            }
            if ( $config{PORTKNOCKING_LOG} ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S$nsteps -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_IN* '" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S$nsteps -j ACCEPT" );
        }
    }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{TCP_IN} =~ s/\s//g;
    if ( $config{TCP_IN} ne "" ) {
        foreach my $port ( split( /\,/, $config{TCP_IN} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid TCP_IN port [$port]" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp $statemodulenew --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("TCP_IN") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{TCP6_IN} =~ s/\s//g;
    if ( $config{IPV6} and $config{TCP6_IN} ne "" ) {
        foreach my $port ( split( /\,/, $config{TCP6_IN} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid TCP6_IN port [$port]" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p tcp $statemodule6new --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("TCP6_IN") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{TCP_OUT} =~ s/\s//g;
    if ( $config{TCP_OUT} ne "" ) {
        foreach my $port ( split( /\,/, $config{TCP_OUT} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid TCP_OUT port [$port]" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p tcp $statemodulenew --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("TCP_OUT") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{TCP6_OUT} =~ s/\s//g;
    if ( $config{IPV6} and $config{TCP6_OUT} ne "" ) {
        foreach my $port ( split( /\,/, $config{TCP6_OUT} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid TCP6_OUT port [$port]" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p tcp $statemodule6new --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("TCP6_OUT") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{UDP_IN} =~ s/\s//g;
    if ( $config{UDP_IN} ne "" ) {
        foreach my $port ( split( /\,/, $config{UDP_IN} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid UDP_IN port [$port]" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p udp $statemodulenew --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("UDP_IN") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{UDP6_IN} =~ s/\s//g;
    if ( $config{IPV6} and $config{UDP6_IN} ne "" ) {
        foreach my $port ( split( /\,/, $config{UDP6_IN} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid UDP6_IN port [$port]" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp $statemodule6new --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("UDP6_IN") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{UDP_OUT} =~ s/\s//g;
    if ( $config{UDP_OUT} ne "" ) {
        foreach my $port ( split( /\,/, $config{UDP_OUT} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid UDP_OUT port [$port]" ) }
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p udp $statemodulenew --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("UDP_OUT") }

    if ( $config{FASTSTART} ) { $faststart = 1 }
    $config{UDP6_OUT} =~ s/\s//g;
    if ( $config{IPV6} and $config{UDP6_OUT} ne "" ) {
        foreach my $port ( split( /\,/, $config{UDP6_OUT} ) ) {
            if ( $port eq "" )         { next }
            if ( $port !~ /^[\d:]*$/ ) { error( __LINE__, "Invalid UDP6_OUT port [$port]" ) }
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p udp $statemodule6new --dport $port -j $accept" );
        }
    }
    if ( $config{FASTSTART} ) { faststart("UDP6_OUT") }

    #	if ($config{IPV6}) {
    #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp -m frag --fraglast -j $accept");
    #	}

    #	my $icmp_in_rate = "";
    #	my $icmp_out_rate = "";
    #	if ($config{ICMP_IN_RATE}) {$icmp_in_rate = "-m limit --limit $config{ICMP_IN_RATE}"}
    #	if ($config{ICMP_OUT_RATE}) {$icmp_out_rate = "-m limit --limit $config{ICMP_OUT_RATE}"}
    #
    #	if ($config{ICMP_IN}) {
    #		syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request $icmp_in_rate -j $accept");
    #		syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-reply $icmp_out_rate -j $accept");
    #	}
    #
    #	if ($config{ICMP_OUT}) {
    #		syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request $icmp_out_rate -j $accept");
    #		syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-reply $icmp_in_rate -j $accept");
    #	}
    #
    #	syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type time-exceeded -j $accept");
    #	syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type destination-unreachable -j $accept");
    #
    #	syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type time-exceeded -j $accept");
    #	syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type destination-unreachable -j $accept");
    #
    #	if ($config{IPV6}) {
    #		if ($config{IPV6_ICMP_STRICT}) {
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type destination-unreachable -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type packet-too-big -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type time-exceeded -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type parameter-problem -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-request -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-reply -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept");
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept");
    #		} else {
    #			syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A INPUT $eth6devin -p icmpv6 -j $accept");
    #		}
    #
    #		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type destination-unreachable -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type packet-too-big -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type time-exceeded -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type parameter-problem -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-request -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-reply -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept");
##		syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose  -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept");
    #	}

    if ( -e "/etc/csf/csf.redirect" ) {
        my $dnat    = 0;
        my @entries = slurp("/etc/csf/csf.redirect");
        foreach my $line (@entries) {
            if ( $line =~ /^Include\s*(.*)$/ ) {
                my @incfile = slurp($1);
                push @entries, @incfile;
            }
        }
        foreach my $line (@entries) {
            $line =~ s/$cleanreg//g;
            if ( $line eq "" )               { next }
            if ( $line =~ /^\s*\#|Include/ ) { next }
            my ( $redirect, $comment ) = split( /\s/, $line, 2 );
            my ( $ipx, $porta, $ipy, $portb, $proto ) = split( /\|/, $redirect );
            unless ( $proto eq "tcp" or $proto eq "udp" )            { error( __LINE__, "csf: Incorrect csf.redirect  setting ([$proto]): [$line]" ) }
            unless ( $ipx eq "*" or checkip( \$ipx ) )               { error( __LINE__, "csf: Incorrect csf.redirect  setting ([$ipx]): [$line]" ) }
            unless ( $porta eq "*" or $porta > 0 or $porta < 65536 ) { error( __LINE__, "csf: Incorrect csf.redirect  setting ([$porta]): [$line]" ) }
            unless ( $ipy eq "*" or checkip( \$ipy ) )               { error( __LINE__, "csf: Incorrect csf.redirect  setting ([$ipy]): [$line]" ) }
            unless ( $portb eq "*" or $portb > 0 or $portb < 65536 ) { error( __LINE__, "csf: Incorrect csf.redirect  setting ([$portb]): [$line]" ) }

            if ( $ipy eq "*" ) {
                if   ( $ipx eq "*" ) { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto --dport $porta -j REDIRECT --to-ports $portb" ) }
                else                 { syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx --dport $porta -j REDIRECT --to-ports $portb" ) }
            }
            else {
                unless ($dnat) {
                    open( my $OUT, ">", "/proc/sys/net/ipv4/ip_forward" );
                    flock( $OUT, LOCK_EX );
                    print $OUT "1";
                    close($OUT);
                    $dnat = 1;
                }
                if ( $ipx ne "*" and $porta eq "*" ) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx -j DNAT --to-destination $ipy" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING $ethdevout -p $proto -d $ipy -j SNAT --to-source $ipx" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -p $proto -d $ipy  $statemodulenew -j ACCEPT" );
                }
                elsif ( $ipx ne "*" and $porta ne "*" and $portb ne "*" ) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx --dport $porta -j DNAT --to-destination $ipy:$portb" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING $ethdevout -p $proto -d $ipy -j SNAT --to-source $ipx" );
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -p $proto -d $ipy --dport $portb  $statemodulenew -j ACCEPT" );
                }
                else { error( __LINE__, "csf: Invalid csf.redirect format [$line]" ) }
            }
        }
        if ( $dnat and $config{LF_SPI} ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin $statemodule ESTABLISHED,RELATED -j ACCEPT" );
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -j LOGDROPIN" );
        }
    }
    return;
}

sub dodisable {
    open( my $OUT, ">", "/etc/csf/csf.disable" );
    flock( $OUT, LOCK_EX );
    close($OUT);

    sysopen( my $CONF, "/etc/chkserv.d/chkservd.conf", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/chkserv.d/chkservd.conf: $!" );
    flock( $CONF, LOCK_EX )                                               or error( __LINE__, "Could not lock /etc/chkserv.d/chkservd.conf: $!" );

    my $text = join( "", <$CONF> );
    my @conf = split( /$slurpreg/, $text );
    chomp @conf;
    seek( $CONF, 0, 0 );
    truncate( $CONF, 0 );
    foreach my $line (@conf) {
        if ( $line =~ /^lfd:/ ) { $line = "lfd:0" }
        print $CONF $line . "\n";
    }
    close($CONF) or error( __LINE__, "Could not close /etc/conf: $!" );

    ConfigServer::Service::stoplfd();
    dostop(0);

    print "csf and lfd have been disabled\n";
    return;
}

sub doenable {
    unless ( -e "/etc/csf/csf.disable" ) {
        print "csf and lfd are not disabled!\n";
        exit 0;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command early termination
    }
    unlink("/etc/csf/csf.disable");
    dostart();
    ConfigServer::Service::startlfd();
    sysopen( my $CONF, "/etc/chkserv.d/chkservd.conf", O_RDWR | O_CREAT ) or error( __LINE__, "Could not open /etc/chkserv.d/chkservd.conf: $!" );
    flock( $CONF, LOCK_EX )                                               or error( __LINE__, "Could not lock /etc/chkserv.d/chkservd.conf: $!" );

    my $text = join( "", <$CONF> );
    my @conf = split( /$slurpreg/, $text );
    chomp @conf;
    seek( $CONF, 0, 0 );
    truncate( $CONF, 0 );
    foreach my $line (@conf) {
        if ( $line =~ /^lfd:/ ) { $line = "lfd:1" }
        print $CONF $line . "\n";
    }
    close($CONF) or error( __LINE__, "Could not close /etc/conf: $!" );

    open( my $OUT, ">", "/etc/chkserv.d/lfd" );
    flock( $OUT, LOCK_EX );
    print $OUT "service[lfd]=x,x,x,service lfd restart,lfd,root\n";
    close($OUT);

    print "csf and lfd have been enabled\n";
    return;
}

sub crontab {
    my $act     = shift;
    my @crontab = slurp("/etc/crontab");
    my $hit     = 0;
    my @newcrontab;
    foreach my $line (@crontab) {
        if ( $line =~ /csf(\.pl)? -f/ ) {
            $hit = 1;
            if ( $act eq "add" ) {
                push @newcrontab, $line;
            }
        }
        else {
            push @newcrontab, $line;
        }
    }
    if ( ( $act eq "add" ) and !($hit) ) {
        push @newcrontab, "*/$config{TESTING_INTERVAL} * * * * root /usr/sbin/csf -f > /dev/null 2>&1";
    }

    if ( ( $act eq "remove" ) and !($hit) ) {

        # don't do anything
    }
    else {
        sysopen( my $CRONTAB, "/etc/crontab", O_RDWR | O_CREAT ) or die "Could not open /etc/crontab: $!";
        flock( $CRONTAB, LOCK_EX )                               or die "Could not lock /etc/crontab: $!";
        seek( $CRONTAB, 0, 0 );
        truncate( $CRONTAB, 0 );
        foreach my $line (@newcrontab) {
            print $CRONTAB $line . "\n";
        }
        close($CRONTAB) or die "Could not close /etc/crontab: $!";
    }
    return;
}

sub error {
    my $line  = shift;
    my $error = shift;
    my $verbose;
    if ( $config{DEBUG} >= 1 ) { $verbose = "--verbose" }
    system("$config{IPTABLES} $verbose --policy INPUT ACCEPT");
    system("$config{IPTABLES} $verbose --policy OUTPUT ACCEPT");
    system("$config{IPTABLES} $verbose --policy FORWARD ACCEPT");
    system("$config{IPTABLES} $verbose --flush");
    system("$config{IPTABLES} $verbose --delete-chain");

    if ( $config{NAT} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t nat --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t nat --delete-chain" );
    }
    if ( $config{RAW} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t raw --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t raw --delete-chain" );
    }
    if ( $config{MANGLE} ) {
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t mangle --flush" );
        syscommand( __LINE__, "$config{IPTABLES} $verbose -t mangle --delete-chain" );
    }

    if ( $config{IPV6} ) {
        system("$config{IP6TABLES} $verbose --policy INPUT ACCEPT");
        system("$config{IP6TABLES} $verbose --policy OUTPUT ACCEPT");
        system("$config{IP6TABLES} $verbose --policy FORWARD ACCEPT");
        system("$config{IP6TABLES} $verbose --flush");
        system("$config{IP6TABLES} $verbose --delete-chain");
        if ( $config{NAT6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t nat --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t nat --delete-chain" );
        }
        if ( $config{RAW6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t raw --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t raw --delete-chain" );
        }
        if ( $config{MANGLE6} ) {
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t mangle --flush" );
            syscommand( __LINE__, "$config{IP6TABLES} $verbose -t mangle --delete-chain" );
        }
    }

    if ( $config{LF_IPSET} ) {
        system("$config{IPSET} flush");
        system("$config{IPSET} destroy");
    }

    print "Error: $error, at line $line\n";
    open( my $OUT, ">", "/etc/csf/csf.error" );
    flock( $OUT, LOCK_EX );
    print $OUT "Error: $error, at line $line in /usr/sbin/csf\n";
    close($OUT);
    if ( $config{TESTING} ) { crontab("remove") }
    exit 1;    ## no critic (Cpanel::NoExitsFromSubroutines) - Fatal error termination
}

sub version {
    my ($myv) = slurpee( "/etc/csf/version.txt", 'fatal' => 1 );
    chomp $myv;
    return $myv;
}

sub getethdev {
    my $ethdev   = ConfigServer::GetEthDev->new();
    my %g_ifaces = $ethdev->ifaces;
    my %g_ipv4   = $ethdev->ipv4;
    my %g_ipv6   = $ethdev->ipv6;
    foreach my $key ( keys %g_ifaces ) {
        $ifaces{$key} = 1;
    }
    foreach my $key ( keys %g_ipv4 ) {
        $ips{$key} = 1;
    }
    if ( $config{IPV6} ) {
        foreach my $key ( keys %g_ipv6 ) {
            eval {
                local $SIG{__DIE__} = undef;
                $ipscidr6->add($key);
            };
        }
    }

    $config{ETH_DEVICE} //= "";
    $config{ETH_DEVICE} =~ s/:.*//;    # Strip everything after the first colon.
    if ( $config{ETH_DEVICE} eq "" ) {
        $ethdevin  = "! -i lo";
        $ethdevout = "! -o lo";
    }
    else {
        $ethdevin  = "-i $config{ETH_DEVICE}";
        $ethdevout = "-o $config{ETH_DEVICE}";
    }

    $config{ETH6_DEVICE} //= "";
    if ( $config{ETH6_DEVICE} eq "" ) {
        $eth6devin  = $ethdevin;
        $eth6devout = $ethdevout;
    }
    else {
        $eth6devin  = "-i $config{ETH6_DEVICE}";
        $eth6devout = "-o $config{ETH6_DEVICE}";
    }
    return;
}

sub linefilter {
    my $line     = shift;
    my $ad       = shift;
    my $chain    = shift // "";
    my $delete   = shift;
    my $pktin    = "$accept";
    my $pktout   = "$accept";
    my $localin  = "ALLOWIN";
    my $localout = "ALLOWOUT";
    my $inadd    = "-I";

    if ( $ad eq "deny" ) {
        $inadd  = "-A";
        $pktin  = $config{DROP};
        $pktout = $config{DROP_OUT};
        if ( $config{DROP_IP_LOGGING} )  { $pktin  = "LOGDROPIN" }
        if ( $config{DROP_OUT_LOGGING} ) { $pktout = "LOGDROPOUT" }
        $localin  = "DENYIN";
        $localout = "DENYOUT";
    }
    my $chainin  = $chain . "IN";
    my $chainout = $chain . "OUT";

    $line =~ s/[\n\r]//g;
    $line = lc $line;
    if ( $line =~ /^\#/ )      { return }
    if ( $line =~ /^Include/ ) { return }
    if ( $line eq "" )         { return }

    my $checkip  = checkip( \$line );
    my $iptables = $config{IPTABLES};
    my $ipv4     = 1;
    my $ipv6     = 0;
    my $linein   = $ethdevin;
    my $lineout  = $ethdevout;
    if ( $checkip == 6 ) {
        if ( $config{IPV6} ) {
            $iptables = $config{IP6TABLES};
            $linein   = $eth6devin;
            $lineout  = $eth6devout;
            $ipv4     = 0;
            $ipv6     = 1;
        }
        else { return }
    }

    if ($checkip) {
        if ($chain) {
            if ( $config{LF_IPSET} ) {
                if   ($ipv4) { ipsetadd( "chain_$chainin",     $line ) }
                else         { ipsetadd( "chain_6_${chainin}", $line ) }
            }
            else {
                syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein -s $line -j $pktin" );
                if ( ( $ad eq "deny" and !$config{LF_BLOCKINONLY} ) or ( $ad ne "deny" ) ) { syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -A $chainout $lineout -d $line -j $pktout" ) }
            }
        }
        else {
            if ($delete) {
                if ( $config{LF_IPSET} ) {
                    if   ($ipv4) { ipsetdel( "chain_$localin",     $line ) }
                    else         { ipsetdel( "chain_6_${localin}", $line ) }
                }
                else {
                    syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -D $localin $linein -s $line -j $pktin" );
                    if ( ( $ad eq "deny" and !$config{LF_BLOCKINONLY} ) or ( $ad ne "deny" ) ) { syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -D $localout $lineout -d $line -j $pktout" ) }
                }
                if ( ( $ad eq "deny" ) and ( $ipv4 and $config{MESSENGER}  and $config{MESSENGER_PERM} ) ) { domessenger( $line, "D" ) }
                if ( ( $ad eq "deny" ) and ( $ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM} ) ) { domessenger( $line, "D" ) }
            }
            else {
                if ( $config{LF_IPSET} ) {
                    if   ($ipv4) { ipsetadd( "chain_$localin",     $line ) }
                    else         { ipsetadd( "chain_6_${localin}", $line ) }
                }
                else {
                    syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose $inadd $localin $linein -s $line -j $pktin" );
                    if ( ( $ad eq "deny" and !$config{LF_BLOCKINONLY} ) or ( $ad ne "deny" ) ) { syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose $inadd $localout $lineout -d $line -j $pktout" ) }
                }
                if ( ( $ad eq "deny" ) and ( $ipv4 and $config{MESSENGER}  and $config{MESSENGER_PERM} ) ) { domessenger( $line, "A" ) }
                if ( ( $ad eq "deny" ) and ( $ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM} ) ) { domessenger( $line, "A" ) }
            }
        }
    }
    elsif ( $line =~ /[:|]/ ) {
        if ( $line !~ /\|/ ) { $line =~ s/\:/\|/g }
        my $sip      = "";
        my $dip      = "";
        my $sport    = "";
        my $dport    = "";
        my $protocol = "-p tcp";
        my $inout;
        my $from = 0;
        my $uid  = "";
        my $gid  = "";
        my $iptype;

        my @ll = split( /\|/, $line );
        if ( $ll[0] eq "tcp" ) {
            $protocol = "-p tcp";
            $from     = 1;
        }
        elsif ( $ll[0] eq "udp" ) {
            $protocol = "-p udp";
            $from     = 1;
        }
        elsif ( $ll[0] eq "icmp" ) {
            $protocol = "-p icmp";
            $from     = 1;
        }
        for ( my $x = $from; $x < 2; $x++ ) {
            next unless defined $ll[$x];
            if ( ( $ll[$x] eq "out" ) ) {
                $inout = "out";
                $from  = $x + 1;
                last;
            }
            elsif ( ( $ll[$x] eq "in" ) ) {
                $inout = "in";
                $from  = $x + 1;
                last;
            }
        }
        for ( my $x = $from; $x < 3; $x++ ) {
            next unless defined $ll[$x];
            if ( ( $ll[$x] =~ /d=(.*)/ ) ) {
                $dport = "--dport $1";
                $dport =~ s/_/:/g;
                if ( $protocol eq "-p icmp" ) { $dport = "--icmp-type $1" }
                if ( $dport =~ /,/ )          { $dport = "-m multiport " . $dport }
                $from = $x + 1;
                last;
            }
            elsif ( ( $ll[$x] =~ /s=(.*)/ ) ) {
                $sport = "--sport $1";
                $sport =~ s/_/:/g;
                if ( $protocol eq "-p icmp" ) { $sport = "--icmp-type $1" }
                if ( $sport =~ /,/ )          { $sport = "-m multiport " . $sport }
                $from = $x + 1;
                last;
            }
        }
        for ( my $x = $from; $x < 4; $x++ ) {
            next unless defined $ll[$x];
            if ( ( $ll[$x] =~ /d=(.*)/ ) ) {
                my $ip     = $1;
                my $status = checkip( \$ip );
                if ($status) {
                    $iptype = $status;
                    $dip    = "-d $1";
                }
                last;
            }
            elsif ( ( $ll[$x] =~ /s=(.*)/ ) ) {
                my $ip     = $1;
                my $status = checkip( \$ip );
                if ($status) {
                    $iptype = $status;
                    $sip    = "-s $1";
                }
                last;
            }
        }
        for ( my $x = $from; $x < 5; $x++ ) {
            next unless defined $ll[$x];
            if ( ( $ll[$x] =~ /u=(.*)/ ) ) {
                $uid = "--uid-owner $1";
                last;
            }
            elsif ( ( $ll[$x] =~ /g=(.*)/ ) ) {
                $gid = "--gid-owner $1";
                last;
            }
        }

        if ( $uid or $gid ) {
            if ( $config{VPS} and $noowner ) {
                print "Cannot use UID or GID rules [$ad: $line] on this VPS as the Monolithic kernel does not support the iptables module ipt_owner/xt_owner - rule skipped\n";
            }
            else {
                if ($chain) {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                    if ( $config{IPV6} ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                    }
                }
                else {
                    if ($delete) {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                        if ( $config{IPV6} ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                        }
                    }
                    else {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                        if ( $config{IPV6} ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout" );
                        }
                    }
                }
            }
        }
        elsif ( ( $sip or $dip ) and ( $dport or $sport ) ) {
            my $iptables = $config{IPTABLES};
            if ( $iptype == 6 ) {
                if ( $config{IPV6} ) {
                    $iptables = $config{IP6TABLES};
                }
                else {
                    return;
                }
            }
            if ( ( $inout eq "" ) or ( $inout eq "in" ) ) {
                my $bport = $dport;
                $bport =~ s/--dport //o;
                my $bip = $sip;
                $bip =~ s/-s //o;
                if ($chain) {
                    syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein $protocol $dip $sip $dport $sport -j $pktin" );
                }
                else {
                    if ($delete) {
                        syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -D $localin $linein $protocol $dip $sip $dport $sport -j $pktin" );
                        if ( $messengerports{$bport} and ( $ad eq "deny" ) and ( $ipv4 and $config{MESSENGER}  and $config{MESSENGER_PERM} ) ) { domessenger( $bip, "D", "$bport" ) }
                        if ( $messengerports{$bport} and ( $ad eq "deny" ) and ( $ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM} ) ) { domessenger( $bip, "D", "$bport" ) }
                    }
                    else {
                        syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose $inadd $localin $linein $protocol $dip $sip $dport $sport -j $pktin" );
                        if ( $messengerports{$bport} and ( $ad eq "deny" ) and ( $ipv4 and $config{MESSENGER}  and $config{MESSENGER_PERM} ) ) { domessenger( $bip, "A", "$bport" ) }
                        if ( $messengerports{$bport} and ( $ad eq "deny" ) and ( $ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM} ) ) { domessenger( $bip, "A", "$bport" ) }
                    }
                }
            }
            if ( $inout eq "out" ) {
                if ($chain) {
                    syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dip $sip $dport $sport -j $pktout" );
                }
                else {
                    if ($delete) {
                        syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dip $sip $dport $sport -j $pktout" );
                    }
                    else {
                        syscommand( __LINE__, "$iptables $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dip $sip $dport $sport -j $pktout" );
                    }
                }
            }
        }
    }
    return;
}

sub docheck {

    # Auto-updates have been deprecated. This command now performs a local installation check.
    print "Checking CSF installation...\n";
    print "CSF version: v$version\n";

    # Verify critical files exist
    my @critical_files = (
        '/usr/sbin/csf',
        '/usr/sbin/lfd',
        '/etc/csf/csf.conf',
    );

    my $all_ok = 1;
    foreach my $file (@critical_files) {
        if ( -e $file ) {
            print "  ✓ $file exists\n";
        }
        else {
            print "  ✗ $file missing\n";
            $all_ok = 0;
        }
    }

    if ($all_ok) {
        print "\nCSF installation check passed\n";
        print "Note: Auto-updates are no longer supported. Please use your package manager to update CSF.\n";
    }
    else {
        print "\nCSF installation check failed - some files are missing\n";
        exit 1;    ## no critic (Cpanel::NoExitsFromSubroutines) - Installation check failure
    }

    return;
}

sub doiplookup {
    my $ip = $input{argument}[0];

    if ( checkip( \$ip ) ) {
        print iplookup($ip) . "\n";
    }
    else {
        print "lookup failed: [$ip] is not a valid PUBLIC IP\n";
    }
    $input{argument}[0] = $ip;

    return;
}

sub dogrep {
    my $ipmatch = $input{argument}[0];
    checkip( \$ipmatch );
    my $ipstring = quotemeta($ipmatch);
    my $mhit     = 0;
    my $head     = 0;
    my $oldchain = "INPUT";
    my $table    = "filter";
    my $chain    = "";
    my $rest     = "";
    format GREP =
@<<<<< @<<<<<<<<<<<<<<< @*
$table, $chain, $rest
.
    local $~ = "GREP";

    my $command = "echo 'filter table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers";
    if ( $config{NAT} )    { $command .= " ; echo 'nat table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers" }
    if ( $config{MANGLE} ) { $command .= " ;echo 'mangle table:\n' ;  $config{IPTABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers" }
    if ( $config{RAW} )    { $command .= " ; echo 'raw table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers" }
    my ( $childin, $childout );
    my $pid    = IPC::Open3::open3( $childin, $childout, $childout, $command );
    my @output = <$childout>;
    waitpid( $pid, 0 );
    chomp @output;
    if ( $output[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @output }

    foreach my $line (@output) {
        if ( $line =~ /^Chain\s([\w\_]*)\s/ )         { $chain = $1 }
        if ( $line =~ /^(\S+) table:$/ )              { $table = $1 }
        if ( defined $chain && $chain eq "acctboth" ) { next }
        if ( !$head and ( $line =~ /^num/ ) )         { print "\nTable  Chain            $line\n"; $head = 1 }
        if ( $line !~ /\d+/ )                         { next }
        my ( undef, undef, undef, $action, undef, undef, undef, undef, $source, $destination, $options ) = split( /\s+/, $line, 11 );

        my $hit = 0;
        if ( $line =~ /\b$ipstring\b/i ) {
            $hit = 1;
        }
        else {
            if ( defined $source and ( $source =~ /\// ) and ( $source ne "0.0.0.0/0" ) ) {
                if ( checkip( \$source ) ) {
                    my $cidr = Net::CIDR::Lite->new;
                    eval { local $SIG{__DIE__} = undef; $cidr->add($source) };
                    if ( $cidr->find($ipmatch) ) { $hit = 1 }
                }
            }
            if ( !$hit and defined $destination and ( $destination =~ /\// ) and ( $destination ne "0.0.0.0/0" ) ) {
                if ( checkip( \$destination ) ) {
                    my $cidr = Net::CIDR::Lite->new;
                    eval { local $SIG{__DIE__} = undef; $cidr->add($destination) };
                    if ( $cidr->find($ipmatch) ) { $hit = 1 }
                }
            }
        }
        if ($hit) {
            $rest = $line;
            if ( $oldchain ne $chain ) { print "\n" }
            write;
            $oldchain = $chain;
            $mhit     = 1;
        }
    }
    unless ($mhit) {
        print "No matches found for $ipmatch in iptables\n";
    }

    if ( $config{LF_IPSET} and checkip( \$ipmatch ) ) {
        print "\n";
        my $mhit     = 0;
        my $head     = 0;
        my $oldchain = "INPUT";
        my ( $childin, $childout );
        my $pid    = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "-n", "list" );
        my @output = <$childout>;
        waitpid( $pid, 0 );
        chomp @output;
        my %sets;
        foreach my $line (@output) { $sets{$line} = 1 }

        foreach my $chain ( keys %sets ) {
            my $option;
            my $cc;
            my $country;

            if ( $chain =~ /^cc_(\w+)$/ ) {
                $cc      = $1;
                $country = uc $cc;
                if ( $config{CC_DENY}         =~ /$cc/i ) { $option = "CC_DENY" }
                if ( $config{CC_ALLOW}        =~ /$cc/i ) { $option = "CC_ALLOW" }
                if ( $config{CC_ALLOW_FILTER} =~ /$cc/i ) { $option = "CC_ALLOW_FILTER" }
                if ( $config{CC_ALLOW_PORTS}  =~ /$cc/i ) { $option = "CC_ALLOW_PORTS" }
                if ( $config{CC_DENY_PORTS}   =~ /$cc/i ) { $option = "CC_DENY_PORTS" }
            }
            if ( $chain =~ /^cc_6_(\w+)$/ ) {
                $cc      = $1;
                $country = uc $cc;
                if ( $config{CC_DENY}         =~ /$cc/i ) { $option = "CC_DENY" }
                if ( $config{CC_ALLOW}        =~ /$cc/i ) { $option = "CC_ALLOW" }
                if ( $config{CC_ALLOW_FILTER} =~ /$cc/i ) { $option = "CC_ALLOW_FILTER" }
                if ( $config{CC_ALLOW_PORTS}  =~ /$cc/i ) { $option = "CC_ALLOW_PORTS" }
                if ( $config{CC_DENY_PORTS}   =~ /$cc/i ) { $option = "CC_DENY_PORTS" }
            }

            if ( $chain =~ /^bl_(\w+)$/ ) {
                $cc     = $1;
                $option = "$cc file:/etc/csf/csf.blocklists";
            }
            if ( $chain =~ /^bl_6_(\w+)$/ ) {
                $cc     = $1;
                $option = "$cc file:/etc/csf/csf.blocklists";
            }

            if ( $chain =~ /^chain_(\w+)$/ ) {
                $cc = $1;
                if ( $cc eq "DENY" )     { $option = " File:/etc/csf/csf.deny" }
                if ( $cc eq "ALLOW" )    { $option = " File:/etc/csf/csf.allow" }
                if ( $cc eq "GDENY" )    { $option = "GLOBAL_DENY" }
                if ( $cc eq "GALLOW" )   { $option = "GLOBAL_ALLOW" }
                if ( $cc eq "ALLOWDYN" ) { $option = "DYNDNS" }
                if ( $cc eq "GDYN" )     { $option = "GLOBAL_DYNDNS" }
            }
            if ( $chain =~ /^chain_6_(\w+)$/ ) {
                $cc = $1;
                if ( $cc eq "DENY" )     { $option = " File:/etc/csf/csf.deny" }
                if ( $cc eq "ALLOW" )    { $option = " File:/etc/csf/csf.allow" }
                if ( $cc eq "GDENY" )    { $option = "GLOBAL_DENY" }
                if ( $cc eq "GALLOW" )   { $option = "GLOBAL_ALLOW" }
                if ( $cc eq "ALLOWDYN" ) { $option = "DYNDNS" }
                if ( $cc eq "GDYN" )     { $option = "GLOBAL_DYNDNS" }
            }

            my $hit = 0;
            my ( $childin, $childout );
            my $pid    = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "test", "$chain", "$ipmatch" );
            my @output = <$childout>;
            waitpid( $pid, 0 );
            chomp @output;
            my $line = $output[0];
            if ( $line =~ /is in set/ ) { $hit = 1 }

            if ($hit) {
                $rest = $line;
                if ( $oldchain ne $chain ) { print "\n" }
                print "IPSET: Set:$chain Match:$ipmatch";
                if ($option) {
                    print " Setting:$option";
                    if ($country) { print " Country:$country" }
                }
                print "\n";
                $oldchain = $chain;
                $mhit     = 1;
            }
        }
        unless ($mhit) {
            print "IPSET: No matches found for $ipmatch\n";
        }
    }

    if ( $config{IPV6} ) {
        my $mhit = 0;
        my $head = 0;
        $table = "filter";
        my $oldchain = "INPUT";
        print "\n\nip6tables:\n";
        my $command = "echo 'filter table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers";
        if ( $config{NAT6} )    { $command .= " ; echo 'nat table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers" }
        if ( $config{MANGLE6} ) { $command .= " ; echo 'mangle table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers" }
        if ( $config{RAW6} )    { $command .= " ; echo 'raw table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers" }
        my ( $childin, $childout );
        my $pid    = IPC::Open3::open3( $childin, $childout, $childout, $command );
        my @output = <$childout>;
        waitpid( $pid, 0 );
        chomp @output;
        if ( $output[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @output }

        foreach my $line (@output) {
            if ( $line =~ /^Chain\s([\w\_]*)\s/ )          { $chain = $1 }
            if ( $line =~ /^(\S+) table:$/ )               { $table = $1 }
            if ( defined $chain and $chain eq "acctboth" ) { next }
            if ( !$head and ( $line =~ /^num/ ) )          { print "\nTable  Chain            $line\n"; $head = 1 }

            if ( $line !~ /\d+/ ) { next }
            my ( undef, undef, undef, $action, undef, undef, undef, $source, $destination, $options ) = split( /\s+/, $line, 11 );

            my $hit = 0;
            if ( $line =~ /\b$ipstring\b/i ) {
                $hit = 1;
            }
            else {
                if ( defined $source and ( $source =~ /\// ) and ( $source ne "::/0" ) ) {
                    if ( checkip( \$source ) ) {
                        my $cidr = Net::CIDR::Lite->new;
                        eval { local $SIG{__DIE__} = undef; $cidr->add($source) };
                        if ( $cidr->find($ipmatch) ) { $hit = 1 }
                    }
                }
                if ( !$hit and defined $destination and ( $destination =~ /\// ) and ( $destination ne "::/0" ) ) {
                    if ( checkip( \$destination ) ) {
                        my $cidr = Net::CIDR::Lite->new;
                        eval { local $SIG{__DIE__} = undef; $cidr->add($destination) };
                        if ( $cidr->find($ipmatch) ) { $hit = 1 }
                    }
                }
            }
            if ($hit) {
                $rest = $line;
                if ( $oldchain ne $chain ) { print "\n" }
                write;
                $oldchain = $chain;
                $mhit     = 1;
            }
        }
        unless ($mhit) {
            print "No matches found for $ipmatch in ip6tables\n";
        }
    }

    my @tempallow = slurpee( "/var/lib/csf/csf.tempallow", 'fatal' => 1 );
    chomp @tempallow;
    foreach my $line (@tempallow) {
        next unless $line =~ /\S/;    # Skip blank lines
        my ( $time, $ipd, $port, $inout, $timeout, $message ) = split( /\|/, $line );
        checkip( \$ipd );
        if ( $ipd eq $ipmatch ) {
            print "\nTemporary Allows: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n";
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ipmatch) ) {
                    print "\nTemporary Allows: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n";
                }
            }
        }
    }
    my @allow = slurp("/etc/csf/csf.allow");
    foreach my $line (@allow) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @allow, @incfile;
        }
    }
    foreach my $line (@allow) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ipmatch ) {
            print "\ncsf.allow: $line\n";
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ipmatch) ) {
                    print "\nPermanent Allows (csf.allow): $line\n";
                }
            }
        }
    }
    my @tempdeny = slurpee( "/var/lib/csf/csf.tempban", 'fatal' => 1 );
    chomp @tempdeny;
    foreach my $line (@tempdeny) {
        next unless $line =~ /\S/;    # Skip blank lines
        my ( $time, $ipd, $port, $inout, $timeout, $message ) = split( /\|/, $line );
        checkip( \$ipd );
        if ( $ipd eq $ipmatch ) {
            print "\nTemporary Blocks: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n";
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ipmatch) ) {
                    print "\nTemporary Blocks: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n";
                }
            }
        }
    }
    my @deny = slurp("/etc/csf/csf.deny");
    foreach my $line (@deny) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @deny, @incfile;
        }
    }
    foreach my $line (@deny) {
        $line =~ s/$cleanreg//g;
        if ( $line eq "" )               { next }
        if ( $line =~ /^\s*\#|Include/ ) { next }
        my ( $ipd, $commentd ) = split( /\s/, $line, 2 );
        $ipd //= '';
        checkip( \$ipd );
        if ( $ipd eq $ipmatch ) {
            print "\ncsf.deny: $line\n";
        }
        elsif ( $ipd =~ /(.*\/\d+)/ ) {
            my $cidrhit = $1;
            if ( checkip( \$cidrhit ) ) {
                my $cidr = Net::CIDR::Lite->new;
                eval { local $SIG{__DIE__} = undef; $cidr->add($cidrhit) };
                if ( $cidr->find($ipmatch) ) {
                    print "\nPermanent Blocks (csf.deny): $line\n";
                }
            }
        }
    }
    return;
}

sub dotempban {
    my ( $ip, $deny, $ports, $inout, $time, $timeout, $message );
    format TEMPBAN =
@<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @|||||| @<<<< @<<<<<<<<<<<<<<< @*
$deny, $ip,                                   $ports,  $inout,$time,$message
.
    local $~ = "TEMPBAN";
    if ( ( !-z "/var/lib/csf/csf.tempban" ) or ( !-z "/var/lib/csf/csf.tempallow" ) ) {
        print "\nA/D   IP address                               Port   Dir   Time To Live     Comment\n";
        if ( !-z "/var/lib/csf/csf.tempban" ) {
            sysopen( my $IN, "/var/lib/csf/csf.tempban", O_RDWR );
            flock( $IN, LOCK_SH );
            my @data = <$IN>;
            chomp @data;
            close($IN);

            foreach my $line (@data) {
                if ( $line eq "" ) { next }
                ( $time, $ip, $ports, $inout, $timeout, $message ) = split( /\|/, $line );
                $time = $timeout - ( time - $time );
                if ( $ports eq "" ) { $ports = "*" }
                if ( $inout eq "" ) { $inout = " *" }
                if ( $time < 1 ) {
                    $time = "<1";
                }
                else {
                    my $days  = int( $time / ( 24 * 60 * 60 ) );
                    my $hours = ( $time / ( 60 * 60 ) ) % 24;
                    my $mins  = ( $time / 60 ) % 60;
                    my $secs  = $time % 60;
                    $days  = $days < 1  ? '' : $days . 'd ';
                    $hours = $hours < 1 ? '' : $hours . 'h ';
                    $mins  = $mins < 1  ? '' : $mins . 'm ';
                    $time  = $days . $hours . $mins . $secs . 's';
                }
                $deny = "DENY";
                foreach ( split( /,/, $ports ) ) { write }
            }
        }
        if ( !-z "/var/lib/csf/csf.tempallow" ) {
            sysopen( my $IN, "/var/lib/csf/csf.tempallow", O_RDWR );
            flock( $IN, LOCK_SH );
            my @data = <$IN>;
            chomp @data;
            close($IN);

            foreach my $line (@data) {
                if ( $line eq "" ) { next }
                ( $time, $ip, $ports, $inout, $timeout, $message ) = split( /\|/, $line );
                $time = $timeout - ( time - $time );
                if ( $ports eq "" ) { $ports = "*" }
                if ( $inout eq "" ) { $inout = " *" }
                if ( $time < 1 ) {
                    $time = "<1";
                }
                else {
                    my $days  = int( $time / ( 24 * 60 * 60 ) );
                    my $hours = ( $time / ( 60 * 60 ) ) % 24;
                    my $mins  = ( $time / 60 ) % 60;
                    my $secs  = $time % 60;
                    $days  = $days < 1  ? '' : $days . 'd ';
                    $hours = $hours < 1 ? '' : $hours . 'h ';
                    $mins  = $mins < 1  ? '' : $mins . 'm ';
                    $time  = $days . $hours . $mins . $secs . 's';
                }
                $deny = "ALLOW";
                foreach ( split( /,/, $ports ) ) { write }
            }
        }
    }
    else {
        print "csf: There are no temporary IP entries\n";
    }
    return;
}

sub dotempdeny {
    my $cftemp = shift;
    my ( $ip, $timeout, $portdir ) = @{ $input{argument} }[ 0 .. 2 ];
    my $inout = "in";
    my $port  = "";
    if ( $timeout =~ /^(\d*)([mhd])/i ) {
        my $secs = $1;
        my $dur  = lc $2;
        if    ( $dur eq "m" ) { $timeout = $secs * 60 }
        elsif ( $dur eq "h" ) { $timeout = $secs * 60 * 60 }
        elsif ( $dur eq "d" ) { $timeout = $secs * 60 * 60 * 24 }
        else                  { $timeout = $secs }
    }

    my $iptype = checkip( \$ip );
    if ( !$iptype ) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }

    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    getethdev();

    if ( $ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip) ) {
        print "deny failed: [$ip] is one of this servers addresses!\n";
        return;
    }

    if ( $timeout =~ /\D/ ) {
        $portdir = join( " ", $timeout, $portdir );
        $timeout = 0;
    }

    if ( $portdir =~ /\-d\s*out/i )          { $inout = "out" }
    if ( $portdir =~ /\-d\s*inout/i )        { $inout = "inout" }
    if ( $portdir =~ /\-p\s*([\w\,\*\;]+)/ ) { $port  = $1 }
    my $comment = $portdir;
    $comment =~ s/\-d\s*out//ig;
    $comment =~ s/\-d\s*inout//ig;
    $comment =~ s/\-d\s*in//ig;
    $comment =~ s/\-p\s*[\w\,\*\;]+//ig;
    $comment =~ s/^\s*|\s*$//g;
    if ( $comment eq "" ) { $comment = "Manually added: " . iplookup($ip) }

    my @deny = slurp("/etc/csf/csf.deny");
    foreach my $line (@deny) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @deny, @incfile;
        }
    }
    my $ipstring = quotemeta($ip);
    if ( grep { $_ =~ /^$ipstring\b/ } @deny ) {
        print "csf: $ip is already permanently blocked\n";
        exit 0;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command early termination
    }
    @deny = slurpee( "/var/lib/csf/csf.tempban", 'fatal' => 1 );
    chomp @deny;
    if ( grep { $_ =~ /\b$ip\|$port\|\b/ } @deny ) {
        print "csf: $ip is already temporarily blocked\n";
        exit 0;
    }

    my $dropin  = $config{DROP};
    my $dropout = $config{DROP_OUT};
    if ( $config{DROP_IP_LOGGING} )         { $dropin  = "LOGDROPIN" }
    if ( $config{DROP_OUT_LOGGING} )        { $dropout = "LOGDROPOUT" }
    if ( !length $timeout || $timeout < 2 ) { $timeout = 3600 }
    if ( $port =~ /\*/ )                    { $port    = "" }

    if ( $inout =~ /in/ ) {
        if ($port) {
            foreach my $dport ( split( /\,/, $port ) ) {
                my ( $tport, $proto ) = split( /\;/, $dport );
                $dport = $tport;
                if ( !length $proto ) { $proto = "tcp" }
                if ( $iptype == 6 ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin" );
                    if ( $messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A", $dport ) }
                }
                else {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin" );
                    if ( $messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A", $dport ) }
                }
            }
        }
        else {
            if ( $iptype == 6 ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -s $ip -j $dropin" );
                if ( $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A" ) }
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -s $ip -j $dropin" );
                if ( $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "A" ) }
            }
        }
    }
    if ( $inout =~ /out/ ) {
        if ($port) {
            foreach my $dport ( split( /\,/, $port ) ) {
                my ( $tport, $proto ) = split( /\;/, $dport );
                $dport = $tport;
                if ( !length $proto ) { $proto = "tcp" }
                if ( $iptype == 6 ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout" );
                }
                else {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout" );
                }
            }
        }
        else {
            if ( $iptype == 6 ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -d $ip -j $dropout" );
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -d $ip -j $dropout" );
            }
        }
    }

    if ( $config{CF_ENABLE} and $cftemp ) { $comment .= " (CF_ENABLE)" }

    sysopen( my $OUT, "/var/lib/csf/csf.tempban", O_WRONLY | O_APPEND | O_CREAT ) or error( __LINE__, "Error: Can't append out file: $!" );
    flock( $OUT, LOCK_EX );
    print $OUT time . "|$ip|$port|$inout|$timeout|$comment\n";
    close($OUT);

    if ( $port eq "" )       { $port  = "*" }
    if ( $inout eq "in" )    { $inout = "inbound" }
    if ( $inout eq "out" )   { $inout = "outbound" }
    if ( $inout eq "inout" ) { $inout = "in and outbound" }
    print "csf: $ip blocked on port $port for $timeout seconds $inout\n";
    return;
}

sub dotempallow {
    my $cftemp = shift;
    my ( $ip, $timeout, $portdir ) = @{ $input{argument} }[ 0 .. 2 ];
    my $inout = "inout";
    my $port  = "";
    if ( $timeout =~ /^(\d*)([mhd])/i ) {
        my $secs = $1;
        my $dur  = lc $2;
        if    ( $dur eq "m" ) { $timeout = $secs * 60 }
        elsif ( $dur eq "h" ) { $timeout = $secs * 60 * 60 }
        elsif ( $dur eq "d" ) { $timeout = $secs * 60 * 60 * 24 }
        else                  { $timeout = $secs }
    }

    my $iptype = checkip( \$ip );
    if ( !$iptype ) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }

    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    if ( $timeout =~ /\D/ ) {
        $portdir = join( " ", $timeout, $portdir );
        $timeout = 0;
    }

    if ( $portdir =~ /\-d\s*in/i )           { $inout = "in" }
    if ( $portdir =~ /\-d\s*out/i )          { $inout = "out" }
    if ( $portdir =~ /\-d\s*inout/i )        { $inout = "inout" }
    if ( $portdir =~ /\-p\s*([\w\,\*\;]+)/ ) { $port  = $1 }
    my $comment = $portdir;
    $comment =~ s/\-d\s*out//ig;
    $comment =~ s/\-d\s*inout//ig;
    $comment =~ s/\-d\s*in//ig;
    $comment =~ s/\-p\s*[\w\,\*\;]+//ig;
    $comment =~ s/^\s*|\s*$//g;
    if ( $comment eq "" ) { $comment = "Manually added: " . iplookup($ip) }

    my @allow = slurp("/etc/csf/csf.allow");
    foreach my $line (@allow) {
        if ( $line =~ /^Include\s*(.*)$/ ) {
            my @incfile = slurp($1);
            push @allow, @incfile;
        }
    }
    if ( grep { $_ =~ /^$ip\b/ } @allow ) {
        print "csf: $ip is already permanently allowed\n";
        exit 0;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command early termination
    }
    @allow = slurpee( "/var/lib/csf/csf.tempallow", 'fatal' => 1 );
    chomp @allow;
    if ( grep { $_ =~ /\b$ip\|$port\|\b/ } @allow ) {
        print "csf: $ip is already temporarily allowed\n";
        exit 0;
    }

    if ( !length $timeout || $timeout < 2 ) { $timeout = 3600 }
    if ( $port =~ /\*/ )                    { $port    = "" }

    getethdev();

    if ( $inout =~ /in/ ) {
        if ($port) {
            foreach my $dport ( split( /\,/, $port ) ) {
                my ( $tport, $proto ) = split( /\;/, $dport );
                $dport = $tport;
                if ( !length $proto ) { $proto = "tcp" }
                if ( $iptype == 6 ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept" );
                }
                else {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept" );
                }
            }
        }
        else {
            if ( $iptype == 6 ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -s $ip -j $accept" );
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -s $ip -j $accept" );
            }
        }
    }
    if ( $inout =~ /out/ ) {
        if ($port) {
            foreach my $dport ( split( /\,/, $port ) ) {
                my ( $tport, $proto ) = split( /\;/, $dport );
                $dport = $tport;
                if ( !length $proto ) { $proto = "tcp" }
                if ( $iptype == 6 ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept" );
                }
                else {
                    syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept" );
                }
            }
        }
        else {
            if ( $iptype == 6 ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -d $ip -j $accept" );
            }
            else {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -d $ip -j $accept" );
            }
        }
    }

    if ( $config{CF_ENABLE} and $cftemp ) { $comment .= " (CF_ENABLE)" }

    sysopen( my $OUT, "/var/lib/csf/csf.tempallow", O_WRONLY | O_APPEND | O_CREAT ) or error( __LINE__, "Error: Can't append out file: $!" );
    flock( $OUT, LOCK_EX );
    print $OUT time . "|$ip|$port|$inout|$timeout|$comment\n";
    close($OUT);

    if ( $port eq "" )       { $port  = "*" }
    if ( $inout eq "in" )    { $inout = "inbound" }
    if ( $inout eq "out" )   { $inout = "outbound" }
    if ( $inout eq "inout" ) { $inout = "in and outbound" }
    print "csf: $ip allowed on port $port for $timeout seconds $inout\n";
    return;
}

sub dotemprm {
    my $ip = $input{argument}[0];

    if ( $ip eq "" ) {
        print "csf: No IP specified\n";
        return;
    }

    my $iptype = checkip( \$ip );
    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    unless ($iptype) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }
    getethdev();
    if ( !-z "/var/lib/csf/csf.tempban" ) {
        my $unblock = 0;
        sysopen( my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT );
        flock( $TEMPBAN, LOCK_EX );
        my @data = <$TEMPBAN>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $thisip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            if ( $thisip eq $ip ) {
                my $dropin  = $config{DROP};
                my $dropout = $config{DROP_OUT};
                if ( $config{DROP_IP_LOGGING} )  { $dropin  = "LOGDROPIN" }
                if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }

                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin" );
                            if ( $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin" );
                            if ( $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout" );
                        }
                    }
                }
                if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, $config{CF_BLOCK} ) }
                print "csf: $ip temporary block removed\n";
                $unblock = 1;
            }
            else {
                push @newdata, $line;
            }
        }
        seek( $TEMPBAN, 0, 0 );
        truncate( $TEMPBAN, 0 );
        foreach my $line (@newdata) { print $TEMPBAN "$line\n" }
        close($TEMPBAN);
        unless ($unblock) {
            print "csf: $ip not found in temporary bans\n";
        }
    }
    else {
        print "csf: There are no temporary IP bans\n";
    }
    if ( !-z "/var/lib/csf/csf.tempallow" ) {
        my $unblock = 0;
        sysopen( my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT );
        flock( $TEMPALLOW, LOCK_EX );
        my @data = <$TEMPALLOW>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $thisip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            if ( $thisip eq $ip ) {
                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept" );
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept" );
                        }
                    }
                }
                if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, "whitelist" ) }
                print "csf: $ip temporary allow removed\n";
                $unblock = 1;
            }
            else {
                push @newdata, $line;
            }
        }
        seek( $TEMPALLOW, 0, 0 );
        truncate( $TEMPALLOW, 0 );
        foreach my $line (@newdata) { print $TEMPALLOW "$line\n" }
        close($TEMPALLOW);
        unless ($unblock) {
            print "csf: $ip not found in temporary allows\n";
        }
    }
    else {
        print "csf: There are no temporary IP allows\n";
    }
    return;
}

sub dotemprmd {
    my $ip = $input{argument}[0];

    if ( $ip eq "" ) {
        print "csf: No IP specified\n";
        return;
    }

    my $iptype = checkip( \$ip );
    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    unless ($iptype) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }
    getethdev();
    if ( !-z "/var/lib/csf/csf.tempban" ) {
        my $unblock = 0;
        sysopen( my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT );
        flock( $TEMPBAN, LOCK_EX );
        my @data = <$TEMPBAN>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $thisip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            if ( $thisip eq $ip ) {
                my $dropin  = $config{DROP};
                my $dropout = $config{DROP_OUT};
                if ( $config{DROP_IP_LOGGING} )  { $dropin  = "LOGDROPIN" }
                if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }

                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin" );
                                if ( $messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin" );
                            if ( $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin" );
                            if ( $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout" );
                        }
                    }
                }
                if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, $config{CF_BLOCK} ) }
                print "csf: $ip temporary block removed\n";
                $unblock = 1;
            }
            else {
                push @newdata, $line;
            }
        }
        seek( $TEMPBAN, 0, 0 );
        truncate( $TEMPBAN, 0 );
        foreach my $line (@newdata) { print $TEMPBAN "$line\n" }
        close($TEMPBAN);
        unless ($unblock) {
            print "csf: $ip not found in temporary bans\n";
        }
    }
    else {
        print "csf: There are no temporary IP bans\n";
    }

    return;
}

sub dotemprma {
    my $ip = $input{argument}[0];

    if ( $ip eq "" ) {
        print "csf: No IP specified\n";
        return;
    }

    my $iptype = checkip( \$ip );
    if ( $iptype == 6 and !$config{IPV6} ) {
        print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n";
    }

    unless ($iptype) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }
    getethdev();
    if ( !-z "/var/lib/csf/csf.tempallow" ) {
        my $unblock = 0;
        sysopen( my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT );
        flock( $TEMPALLOW, LOCK_EX );
        my @data = <$TEMPALLOW>;
        chomp @data;

        my @newdata;
        foreach my $line (@data) {
            my ( $time, $thisip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            if ( $thisip eq $ip ) {
                if ( $inout =~ /in/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept" );
                        }
                    }
                }
                if ( $inout =~ /out/ ) {
                    if ($port) {
                        foreach my $dport ( split( /\,/, $port ) ) {
                            my ( $tport, $proto ) = split( /\;/, $dport );
                            $dport = $tport;
                            if ( !length $proto ) { $proto = "tcp" }
                            if ( $iptype == 6 ) {
                                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                            else {
                                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept" );
                            }
                        }
                    }
                    else {
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept" );
                        }
                    }
                }
                if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, "whitelist" ) }
                print "csf: $ip temporary allow removed\n";
                $unblock = 1;
            }
            else {
                push @newdata, $line;
            }
        }
        seek( $TEMPALLOW, 0, 0 );
        truncate( $TEMPALLOW, 0 );
        foreach my $line (@newdata) { print $TEMPALLOW "$line\n" }
        close($TEMPALLOW);
        unless ($unblock) {
            print "csf: $ip not found in temporary allows\n";
        }
    }
    else {
        print "csf: There are no temporary IP allows\n";
    }
    return;
}

sub dotempf {
    getethdev();
    if ( !-z "/var/lib/csf/csf.tempban" ) {
        sysopen( my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT );
        flock( $TEMPBAN, LOCK_EX );
        my @data = <$TEMPBAN>;
        chomp @data;

        foreach my $line (@data) {
            if ( $line eq "" ) { next }
            my ( $time, $ip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            my $iptype = checkip( \$ip );
            if ( $iptype == 6 and !$config{IPV6} ) { next }
            my $dropin  = $config{DROP};
            my $dropout = $config{DROP_OUT};
            if ( $config{DROP_IP_LOGGING} )  { $dropin  = "LOGDROPIN" }
            if ( $config{DROP_OUT_LOGGING} ) { $dropout = "LOGDROPOUT" }

            if ( $inout =~ /in/ ) {
                if ($port) {
                    foreach my $dport ( split( /\,/, $port ) ) {
                        my ( $tport, $proto ) = split( /\;/, $dport );
                        $dport = $tport;
                        if ( !length $proto ) { $proto = "tcp" }
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin" );
                            if ( $messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin" );
                            if ( $messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D", $dport ) }
                        }
                    }
                }
                else {
                    if ( $iptype == 6 ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin" );
                        if ( $config{MESSENGER6} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                    }
                    else {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin" );
                        if ( $config{MESSENGER} and $config{MESSENGER_TEMP} ) { domessenger( $ip, "D" ) }
                    }
                }
            }
            if ( $inout =~ /out/ ) {
                if ($port) {
                    foreach my $dport ( split( /\,/, $port ) ) {
                        my ( $tport, $proto ) = split( /\;/, $dport );
                        $dport = $tport;
                        if ( !length $proto ) { $proto = "tcp" }
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout" );
                        }
                    }
                }
                else {
                    if ( $iptype == 6 ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout" );
                    }
                    else {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout" );
                    }
                }
            }
            if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, $config{CF_BLOCK} ) }
            print "csf: $ip temporary block removed\n";
        }
        seek( $TEMPBAN, 0, 0 );
        truncate( $TEMPBAN, 0 );
        close($TEMPBAN);
    }
    else {
        print "csf: There are no temporary IP bans\n";
    }
    if ( !-z "/var/lib/csf/csf.tempallow" ) {
        sysopen( my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT );
        flock( $TEMPALLOW, LOCK_EX );
        my @data = <$TEMPALLOW>;
        chomp @data;

        foreach my $line (@data) {
            if ( $line eq "" ) { next }
            my ( $time, $ip, $port, $inout, $timeout, $message ) = split( /\|/, $line );
            my $iptype = checkip( \$ip );
            if ( $iptype == 6 and !$config{IPV6} ) { next }
            if ( $inout =~ /in/ ) {
                if ($port) {
                    foreach my $dport ( split( /\,/, $port ) ) {
                        my ( $tport, $proto ) = split( /\;/, $dport );
                        $dport = $tport;
                        if ( !length $proto ) { $proto = "tcp" }
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept" );
                        }
                    }
                }
                else {
                    if ( $iptype == 6 ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept" );
                    }
                    else {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept" );
                    }
                }
            }
            if ( $inout =~ /out/ ) {
                if ($port) {
                    foreach my $dport ( split( /\,/, $port ) ) {
                        my ( $tport, $proto ) = split( /\;/, $dport );
                        $dport = $tport;
                        if ( !length $proto ) { $proto = "tcp" }
                        if ( $iptype == 6 ) {
                            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept" );
                        }
                        else {
                            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept" );
                        }
                    }
                }
                else {
                    if ( $iptype == 6 ) {
                        syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept" );
                    }
                    else {
                        syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept" );
                    }
                }
            }
            if ( $config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/ ) { ConfigServer::CloudFlare::action( "remove", $ip, "whitelist" ) }
            print "csf: $ip temporary allow removed\n";
        }
        seek( $TEMPALLOW, 0, 0 );
        truncate( $TEMPALLOW, 0 );
        close($TEMPALLOW);
    }
    else {
        print "csf: There are no temporary IP allows\n";
    }
    return;
}

sub dowatch {
    print "csf: --watch, -w is no longer supported. Use --trace instead\n";
    return;
}

sub dotrace {
    my $cmd = $ARGV[1];
    my $ip  = $ARGV[2];

    if ( $ip eq "" ) {
        print "csf: No IP specified\n";
        return;
    }

    my $checkip = checkip( \$ip );
    unless ($checkip) {
        print "csf: [$ip] is not a valid PUBLIC IP\n";
        return;
    }

    if ( $cmd eq "add" ) {
        if ( $checkip == 4 ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -I PREROUTING -p tcp --syn --source $ip -j TRACE" );
        }
        else {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -I PREROUTING -p tcp --syn --source $ip -j TRACE" );
        }
        print "csf: Added trace for $ip\n";
    }
    elsif ( $cmd eq "remove" ) {
        if ( $checkip == 4 ) {
            syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -D PREROUTING -p tcp --syn --source $ip -j TRACE" );
        }
        else {
            syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -D PREROUTING -p tcp --syn --source $ip -j TRACE" );
        }
        print "csf: Removed trace for $ip\n";
    }
    else {
        print "csf: Error, use [add|remove] [ip]\n";
    }

    return;
}

sub dologrun {
    if ( $config{LOGSCANNER} ) {
        open( my $OUT, ">", "/var/lib/csf/csf.logrun" ) or error( __LINE__, "Could not create /var/lib/csf/csf.logrun: $!" );
        flock( $OUT, LOCK_EX );
        close($OUT);
    }
    else {
        print "Option LOGSCANNER needs to be enabled in csf.conf for this feature\n";
    }
    return;
}

sub domessenger {
    my $ip     = shift;
    my $delete = shift;
    my $ports  = shift;
    if ( $ports eq "" ) { $ports = "$config{MESSENGER_HTTPS_IN},$config{MESSENGER_HTML_IN},$config{MESSENGER_TEXT_IN}" }
    my $iptype = checkip( \$ip );

    if ( $config{CC_MESSENGER_ALLOW} or $config{CC_MESSENGER_DENY} ) {
        my ( $cc, $asn ) = iplookup( $ip, 1 );
        ( $asn, undef ) = split( /\s+/, $asn );

        if ( $config{CC_MESSENGER_ALLOW} ) {
            my $allow = 0;
            if     ( $cc ne "" and $config{CC_MESSENGER_ALLOW} =~ /$cc/i )   { $allow = 1 }
            if     ( $asn ne "" and $config{CC_MESSENGER_ALLOW} =~ /$asn/i ) { $allow = 1 }
            unless ($allow)                                                  { return 1 }
        }

        if ( $config{CC_MESSENGER_DENY} ) {
            if ( $cc ne ""  and $config{CC_MESSENGER_DENY} =~ /$cc/i )  { return 1 }
            if ( $asn ne "" and $config{CC_MESSENGER_DENY} =~ /$asn/i ) { return 1 }
        }
    }

    my $del = "-A";
    if ( $delete eq "D" ) { $del = "-D" }

    my %textin;
    my %htmlin;
    my %httpsin;
    foreach my $port ( split( /\,/, $config{MESSENGER_HTTPS_IN} ) ) { $httpsin{$port} = 1 }
    foreach my $port ( split( /\,/, $config{MESSENGER_HTML_IN} ) )  { $htmlin{$port}  = 1 }
    foreach my $port ( split( /\,/, $config{MESSENGER_TEXT_IN} ) )  { $textin{$port}  = 1 }

    my $textports;
    my $htmlports;
    my $httpsports;
    foreach my $port ( split( /\,/, $ports ) ) {
        if ( $httpsin{$port} ) {
            if ( $httpsports eq "" ) { $httpsports = "$port" }
            else                     { $httpsports .= ",$port" }
        }
        if ( $htmlin{$port} ) {
            if ( $htmlports eq "" ) { $htmlports = "$port" }
            else                    { $htmlports .= ",$port" }
        }
        if ( $textin{$port} ) {
            if ( $textports eq "" ) { $textports = "$port" }
            else                    { $textports .= ",$port" }
        }
    }

    if ( $config{LF_IPSET} ) {
        if ( $ip =~ /^-m set/ ) {
            my $ip6 = $ip;
            $ip6 =~ s/MESSENGER src/MESSENGER_6 src/g;
            if ( $httpsports ne "" ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}" );
                if ( $config{MESSENGER6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}" );
                }
            }
            if ( $htmlports ne "" ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}" );
                if ( $config{MESSENGER6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}" );
                }
            }
            if ( $textports ne "" ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}" );
                if ( $config{MESSENGER6} ) {
                    syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}" );
                }
            }
        }
        else {
            if ( $delete eq "D" ) {
                if ( $iptype == 4 ) {
                    ipsetdel( "MESSENGER", $ip );
                }
                if ( $iptype == 6 and $config{MESSENGER6} ) {
                    ipsetdel( "MESSENGER_6", $ip );
                }
            }
            else {
                if ( $iptype == 4 ) {
                    ipsetadd( "MESSENGER", $ip );
                }
                if ( $iptype == 6 and $config{MESSENGER6} ) {
                    ipsetadd( "MESSENGER_6", $ip );
                }
            }
        }
    }
    else {
        if ( $httpsports ne "" ) {
            if ( $iptype == 4 ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}" );
            }
            if ( $iptype == 6 and $config{MESSENGER6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}" );
            }
        }
        if ( $htmlports ne "" ) {
            if ( $iptype == 4 ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}" );
            }
            if ( $iptype == 6 and $config{MESSENGER6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}" );
            }
        }
        if ( $textports ne "" ) {
            if ( $iptype == 4 ) {
                syscommand( __LINE__, "$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}" );
            }
            if ( $iptype == 6 and $config{MESSENGER6} ) {
                syscommand( __LINE__, "$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}" );
            }
        }
    }
    return;
}

sub domail {
    my $output = ConfigServer::ServerCheck::report();

    if ( $input{argument}[0] ) {
        my $message = "From: root\n";
        $message .= "To: root\n";
        $message .= "Subject: Server Check on [hostname]\n";
        $message .= "MIME-Version: 1.0\n";
        $message .= "Content-Type: text/html\n";
        $message .= "\n";
        $message .= $output;
        my @message = split( /\n/, $message );
        ConfigServer::Sendmail::relay( $input{argument}[0], "", @message );
    }
    else {
        print $output;
        print "\n";
    }
    return;
}

sub dorbls {
    my ( $failures, $output ) = ConfigServer::RBLCheck::report( 1, "", 0 );
    my $failure_s = "failure";
    if ( $failures ne 1 )  { $failure_s .= "s" }
    if ( $failures eq "" ) { $failures = 0 }
    if ( $input{argument}[0] ) {
        my $message = "From: root\n";
        $message .= "To: root\n";
        $message .= "Subject: RBL Check on [hostname]: [$failures] $failure_s\n";
        $message .= "MIME-Version: 1.0\n";
        $message .= "Content-Type: text/html\n";
        $message .= "\n";
        $message .= $output;
        my @message = split( /\n/, $message );
        ConfigServer::Sendmail::relay( $input{argument}[0], "", @message );
    }
    else {
        print $output;
        print "\n";
    }
    return;
}

sub doprofile {
    my $cmd      = $ARGV[1];
    my $profile1 = $ARGV[2];
    my $profile2 = $ARGV[3];
    my $stamp    = time;

    $profile1 =~ s/\W/_/g;
    $profile2 =~ s/\W/_/g;

    if ( $cmd eq "list" ) {
        my @profiles = sort glob("/usr/local/csf/profiles/*");
        my @backups  = reverse glob("/var/lib/csf/backup/*");
        print "\n";
        print "Configuration Profiles\n";
        print "======================\n";
        foreach my $profile (@profiles) {
            my ( $file, undef ) = File::Basename::fileparse($profile);
            $file =~ s/\.conf$//;
            print "$file\n";
        }
        print "\n";

        print "Configuration Backups\n";
        print "=====================\n";
        foreach my $backup (@backups) {
            my ( $file,  undef ) = File::Basename::fileparse($backup);
            my ( $stamp, undef ) = split( /_/, $file );
            print $file. " (" . localtime($stamp) . ")\n";
        }
        print "\n";
    }
    elsif ( $cmd eq "backup" ) {
        unless ($profile1) { $profile1 = "backup" }
        print "Creating backup...\n";
        system( "/bin/cp", "-avf", "/etc/csf/csf.conf", "/var/lib/csf/backup/${stamp}_${profile1}" );
    }
    elsif ( $cmd eq "restore" ) {
        if ( -e "/var/lib/csf/backup/$profile1" ) {
            print "Restoring backup...\n";
            system( "/bin/cp", "-avf", "/var/lib/csf/backup/${profile1}", "/etc/csf/csf.conf" );
            print "You should now restart csf and then lfd\n";
        }
        else {
            print "File [$profile1] not found in /var/lib/csf/backup/\n";
        }
    }
    elsif ( $cmd eq "apply" ) {
        if ( -e "/usr/local/csf/profiles/${profile1}.conf" ) {
            my %apply;
            print "Creating backup...\n";
            system( "/bin/cp", "-avf", "/etc/csf/csf.conf", "/var/lib/csf/backup/${stamp}_pre_${profile1}" );
            print "Applying profile...\n";
            my @applyconfig = slurpee( "/usr/local/csf/profiles/${profile1}.conf", 'fatal' => 1 );
            chomp @applyconfig;

            foreach my $line (@applyconfig) {
                if ( $line =~ /^\#/ ) { next }
                if ( $line !~ /=/ )   { next }
                my ( $name, $value ) = split( /=/, $line, 2 );
                $name =~ s/\s//g;
                if ( $value =~ /\"(.*)\"/ ) { $value = $1 }
                $apply{$name} = $value;
            }

            sysopen( my $CONF, "/etc/csf/csf.conf", O_RDWR | O_CREAT ) or die "Unable to open file: $!";
            flock( $CONF, LOCK_SH );
            my @confdata = <$CONF>;
            close($CONF);
            chomp @confdata;

            sysopen( my $OUT, "/etc/csf/csf.conf", O_WRONLY | O_CREAT ) or die "Unable to open file: $!";
            flock( $OUT, LOCK_EX );
            seek( $OUT, 0, 0 );
            truncate( $OUT, 0 );
            for ( my $x = 0; $x < @confdata; $x++ ) {
                if ( ( $confdata[$x] !~ /^\#/ ) and ( $confdata[$x] =~ /=/ ) ) {
                    my ( $name, $value ) = split( /=/, $confdata[$x], 2 );
                    $name =~ s/\s//g;
                    if ( $value =~ /\"(.*)\"/ )                                  { $value = $1 }
                    if ( defined $apply{$name} and ( $apply{$name} ne $value ) ) { $value = $apply{$name} }
                    print $OUT "$name = \"$value\"\n";
                }
                else {
                    print $OUT "$confdata[$x]\n";
                }
            }
            close($OUT);

            print "[$profile1] has been applied. You should now restart csf and then lfd\n";
        }
        else {
            print "[$profile1] is not a valid profile\n";
        }
    }
    elsif ( $cmd eq "keep" ) {
        if ( $profile1 =~ /^\d+$/ ) {
            my @backups = reverse glob("/var/lib/csf/backup/*");
            for ( $profile1 .. ( @backups - 1 ) ) {
                system( "/bin/rm", "-fv", $backups[$_] );
            }
        }
        else {
            print "You must specify the number of backups to keep\n";
        }
    }
    elsif ( $cmd eq "diff" ) {
        my $firstfile  = "/var/lib/csf/backup/$profile1";
        my $secondfile = "/var/lib/csf/backup/$profile2";
        if ( -e "/usr/local/csf/profiles/${profile1}.conf" ) {
            $firstfile = "/usr/local/csf/profiles/${profile1}.conf";
        }
        if ( -e "/usr/local/csf/profiles/${profile2}.conf" ) {
            $secondfile = "/usr/local/csf/profiles/${profile2}.conf";
        }
        if ( -e $firstfile ) {
            if ( -e $secondfile or $profile2 eq "" or $profile2 eq "current" ) {
                my %config1;
                my @configdata = slurpee( $firstfile, 'fatal' => 1 );
                chomp @configdata;
                foreach my $line (@configdata) {
                    if ( $line =~ /^\#/ ) { next }
                    if ( $line !~ /=/ )   { next }
                    my ( $name, $value ) = split( /=/, $line, 2 );
                    $name =~ s/\s//g;
                    if ( $value =~ /\"(.*)\"/ ) { $value = $1 }
                    $config1{$name} = $value;
                }

                if ( $profile2 eq "" or $profile2 eq "current" ) {
                    $profile2   = "current";
                    @configdata = slurpee( "/etc/csf/csf.conf", 'fatal' => 1 );
                }
                else {
                    @configdata = slurpee( $secondfile, 'fatal' => 1 );
                }
                @configdata = sort @configdata;
                chomp @configdata;

                print "[SETTING]\t[$profile1]\t[$profile2]\n\n";
                foreach my $line (@configdata) {
                    if ( $line =~ /^\#/ ) { next }
                    if ( $line !~ /=/ )   { next }
                    my ( $name, $value ) = split( /=/, $line, 2 );
                    $name =~ s/\s//g;
                    if ( $value =~ /\"(.*)\"/ ) { $value = $1 }
                    if ( defined $config1{$name} and ( $config1{$name} ne $value ) ) {
                        print "[$name]\t[$config1{$name}]\t[$value]\n";
                    }
                }
            }
            else {
                print "File [$profile2] not found in /var/lib/csf/backup/\n";
            }
        }
        else {
            print "File [$profile1] not found in /var/lib/csf/backup/\n";
        }
    }
    else {
        print "Incorrect syntax for command\n";
    }
    return;
}

sub doports {
    my ( $fport, $fopen, $fconn, $fpid, $fexe, $fcmd );
    format PORTS =
@<<<<<<<<< @<<< @<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @*
$fport,    $fopen,$fconn,$fpid,            $fcmd,                                  $fexe
.
    local $~ = "PORTS";

    print "Ports listening for external connections and the executables running behind them:\n";
    print "Port/Proto Open Conn  PID/User             Command Line                            Executable\n";
    my %listen = ConfigServer::Ports->listening;
    my %ports  = ConfigServer::Ports->openports;
    foreach my $protocol ( sort keys %listen ) {
        foreach my $port ( sort { $a <=> $b } keys %{ $listen{$protocol} } ) {
            foreach my $pid ( sort { $a <=> $b } keys %{ $listen{$protocol}{$port} } ) {
                $fport = "$port/$protocol";
                if   ( $ports{$protocol}{$port} ) { $fopen = "4" }
                else                              { $fopen = "-" }
                if   ( $config{IPV6} and $ports{ $protocol . "6" }{$port} ) { $fopen .= "/6" }
                else                                                        { $fopen .= "/-" }
                $fpid  = "($pid/" . $listen{$protocol}{$port}{$pid}{user} . ")";
                $fexe  = $listen{$protocol}{$port}{$pid}{exe};
                $fcmd  = $listen{$protocol}{$port}{$pid}{cmd};
                $fconn = $listen{$protocol}{$port}{$pid}{conn};
                write;
            }
        }
    }
    return;
}

sub domessengerv2 {
    print "csf - MESSENGERV2 /etc/apache2/conf.d/csf_messenger.conf regeneration:\n\n";
    ConfigServer::Messenger::messengerv2();
    print "\n...Done.\n";
    return;
}

sub docloudflare {
    my $cmd       = $ARGV[1];
    my $setting   = $ARGV[2];
    my $value     = $ARGV[3];
    my $valuemore = $ARGV[4];
    my $valuelist;
    my $valuemorelist;
    foreach my $i ( 3 .. $#ARGV ) { $valuelist     .= $ARGV[$i] }
    foreach my $i ( 4 .. $#ARGV ) { $valuemorelist .= $ARGV[$i] }

    unless ( $config{CF_ENABLE} ) {
        print "csf - CF_ENABLE must be enabled and CloudFlare access details configured to use these commands\n";
        exit 1;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command precondition failure
    }

    if ( $cmd eq "list" ) {
        unless ( $setting eq "all" or $setting eq "block" or $setting eq "challenge" or $setting eq "whitelist" ) {
            print "Invalid list type, must be: [block], [challenge], [whitelist] or [all]\n";
            exit 1;
        }
        my ( $ip, $domain, $mode, $date, $comment );
        format CLOUDFLARE =
@<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< @*
$ip,             $domain,             $mode,     $date,                    $comment
.
        local $~ = "CLOUDFLARE";

        print "Target           Local User           Mode       Date                      Notes\n";
        print "======           ==========           ====       ====                      =====\n";
        my @domains = ConfigServer::CloudFlare::action( "getlist", "", "", "", $valuelist );
        foreach my $domainkey (@domains) {
            foreach my $key ( sort { $domainkey->{$a}{created_on} <=> $domainkey->{$b}{created_on} } keys %{$domainkey} ) {
                if ( $domainkey->{$key}{success} ) {
                    if ( $setting eq "all" or $domainkey->{$key}{mode} eq $setting ) {
                        $ip      = $key;
                        $date    = localtime( $domainkey->{$key}{created_on} );
                        $comment = $domainkey->{$key}{notes};
                        $domain  = $domainkey->{$key}{domain};
                        $mode    = $domainkey->{$key}{mode};
                        write;
                    }
                }
                else {
                    print $domainkey->{$key}{domain} . "\n";
                }
            }
        }
    }
    elsif ( $cmd eq "add" ) {
        my $mode;
        if    ( $setting eq "block" )     { $mode = "block" }
        elsif ( $setting eq "challenge" ) { $mode = "challenge" }
        elsif ( $setting eq "whitelist" ) { $mode = "whitelist" }
        else {
            print "Invalid add type, must be: [block], [challenge] or [whitelist]\n";
            exit 1;
        }
        my $status = ConfigServer::CloudFlare::action( "add", $value, $mode, "", $valuemorelist );
    }
    elsif ( $cmd eq "del" ) {
        my $status = ConfigServer::CloudFlare::action( "del", $setting, "whitelist", "", $valuelist );
    }
    elsif ( $cmd eq "tempadd" ) {
        my $mode;
        if    ( $setting eq "deny" )  { $mode = "block" }
        elsif ( $setting eq "allow" ) { $mode = "whitelist" }
        else {
            print "Invalid tempadd type, must be: [deny], or [allow]\n";
            exit 1;
        }
        $input{argument} = [ $value, $config{CF_TEMP} ];
        if ( $setting eq "deny" ) {
            my $status = ConfigServer::CloudFlare::action( "deny", $value, $mode, "", $valuemorelist, 1 );
            dotempdeny("cf");
        }
        elsif ( $setting eq "allow" ) {
            my $status = ConfigServer::CloudFlare::action( "allow", $value, $mode, "", $valuemorelist, 1 );
            dotempallow("cf");
        }
    }
    else {
        print "Invalid command, must be: [list], [remove], [add], or [tempadd]\n";
        exit 1;
    }

    return;
}

sub dographs {
    my ( $type, $dir ) = @{ $input{argument} }[ 0, 1 ];
    my %types = (
        "load"             => 1,
        "cpu"              => 1,
        "mem"              => 1,
        "net"              => 1,
        "disk"             => 1,
        "diskw"            => 1,
        "email"            => 1,
        "temp"             => 1,
        "mysqldata"        => 1,
        "mysqlqueries"     => 1,
        "mysqlslowqueries" => 1,
        "mysqlconns"       => 1,
        "apachecpu"        => 1,
        "apacheconn"       => 1,
        "apachework"       => 1
    );
    if ( $dir !~ /\/$/ ) { $dir .= "/" }

    unless ( $config{ST_ENABLE} ) {
        print "ST_ENABLE is disabled\n";
        exit 1;    ## no critic (Cpanel::NoExitsFromSubroutines) - CLI command precondition failure
    }
    unless ( $config{ST_SYSTEM} ) {
        print "ST_SYSTEM is disabled\n";
        exit 1;
    }

    # GD::Graph availability is now verified at ServerStats compile time

    if ( $type eq "" and $dir eq "" ) {
        print "Valid graph types:\n";
        foreach my $key ( keys %types ) { print "$key " }
        print "\n";
        print "Usage: csf [graph type] [directory]\n";
        exit 1;
    }

    if ( $type eq "" or !$types{$type} ) {
        print "Invalid graph type. Choose one of:\n";
        foreach my $key ( keys %types ) { print "$key " }
        print "\n";
        print "Usage: csf [graph type] [directory]\n";
        exit 1;
    }
    if ( $dir eq "" or !( -d $dir ) ) {
        print "You must specify a valid directory in which to create the graphs and html pages\n";
        print "Usage: csf [graph type] [directory]\n";
        exit 1;
    }

    print "Creating html pages and images...\n";

    ConfigServer::ServerStats::charts( $config{CC_LOOKUPS}, $dir );
    open( my $CHARTS, ">", $dir . "/charts.html" );
    flock( $CHARTS, LOCK_EX );
    print $CHARTS ConfigServer::ServerStats::charts_html( $config{CC_LOOKUPS}, "" );
    close($CHARTS);

    ConfigServer::ServerStats::graphs( $type, $config{ST_SYSTEM_MAXDAYS}, $dir );
    open( my $GRAPHS, ">", $dir . "/graphs.html" );
    flock( $GRAPHS, LOCK_EX );
    print $GRAPHS ConfigServer::ServerStats::graphs_html("");
    close($GRAPHS);

    print "Created charts.html, graphs.html and their images in $dir\n";
    return;
}

sub loadmodule {
    my $module = shift;
    my @output;

    eval {
        local $SIG{__DIE__} = undef;
        local $SIG{'ALRM'}  = sub { die };
        alarm(5);
        my ( $childin, $childout );
        my $pid = IPC::Open3::open3( $childin, $childout, $childout, $config{MODPROBE}, $module );
        @output = <$childout>;
        waitpid( $pid, 0 );
        alarm(0);
    };
    alarm(0);

    return @output;
}

sub syscommand {
    my $line         = shift;
    my $command      = shift;
    my $force        = shift;
    my $status       = 0;
    my $iptableslock = 0;
    if ( $command =~ /^($config{IPTABLES}|$config{IP6TABLES})/ ) { $iptableslock = 1 }
    if ($faststart) {
        if ( $command =~ /^$config{IPTABLES}\s+(.*)$/ ) {
            my $fastcmd = $1;
            $fastcmd =~ s/-v//;
            $fastcmd =~ s/--wait//;
            if ( $fastcmd =~ /-t\s+nat/ ) {
                $fastcmd =~ s/-t\s+nat//;
                push @faststart4nat, $fastcmd;
            }
            else {
                push @faststart4, $fastcmd;
            }
        }
        if ( $command =~ /^$config{IP6TABLES}\s+(.*)$/ ) {
            my $fastcmd = $1;
            $fastcmd =~ s/-v//;
            $fastcmd =~ s/--wait//;
            if ( $fastcmd =~ /-t\s+nat/ ) {
                $fastcmd =~ s/-t\s+nat//;
                push @faststart6nat, $fastcmd;
            }
            else {
                push @faststart6, $fastcmd;
            }
        }
        return;
    }

    if ( $config{VPS} ) { $status = checkvps() }

    if ($status) {
        error( $line, $status );
    }
    else {
        if ( $config{DEBUG} >= 1 ) { print "debug[$line]: Command:$command\n"; }

        if ($iptableslock) { iptableslock("lock") }
        my @output;
        if ( $iptableslock and $config{WAITLOCK} ) {
            eval {
                local $SIG{__DIE__} = undef;
                local $SIG{'ALRM'}  = sub { die "alarm\n" };
                alarm( $config{WAITLOCK_TIMEOUT} );
                my ( $childin, $childout );
                my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $command );
                @output = <$childout>;
                waitpid( $cmdpid, 0 );
                alarm(0);
            };
            alarm(0);
            if ( $@ eq "alarm\n" ) {
                error( __LINE__, "*Error* timeout after iptables --wait for $config{WAITLOCK_TIMEOUT} seconds - WAITLOCK" );
            }
        }
        else {
            my ( $childin, $childout );
            my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $command );
            @output = <$childout>;
            waitpid( $cmdpid, 0 );
        }
        if ($iptableslock) { iptableslock("unlock") }

        chomp @output;
        if ( defined $output[0] && $output[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @output }
        foreach my $line (@output) {
            if ( $line =~ /^Using intrapositioned negation/ ) { next }
            print $line. "\n";
        }
        if ( defined $output[0] && $output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/ and !$config{WAITLOCK} ) {
            my $cnt    = 0;
            my $repeat = 6;
            while ( $cnt < $repeat ) {
                sleep 1;
                if ( $config{DEBUG} >= 1 ) { print "debug[$line]: Retry (" . ( $cnt + 1 ) . ") [$command] due to [$output[0]]" }
                if ($iptableslock)         { iptableslock("lock") }
                my ( $childin, $childout );
                my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $command );
                my @output = <$childout>;
                waitpid( $cmdpid, 0 );
                if ($iptableslock) { iptableslock("unlock") }
                chomp @output;
                if ( defined $output[0] && $output[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @output }
                $cnt++;
                if     ( defined $output[0] && $output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/ and $cnt == $repeat ) { error( $line, "Error processing command for line [$line] ($repeat times): [$output[0]]" ); }
                unless ( defined $output[0] && $output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/ )                     { $cnt = $repeat }
            }
        }
        if ( defined $output[0] && $output[0] =~ /^(iptables|xtables|Bad|Another)/ and ( $config{TESTING} or $force ) ) {
            if ( $output[0] =~ /iptables: No chain\/target\/match by that name/ ) {
                error( $line, "iptables command [$command] failed, you appear to be missing a required iptables module" );
            }
            else {
                error( $line, "iptables command [$command] failed" );
            }
        }
        if ( defined $output[0] && $output[0] =~ /^(ip6tables|Bad|Another)/ and ( $config{TESTING} or $force ) ) {
            if ( $output[0] =~ /ip6tables: No chain\/target\/match by that name/ ) {
                error( $line, "ip6tables command [$command] failed, you appear to be missing a required ip6tables module" );
            }
            else {
                error( $line, "ip6tables command [$command] failed" );
            }
        }
        if ( defined $output[0] && $output[0] =~ /xtables lock/ ) {
            $warning .= "iptables command [$command] failed due to xtables lock, enable WAITLOCK in csf.conf\n\n";
        }
        if ( defined $output[0] && $output[0] =~ /^(iptables|xtables|ip6tables|Bad|Another)/ ) {
            $warning .= "*ERROR* line:[$line]\nCommand:[$command]\nError:[$output[0]]\nYou should check through the main output carefully\n\n";
        }
    }
    return;
}

sub iptableslock {
    my $lock      = shift;
    my $iptablesx = shift;
    if ( $lock eq "lock" ) {
        if ( sysopen( $iptableslock_fh, "/var/lib/csf/command.lock", O_RDWR | O_CREAT ) ) {
            flock( $iptableslock_fh, LOCK_EX );
            autoflush $iptableslock_fh 1;
            seek( $iptableslock_fh, 0, 0 );
            truncate( $iptableslock_fh, 0 );
            print $iptableslock_fh $$;
        }
    }
    elsif ( $lock eq "unlock" && defined $iptableslock_fh ) {
        close($iptableslock_fh);
        undef $iptableslock_fh;
    }
    return;
}

sub checkvps {
    if ( -e "/proc/user_beancounters" and !( -e "/proc/vz/version" ) ) {
        my @data = slurp("/proc/user_beancounters");
        chomp @data;

        foreach my $line (@data) {
            if ( $line =~ /^\s*numiptent\s+(\d*)\s+(\d*)\s+(\d*)\s+(\d*)/ ) {
                if ( $1 > $4 - 10 ) { return "The VPS iptables rule limit (numiptent) is too low ($1/$4) - stopping firewall to prevent iptables blocking all connections" }
            }
        }
    }
    return 0;
}

sub modprobe {
    if ( -e $config{MODPROBE} ) {
        my @modules = ( "ip_tables", "ipt_multiport", "iptable_filter", "ipt_limit", "ipt_LOG", "ipt_REJECT", "ipt_conntrack", "ip_conntrack", "ip_conntrack_ftp", "iptable_mangle", "ipt_REDIRECT", "iptable_nat" );

        unless ( loadmodule("xt_multiport") ) {
            @modules = ( "ip_tables", "xt_multiport", "iptable_filter", "xt_limit", "ipt_LOG", "ipt_REJECT", "ip_conntrack_ftp", "iptable_mangle", "xt_conntrack", "ipt_REDIRECT", "iptable_nat", "nf_conntrack_ftp", "nf_nat_ftp" );
        }

        if ( $config{SMTP_BLOCK} ) {
            push @modules, "ipt_owner";
            push @modules, "xt_owner";
        }
        if ( $config{PORTFLOOD} or $config{PORTFLOOD6} or $config{PORTKNOCKING} ) {
            push @modules, "ipt_recent ip_list_tot=1000 ip_list_hash_size=0";
        }
        if ( $config{CONNLIMIT} ) {
            push @modules, "xt_connlimit";
        }

        foreach my $module (@modules) { loadmodule($module) }
    }
    return;
}

sub faststart {
    my $text = shift;
    if (@faststart4) {
        if ($verbose) { print "csf: FASTSTART loading $text (IPv4)\n" }
        my $status;
        if ( $config{VPS} )        { $status = fastvps( scalar @faststart4 ) }
        if ($status)               { error( __LINE__, $status ) }
        if ( $config{DEBUG} >= 2 ) { print join( "\n", @faststart4 ) . "\n" }
        iptableslock("lock");
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, "$config{IPTABLES_RESTORE} $config{IPTABLESWAIT} -n" );
        print $childin "*filter\n" . join( "\n", @faststart4 ) . "\nCOMMIT\n";
        close $childin;
        my @results = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @results;
        if ( length $results[0] && $results[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @results }

        if ( length $results[0] && $results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/ ) {
            my $cmd;
            if ( $results[1] =~ /^Error occurred at line: (\d+)$/ ) { $cmd = $faststart4[ $1 - 1 ] }
            error( __LINE__, "FASTSTART: ($text IPv4) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled" );
        }
        iptableslock( "unlock", 1 );
    }
    if (@faststart4nat) {
        if ($verbose) { print "csf: FASTSTART loading $text (IPv4 nat)\n" }
        my $status;
        if ( $config{VPS} )        { $status = fastvps( scalar @faststart4nat ) }
        if ($status)               { error( __LINE__, $status ) }
        if ( $config{DEBUG} >= 2 ) { print join( "\n", @faststart4nat ) . "\n" }
        iptableslock("lock");
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, "$config{IPTABLES_RESTORE} $config{IPTABLESWAIT} -n" );
        print $childin "*nat\n" . join( "\n", @faststart4nat ) . "\nCOMMIT\n";
        close $childin;
        my @results = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @results;
        if ( length $results[0] && $results[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @results }

        if ( length $results[0] && $results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/ ) {
            my $cmd;
            if ( $results[1] =~ /^Error occurred at line: (\d+)$/ ) { $cmd = $faststart4[ $1 - 1 ] }
            error( __LINE__, "FASTSTART: ($text IPv4nat) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled" );
        }
        iptableslock( "unlock", 1 );
    }
    if ( @faststart6 and $config{IPV6} ) {
        if ($verbose) { print "csf: FASTSTART loading $text (IPv6)\n" }
        my $status;
        if ( $config{VPS} )        { $status = fastvps( scalar @faststart6 ) }
        if ($status)               { error( __LINE__, $status ) }
        if ( $config{DEBUG} >= 2 ) { print join( "\n", @faststart6 ) . "\n" }
        iptableslock("lock");
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, "$config{IP6TABLES_RESTORE} $config{IPTABLESWAIT} -n" );
        print $childin "*filter\n" . join( "\n", @faststart6 ) . "\nCOMMIT\n";
        close $childin;
        my @results = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @results;
        if ( length $results[0] && $results[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @results }

        if ( length $results[0] && $results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/ ) {
            my $cmd;
            if ( $results[1] =~ /^Error occurred at line: (\d+)$/ ) { $cmd = $faststart4[ $1 - 1 ] }
            error( __LINE__, "FASTSTART: ($text IPv6) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled" );
        }
        iptableslock( "unlock", 1 );
    }
    if ( @faststart6nat and $config{IPV6} ) {
        if ($verbose) { print "csf: FASTSTART loading $text (IPv6 nat)\n" }
        my $status;
        if ( $config{VPS} )        { $status = fastvps( scalar @faststart6nat ) }
        if ($status)               { error( __LINE__, $status ) }
        if ( $config{DEBUG} >= 2 ) { print join( "\n", @faststart6nat ) . "\n" }
        iptableslock("lock");
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, "$config{IP6TABLES_RESTORE} $config{IPTABLESWAIT} -n" );
        print $childin "*nat\n" . join( "\n", @faststart6nat ) . "\nCOMMIT\n";
        close $childin;
        my @results = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @results;
        if ( length $results[0] && $results[0] =~ /# Warning: iptables-legacy tables present/ ) { shift @results }

        if ( length $results[0] && $results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/ ) {
            my $cmd;
            if ( $results[1] =~ /^Error occurred at line: (\d+)$/ ) { $cmd = $faststart6[ $1 - 1 ] }
            error( __LINE__, "FASTSTART: ($text IPv6nat) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled" );
        }
        iptableslock( "unlock", 1 );
    }
    if (@faststartipset) {
        if ($verbose) { print "csf: FASTSTART loading $text (IPSET)\n" }
        my ( $childin, $childout );
        my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "restore" );
        print $childin join( "\n", @faststartipset ) . "\n";
        close $childin;
        my @results = <$childout>;
        waitpid( $cmdpid, 0 );
        chomp @results;

        if ( length $results[0] && $results[0] =~ /^ipset/ ) {
            print "FASTSTART: (IPSET) Error:[$results[0]]. Try restarting csf with FASTSTART disabled";
        }
    }
    undef @faststart4;
    undef @faststart4nat;
    undef @faststart6;
    undef @faststart6nat;
    undef @faststartipset;
    $faststart = 0;
    return;
}

sub fastvps {
    my $size = shift;
    if ( -e "/proc/user_beancounters" and !( -e "/proc/vz/version" ) ) {
        my @data = slurp("/proc/user_beancounters");
        chomp @data;

        foreach my $line (@data) {
            if ( $line =~ /^\s*numiptent\s+(\d*)\s+(\d*)\s+(\d*)\s+(\d*)/ ) {
                if ( $1 > $4 - ( $size + 10 ) ) { return "The VPS iptables rule limit (numiptent) is too low to add $size rules ($1/$4) - *IPs not added*" }
            }
        }
    }
    return 0;
}

sub ipsetcreate {
    my $set = shift;
    $SIG{PIPE} = 'IGNORE';
    my $family = "inet";
    if ( $set =~ /_6/ ) { $family = "inet6" }
    if ($verbose)       { print "csf: IPSET creating set $set\n" }
    my ( $childin, $childout );
    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "create", "-exist", $set, "hash:net", "family", $family, "hashsize", $config{LF_IPSET_HASHSIZE}, "maxelem", $config{LF_IPSET_MAXELEM} );
    close $childin;
    my @results = <$childout>;
    waitpid( $cmdpid, 0 );
    chomp @results;

    if ( length $results[0] && $results[0] =~ /^ipset/ ) {
        print "IPSET: [$results[0]]\n";
        $warning .= "*ERROR* IPSET: [$results[0]]\n";
    }
    return;
}

sub ipsetrestore {
    my $set = shift;
    $SIG{PIPE} = 'IGNORE';
    if ($verbose) { print "csf: IPSET loading set $set with " . scalar(@ipset) . " entries\n" }
    my ( $childin, $childout );
    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "restore" );
    print $childin join( "\n", @ipset ) . "\n";
    close $childin;
    my @results = <$childout>;
    waitpid( $cmdpid, 0 );
    chomp @results;

    if ( length $results[0] && $results[0] =~ /^ipset/ ) {
        print "IPSET: [$results[0]]\n";
        $warning .= "*ERROR* IPSET: [$results[0]]\n";
    }
    undef @ipset;
    return;
}

sub ipsetadd {
    my $set = shift;
    my $ip  = shift;
    $SIG{PIPE} = 'IGNORE';
    if ( $set =~ /^chain(_6)?_NEW(\w+)$/ ) { $set = "chain" . $1 . "_" . $2 }
    if ( $set =~ /^(\w+)(IN|OUT)$/ )       { $set = $1 }
    if ( $set =~ /^bl(_6)?_NEW(\w+)$/ )    { $set = "bl" . $1 . "_" . $2 }
    if ( $set eq "" or $ip eq "" ) { return }
    if ($faststart) {
        push @faststartipset, "add -exist $set $ip";
        return;
    }
    if ($verbose) { print "csf: IPSET adding [$ip] to set [$set]\n" }
    my ( $childin, $childout );
    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "add", "-exist", $set, $ip );
    close $childin;
    my @results = <$childout>;
    waitpid( $cmdpid, 0 );
    chomp @results;

    if ( length $results[0] && $results[0] =~ /^ipset/ ) {
        print "IPSET: [$results[0]]\n";
        $warning .= "*ERROR* IPSET: [$results[0]]\n";
    }
    return;
}

sub ipsetdel {
    my $set = shift;
    my $ip  = shift;
    $SIG{PIPE} = 'IGNORE';
    if ( $set =~ /^chain(_6)?_NEW(\w+)$/ ) { $set = "chain" . $1 . "_" . $2 }
    if ( $set =~ /^(\w+)(IN|OUT)$/ )       { $set = $1 }
    if ( $set =~ /^bl(_6)?_NEW(\w+)$/ )    { $set = "bl" . $1 . "_" . $2 }
    if ( $set eq "" or $ip eq "" )         { return }
    if ($verbose)                          { print "csf: IPSET deleting [$ip] from set [$set]\n" }
    my ( $childin, $childout );
    my $cmdpid = IPC::Open3::open3( $childin, $childout, $childout, $config{IPSET}, "del", $set, $ip );
    close $childin;
    my @results = <$childout>;
    waitpid( $cmdpid, 0 );
    chomp @results;

    if ( length $results[0] && $results[0] =~ /^ipset/ ) {
        print "IPSET: [$results[0]]\n";
        $warning .= "*ERROR* IPSET: [$results[0]]\n";
    }
    return;
}

1;