Nodes - FrankoonG/hy2scale GitHub Wiki
π English | δΈζ | νκ΅μ΄
Nodes
Nodes are the building blocks of an HY2 SCALE mesh. Each node runs a Hysteria 2 QUIC server and connects to other nodes as peers, forming a decentralised peer-to-peer topology.
Concepts
What is a node?
Any machine running HY2 SCALE. Each node has:
- an auto-generated node ID (8-char hex)
- a configurable display name (e.g.
sg-home) - a Hysteria 2 QUIC server listening on 5565 by default
- an exit-node flag β when set, peers may route traffic through this node to the internet
- optional TUN capability β raw IP packet forwarding for routing rules and TUN-mode VPN clients
A node can be a cloud VPS with a public IP, a home server behind NAT, a NAS, or a router running iKuai v4 via the .ipkg bundle.
Peer-to-peer topology
Nodes connect to each other directly via QUIC tunnels; there is no central control plane.

The example above shows a Singapore home node (sg-home) peering with ten remote nodes; three of the remote peers expose a further layer of sub-peers through nested discovery.
Connection direction
- Outbound β you initiate the QUIC connection to a peer (you need their address + server password).
- Inbound β a peer initiates the QUIC connection to you.
Both directions are functionally equivalent once connected. Direction only determines who needs whose address.
Two views, one topology
The Nodes page has two equivalent representations, switchable via the toolbar tabs at the top of the topology card:
Graph view (default)
- interactive SVG canvas with pan, wheel-zoom, and pinch-to-zoom on mobile / trackpad
- every edge carries its round-trip latency (coloured green β€ 100 ms, amber β€ 200 ms, red otherwise) and current throughput
- drag a node to reposition it; the layout is saved server-side and synchronised to every logged-in session over SSE
- click a destination dot (including your own self dot) to highlight the full relay path and reveal a breadcrumb at the bottom β each non-self hop in the breadcrumb is a clickable link that opens the remote view for that prefix (the same shortcut as the node-link in list view)
- native peers render as a yellow dot, offline peers as a light-red dot; edges that touch a native peer are tinted pale yellow at rest and saturate on selection so the path stays visually grouped
- toolbar controls: Reset view, Reset layout (with confirmation), Snap to grid
List / tree view
- ordered tree of peers with depth indicated by indentation and
via Xhints - columns: checkbox, latency, direction badge, node name + address, traffic upload / download β editing is driven by selection (see below) rather than a per-row icon
- the entire checkbox cell (including its padding) is the click target for that row's checkbox; the row's body click selects exclusively (single-row replace)

Adding a peer (outbound)
The + Add Node button supports two interactions:
- Click β opens the manual form below.
- Long-press (β₯ 600 ms) β opens an Import from hysteria2:// URL dialog where you can paste a
hysteria2://[auth@]host[:port][?params]#name(orhy2://alias). The URL is parsed live (host / port / password / SNI / insecure /mport/up/down/fastopen/pinSHA256) and a preview shows what would be imported; obfs / obfs-password are surfaced as ignored fields rather than silently swallowed.
Manual form fields:
| Field | Description |
|---|---|
| Node Name | Optional. Empty = falls back to the first address. Locked while editing an online hy2scale peer (renaming a live QUIC session would orphan its keyed state); always editable for native peers and for offline entries. Rejects /, whitespace, and control characters. |
| Address(es) | host:port of the peer β enter one, or several for multi-IP aggregation. The port field also accepts a comma/range list (5000-6000, 5000,5001,5002) for hy2 port hopping. |
| Connection mode | Direct (single address), Quality (adaptive failover), or Aggregate (load-balance across addresses) |
| Password | The peer's Hysteria 2 server password |
| Fast Open | TCP-Fast-Open-style 0-RTT request optimisation (toggle) |
| Brutal | Hysteria 2 brutal congestion control (toggle, sits flush right of Fast Open). When on, the Upload / Download Mbps inputs appear below; when off the inputs are hidden and any previous values are cleared so they can't be silently shipped. |
| BBR Profile | Standard / Conservative / Aggressive β left independent of Brutal so the column doesn't reflow when toggling |
| SNI | TLS SNI (usually the hostname) |
| Insecure | Skip TLS certificate verification |
| CA | Optional PEM-encoded CA to validate the peer cert |
Click Connect (create) or Save (edit). In edit mode an additional Export URL button between Cancel and Save copies a hysteria2://... share URL for the peer to your clipboard (multi-address peers fall back to the first address β the URL standard has no multi-addr slot). The clipboard helper falls back to a hidden textarea + execCommand('copy') on HTTP-over-IP so admin nodes reachable only by IP still work.
Receiving peers (inbound)
To receive inbound connections, share your node's address + server password with the peer. They add you as an outbound peer on their side.
Your server password is visible from the Edit Self modal (select your own node and use the Edit button).
Selecting and editing
The Nodes page (and every other list page on HY2 SCALE) shares one select-then-act pattern:
- Click anywhere in the row body (or a graph dot) to single-select that node β including your own self node, which routes Edit to the Edit Local Node modal.
- Click the leading checkbox cell (anywhere in its padded area, not just the tiny input) to multi-select; checkboxes are additive.
- When exactly one node is selected, a green Edit button appears at the top right of the topology card, between Import and + Add Node. The same button is hidden when nothing or more than one row is selected; it's also hidden when the single selection is a nested sub-peer (whose configuration lives on the parent and isn't editable here).
- Any blank click outside the topology card body β page heading, sidebar, the gap between cards, even the topology card's own header strip β clears a single-row selection. Multi-select stays sticky (clicks on buttons / inputs / open modals never deselect).
- Bulk actions (Enable / Disable / Nest / Unnest / Delete) appear left of the Edit button as soon as one or more rows are selected.
- For the self row specifically: nested toggle is hidden (no nested concept for self) but enable/disable remains for symmetry.
In the graph view, selecting a dot promotes the same top-right Edit button β list and graph share one editing entry point.
Nested discovery
Nested discovery lets you see a peer's peers β one level deeper into the mesh per hop.
Each hop is gated by the local nested flag on that peer:
- sg-home grants nested on
usβus's peers show up as children ofus - sg-home also grants nested on
us/us-eastβus-east's peers show up as grandchildren - flip any hop off and everything under it disappears from both the UI and the routing plane
The same display name is allowed on different paths (for example A/B/D and A/B/C/D can coexist), but a name may not appear twice within a single path. If you cannot see a node in the UI, you cannot dial it either β display and routing share the same authorisation predicate.
Enabling
- open a peer, toggle Nested, save. Sub-peers appear within one probe cycle.
- deeper levels (nested-of-nested) require granting
nestedon each intermediate path segment β open the sub-peer row and toggle Nested there too.
Bond aggregation (multi-IP)
When a peer exposes several addresses (e.g. two ISPs), add them all under Address(es). Two aggregation modes are available:
| Mode | Behaviour |
|---|---|
| Quality | Continuously probes all links, forwards traffic over the lowest-latency one, fails over immediately when it degrades |
| Aggregate | Load-balances packets across every healthy link β combines bandwidth of both ISPs |
Direct mode is the degenerate single-address case.
Native Hysteria 2 peers
HY2 SCALE can connect to plain Hysteria 2 servers that don't speak the relay protocol. They appear with a [NATIVE] badge, support direct traffic routing, but cannot participate in nested discovery.
Topology indicators
| Badge / colour | Meaning |
|---|---|
| Blue centre dot | self node |
| Yellow dot + edges | NATIVE peer (plain Hysteria 2) β its incident edges idle in pale yellow and saturate on selection |
| Light-red dot | offline / unreachable peer |
| Solid edge | connected, healthy |
| Dashed / faded edge | disconnected or unreachable |
| Latency label | round-trip time per edge (coloured by value) |
Direction badge (OUT / IN / LOCAL) |
connection direction |
[NATIVE] badge |
plain Hysteria 2 peer |
| Yellow version badge | peer runs a different HY2 SCALE version |
Red Γ marker |
offline / unreachable peer |
Exit routing
Any node with Exit node enabled can forward traffic to the internet. Per-user or per-rule exit_via paths steer specific traffic through a chain of nodes:
exit_via: "jp" # one hop
exit_via: "us/us-east" # two hops
exit_via: "kr/kr-r1/kr-r1-a" # three hops
Autocomplete in the UI is driven by your current topology β only reachable, nested-authorised paths are suggested.
Metadata exchange
Peers exchange small JSON documents over the relay protocol:
- node name and ID
- version string
- exit-node flag
- cached sub-peer list (for nested discovery)
- latency probes
The schema is extensible so future features can be rolled out without protocol breakage.
Relay protocol streams
Internal QUIC stream IDs for the curious:
| Stream prefix | Purpose |
|---|---|
_relay_register_ |
Node registration |
_relay_s2c_ctrl_ |
Server-to-client control |
_relay_list_peers_ |
Peer list exchange |
_relay_latency_ |
Latency probing |
_relay_via_* |
Route control |
_relay_data_* |
Data forwarding |