get2knowio / get2knowio/deacon
auto-forward: UDP port forwarding (detect /proc/net/udp + datagram relay)
- Dominant language
- Rust
- Stars
- 2
- Forks
- 0
- Avg merge
- 2h 36m
- Merged PRs (30d)
- 78
Description
Tracked deferral from `up --auto-forward` (spec `015-auto-forward-ports`, task **T058**; shipped in #188). v1 is **TCP-only**; this adds UDP.
## Goal / acceptance
UDP listeners inside the container are detected and relayed to the host.
## Hidden issues / gotchas
- **Detection:** the parser (`crates/core/src/port_forward/detect.rs`) reads `/proc/net/tcp{,6}` only. UDP needs `/proc/net/udp{,6}`, which has a different state model — **there is no `LISTEN` state for UDP** (the `st` field isn't `0A`). You'd treat a bound UDP socket (often `st == 07`, with a wildcard/loopback local address) as "forwardable," which is fuzzier than TCP LISTEN and risks false positives (transient client sockets).
- **Relay is fundamentally different.** The current relay is a bidirectional **byte stream** over `docker exec -i` (`nc`/`socat`/`/dev/tcp`). UDP is datagram + connectionless: you need per-source-address pseudo-session tracking, datagram framing, and timeouts. `nc`/`/dev/tcp` can't do this; you'd need `socat UDP-LISTEN:...,fork UDP:127.0.0.1:port` (so `socat` becomes effectively required for UDP — narrows the relay-program fallback), or the eventual embedded agent (#190) extended for UDP.
- **Host side:** bind a `tokio::net::UdpSocket` instead of `TcpListener`; the registry/`Allocation` type currently hands back a `std::net::TcpListener` — needs a transport-aware allocation.
- **Reporting/contract:** `PortEvent`/registry have no protocol/transport field distinguishing TCP vs UDP; would need one to disambiguate (and to avoid colliding a TCP:3000 and UDP:3000 in the host-global registry).
- **Datagram semantics over `docker exec`** add latency/packet-boundary concerns that don't exist for TCP.
## Recommended path forward
1. Add a `transport: Tcp|Udp` dimension to `DetectedPort`/`ForwardSpec`/`RegistryEntry`/`PortEvent` (schema bump).
2. Parse `/proc/net/udp{,6}` for bound sockets; conservatively forward only wildcard/loopback binds; document the false-positive tradeoff.
3. UDP relay via `socat UDP-LISTEN:,fork,reuseaddr UDP:127.0.0.1:` (fail-fast if `socat` absent and no embedded agent); host side uses `UdpSocket`.
4. Docker integration test with a UDP echo server (`socat`/`nc -u`) inside the container.
## Notes
Probably best done **after** the embedded relay agent (#190), which can carry UDP cleanly; until then UDP would hard-depend on `socat` in the image.
Contributor guide
Assessment
This issue has not been assessed yet.