OwlCyberSecurity - MANAGER
Edit File: 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;