fix(rust-plugins): SNMP protocol hardening — validate agent responses, bound walks, timeouts & retries - #6413
Open
julienmathis wants to merge 3 commits into
Open
julienmathis wants to merge 3 commits into
julienmathis wants to merge 3 commits into
Conversation
…, bound walks, timeouts & retries The engine blindly trusted the agent it queried, which is precisely the untrusted party of the dialogue: - Agent errors are now detected: a response with error-status != 0 produces a typed error naming the RFC 3416 status (e.g. "noSuchName"). - Request/response correlation: every request carries a fresh request-id, and received datagrams are validated (request-id, community echo, PDU type) before being accepted — unrelated datagrams (e.g. a late retransmission of a previous request) are discarded instead of being consumed as the current answer. - Bounded walks: OIDs must be strictly increasing during a walk (the classic snmpwalk "OID not increasing" guard) and a single walk may collect at most 100 000 values — both protect against a buggy or malicious agent looping the walk or streaming endless data. - Configurable timeouts and retries via three new CLI options: --timeout (per-attempt receive timeout, default 1s), --snmp-retries (default 2), and --collect-timeout (global budget for the whole collection, default 50s, so the plugin exits with a clean UNKNOWN before centengine's own kill timeout). - The UDP receive buffer was 1024 bytes, silently truncating large bulk responses; raised to 65535. Connection parameters (target, community, timeouts, retries) are now threaded through a single SnmpConfig instead of loose string arguments, and the two walk loops share one implementation. Test plan: - cargo build --release succeeds - cargo test: 75 passed, 0 failed (10 new: RFC 3416 names, response validation, non-increasing OID, varbind cap, expired deadline) - Manual check against an unroutable address: default settings exit UNKNOWN after retries*timeout with the attempt count in the message; --collect-timeout correctly preempts a longer per-attempt timeout
…-failure message The protocol-hardening commit changed the no-connection error message from "Could not connect to X is the hostname..." to "No valid SNMP response from X after N attempts (timeout Ts per attempt)" (clearer: it names the retry budget actually exhausted), but never updated the Robot fixture that pins it. Both cgs-no-connection cases have been failing CI since this branch was opened.
snmp_bulk_get built a GetBulkRequest PDU for every "get" query, relying on a workaround that stripped a trailing .0 and depended on GetNext landing exactly one leaf ahead. GetBulk (even with max-repetitions=1) can never perform an exact match, so this silently returned the wrong value for any non-.0-suffixed OID, such as a specific row of a multi-row table. Every currently shipped definition only queries .0-suffixed scalars, so the bug was latent. Switch to a real GetRequest and drop the trailing-zero workaround, which is no longer needed.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The SNMP engine blindly trusted the agent it queried — yet the agent is precisely the untrusted party of the dialogue.
error-status != 0produces a typed error naming the RFC 3416 status, e.g.UNKNOWN: SNMP agent returned an error: noSuchName (status 2, index 3).--timeout <s>--snmp-retries <n>--collect-timeout <s>Connection parameters (target, community, timeouts, retries) are now threaded through a single
SnmpConfiginstead of loose string arguments, and the two walk loops (snmp_bulk_walk/snmp_bulk_walk_with_labels) share one implementation.Test plan
cargo build --releasesucceedscargo test: 75 passed, 0 failed (10 new tests: RFC 3416 error names, response validation — valid / wrong id / wrong community / agent error —, non-increasing OID ×2, varbind cap, expired deadline)UNKNOWN: No valid SNMP response from 203.0.113.1:161 after 2 attempts (timeout 1s per attempt)after ~2s, exit 3--collect-timeout 2with a longer per-attempt timeout →UNKNOWN: SNMP collection exceeded the global timeout of 2safter ~2s, exit 3 — the global budget correctly preempts the attempt schedule