mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 00:04:54 +00:00
node: enforce the inbound max_peers cap solely at promotion on XX
At the inbound peer cap the XX FMP handshake had two cap checks: an early gate in handle_msg3 and the late promote_connection check. On XX the peer's identity is not known until the third handshake message, by which point all three messages have already crossed the wire, so the early gate saved no wire bytes and governed exactly the same net-new-peer set as the late check (known and pending-outbound peers return earlier via the cross-connection paths). Remove the early gate and rely on the promotion check, and log the resulting MaxPeersExceeded rejection at debug instead of warn so a cap'd node under sustained inbound pressure does not emit WARN spam for expected policy rejections. Re-enable the two previously-ignored inbound-cap unit tests, rewritten to drive a full XX three-message handshake and assert the path-agnostic invariant (no promotion over cap, peer count unchanged, no connection/link/index leak) plus the known-peer reconnect bypass. Update the admission-cap integration suite's enforcement-event discriminator to match: drop the removed early-gate string and count the new debug-level promotion-cap rejection.
This commit is contained in:
@@ -204,25 +204,24 @@ info "node-$CAP_NODE final peer_count=$pc_final (expected $MAX_PEERS)"
|
||||
[ "$pc_final" = "$MAX_PEERS" ] || { info " FAIL: peer_count drifted from cap"; OVERALL=1; }
|
||||
|
||||
# ── Phase 5: daemon actively refused over-cap promotions ─────────────
|
||||
# Path-agnostic enforcement evidence. The early handle_msg3 gate logs
|
||||
# "Silent-dropping Msg3 at max_peers cap" (debug); the late
|
||||
# promote_connection check logs "Failed to promote inbound connection"
|
||||
# (warn, "max peers exceeded"). In the mesh topology denied peers are
|
||||
# also dialed by the cap'd node, so the late check is the active enforcer
|
||||
# — but counting both keeps the test correct regardless of which path
|
||||
# fires (and survives a future change to the early gate).
|
||||
# Enforcement evidence. The inbound max_peers cap is enforced by the late
|
||||
# promote_connection check, which logs "Rejecting inbound connection at
|
||||
# max_peers cap" at debug (node-$CAP_NODE runs
|
||||
# fips::node::handlers::handshake at debug in the mesh profile). In the
|
||||
# mesh topology denied peers are also dialed by the cap'd node, so the
|
||||
# cross-connection path handles them and the late check is the active
|
||||
# enforcer.
|
||||
clogs=$(docker logs fips-node-$CAP_NODE 2>&1 || true)
|
||||
gate_drops=$(echo "$clogs" | grep -c "Silent-dropping Msg3 at max_peers cap" || true)
|
||||
late_rejects=$(echo "$clogs" | grep -c "Failed to promote inbound connection" || true)
|
||||
enforcement=$((gate_drops + late_rejects))
|
||||
info "enforcement events on node-$CAP_NODE: early-gate=$gate_drops, late-check=$late_rejects (total $enforcement)"
|
||||
late_rejects=$(echo "$clogs" | grep -c "Rejecting inbound connection at max_peers cap" || true)
|
||||
enforcement=$late_rejects
|
||||
info "enforcement events on node-$CAP_NODE: late-check=$late_rejects (total $enforcement)"
|
||||
[ "$enforcement" -gt 0 ] || { info " FAIL: no cap-enforcement events observed in node-$CAP_NODE logs"; OVERALL=1; }
|
||||
|
||||
if [ "$OVERALL" -eq 0 ]; then
|
||||
pass "admission-cap: cap holds under sustained denied-peer load"
|
||||
pass " denied peers: $(echo $DENIED | wc -w), capture: ${CAPTURE_SECS}s"
|
||||
pass " total inbound from denied: $TOTAL_IN (sustained retries observed)"
|
||||
pass " cap enforcement events: $enforcement (early-gate $gate_drops + late-check $late_rejects)"
|
||||
pass " cap enforcement events: $enforcement (late-check $late_rejects)"
|
||||
pass " cap'd node held peer_count=$pc_final (max=$MAX_PEERS)"
|
||||
rm -f "$CAP_FILE"
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user