1
0
mirror of https://github.com/coturn/coturn.git synced 2026-10-24 00:08:57 +03:00

1 Commits

Author SHA1 Message Date
Pavel Punsky
0fb7fbade1 Binding stateless fastpath (#2024)
## What

Answer a plain STUN Binding request from an unknown UDP source in the
listener, instead of building a child socket and a session to reach
`handle_turn_binding()`.

That function derives its entire response from the request bytes and the
socket's own addresses — nothing in it needs session state. But reaching
it costs an `ioa_socket` plus an ~18KB `ts_ur_super_session`, and the
to-be-allocated timer holds both for 60 seconds. So one spoofed Binding
request per source buys ~22KB of server memory for a minute, in the
**default configuration**, with no authentication and no flag involved.

| | RSS growth, 3000 Binding requests from distinct source ports |
|---|---|
| master | **+66,720 KB** |
| this branch | **+304 KB** |

All requests are still answered, byte for byte.

## How

`udp_stateless_binding_fast_path()` in `dtls_listener.c`, called from
`handle_udp_packet()` for a source with no child socket yet. It rebuilds
the reply attribute for attribute:

- success response with XOR-MAPPED-ADDRESS (plus MAPPED-ADDRESS under
`--stun-backward-compatibility`, plus RESPONSE-ORIGIN/OTHER-ADDRESS
under `--rfc5780`), or `420` with the same UNKNOWN-ATTRIBUTES list;
- then SOFTWARE and FINGERPRINT on the same conditions as the session
path;
- and the same Prometheus binding counters (`stun_report_binding()`
already ignores its session argument).

The attribute walk mirrors `handle_turn_binding()`'s exactly, including
`SKIP_ATTRIBUTES`, so ICE-style requests carrying
USERNAME/PRIORITY/MESSAGE-INTEGRITY/FINGERPRINT are accepted rather than
flagged as unknown.

Requests the listener cannot answer identically still take the session
path:

- `--secure-stun` — BINDING is an authenticated method there, which is
`check_stun_auth()`'s business;
- CHANGE-REQUEST / RESPONSE-PORT / PADDING — the RFC 5780 probes leave
from an alternate socket that only the relay owns;
- `--log-binding` — its per-session log lines can only be written by the
relay, so the old path stays available for debugging.

Under `--no-stun` the request is dropped where the relay would have
ignored it anyway — same silence on the wire, minus the session it used
to leave behind.

`MAX_NUMBER_OF_UNKNOWN_ATTRS` moves from `ns_turn_server.c` to
`ns_turn_server.h` so both call sites share one definition.

## Wire compatibility

A byte-level dump of the reply (message type plus every attribute TLV)
was compared between a master build and this one for ten request shapes
— bare Binding, ICE-style, unknown comprehension-required attributes,
unknown comprehension-optional attribute, CHANGE-REQUEST with and
without bits set, RESPONSE-PORT, PADDING, and an attribute placed after
MESSAGE-INTEGRITY — in default configuration and with
`--software-attribute --fingerprint --stun-backward-compatibility`.
**Identical in every case.**

## Tests

New `examples/run_tests_stateless_binding.sh` with
`examples/scripts/stateless_binding_probe.py`:

- wire shapes, including that the reflexive port in XOR-MAPPED-ADDRESS
is the client's own and that the 420 echoes the offending attributes;
- `--no-stun` stays silent, `--secure-stun` still challenges with 401;
- a 2000-request flood asserting RSS growth stays under the threshold.

The suite discriminates: against a master binary the memory case fails
with `Binding flood grew RSS by 43632KB ... sessions are being created
again`, while every wire assertion passes on both builds.

Also run green: `ctest` (18/18 macOS, 17/17 Linux),
`turnutils_rfc5769check`, and `run_tests.sh`, `run_tests_conf.sh`,
`run_tests_mobile.sh`, `run_tests_multiplex_peer.sh`,
`run_tests_stateless_nonce.sh`, `run_tests_ratelimit_401.sh`,
`run_tests_rfc5780.sh` — the last one being the important one here,
since it exercises both the plain Binding response that now comes from
the listener and the CHANGE-REQUEST probes that must still reach the
relay.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 22:16:45 -07:00