cPHulk is the brute-force protection built into WHM. It watches SSH, WHM, cPanel, Webmail, FTP, POP3, IMAP, and SMTP for repeated authentication failures and blocks the source IP or account. The defaults are too lenient for a public-facing server and the first time you crank them up you will almost certainly lock yourself out — usually from a hotel Wi-Fi at the worst possible moment.
This is the configuration that survives a real shared-hosting workload: tight enough that SSH password sprays die in under a minute, loose enough that a customer mistyping their mail password three times doesn't generate a support ticket.
Step 0 — Whitelist before you touch anything else
The single most common cPHulk mistake is tightening the thresholds first and adding a whitelist second. Do this in the opposite order. Under WHM → Security Center → cPHulk Brute Force Protection → History Reports / Whitelist Management, add:
- Your office or VPN egress IP
- Your monitoring system's IP
- Any IPs that run automated WHM API calls (Blesta, WHMCS, billing automation)
- The server's own primary IP — surprisingly easy to lock out via loopback under some configs
Or from the shell:
whmapi1 create_cphulk_record list_name=white ip=203.0.113.42
whmapi1 create_cphulk_record list_name=white ip=198.51.100.0/24
CIDR notation works. Whitelisted IPs bypass all cPHulk checks, so do not whitelist shared-hosting customer IPs — only your own administrative ranges.
If you provision new servers from a single bastion, bake the whitelist into your cPanel VPS install playbook so a fresh build is never wide open.
Step 1 — Pick the right detection windows
cPHulk has two trigger pairs that map to different threat models:
| Setting | Defaults | What it catches |
|---|---|---|
| IP-based: failures + minutes | 9 in 5 | Single attacker pounding from one IP |
| Username-based: failures + minutes | 15 in 5 | Distributed attack across many IPs on one account |
For a public server, drop the IP-based pair to 5 failures in 5 minutes and leave the username-based pair at the default. Going below 5 produces too many false positives from mail clients with stale passwords; going above 10 lets a slow brute-force run for hours.
The One-Day Block values matter more than the short-window ones — a one-day block should require a sustained attack, not a single bad afternoon. Set:
- One-Day Block period: 24 hours
- Failures before one-day block (IP): 40
- Failures before one-day block (username): 80
The cPHulk database is checked on every login attempt and grows fast on a busy server. Keep Command to run when an IP triggers a one-day block empty unless you actually shovel events into a SIEM — running a shell hook on every block adds measurable CPU under attack.
Step 2 — Choose IP-based blocking, not just account-based
In Configuration Settings, two toggles change the behaviour materially:
- Block IP addresses at the firewall level for failed logins. Turn this on. Without
it, cPHulk only inserts records into its MySQL table and checks them application-side —
fine for SSH, useless for protecting an exposed mail port from a 10k-IP botnet. With it
on, cPHulk drops blocked IPs into
iptablesand the kernel rejects them before any daemon sees the connection. - Notify on brute force. On. Send to a real, monitored inbox — not the catch-all that no one reads.
The iptables chain cPHulk uses is cphulk, and rules are flushed and rebuilt by
cphulkd on every config reload. Do not hand-edit it; use the whitelist UI or
create_cphulk_record.
Step 3 — Country blocking is a 70% solution
Under Country Management, you can deny or allow logins from entire country codes. Useful, but with caveats:
- The GeoIP database lags real allocations by weeks. A new VPS range in a "blocked" country may not be blocked.
- Customers travel. A blanket block on countries you don't sell to will eventually deny a legitimate login from someone on holiday.
- Tor exit nodes and residential proxies route around it trivially.
The right use: block at the firewall, not at the application. Keep the list short — the worst three or four offenders for your specific workload — and pair it with Imunify360's brute-force module for actual coverage. If you run both, disable one of them so they don't double-count failures.
Step 4 — Get back in when you lock yourself out
You will. When it happens, you have three options.
From an already-open SSH session (or your KVM/console):
# Confirm you are blocked
whmapi1 get_cphulk_status
# Remove the block on your IP
whmapi1 flush_cphulk_login_history_for_ips ip=203.0.113.42
# Or wipe the whole login history if you also need account unlock
whmapi1 flush_cphulk_login_history
If cPHulk is locked out and refusing all logins (the database can corrupt under heavy attack):
/usr/local/cpanel/bin/cphulkdwhitelist 203.0.113.42
/usr/local/cpanel/etc/init/stopcphulkd
/usr/local/cpanel/etc/init/startcphulkd
As an absolute last resort, disable cPHulk entirely from the console:
whmapi1 disable_cphulk
The setting persists across reboots. Re-enable as soon as you've added a whitelist entry via the API:
whmapi1 enable_cphulk
Step 5 — Monitor what's actually happening
The signal you want isn't "cPHulk is enabled" — it's "cPHulk is blocking faster than the attackers can find new IPs." Two things to watch:
- cPHulk's own log:
/usr/local/cpanel/logs/cphulkd.log—grep BLOCKshows real-time blocks, useful as a tail in a tmux pane during an attack. - The dashboard's History Reports: sorted by Number of Brutes, this surfaces the /16 ranges that need to go on the deny list. If you see the same /24 generate 800 failures across 200 IPs in an hour, deny the /16 in Whitelist/Blacklist Management.
The /blacklist API is symmetric to the whitelist:
whmapi1 create_cphulk_record list_name=black ip=192.0.2.0/24
Next steps
- Install Imunify360 on cPanel for malware scanning and WAF coverage that cPHulk doesn't provide.
- Run Imunify360 alongside CSF and ModSecurity without duplicating brute-force events.
- See the cPanel license tier breakdown if you're sizing a new server and want to know which features are gated by tier.