Journal des modifications
Toutes les versions de l'agent InfraFence, de la plus récente à la plus ancienne : nouveautés, corrections et changements de sécurité, tirés du journal des modifications de l'agent.
Dernière mise à jour:
Les notes de version de l'agent, de la plus récente à la plus ancienne, telles que publiées dans le dépôt de l'agent. Pour mettre à jour, voir Mettre à jour l'agent.
v1.0.32
- feat: protection is switched off after 24 hours of explicit refusal. When every answer of the dashboard for 24 hours in a row is a refusal (401, or 403 on the agent endpoints such as
{"error":"suspended"}; any success resets the clock, which is kept in the state file across restarts), the account is suspended or the subscription ended and the agent switches its protection off cleanly: its own iptables/ip6tables chains, jumps and ipsets go (bans, allow list, country blocks, threat feeds, closed ports, egress blocks), its ModSecurity rules (virtual patches included) and user-agent blocking are taken out of the web server, the realtime malware watcher stops and the watchers only monitor. Other tools' rules are never touched and no table is flushed. SSH is checked afterwards with the same verification as closing a port. The agent keeps running, asks the dashboard every 30 minutes, and switches protection back on at the first successful sync. A login notice is written to/etc/motd.d/infrafencewhere the distribution uses/etc/motd.d("InfraFence no longer protects this server: the account is suspended or the subscription ended. Reactivate it at https://infrafence.com/billing", also logged once as a warning) and removed when protection is back. An unreachable dashboard (network errors, timeouts, 5xx, DNS) is never a refusal: protection then stays on indefinitely. - panel status: new fields
protection(active,refused,disabled),refused_sinceanddisabled_at(timestamps ornull), seedocs/panel-json.md; the plugins can show a red banner ondisabled. - fix: protection survives a restart while the dashboard is unreachable or refuses the agent. The allow list, the blocked countries, monitor mode and the brute-force settings of the last successful sync, and every active ban with its expiry, are kept in
/var/lib/infrafence/protection-state.json(0600, replaced atomically). At startup the bans and the allow list are put back before the firewall is set up (without ipset every ban used to be wiped by a restart), and the allow list, monitor mode and country blocks before any watcher runs, so a restart during an outage can no longer ban an address the customer allowed. A corrupt file is set aside (.corrupt) and the agent starts without it. The first successful sync replaces all of it with the dashboard's state. - fix: bans expire on time without the dashboard. Bans used to expire only at a successful sync, so a refused agent never lifted one. They are now lifted on the server every 30 seconds at their expiry (the dashboard's
expires_at; 24 hours for the agent's own detections until the dashboard sends one), from the ipset or the chain and from ModSecurity's list. A sync no longer re-applies a ban that already expired. - fix: the ban set never fills up silently. At most 65,000 bans with ipset (the set holds 65,536, so an add can no longer fail) and 500 without (the capacity the heartbeat reports). Past that the oldest bans make room and one
ban_capacity_reachedwarning (at most every 10 minutes) says how many; a sync listing more bans than the capacity is applied up to it. - fix: bans made while the dashboard can't be told are reported later, not lost. Bans the agent makes while the dashboard is unreachable or refuses it wait in the state file and are reported, oldest first, at the next successful sync; that sync's cleanup spares them until the dashboard lists them (or for 10 minutes after the report, after which the dashboard's state wins). A ban that expired or was lifted meanwhile is dropped instead of reported. The same now protects a ban reported moments before a sync that didn't list it yet.
- fix: backoff when the dashboard refuses the agent. After a 401 or 403 the heartbeat, sync, events and the websocket used to retry at fixed intervals (every minute, every 30 seconds). Now nothing is sent until a shared backoff ends: 1 minute, doubling up to 30 minutes, with jitter; the first accepted request resets it.
403 {"error":"suspended"}(organization suspended) is logged once as a warning and asked again every 30 minutes. Queued events wait for the backoff and are kept. A refusal does not remove local protection (bans, allow list, country blocks, closed ports), for a 401 as for a 403, until it has lasted 24 hours (see above). A 403 starts the backoff only on the agent endpoints (heartbeat, sync, events, bans): elsewhere it may only refuse a feature. The websocket backs off on its own when its channel auth is refused. - tests: the distribution matrix also switches protection off after a (shortened, test builds only) refusal: no InfraFence chain or set left, another tool's chain and set untouched, SSH reachable, the login notice present, then protection back and the notice gone once the dashboard accepts the agent. It also runs the dashboard refusing the agent (403 suspended) across a restart with the chains emptied: the allow list and the country block (from a generated one-network GeoIP database) come back, an allowed address is never banned, a ban expires locally, the refusal is logged once with only a handful of requests, and a ban made meanwhile is reported once the dashboard answers. Uninstall removes the new state file.
- feat: hosting panel commands for the cPanel/WHM and Plesk plugins.
infrafence-agent panel <command> --jsonanswers the panel plugins with one JSON object (ok, or an error code and a message; exit status 0 only when ok):status(version, last heartbeat, connected, agent id, plan and AutoMode when the dashboard sends them, the server's dashboard link),bans,unban <ip>,allow <ip>,allowlist,disallow <ip>,findings,events,coexistence,sitesandscan <document root>. The command asks the running agent over a local Unix socket,/run/infrafence/panel.sock: created by the agent in a 0700 directory with mode 0600, only root may connect (checked with the kernel's peer credentials), removed on shutdown, nothing listens on the network. Without a running agentstatus,coexistenceandsitesstill answer, read-only, and every answer says"agent_running": false. Addresses (single IPv4/IPv6 only; unspecified, broadcast and multicast refused), paths, the panel user and notes are validated by the command and again by the agent; text taken from logs and file names is cleaned of control characters and capped (the plugins still escape everything they show). A change that can't be saved is refused and nothing is changed. - Unban, allow and disallow from the panel go through the same firewall and allow-list code as the dashboard's bans and allow list. Each is logged and reported to the dashboard as an event (
panel_unban,panel_allow,panel_disallow,panel_scan) withsource: paneland the panel user; when the dashboard can't be reached the event waits in an outbox and is sent after the next sync. An unban from the panel lifts the ban on this server only (scope: server), whatever its source (local, network, AutoMode, manual): the ban stays in the dashboard and on the organization's other servers, and thepanel_unbanevent only records the local lift (no ban ids, nothing for the dashboard to delete). The lifted ban is left out of this server's syncs until the dashboard stops sending it or for at most 30 days, after which a ban the dashboard still sends is enforced again; a new detection of the address bans it again. Loopback addresses are refused; allowing one of the server's own addresses works but the reply flags it (own_address). Addresses allowed from the panel are added to the dashboard's allow list on this server until they are disallowed; entries of the organization's allow list can only be removed in the dashboard. Both are kept in/var/lib/infrafence/panel-state.json(0600), written only once the panel changes something. - Coexistence report.
panel coexistencelists the other security tools found, read-only: CSF/lfd, Imunify360/ImunifyAV, cPHulk, fail2ban, CrowdSec, the Plesk Firewall extension, BitNinja, Monarx, firewalld, ufw, and ModSecurity with its vendors and rule sets (cPanel vendors, Plesk WAF rule set, OWASP CRS, Comodo, Imunify, Atomicorp), with what InfraFence does next to each. The mode iscoexistwhen another active tool writes firewall rules (InfraFence keeps to its own chains and never edits theirs),primaryotherwise. - Sites.
panel siteslists cPanel accounts and domains (/var/cpanel/users, userdata,/etc/trueuserdomains), Plesk domains (a read-only query of the Plesk database, orplesk bin site --list) and DirectAdmin domains, with document roots and whether the malware scan covers them.panel scanqueues a malware scan of one site's document root, nothing else. After resolving symlinks it must sit inside the account's home (or/var/www/vhosts/<domain>on Plesk) and be owned by the account's uid; a document root its owner pointed elsewhere (a symlink to/,/etc, another account) is refused (not_scannable, andsites[].scannableis false). The directory is opened once without following a symlink and checked again by device and inode before the walk. The scan follows no symlink (files or directories; YARA with-N), reads nothing but the files under the root, runs no server-wide check and leaves the server's security score alone. Itsmalware_scan_startedevent carriesscope: panel. - JSON reference for the plugins:
docs/panel-json.mdlists every field of every reply (type, values, whether always present) with a real example per command; the same examples are intestdata/panel/. Both are produced by a test that runs the CLI against the real socket and fails when the output changes without them. Every documented key is always present; an unknown value isnull. - Only on hosting panel servers. The socket, its goroutine and every panel hook (copies of the sync, recent events and findings, lifted bans, the panel allow list, the outbox) run only when cPanel/WHM or Plesk is detected, or with
"panel": truein/etc/infrafence/config.json. On every other server nothing of it runs, even if a panel state file is left on disk. - Nothing changes for servers whose panel never uses these commands. Uninstall removes the panel state file and the socket.
- tests: the distribution matrix also runs the panel commands (socket mode, non-root refused, unban not reapplied by the sync or after a restart, allow/disallow, validation, answers without the agent).
- perf: events reach the dashboard in batches. Urgent events (critical severity, bans and brute force, malware and quarantine, high-severity web attacks, failed or rolled-back changes, updates) are still sent at once, at most one request per second during a burst; all others are sent every 5 seconds or 100 at a time in one request. Events are never merged: each keeps its own type, details and time. About 90% fewer requests at 2 events per second, 99% at 20. Blocking on the server never waits for delivery.
- fix: no events lost while the dashboard is unreachable. Failed batches are retried in order with backoff (honouring Retry-After); a batch the dashboard keeps refusing is split so one bad event can't block the others. On shutdown and before an update the queue is flushed, and urgent events that still can't be sent are kept in the state directory and sent at the next start.
- security: bounded memory under an event flood. At most 5,000 queued events and a byte budget, with long values (URLs, user agents) truncated; when full, the oldest non-urgent events are dropped and one
event_queue_overflowwarning reports how many.
v1.0.31
- feat: closing exposed database and admin ports. The dashboard can ask the agent to close a port such as MySQL, PostgreSQL, Redis, MongoDB, Elasticsearch, Memcached or the Docker API to public addresses (its own
INFRAFENCE-PORTSchain, mirrored to IPv6 with ip6tables; loopback and allowlisted addresses keep access). The agent closes only ports on a fixed list of database, cache and admin services and always refuses SSH ports (including ports set byssh.socketand the ports of live SSH sessions), 80 and 443, and ports with a live public connection. Without ip6tables it says the port is still reachable over IPv6. Closed ports are kept in/var/lib/infrafence/firewall-state.jsonand stay closed across restarts and while the dashboard is unreachable. - feat: blocking outbound traffic to a threat. The agent can block outbound connections to an IPv4 address (
INFRAFENCE-EGRESSchain, ipsetinfrafence-egress), but only to an address it flagged itself as a threat in the last 24 hours. It always refuses the dashboard, DNS resolvers, addresses that logged in over SSH in the last 30 days, addresses with a live connection to the server and allowlisted addresses. - feat: every change is checked, and undone if it breaks something. Before closing a port, blocking outbound traffic, applying a hardening fix or a virtual patch, the agent records which SSH ports accept connections and how the configured sites answer (HTTP and HTTPS); afterwards it checks again for up to 20 seconds and undoes the change by itself if SSH or a site stopped answering. The result is sent with the change.
- feat: virtual patches for exploited vulnerabilities (Apache with ModSecurity). A small built-in set of narrow ModSecurity rules for actively exploited web vulnerabilities (path traversal in Apache 2.4.49/50, Log4Shell lookups, Confluence OGNL, Struts content-type, Joomla API, PHP-CGI argument injection) can be applied on request; the agent tests the configuration, reloads gracefully, checks that the rule actually blocks (it refuses when ModSecurity is in DetectionOnly) and rolls back on any failure. Rules go only between the agent's markers in
infrafence-dynamic.conf. - feat: restoring a quarantined file. A file quarantined by mistake can be put back on request, with its original owner and mode (execute bits removed), only inside a web root and never over an existing file.
- feat: SSH logins carry their address and country.
ssh_sessionevents now set the source IP, and events with a public source IP carry its country from the local GeoLite2 database. The heartbeat reports the SSH and web ports. - fix: uninstall stops the agent before cleaning up, so the firewall guard can no longer put chains back while they are being removed.
v1.0.30
- fix: Kubernetes clusters can register. The Helm chart passed its key to the agent as a single-use install token, so only the first node could ever register, and the container's cluster registration called an
api.subdomain that isn't the dashboard. The DaemonSet now passes the key as a cluster key (INFRAFENCE_API_KEY, created in the dashboard under Settings → Kubernetes) and registration goes to the dashboard URL itself (override withINFRAFENCE_API_URL). Every node registers as its own server; a node that registers again (rebuilt node, wiped/etc/infrafence) keeps its server and gets a new token. Nothing changes for servers installed withinstall.shor Docker with an install token.
v1.0.29
- feat: automatic updates only for those who choose them. The agent installs a new version by itself only when the dashboard setting "Agent updates" is "Install automatically"; with no choice made, "Notify only" or anything else it only reports the new version. The dashboard now defaults to "Notify only" and sends the new version only to organizations that chose automatic updates.
- security: only signed InfraFence releases are installed. Updates are downloaded only from the official GitHub release of that version (the address sent by the dashboard is ignored, the unversioned infrafence.com mirror is gone) and installed only if the cosign release signature matches the InfraFence public key built into the agent. The signature is checked on the downloaded bytes, and those same bytes are tested and installed. Download sizes are capped.
- security: the recovery script verifies what it installs. When the agent binary is damaged at startup, the recovery script used to download the latest release and install it with an optional checksum and no signature check, whatever the update setting. It now requires both the checksum and the signature (checked with openssl) and downloads nothing when it can't verify. Running agents rewrite the script with this version.
- security: Kubernetes updates use the signed image. The update used to restart the pods on the DaemonSet's image tag, which the Helm chart pins to the installed version, so nothing was actually updated. The agent now resolves the new version's image, checks its cosign signature for that exact digest, and pins the agent container to that digest. A DaemonSet using another registry (a private mirror) is left alone and the new version is only reported.
- security: rollback state is root-only. The crash counter that triggers a rollback and the recovery marker moved from /tmp, where any local user could write them, to /var/lib/infrafence (0700).
v1.0.28
- fix: the agent follows the dashboard when it moves to another server. The agent kept its HTTPS connection to the dashboard open and reused it for every request; with a heartbeat every minute plus events and syncs it never stayed idle long enough to close, so the dashboard's address was never looked up again. When infrafence.com moved to a new server, the demo agent kept talking to the old one and, once that was switched off, got "503: no available server" for every request and showed as offline until it was restarted. Connections to the dashboard are now renewed every 5 minutes, closed after 30 seconds of inactivity, and closed right after a network error or a 502/503/504, so the next request connects again and finds the new address — within a minute in that case. Nothing changes on the host.
v1.0.27
- feat: distributed port scans. On the demo server, v1.0.26 reported no scan: they came spread over many addresses of one network, each trying only 2–6 random ports, so no single address stood out. The agent now also reports a network (/24 for IPv4, /64 for IPv6) from which at least 3 addresses tried 30 or more distinct ports within 10 minutes, with the network, how many addresses and how many ports (one report per network per 30 minutes). Replaying 3 minutes of the demo's real traffic: two such scans (29 and 14 addresses), no false positive. Banning, when turned on, still applies to single scanning addresses only, never to a whole network.
- change: slow scans. One address trying 15 or more distinct ports is now a scan within 10 minutes instead of 1, catching slow scanners; normal clients never use more than two or three ports.
v1.0.26
- fix: port scans are actually detected. The detector looked at the connection table once a minute for half-open connections to listening ports. Scans mostly hit closed ports, which leave no trace there, and a half-open connection lasts milliseconds: on a server with a handful of open ports it could never reach its threshold of 15, and the demo server — scanned all day — never reported one. The agent now sees every incoming connection attempt (TCP SYN, IPv4 and IPv6) through a filter run in the kernel, read-only like the DNS inspection, and reports an address that tries 15 or more ports, open or closed, within 60 seconds (one report per address per 10 minutes; at most 5,000 attempts analyzed per second). Reserved, own, protected and whitelisted addresses are never reported. Port scans also raise the risk of open SSH sessions (Sigma correlation). Detection is on by default and can be turned off in the dashboard; banning scanners is off by default (monitoring services and search engines such as Shodan scan too) and can be turned on. Where packet capture isn't available, the previous check stays.
- tests: the distribution matrix now also runs a 30-port scan and requires the port_scan event.
v1.0.25
- feat: install security updates from the dashboard. For packages with a known vulnerability that has a fix, the dashboard can ask the agent to upgrade them. Only installed packages built from the requested source packages are upgraded (
apt-get install --only-upgrade,dnf upgrade <names>,yum update <names>): nothing new is installed or removed; configuration files you changed are kept (--force-confold); the agent refuses while another package operation (apt, dpkg, dnf, unattended-upgrades) is running; it never reboots the server and restarts no service itself (needrestart in list mode). The result lists each package's old and new version, the services still running old code and whether a reboot is needed, and the software audit runs again. A package's own upgrade script may restart its service (e.g. nginx, OpenSSH); the dashboard says so before asking for confirmation. Tested for real on Ubuntu 24.04 (apt) and Rocky Linux 9 (dnf): only the requested packages changed. - feat: SSH detection reads the systemd journal. Authentication messages now come from the journal (its auth and authpriv facilities — the same lines, in the same format, that rsyslog copies to
/var/log/auth.logor/var/log/secure). Two real failures this fixes: Debian 12 and 13, Fedora and Amazon Linux 2023 don't install rsyslog, so there was no log file and SSH brute force went undetected; and when rsyslog stops copying (its journal reader stuck — seen on Rocky Linux 9 in our tests,/var/log/securestayed empty while the journal had every failed login) the agent read an empty file. A log file is still used where there is no journal (agent in a container, non-systemd hosts) or whenAUTH_LOG_PATHnames a custom file. The installer no longer writes a non-existentAUTH_LOG_PATH. - fix: SSH sessions on OpenSSH 9.8 and later. Logins and logouts are logged by
sshd-sessioninstead ofsshd(Debian 13, Fedora 41+, recent Ubuntu); the session tracker only recognizedsshdand missed them. - fix: no more "FTP service detected" on servers without FTP.
/var/log/auth.logwas treated as an FTP log, so every Debian/Ubuntu server with rsyslog reported an FTP service. It is used for FTP only when Pure-FTPd, which logs there, is installed. - fix: the malware scan's security score reaches the dashboard. It was sent only when the dashboard returned a scan id for the results, which it never did, so the score was computed and dropped. It is now always sent at the end of a scan.
- tests: distribution matrix.
test/distro/run.shruns, for each distribution in a container with systemd, the real installer, an SSH brute force from another network namespace, and checks detection, the firewall ban, the blocked connection and a clean uninstall.
v1.0.24
- feat: hardening checks, software audit and one-click fixes from the dashboard. The agent's ~40 hardening checks (SSH, file permissions, open ports, users, firewall, processes, web server, exposed credentials, software versions) and the software inventory could only be started by an old channel nobody used. They now run on request from the dashboard and once a day on their own; the inventory includes each package's source package and the OS, so the dashboard can match it against vulnerability databases (CVE).
- feat: safe automatic fixes. For 10 checks the dashboard offers a fix:
X11Forwarding noandMaxAuthTries 4for SSH, stricter permissions on/etc/shadow,/etc/passwd,sshd_configand root'sauthorized_keys, and hiding the nginx/Apache version (server_tokens,ServerTokens,ServerSignature,TraceEnable). Each fix lives in a file of its own (sshd_config.d/00-infrafence-hardening.conf, nginxconf.d/zz-infrafence-hardening.conf, Apachezz-infrafence-hardening.conf), main configuration files are never edited; the service's config test must pass and the value must actually be in effect (sshd -T), otherwise the change is undone before any reload; services are reloaded, never restarted. Fixes that could lock people out (root login, password login, SSH port) or change how sites behave (directory listing, security headers, TLS versions) are never automatic. Nothing but permissions is changed on servers managed by a hosting panel or configuration management. Fixes can be reverted; uninstall removes them. The previous fixer code (never called) edited main files and restarted sshd without a config test; it was replaced. - fix: hardening checks read the configuration actually in effect. SSH settings come from
sshd -T(they ignoredsshd_config.d, so a server hardened there was reported as not hardened);MaxAuthTrieswas compared as text (10passed as "≤ 4"); nginx is read withnginx -T(every included file); Apache files are read in load order and the last value counts (Debian'sconf-enabled/security.confwas ignored); with nginx in front of Apache both are checked. - feat: SSH detection patterns per server from the dashboard. Custom patterns are added to the 15 built-in ones (before, a synced list would have replaced them); a pattern must have a capture group for the IP; an empty list removes them.
- feat: bans enforced by ModSecurity too. Where InfraFence set up ModSecurity (Apache, web server changes allowed), active bans are also written as ModSecurity rules, so visitors behind a proxy or CDN — which the firewall sees as the proxy's address — are refused when Apache knows their real address (mod_remoteip). Addresses are validated before reaching Apache's configuration, the file is only rewritten when the list changes, Apache's config test must pass (otherwise the previous file is restored) and reloads are graceful, at most every 5 minutes.
v1.0.23
- feat: DNS inspection at packet level. The agent now reads the server's DNS packets (UDP 53, IPv4 and IPv6) read-only, through a filter run in the kernel so nothing else reaches it, and attributes each query to its process (name, pid, executable, user). It sees what the previous monitor couldn't (queries from unconnected sockets, single lookups, the domain names and the answers) and reports queries to unconfigured or threat-listed DNS servers, domains resolving to known malicious IPs, possible DNS tunnels (many long, distinct subdomains of one domain) and DGA-style lookups (bursts of non-existent, random-looking domains). Antivirus, anti-spam and cloud names are allowlisted; queries the host answers as a DNS server are ignored; at most 3,000 packets/s are analyzed. On by default; it can be turned off in the dashboard settings. Where packet capture isn't available, the previous monitor stays active.
v1.0.22
- fix: no more "unusual DNS resolver" alarms for normal lookups, and the alarm says which process. Configured DNS servers were read only from
/etc/resolv.conf, which with systemd-resolved (Ubuntu's default) names just the local stub127.0.0.53, so every lookup sent to the real upstream servers was reported. Configured servers now also come from systemd-resolved's and NetworkManager's files, re-read every 5 minutes. Each external DNS query is traced to its process (name, pid, executable, user), which the events now include. Queries made by the server's own DNS service (systemd-resolved, dnsmasq, unbound, BIND, Docker's embedded DNS...) to its upstream or root servers are no longer reported as unusual or as resolver hopping; it must run from a system path. Threat-listed DNS servers are reported whoever queries them.
v1.0.21
- feat: 24 hosting panels recognized, with one detection. Panels were detected in two places that disagreed: the preflight scan (13 panels, decides whether web server edits are safe) and the panel shown in the dashboard (only cPanel, Plesk, DirectAdmin). Both now use the same detection, which also recognizes Easypanel, Dokploy, CapRover, aaPanel, CentOS Web Panel, Webmin, KeyHelp, Froxlor, Enhance, Laravel Forge and Ploi (markers taken from each panel's documentation or install script). The version is reported where the panel records it (cPanel/WHM, Plesk, DirectAdmin, HestiaCP, Webmin/Virtualmin). Every recognized panel prevents InfraFence from editing the web server configuration.
v1.0.20
- fix: bot settings apply right after upgrading. The agent loads the bot list from its cache at startup and re-downloads it once a day; after upgrading to v1.0.19 the cache still carried the old bot ids (
ccfor ClaudeBot), so a setting forclaudebotdidn't apply for up to 24 hours. Ids are now re-derived from the patterns whenever the list is loaded.
v1.0.19
- fix: bot identifiers from patterns with case classes. Bot settings are keyed by the id the agent derives from each list pattern. Patterns like
[cC]laude[bB]ot,[Cc]urebotand[cC]ludoall becamecc(also the id of "CC Metadata Scaper"),S[eE][mM]rushBotbecames,[wW]getww: a setting for one of them applied to the others. Case classes are now resolved first (claudebot,curebot,semrushbot,wget...). 11 ids change; the reverse-DNS verified crawlers (Googlebot, Bingbot...) are unaffected. The dashboard derives the same ids.
v1.0.18
- feat: bot settings from the dashboard. Bots are recognized from public lists downloaded daily (about 1,500 bots in 12 categories), each with its category's default action: search engines, SEO tools, monitoring, advertising, link previews, feed readers, archivers and research crawlers are allowed; AI crawlers, scanners, HTTP libraries and browser automation are logged. Organizations can now override that per category and per bot (allow, log only, block; a bot's own setting wins over its category's). The agent re-applies the settings whenever they or the lists change, without downloading again; changes arrive within seconds. Blocked bots are banned at the firewall and, when web server changes are allowed, blocked in nginx/Apache too.
- fix: expired bans are lifted on time. Bans now have durations (ban policy in the dashboard, or per-ban changes), but an expired ban was only lifted at the next periodic sync, up to 5 minutes late. The agent now syncs right after the earliest ban expiry.
v1.0.17
- fix: each ban is reported once. Watchers remember their bans only for their detection window, so an IP seen again later was reported again although it was still banned, and every report added a ban row (55 rows for one IP on a real server). All ban paths (SSH, web, scored web, mail, database, FTP) now report a ban only when the agent doesn't already ban the IP (its own detection or an active dashboard ban); after the ban expires, a new detection is a new ban, which drives escalation. Whitelisted and protected IPs, which the firewall refuses to ban, are no longer reported as banned.
- fix: the installer no longer mistakes an idle Ubuntu daemon for a package operation.
unattended-upgrade-shutdown --wait-for-signalruns permanently on Ubuntu (process nameunattended-upgr) and holds no lock, but preflight andinstall.shcounted it as a running package operation: on a fresh Ubuntu server the installer waited 5 minutes and then didn't install missing dependencies or ipset. A package operation now means a package manager process or a dpkg/apt lock actually held (read from/proc/locks, without taking it).packagekitdno longer counts either. - diagnostics: syncs triggered by a real-time push or by the heartbeat's config version are logged with their reason.
v1.0.16
Built for production servers: every change InfraFence makes to a host is checked first, isolated, reversible and opt-in.
- feat: dashboard changes reach servers in real time. Settings, whitelist, WAF rules, bans, finding actions, "Scan now" and YARA installs used to wait for the next 5-minute sync. Each agent now subscribes to its own Supabase Realtime channel and syncs as soon as the dashboard signals a change (~0.3 s). If that channel is down, a config version in the heartbeat catches it within 60 s, and the 5-minute sync remains the safety net. A push is only a "sync now" hint: the agent never acts on its contents and always fetches its configuration through the authenticated API. All syncs now run one at a time (a websocket-requested sync could previously overlap the periodic one), bursts are merged, at most one sync every 3 s.
- feat: all firewall enforcement lives in dedicated
INFRAFENCEchains, and repairs itself. Bans, threat-feed and country blocks, and dashboard rules no longer insert rules intoINPUT: one marked jump fromINPUT(andDOCKER-USER, so published container ports are covered) leads to InfraFence's own chains, rebuilt atomically withiptables-restore --noflush. The jump is placed before the first rule that can accept traffic, so ufw/firewalldACCEPTs can't bypass a ban. Whitelisted and protected IPs are exempted withRETURN, neverACCEPT, so InfraFence never opens anything. A guard checks every 60 s and restores the chains and jumps if a firewall reload (ufw, firewalld, CSF, iptables-restore) removed them (firewall_rules_restored,firewall_conflictwhen it keeps happening). Rules from older versions are migrated out ofINPUTonly when provably the agent's. Verified with real traffic on nf_tables and legacy backends, with and without ipset. - feat: preflight host scan.
infrafence-agent preflight [--json]inspects the server read-only: iptables backend, ipset, ufw/firewalld/CSF/fail2ban/CrowdSec/Docker/Kubernetes, web servers, hosting panels, configuration management, running package operations, disk and memory. The installer runs it before changing anything; the agent at startup and daily, reported ashost_preflight(shown on the dashboard's host compatibility card). - feat: conservative defaults for host changes, set from the dashboard. Web server configuration changes (UA blocking in nginx/Apache, ModSecurity rules) are now off by default and never made where a hosting panel or configuration management owns the config; previously every nginx server block was edited at first start. Bots set to "block" are still banned at the firewall. Inbound blocking from threat-intelligence lists is off by default (the lists still drive egress/DNS detection). Auto-update can be set to notify-only (
update_available). Changes made by earlier versions are not removed automatically. - feat: LiteSpeed support. LiteSpeed Enterprise and OpenLiteSpeed are detected (they live outside PATH) and reported as the web server. LiteSpeed Enterprise keeps Apache's
httpdfor its configuration, so the agent used to believe Apache served the sites and could edit and reload Apache under LiteSpeed; while LiteSpeed serves the sites, InfraFence no longer edits any web server configuration. OpenLiteSpeed and CyberPanel per-site access logs are now found from their configuration. - feat:
install.sh --dry-runand a clean uninstall. The dry run shows the preflight and what would be done, and changes nothing. The installer installs ipset only when preflight says it's safe (--no-ipsetto skip), waits for running package operations, no longer runsdpkg --configure -aorapt-get --fix-broken(they can restart unrelated services), and no longer modifies the system CA bundle.install.sh --uninstallnow runsinfrafence-agent uninstall --clean, which removes exactly what InfraFence added: firewall chains, jumps and sets, UA blocking, ModSecurity includes (restored if the web server's config test fails). - fix: a failed ModSecurity setup could break the next Apache restart. A failed
apachectl configtestleft the added include on disk. Setup is now transactional.
v1.0.15
- feat: threat intelligence and bot fingerprints downloaded on each server, daily. Egress/DNS threat matching and bot fingerprinting relied on lists the dashboard never sent, so they could not fire. Each server now downloads public lists directly from their publishers once a day (cached across restarts): known-hijacked netblocks (~1,800), the Emerging Threats compromised-hosts list (~670), and ~1,580 bot user-agent fingerprints (crawler-user-agents and ai.robots.txt, MIT). The threat lists always feed egress/DNS detection; inbound blocking uses a single ipset (only when ipset is installed and not in monitor mode) and never covers reserved, local, protected or whitelisted IPs, or anything broader than /8. Known crawlers are allowed (FCrDNS-verified where possible); AI crawlers, scanners, HTTP libraries and browser automation are logged. Bot matching uses a literal-prefix index (~70µs per request instead of ~3ms) and emits at most one event per IP and bot per hour.
- feat: built-in WAF rule catalog. Each release now publishes
waf-catalog.json(every built-in pattern with a stable ID, threshold rules, score points, action levels), which the dashboard's WAF page reads.waf_config.disabled_patternsturns off individual built-in patterns, e.g. for a false positive. - fix: SSH brute force never showed up as an event outside monitor mode. The SSH watcher only banned; the attack reached the bans table but not the event stream. It now emits a
brute_forceevent alongside the ban. - docs: READMEs no longer name third-party feed providers; the "50+ decoy endpoints" honeypot didn't exist (honeypots are custom WAF rules now).
v1.0.14
- feat: real YARA rules, refreshed daily. YARA was installed on servers but never scanned anything: rules only came from the dashboard, which never sent any. The agent now checks the latest YARA Forge release daily (hourly while none is installed) and keeps only web-relevant rules from sources whose license allows commercial use, verified against each repo's LICENSE: signature-base (Detection Rule License 1.1) and ReversingLabs (MIT). ~920 rules today. A new set is installed only if
yaracompiles it; otherwise the previous one stays. Reportsyara_rules_updated. - feat: richer findings. YARA matches now carry the rule's description, author (required by DRL 1.1 wherever a match is reported), reference, source, license, a severity derived from the rule's score, the matched text and its line number. Every finding now includes the file's SHA-256.
- fix: quarantine could move any file on the server. Requests from the dashboard were executed as root with no path check. The agent now refuses anything but a regular file inside a detected web root, resolved through symlinks.
- fix: the AniShell signature never matched. Its pattern was declared as a literal, so the scanner searched for the text
AniShell|Ani-Shellincluding the pipe. A new test fails if any literal signature contains regex syntax. - docs: README claims corrected — there were no "229 YARA rules", and the "64,000 MalwareBazaar hashes" lookup was a stub.
v1.0.13
- fix: a YARA install request stayed pending forever if YARA was already installed. The sync handler only acted on the dashboard's install request when YARA was missing; otherwise it skipped it without reporting anything, so the request flag (cleared when the agent reports
yara_installed) was never cleared. The agent now acknowledges the request withyara_installed(status: already_installed).
v1.0.12
- feat: malware scans can now run on an interval (every 3, 6, 12 or 24 hours). The scheduler is a plain interval ticker driven by
interval_hoursin the dashboard's malware scan config, replacing the daily/weekly-at-HH:MM model, which no dashboard could ever actually configure. The first scheduled scan fires one full interval after the schedule is enabled; the dashboard's per-server "Scan now" button covers wanting a result immediately (already supported by the sync loop). - fix: agents that registered before the server offered real-time push never picked it up. The Reverb websocket URL was only read during first registration, so those agents stayed on heartbeat/sync polling until someone re-registered manually. The heartbeat response can now carry it: when the agent has no websocket connection and the server starts reporting one, it saves it to its config and connects without a restart.
v1.0.11
- fix: Helm chart never got a new version, so Artifact Hub stopped picking up updates. The release workflow bumped
appVersioninChart.yamlon every release but neverversion— andversionis the OCI tag Helm charts get published under, so every release silently overwrote the same "0.6.0" tag with different content underneath. Confirmed on Artifact Hub: its security scanner kept running normally, but its version tracker had been stuck for days, since (from its point of view) there was never a new version to index.versionnow tracks the release tag exactly likeappVersionalready did, so every release is a genuinely new, unique chart version. - cleanup: removed a stray, fully orphaned
charts/charts/infrafence-agent/directory — a duplicate, unrelated-to-the-real-one chart nested a level too deep, referenced by no workflow or Chart.yaml dependency, just confusing dead weight sitting in the repo.
v1.0.10
- fix: dashboard "Uptime" reset on every agent update. It was computed from the agent process's own start time, so any routine agent restart (an update, a crash-restart, a manual
systemctl restart) reset it to zero — reported live as confusing since it happens frequently and made the field look broken. Now reads the server's real OS uptime from/proc/uptime, independent of the agent process's own lifetime — only a genuine server reboot resets it, matching what "Uptime" means on an operations dashboard.
v1.0.9
- diagnostics: WAF score/event decisions and event-reporting failures are now logged. Investigating a live report of WAF test requests (clear SQLi/XSS payloads, correctly reaching nginx and matching the built-in patterns by inspection) never showing up as events in the dashboard — the code path looked correct end to end but had zero visibility into where it was actually going wrong.
addScorenow logs every scored match and whether it crossed the observe threshold to report an event; the webwatcher's event-reporting callback now logsReportEventsfailures instead of silently swallowing them (every other callback already did this — this one was the exception). No behavior change, purely for diagnosing this live.
v1.0.8
- cleanup:
go vet ./...now passes clean across the whole module. Two pre-existing issues surfaced while testing:internal/scanner/scanner.go'sisPortOpenbuilt its address withfmt.Sprintf("%s:%d", host, port), which breaks on IPv6 hosts — now usesnet.JoinHostPort.internal/malware/wp_database.go'squeryForMalwarehad a leftoverappend([]string{...})call with nothing actually appended (its result was immediately discarded by the next line, which rebuilt the full arg list by hand) — rewritten to build the mysql args in one straight line without the dead step. Both are behavior-preserving; no functional change.
v1.0.7
- fix: the agent could ban its own public IP. Reproduced live during testing: SSHing into a server from a shell already on that same server (targeting its own public IP) can get logged by sshd with the source IP being the server's own public address — depending on the provider's routing, this doesn't always land on a directly interface-bound address, so
collectLocalIPs()'s self-protection (which only enumerates local network interfaces) didn't recognize it as "self" and banned the server's own IP after 5 failed attempts. The agent now also explicitly protects its own detected outbound IP (the same one it reports inagents.ip_address), the same mechanism already used to protect the InfraFence API server's IP.
v1.0.6
- fix: re-running the installer to update an already-running agent never actually restarted it. Confirmed live on a real server after the v1.0.5 fix: the binary on disk was replaced correctly, but
install_servicecalledsystemctl start(and the equivalent for Upstart/SysVinit), which is a no-op on a unit that's already active — the old process kept running in memory, unchanged, indefinitely. All three init systems now force an actual restart (systemctl restart, stop-then-start for Upstart, the init script's ownrestartcase for SysVinit), so re-running the one-liner now genuinely takes effect.
v1.0.5
- fix: the documented one-liner still required
--tokenwhen updating an already-registered server. The v1.0.4 fix stopped the re-register prompt from hanging the script, but the token requirement check ran before that logic and didn't know about it — so re-running the exact same install command to pick up a new release (with no--token, since install tokens are single-use and typically long gone by then) still failed immediately with "Install token is required," before ever reaching the code that would have skipped registration anyway. The token is now only required for a genuinely new registration (no existing config, or--force-register).
v1.0.4
- fix: install.sh could hang (again) when re-running on an already-registered server. The "Existing config found — re-register?" prompt used a plain
read, which reads from the piped script itself (not the operator's keyboard) in the documentedcurl | sudo bashflow — withset -eactive, the failed read killed the script silently right after printing the warning, with the binary already updated but the service never restarted. The prompt is gone: re-running now always keeps the existing registration, updates the binary, and restarts the service, with a new--force-registerflag for the rare case you actually want to re-register.
v1.0.3
- fix: heartbeat never reported listening ports or agent runtime stats.
DetectListeningServices()and the wholeRuntimeStatspayload (uptime, goroutine count, heap, RSS, event queue depth/drops) were fully implemented but never actually called from the heartbeat loop — the dashboard always showed "0 porte" and a blank uptime regardless of what was really running. Both are now populated on every heartbeat. - fix: websocket client retried forever with a noisy dial error when the server has no Reverb URL. Some backends intentionally never implement the Reverb push channel (the agent works fine without it via heartbeat/sync). The agent now skips starting the websocket client entirely in that case instead of logging a reconnect failure every 30s.
v1.0.2
- fix: install.sh could hang waiting for input on a real interactive install. The v1.0.1 fix made the server-URL prompt actually work when a real terminal is attached (reading from
/dev/tty) — but that meant it now always paused to ask, even though a sensible default exists, which contradicts "one command, zero configuration" and was caught immediately on the next real-server test (an operator running the documented one-liner over SSH has a real tty, so it always paused). Removed the interactive prompt entirely:INFRAFENCE_SERVER_URL/INFRAFENCE_AGENT_NAMEenv vars still override, otherwise it silently uses the default — never waits for input.
v1.0.1
- fix:
install.shfailed with "Server URL is required" on every real install. Found during the first real-server test: the documented one-liner (curl ... | sudo bash -s -- --token <TOKEN>, no env var) tried to interactively prompt for the server URL, butreadwas reading from stdin — which is the piped script itself when run viacurl | bash, not the operator's keyboard — so the prompt got nothing and the install aborted immediately.server_urlnow defaults tohttps://infrafence.com(matching the pattern already used elsewhere in the script), and the interactive prompt (still available for custom/self-hosted servers) now reads from/dev/ttyso it actually works when a real terminal is attached.
v1.0.0
- First official InfraFence release. This agent was forked and fully rebranded from an MIT-licensed upstream codebase (previously versioned up to v1.4.57 under its original name). Version numbering restarts at 1.0.0 for the InfraFence project — entries below this line predate the rebrand and describe the codebase under its original name.
- Sigma correlation wired up — cross-detector session risk scoring (WAF, integrity, malware, port scan, egress, DNS signals now credit open SSH sessions with a correlated risk hit; previously a synced config field with no effect).
- Egress & DNS threat detection — outbound connections and DNS resolvers are now checked against the same threat feed used for inbound bans, catching an already-compromised host beaconing out.
- Extended persistence monitoring — file integrity baseline now also covers
/etc/ld.so.preload, per-user crontabs, and systemd.service/.timerunits. - Release signing — binaries, container images, and the Helm chart are now signed with InfraFence's own Cosign and GPG keys.
v1.4.51
- fix: false positive CORE_FILE_MODIFIED on wp-includes/version.php — this file changes on every WordPress update and is not a useful injection target. Now excluded from core file integrity checks.
v1.4.50
- fix: false positive PHP in uploads — standard anti-directory-listing
index.phpfiles (< 120 bytes, "Silence is golden") inwp-content/uploads/subdirectories are now skipped by the framework checker. Affects plugins like Astra, Elementor, MainWP, iThemes Security.
v1.4.49
- feat: cancel malware scan from dashboard — new WebSocket event
malware_scan.cancelledstops the scan between root iterations. Reports partial results before exiting.
v1.4.48
- fix: MariaDB deprecation warning causing false positive malware findings —
CombinedOutput()mixed stderr warnings ("Deprecated program name") into query results, triggeringWP_DB_INJECTED_POST,WP_DB_INJECTED_OPTION, andWP_DB_ROGUE_ADMINon every WordPress site using MariaDB. Now usesOutput()(stdout only) and filters any remaining warning lines. - fix: false positive HEURISTIC_RECENT_PHP on plugin index.php files — standard anti-directory-listing files (
<?php // Silence is golden) in plugin asset directories are now skipped.
v1.4.47
- fix: custom scan paths ending in
/were silently ignored — a trailing separator makesfilepath.Globreturn zero matches and a nil error, so a path like/home/*/web/*/public_html/never got scanned and never reported an error. Patterns are now trimmed before matching, and blank entries are skipped instead of resolving to.or/(which made the scanner walk the whole filesystem). - HestiaCP / VestaCP support —
/home/*/web/*/public_htmlis now detected automatically, no custom path needed. The vhost directory is the domain, so each web root is reported with its domain. - fix: stop tailing bandwidth accounting logs — HestiaCP/VestaCP write a second
CustomLog <domain>.bytesper vhost holding byte counters, not HTTP requests. These are now skipped, removing roughly 40% of watched log sources on those servers.
v1.4.25
- fix: iptables rule ordering — geo DROP rules now use -A (append) instead of -I (insert first), ensuring ACCEPT rules for panel IP and whitelisted IPs always take precedence
v1.4.24
- fix: geoblocking never blocks panel IP — resolves InfraFence panel URL to IP and inserts iptables ACCEPT rule before any geo DROP rules. Also protects all whitelisted IPs from geoblocking.
v1.4.23
- fix: WAF disable toggle — empty
enabled_typesarray from panel now correctly disables WAF detection (previously treated as "use all defaults")
v1.4.22
- ipset for ALL bans — BanIP/UnbanIP use
infrafence-banshash:ip set (65K capacity) - Eliminates iptables "Memory allocation problem" — from 1,200+ rules to 3
- Batch
ipset restorefor ApplyBans (sub-second for 1,000+ IPs) - CleanupStaleBans works with ipset members
v1.4.21
- Proactive country geoblocking — ipset hash:net with full CIDR ranges from MaxMind mmdb
- Blocks ALL traffic from a country at kernel level (not reactive per-IP anymore)
- One ipset set per country, batch-loaded via
ipset restore(sub-second) - CIDR extraction cached after first call per country
- IPv4 only filter (ipset hash:net doesn't support IPv6)
- Graceful fallback to reactive blocking if ipset not installed
- Added
firewall.Init(),FirewallStatus(), ipset detection
v1.2.0
- ModSecurity inline WAF — auto-detects Apache + mod_security2, writes 14 static rules (SQLi, XSS, RCE, SSRF, Shellshock, Log4Shell, Spring4Shell), configures Include + graceful reload. Blocks on first request. Zero impact without ModSecurity.
- Reports
modsec_activein heartbeat
v1.1.5
- YARA install from dashboard — "Install YARA" button auto-detects apt/dnf/yum/apk
- Reports
yara_installedin heartbeat
v1.1.4
- YARA engine — uses yara CLI if installed, 229 web rules from LMD synced from backend, cached locally
v1.1.3
- Cap dynamic signatures at 200 to prevent scan stall on large servers
- Disabled LMD HEX regex patterns (need native YARA for performance)
v1.1.2
- Removed UPLOAD_SHELL_PNG (too many FPs), skip WP <5.0 checksums, core file cap at 10
v1.1.1
- Cap CORE_FILE_MODIFIED at 10 in scanner walk
v1.1.0
- Phase 3 complete — WP database scanning, malicious process detection, quarantine, security posture score (0-100, A-F grade)
v1.0.8
- Disabled exe/cmdline mismatch rootkit check (too many FPs on production servers)
v1.0.7
- Fix rootkit exe/cmdline FPs (cron, php-fpm, redis, postgres, case-insensitive)
- Fix hash lookup empty JSON response
v1.0.6
- Fix rootkit exe/cmdline FPs (python, busybox, interpreters)
v1.0.5
- Credential scan — .env exposure, SSH key permissions, .git in web root, cloud credentials
v1.0.4
- Malware scanner fully opt-in — nothing runs until user enables from dashboard
v1.0.3
- Phase 2 complete — entropy analysis, timestamp anomalies, realtime watcher, system integrity (dpkg -V/rpm -Va), rootkit checks
v1.0.2
- Hash matching — 64K+ hashes from MalwareBazaar + LMD, lookup via backend API
v1.0.1
- Dynamic signatures — admin panel management, synced to agents via /sync
v1.0.0
- Scheduled malware scans — configurable frequency/time/intensity from dashboard
- Allowlist sync from backend for user-ignored findings
v0.9.99
- Symfony, CakePHP, CodeIgniter detection and security checks
v0.9.98
- Framework checks FP prevention — production-only debug checks, line-level parsing
v0.9.97
- Signature test suite — FP and detection tests for all signatures
- Fixed patterns with | (OR) using IsRegex
- Reduced FPs: MINER_GENERIC PHPOnly, narrowed PHISH_PAYPAL, FilesMan context
v0.9.96
- Removed OBFUSC_HEX_DECODE and OBFUSC_LONG_BASE64 (getID3, theme configs FPs)
- Cap modified core files at 20
v0.9.95
- 3-layer FP prevention — WP core checksums, context-based severity, user allowlist with herd immunity
v0.9.94
- Reduced malware signatures from 40 to 26 (removed TimThumb, preg_replace, iframe, PHPMailer FPs)
- PHPOnly flag, minified file skip, expanded exclusion dirs
v0.9.93
- Malware scanner Phase 1 — 40 signatures, framework detection (10 frameworks), framework security checks, dashboard tab with scan history
v0.9.92
- Malware scanner foundation — scan engine, web root detection, signature matching
v0.9.90
- Fix: auto-discover ingress logs from
/var/log/pods/using pod UID
v0.9.89
- Fix: entrypoint version detection + API URL for K8s registration
v0.9.88
- Fix: entrypoint curl JSON payload on Alpine — single-line to avoid bad argument error
v0.9.87
- K8s API key registration — multi-use Organization API Key for DaemonSet deployments
v0.9.86
- Fix: remove
docker.sockmount from Helm DaemonSet (fails on containerd-only K8s)
v0.9.85
- K8s ingress-level firewall — ConfigMap deny list for nginx-ingress controller
v0.9.84
- Signed releases with SLSA provenance
- Helm chart bumped to 0.3.0
v0.9.83
- Kubernetes Level 5 — K8s API integration, containerd log adapter, request counter
- K8s-aware Docker image with dual binary release (bare metal + K8s)
v0.9.82
- FTP brute force detection — vsftpd, ProFTPD, Pure-FTPd
v0.9.81
- Helm chart bumped to 0.2.0 (appVersion 0.9.80, mail + DB watchers)
v0.9.80
- Database auth watcher — MySQL, PostgreSQL, MongoDB brute force detection + exposed port detection
v0.9.79
- Mail watcher — Postfix SASL, Dovecot IMAP/POP3, Roundcube brute force detection (11 patterns)
v0.9.78
- Fix: let backend handle ban escalation instead of agent-side
ExpiresAt
v0.9.77
- Fix: geoblocking reads
blocked_countriesfrom sync config (was silently ignored)
v0.9.76
- Helm chart README with OCI install instructions, Docker labels docs, values table
v0.9.75
- Fix: install oras in Helm chart workflow for provenance attach
v0.9.74
values.schema.jsonfor Artifact Hub validation
v0.9.73
- Fix: add Docker login for Cosign in Helm chart CI job
v0.9.72
- Cosign signing for Docker images and Helm charts
v0.9.71
- Security: upgrade Go from 1.22 to 1.26 — fixes 25 CVEs in stdlib
v0.9.70 – v0.9.66
- CI: Docker Hub push fixes and repo setup
v0.9.65
- Docker Hub dual-push (
infrafence/infrafence-agent) + fix GHCR tags
v0.9.64
- Kubernetes Helm chart — DaemonSet deployment + OCI chart published to GHCR
v0.9.63
- Docker Swarm support —
docker-compose.swarm.ymlwithdeploy: mode: global(1 agent per node) - Docker secrets support (
INFRAFENCE_TOKEN_FILE) for secure multi-node deployments
v0.9.62
- Docker labels autoconf —
infrafence.monitor,infrafence.log-path,infrafence.domain,infrafence.waf - Configure monitoring per container via Docker labels without agent restart
v0.9.61
- Docker image published to GHCR (
ghcr.io/infrafence/infrafence-agent) — multi-arch (amd64 + arm64) - Auto-register via
INFRAFENCE_TOKENenv var, docker-compose snippet included - Automated build + push on every release tag
v0.9.60
- Threat feed blocking — public threat-intelligence blocklists applied to firewall
- Pre-emptive blocking of known-bad IPs
v0.9.59
- Virtual patching — dynamic WAF rules from panel (regex patterns synced via heartbeat)
v0.9.58
- Heartbeat reports
auth_watcher_method,firewall_mode,ban_capacity,active_bans_count - Fix: enable all WAF types by default when
waf_configis null
v0.9.57
- Fix: web log detection for Docker containers with non-standard log paths
- Improved Apache log discovery on cPanel servers
v0.9.56
- Agent reports all bot actions (allow/log/block) as events for dashboard visibility
- Fix: skip web server reload when UA blocklist unchanged
v0.9.55
- UA bot blocking at web server level — nginx
map+include/ ApacheSetEnvIfNoCase - Zero app load, graceful reload on every policy change
v0.9.54
bot_unknownevents for unrecognized bot User-Agents — surfaces unknown crawlers in dashboard
v0.9.53
- Restore ipset firewall backend —
infrafence-banshash:ip set (65K capacity) - Automatic FIFO rotation at 500 bans when ipset absent
- Migrates existing DROP rules on first run
v0.9.52
- Skip private/reserved IPs (Docker bridge, localhost) in both SSH and WAF watchers
v0.9.51
- Fix: deduplicate WAF scoring when same request appears in multiple log files
v0.9.50
- Cumulative per-IP WAF scoring engine with configurable weights
v0.9.49
- Fix: check WAF patterns against both raw and decoded URI to catch encoded attacks
- Private IP filter for WAF
v0.9.48
- WAF config debug logging to confirm sync applies correctly
v0.9.47
- Fix: connect WAF config from panel sync to web watcher — WAF detection was completely disabled
v0.9.46
- Fix: remove duplicate
EventFuncdeclaration
v0.9.45
- User-Agent
InfraFenceAgent/{version}header on all API calls - Allowed bots reported as
bot_crawlevents
v0.9.44
- Dynamic detection rules from panel sync — SSH patterns configurable per server from dashboard
v0.9.43
- Expanded SSH detection — 15 patterns (9 auth failures + 6 pre-auth scanning)
v0.9.42
- Monitor mode — detect threats without blocking; new servers default to monitor mode
v0.9.41
- Bot fingerprint detection with pre-filter gate before WAF scoring
v0.9.40
- Report allowed bots as events for full visibility in dashboard
v0.9.39
- Bot fingerprint detection from panel sync with allow/log/block policies
v0.9.38
- Fix: nil pointer crash in
syncAndApplywhen WAF disabled and BotFingerprints non-empty
v0.9.37
- Dynamic WAF rules synced from panel (Phase 1)
v0.9.36
- Regex support for dynamic WAF rules (OWASP CRS compatible)
v0.9.35
- Bot management — pre-filter gate with allow/log/block policies per fingerprint
v0.9.34
- Configurable score weights per server via WAF config from dashboard
v0.9.33
- ipset firewall backend (65K+ ban capacity) with iptables FIFO fallback (500 bans)
- Startup trim for existing rules exceeding capacity
v0.9.32
- Replace malware detection with WAF bot scoring engine
v0.9.31
- Expand malware detection with YARA-sourced signatures and multi-language support
v0.9.30
- Report monitor scan summaries to API
- Port scan detection, SYN flood monitoring, file integrity checks
v0.9.29
- Add
port_scan,flood,integrity_change,malwaredetectors
v0.9.28
- Report
auth_watcher_methodin heartbeat - Honeypot trap detection (50+ decoy endpoints)
v0.9.27
- Fix: prefer journald on RHEL-family path (
/var/log/secure) for CloudLinux 9.7/cPanel
v0.9.26
- Auto-remediation — agent can fix 12 security findings on demand from dashboard
v0.9.25
- Security scanner — 30+ hardening checks (SSH, web server, file permissions, CVEs)
v0.9.24
- CloudLinux/cPanel support — journald fallback,
Invalid userpattern, domlogs detection
v0.9.23
- Fix: associate
server_namedomains with globalaccess_login nginx multi-vhost configs
v0.9.22
- Improved Apache detection for CentOS/RHEL —
ServerRootresolution, symlink following,apachectl -S
v0.9.21
- Fix: web container detection matches container port (
->80/tcp) not host port (:80->)
v0.9.20
- Docker container detection — auto-detect Docker, container inventory, web container identification
- Stdout log reader for containers using
docker logs - Docker info in heartbeat (
docker_version,docker_containers) - Bind mount + volume log discovery
v0.9.19
- Whitelisted IPs are detected (events reported) but never banned
v0.9.18
- Raw access log line included in event details for attack evidence
v0.9.17
- Fix: Apache
${APACHE_LOG_DIR}resolution - Monitored domains and log paths reported in heartbeat
v0.9.16
- Instant whitelist propagation via
sync.requestedWebSocket event
v0.9.15
- WAF disabled by default until explicitly configured from panel
- Fix: false rollback on
"signal: terminated"
v0.9.14
- Fix: removed
updateServiceFile()from updater — caused regression loop on every update
v0.9.13
- Fix: clean up partial
.rollbackstaging file on copy failure StartLimitIntervalSec=0moved to[Unit]section
v0.9.12
- Fix:
ExecStartPrealso restores when binary is not executable - Improved updater diagnostics,
recent_logsin failure event payloads
v0.9.11
- Fix: move
StartLimitIntervalSecto[Unit]and auto-patch service file on update
v0.9.10
- Fix: prevent binary loss during failed rollback
- Health-check window extended, stale ban cleanup on sync
v0.9.9
- Fix: prevent
start-limit-hitduring auto-updates - Fix: cross-device rename failure in updater
v0.9.8
- Report
waf_disabledevent to panel when no web logs found - Preflight check uses
checksubcommand; atomic rollback
v0.9.7
- Docker container log detection via bind-mounts
v0.9.6
- Web exploit detection — Spring4Shell, Log4Shell, Struts OGNL, ThinkPHP RCE, Drupalgeddon2
v0.9.5
- Atomic binary replacement + 15s post-restart health check; rollback on crash
v0.9.4
- Fix: double URL-decode bypass detection
- Reduce 404 flood threshold
v0.9.3
- Per-server WAF configuration — enable/disable types, detect-only mode, custom thresholds
v0.9.2
- XSS, SSRF, web shell, header injection detection
v0.9.1
- Fix: restore release workflow, LICENSE
v0.9.0
- Initial WAF — SQL injection, path traversal, RCE, shellshock,
.envprobe, config probe, WordPress brute force, XMLRPC abuse, 404 flood, scanner detection
v0.8.5
- Fix: prevent banning server's own IPs and organization sibling IPs
v0.8.4
- Fix: prevent banning reserved IPs (loopback, private, link-local)
v0.8.3
- Include recent service logs in update failure events
v0.8.2
- Report update outcomes (success/failure) to server via events API
v0.8.1
- Robust auto-updater with backup, preflight check, and rollback
v0.8.0
- System metrics collection — CPU, memory, disk, load, network reported to dashboard
v0.7.0
- Fix: skip systemd hardening on old kernels
v0.6.1
- Force update via WebSocket command
v0.6.0
- Multi-vhost domain mapping — auto-detect nginx/Apache vhosts, hot-reload every 5 min
v0.5.2
- Maintenance release
v0.5.1
- Multi-log web watcher — monitor multiple log files simultaneously
- Software version scanner, updater improvements
v0.3.1
- Fix: support upstart and sysvinit restart in auto-updater
v0.3.0
- Software audit collector and sync via API/WebSocket
v0.2.2
- Fix: static-link binary + support upstart/sysvinit
v0.2.1
- Fix: resolve "text file busy" error on auto-update
- Allow ldflags version injection
v0.2.0
- IP detection, auto-update via heartbeat, install-only mode
- DigitalOcean Marketplace support
v0.1.0
- Initial release — SSH brute force detection, GeoIP blocking, heartbeat, ban enforcement via iptables
