.NET plugins return, the WEB server keeps passive results, and more security fixes
0.20.0 brings back .NET plugins — on Linux as well as Windows this time — and
lets the WEB server hold on to passive check results so a monitoring server
can collect a host's scheduled checks in a single request instead of being
pushed to. A security review of NRPE and the TLS layer underneath it fixed a
handful of findings; the one to act on is that TLS certificates the agent
generated itself were readable by every local user, and a generated CA handed
its private key to every client it was distributed to.
The release also fixes some seventy crash and hang bugs found by scanning the
whole code base after the check_service crash in 0.19.0, closes two gaps in
the credential guard introduced in 0.19.0, and makes stopping the service
prompt again on Windows hosts where it could hang for minutes.
✨ Highlights
- 🔌 .NET plugins are back, on Windows and Linux. The
DotnetPlugins
module hosts an installed .NET runtime (8.0 or newer), so plugins written in
C# or F# load on both platforms. Nothing changes on a default install: the
module stays off until you enable it, and no runtime is bundled. Plugins
built for the old .NET Framework API need a rebuild against the new
NSCP.Core.dll; the interfaces are the same. (#1481) - 📤 The WEB server can keep passive results and serve them over REST.
Turn the result cache on and everything submitted to its channel — typically
scheduled checks — waits in the agent until something polls
GET /api/v2/results. The bundledcheck_nsclient1.1.0 adds
results feed, which collects that cache and hands every entry to Nagios as
a passive result: one active check per host instead of one per service, and
no NSCA or NRDP receiver needed. A new scenario walks through the Nagios
Core setup. (#1498) - 🔒 Generated TLS keys are private now; check yours. Certificates the
agent generated itself — including the one a default NRPE start creates —
were written world-readable, and a generated CA wrote its private key into
theca.pemmeant for clients. New files are created correctly; existing
ones are left alone, so see the upgrade notes. (#1496) - 🛡️ NRPE and TLS hardened. A TLS handshake can no longer be left open
forever by a permitted host, a short NRPE packet can no longer smuggle
unverified bytes into the command, the NRPE client tells you when it is not
authenticating the server, and the Logjam-broken 512-bit DH parameter file
is gone. (#1496) - 🐛 Seventy crash and hang fixes across the agent. Three could be
triggered from outside: a malformed HTTP response from any server the agent
talks to could hang it, an empty console command over REST could crash it,
andfilter_perf sort=normalcould crash on the NagiosUmarker. The rest
were bugs on the default paths of common Windows checks, races when a module
is reloaded or unloaded, and thresholds that silently overflowed. (#1505) - 🔐 Two ways past the credential guard closed. A token or password
written inside a target'saddressis now protected the same way as one in
its own key, and a target without an address no longer adopts the caller's
host as its own. - ⏱️ Stopping the service is prompt again. On Windows, stopping shortly
after start could take minutes while the Windows Update check or a WMI query
finished; those are now abandoned on shutdown. (#1504) - 🐧 Builds with GCC 16 for anyone building from source on a current
Debian or Fedora. (#1479)
🔍 Detailed changes
🔌 DotnetPlugins — .NET plugins on Windows and Linux
The old module only ever worked on Windows and had been out of the build for
years. The new one finds an installed .NET runtime — DOTNET_ROOT, the
registered install location or the platform's default folders, or a path you
give in runtime path — and hosts your plugins through it. Everything a
plugin could do before still works: commands, submission channels,
command-line exec and log messages all reach the managed side.
[/modules]
DotnetPlugins = enabled
[/settings/dotnet/plugins]
MyPlugin = MyPlugin.dllAssemblies are looked up in plugin path (modules/dotnet by default,
where NSCP.Core.dll lives too). On Windows the installer has a ".NET plugin
support" feature again, selected by default; the Linux packages ship the same
files. See Extending with .NET
and the
DotnetPlugins reference.
📤 WEBServer — a passive result cache served over REST
Passive monitoring normally means the agent pushes results to the monitoring
server. That does not work when the server has no NSCA or NRDP receiver, or
when the agent cannot reach it. The WEB server can now turn it around: with
the cache enabled it listens on a submission channel (WEB by default),
keeps whatever arrives there — scheduled checks from Scheduler,
check_and_forward from CheckHelpers, anything that submits to a channel —
and hands it over when polled.
Setting (/settings/WEB/server/results)
| Default | Meaning |
|---|---|---|
enabled
| false
| Turn the cache on (takes effect on restart) |
channel
| WEB
| The submission channel to listen on |
primary index
| ${host}/${alias-or-command}
| What makes two results "the same check" |
mode
| last
| Which of two results for a check to keep: the newest (last) or the most severe (worst)
|
clear on poll
| true
| Polling empties the cache, so worst means "worst since the last poll"
|
max entries
| 1000
| How many checks to keep before the oldest is dropped |
max age
| none | Drop results older than this |
The cache is exposed as GET /api/v2/results, GET /api/v2/results/{key},
DELETE /api/v2/results and DELETE /api/v2/results/{key}. They need the
new results.list, results.get and results.delete privileges, which only
the full role has, so grant them to the account that polls:
nscp web add-role --role poller --grant results.list,results.get,login.get
check_nsclient 1.1.0, bundled with the Windows and Linux packages, adds the
results list, results show, results delete, results clear and
results feed commands; feed is the one to schedule from Nagios. The
REST results page describes
the API and the
Polled Passive Checks (Nagios Core)
scenario the complete setup.
🔒 NRPE and TLS — what the review found
None of the findings lets anyone past allowed hosts run code on the agent.
- Generated private keys were readable by every local user, and a
generated CA put its private key into theca.pemyou distribute to
clients — anyone holding that file could mint certificates the server
accepts withverify mode = peer-cert. New keys are created readable only
by the agent, and a generated CA keeps its key in a separateca-key.pem. - A TLS handshake could be left open forever. A permitted host could open
connections, send nothing, and hold them indefinitely. The listener's
timeoutnow covers the handshake as well. - The NRPE client did not authenticate the server. With
ssl = trueand
the defaultverify mode = nonethe link is encrypted but anyone on the
path could impersonate the server. The default stays, but the client now
logs one error per target so the choice is visible, and generated
certificates name the machine rather than onlylocalhostso verification
can actually be turned on. - A short NRPE v3/v4 packet could carry extra bytes into the command that
the checksum never covered. - The 512-bit DH parameter file is no longer shipped. Nothing used it by
default, but anyone who copied it intodhwas running a Logjam-broken
key exchange. - Smaller fixes:
tls versionaccepts every spelling the documentation lists
(tlsv1.3+,1.0+,sslv3+,any, … used to fail with "Invalid tls
version", which for an NRPE listener showed up as "listener failed to
start"), and several NRPE wire-format bugs are fixed, including version 4
packets not being recognised by the server.
🔐 Client modules — the credential guard covers the address too
0.19.0 stopped a caller from redirecting a target that carries a credential
to a host of their choosing. It missed two cases: a secret written inside the
address itself (?token=SECRET in the URL, or user:password@host), and a
target that had a credential but no address, which took the caller's host as
its own. Both are closed. If you relied on either, the options are the same as
in 0.19.0: pass the credential with the request, configure one target per
destination and pick it with target=, or set allow host override = true.
🛡️ Crash and hang fixes across the agent
After the check_service crash in 0.19.0 (#1499) the whole code base was
checked for the same kind of mistake, and roughly seventy were fixed. Most
were on paths ordinary checks take every day: reading event log records, WMI
results and scheduled tasks, taking process snapshots, check_cpu and
check_pagefile. Others showed up when a module was reloaded or unloaded
while a check was running, or when a threshold or unit suffix was larger than
the agent could represent. As a side effect, a few inputs that used to do
something odd are now rejected outright:
| Input | Now |
|---|---|
check_cpu time=0
| An error: the window must be at least one second |
A threshold or unit that overflows (used > 1.0e30T, time=5000000w)
| An error instead of a wrapped-around value |
| A module that failed to load | Dropped from the module list; no longer answers exec
|
NSClientServer (check_nt) or CheckMKServer on a settings reload
| Restart their listener so a changed port or password takes effect; open connections drop |
A Python script unloading PythonScript from inside
| Refused |
⏱️ CheckSystem and CheckDisk — shutdown no longer waits on Windows Update or WMI
Stopping the service shortly after it started could take minutes on Windows
(#1504). The first Windows Update check the agent runs goes online to Windows
Update or WSUS and cannot be interrupted, and the service waited for it. The
WMI queries behind the network, temperature, CPU frequency, battery and disk
I/O collectors could hold things up the same way while the WMI performance
service restarts. All of them are now abandoned when the service stops.
🐧 Building from source
The tree builds with GCC 16 (Debian unstable, Fedora rawhide), which defaults
to C++20 (#1479).
📚 Documentation
- New scenario: Polled Passive Checks (Nagios Core).
- New REST page: Results.
- New extending page: .NET plugins.
- The WEB server reference covers the new
/settings/WEB/server/resultssection.
⚠️ Upgrade notes
- 🔒 Check the permissions of certificates the agent generated for you.
The upgrade does not touch existing files: run
chmod 600 /etc/nscp/security/certificate.pem(or restrict the file to the
service account on Windows). If you handed out a generatedca.pem,
regenerate that CA and re-issue client certificates — the old file contains
the CA's private key. - 🔒 If
dhnamesnrpe_dh_512.pem, change it before upgrading to
${nrpe-dh}/nrpe_dh_2048.pem; the file is no longer shipped and the
listener will otherwise fail to start. An existing copy on disk is left
where it is. - 🔒 The NRPE client logs an error for every target it does not
authenticate. The default (verify mode = none) is unchanged. Set
verify mode = peer-certwithcapointing at the issuer to authenticate
the server and silence it. Regenerate an existing generated certificate to
get one that can be verified. - 🔒 Slow clients may be dropped during the TLS handshake. The handshake
now has to finish within the listener'stimeout(30 s by default). Raise
timeoutif a client on a slow link stops connecting. - 🔒 A credential inside a target's
addressnow blockshost=overrides,
as one inpasswordortokenalready did. Usetarget=, pass the
credential with the request, or setallow host override = true. - 🔒 Some inputs that used to misbehave are rejected: see the table above.
Nothing to do unless you relied on one of them. - 🔌
DotnetPluginsis available again but not loaded unless you add
DotnetPlugins = enabledunder[/modules], and it needs a .NET runtime
(8.0 or newer) installed on the host. Plugins built against the old .NET
FrameworkNSCP.Core.dllmust be rebuilt against the new one. - 📤 The result cache is off by default. Enabling it needs a service
restart, and the account that polls needs theresults.*privileges. The
bundledcheck_nsclientis now 1.1.0; existing invocations are unaffected. - 🔧 Every documented
tls versionspelling works now. Nothing to do; the
defaulttlsv1.2+was never affected.
Full detail on the security items lives in Security notices; the operator
actions are mirrored on Upgrading.
Full Changelog: 0.19.0...0.20.0