Default-deny egress is good practice on a hosting fleet, and it breaks licensing in a way that is genuinely hard to diagnose: nothing fails at the moment you apply the rule. The panel keeps running on a cached key for hours or days, then a cron job somewhere fails to re-validate and WHM shows a red banner on a server nobody touched.
This is the reference for every outbound connection the products we sell need in order to validate a license. It covers only licensing and the package repos that sit next to it — not mail, DNS, or the panel's own ingress ports. If you need per-product diagnosis rather than a port list, start at checking license status from the command line.
The connection model
Licensing is always agent-initiated and outbound. No vendor connects to your server to
check a key, so you never need an ingress rule for licensing, and you never need to expose a
port to the internet to fix a license error. Anyone telling you to open 2089 in TCP_IN has
the direction backwards.
Three consequences follow from that, and they cause most of the tickets:
- The IP the vendor sees is your egress IP. On a NAT gateway, a floating IP, or an
Elastic IP setup, that is often not the address in
ip addr. Confirm withcurl ifconfig.mebefore you argue with a portal. - Checks are periodic, not continuous. JetBackup revalidates every 48 hours, Plesk re-pulls its key monthly, cPanel re-checks daily via cron. A firewall change on Monday surfaces as a licensing failure on Wednesday.
- Blocked egress and an invalid key look identical from the panel. Both render as "license not valid". Rule out the network first — it takes one command.
Egress reference
| Product | Host | Port | Also needs |
|---|---|---|---|
| cPanel & WHM | verify.cpanel.net | TCP 2089 | httpupdate.cpanel.net on 443 for updates |
| Plesk Obsidian | ka.plesk.com | TCP 443 | Legacy 5224 still accepted, not required |
| LiteSpeed Enterprise | license.litespeedtech.com | TCP 443 | rpms.litespeedtech.com on 443 |
| CloudLinux OS | cln.cloudlinux.com | TCP 443 | repo.cloudlinux.com on 443 |
| KernelCare | cln.cloudlinux.com | TCP 443 | patches.kernelcare.com, repo.cloudlinux.com |
| Imunify360 | imunify-lic.cloudlinux.com | TCP 443 | *.imunify360.com for feeds and signatures |
| JetBackup 5 | check-v3.jetlicense.com | TCP 443 | repo.jetlicense.com on 443 |
| Softaculous | www.softaculous.com | TCP 443 | Mirror hosts on 443 for app packages |
| InterWorx | license.interworx.com | TCP 2443 | Whitelist 207.32.181.150 on default-deny |
| R1Soft | licensing.r1soft.com | TCP 443 | licensing.tuxcare.com on 443 |
| Blesta | account.blesta.com | TCP 443 | Domain-locked, so egress IP does not matter |
Allow by hostname where your firewall supports it. ka.plesk.com resolves round-robin across
several addresses and the CloudLinux endpoints sit behind a CDN, so an allowlist pinned to a
single IP will work until the day it silently doesn't.
The two ports that aren't 443
Nine of the eleven products above are plain outbound HTTPS. The exceptions are cPanel on 2089 and InterWorx on 2443, and between them they account for most licensing-vs-firewall confusion on mixed fleets.
InterWorx runs an XMLRPC handshake over 2443 against license.interworx.com, and on a
default-deny setup you also need the license server's address allowed explicitly. It grants a
24-hour grace period after a failed check, so a blocked 2443 gives you a full day of normal
operation before the panel locks — see fixing InterWorx license errors
for the sync commands.
CSF: one TCP_OUT line
The CSF baseline for cPanel already includes 2089, but not
2443. Edit /etc/csf/csf.conf:
TCP_OUT = "20,21,22,25,53,80,110,113,443,465,587,873,993,995,2087,2089,2443,2703"
csf -r
CSF filters on ports, not hostnames, so 443 plus 2089 plus 2443 covers every product in the table. If you also run the Imunify360 firewall, check that the two are not fighting each other first — running Imunify360 alongside CSF covers the split.
firewalld, UFW, and nftables
Egress rules on firewalld need a direct rule or a policy object; the zone model only
governs ingress:
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --dport 2089 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --dport 2443 -j ACCEPT
firewall-cmd --reload
UFW, on a Plesk-on-Ubuntu box with default-deny outgoing:
ufw allow out 443/tcp
ufw allow out 2089/tcp
ufw allow out 2443/tcp
nftables, added to an existing output chain:
nft add rule inet filter output tcp dport { 443, 2089, 2443 } accept
Cloud security groups and proxies
AWS, GCP, and Hetzner security groups apply on top of whatever runs on the host. An ACCEPT
in CSF means nothing if the security group's egress rules are restricted to 80 and 443 — and
the failure is a silent timeout, not a rejection, which is why it reads as a hung command
rather than a blocked one.
Behind a forward proxy, most agents need to be told about it explicitly rather than
inheriting http_proxy from a shell. KernelCare reads its proxy from
/etc/sysconfig/kcare/kcare.conf, and yum- or dnf-based repo access reads
/etc/yum.conf — exporting the variable in your session fixes your manual test and nothing
that runs from cron.
Verify every endpoint in one pass
Paste this on any server before you file a licensing ticket. It opens a TCP connection to each endpoint and reports reachability without touching a single service:
for target in verify.cpanel.net:2089 ka.plesk.com:443 license.litespeedtech.com:443 \
cln.cloudlinux.com:443 patches.kernelcare.com:443 imunify-lic.cloudlinux.com:443 \
check-v3.jetlicense.com:443 www.softaculous.com:443 license.interworx.com:2443 \
licensing.r1soft.com:443 account.blesta.com:443; do
host=${target%:*}; port=${target#*:}
timeout 5 bash -c "</dev/tcp/$host/$port" 2>/dev/null \
&& echo "OK $target" || echo "BLOCK $target"
done
Expect BLOCK on products you don't run — the hostname still resolves, but nothing is
listening for you to care about. What matters is that every product actually installed on
the box returns OK. A BLOCK on a product you do run is your answer, and no amount of
re-issuing keys will change it.
If a check resolves but times out on a host with open egress, test DNS separately with
dig +short verify.cpanel.net. Servers using a local resolver that filters unknown domains
produce exactly this pattern.
When the ports are open and it still fails
At that point it is a key problem, not a network one. The usual causes, in order of frequency: the license is bound to the old address after a migration (see moving a cPanel license to a new server IP), the egress IP differs from the bound IP on a NAT'd cloud instance, or the key genuinely lapsed. Per-product triage lives in the licensing articles for Plesk, LiteSpeed, CloudLinux, KernelCare, JetBackup, and Softaculous. If a license you bought from us looks wrong in the portal, contact us with the server's egress IP rather than re-issuing keys and hoping.
What port does cPanel use to check its license?+
Do I need to open any inbound ports for license validation?+
Why did my license break days after I changed the firewall?+
Can I allowlist license servers by IP instead of hostname?+
How do I test license connectivity without restarting services?+
Does a blocked license check suspend hosting accounts?+
Next steps
- Confirm the key itself with license status commands for every product.
- Build the firewall baseline properly: install and tune CSF on cPanel.
- Backups have their own port model — see the R1Soft port and firewall reference.