Rallypoint Link Options - rallytac/pub GitHub Wiki

Rallypoint Link Options

Rallypoint links always use TCP for some or all of their communications. Control-plane messaging is transactional (bi-directional), so TCP is a natural fit: requests and responses get reliable delivery.

Those same TCP links can also carry media-plane traffic (voice and other streams). Media is generally uni-directional and loss-tolerant—a dropped packet is often less than a tenth of a second of audio. TCP’s insistence on delivering every byte can actually hurt media on a lossy network via retransmission delay and head-of-line blocking.

This article covers when to keep media on TCP (the default) and when to move it to UDP. Rallypoint also supports QUIC as an alternative control path (TLS 1.3 over UDP, one reliable stream) — see Engage Rallypoints. QUIC does not replace udpStreaming for media.

TCP / TLS (default)

In the typical setup, each Engage client nails up a secured TLS connection over TCP to the Rallypoint and uses that single connection for both control-plane and media-plane traffic.

------            
| C1 | <---------- TCP/TLS --------+
------                             |
                                   v
                              -----------
                              |         |
------                        |         |
| C2 | <--------- TCP/TLS --> |   RP    |
------                        |         |
                              |         |
                              -----------
                                   ^
------                             |
| C3 | <---------- TCP/TLS --------+
------            

On a reasonably clean network (enough bandwidth, low loss, sensible latency), this is a solid default: one port, mutual TLS authentication, and predictable firewall behavior.

When the network gets ugly, TCP starts “helping” by retransmitting and stalling the stream. Your audio pays the price. That’s when UDP for media becomes interesting.

Pros

  • TLS encrypts the link (TRANSEC) in addition to any group encryption (COMSEC)
  • Client/RP session uses a single TCP port for control and media
  • Packet delivery is guaranteed (great for control-plane; mixed blessing for media)
  • Works through most firewalls and NAT setups that allow outbound TLS

Cons

  • TCP management adds bandwidth overhead
  • TLS management adds bandwidth overhead
  • Head-of-line blocking can introduce delay under loss
  • RP-side work includes decrypt (from source) plus per-target encrypt when forwarding over TLS

Why UDP for media

Ideally you want reliable delivery for control-plane traffic and best-effort delivery for the media-plane. UDP is a far more efficient way to carry media: less per-packet overhead, no connection back-and-forth, and no TCP-style stall when a packet is lost.

Think of TCP as fire-and-hit-the-target and UDP as fire-and-forget. Most of the time UDP packets arrive; they’re just not guaranteed the way TCP guarantees them—and for voice, that’s often exactly what you want.

So why not use UDP for everything? Because you’d have to reinvent reliable request/response delivery for the control plane—something TCP already does well. Also, UDP doesn’t always cross organizational boundaries: some firewalls and NAT setups block or break bidirectional UDP. Keeping control on TCP gives you a reliable backup path if UDP fails, fails mid-session, or goes one-way.

Engage and Rallypoints support asymmetric streaming: media can flow one direction over UDP and the reverse over TCP when that’s what the path allows.

Something like this is the goal:

------            
| C1 | <---------- TCP ------------+
|    | <---------- UDP ---------+  |
------                          |  |
                                v  v
                              -----------
                              |         |
------                        |         |
| C2 | <--------- TCP ------> |   RP    |
|    | <--------- UDP ------> |         |
------                        |         |
                              -----------
                                ^  ^
------                          |  |
|    | <---------- UDP ---------+  |
| C3 | <---------- TCP ------------+
------            

Control stays on TCP/TLS. Media prefers UDP when both ends agree and the path works; otherwise it falls back to the TLS tunnel.

Shared-key over UDP

When UDP streaming is enabled on the Rallypoint, clients still establish the TLS/TCP control link as usual. After negotiation, media packets can traverse a separate UDP path. That UDP path is encrypted with a shared-key scheme: the Rallypoint generates master key material for the session and both ends derive symmetric keys and (for indexed modes) an IV table. Details are in Engage Security — Rallypoint UDP Streaming.

Configure this with the udpStreaming object in rallypointd_conf.json:

"udpStreaming": {
   "enabled": true,
   "cryptoType": 4,
   "listenPort": 7444,
   "keepaliveIntervalSecs": 15,
   "priority": 3,
   "ttl": 64,
   "ipv4": {
      "enabled": true,
      "external": {
         "address": "",
         "port": 0
      }
   },
   "ipv6": {
      "enabled": true,
      "external": {
         "address": "",
         "port": 0
      }
   }
}

udpStreaming fields

  • enabled — turn UDP media streaming on or off. When disabled (or when setup fails), media stays on the TLS/TCP link.
  • cryptoType — which shared-key algorithm/IV mode to use (see table below). Values other than 1–4 are not supported; the Rallypoint will disable UDP streaming.
  • listenPort — UDP port the Rallypoint listens on for media. Default is 7444. Open this port on firewalls when UDP streaming is enabled (in addition to TCP 7443 for the control/TLS link).
  • keepaliveIntervalSecs — how often to send UDP keepalives so NAT mappings and path liveness stay healthy. Default is 15.
  • priority / ttl — QoS-related transmit priority and IP TTL for UDP media packets. See Engage and Network Quality Of Service.
  • ipv4 / ipv6 — enable per address family. At least one family must be enabled or UDP streaming is turned off.
  • ipv4.external / ipv6.external — optional publicly reachable address and port when the Rallypoint sits behind NAT or a load balancer and clients must send UDP to a different destination than the bind address.

Crypto types

cryptoType Algorithm IV handling Relative efficiency
1 AES-256 Full IV per packet Default. Least efficient.
2 AES-256 Indexed IV More efficient than full IV.
3 ChaCha20 Full IV per packet Typically better than AES indexed.
4 ChaCha20 Indexed IV Most efficient.

Indexed modes send a small IV index instead of the full IV on every packet. The Rallypoint and client share a derived IV table for the session. Prefer type 4 when both ends support it and you care about bandwidth and CPU; stick with the default (1) if you want the safest “just work” choice until you’ve validated the path.

Note: Link encryption (TRANSEC on the RP path) is separate from group encryption (COMSEC). Even with shared-key UDP, keep groups encrypted unless you have a deliberate reason not to (for example, interop with an unencrypted LMR gateway).

Negotiation and fallback

  1. Client connects over TLS/TCP and authenticates as usual.
  2. If the Rallypoint has UDP streaming enabled and the client supports the configured cryptoType, both ends can move media onto UDP.
  3. If UDP never comes up, fails mid-call, or only works in one direction, media stays on (or falls back to) the TLS tunnel. Asymmetric streaming is allowed.
  4. Control-plane traffic never leaves TCP/TLS.

Pros

  • Lower latency and less HOL blocking for media under loss
  • Lower per-packet overhead than TLS-wrapped media on TCP
  • Link still encrypted (shared-key TRANSEC)
  • Single UDP port on the RP for all clients/streams (default 7444)
  • TCP remains available as backup and for control

Cons

  • Extra UDP port and firewall/NAT considerations
  • Shared-key setup and keepalives add a bit of session complexity
  • Still some crypto CPU on endpoints (less than TLS media in many cases, especially with ChaCha20 indexed)
  • Path must allow bidirectional UDP (or you live with asymmetric / TCP fallback)

No-key over UDP (conceptual)

On a network you fully control and already trust—locked-down LAN/WAN, vetted users, no untrusted transit—you might ask: “Why encrypt the link at all if the group is already encrypted, or if the network itself is the security boundary?”

That’s the idea behind no-key UDP streaming: media packets carry a small stream header but no additional link-layer encryption. You save CPU and a few bytes per packet. Group COMSEC (if enabled) still protects payloads; you’re only skipping extra TRANSEC on the RP↔client UDP path.

Important: The shipped udpStreaming.cryptoType values are shared-key modes 1–4. An unsupported or unknown type causes the Rallypoint to disable UDP streaming rather than run an unencrypted UDP media path. Treat no-key link encryption as a design discussion for locked-down environments, not as a currently selectable cryptoType. If your threat model allows skipping link encryption, you still need to be deliberate about group encryption, network access control, and replay/spoofing exposure on the wire.

Pros (if an unencrypted UDP path were in use)

  • Negligible per-packet bandwidth overhead beyond the stream header
  • Negligible crypto CPU on RP and client for the link
  • Single UDP port for streams on RP and client

Cons

  • No link encryption
  • Little protection against replay, man-in-the-middle, or spoofing on that path
  • Inappropriate anywhere untrusted networks or users can observe or inject traffic

Choosing a mode

Situation Suggestion
Default / unknown network quality TCP/TLS only (udpStreaming.enabled = false)
Lossy or high-latency paths, UDP allowed Shared-key UDP (enabled = true, prefer cryptoType 4 if supported)
Strict firewalls, UDP blocked TCP/TLS only
Fully trusted internal WAN, max efficiency Still use shared-key UDP today; rely on network controls and group COMSEC as appropriate

Open TCP 7443 (or your configured listenPort) everywhere clients and peer Rallypoints connect. When UDP streaming is on, also open UDP 7444 (or your configured udpStreaming.listenPort), including any external/NAT mappings listed under ipv4.external / ipv6.external.