ConfigServer CSF has shipped country-level blocking for over a decade, but most operators still configure it the way the wiki showed in 2014 — flat iptables rules, MaxMind lookups on every restart, and a CC_DENY list that grew until csf -r took six minutes. With ipset support and DB-IP as a free MaxMind alternative, modern CSF can drop traffic from any country with one ipset match per packet — single-digit microseconds, no rule explosion.
This article is for the operator who has already followed Install ConfigServer CSF on cPanel and tune the defaults and now wants to block half a dozen high-abuse countries from SSH and SMTP without breaking real visitors. It assumes CSF is running and you have root.
CC_DENY versus CC_ALLOW — pick the right mode first
The two settings are not symmetric. They behave very differently and most country-blocking disasters come from confusing them.
CC_DENY = "CN,RU,KP"— blocks all incoming traffic from listed countries on every port. Everything else is allowed (subject to your other rules). This is the right setting for a host that takes traffic from the whole world but wants a deny list.CC_ALLOW = "US,GB,DE"— allows traffic from listed countries and blocks everything else. This is the right setting only if you are running a regional service and have a hard requirement for geo-restriction. It will silently break customers who travel.CC_ALLOW_FILTER = "US,GB"— allows the listed countries only on the ports listed inCC_ALLOW_PORTSandCC_ALLOW_PORTS_UDP. This is what most operators actually want when they say "allow list": lock SSH and webmail to a country list while leaving HTTP and SMTP open to the world.
The combination of CC_DENY plus CC_ALLOW_FILTER covers 95% of real deployments — block egregious abuse globally, then restrict admin ports to known geographies. Don't use CC_ALLOW alone unless you've audited every port.
Enable ipset before turning any of this on
This is the single most important change. With the default IPSET = 0, CSF expands every country into thousands of individual iptables rules — China alone is about 10,000 CIDRs, and that's before you add Russia. A flat ruleset that large adds 10-30ms per new connection on a busy server and makes csf -r painfully slow.
With IPSET = 1, CSF stores the country blocklist in a kernel ipset hash table. Lookups are O(1), restart is instant, and the iptables rule count stays in single digits.
sed -i 's/^IPSET = .*/IPSET = "1"/' /etc/csf/csf.conf
csf -r
Verify after restart:
ipset list -n | grep -i cc_
# cc_deny
# cc_allow_filter
If those tables don't appear, ipset isn't loaded — yum install ipset on AlmaLinux/RHEL, apt install ipset on Debian/Ubuntu, then csf -r again.
Pick a country IP database
CSF has shipped MaxMind GeoLite2 as the default source, but MaxMind closed free public downloads in 2020 and now requires a free signup plus a licence key. Most operators have migrated to DB-IP, which CSF supports out of the box and which does not require credentials.
grep -E '^CC_SRC|^MM_LICENSE_KEY' /etc/csf/csf.conf
# CC_SRC = "2" # 1 = MaxMind, 2 = DB-IP, 3 = ip2location
DB-IP refreshes monthly and is accurate enough for country-level blocking — it is not good enough for city-level analytics, but that is not what CSF is doing. Switch to it unless you already have a paid MaxMind subscription.
Configure CC_DENY for a global drop list
Edit /etc/csf/csf.conf and set the country codes you want to block. Use ISO 3166-1 alpha-2 codes, comma-separated, no spaces:
sed -i 's/^CC_DENY = .*/CC_DENY = "CN,RU,KP,IR"/' /etc/csf/csf.conf
sed -i 's/^CC_INTERVAL = .*/CC_INTERVAL = "7"/' /etc/csf/csf.conf
csf -r
CC_INTERVAL is how often (in days) CSF re-downloads the country IP database. The default is 7 — leave it. Lower than that wastes bandwidth; higher than 14 means new IP allocations slip through.
After restart, check the ipset is populated:
ipset list cc_deny | head -5
# Name: cc_deny
# Type: hash:net
# Header: family inet hashsize 32768 maxelem 65536
# Size in memory: 1234567
# References: 1
The size in memory is roughly 50MB for a full CN+RU+KP+IR drop — trivial on any modern server.
Lock SSH and webmail to known countries
Use CC_ALLOW_FILTER for the allow-list-on-specific-ports pattern. Add SSH (22), Webmail (2096), and WHM (2087) to the allow ports, then list the countries that can reach those ports:
sed -i 's/^CC_ALLOW_FILTER = .*/CC_ALLOW_FILTER = "US,GB,DE,NL"/' /etc/csf/csf.conf
sed -i 's/^CC_ALLOW_PORTS = .*/CC_ALLOW_PORTS = "22,2087,2096,2083"/' /etc/csf/csf.conf
csf -r
Now port 80 and 25 stay open to the world (minus CC_DENY), but a Chinese IP cannot even open a TCP connection to SSH. This is significantly stronger than fail2ban or cphulkd tuning, because the packet never reaches sshd.
Allow specific IPs through the country block
Country blocks are coarse. You will inevitably need to let specific IPs through — a vendor in a blocked country, a CDN PoP, a monitoring probe. Use csf.allow for whitelists that override CC_DENY:
echo "tcp|in|d=22|s=203.0.113.42 # vendor jumpbox in HK" >> /etc/csf/csf.allow
csf -r
The advanced syntax (tcp|in|d=22|s=...) restricts the allow to a specific protocol, direction, and port — without it, you'd open the entire vendor IP to every service on the box.
Watch what gets blocked before tightening
CSF logs every country drop to /var/log/lfd.log. Tail it for a few hours after enabling CC_DENY to confirm you're not blocking legitimate traffic — particularly transactional email senders and customer support contacts.
grep -i "country code" /var/log/lfd.log | tail -50
You will see entries like (CN/China) detected, blocked port 80 dport=80. If you see traffic from a country you didn't intend to block, narrow the list — country blocking is a coarse tool and a single misconfigured ISP can route through a country you wouldn't expect.
For application-layer protection that complements packet drops, pair this with Imunify360 behind Cloudflare so HTTP traffic is also filtered after Cloudflare hands off the real client IP. The two layers do not overlap — CSF blocks at L3/L4, Imunify360 at L7.
Next steps
- Imunify360 and CSF coexistence rules — what to disable in CSF when Imunify is installed
- WHM cPHulkd tuning — application-layer brute force protection that pairs with country blocking
- Install Imunify360 on cPanel — if you decide L7 inspection is worth the licence