Skip to content

fix(relay): don't exit when a UDP reply bounces - #84

Merged
elementbound merged 2 commits into
foxssake:mainfrom
Jaedee:fix/registrar-socket-error
Aug 3, 2026
Merged

fix(relay): don't exit when a UDP reply bounces#84
elementbound merged 2 commits into
foxssake:mainfrom
Jaedee:fix/registrar-socket-error

Conversation

@Jaedee

@Jaedee Jaedee commented Aug 1, 2026

Copy link
Copy Markdown

📓 Description

A single UDP packet from any source can stop noray.

UDPRemoteRegistrar.listen() creates its socket with a data handler but no
error handler. When a packet arrives that is not a valid PID, handle()
catches the assertion and replies with the error message. If the sender has
gone — a port scanner, a stray packet, a client that has moved on — that reply
provokes an ICMP port-unreachable, which surfaces on the socket as
ECONNREFUSED. With no handler, Bun treats it as fatal and the process exits.

Reproduced on 1 August 2026 against c0c34dc, with NORAY_UDP_REGISTRAR_PORT
reachable from the internet:

printf 'not-a-pid' | nc -u -w1 <host> 8809
ECONNREFUSED: connection refused, recv
 syscall: "recv", errno: -111
Shutting down
noray.service: Main process exited, code=exited, status=1/FAILURE

systemd restarted it and the next stray packet killed it again. In our case it
had been restarting every few seconds for an hour before we noticed, which made
every other measurement meaningless — ports appeared closed, join codes were
issued and then were not, and nothing reproduced twice.

The fix copies the handler bindPortForRelaying already installs on the relay
sockets in src/relay/relay.ts. After it, the same packet logs a line and the
process carries on:

{"level":50,"name":"UDPRemoteRegistrar","msg":"UDP registrar socket encountered an error!"}

Verified against a live instance: the packet that previously killed it, then an
empty packet, binary junk, a 2KB payload and a TCP command sent over UDP — all
logged, same PID throughout, and the instance kept issuing OIDs between them.

☑️ Checklist

  • Documentation is up to date — no user-facing change
  • Versions are bumped as needed — no API change

🔗 Related issues

Partially addresses #74 — this is one of the "thrown inside an event handler"
cases. Same family as #54.

Happy to widen it to the other sockets in the relay module if you would rather
have that in one go, but I have only reproduced this one.

Jaedee and others added 2 commits August 3, 2026 20:36
The registrar replies to packets it cannot parse. If the sender has gone,
that reply provokes an ICMP unreachable, which arrives back on the socket
as ECONNREFUSED. With no error handler the process exits.

The relay sockets in src/relay/relay.ts already handle this; the registrar
was missed.

Refs foxssake#74
@elementbound
elementbound force-pushed the fix/registrar-socket-error branch from bf836d8 to 13fdb8e Compare August 3, 2026 18:36
@elementbound
elementbound merged commit 1bc2a13 into foxssake:main Aug 3, 2026
4 checks passed
@elementbound

elementbound commented Aug 3, 2026

Copy link
Copy Markdown

Thanks for the fix @Jaedee! Happy to look at more PRs if you're willing to send!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants