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

4 Commits

Author SHA1 Message Date
Pavel Punsky
47ce433cde Add per-source rate-limiting of UDP 401 Unauthorized responses (#1957)
TURN/STUN long-term auth answers the first unauthenticated request with
a 401 Unauthorized carrying REALM/NONCE. On UDP, where source addresses
are spoofable and the 401 is larger than the request that triggers it,
the server becomes a reflection/amplification vector: an attacker forges
a victim's source IP and bounces amplified 401s at it.

This adds an opt-in mitigation that caps how many UDP 401 responses the
server emits toward any single source IP per second. Past the cap the
server stays silent, denying both the reflection and the amplification.
Authenticated relay traffic is untouched — only requests that reach the
401 branch spend budget.

Flags (off by default):
  --unauthorized-ratelimit            Enable the mitigation (UDP only).
--unauthorized-ratelimit-rps=<n> Max 401 responses per source IP per
second. Default 10.

Implementation:
- Lock-free, fixed 4096-bucket direct-mapped table (~80 KiB, no
malloc/free, no lock, no list scan on the hot path); the source IP
appears only as a 32-bit tag, never as a pointer. The port is stripped
from the key so an attacker cannot evade the limit by rotating the
source port. A fixed 1-second window backs the per-second limit.
- Colliding addresses share the live bucket budget instead of receiving
a fresh allowance, so hash collisions can never expand reflected output.
- Drop and collision diagnostics are each latched to one log line per
(bucket, window) to avoid log amplification.
- Portable 32-bit atomics over C11 <stdatomic.h> with an MSVC
Interlocked* fallback; the on/off flag and the per-second threshold are
pointers into turn_params so every relay thread sees live CLI values
without per-thread copies.

Observability (Prometheus):
- turn_unauthenticated_401_{requests,responses,dropped_responses}
- turn_ratelimit_{hash_collisions,occupied_buckets,total_buckets}

Tests & docs:
- Unity unit test (tests/test_ratelimit.c) covering live-bucket
collisions, occupancy tracking, and the collision counter.
- End-to-end positive/negative system test (run_tests_ratelimit_401.sh)
and a Prometheus counter test (run_tests_prom.sh).
- A 401-response-flood load harness under examples/loadtest/.
- docs/401-ratelimit.md design note, plus man page, README, Prometheus
docs, and the example/Docker turnserver.conf entries.
2026-06-21 14:25:09 -07:00
Pavel Punsky
53f3ed9104 Prom https (#1956)
## Summary

Adds an optional **HTTPS mode for the Prometheus `/metrics` endpoint**,
and bundles three supporting improvements that surfaced while building
and testing it: more reliable `libmicrohttpd` detection, a fix for slow
`turnserver` startup on macOS, and expanded/robust Prometheus tests.

## Changes

### 1. Optional HTTPS for the Prometheus exporter
The exporter previously served `/metrics` over plain HTTP only. It can
now optionally serve over HTTPS via libmicrohttpd's TLS support.

- `--prometheus-tls` — serve the metrics endpoint over HTTPS instead of
HTTP.
- `--prometheus-cert <file>` / `--prometheus-key <file>` — PEM cert/key
for the endpoint; default to the server's own `--cert` / `--pkey` when
unset.

`start_prometheus_server()` loads the cert/key into memory, enables
`MHD_USE_TLS`, and passes `MHD_OPTION_HTTPS_MEM_CERT/KEY`. If TLS is
requested but no cert/key can be loaded (or libmicrohttpd lacks TLS
support), it logs an error and does not start. The startup log now notes
the `(http)`/`(https)` scheme. `docs/Prometheus.md` documents the new
flags.

*(`src/apps/relay/prom_server.c`, `mainrelay.c`, `mainrelay.h`,
`docs/Prometheus.md`)*

### 2. Reliable `libmicrohttpd` detection in `configure`
The autotools `configure` probed libmicrohttpd with a bare `cc
-lmicrohttpd` link test (no include/lib paths), so it failed to find
Homebrew-installed libmicrohttpd on macOS and silently disabled
Prometheus — even though OpenSSL/libevent (also Homebrew) were found via
pkg-config. `configure` now detects libmicrohttpd via `pkg-config` first
(matching how libssl/libevent are already detected), falling back to the
bare link probe on platforms without a `.pc` file. `./configure && make`
now builds the exporter on macOS without manual `CFLAGS`/`LDFLAGS`.

*(`configure`)*

### 3. Faster `turnserver` startup on macOS
macOS lacks `pthread_barrier_*`, so the thread-startup rendezvous in
`netengine.c` degraded to a flat `sleep(5)` — adding ~5s to every
startup (and it was racy: threads proceeded even if setup took longer
than the fixed sleep). Replaced the shim with a real portable barrier
built on a mutex + condition variable, behind a unified macro API:
**native `pthread_barrier` is still used on Linux**, the portable
barrier is used only where it is unavailable. The previous racy
`sched_yield()` spin-wait fallback is removed as well.

*(`src/apps/relay/netengine.c`)*

### 4. Prometheus test coverage + robustness
`examples/run_tests_prom.sh` now also covers the HTTPS endpoint
(explicit cert/key, cert/key inherited from `--cert`/`--pkey`, and a
negative test that an unreadable cert keeps the endpoint down, including
a check that the TLS endpoint rejects plaintext HTTP). Readiness is now
detected by polling the endpoint / server log instead of fixed `sleep`
intervals, making the suite both faster (~70s → ~2s) and less flaky.

*(`examples/run_tests_prom.sh`)*

## New flags

| Flag | Description |
|---|---|
| `--prometheus-tls` | Serve `/metrics` over HTTPS. Requires
libmicrohttpd built with TLS support. |
| `--prometheus-cert <file>` | PEM certificate for the HTTPS endpoint
(default: the server's `--cert`). |
| `--prometheus-key <file>` | PEM private key for the HTTPS endpoint
(default: the server's `--pkey`). |

## Validation

- **macOS** (portable-barrier path): `clang-format` clean, 10/10 unit
tests, and `run_tests.sh` / `run_tests_conf.sh` /
`run_tests_multiplex_peer.sh` / `run_tests_prom.sh` all pass. Exporter
now reachable at startup `t=0` (was `t=5`).
- **Linux** (Docker, native-`pthread_barrier` path): clean build, 9/9
unit tests, and all four system-test suites pass (TCP/TLS/UDP/DTLS).

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 23:02:01 -07:00
Pavel Punsky
1ec81eff10 Build Prometheus exporter from vendored local sources (#1955)
## Summary

The Prometheus exporter previously linked the
[digitalocean/prometheus-client-c](https://github.com/digitalocean/prometheus-client-c)
(`prom`) library, which is **no longer maintained**. This replaces it
with a minimal, self-contained Prometheus client under `src/prometheus/`
that is built straight from coturn's own sources and implements exactly
the slice of the API coturn uses: counters, gauges, a single default
registry, and the text-exposition serializer.

The vendored client is **drop-in API-compatible**, so `prom_server.c` is
unchanged. Histograms, summaries, custom registries and the upstream
`promhttp` handler are intentionally omitted (coturn serves `/metrics`
with its own libmicrohttpd handler).

The exporter is now **always compiled in**; the runtime `--prometheus`
flag still controls whether it starts. **libmicrohttpd** — actively
maintained — is the only remaining external dependency and is now
required by the build.

## Changes

- **`src/prometheus/{prom.h,prom.c}`** — vendored client. Thread-safe
(per-metric mutex on the increment path, read under lock in the bridge),
label-aware, with proper Prometheus value/label escaping and clean
integer formatting for counters. No deps beyond pthread/libc.
- **CMake** — replace `find_package(Prometheus)` with required
`find_package(MicroHTTPD)`; add `cmake/FindMicroHTTPD.cmake`; remove
dead `cmake/FindPrometheus.cmake` and the `WITH_PROMETHEUS` option.
- **`configure` / `Makefile.in`** — drop `-lprom`, compile the vendored
source.
- **Docker** (`debian`, `alpine`) and **CI** (`ubuntu-build-deps`,
`mingw`) — remove the `prometheus-client-c` build/install steps; keep
libmicrohttpd.
- **`docs/Prometheus.md`** rewritten.
- **`tests/test_prometheus.c`** — Unity tests for counter
accumulation/monotonicity, gauge inc/dec, and label-value escaping.

## Validation

- Full build green; all unit tests pass (incl. new `test_prometheus`);
`clang-format-15` clean.
- Live exporter scraped over HTTP — all `run_tests_prom.sh` scenarios
(default / custom address / port / path, plus the negative case) pass.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 18:58:30 -07:00
Kang Lin
294f897ccd CMake: find prometheus(fix #1304) (#1315)
fix #1304
2023-11-22 20:34:53 -08:00