Repository navigation
feat: report what the node's sb script can do as sb:<cap> on hello and heartbeat - #31
Merged
Merged
Conversation
…d heartbeat
The server now removes a deleted VPN user from an adopted line by name only
on nodes that report sb:user-del-by-name, and it learns that from nothing but
the agent's capability list. lr00rl/sing-box v1.24.3-alpha.8 answers
`sb --json caps` with the list, so with -singbox-discover on the agent runs it
at startup, before hello, and then at most every 10 minutes with a 5 s
timeout, and appends each cap as "sb:<cap>" to the capabilities in the hello
and metrics bodies, the two places the server reads them.
Only names from a fixed allowlist pass: the seven alpha.8 lists
(user-del-by-name, user-park, user-parked-list, user-open-proxy-guard,
user-match-counts, user-socks-add, user-lock). A broken or hostile script
cannot put an arbitrary string into the capability set the server trusts,
and a later script's new cap needs an agent release to reach the server.
An alpha.7 or older script has no caps verb; it routes the word to change,
which refuses it with ok=false and exit 1. That, a timeout, any other
non-zero exit, or output that is not one {"ok":true,"caps":[...]} object
means no sb caps: one debug line and an unchanged heartbeat. The agent logs
at normal level only when the reported set changes.
The probe lives next to the existing `sb --json list` runner in
singboxdiscover and uses the same bounded, shell-free command. The task poll
header keeps only the agent's own capabilities, since the lease reads nothing
else from it. capabilitiesFor and the heartbeat goroutine are unchanged; the
work loop hands the cached caps to the heartbeat through its config, as it
already does for the discovered stats API address.
Tested: go test ./... (21 packages ok), gofmt -l . and go vet ./... clean,
scripts/check-release-workflow.sh and scripts/test-install-integrity.sh ok.
The alpha.8 fixture matches the fork's jq expression byte for byte; real
shell scripts cover the alpha.7 exit 1 and a hung script killed at the
timeout.
Not-tested: against a real node running the fork.
runBoundedCommand ran sb under a context deadline, but the deadline kills only sb itself. A child it started (jq, a sleep, a flock wait) inherits stdout, and cmd.Run waits for that pipe to close, so the call returned when the child exited rather than at the deadline. A script whose shell runs `sleep 8` under a 500 ms timeout held the caller for 8 s. Both the `sb --json list` discovery call and the new `sb --json caps` probe run on the work loop, so either could hold hello and the loop for as long as such a child lived. cmd.WaitDelay now closes the pipes one second after the kill and returns. The orphaned child is left to finish on its own; the agent no longer waits for it. Tested: a script that runs `sleep 30` as a child under a 100 ms timeout took 30.1 s before this change and returns in about a second after it. go test ./... (21 packages ok), gofmt, go vet, check-release-workflow.sh and test-install-integrity.sh ok.
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
lattice-server (integration 05c5176, PR #135) removes a deleted VPN user from an adopted line by name only on nodes that report the capability
sb:user-del-by-name, and it learns script capabilities only from the agent's capability list. This branch makes the agent report them.-singbox-discoveron, the agent runssb --json caps(the same-singbox-binbinary and bounded, shell-free runner assb --json list) once at startup, before hello, and then at most every 10 minutes with a 5 s timeout.capabilitiesof the hello and metrics bodies assb:<cap>. The server replaces its per-node set from both, so both carry it. The task poll header keeps only the agent's own capabilities.lr00rl/sing-boxv1.24.3-alpha.8 lists:user-del-by-name,user-park,user-parked-list,user-open-proxy-guard,user-match-counts,user-socks-add,user-lock(the last only on nodes with flock). Nothing else a script prints can reach the server.change, which answers{"ok":false,...}with exit 1). That, a timeout, any other non-zero exit, or output that is not one{"ok":true,"caps":[...]}object means nosb:caps, one debug line, and an unchanged heartbeat. A normal log line appears only when the reported set changes.runBoundedCommandnow setscmd.WaitDelay(1 s). Before, a child of sb that kept stdout open (jq, sleep, a flock wait) held the call past its deadline for as long as the child lived. This also bounds the existingsb --json listcall.capabilitiesFor,reportedCapabilitiesand the heartbeat goroutine are untouched, so this merges cleanly next tofeat/control-plane-witness. No version bump and no changelog entry; the release cut adds those.A probe failure on an alpha.8 node drops the
sb:caps until the next probe, up to 10 minutes. That fails closed: the server keeps the old removal path for that node.Test plan
gofmt -l .empty,go vet ./...cleango test ./...: 21 packages oksh scripts/check-release-workflow.shandsh scripts/test-install-integrity.shokcmd_json_capsjq output; parse, no-flock, trim and dedupe, oversized listexec sleep 30, and asleep 30child (30.1 s before the WaitDelay fix, about 1 s after)-singbox-discover; a heartbeat carries the prefixed caps and still withholds the durable capability while recovery is blockedsb:user-del-by-nameafter the agent restarts