Reflector — cross-VLAN casting (mDNS + SSDP + DIAL) as a RouterOS container, <10 MB RAM

Segmented networks (separate VLANs for IoT/guest/trusted) break service discovery: mDNS and SSDP ride multicast that routers don't forward, so Chromecast, AirPlay, DLNA, printers, and Sonos stop appearing across segments.

RouterOS 7.16+ has a built-in mDNS repeater, and avahi/mdns-repeater containers are a well-known fix here. They restore discovery — but not casting. A DIAL device (the YouTube/Netflix "cast" target) serves its device description and REST control endpoints only to its own subnet, so a client on another VLAN sees the TV but can't drive it. reflector adds the parts the mDNS-only options miss: SSDP M-SEARCH relay and a DIAL proxy, so the cast actually launches and stops across VLANs. It also does mDNS and WoL, so it can replace the repeater rather than sit alongside it.

What it does:

  • mDNS reflection — Bonjour/Avahi discovery (AirPlay, printers, Chromecast) across the two segments.

  • SSDP reflection with active discovery, not just passive NOTIFY: relays the client's M-SEARCH and proxies the device's unicast 200 OK back.

  • DIAL proxy (opt-in) — a terminating HTTP reverse proxy that rewrites the device's LOCATION/description URLs and connects upstream bound to the device's subnet, so it sees an on-subnet client. This is what makes the cast launch/stop work.

  • Wake-on-LAN across segments.

  • Per-device MAC filter — set it to expose one or several device(s), or omit it to mirror the whole segment.

Config is interface-based, no IPs:

[reflectors.tv]
source_if = "vlan-trusted"
target_if = "vlan-iot"
macs = ["B0:37:95:C5:60:BE"]   # optional; omit to mirror the whole segment
wol  = true
mdns = true
ssdp = true
dial = true                    # requires ssdp; IPv4 only

It is also possible to configure it with environment variables:

/container/envs/add list=REFLECTOR key=REFLECTOR_TV_SOURCE_IF value=vlan-trusted
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_TARGET_IF value=vlan-iot
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_MACS value=B0:37:95:C5:60:BE
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_WOL value=true
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_MDNS value=true
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_SSDP value=true
/container/envs/add list=REFLECTOR key=REFLECTOR_TV_DIAL value=true

Running it on RouterOS: I give the container two veth interfaces, one bridged to each VLAN — those are the source_if/target_if reflector binds to. Prebuilt binaries and container images for arm64, amd64, armv7, and armv5, covering the container-capable MikroTik range (RB5009 / hAP ax / CCR are arm64; RB4011 / hAP ac² are armv7; hEX refresh and other EN7562CT boards are armv5). Pull/install details are in the repo. Runs under 10 MB RAM.

Security: it doesn't merge VLANs. It relays only mDNS/SSDP/WoL on the interface pair you name, and the MAC filter scopes the exposed direction to one or several device(s). The DIAL proxy does expose that device's HTTP control endpoint to the source side, and the daemon parses untrusted mDNS/SSDP/HTTP. Tested with ASan+UBSan, Valgrind memcheck, and Docker e2e over real veth/feth pairs.

Single binary, Linux + macOS. Linux runs unprivileged with CAP_NET_RAW; macOS needs root or the ChmodBPF helper. mDNS, SSDP, and WoL run on both IPv4 and IPv6 (IPv6 best-effort by default, or required per entry). DIAL is IPv4-only because the DIAL spec ties the device's authority to an IPv4 address.

https://github.com/sbogomolov/reflector — Apache-2.0

Feedback welcome, especially on the SSDP/DIAL handling.

Like the idea, good concept. Now I'm still waiting on RouterOS supporting DNS-SD...

Instead of the toml file, you might consider supporting setting via ENV variables. And that approach work well with custom /app YAML container support in RouterOS, since it has placeholder variables and networks to do the mapping, and "placeholder" variables (e.g. interface name) that can be provided via ENV variables. And in /app, the ENV appear next to the container so that may better "interface" for configuration. Also, /app does support mapping a single config file like your current toml file.

Thanks for the feedback! I’ve never used /app, I’ll look into it. Configuration from env variables is also a great idea.

EDIT: It looks like /app will not work because reflector uses multiple veths.

EDIT2: Configuration with env variables is implemented.