computer made a thing

This commit is contained in:
Ricardo (XenGi) Band 2026-08-07 15:42:27 +02:00
commit c7d2470f22
No known key found for this signature in database
7 changed files with 651 additions and 0 deletions

103
README.md Normal file
View file

@ -0,0 +1,103 @@
# mdns-reflector — IPv4 + IPv6 mDNS reflector for MikroTik RouterOS
A lightweight mDNS reflector (multicast DNS repeater) designed to run as a container on MikroTik RouterOS 7.x. It relays mDNS packets (port 5353, groups `224.0.0.251` and `ff02::fb`) between all specified interfaces — both IPv4 **and** IPv6 — filling the gap where RouterOS' built-in `/ip dns set mdns-repeat-ifaces=` only supports IPv4.
## How it works
- Opens one IPv4 and one IPv6 UDP socket **per interface**, bound to that interface via `SO_BINDTODEVICE`
- Joins the mDNS multicast groups on each interface
- Spawns one reader thread per interface; packets received on any interface are forwarded to every other interface
- Writes a health heartbeat to `/tmp/mdns-health` every 10 seconds
- Runs as non-root user `mdns` with `cap_net_raw,cap_net_bind_service` capabilities
## Quick start
```bash
# Build
podman build -t mdns-reflector .
# Run (auto-detect non-loopback interfaces)
podman run --rm --network host mdns-reflector
# Run with explicit interfaces
podman run --rm --network host \
-e INTERFACES="ether1 bridge" \
mdns-reflector
```
## MikroTik RouterOS container setup
RB5009 running RouterOS 7.x:
```routeros
/container config set registry-url=https://git.sb20.xengi.de
/container add \
remote-image=git.sb20.xengi.de/xengi/mdns-reflector:latest \
interface=bridge \
root-dir=mdns-reflector \
envlist=mdns-env \
start-on-boot=yes
/container env add name=mdns-env key=INTERFACES value="bridge iot private"
/container start [find where image~"mdns-reflector"]
```
> **Note:** MikroTik containers require `--network host`-like behavior, which you get by attaching the container to a single interface (usually your LAN bridge). The `INTERFACES` env var tells the reflector which interfaces *inside* the host to bridge mDNS across.
### Unprivileged container considerations
> This container already runs as non-root user `mdns`.
> On RouterOS, ensure the container has sufficient privileges:
>
> ```routeros
> /container set [find where image~"mdns-reflector"] \
> nesting=yes \
> hostname=mdns-reflector
> ```
## Environment variables
| Variable | Default | Description |
|---------------|-----------------------|--------------------------------------------------|
| `INTERFACES` | all non-lo interfaces | Space-separated list of interface names to bridge |
## Health check
The container exposes a Docker `HEALTHCHECK` driven by `healthcheck.sh`. It verifies:
1. Health heartbeat file exists and is < 30 seconds old
2. `mdns-repeater` process is running
3. At least one bound UDP socket exists on port 5353
Then on RouterOS, pull the updated image:
```routeros
/container pull [find where image~"mdns-reflector"]
```
## Building from source
```bash
# Multi-stage build (produces ~3 MB image)
podman build -t mdns-reflector .
# Or compile the C binary directly
gcc -static -O2 -o mdns-repeater mdns-repeater.c -lpthread
```
## Files
| File | Purpose |
|---------------------|-----------------------------------------------|
| `mdns-repeater.c` | IPv4/IPv6 mDNS reflector |
| `Dockerfile` | Multi-stage Alpine build |
| `entrypoint.sh` | Interface detection & launcher |
| `healthcheck.sh` | Docker HEALTHCHECK probe |
| `.dockerignore` | Reduces build context size |
## License
MIT