mDNS reflector for Mikrotik router.
  • C 77.4%
  • Shell 15.4%
  • Dockerfile 7.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
xengi ea069b2244
Some checks failed
Build container / Build container (push) Failing after 26s
Update Dockerfile
Signed-off-by: xengi <forgejo@xengi.de>
2026-08-16 12:42:36 +02:00
.forgejo/workflows build multiarch 2026-08-07 16:13:52 +02:00
.dockerignore computer made a thing 2026-08-07 15:42:27 +02:00
Dockerfile Update Dockerfile 2026-08-16 12:42:36 +02:00
entrypoint.sh redo vlan logic 2026-08-07 17:00:47 +02:00
healthcheck.sh computer made a thing 2026-08-07 15:42:27 +02:00
mdns-repeater.c fix 2026-08-07 17:09:45 +02:00
README.md computer made a thing 2026-08-07 15:42:27 +02:00

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

# 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:

/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:

/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:

/container pull [find where image~"mdns-reflector"]

Building from source

# 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