Help us shape the future of Go! Take the 2026 Go Developer Survey

sub

command
v1.3.98 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

README

sub — standalone UDP→dmsg bridge (sky UDP bridge)

Standalone, dmsg-only UDP→skywire bridge. Frames UDP datagrams with a uint16 length prefix and ferries them over a dmsg stream; the peer end unframes and replays them as UDP onto a local target.

This is Plan B for UDP-over-skynet — TCP-shaped reliable + in-order transport. Suitable for non-realtime UDP:

  • DNS (53)
  • NTP (123)
  • SNMP (161/162)
  • MQTT-SN
  • WireGuard control-plane handshakes (not bulk data)

For media-class UDP (RTP, VoIP, WebRTC media, real-time game protocols) use Plan A — true packet-level UDP at the route-group layer (RFC #2607). The TCP wrap in this bridge adds head-of-line blocking, which is fine for DNS/NTP/SNMP (the app retries anyway) and wrong for voice/video (one lost packet stalls the whole stream).

Reachable two ways:

  • As a standalone binary built from cmd/sub/ — invoke sub ….
  • As a subcommand of the unified skywire binary — invoke skywire dmsg sub …. Both share the same cobra.Command.

Wire format

A single frame:

+--------+----------------+
| u16 BE | payload (≤64K) |
+--------+----------------+

One frame per UDP datagram. MaxFrameSize = 65535. Per-source UDP flows get their own stream (per (ip, port) tuple on the client), held open until idle (--idle, default 60s). Replies flow back over the same stream/socket pair so stateful protocols (DNS req + reply on the same socket) work.

Usage

Two subcommands; deploy one of each (one per side of the bridge):

Client side (host with the UDP app)
export SKYUDP_SK=<hex-secret-key>     # persistent identity
sub client \
  --listen      127.0.0.1:5353 \
  --peer        <peer-visor-pk-hex> \
  --remote-port 53

Then point the local app at 127.0.0.1:5353 (e.g. dig @127.0.0.1 -p 5353 example.com).

Server side (host with the UDP target)
export SKYUDP_SK=<hex-secret-key>
sub server \
  --dmsg-port 53 \
  --target    127.0.0.1:53

The peer dmsg port (--dmsg-port on server, --remote-port on client) is arbitrary but must match. --target is the local UDP endpoint the unframed datagrams hit (e.g. a local DNS resolver).

Keypair sourcing

SKYUDP_SK env var, --sk <hex>, --sk-file <path>, or — if nothing is provided — an ephemeral keypair generated per launch. Use a persistent key in production so the server's allowlist (future work via a wrapping cli serve whitelist) remains stable across restarts.

When to reach for sub vs the alternatives

Need Use
DNS / NTP / SNMP / MQTT-SN over skywire sub (this)
WireGuard control plane over skywire sub
RTP / VoIP / WebRTC media / real-time game Plan A (RFC #2607)
Plain TCP over skywire skywire cli serve + a TCP forwarder
SMTP over skywire smb / skywire cli mail

Out of scope

  • DTLS / per-frame auth: dmsg already provides E2E encryption + PK-bound identity. Adding DTLS on top would be redundant.
  • Path MTU discovery: every frame fits in [0, 65535] bytes (UDP payload limit). Apps that fragment at IP layer are re-fragmented by the receiver's UDP stack as usual.
  • Source-address spoofing across the bridge: per-source flows are keyed by the local sender's (ip, port) — the peer end always sees the bridge's UDP source on --target.

Documentation

Overview

Package main cmd/sub/sub.go c2-net-transport

Standalone (dmsg-only) UDP→dmsg bridge ("sub"). Length-prefixed UDP datagrams ferried over a dmsg stream. Plan B for UDP-over-skynet — for non-realtime UDP (DNS, NTP, SNMP, MQTT-SN, WireGuard control plane). For media-class UDP use Plan A (packet-level UDP at the route-group layer; RFC #2607).

Reachable from a unified skywire binary as `skywire dmsg sub`.

Directories

Path Synopsis
Package commands cmd/sub/commands/sub.go c2-net-transport
Package commands cmd/sub/commands/sub.go c2-net-transport

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL