@@PRODUCT@@

The firewall of a server

Every CoreCP machine has one firewall manager. By default that is CoreCP itself — no CSF, no ufw beside it — and that is a deliberate choice: two programs pulling at the same rules produce an outcome nobody can predict. Everything you are u

Written for: Administrator

Every CoreCP machine has one firewall manager. By default that is CoreCP itself — no CSF, no ufw beside it — and that is a deliberate choice: two programs pulling at the same rules produce an outcome nobody can predict. Everything you are used to from CSF is on this screen.

A server can in principle be handed to a different firewall manager; CoreCP then withdraws completely and this screen becomes read-only. For cPGuard such a hand-over is refused, with the reason — see Changing the firewall manager at the bottom.

Servers → the server → Firewall.

What the screen shows

Top to bottom, in the order you usually need it:

  • Blocked right now — addresses with a countdown, each saying where the block came from: the name of the watcher that set it, or "by hand". This is the list you look at when somebody rings up saying "I can't get in any more".
  • Permanent lists — addresses and ranges that are always accepted or always dropped.
  • Built-in protections — three defences that run in the kernel itself: SYN flood, connections per address, port scans.
  • Blocked countries — with, per country, how many address ranges are actually loaded.
  • Log watchers — the processes that read the server's own logs and block on their own, with what each one reads, whether it is running, and what it has caught.
  • Open ports — the ports this server's roles and addons open, as the active firewall manager holds them. A port with "from" after it is open only to those addresses.
  • Generated ruleset — under Advanced, exactly what the machine loaded.

Banning somebody for a while

Click Deny address, type the address, pick a lifetime (15 minutes, 1 hour, 24 hours, 7 days or permanent) and write down why. In six months that reason is the only explanation anybody has.

A temporary ban expires by itself. Not because a job is waiting on a clock, but because the kernel releases the rule when the time is up — nothing has to be running, and it still works if the server was reconfigured in the meantime.

On the command line it is the same thing:

root@stck1:~# corectl firewall deny 203.0.113.7 --ttl 15m --comment "six bad IMAP logins"
[corecp] 203.0.113.7 denied for 15m

root@stck1:~# corectl firewall list --temp
ADDRESS       ACTION KIND       EXPIRES IN   COMMENT
203.0.113.7   deny   temporary  14m56s       six bad IMAP logins

The watchers: blocking without you looking

The server reads its own logs. Anyone who tries a wrong password too often — on mail, on FTP, on SSH, on the panel — is blocked automatically. The default is five failed attempts within ten minutes, then an hour out.

Those blocks land in the same list as the ones you set yourself. There is no "system list" and "your list": there is one answer to who is blocked right now, and the Origin column says who put them there.

Which watchers run depends on what the server does:

WatcherRuns on a server withWatches
sshdalwaysSSH sign-ins
dovecotthe mail roleIMAP, POP3 and managesieve
postfix and postfix-saslthe mail rolethe mail server itself
rspamdthe mail rolewhat the spam filter rejects
proftpdthe ftp roleFTP sign-ins
corecp-panela machine running the panelrefused sign-ins to the panel

On the command line:

root@stck1:~# corectl firewall watch
watchers    running
policy      5 failures in 10m, then banned for 1h
banned      1 address right now

JAIL             STATE      FAILED     BANNED     WATCHES
sshd             watching   0          0          ssh, sshd
dovecot          watching   3          1          dovecot
proftpd          watching   0          0          /var/log/proftpd/proftpd.log
Careful: a block applies to everything from that address, not only to the service where it went wrong. An office that gets its mail password wrong five times loses the website and SSH too. That is what the permanent allow list below is for: an allowed address is never blocked.

Webmail counts too now

Until recently there was one gap in this story, and it sat exactly where most customers read their mail. Webmail runs on the server itself, so when somebody sat there guessing a mailbox password, the mail server saw its own machine as the visitor — and its own machine is never blocked, because that would take every website on the server down at once. Guessing through a mail program was stopped after five tries; the same guessing through webmail could go on for ever.

That is closed. The webmail now passes the visitor's real address to the mail server, and the dovecot watcher blocks that address — same threshold, same list, same button to lift it. There is nothing to switch on.

Note, and this is the other side of it: a customer who mistypes their webmail password five times blocks their own address for everything on that server — mail, website and SSH. Behind an office or mobile network they share that address with other people. Lifting such a block is one action and takes a second; it is right below.

Lifting a block

Click Lift ban on the row and confirm. That works for both kinds: it does not matter whether the address was banned temporarily or permanently, because that is not something you should have to know to let somebody back in.

If the block came from a watcher, that watcher is told as well. It sounds like a detail and is not: without it the watcher still remembers the earlier attempts, so the next failure is immediately the fifth. You would lift the block and watch it come back within the minute.

# a block a watcher set
root@stck1:~# corectl firewall unban 198.51.100.7 --jail dovecot
[corecp] 198.51.100.7 is no longer banned (dovecot)

# an address that was never banned says so
root@stck1:~# corectl firewall unban 203.0.113.222
corectl: 203.0.113.222 is not banned on this node

# a permanent rule comes off the list
root@stck1:~# corectl firewall remove 203.0.113.7
[corecp] 203.0.113.7 removed from the firewall's lists

Letting customers unblock themselves

By default every lift is yours. It does not have to be: per server you can switch the self-service on, and then a customer who locked themselves out can release their own address without a ticket.

# root@stck1:~# corectl node set firewall.watch.selfservice_unblock on
# or, in node.yaml:
firewall:
    watch:
        selfservice_unblock: "on"

Off until you switch it on — the opposite way round from every other setting here, and deliberately so: this is a door out of a defence, and something like that is switched on by somebody or nobody decided it.

What a customer can actually do with it is far less than what you can:

  • only their own address, and only if they open the link from the connection that is blocked;
  • only on the servers their own hosting accounts live on;
  • only a block a watcher set. An address you put on the permanent list, or dropped for a while with firewall deny --ttl, is refused — that is a person's decision and it stays yours;
  • three times a day. The fourth is refused and wakes an administrator: an address that earns a block three times a day has an out-of-date or a stolen password behind it.

The customer never sees which machine they are on, which watcher set the block, or how many servers were asked. Every lift is in the security log, with the address and the login beside it.

The explanation for the customer is in Your internet address is blocked — how to get back in.

Reading back who has been there

Every block and every lift is in the security log. Click Events in the log beside the watchers, or go to Logs and pick the security source. Sign-in attempts, the watchers' blocks and the panel's own actions are there together — one column instead of three files.

root@stck1:~# corectl logs tail security --lines 20 --grep 198.51.100.7
2026-08-13 03:55:11Z warning fail2ban: [dovecot] Ban 198.51.100.7
2026-08-13 03:55:23Z warning fail2ban: [dovecot] Unban 198.51.100.7
2026-08-13 03:55:23Z notice  unbanned 198.51.100.7 (dovecot)

Always allowing an address

Allow address puts an address or a range on the permanent list. An allowed address is accepted before anything looks at the drops: a blocked country, a rate limit and a port-scan ban all leave it alone. Use it for your own office, your monitoring and your backup server.

Some entries CoreCP puts there itself. They carry the automatic label and cannot be removed by hand — they are worked out again on every apply. The best-known case is the mail gateway: if a PMG stands in front of this server, its addresses are allowlisted automatically, because all of the world's mail arrives from that machine and a limit that treats it as one troublesome visitor throws your customers' post away.

The built-in protections

ProtectionDefaultWhat it does
SYN flood60 per second, burst 120bounds new connections
Connections per address100nobody holds more at once
Port scans20 dropped packets per minute → 15-minute banrattling doorknobs locks you out

The defaults are on and generously chosen: a firewall that throws away a busy customer's traffic is a bigger outage than the attack it prevented. Raise, lower or switch them off per server:

root@stck1:~# corectl firewall protect --connlimit 250 --portscan-ban 1h
root@stck1:~# corectl firewall protect --synflood off

The database port of a database server

If this machine runs databases for websites on another server, an extra line appears in the list of open ports: 3306/tcp database (1 peer machine). That port is open to exactly that other machine and to nobody else — not to the internet.

There is nothing to do for it. The panel opens it when the first account with such a split placement is created, and closes it again as soon as the link between the two machines is removed.

Blocking a country

Block country asks for a two-letter country code. CoreCP fetches that country's address ranges from ipdeny.com — free, refreshed daily, IPv4 as well as IPv6 — and puts them in the firewall.

Mind the difference between on the list and blocked: a country is on the list the moment you add it, but nothing is dropped until the ranges have arrived. The screen says which of the two each country is. A daily task refreshes the zones; Fetch country zones now does it immediately.

root@stck1:~# corectl firewall country add cn
[corecp] country cn added to the block list
[corecp] country cn: 8221 IPv4 ranges, 2145 IPv6 ranges

root@stck1:~# corectl firewall geoip sync
COUNTRY  IPV4       IPV6       RESULT
cn       8221       2145       synced 2026-08-13T04:11:07Z

Blocking a country affects everybody coming from it, including the visitors your customer may well want. An address on the allow list still gets through.

What happens to the rules during maintenance

When CoreCP writes the firewall again — after a role change, after installing an addon, or simply with Apply — the temporary bans are carried over, with the time they have left. So you never have to choose between "update the server" and "keep this afternoon's bans".

What a reboot does clear is the temporary bans: they live in the kernel and not on disk. The permanent lists and the blocked countries stay.

When something goes wrong

  • A customer cannot get in. Look for the address under Temporary bans. If it is there, click Lift; then put it on the permanent allow list if it keeps happening.
  • The mail gateway is not listed. Check that the gateway's hostname resolves. If it does not, CoreCP skips the entry and says so in the task log.
  • A country is not blocking. Look at the Ranges column. If it says 0 the zone has not been fetched yet — use Fetch country zones now.

Changing the firewall manager

If a server already runs another firewall you want to keep, you do not have to choose between that program and CoreCP: you hand the firewall over, in one act, and there is no moment in which the machine has no firewall.

cPGuard cannot take it, and CoreCP refuses the hand-over. Measured on 22 August 2026: cPGuard's port filter is one flat list of allowed ports with no way to say "this port, but only from this address". Every CoreCP server has at least one such port — the agent port is open to the panel and to nobody else — so a hand-over would either throw that restriction away or shut the panel out. See cPGuard: what it can and cannot do below.

What a hand-over does, in this order and as one act on the server:

  1. The new manager takes the whole model first: the ports the roles and addons open, the permanent lists, the countries and the protections.
  2. Then CoreCP withdraws. The CoreCP table leaves the kernel, the file that loads it at boot is replaced by one that loads nothing, and the daily task that fetches country ranges stops.
  3. The watcher moves with it: fail2ban stops and the new manager's own watcher starts. Exactly one of them ever runs.

Step 2 is the one that hurts later if it is skipped. A CoreCP ruleset begins by emptying the kernel's tables; leave that file in the boot path and the new manager's firewall is gone after the next reboot — months later, with nothing in any log connecting the two.

How to do it:

  1. Go to Servers → the server → Firewall.
  2. Click More actions → Change firewall manager at the top right.
  3. Choose the manager and read the yellow block: it says what is about to happen.

If the manager you chose cannot carry this server's port model, you get a refusal rather than half a hand-over, with the ports that are the problem:

root@stck1:~# corectl firewall provider set cpguard
corectl: cpguard cannot carry this node's port model: 22/tcp from
185.117.226.120, … and 16 more are open only to named sources, and this backend
has one flat list of ports for every source — enforcing it would either put
those ports on the internet or stop the panel reaching this node

Nothing changes: the server stays on nftables, the rules stay in the kernel and fail2ban keeps reading the logs.

cPGuard: what it can and cannot do

cPGuard stays perfectly usable on a CoreCP server — as an addon, beside CoreCP's own firewall. Its WAF, its malware scanner and its reputation feed do their work and touch nothing of the packet filter. What cPGuard does not become is the manager of the ports:

  • its port filter knows only a general list of ports; a port that should be open to a handful of addresses does not exist there;
  • an address on its whitelist may pass its automatic blocks (DoS, reputation, brute force) — but that does not open a port the port filter is holding shut. That is exactly what the previous version of CoreCP relied on, and it was not true;
  • so CoreCP never switches that port filter on, and switches it back off if somebody turns it on by hand. On 22 August one such switch made a test server unreachable from every address, over IPv4 and IPv6 alike.

CoreCP still writes rows on cPGuard's whitelist for the panel and the jumphost, because being exempt from those automatic blocks is genuinely useful. The screen shows them as an exemption, not as an open port.

What a manager cannot do

Under Built-in protections a handed-over server carries a short list of what the active manager cannot express. For cPGuard there are four:

  • no port that is open only to named addresses — the reason the hand-over is refused;
  • no limit on concurrent connections per source (cPGuard sets one per destination port, which is a different policy);
  • no port-scan detection (cPGuard blocks on the reputation of an address);
  • a lifetime counts in whole minutes, so a thirty-second ban becomes a one-minute ban.

That list is there so a screen never promises three defences of which one exists.

Changing back

Choose nftables and CoreCP renders the ruleset itself again. It is byte-for-byte the one from before the hand-over: the model was in node.yaml all along and does not change when the machinery does.

root@stck1:~# corectl firewall provider
root@stck1:~# corectl firewall provider set nftables

The SSH opening follows the server

The rule that lets SSH through is no longer a fixed port number. It comes from the same setting the SSH server does, so moving the port moves the hole in the firewall with it — and during a port change both ports are open, for exactly as long as the confirmation window lasts. That way the server can never end up listening on a port the firewall lets nothing through.

The log watcher (fail2ban) reads the same number, so failed logins on the new port are counted just the same. See Server settings and services.

Who may reach SSH (round 3)

Since round 3 the rule for port 22 also carries a list of sources. While that list is empty, port 22 is open to the whole internet — exactly as it always was. Put one address on it and only that address reaches the SSH server; everything else is dropped before the daemon ever sees it.

Why that was needed, in one number: on 19 August 2026 the panel server counted 709 failed logins in one hour. That is not only noise — the SSH server's own queue filled up and threw our own automation out of it.

The list belongs to the server rather than to the platform: every machine has its own visitors. From that server's terminal:

corectl sshd allow list
corectl sshd allow add --address 203.0.113.7 --comment "office"
corectl sshd allow remove --address 203.0.113.7

You cannot lock yourself out. A change that would leave the address you are working from off the list is refused, and the refusal names that address. If you want it anyway — because you have another way in — you say so with --force.

And there is always a way back. Put --window 10m after a change that takes access away and the server puts the previous list back on its own unless you confirm within that window. A connection that is already open is never dropped by such a change.

The screen for this comes in round 4; today it is a terminal action.

The bar at the top

This screen is not one of the server’s own tabs, but the server bar is at the top of it anyway — with nothing selected. So after unbanning an address you can go straight on to the logs or to Manage instead of having to go back to the dashboard first. The back link to the server is unchanged.

See Managing a server for the seven sections and what sits behind each.