v1.6.2 - upstream parity (carrier/logs/status), backhaul 1:1 guard, doctor fix - #5
Merged
Conversation
The WS probe hit only https://$domain/ without forcing HTTP/1.1, so curl could negotiate h2 — nginx drops the Upgrade header under h2, the $http_upgrade map falls to the fake site, and doctor reported a false 200 while tunnels were down. Now: force --http1.1, keep the / fallback line, and additionally probe the real secret control_path (/_rh/<hex>) where 101 means the control channel is healthy.
…PC timeouts) backhaul is 1:1 — one server, one global token, one 'ports' set. Putting two different foreign machines on backhaul collapses them into a single namespace, so the server cannot know which connection belongs to which machine and mis-routes them. Duplicate inbound_port across backhaul nodes is the signature (e.g. three nodes on 62050 = three machines each running Pasargad there), and gRPC dies first because its handshake/cert never matches the wrong peer. Now 'backhaul node <name> on' warns on duplicate inbounds and doctor reports it.
…us, backhaul logs
Upstreams were second-class: only kcp among transports, no way to see their
logs or tunnel mode. gen_up_client already understood ws/kcp/plain/noise — only
the commands and UI were missing. Now every upstream has the same carrier
surface as the main tunnel, and multiple upstreams each get their own.
node (ratholenode):
- upstream plain <id> on <host:port> | off
- upstream noise <id> on <host:port> <pubkey> [pattern] | off
- upstream ws <id> (reset any carrier back to the default)
- upstream status <id> (carrier + per-mode detail + unit state)
- upstream logs <id> [n] (rathole-client@<id> + rathole-kcp-up-<id>)
- backhaul logs (rathole-backhaul-client)
iran (ratholectl):
- backhaul logs (rathole-backhaul-server)
hub:
- upstream_{plain,noise}_{on,off}, upstream_ws (writes), upstream_{logs,status}
and backhaul_logs (read-only), all RE-validated argv
- per-upstream <select> mirroring the main-tunnel carrier select, unique ids so
several upstreams render side by side; backhaul is deliberately absent there
(it is a 1:1 core scoped to the whole Iran server, not per upstream)
- backhaul status/logs buttons on both the Iran and node pages
- i18n fa/en: logs, bh_logs, upcarrier_confirm, upcarrier_hint
tests: 26 pass (+8) — argv shape, pubkey validation, injection, WRITE_ACTIONS
The user confirmed the failure mode: with two machines on backhaul the FIRST one connects, then adding the SECOND drops BOTH — they fight over the single control channel because backhaul has one global token and one 'ports' set. - ratholectl: 'backhaul node <name> on' now refuses (die) BEFORE mutating state when another backhaul node already holds the same inbound_port, naming the clashing node. Previously it only warned after the fact. - hub: the "Available carriers" section lists which nodes are on backhaul and shows a red warning with the duplicate ports when the 1:1 rule is violated. - hub: adding the FIRST SNI/game node now asks for confirmation, stating that 443 flips to stream/L4 and how many normal nodes route through the new path. - i18n fa/en: bh_users, bh_dup_warn, cf_game_l4
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.
Why
Two production incidents drove this:
doctorlied. It reported WS to200/OK while every tunnel was down, because the probe hit only/without forcing HTTP/1.1 - under HTTP/2 nginx strips theUpgradeheader, the$http_upgrademap falls through to the fake site, and you get a false200. It also never probed the real secretcontrol_path.Multi-machine backhaul silently destroys tunnels. Backhaul is 1:1 - one server, one global token, one
portsset. Put two foreign machines on it and the first connects, then adding the second drops both: they fight over the single control channel. gRPC (Pasargad on 62050) dies first because its handshake/cert never matches the wrong peer. The signature is a duplicateinbound_portacross backhaul nodes.Upstreams were also second-class: only
kcpamong transports, and no way at all to see their logs or tunnel mode.What changed
Upstream parity - every upstream now has the same surface as the main tunnel, and several upstreams work side by side:
ratholenode upstream <plain|noise|ws> <id> ...,upstream status <id>,upstream logs <id> [n]<select>in the hub, unique ids per upstreamBackhaul -
backhaul node <name> onnow refuses before mutating state when another backhaul node holds the same inbound, naming the clash.doctorreports an existing violation; the hub lists which nodes are on backhaul and warns in red.backhaul logsadded on both sides.Safety - adding the first SNI/game node now confirms first, stating that 443 flips to stream/L4 and how many normal nodes are affected.
Verification
WRITE_ACTIONSmembershipgen_up_clientexecuted in a sandbox for all three modes - plain emitstls = false, noise emitstype = "noise"with the pubkey, ws emitstls = truewith SNI1101, 62050) and a healthy one (silent)bash -n,py_compile,node --checkclean