mirror of
https://github.com/Cacti/rrdproxy.git
synced 2026-10-31 00:57:32 +09:00
* Harden RRDtool proxy request handling * Address PR review feedback: encrypt oversized-request errors, fix env inheritance, spacing, and symlink test Addresses review comments on PR #17: - lib/client.php: encrypt the 'Request too large' error frame once the client is authenticated, matching the existing encrypted-error pattern - lib/client.php: build the removespikes child-process environment from getenv() instead of $_ENV so the full current environment (e.g. TEMP on Windows) is inherited, with RRDP_RRDTOOL_PATH merged on top - lib/client.php: add the missing space in the RRDTOOL_PIPE_UNAVAILABLE error frame so it matches the other 'ERROR: ...' responses - tests/run.php: check the symlink() fixture return value and skip the symlink-escape assertion (instead of producing a false positive) when symlink() is unavailable * Upgrade phpseclib 3.x to phpseclib/phpseclib ^4.0 - composer.json/composer.lock: require phpseclib/phpseclib ^4.0 (was ^3.0) - Update phpseclib3\\... namespace usages to phpseclib4\\... across rrdtool-proxy.php, lib/client.php, lib/functions.php, lib/wizard.php, and tests/run.php - lib/functions.php: phpseclib4 removed the Random class, so Random::string(32) is replaced with random_bytes(32) - Fix lib/__master__.php and lib/replicator.php, which PR #17 never migrated off the old pre-Composer phpseclib API (new \\phpseclib\\Crypt\\RSA(), ->loadKey(), ->getPublicKeyFingerprint() -- none of which exist in phpseclib 3.x or 4.x, so these MSR/replicator peer-authentication code paths would fatal at runtime). Both now use RSA::loadPublicKey()->getFingerprint('md5') wrapped in try/catch, matching the pattern already used in lib/client.php, plus a constant-time hash_equals() fingerprint comparison - tests/run.php: relabel the phpseclib round-trip check from 'phpseclib 3' to 'phpseclib 4' * Bump minimum PHP version to 8.2 and add CHANGELOG.md - composer.json: require php ^8.2 (was ^8.1) - include/global.php: bump RRDP_PHP_VERSION_REQUIRED to 80200 to match - README.md: update minimum/recommended PHP version to 8.2 - composer.lock: refreshed for the new php platform constraint - Add CHANGELOG.md tracking changes prefixed security:/issue:/feature: * Add PHPDoc blocks to all functions Adds a PHPDoc block above every function in rrdtool-proxy.php, lib/functions.php, lib/client.php, lib/__master__.php, lib/replicator.php, lib/wizard.php, cli/removespikes.php, tests/run.php, and .phpstan-bootstrap.php, each with a brief description and inferred @param/@return types. Function signatures themselves are unchanged; PHPStan will flag any inferred types that turn out to be inaccurate. * Add .github/copilot-instructions.md Generated from README.md and this session's learnings: project architecture (daemon entrypoint, shared lib helpers, client/master/replicator roles, wizard, removespikes CLI), build/lint/test commands (composer scripts, php tests/run.php, Windows platform-req caveats), and conventions (tabs, GPL header block, PHPDoc-only typing, phpseclib4 gotchas, CHANGELOG entry prefixes). Also fix .gitignore: the '.git*' pattern was unintentionally also matching and ignoring the .github/ directory; added a '!.github/' exception so files under .github/ (like this one) are tracked. * Add .gitattributes enforcing LF line endings; normalize existing CRLF files - Add .gitattributes with '* text=auto eol=lf' so Git normalizes line endings to LF on checkout/commit regardless of local core.autocrlf settings. - .gitignore: add '!.gitattributes' alongside the existing '!.github/' exception, since '.git*' was also unintentionally ignoring .gitattributes itself. - Normalize the two tracked files that had CRLF line endings (.github/copilot-instructions.md, CHANGELOG.md) to LF; no other tracked files were affected. * Manual PSR coding-style adjustments Manual formatting/coding-style cleanup in cli/removespikes.php, lib/__master__.php, lib/client.php, and lib/replicator.php. * Address automated review feedback: symlink confinement, key-pair validation, and misc fixes Addresses 10 unresolved copilot-pull-request-reviewer comments on PR #20: - lib/functions.php: rewrite rrdp_resolve_path_within() to walk the path one segment at a time (instead of only checking the nearest existing ancestor via file_exists()), so a symlink anywhere along a not-yet-fully-existing path is resolved and confined even if the symlink itself is dangling. - lib/functions.php: add rrdp_resolve_command_paths(), which resolves every RRD file path operand referenced by an RRDtool command (leading bare file arguments and DEF:/SDEF: clauses) against the RRA root and rewrites the command to use the canonical resolved paths, closing the symlink-escape gap left by the lexical-only rrdp_command_has_unsafe_path() check. - lib/client.php: wire rrdp_resolve_command_paths() into the RRDtool command dispatch path, rejecting/rewriting unsafe operands before they reach the RRDtool pipe. - lib/client.php: enforce the request-size limit on each completed transaction and the trailing unfinished remainder, instead of on the aggregate receive buffer before splitting on _EOT_, so multiple legitimate transactions in one read no longer trip a false 'Request too large'. - rrdtool-proxy.php: validate at startup that the loaded public/private key files actually form a matching pair (comparing derived fingerprints) instead of only deriving a fingerprint from the public key, failing startup instead of accepting requests that will all fail to decrypt. - lib/__master__.php, lib/replicator.php: resolve peer-supplied FULLSCAN folder/file names (and RRDLAST/RRDDUMP request filenames) through rrdp_resolve_rra_path() before using them in mkdir()/touch()/ file_put_contents()/RRDtool restore-dump-last-flushcached operations, instead of concatenating raw peer-supplied text; reject and skip entries that fail confinement. - lib/replicator.php, lib/__master__.php: guard rrdtool_pipe_init() failures in the main replication loop the same way lib/client.php already does, instead of indexing into a false return value and never retrying. - cli/removespikes.php: make createRRDFileFromXML() return whether the RRDtool restore actually succeeded, and exit non-zero when it fails instead of silently exiting 0. - .phpstan.neon: restore level 6 (was lowered to 2, contradicting .github/copilot-instructions.md) and add .phpstan-baseline.neon to capture the 42 pre-existing findings surfaced at level 6 without hiding future regressions. - tests/run.php: add the standard Cacti Group GPL header block required for every PHP file. --------- Co-authored-by: Thomas Vincent <thomasvincent@gmail.com>
211 lines
7.1 KiB
Markdown
211 lines
7.1 KiB
Markdown
# rrdproxy
|
|
|
|
Cacti RRDtool Proxy Server is a standalone proxy interface to Tobi Oetiker's
|
|
great RRDtool.
|
|
|
|
The main focus of this project is to allow the relocation of RRD files, data
|
|
replication, support of Cacti Boost and, if needed, the RRDcached daemon. It
|
|
allows system administrators to split Cacti's access resources across machines
|
|
without the need for NFS.
|
|
|
|
Because updates may contain sensitive data, RRDtool Proxy encrypts client
|
|
traffic using RSA-2048 key exchange and a fresh 256-bit symmetric key for each
|
|
message. Client IP addresses and public-key fingerprints must also be explicitly
|
|
allowlisted.
|
|
|
|
The current compatibility protocol verifies the presented public-key
|
|
fingerprint, but does not yet perform a signed challenge proving possession of
|
|
the corresponding private key. Its legacy CBC message format also lacks an
|
|
authenticated integrity tag. Deploy the client port only on a trusted,
|
|
firewalled management network. A future protocol version must add private-key
|
|
proof and authenticated encryption in coordination with the Cacti client
|
|
before these limitations can be removed.
|
|
|
|
A local service port is provided to allow administrators are able to access a
|
|
separate command line interface which provides easy access to configure and
|
|
debug the proxy.
|
|
|
|
## Contribute
|
|
|
|
Get involved in development by participating in active development on
|
|
[GitHub](https://github.com/Cacti/rrdproxy/).
|
|
|
|
## Requirements
|
|
|
|
RRDtool Proxy Server runs on any Unix-based operating system that can meet the
|
|
minimum requirements, though it will perform better with the recommended (or
|
|
higher). The most recent version of RRDProxy requires composer
|
|
|
|
### Minimum Requirements
|
|
|
|
- PHP Version 8.2 or higher
|
|
|
|
Installation must include and enable the following modules:
|
|
|
|
- Sockets
|
|
- Posix
|
|
- PCntl
|
|
- GMP
|
|
- ZLIB
|
|
|
|
- RRDtool Version 1.5 or higher
|
|
|
|
- Cacti Version 1.2.31 or higher
|
|
|
|
### Recommended Requirements
|
|
|
|
All minimum requirements must be met, though the following are more optional:
|
|
|
|
- PHP Version 8.2 or higher
|
|
|
|
Include all minimum recommendation modules
|
|
|
|
- RRDtool 1.7 or higher
|
|
|
|
- Cacti 1.2.7
|
|
|
|
## Usage
|
|
|
|
Before using the RRDtool Proxy Server, you must install the system using the
|
|
setup wizard which can be run at any point using the -w parameter.
|
|
|
|
```shell
|
|
composer install --no-dev
|
|
|
|
php rrdtool-proxy.php --help
|
|
|
|
RRDtool Proxy v1.2.17
|
|
Copyright (C) 2004-2026 The Cacti Group
|
|
usage: rrdtool-proxy.php [--wizard] [-w] [--version] [-v]
|
|
Optional:
|
|
-v --version - Display this help message
|
|
-w --wizard - Start Configuration Wizard
|
|
```
|
|
|
|
When running through the wizard, the status of items will appear on the right
|
|
hand side of the screen. When an item is successfully completed, the status of
|
|
`[OK]` will be shown in green (when color is supported) as seen below:
|
|
|
|
```shell
|
|
Checking System Requirements...
|
|
[0.00001] test: operation system supported [OK]
|
|
[0.00007] test: php module 'sockets' [OK]
|
|
[0.00011] test: php module 'posix' [OK]
|
|
```
|
|
|
|
Should any item have an issue, the status will be displayed as something other
|
|
than `[OK]` such as `[FAILED]`:
|
|
|
|
```shell
|
|
[0.40270] read: RRDproxy configuration file [FAILED]
|
|
```
|
|
|
|
Status Color | Description
|
|
: --- | : ---
|
|
Green | Success and without issue
|
|
Yellow | Warnings and will be ignored, correct the problem if needed
|
|
Red | Errors and will not be ignored, may prevent continuation
|
|
|
|
When the wizard prompts for the various settings that are available, you can
|
|
accept the default value simply by pressing return to accept it. Below are a few
|
|
of these settings and the default values that can be accepted:
|
|
|
|
Setting | Default | Comment
|
|
: --- | : --- | : ---
|
|
CLI System Prompt | rrdp | Max 8 chars
|
|
IPv4 Listen Addr | 0.0.0.0 | Listen all addr
|
|
Client Proxy Port | 40301 | Connections from a client
|
|
Proxy Proxy port | 40302 | Connections from another proxy
|
|
Dedicated CLI port | 40303 | Connections to the proxy cli
|
|
|
|
If the wizard displays a prompt that requires a response and it has no default,
|
|
you will be prompted again until a valid response has been entered.
|
|
|
|
## Command Line Interface
|
|
|
|
Use '?' or 'help' to get a list of all commands being supported by the proxy or
|
|
hints about missing parameters. The following shows an example of using the CLI
|
|
to list the available commands to find the version of RRDtool Proxy Server.
|
|
|
|
Note: that most commands require that the CLI is in privileged mode and this
|
|
password is encrypted in the configuration so cannot be guessed. If the
|
|
password has been forgotten, it can be reset using the RRDtool Proxy
|
|
Server Wizard but the background process will need to be manually terminated.
|
|
|
|
```
|
|
telnet localhost 40303
|
|
Trying 127.0.0.1...
|
|
Connected to localhost.
|
|
Escape character is '^]'.
|
|
rrdp>?
|
|
enable Turn on privileged commands
|
|
help Display help
|
|
show Show running system information
|
|
quit Close terminal session
|
|
|
|
rrdp>ena Tester12
|
|
|
|
rrdp# help
|
|
clear Clear functions for internal buffers
|
|
disable Turn off privileged commands
|
|
reset Reset terminal screen
|
|
set Configure proxy settings
|
|
show Show running system information
|
|
shutdown Close all connections and shut down proxy
|
|
quit Close terminal session
|
|
|
|
rrdp# show ?
|
|
clients List all trusted client connections
|
|
counters Return all system counters
|
|
cluster List all trusted cluster peers
|
|
logging Display state of logging
|
|
msr Display replication state
|
|
processes Display running child processes
|
|
rsa Show Encryption setup
|
|
threads Display currently open connections
|
|
variables Show Current Operating configuration
|
|
version System software status
|
|
|
|
rrdp#sh version
|
|
|
|
# ___ _ _ __ __ ___ ___
|
|
# / __\__ _ ___| |_(_) /__\ /__\ / \ / _ \_ __ _____ ___ _
|
|
# / / / _` |/ __| __| | / \// / \// / /\ / / /_)/ '__/ _ \ \/ / | | |
|
|
# / /__| (_| | (__| |_| | / _ \/ _ \/ /_// / ___/| | | (_) > <| |_| |
|
|
# \____/\__,_|\___|\__|_| \/ \_/\/ \_/___,' \/ |_| \___/_/\_\__, |
|
|
# |___/
|
|
|
|
RRDtool Proxy v1.2.17
|
|
Copyright (C) 2004-2026 The Cacti Group
|
|
rrdp uptime is 14 days, 0 hours, 4 minutes, 14 seconds
|
|
Memory usage 0.18872917 % (2026464/1073741824 in bytes)
|
|
a8:29:6a:b7:5d:be:c3:8a:be:13:7a:61:ee:0c:8b:d3
|
|
Process ID: 13996
|
|
Session usage (1/399)
|
|
|
|
Server IP [192.168.10.10]
|
|
Administration: [localhost :40303]
|
|
Replication: [192.168.10.10 :40302]
|
|
Clients: [192.168.10.10 :40301]
|
|
|
|
rrdp#
|
|
```
|
|
|
|
## Planned features
|
|
|
|
- Data replication
|
|
|
|
This is currently being written and has been mostly completed, but it is still
|
|
being tested and so hasn't been made available yet.
|
|
|
|
- Proxy stats via SNMP
|
|
|
|
A NET-SNMP persistent daemon and MIB needs to written to enabled support of
|
|
proxy stats via SNMP. This could lead to an interesting loop of Cacti storing
|
|
stats for RRDproxy within RRDproxy.
|
|
|
|
- International language support
|
|
|
|
Currently, the RRDproxy wizard and command line interface port are both
|
|
offering only english as the default language.
|