3.9.3
Mail did not work at all on AlmaLinux, Rocky or any other RHEL-family server. This release repairs it in place. Update.
Mail could not be sent or received
The Postfix configuration this product generates asked for its four lookup
tables as hash: — Berkeley DB. That is an optional Postfix plugin and the
RHEL family ships without it: on AlmaLinux postconf -m lists lmdb and no
hash, and default_database_type is lmdb. postmap with no prefix builds
the default type, so the compiled maps on disk were .lmdb files while
main.cf asked for hash: ones. Postfix logged, for every message:
warning: hash:/etc/hitechcloud/mail/valias is unavailable.
unsupported dictionary type: hash
warning: virtual_alias_maps map lookup problem for … -- message not accepted
and answered every authenticated RCPT TO with 451 4.3.0 …: Temporary lookup failure. Not one message could be sent or received. The sender-login
map was worse: it was compiled as hash: explicitly, which is fatal, so it
was never built at all and the check that stops one mailbox sending as another
had nothing to consult.
The type now comes from Postfix itself. On Debian and Ubuntu, where hash is
the default, nothing changes.
This release repairs servers that are already running. A new binary does not rewrite a config file that is already on disk, so the update rewrites the four settings, rebuilds the compiled maps and reloads Postfix — and says so if it could not.
Security
-
An SSH login never entered the account jail. The login shell decided whether to enter the jail by testing for a file in
/etc/sudoers.d, which isdrwxr-x---and owned by root — and it ran that test as the account. The answer was therefore false for every account, including every account that had the rule. An account given SSH access stood on the shared filesystem with an unrestricted shell: it could list/home, read/etc/passwdand the panel's own logs, and leave the restricted shell in one step. It could not read another account's files or any credential, which is the only reason this is not worse. The check now askssudo, which owns the answer and is setuid. -
Two-factor authentication could be turned off without a credential. The disable form posted only its CSRF token, and the handler accepted that and cleared the stored secret. Email OTP on the same page had always required the password. It now does too — but only while 2FA is actually on, so abandoning a half-finished setup still works.
-
A custom certificate upload wrote the private key into the web root. The panel wrote the PEM pair into the account's own document root before handing the paths to the CLI, so for the duration of that call the key was fetchable over HTTPS at a guessable URL. It now goes to a private temporary directory outside every document root. The same code named a container path that does not exist on a native server, so the upload also installed nothing while reporting success.
Fixed
-
The per-account memcached never started. The unit template ships with the product and the installer copies it into the templates directory, but nothing ever installed it into systemd — so enabling memcached for an account ran against a unit that does not exist and the customer was told
Unit hitechcloud-memcached@<account>.service could not be found. The update installs the template and starts memcached for every account that had already asked for it. -
Every per-domain firewall action was a no-op that reported success. The panel handed the CLI a bare subcommand —
hitechcloudcli mode example.com detect— which is not a command. The CLI answeredCommand 'mode' not found, exited 127, and the panel showed that as the outcome of changing the firewall. Mode, rule exceptions, both IP lists and both challenge controls. Two of those controls also read a field name the form does not send, so the challenge toggle saved the opposite of what was chosen and under-attack mode could not be turned on at all. -
The IP blocker blocked nobody. It stored the list correctly and wrote it in Caddy's syntax, on a server whose front end is nginx.
-
Reverse DNS was reported from the wrong place. The Deliverability page said this server's reverse record was correct on a server whose address has no PTR record at all: Go's resolver answers a reverse lookup out of
/etc/hosts, and a hosting server's hosts file names itself. The page now asks public DNS, and says "could not be checked" rather than guessing when it cannot. -
/emails/lognever answered. It read the last 64 MiB of the mail log and asked the operating system for the time zone once per line — half a million processes for one page, fourteen minutes of forking before any parsing. The answer is now kept for a minute. -
/account/activityanswered 500. The renderer computed the page size and dropped it, and the template multiplies by it. -
The website's "back up now" could never run. It called
podman execon a server with no containers. -
MongoDB pages ran three
mongoshshells per request, a created MongoDB database did not exist afterwards, and every MongoDB size read0 B. -
PostgreSQL grants silently failed. Three statements were sent through a prepared statement, and PostgreSQL allows one.
-
Two SSL pages listed no domains for anybody, because the query named columns the table does not have.
-
Search found nothing. Thirteen of fourteen search types answered 503: the engine handed them back to Go, and Go had registered a placeholder that answers 503 instead of the handler that was sitting there intact.
-
File Manager had no right-click menu. It had never been written; every action was a toolbar button. There is one now, built from those same buttons.
-
Usage timestamps read seven hours old. Samples were stamped in UTC and printed verbatim.
-
A plan's
bandwidthnow means one thing: a monthly transfer allowance in GB. Two commands had documented it as a port speed in Mbit/s while the usage reader treated it as gigabytes per month. Nothing set a port speed from it on any server, so no account's behaviour changes.
Added
- Edge Side Includes per site, off by default
(
hitechcloudcli native-varnish esi <domain> on). - Bot management on the firewall: crawlers verified against the operators' own published address ranges or forward-confirmed reverse DNS, a forged crawler challenged, and a request-shape fingerprint for the rest. Real JA3/JA4 is not included and cannot be on the distribution's nginx — the reason is written down in the plan.
- Anomaly detection, runaway-process kill and a plan recommendation
(
hitechcloudcli native-limits anomaly|runaway|recommend). Killing is off until an operator turns it on. - Slow database queries lined up against slow PHP requests on the X-Ray page, with what a time-window match does and does not prove stated on the page itself.
- A one-time link into the administrator panel
(
hitechcloudcli admin login <username>), five minutes and single use. 2083 has had the customer-side equivalent for years; 2087 had nothing, which is why it had never been tested end to end.
Backups
On an Enterprise licence the destination, the schedule and the retention are now the administrator's on 2087, and 2083 keeps taking, downloading and restoring backups. A Community licence keeps all of it, because there is no panel above it. The withheld pages refuse with a reason rather than quietly disappearing from the menu.