The Definite Guide of Obscure Tweaks to Install and Maintain cPanel / WHM (version 10)

I have recently gone more deeply into the bare bones of WHM and cPanel 10 to improve security, reduce bandwidth and cpu usage and generaly make sure servers are as good as they can possibly be.

So, in the process, I had to go deep into tons of scripts, code, discussions, forums and google to find out the best configurations and how to achieve them.

This is an on-going guide, not meant to be new release of information but more an aggregation of several feeds, with an hands-on approach.

It is not intended for the basic setup, nor for basic security (like disabling telnet) but more for obscure or interesting tweaks, which are either hard to find or you simply wouldn’t be looking for them.

I’ll be updating it regularly.


The Definite Guide of Obscure Tweaks to Install and Maintain cPanel / WHM (version 10)


1) Since verification is now done on the RCPT stage, make the default catch-all to :fail: , not :blackhole: . For new accounts, change the settings in the “tweak settings” from WHM. For existing accounts, see script below.

The reasons are:

1. :blackhole: accepts the email and receives it, then sends it to /dev/null. This wastes your bandwidth and actually breaks the SMTP RFC because you’re not notifying the sender that the email is undelivered.

2. :fail: stops the email from being received, because verify = recipient occurs at the RCPT phase of the SMTP exchange before any data has been received. No bounce is sent, the exchange simply termintates with an SMTP error code. This means much less processing resources on your SMTP server, much less bandwidth (you don’t actually receive the email) and you maintain RFC compliance by notifying the senders SMTP server that the delivery failed (which spammers ignore and real people appreciate if they’ve made an addressing mistake).
(Jonathan Michaelson)

Script to change all existing catch-all emails from :blackhole: to :fail:
Run this in a different directory than valiases, I recomend your home directory because it will create a backup of the current aliases (just in case)
This also keeps permissions and owners settings.

tar -cf valiases_backup.tar /etc/valiases/*
gzip valiases_backup.tar

files=`find /etc/valiases -type f`

for file in $files
cp -p $file $file.tmp
cat /dev/null > $file.tmp
cat $file | sed ‘s/\:blackhole\:/\:fail\:/g’ > $file.tmp
mv $file.tmp $file -f

2) Let exim read userdomains!
It happens that eximstats cannot read /etc/userdomains as this fille is owned by root.mail, and smtp records in /var/log/exim_mainlog dont contain the system user so a lookup must be used.
This affects bandwidth measures will improve the accurracy, by including transfers in the users which were previously being counted towards the mailnull or cpanel user.

open /etc/passwd with your favourite editor and change this line:

3)Fix BFD to properly check the Exim logs
You should already be running APF and BFD.
BFD 0.9 script does not work for me , and it doesnt parse exim logs properly, so I had to hack it.
I would advise you to do the same, if you want to block IP addresses that consistently try to flood your email server and they belong to a spam list


In the BFD itself, I changed one line. Here’s the diff:

root@host [/usr/local/bfd]# diff bfd bfd.backup
< for ihost in `echo $ARG_VAL | tr ' ' '\n' | tr ':' ' ' | awk '{print$1}' | grep -E '[.0-9]+' | sort -u`; do --- > for ihost in `echo $ARG_VAL | tr ‘ ‘ ‘\n’ | tr ‘:’ ‘ ‘ | awk ‘{print$1}’ | grep -E ‘[.0-9]+’ | uniq`; do

In the rules directory , I changed my exim file and it looks like this now:

if [ -f “$REQ” ]; then

# Max log entries to process at once for this rule

ARG_VAL=`$TLOGP $LP $TLOG_TF | grep -iw “rejected RCPT” | awk ‘{print$4}’ | tr -d ‘[]’ | tr ‘:’ ‘ ‘ | awk ‘{print$1}’ | grep -E ‘^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$’ | tail -n $MLOG`

I have also setup BFD to run once a minute, with minimal performance impact.


I found that uniq doesnt really uniq the list down, but simply uniques lines that are consecutively repeated. So it will change this:

into this:

when in reality, what we want is this:

which is what sort -u does.

The original exim rules don’t parse my exim log properly, so my exim file placed in the directory rules does the job. I found that the original rule does not take the ip address properly, because it tries to make a match at, where in reality we need first to remove the port number (:1312) and then look for an ip address, I also found it lets things like ( pass, which shouldn’t.

— Monitoring

1) Make sure you get an e-mail everytime root logs in!


Edit your .bash_profile and include these lines:

echo ‘ALERT – Root Shell Access on:’ `date` `who` | mail -s “Alert: Root Access from `who | awk ‘{print $6}’`” should be an external e-mail address for obvious reasons.

2)Set an SSH Legal Message

To add a SSH legal message upon login, SSH into server and login as root.
At command prompt type: pico /etc/motd
Enter your message, save and exit.

3) Get an e-mail every day with the total disk usage plus the 30 biggest directories.

It’s easy, simply add this to cron:

du / | sort -n | tail -n 30 | mail -s "Daily disk usage report"

4)Use LogWatch to get an e-mail with details parsed from your server logs.

Apart from the normal instalation of LogWatch, to make it useful take these steps:

– edit the /usr/share/logwatch/default.conf/logwatch.conf
change: the email destination (external email is better) , set Detail to medium or high (I would set to high)

– edit /etc/logwatch/override.conf (originally this file is empty) and put these lines:
logfiles/exim: LogFile = exim_mainlog
logfiles/http: LogFile = /usr/local/apache/logs/access_log
services/pop3: *OnlyService = cpanelpop
services/pop3: *RemoveHeaders = 1
services/pure-ftpd: LogFile = messages

This overrides the logfiles and messages for some of the services, these are the working ones under cPanel 10.8 (not using maildir).

In my current version (Logwatch 7.2.1 and cPanel 10.8.1) both POP3 and Exim parsing does not work properly. I have recoded the POP3 perl script to output something useful, but this is work in progress still.

I am working on the Exim script now, but I am having serious problems with performance.

Once I have both script ready, I’ll post them here.

Pure ftpd is not working either, but I think this is a configuration issue, not a problem with the parser itself.

Run logwatch once from the command line and see if you like the emails. Tweak as necessary.

5)PRM – (Process Resource Monitor) . This tool does what it says on the tin.
Quick reference article, taken from Crucial Paradigm help pages:

How to install PRM (Process Resource Monitor)

PRM (Process Resource Monitor)

PRM monitors the process table on a given system and matches process id’s with set resource limits in the config file or per-process based rules. Process id’s that match or exceed the set limits are logged and killed; includes e-mail alerts, kernel logging routine and more…

How it works?
PRM works on the basis that once a process id is found matching resource limits; there is a corresponding trigger and wait value. The trigger value increments upwards from zero (0) to the defined value, pausing the duration of seconds defined as wait value. There after the status of the flagged pid is checked again, if still above or equal to resource limits the trigger/wait cycle begins again till the max trigger value is reached. When this trigger value is reached the given process is logged/killed.

This all together has the effect that applications with short burst resource spikes (e.g: apache, mysql etc..) are not killed; but rather on applications with prolonged resource consumption. Using the rule system, you can define different wait/trigger/resource values for any application.

First we must fetch the package:

And extract it:
tar xvfz prm-current.tar.gz

The current version of prm as of this writing is 0.3, so lets cd to the 0.3 extracted path:
cd prm-0.3/

And finally run the enclosed script:

The prm installation is located at ‘/usr/local/prm’, and the configuration file is labeled ‘conf.prm’.

Open the ‘/usr/local/prm/conf.prm’ file with your preferred editor. There is an array of options in this file but we will only be focusing on the main variables.

Lets skip down to the user e-mail alert’s section and set the USR_ALERT value to ‘1’; enabling alerts.
# enable user e-mail alerts [0=disabled,1=enabled] USR_ALERT=”1″

And configure our e-mail addresses for alerts:
# e-mail address for alerts USR_ADDR=”root,”

Check the 5,10, or 15 minute load average; relative to the later option below for min. load level.
# check 5,10,15 minute load average. [1,2,3 respective of 5,10,15] LC=”1″

PRM optionally has a required load average for running. If the load is not equal to or greater than this value; PRM will not run. Setting this value to zero will force the script to always run but this should not be needed.
# min load level required to run (decimal values unsupported) MIN_LOAD=”1″

This is the introduction described wait value, used for pauses between trigger increments. The value of wait multiplied by the value of kill_trig equal the duration of time before a process is killed (10×3=30seconds).
# seconds to wait before rechecking a flagged pid (pid’s noted resource # intensive but not yet killed). WAIT=”10″

The trigger limit before processes are killed, described in detail in the above ‘wait’ description and introduction.
# counter limit that a process must reach prior to kill. The counter value # increases for a process flagged resource intensive on rechecks. KILL_TRIG=”3″

The max percentage of CPU a process should be allowed to use before PRM flags it for killing.
# Max CPU usage readout for a process – % of all cpu resources (decimal values unsupported) MAXCPU=”35″

The max percentage of MEM a process should be allowed to use before PRM flags it for killing.
# Max MEM usage readout for a process – % of system total memory (decimal values unsupported) MAXMEM=”15″

That is it; you should tweak the MAXCPU/MAXMEM limits to your desired needs but the defaults should be fine for most.

The executable program resides in ‘/usr/local/prm/prm’ and ‘/usr/local/sbin/prm’. The prm executable can receive one of two arguments:

-s Standard run
-q Quiet run

The log path for prm is ‘/usr/local/prm/prm_log’, as well pid specific logs are stored in ‘/usr/local/prm/killed/’.

A default cronjob for PRM is installed to ‘/etc/cron.d/prm’, and is configured to run once every 5 minutes.

There is a provided ignore file, to ignore processes based on string rules. The ignore file is located at ‘/usr/local/prm/ignore’. This file supports line separated ignore strings. As a default the strings ‘root, named and postgre’ are ignored by PRM; this script was not intended to monitor root processes but rather user land tasks. It could easily watch root processes by removing the given line in the ignore file but this is strongly discouraged.

— Web (apache)

1) Remove version information from Apache (check Security by Obscurity part)

2) Activate the Php open_basedir Tweak (go to Tweak Security in WHM)

3) Install Modsecurity

Mod security allows filtering the incoming requests. There are already filters available on the web to use straight away and they are updated regularly.


Go to the “Addon Modules” in WHM and check the Modsecurity module

You now have to edit your Apache httpd.conf file (usually resides in /usr/local/apache/conf/httpd.conf)

cPanel should have added this line in there already for you, but double check anyway:

Include "/usr/local/apache/conf/modsec.conf"

Now, edit the modsec.conf file.
This is how my modsec.conf file looks like. You might want to change some settings. Notice the inclusion of the rules for the modsecurity module:

SecFilterEngine On
SecFilterCheckURLEncoding On
SecFilterForceByteRange 0 255
SecAuditEngine RelevantOnly
SecAuditLog logs/audit_log
SecFilterDebugLog logs/modsec_debug_log
SecFilterDebugLevel 0
SecFilterDefaultAction "deny,log,status:406"
SecFilterSelective REMOTE_ADDR "^$" nolog,allow
Include "/usr/local/apache/conf/modsec.user.conf"
#And now, the rules
#Remove any of these Include lines you do not use or have rules for.

#First, add in your exclusion rules:
#These MUST come first!
Include /etc/modsecurity/exclude.conf

#Application protection rules
#Include /etc/modsecurity/rules.conf

#Comment spam rules
Include /etc/modsecurity/blacklist.conf

#Bad hosts, bad proxies and other bad players
Include /etc/modsecurity/blacklist2.conf

#Bad clients, known bogus useragents and other signs of malware
#Include /etc/modsecurity/useragents.conf

#Known bad software, rootkits and other malware
Include /etc/modsecurity/rootkits.conf

#Signatures to prevent proxying through your server
#only rule these rules if your server is NOT a proxy
Include /etc/modsecurity/proxy.conf

#Additional rules for Apache 2.x ONLY! Do not add this line if you use Apache 1.x
#Include /etc/modsecurity/apache2-rules.conf

The reason I don’t use all rules is because some where crashing my apache. Anyway, you see the /etc/modsecurity needs to exist and the rules need to be there. So go ahead and mkdir /etc/modsecurity

Now, you need the rules. You can download them from website. I have, however, made a script to auto-update these rules, based on a existing script from I was informed they will include my script on their page soon, but meanwhile you can download it here.

Here’s the direct link to rules page:

If you use my script, just put it in /etc/modsecurity and run it. It should download the rules if you don’t have them yet or update them if you have an old version. It also tries to restart apache, so no need to do that manually. You’ll get an error if apache doesn’t load.

— Security by Obscurity

I will include here the necessary steps to remove all version information from named, exim, apache and cppop.

Some recommended actions:

1)Change the default port for SSH. Ideally you should have as litle shell users as possible, so it is not an inconvenient to advise whoever uses it to use a different non-standard port.
On a regular day, even with pro-active firewalling, you will have hundreds of attempts to connect to SSH. Serious. This is how you do it:


sudo pico -w /etc/ssh/sshd_config

You’ll probably see this:

#Port 22

Change this to:

Port 12345

Or whatever port number you like, keeping in mind not to use any other standard port for other services (I recommend anything between 9999 and 49151)

While you’re at it, remove ssh version 1 from usage:

Protocol 2

You can also only listen on certain IP addresses and there are plenty of other options here, play around.

Now you need to close port 22 on your firewall and open your new port up:

sudo pico -w /etc/apf/conf.apf

Look for your line looking like this one:


and remove 22 and add your new port.

After you finish, just do:

apf –restart
service sshd restart

Before you logoff, you better ensure your configuration is working:

ssh -2 -l username -p newPortNumber

Now, you might want to change your local SSH client options to set the new port number and protocol, just so you don’t have to do that all the time. Under linux, this can easily be done by editing, this time on your local computer, the same ssh_config file:

sudo pico -w /etc/ssh/ssh_config

Add these lines:

Port 12345 (your port number)
Protocol 2

Thats it!

— Handy scripts and information

I have made a few scripts to solve some common problems, such as removing the .cpanel-datastore from all your accounts home directory and the .cpanel-ducache as well.
Other things include fixing the /home directory permissions.
In a post near you…

cPanel and WHM list of used (or possibly used) incoming ports:

20 FTP Data (if you FTP out)
21 FTP (TCP)
22 SSH (TCP) (only if you haven’t changed this, as recommended)
53 DNS – Domain Name Server (TCP)
110 POP3 (TCP)
143 IMAP (TCP)
465 SMTPs (TCP)
953 ??BIND??
993 IMAP4s protocol over TLS/SSL (TCP)
995 POP3s protocol over TLS/SSL (TCP)
2084 entropychat server (TCP)
2086 WHM (TCP)
2087 WHM SSL (TCP)
2095 WebMail (TCP)
2096 WebMail SSL (TCP)
3306 mySQL remote access (TCP)
6666 Melange chat Server (TCP)
7786 Interchange (TCP)
5100 for ASP,
8080 and 8443 for JSP



, ,