Talking to Roon from another VLAN (I got it working)

So as a networking / systems engineer it really annoyed me that Roon wasn’t reachable between subnets. I won’t go into why I need multiple VLAN’s at home, but it is what it is. I just got it working and it seems stable so far and a quick search in the forums makes me think I’m the only person to document this solution. As always, YMMV.

Anyways, my config:

Internet <-> pfSense <-> Multiple /24 network segments

My Roon core is 172.16.1.100 where my laptop moves between the 172.16.1.0/24 network (works fine as you’d expect) and 172.16.2.0/24 network (unable to locate the Roon core).

The challenge is that Roon does discovery on UDP/9003 which is sent out the local broadcast address (172.16.1.255 or 172.16.2.255 depending on what network). IMHO, Roon should be using multicast for this since that is routable (mDNS anyone?), but whatever.

The problem is, even if you forward these packets from one subnet to another, you also have to modify the destination IP address since a host on 172.16.1.0/24 will ignore traffic destined to 172.16.2.255 even if it lands on the network card.

Anyways, this solution should work for anyone who can figure out how to compile a simple C program for their router/firewall. For my pfSense box, that means FreeBSD/x86_64. I haven’t tried, but in theory it should work for all you Ubiquiti people (Linux/MIPS64) but you’ll need to cross-compile for the MIPS64 architecture.

That said this is what you need to download & compile: https://github.com/udp-redux/udp-broadcast-relay-redux

It’s actually a really simple program which listens to UDP broadcasts on certain interfaces and does the necessary forwarding & rewriting of the destination IP for other the interfaces. For me that meant running:

udp-broadcast-relay-redux --id 1 --port 9003 --dev lagg0 --dev lagg0.200

because lagg0 and lagg0.200 are my network interfaces- you’ve probably using different names. :slight_smile: Definitely check out the docs for the program. If you have other VLAN’s and you don’t want them visible to Roon (like my VLAN 300 which I have for IoT devices) then don’t list it.

What this means is that when my laptop (172.16.2.109) sends a udp/9003 packet to 172.16.2.255 udp-broadcast-relay-redux sees the packet on the lagg0.200 interface and changes the destination IP to 172.16.1.255 and sends it out lagg0 where my Roon core lives. The opposite happens when the Roon core (172.16.1.100) sends to 172.16.1.255, now my Roon app on the laptop sees it.

I’ve tested and I can even control other zones on the 172.16.1.0/24 network from my laptop.

Anyways, in theory this should also be workable for talking to their Roon while on the road over a VPN. In theory, you shouldn’t need to require a L2 VPN- a more traditional L3 VPN would work if you make sure to specify the appropriate VPN tunnel interface on the firewall. But I haven’t tested that either (definitely on my list though).

15 Likes

Update: No problems using the Roon app on my phone on the 172.16.1.0/24 network to control the Roon zone on my laptop while on 172.16.2.0/24.

I don’t have any Apple devices on the 172.16.2.0/24 network so no idea if that works FWIW.

this is definitely advanced networking. Kudos on getting this working. I used to have VLAN at home but I ended up removing them because I ran into issues with AirPlay, maybe something similar to what you mention here.

Thanks for sharing. Figured this could be useful for being able to discover Roon via vpn on my unifi usg setup. Tried it out but didn’t seem to work. Probably because I have a hard time identifying the interfaces (ie. doesn’t seem like ipsec/l2tp uses separate interfaces).

@mysticalgator: Honestly, it’s not that advanced. The software I referenced is just a simple UDP proxy. It’s more “niche” than advanced and I think that’s what throws people off because there is so little public documentation out there for this sorta thing.

@Nepherte: There are a few ways to do IPSec on USG. You definitely can do it via a vti interface. I’m pretty sure the site-to-site VPN for USG defaults to doing that (I thought it did). If you’re creating the IPSec VPN tunnel manually via the config.gateway.json file, then you’d use a vti interface. Dunno about L2TP for remote access- that’s a big reason why I switched- I had it working for over a year and then one day my USG wouldn’t provision anymore and it was because of the L2TP config.

If you can swing the $$$ for pfSense (check out Protecli boxes on Amazon) I’d highly recommend it. I’ve done much more advanced configuration (a load balanced HA policy route based VPN) entirely done in the WebUI. I’m seeing 780Mbps over VPN on a $500 box. If you don’t need that, you can spend probably half what I did. Compared to my USG Pro4 which did about 150Mbps VPN and required me to do this nightmare config: https://synfin.net/sock_stream/devrandom/split-tunnel-vpn-on-unifi-usg Honestly, this is the first time I’ve had to do anything on the CLI/ssh- everything else has been via their webUI (which I’ll admit is less polished than UniFi). Software is free so you could install it on an old PC you have sitting around and play with it.

2 Likes

Spent the day playing with Roon over OpenVPN tun / routed networks.

TL;DR: It’s going to be harder to make this work with OpenVPN in Layer 3/tun mode.

Basically, say you standup OpenVPN with a tun interface (which is the most standard way of doing things). The reality is that this is a point-to-point interface and thus doesn’t actually support broadcasts. But Roon still tries to send UDP/9003 discovery packets to the “broadcast” address anyways. But that’ll never work because that IP is just another regular host address.

OpenVPN has two “modes” for tun (layer3) based VPN’s:

  1. Shared network (shared subnet)
  2. /30 for each host (isolated)

What is interesting is that if you pick the isolate network then the broadcasts are not sent over the tunnel. But if you pick the shared network option, they are… unfortunately, they are destined to an address which isn’t considered “broadcast” since the interface doesn’t support broadcast at all.

So this means either need to use IPSec (might work, or might not) or write some code to listen on the network in at a low enough level that it can just “sniff” the traffic on the wire instead of using standard socket to listen. Not the end of the world, just more work because you can’t just the normal UDP socket API.

Anyways, I got far enough to realize that it’s at least worth playing with IPSec to see if that will magically work. Otherwise it’s probably a dozen or so hours two write the code to do the needful.

I should point out that you can run OpenVPN in Layer 2 mode which is known to work, but it’s got a lot of compatibility issues and so that’s why I’m not looking into that.

Well done for getting it to work. I did my USG inbuilt vpn, which for some reason works fully for my Android DAP when it’s connected to a cellular network phone via hotspot. I can play music and control other remotes. However pc and new Pixel phone can connect and remote but they are not seen as endpoints. I find why one works very confusing and why it only works on cellular network connection. I guess other networks must be blocking the traffic.

@CrystalGipsy: Can you elaborate on your setup with USG inbuilt vpn? I’m using IPSec over LT2P. My main LAN is on 10.0.0.0/24 but the vpn is on 10.0.1.0/24. Are yours on different subnets or did you configure it differently?

They have to be on seperate subnets, router won’t allow it to be on the same vlan. I’m using same IPSec over LT2P in the same configuration, both corporate vlans so each subnet has access to the other and mdns is on and dnmasq.

Could you post the relevant settings to enable? I have mdns enabled as well. My regular lan is ‘corporate’. For this type, you can’t provide a vlan. My IPSec over L2TP is a ‘Remote user VPN’. For this type, you can’t provide a vlan either. I don’t think mdns is relevant here, as Roon is using broadcast.

Not much to show, set up a L2PT server from the controller and a radius profile for the user. That’s it’s didn’t do anything else.

What @CrystalGipsy means by “they have to be different VLAN” is that they have to be separate L2 broadcast domains and L3 networks. Basically the UniFi/USG stuff puts all the VPN clients in their own “VLAN” which is separate from the other local networks (Corporate, Guest, etc).

Roon uses a mix of UDP: 9003 for discovery of devices running Roon and mDNS for talking to certain endpoints (AppleTV for example).

1 Like

And Android it seems going by my dap working.

1 Like

Well IPSec for me might be a dead end since I’d like to support MOBIKE (aka mobile support) even though I don’t need that for Roon.

The issue is that MOBIKE doesn’t allow vti / route based VPN’s. This means there is no vti network interface for the udp proxy to listen to on the firewall. Basically, vti based VPN’s are more “site-to-site” VPN’s which doesn’t make sense for phones/laptops traveling.

So the answer seems to be OpenVPN (which always creates a tunnel interface) and using libpcap to “sniff” the broadcast packets on the tunnel interface so they can be forwarded to the Roon core on the other network.

1 Like

Huh, I could of sworn I posted another update after the one above.

Anyways, I started working on a solution to the OpenVPN / loopback issue. You can see my progress over here on GitHub: https://github.com/synfinatic/udp-proxy-2020/tree/getting-started

If it’s not obvious, this is super early and the code doesn’t work. When I think I’ve got something for people to play with/test, I’ll post here. Of course, if you know Go and feel like contributing, that’s cool too. I’m not a Go expert (well, I’m I don’t consider myself an expert in any of the 5+ languages I know, but Go is the language I have the least experience with) so consider yourself warned. :smiley: Mostly I’m just committing/pushing code when I’ve made some progress and things compile without warnings. #include <std/disclaimer.h> and all that. I’m hoping to have something to test before my trial runs out in about a week.

Okay, merged to main and this is an initial proof-of-concept showing that it can work with OpenVPN tunnels in route/Layer 3 mode (as well as standard Ethernet interfaces): https://github.com/synfinatic/udp-proxy-2020

So the reason this is just a PoC is I need to do more testing to see how OpenVPN allocates IP addresses to clients on the VPN. Since we can’t use a broadcast message, we can’t send a single packet to every VPN client at once. Right now however, the code only allows sending a packet to a single IP pre-determined address for each interface. So if the OpenVPN client IP ever changes (or you have multiple clients) then it won’t work.

Anyways, not a big deal- the client is the first to send the messages so we can “learn” it’s IP and then send any replies from the Roon server back to that IP(s). But that code isn’t written yet. Also, the code should be able to detect that the interface is a normal Ethernet and not require you to specify the broadcast IP.

Sadly, I found that Go’s support for RAW IP sockets is a bit lame- it’s not supported on platforms other than Linux and Darwin (MacOS). Hence for FreeBSD/pfSense to work, I had to use a lower level network frame injection method using libpcap which makes cross-compiling a bit of a PITA. Hopefully, I’ll find some time to figure out how to get some builds for MIPS64/Linux for Ubiquiti USGs.

Anyways, if you’re feeling adventurous, feel free to grab it and give it a go.

Well I have it building for Intel Linux/MacOS/FreeBSD and MIPS64 Linux (Ubiquiti USG/Edgerouter).

Next up I guess is to more intelligently discover hosts on the VPN so you don’t have to hard code the IP’s on each interface.

Okay, here it is all you Roonies (is that right?) the first official release of udp-proxy-2020. What is cool about this? Well, it’s tested to not only forward UDP packets between ethernet interfaces (like udp-broadcast-relay-redux) but also to easily forward traffic over OpenVPN tunnels (tested with my iPhone using OpenVPN over Verizon with WiFi disabled).

How do you use it? Well, grab a binary from the releases page: https://github.com/synfinatic/udp-proxy-2020/releases/tag/v0.0.4

And then: ./udp-proxy-2020 --port 9003 --interface lagg0,lagg0.200,ovpns2

1 Like

Nice! I just tried it from my remote laptop with my pfsense install, “bridging” openvpn and my lan interface.
What does work is that I can control my roon speakers at home. What currently does not work is my being able to play music on my laptop. But I have not yet activated Avahi Zeroconf Bridging for the openvpn interface, so maybe it will work after I did that.

Definitely should be able to stream music from your Roon Core to your laptop over the VPN- I’ve tested using my iPhone over Verizon using OpenVPN to my pfSense box. Would be curious to hear if it is Avahi related… I don’t believe that should matter, but I’ve been wrong before.

If you still can’t see your laptop as an output zone, please provide more info about your network/config.