fix: let the user delete onion addresses no interface page shows; 0.4.9.12:4 → 0.4.9.12:5 - #34
Conversation
….9.12:4 → 0.4.9.12:5 A torrc entry the URL plugin cannot export is invisible in the UI and has no delete path, yet it is a live HiddenServiceDir with real keys. Two states get there and stay there: the host is missing while the package is still installed (kept on purpose since the batch-restore fix), and the host exists but no longer has a binding on the entry's internal port, so the OS rejects the export with binding-not-found. A relay operator who removes every address the interface pages show then keeps the relay-and-hidden-service warning with nothing left to delete. - A visible Delete Onion Addresses action lists every torrc entry with its .onion hostname and owner, marks the ones no longer attached to an interface, and deletes the selected entries with their key material. - dropOnionService marks an entry undefined and prunes the host and package records it empties, so merge drops them from the file; the per-row delete action uses it too. - The reconcile warning names the action, and the README states that the 0.0.0.0:9050 SocksPort is container-internal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
082ae66 to
c309bc7
Compare
helix-a
left a comment
There was a problem hiding this comment.
Blocking on one downgrade data-loss path. The current serializer/parser round-trip and Tor config validation both pass, and the package builds cleanly. Separately, please remove the Generated with Claude Code footer from the PR body.
| fr_FR: `- Une nouvelle action Supprimer les adresses onion, dans les Actions de Tor, liste chaque adresse .onion hébergée par le serveur, y compris celles qui ne sont plus rattachées à l'interface d'un service, et supprime celles que vous choisissez. | ||
| - Une adresse .onion dont l'interface n'a aucun port joignable cesse de répondre jusqu'au retour du port, et conserve sa clé.`, | ||
| }, | ||
| migrations: { |
There was a problem hiding this comment.
Blocking — prohibit the destructive downgrade of parked entries. With down omitted, this graph advertises canMigrateTo >=0.4.9.11:6 && <=0.4.9.12:5, including 0.4.9.12:4. That release's parser recognizes only uncommented HiddenServiceDir / HiddenServicePort lines. After downgrading, its unconditional seedFiles torrc.merge(effects, {}) therefore rewrites a fully parked service out of torrc (and drops parked ports from a mixed service). The key directory remains, but the package/host/port mapping is gone, so upgrading again cannot resume or list the address. Please import IMPOSSIBLE and set down: IMPOSSIBLE, unless there is a safe down migration that can represent parked ports without forwarding them to the stale/reassigned target.
…eaving its target An entry the reconcile pass could not re-derive kept its last target, a bridge port frozen at write time. Freed external ports return to the pool and a binding claims its preferred external port first, so a package installed later that prefers the same port inherited the old onion's traffic, and the address fronted a service it was never attached to. - A port with no bridge-reachable address in either mode gets a null target. torrc writes it as a commented-out HiddenServicePort, and comments out the HiddenServiceDir once every port of the entry is, so Tor neither forwards nor publishes the address; Tor rejects a HiddenServiceDir with no ports, which is why the whole block is parked rather than emptied. The annotations stay, the parser reads the commented lines back, and the entry resumes unchanged when the binding returns. - A parked port is not exported, and the Delete Onion Addresses action reads attachment from the target rather than looking the host up. - down: IMPOSSIBLE. An older parser reads the commented lines as comments, and its first merge writes the parked entries out of torrc, losing the mapping to their key directories; there is no safe target to hand them back. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
f9fe676 to
4817daf
Compare
|
Added |
helix-a
left a comment
There was a problem hiding this comment.
Confirmed the amended head adds down: IMPOSSIBLE, so the graph now reports only =0.4.9.12:5 as a downgrade target; the destructive path is closed. The PR footer is also gone. Re-ran npm run check, npm run build, and Prettier; all pass, and all three architecture CI builds are green.
Summary
Follow-up to #30. A torrc entry the URL plugin cannot export is invisible in the UI and has no delete path, yet it is a live
HiddenServiceDirwith real keys. Two states get there and stay there:binding-not-found, whichexportUrlslogs and moves past.A relay operator who removes every address the interface pages show then keeps the
relay and a hidden servicewarning with nothing left to delete — the support case behind this PR found three such entries on disk against interfaces reading "No addresses"..onionhostname andpackage/host, marks the ones no longer attached to an interface, and deletes the selected entries with their key material.exportUrlsandreloadTorrcpick the write up through theirtorrcwatches, so the rows and Tor's config follow.dropOnionServicemarks an entryundefinedand prunes the host and package records it empties, somergedrops them from the file; the per-row delete action uses it too.0.0.0.0:9050SocksPortbinds the container's interfaces only, which the support bot had read as a LAN exposure.Verified with
npm run check; not exercised on a box.Parking an entry with no reachable port
Second commit. An entry the reconcile pass could not re-derive kept its last target, a bridge port frozen at write time. Freed external ports return to the pool and a binding claims its preferred external port first, so a package installed later that prefers the same port inherited the old onion's traffic, and the address fronted a service it was never attached to.
torrcwrites it as a commented-outHiddenServicePort, and comments out theHiddenServiceDironce every port of the entry is, so Tor neither forwards nor publishes the address. Tor rejects aHiddenServiceDirwith no ports (verified withtor --verify-config), which is why the block is parked rather than emptied. The annotations stay, the parser reads the commented lines back, and the entry resumes unchanged when the binding returns.down: IMPOSSIBLE: an older parser reads the commented lines as comments, and its first merge writes the parked entries out oftorrc, losing the mapping to their key directories. There is no safe target to hand them back, so the downgrade is prohibited.